@k2works/claude-code-booster 6.2.0 → 6.3.1

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 (618) hide show
  1. package/lib/assets/.claude/skills/practicing-getting-start-tdd/SKILL.md +3 -7
  2. package/lib/assets/docs/article/index.md +17 -41
  3. package/lib/assets/docs/index.md +1 -1
  4. package/lib/assets/mkdocs.yml +0 -6
  5. package/package.json +1 -1
  6. package/lib/assets/docs/article/functional-desgin-ppp/all/01-immutability-and-data-transformation.md +0 -484
  7. package/lib/assets/docs/article/functional-desgin-ppp/all/02-function-composition.md +0 -528
  8. package/lib/assets/docs/article/functional-desgin-ppp/all/03-polymorphism.md +0 -546
  9. package/lib/assets/docs/article/functional-desgin-ppp/all/04-data-validation.md +0 -309
  10. package/lib/assets/docs/article/functional-desgin-ppp/all/05-property-based-testing.md +0 -329
  11. package/lib/assets/docs/article/functional-desgin-ppp/all/06-tdd-and-functional.md +0 -507
  12. package/lib/assets/docs/article/functional-desgin-ppp/all/07-composite-pattern.md +0 -307
  13. package/lib/assets/docs/article/functional-desgin-ppp/all/08-decorator-pattern.md +0 -300
  14. package/lib/assets/docs/article/functional-desgin-ppp/all/09-adapter-pattern.md +0 -345
  15. package/lib/assets/docs/article/functional-desgin-ppp/all/10-strategy-pattern.md +0 -312
  16. package/lib/assets/docs/article/functional-desgin-ppp/all/11-command-pattern.md +0 -295
  17. package/lib/assets/docs/article/functional-desgin-ppp/all/12-visitor-pattern.md +0 -331
  18. package/lib/assets/docs/article/functional-desgin-ppp/all/13-abstract-factory-pattern.md +0 -328
  19. package/lib/assets/docs/article/functional-desgin-ppp/all/14-abstract-server-pattern.md +0 -374
  20. package/lib/assets/docs/article/functional-desgin-ppp/all/15-gossiping-bus-drivers.md +0 -165
  21. package/lib/assets/docs/article/functional-desgin-ppp/all/16-payroll-system.md +0 -187
  22. package/lib/assets/docs/article/functional-desgin-ppp/all/17-video-rental-system.md +0 -321
  23. package/lib/assets/docs/article/functional-desgin-ppp/all/18-concurrency-system.md +0 -296
  24. package/lib/assets/docs/article/functional-desgin-ppp/all/19-wa-tor-simulation.md +0 -295
  25. package/lib/assets/docs/article/functional-desgin-ppp/all/20-pattern-interactions.md +0 -283
  26. package/lib/assets/docs/article/functional-desgin-ppp/all/21-best-practices.md +0 -303
  27. package/lib/assets/docs/article/functional-desgin-ppp/all/22-oo-to-fp-migration.md +0 -346
  28. package/lib/assets/docs/article/functional-desgin-ppp/all/index.md +0 -388
  29. package/lib/assets/docs/article/functional-desgin-ppp/clojure/01-immutability-and-data-transformation.md +0 -282
  30. package/lib/assets/docs/article/functional-desgin-ppp/clojure/02-function-composition.md +0 -389
  31. package/lib/assets/docs/article/functional-desgin-ppp/clojure/03-polymorphism.md +0 -393
  32. package/lib/assets/docs/article/functional-desgin-ppp/clojure/04-clojure-spec.md +0 -359
  33. package/lib/assets/docs/article/functional-desgin-ppp/clojure/05-property-based-testing.md +0 -361
  34. package/lib/assets/docs/article/functional-desgin-ppp/clojure/06-tdd-in-functional.md +0 -392
  35. package/lib/assets/docs/article/functional-desgin-ppp/clojure/07-composite-pattern.md +0 -538
  36. package/lib/assets/docs/article/functional-desgin-ppp/clojure/08-decorator-pattern.md +0 -404
  37. package/lib/assets/docs/article/functional-desgin-ppp/clojure/09-adapter-pattern.md +0 -408
  38. package/lib/assets/docs/article/functional-desgin-ppp/clojure/10-strategy-pattern.md +0 -494
  39. package/lib/assets/docs/article/functional-desgin-ppp/clojure/11-command-pattern.md +0 -575
  40. package/lib/assets/docs/article/functional-desgin-ppp/clojure/12-visitor-pattern.md +0 -576
  41. package/lib/assets/docs/article/functional-desgin-ppp/clojure/13-abstract-factory-pattern.md +0 -484
  42. package/lib/assets/docs/article/functional-desgin-ppp/clojure/14-abstract-server-pattern.md +0 -471
  43. package/lib/assets/docs/article/functional-desgin-ppp/clojure/15-gossiping-bus-drivers.md +0 -334
  44. package/lib/assets/docs/article/functional-desgin-ppp/clojure/16-payroll-system.md +0 -410
  45. package/lib/assets/docs/article/functional-desgin-ppp/clojure/17-video-rental-system.md +0 -459
  46. package/lib/assets/docs/article/functional-desgin-ppp/clojure/18-concurrency-system.md +0 -484
  47. package/lib/assets/docs/article/functional-desgin-ppp/clojure/19-wator-simulation.md +0 -748
  48. package/lib/assets/docs/article/functional-desgin-ppp/clojure/20-pattern-interactions.md +0 -576
  49. package/lib/assets/docs/article/functional-desgin-ppp/clojure/21-best-practices.md +0 -527
  50. package/lib/assets/docs/article/functional-desgin-ppp/clojure/22-oo-to-fp-migration.md +0 -541
  51. package/lib/assets/docs/article/functional-desgin-ppp/clojure/index.md +0 -241
  52. package/lib/assets/docs/article/functional-desgin-ppp/elixir/01-immutability-and-data-transformation.md +0 -392
  53. package/lib/assets/docs/article/functional-desgin-ppp/elixir/02-function-composition.md +0 -383
  54. package/lib/assets/docs/article/functional-desgin-ppp/elixir/03-polymorphism.md +0 -384
  55. package/lib/assets/docs/article/functional-desgin-ppp/elixir/04-data-validation.md +0 -204
  56. package/lib/assets/docs/article/functional-desgin-ppp/elixir/05-property-based-testing.md +0 -277
  57. package/lib/assets/docs/article/functional-desgin-ppp/elixir/06-tdd-and-fp.md +0 -303
  58. package/lib/assets/docs/article/functional-desgin-ppp/elixir/07-effects-and-pure-functions.md +0 -173
  59. package/lib/assets/docs/article/functional-desgin-ppp/elixir/08-error-handling-strategies.md +0 -177
  60. package/lib/assets/docs/article/functional-desgin-ppp/elixir/09-io-and-external-systems.md +0 -263
  61. package/lib/assets/docs/article/functional-desgin-ppp/elixir/10-concurrency-patterns.md +0 -278
  62. package/lib/assets/docs/article/functional-desgin-ppp/elixir/11-command-pattern.md +0 -157
  63. package/lib/assets/docs/article/functional-desgin-ppp/elixir/12-visitor-pattern.md +0 -185
  64. package/lib/assets/docs/article/functional-desgin-ppp/elixir/13-abstract-factory-pattern.md +0 -613
  65. package/lib/assets/docs/article/functional-desgin-ppp/elixir/14-abstract-server-pattern.md +0 -738
  66. package/lib/assets/docs/article/functional-desgin-ppp/elixir/15-gossiping-bus-drivers.md +0 -300
  67. package/lib/assets/docs/article/functional-desgin-ppp/elixir/16-payroll-system.md +0 -429
  68. package/lib/assets/docs/article/functional-desgin-ppp/elixir/17-video-rental-system.md +0 -328
  69. package/lib/assets/docs/article/functional-desgin-ppp/elixir/18-concurrency-system.md +0 -475
  70. package/lib/assets/docs/article/functional-desgin-ppp/elixir/19-wator-simulation.md +0 -532
  71. package/lib/assets/docs/article/functional-desgin-ppp/elixir/20-pattern-interactions.md +0 -296
  72. package/lib/assets/docs/article/functional-desgin-ppp/elixir/21-best-practices.md +0 -349
  73. package/lib/assets/docs/article/functional-desgin-ppp/elixir/22-oo-to-fp-migration.md +0 -404
  74. package/lib/assets/docs/article/functional-desgin-ppp/elixir/index.md +0 -248
  75. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/01-immutability-and-data-transformation.md +0 -393
  76. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/02-function-composition.md +0 -461
  77. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/03-polymorphism.md +0 -504
  78. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/04-data-validation.md +0 -425
  79. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/05-property-based-testing.md +0 -391
  80. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/06-tdd-functional.md +0 -696
  81. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/07-composite-pattern.md +0 -451
  82. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/08-decorator-pattern.md +0 -488
  83. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/09-adapter-pattern.md +0 -488
  84. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/10-strategy-pattern.md +0 -436
  85. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/11-command-pattern.md +0 -437
  86. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/12-visitor-pattern.md +0 -348
  87. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/13-abstract-factory-pattern.md +0 -318
  88. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/14-abstract-server-pattern.md +0 -605
  89. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/15-gossiping-bus-drivers.md +0 -364
  90. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/16-payroll-system.md +0 -359
  91. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/17-video-rental-system.md +0 -423
  92. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/18-concurrency-system.md +0 -376
  93. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/19-wator-simulation.md +0 -412
  94. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/20-pattern-interactions.md +0 -300
  95. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/21-best-practices.md +0 -333
  96. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/22-oo-to-fp-migration.md +0 -341
  97. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/index.md +0 -274
  98. package/lib/assets/docs/article/functional-desgin-ppp/haskell/01-immutability-and-data-transformation.md +0 -307
  99. package/lib/assets/docs/article/functional-desgin-ppp/haskell/02-function-composition.md +0 -313
  100. package/lib/assets/docs/article/functional-desgin-ppp/haskell/03-polymorphism.md +0 -371
  101. package/lib/assets/docs/article/functional-desgin-ppp/haskell/04-data-validation.md +0 -266
  102. package/lib/assets/docs/article/functional-desgin-ppp/haskell/05-property-based-testing.md +0 -263
  103. package/lib/assets/docs/article/functional-desgin-ppp/haskell/06-tdd-functional.md +0 -292
  104. package/lib/assets/docs/article/functional-desgin-ppp/haskell/07-composite-pattern.md +0 -404
  105. package/lib/assets/docs/article/functional-desgin-ppp/haskell/08-decorator-pattern.md +0 -328
  106. package/lib/assets/docs/article/functional-desgin-ppp/haskell/09-adapter-pattern.md +0 -391
  107. package/lib/assets/docs/article/functional-desgin-ppp/haskell/10-strategy-pattern.md +0 -296
  108. package/lib/assets/docs/article/functional-desgin-ppp/haskell/11-command-pattern.md +0 -312
  109. package/lib/assets/docs/article/functional-desgin-ppp/haskell/12-visitor-pattern.md +0 -335
  110. package/lib/assets/docs/article/functional-desgin-ppp/haskell/13-abstract-factory-pattern.md +0 -341
  111. package/lib/assets/docs/article/functional-desgin-ppp/haskell/14-abstract-server-pattern.md +0 -388
  112. package/lib/assets/docs/article/functional-desgin-ppp/haskell/15-gossiping-bus-drivers.md +0 -186
  113. package/lib/assets/docs/article/functional-desgin-ppp/haskell/16-payroll-system.md +0 -228
  114. package/lib/assets/docs/article/functional-desgin-ppp/haskell/17-video-rental-system.md +0 -253
  115. package/lib/assets/docs/article/functional-desgin-ppp/haskell/18-concurrency-system.md +0 -372
  116. package/lib/assets/docs/article/functional-desgin-ppp/haskell/19-wator-simulation.md +0 -447
  117. package/lib/assets/docs/article/functional-desgin-ppp/haskell/20-pattern-interactions.md +0 -334
  118. package/lib/assets/docs/article/functional-desgin-ppp/haskell/21-best-practices.md +0 -412
  119. package/lib/assets/docs/article/functional-desgin-ppp/haskell/22-oo-to-fp-migration.md +0 -478
  120. package/lib/assets/docs/article/functional-desgin-ppp/haskell/index.md +0 -174
  121. package/lib/assets/docs/article/functional-desgin-ppp/index.md +0 -90
  122. package/lib/assets/docs/article/functional-desgin-ppp/rust/01-immutability-and-data-transformation.md +0 -459
  123. package/lib/assets/docs/article/functional-desgin-ppp/rust/02-function-composition.md +0 -472
  124. package/lib/assets/docs/article/functional-desgin-ppp/rust/03-polymorphism.md +0 -434
  125. package/lib/assets/docs/article/functional-desgin-ppp/rust/04-data-validation.md +0 -282
  126. package/lib/assets/docs/article/functional-desgin-ppp/rust/05-property-based-testing.md +0 -256
  127. package/lib/assets/docs/article/functional-desgin-ppp/rust/06-tdd-and-functional.md +0 -850
  128. package/lib/assets/docs/article/functional-desgin-ppp/rust/07-composite-pattern.md +0 -393
  129. package/lib/assets/docs/article/functional-desgin-ppp/rust/08-decorator-pattern.md +0 -392
  130. package/lib/assets/docs/article/functional-desgin-ppp/rust/09-adapter-pattern.md +0 -348
  131. package/lib/assets/docs/article/functional-desgin-ppp/rust/10-strategy-pattern.md +0 -340
  132. package/lib/assets/docs/article/functional-desgin-ppp/rust/11-command-pattern.md +0 -365
  133. package/lib/assets/docs/article/functional-desgin-ppp/rust/12-visitor-pattern.md +0 -388
  134. package/lib/assets/docs/article/functional-desgin-ppp/rust/13-abstract-factory-pattern.md +0 -370
  135. package/lib/assets/docs/article/functional-desgin-ppp/rust/14-abstract-server-pattern.md +0 -401
  136. package/lib/assets/docs/article/functional-desgin-ppp/rust/15-gossiping-bus-drivers.md +0 -309
  137. package/lib/assets/docs/article/functional-desgin-ppp/rust/16-payroll-system.md +0 -306
  138. package/lib/assets/docs/article/functional-desgin-ppp/rust/17-video-rental-system.md +0 -313
  139. package/lib/assets/docs/article/functional-desgin-ppp/rust/18-concurrency-system.md +0 -324
  140. package/lib/assets/docs/article/functional-desgin-ppp/rust/19-wator-simulation.md +0 -320
  141. package/lib/assets/docs/article/functional-desgin-ppp/rust/20-pattern-interactions.md +0 -313
  142. package/lib/assets/docs/article/functional-desgin-ppp/rust/21-best-practices.md +0 -345
  143. package/lib/assets/docs/article/functional-desgin-ppp/rust/22-oo-to-fp-migration.md +0 -358
  144. package/lib/assets/docs/article/functional-desgin-ppp/rust/index.md +0 -243
  145. package/lib/assets/docs/article/functional-desgin-ppp/scala/01-immutability-and-data-transformation.md +0 -337
  146. package/lib/assets/docs/article/functional-desgin-ppp/scala/02-function-composition.md +0 -357
  147. package/lib/assets/docs/article/functional-desgin-ppp/scala/03-polymorphism.md +0 -366
  148. package/lib/assets/docs/article/functional-desgin-ppp/scala/04-data-validation.md +0 -373
  149. package/lib/assets/docs/article/functional-desgin-ppp/scala/05-property-based-testing.md +0 -524
  150. package/lib/assets/docs/article/functional-desgin-ppp/scala/06-tdd-functional.md +0 -566
  151. package/lib/assets/docs/article/functional-desgin-ppp/scala/07-composite-pattern.md +0 -372
  152. package/lib/assets/docs/article/functional-desgin-ppp/scala/08-decorator-pattern.md +0 -336
  153. package/lib/assets/docs/article/functional-desgin-ppp/scala/09-adapter-pattern.md +0 -526
  154. package/lib/assets/docs/article/functional-desgin-ppp/scala/10-strategy-pattern.md +0 -450
  155. package/lib/assets/docs/article/functional-desgin-ppp/scala/11-command-pattern.md +0 -416
  156. package/lib/assets/docs/article/functional-desgin-ppp/scala/12-visitor-pattern.md +0 -388
  157. package/lib/assets/docs/article/functional-desgin-ppp/scala/13-abstract-factory-pattern.md +0 -407
  158. package/lib/assets/docs/article/functional-desgin-ppp/scala/14-abstract-server-pattern.md +0 -485
  159. package/lib/assets/docs/article/functional-desgin-ppp/scala/15-gossiping-bus-drivers.md +0 -400
  160. package/lib/assets/docs/article/functional-desgin-ppp/scala/16-payroll-system.md +0 -351
  161. package/lib/assets/docs/article/functional-desgin-ppp/scala/17-video-rental-system.md +0 -333
  162. package/lib/assets/docs/article/functional-desgin-ppp/scala/18-concurrency-system.md +0 -739
  163. package/lib/assets/docs/article/functional-desgin-ppp/scala/19-wator-simulation.md +0 -633
  164. package/lib/assets/docs/article/functional-desgin-ppp/scala/20-pattern-interactions.md +0 -521
  165. package/lib/assets/docs/article/functional-desgin-ppp/scala/21-best-practices.md +0 -442
  166. package/lib/assets/docs/article/functional-desgin-ppp/scala/22-oo-to-fp-migration.md +0 -697
  167. package/lib/assets/docs/article/functional-desgin-ppp/scala/index.md +0 -243
  168. package/lib/assets/docs/article/getting-start-docker-kubernetes/01-container-and-docker-basics.md +0 -341
  169. package/lib/assets/docs/article/getting-start-docker-kubernetes/02-container-deployment.md +0 -785
  170. package/lib/assets/docs/article/getting-start-docker-kubernetes/03-practical-container-build-deploy.md +0 -466
  171. package/lib/assets/docs/article/getting-start-docker-kubernetes/04-multi-container-application.md +0 -878
  172. package/lib/assets/docs/article/getting-start-docker-kubernetes/05-kubernetes-introduction.md +0 -585
  173. package/lib/assets/docs/article/getting-start-docker-kubernetes/06-kubernetes-deploy-cluster.md +0 -620
  174. package/lib/assets/docs/article/getting-start-docker-kubernetes/07-kubernetes-advanced.md +0 -621
  175. package/lib/assets/docs/article/getting-start-docker-kubernetes/08-kubernetes-packaging.md +0 -518
  176. package/lib/assets/docs/article/getting-start-docker-kubernetes/09-container-operations.md +0 -546
  177. package/lib/assets/docs/article/getting-start-docker-kubernetes/10-optimal-container-image.md +0 -640
  178. package/lib/assets/docs/article/getting-start-docker-kubernetes/11-continuous-delivery.md +0 -607
  179. package/lib/assets/docs/article/getting-start-docker-kubernetes/12-container-use-cases.md +0 -463
  180. package/lib/assets/docs/article/getting-start-docker-kubernetes/13-case-monolith-compose-vs-kustomize.md +0 -346
  181. package/lib/assets/docs/article/getting-start-docker-kubernetes/14-case-event-driven-kustomize-vs-helm.md +0 -324
  182. package/lib/assets/docs/article/getting-start-docker-kubernetes/15-case-escqrs-axon-kustomize-vs-helm.md +0 -297
  183. package/lib/assets/docs/article/getting-start-docker-kubernetes/16-case-escqrs-kafka-kustomize-vs-helm.md +0 -256
  184. package/lib/assets/docs/article/getting-start-docker-kubernetes/17-case-comparison-summary.md +0 -141
  185. package/lib/assets/docs/article/getting-start-docker-kubernetes/18-case-load-testing.md +0 -303
  186. package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-a-dev-tools-setup.md +0 -274
  187. package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-b-orchestration-environments.md +0 -530
  188. package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-c-tips.md +0 -519
  189. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-01-comic.png +0 -0
  190. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-02-comic.png +0 -0
  191. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-03-comic.png +0 -0
  192. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-04-comic.png +0 -0
  193. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-05-comic.png +0 -0
  194. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-06-comic.png +0 -0
  195. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-07-comic.png +0 -0
  196. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-08-comic.png +0 -0
  197. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-09-comic.png +0 -0
  198. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-10-comic.png +0 -0
  199. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-11-comic.png +0 -0
  200. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-12-comic.png +0 -0
  201. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/overview-comic.png +0 -0
  202. package/lib/assets/docs/article/getting-start-docker-kubernetes/index.md +0 -82
  203. package/lib/assets/docs/article/getting-start-docker-kubernetes/outline.md +0 -220
  204. package/lib/assets/docs/article/getting-start-tdd/clojure/01-todo-list-and-first-test.md +0 -175
  205. package/lib/assets/docs/article/getting-start-tdd/clojure/02-fake-it-and-triangulation.md +0 -171
  206. package/lib/assets/docs/article/getting-start-tdd/clojure/03-obvious-implementation-and-refactoring.md +0 -144
  207. package/lib/assets/docs/article/getting-start-tdd/clojure/04-version-control-and-conventional-commits.md +0 -97
  208. package/lib/assets/docs/article/getting-start-tdd/clojure/05-package-management-and-static-analysis.md +0 -308
  209. package/lib/assets/docs/article/getting-start-tdd/clojure/06-task-runner-and-ci-cd.md +0 -250
  210. package/lib/assets/docs/article/getting-start-tdd/clojure/07-protocols-and-records.md +0 -140
  211. package/lib/assets/docs/article/getting-start-tdd/clojure/08-multimethods-and-design-patterns.md +0 -139
  212. package/lib/assets/docs/article/getting-start-tdd/clojure/09-namespaces-and-module-design.md +0 -136
  213. package/lib/assets/docs/article/getting-start-tdd/clojure/10-higher-order-functions-and-composition.md +0 -123
  214. package/lib/assets/docs/article/getting-start-tdd/clojure/11-persistent-data-and-pipeline.md +0 -147
  215. package/lib/assets/docs/article/getting-start-tdd/clojure/12-error-handling-and-spec.md +0 -170
  216. package/lib/assets/docs/article/getting-start-tdd/clojure/index.md +0 -65
  217. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter01.md +0 -241
  218. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter02.md +0 -253
  219. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter03.md +0 -211
  220. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter04.md +0 -101
  221. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter05.md +0 -265
  222. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter06.md +0 -204
  223. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter07.md +0 -223
  224. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter08.md +0 -258
  225. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter09.md +0 -183
  226. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter10.md +0 -175
  227. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter11.md +0 -201
  228. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter12.md +0 -220
  229. package/lib/assets/docs/article/getting-start-tdd/csharp/index.md +0 -83
  230. package/lib/assets/docs/article/getting-start-tdd/elixir/01-todo-list-and-first-test.md +0 -96
  231. package/lib/assets/docs/article/getting-start-tdd/elixir/02-fake-it-and-triangulation.md +0 -104
  232. package/lib/assets/docs/article/getting-start-tdd/elixir/03-obvious-implementation-and-refactoring.md +0 -118
  233. package/lib/assets/docs/article/getting-start-tdd/elixir/04-version-control-and-conventional-commits.md +0 -105
  234. package/lib/assets/docs/article/getting-start-tdd/elixir/05-package-management-and-static-analysis.md +0 -97
  235. package/lib/assets/docs/article/getting-start-tdd/elixir/06-task-runner-and-ci-cd.md +0 -80
  236. package/lib/assets/docs/article/getting-start-tdd/elixir/07-structs-and-protocols.md +0 -119
  237. package/lib/assets/docs/article/getting-start-tdd/elixir/08-pattern-matching-and-guards.md +0 -117
  238. package/lib/assets/docs/article/getting-start-tdd/elixir/09-module-design-and-behaviours.md +0 -113
  239. package/lib/assets/docs/article/getting-start-tdd/elixir/10-higher-order-functions-and-pipeline.md +0 -187
  240. package/lib/assets/docs/article/getting-start-tdd/elixir/11-stream-and-lazy-evaluation.md +0 -151
  241. package/lib/assets/docs/article/getting-start-tdd/elixir/12-error-handling-and-with.md +0 -154
  242. package/lib/assets/docs/article/getting-start-tdd/elixir/index.md +0 -35
  243. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter01.md +0 -211
  244. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter02.md +0 -255
  245. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter03.md +0 -227
  246. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter04.md +0 -188
  247. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter05.md +0 -276
  248. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter06.md +0 -199
  249. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter07.md +0 -170
  250. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter08.md +0 -184
  251. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter09.md +0 -231
  252. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter10.md +0 -198
  253. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter11.md +0 -221
  254. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter12.md +0 -224
  255. package/lib/assets/docs/article/getting-start-tdd/fsharp/index.md +0 -71
  256. package/lib/assets/docs/article/getting-start-tdd/go/01-todo-list-and-first-test.md +0 -222
  257. package/lib/assets/docs/article/getting-start-tdd/go/02-fake-it-and-triangulation.md +0 -311
  258. package/lib/assets/docs/article/getting-start-tdd/go/03-obvious-implementation-and-refactoring.md +0 -348
  259. package/lib/assets/docs/article/getting-start-tdd/go/04-version-control-and-conventional-commits.md +0 -121
  260. package/lib/assets/docs/article/getting-start-tdd/go/05-package-management-and-static-analysis.md +0 -281
  261. package/lib/assets/docs/article/getting-start-tdd/go/06-task-runner-and-ci-cd.md +0 -242
  262. package/lib/assets/docs/article/getting-start-tdd/go/07-encapsulation-and-polymorphism.md +0 -402
  263. package/lib/assets/docs/article/getting-start-tdd/go/08-design-patterns.md +0 -430
  264. package/lib/assets/docs/article/getting-start-tdd/go/09-solid-principles-and-module-design.md +0 -408
  265. package/lib/assets/docs/article/getting-start-tdd/go/10-higher-order-functions-and-composition.md +0 -234
  266. package/lib/assets/docs/article/getting-start-tdd/go/11-immutable-data-and-pipeline.md +0 -304
  267. package/lib/assets/docs/article/getting-start-tdd/go/12-error-handling-and-type-safety.md +0 -419
  268. package/lib/assets/docs/article/getting-start-tdd/go/index.md +0 -83
  269. package/lib/assets/docs/article/getting-start-tdd/haskell/01-todo-list-and-first-test.md +0 -288
  270. package/lib/assets/docs/article/getting-start-tdd/haskell/02-fake-it-and-triangulation.md +0 -346
  271. package/lib/assets/docs/article/getting-start-tdd/haskell/03-obvious-implementation-and-refactoring.md +0 -266
  272. package/lib/assets/docs/article/getting-start-tdd/haskell/04-version-control-and-conventional-commits.md +0 -191
  273. package/lib/assets/docs/article/getting-start-tdd/haskell/05-package-management-and-static-analysis.md +0 -322
  274. package/lib/assets/docs/article/getting-start-tdd/haskell/06-task-runner-and-ci-cd.md +0 -318
  275. package/lib/assets/docs/article/getting-start-tdd/haskell/07-algebraic-data-types-and-type-classes.md +0 -421
  276. package/lib/assets/docs/article/getting-start-tdd/haskell/08-pattern-matching-and-guards.md +0 -399
  277. package/lib/assets/docs/article/getting-start-tdd/haskell/09-module-design-and-smart-constructors.md +0 -470
  278. package/lib/assets/docs/article/getting-start-tdd/haskell/10-higher-order-functions-and-currying.md +0 -443
  279. package/lib/assets/docs/article/getting-start-tdd/haskell/11-function-composition-and-point-free.md +0 -401
  280. package/lib/assets/docs/article/getting-start-tdd/haskell/12-monad-and-error-handling.md +0 -640
  281. package/lib/assets/docs/article/getting-start-tdd/haskell/index.md +0 -49
  282. package/lib/assets/docs/article/getting-start-tdd/index.md +0 -93
  283. package/lib/assets/docs/article/getting-start-tdd/integration/01-language-overview.md +0 -384
  284. package/lib/assets/docs/article/getting-start-tdd/integration/02-test-framework-comparison.md +0 -358
  285. package/lib/assets/docs/article/getting-start-tdd/integration/03-tdd-pattern-comparison.md +0 -454
  286. package/lib/assets/docs/article/getting-start-tdd/integration/04-type-system-comparison.md +0 -418
  287. package/lib/assets/docs/article/getting-start-tdd/integration/05-dev-environment-comparison.md +0 -339
  288. package/lib/assets/docs/article/getting-start-tdd/integration/06-learning-roadmap.md +0 -299
  289. package/lib/assets/docs/article/getting-start-tdd/integration/index.md +0 -69
  290. package/lib/assets/docs/article/getting-start-tdd/java/01-todo-list-and-first-test.md +0 -243
  291. package/lib/assets/docs/article/getting-start-tdd/java/02-fake-it-and-triangulation.md +0 -270
  292. package/lib/assets/docs/article/getting-start-tdd/java/03-obvious-implementation-and-refactoring.md +0 -194
  293. package/lib/assets/docs/article/getting-start-tdd/java/04-version-control-and-conventional-commits.md +0 -124
  294. package/lib/assets/docs/article/getting-start-tdd/java/05-package-management-and-static-analysis.md +0 -391
  295. package/lib/assets/docs/article/getting-start-tdd/java/06-task-runner-and-ci-cd.md +0 -281
  296. package/lib/assets/docs/article/getting-start-tdd/java/07-encapsulation-and-polymorphism.md +0 -635
  297. package/lib/assets/docs/article/getting-start-tdd/java/08-design-patterns.md +0 -402
  298. package/lib/assets/docs/article/getting-start-tdd/java/09-solid-principles-and-module-design.md +0 -319
  299. package/lib/assets/docs/article/getting-start-tdd/java/10-higher-order-functions-and-composition.md +0 -197
  300. package/lib/assets/docs/article/getting-start-tdd/java/11-immutable-data-and-pipeline.md +0 -176
  301. package/lib/assets/docs/article/getting-start-tdd/java/12-error-handling-and-type-safety.md +0 -214
  302. package/lib/assets/docs/article/getting-start-tdd/java/index.md +0 -61
  303. package/lib/assets/docs/article/getting-start-tdd/node/01-todo-list-and-first-test.md +0 -253
  304. package/lib/assets/docs/article/getting-start-tdd/node/02-fake-it-and-triangulation.md +0 -271
  305. package/lib/assets/docs/article/getting-start-tdd/node/03-obvious-implementation-and-refactoring.md +0 -178
  306. package/lib/assets/docs/article/getting-start-tdd/node/04-version-control-and-conventional-commits.md +0 -121
  307. package/lib/assets/docs/article/getting-start-tdd/node/05-package-management-and-static-analysis.md +0 -323
  308. package/lib/assets/docs/article/getting-start-tdd/node/06-task-runner-and-ci-cd.md +0 -244
  309. package/lib/assets/docs/article/getting-start-tdd/node/07-encapsulation-and-polymorphism.md +0 -336
  310. package/lib/assets/docs/article/getting-start-tdd/node/08-design-patterns.md +0 -331
  311. package/lib/assets/docs/article/getting-start-tdd/node/09-solid-principles-and-module-design.md +0 -294
  312. package/lib/assets/docs/article/getting-start-tdd/node/10-higher-order-functions-and-composition.md +0 -208
  313. package/lib/assets/docs/article/getting-start-tdd/node/11-immutable-data-and-pipeline.md +0 -216
  314. package/lib/assets/docs/article/getting-start-tdd/node/12-error-handling-and-type-safety.md +0 -304
  315. package/lib/assets/docs/article/getting-start-tdd/node/index.md +0 -56
  316. package/lib/assets/docs/article/getting-start-tdd/php/01-todo-list-and-first-test.md +0 -268
  317. package/lib/assets/docs/article/getting-start-tdd/php/02-fake-it-and-triangulation.md +0 -209
  318. package/lib/assets/docs/article/getting-start-tdd/php/03-obvious-implementation-and-refactoring.md +0 -257
  319. package/lib/assets/docs/article/getting-start-tdd/php/04-version-control-and-conventional-commits.md +0 -150
  320. package/lib/assets/docs/article/getting-start-tdd/php/05-package-management-and-static-analysis.md +0 -419
  321. package/lib/assets/docs/article/getting-start-tdd/php/06-task-runner-and-ci-cd.md +0 -330
  322. package/lib/assets/docs/article/getting-start-tdd/php/07-encapsulation-and-polymorphism.md +0 -380
  323. package/lib/assets/docs/article/getting-start-tdd/php/08-design-patterns.md +0 -461
  324. package/lib/assets/docs/article/getting-start-tdd/php/09-solid-principles-and-module-design.md +0 -468
  325. package/lib/assets/docs/article/getting-start-tdd/php/10-higher-order-functions-and-composition.md +0 -190
  326. package/lib/assets/docs/article/getting-start-tdd/php/11-immutable-data-and-pipeline.md +0 -274
  327. package/lib/assets/docs/article/getting-start-tdd/php/12-error-handling-and-type-safety.md +0 -316
  328. package/lib/assets/docs/article/getting-start-tdd/php/index.md +0 -84
  329. package/lib/assets/docs/article/getting-start-tdd/python/01-todo-list-and-first-test.md +0 -210
  330. package/lib/assets/docs/article/getting-start-tdd/python/02-fake-it-and-triangulation.md +0 -256
  331. package/lib/assets/docs/article/getting-start-tdd/python/03-obvious-implementation-and-refactoring.md +0 -208
  332. package/lib/assets/docs/article/getting-start-tdd/python/04-version-control-and-conventional-commits.md +0 -96
  333. package/lib/assets/docs/article/getting-start-tdd/python/05-package-management-and-static-analysis.md +0 -283
  334. package/lib/assets/docs/article/getting-start-tdd/python/06-task-runner-and-ci-cd.md +0 -199
  335. package/lib/assets/docs/article/getting-start-tdd/python/07-encapsulation-and-polymorphism.md +0 -217
  336. package/lib/assets/docs/article/getting-start-tdd/python/08-design-patterns.md +0 -181
  337. package/lib/assets/docs/article/getting-start-tdd/python/09-solid-principles-and-module-design.md +0 -139
  338. package/lib/assets/docs/article/getting-start-tdd/python/10-higher-order-functions-and-composition.md +0 -131
  339. package/lib/assets/docs/article/getting-start-tdd/python/11-immutable-data-and-pipeline.md +0 -125
  340. package/lib/assets/docs/article/getting-start-tdd/python/12-error-handling-and-type-safety.md +0 -135
  341. package/lib/assets/docs/article/getting-start-tdd/python/index.md +0 -55
  342. package/lib/assets/docs/article/getting-start-tdd/ruby/01-todo-list-and-first-test.md +0 -240
  343. package/lib/assets/docs/article/getting-start-tdd/ruby/02-fake-it-and-triangulation.md +0 -247
  344. package/lib/assets/docs/article/getting-start-tdd/ruby/03-obvious-implementation-and-refactoring.md +0 -237
  345. package/lib/assets/docs/article/getting-start-tdd/ruby/04-version-control-and-conventional-commits.md +0 -121
  346. package/lib/assets/docs/article/getting-start-tdd/ruby/05-package-management-and-static-analysis.md +0 -296
  347. package/lib/assets/docs/article/getting-start-tdd/ruby/06-task-runner-and-ci-cd.md +0 -257
  348. package/lib/assets/docs/article/getting-start-tdd/ruby/07-encapsulation-and-polymorphism.md +0 -288
  349. package/lib/assets/docs/article/getting-start-tdd/ruby/08-design-patterns.md +0 -338
  350. package/lib/assets/docs/article/getting-start-tdd/ruby/09-solid-principles-and-module-design.md +0 -205
  351. package/lib/assets/docs/article/getting-start-tdd/ruby/10-higher-order-functions-and-composition.md +0 -184
  352. package/lib/assets/docs/article/getting-start-tdd/ruby/11-immutable-data-and-pipeline.md +0 -246
  353. package/lib/assets/docs/article/getting-start-tdd/ruby/12-error-handling-and-type-safety.md +0 -407
  354. package/lib/assets/docs/article/getting-start-tdd/ruby/index.md +0 -83
  355. package/lib/assets/docs/article/getting-start-tdd/rust/01-todo-list-and-first-test.md +0 -220
  356. package/lib/assets/docs/article/getting-start-tdd/rust/02-fake-it-and-triangulation.md +0 -273
  357. package/lib/assets/docs/article/getting-start-tdd/rust/03-obvious-implementation-and-refactoring.md +0 -242
  358. package/lib/assets/docs/article/getting-start-tdd/rust/04-version-control-and-conventional-commits.md +0 -101
  359. package/lib/assets/docs/article/getting-start-tdd/rust/05-package-management-and-static-analysis.md +0 -221
  360. package/lib/assets/docs/article/getting-start-tdd/rust/06-task-runner-and-ci-cd.md +0 -173
  361. package/lib/assets/docs/article/getting-start-tdd/rust/07-encapsulation-and-polymorphism.md +0 -151
  362. package/lib/assets/docs/article/getting-start-tdd/rust/08-design-patterns.md +0 -154
  363. package/lib/assets/docs/article/getting-start-tdd/rust/09-solid-principles-and-module-design.md +0 -119
  364. package/lib/assets/docs/article/getting-start-tdd/rust/10-higher-order-functions-and-composition.md +0 -103
  365. package/lib/assets/docs/article/getting-start-tdd/rust/11-immutable-data-and-pipeline.md +0 -114
  366. package/lib/assets/docs/article/getting-start-tdd/rust/12-error-handling-and-type-safety.md +0 -121
  367. package/lib/assets/docs/article/getting-start-tdd/rust/index.md +0 -83
  368. package/lib/assets/docs/article/getting-start-tdd/scala/01-todo-list-and-first-test.md +0 -120
  369. package/lib/assets/docs/article/getting-start-tdd/scala/02-fake-it-and-triangulation.md +0 -116
  370. package/lib/assets/docs/article/getting-start-tdd/scala/03-obvious-implementation-and-refactoring.md +0 -108
  371. package/lib/assets/docs/article/getting-start-tdd/scala/04-version-control-and-conventional-commits.md +0 -132
  372. package/lib/assets/docs/article/getting-start-tdd/scala/05-package-management-and-static-analysis.md +0 -205
  373. package/lib/assets/docs/article/getting-start-tdd/scala/06-task-runner-and-ci-cd.md +0 -195
  374. package/lib/assets/docs/article/getting-start-tdd/scala/07-case-classes-and-traits.md +0 -148
  375. package/lib/assets/docs/article/getting-start-tdd/scala/08-pattern-matching-and-sealed-traits.md +0 -115
  376. package/lib/assets/docs/article/getting-start-tdd/scala/09-packages-and-module-design.md +0 -84
  377. package/lib/assets/docs/article/getting-start-tdd/scala/10-higher-order-functions-and-composition.md +0 -113
  378. package/lib/assets/docs/article/getting-start-tdd/scala/11-collections-and-lazy-evaluation.md +0 -103
  379. package/lib/assets/docs/article/getting-start-tdd/scala/12-error-handling-and-type-safety.md +0 -101
  380. package/lib/assets/docs/article/getting-start-tdd/scala/index.md +0 -65
  381. package/lib/assets/docs/article/grokking-concurrency/all/index.md +0 -403
  382. package/lib/assets/docs/article/grokking-concurrency/all/part-1-ch02-sequential.md +0 -563
  383. package/lib/assets/docs/article/grokking-concurrency/all/part-2-ch04-05-threads.md +0 -478
  384. package/lib/assets/docs/article/grokking-concurrency/all/part-3-ch06-multitasking.md +0 -529
  385. package/lib/assets/docs/article/grokking-concurrency/all/part-4-ch07-parallel-patterns.md +0 -429
  386. package/lib/assets/docs/article/grokking-concurrency/all/part-5-ch08-09-synchronization.md +0 -519
  387. package/lib/assets/docs/article/grokking-concurrency/all/part-6-ch10-11-nonblocking-io.md +0 -444
  388. package/lib/assets/docs/article/grokking-concurrency/all/part-7-ch12-async.md +0 -474
  389. package/lib/assets/docs/article/grokking-concurrency/all/part-8-ch13-mapreduce.md +0 -386
  390. package/lib/assets/docs/article/grokking-concurrency/clojure/index.md +0 -106
  391. package/lib/assets/docs/article/grokking-concurrency/clojure/part-1.md +0 -107
  392. package/lib/assets/docs/article/grokking-concurrency/clojure/part-2.md +0 -100
  393. package/lib/assets/docs/article/grokking-concurrency/clojure/part-3.md +0 -121
  394. package/lib/assets/docs/article/grokking-concurrency/clojure/part-4.md +0 -122
  395. package/lib/assets/docs/article/grokking-concurrency/clojure/part-5.md +0 -117
  396. package/lib/assets/docs/article/grokking-concurrency/clojure/part-6.md +0 -88
  397. package/lib/assets/docs/article/grokking-concurrency/clojure/part-7.md +0 -99
  398. package/lib/assets/docs/article/grokking-concurrency/clojure/part-8.md +0 -119
  399. package/lib/assets/docs/article/grokking-concurrency/csharp/index.md +0 -91
  400. package/lib/assets/docs/article/grokking-concurrency/csharp/part-1.md +0 -96
  401. package/lib/assets/docs/article/grokking-concurrency/csharp/part-2.md +0 -122
  402. package/lib/assets/docs/article/grokking-concurrency/csharp/part-3.md +0 -100
  403. package/lib/assets/docs/article/grokking-concurrency/csharp/part-4.md +0 -111
  404. package/lib/assets/docs/article/grokking-concurrency/csharp/part-5.md +0 -98
  405. package/lib/assets/docs/article/grokking-concurrency/csharp/part-6.md +0 -60
  406. package/lib/assets/docs/article/grokking-concurrency/csharp/part-7.md +0 -83
  407. package/lib/assets/docs/article/grokking-concurrency/csharp/part-8.md +0 -91
  408. package/lib/assets/docs/article/grokking-concurrency/fsharp/index.md +0 -55
  409. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-1.md +0 -79
  410. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-2.md +0 -102
  411. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-3.md +0 -93
  412. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-4.md +0 -109
  413. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-5.md +0 -103
  414. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-6.md +0 -92
  415. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-7.md +0 -120
  416. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-8.md +0 -106
  417. package/lib/assets/docs/article/grokking-concurrency/haskell/index.md +0 -238
  418. package/lib/assets/docs/article/grokking-concurrency/haskell/part-1.md +0 -95
  419. package/lib/assets/docs/article/grokking-concurrency/haskell/part-2.md +0 -95
  420. package/lib/assets/docs/article/grokking-concurrency/haskell/part-3.md +0 -90
  421. package/lib/assets/docs/article/grokking-concurrency/haskell/part-4.md +0 -105
  422. package/lib/assets/docs/article/grokking-concurrency/haskell/part-5.md +0 -98
  423. package/lib/assets/docs/article/grokking-concurrency/haskell/part-6.md +0 -94
  424. package/lib/assets/docs/article/grokking-concurrency/haskell/part-7.md +0 -110
  425. package/lib/assets/docs/article/grokking-concurrency/haskell/part-8.md +0 -117
  426. package/lib/assets/docs/article/grokking-concurrency/index.md +0 -66
  427. package/lib/assets/docs/article/grokking-concurrency/java/index.md +0 -92
  428. package/lib/assets/docs/article/grokking-concurrency/java/part-1.md +0 -307
  429. package/lib/assets/docs/article/grokking-concurrency/java/part-2.md +0 -333
  430. package/lib/assets/docs/article/grokking-concurrency/java/part-3.md +0 -220
  431. package/lib/assets/docs/article/grokking-concurrency/java/part-4.md +0 -212
  432. package/lib/assets/docs/article/grokking-concurrency/java/part-5.md +0 -111
  433. package/lib/assets/docs/article/grokking-concurrency/java/part-6.md +0 -68
  434. package/lib/assets/docs/article/grokking-concurrency/java/part-7.md +0 -100
  435. package/lib/assets/docs/article/grokking-concurrency/java/part-8.md +0 -100
  436. package/lib/assets/docs/article/grokking-concurrency/python/index.md +0 -303
  437. package/lib/assets/docs/article/grokking-concurrency/python/part-1.md +0 -238
  438. package/lib/assets/docs/article/grokking-concurrency/python/part-2.md +0 -417
  439. package/lib/assets/docs/article/grokking-concurrency/python/part-3.md +0 -226
  440. package/lib/assets/docs/article/grokking-concurrency/python/part-4.md +0 -298
  441. package/lib/assets/docs/article/grokking-concurrency/python/part-5.md +0 -314
  442. package/lib/assets/docs/article/grokking-concurrency/python/part-6.md +0 -296
  443. package/lib/assets/docs/article/grokking-concurrency/python/part-7.md +0 -313
  444. package/lib/assets/docs/article/grokking-concurrency/python/part-8.md +0 -359
  445. package/lib/assets/docs/article/grokking-concurrency/rust/index.md +0 -260
  446. package/lib/assets/docs/article/grokking-concurrency/rust/part-1.md +0 -107
  447. package/lib/assets/docs/article/grokking-concurrency/rust/part-2.md +0 -119
  448. package/lib/assets/docs/article/grokking-concurrency/rust/part-3.md +0 -125
  449. package/lib/assets/docs/article/grokking-concurrency/rust/part-4.md +0 -174
  450. package/lib/assets/docs/article/grokking-concurrency/rust/part-5.md +0 -157
  451. package/lib/assets/docs/article/grokking-concurrency/rust/part-6.md +0 -93
  452. package/lib/assets/docs/article/grokking-concurrency/rust/part-7.md +0 -132
  453. package/lib/assets/docs/article/grokking-concurrency/rust/part-8.md +0 -154
  454. package/lib/assets/docs/article/grokking-concurrency/scala/index.md +0 -59
  455. package/lib/assets/docs/article/grokking-concurrency/scala/part-1.md +0 -77
  456. package/lib/assets/docs/article/grokking-concurrency/scala/part-2.md +0 -111
  457. package/lib/assets/docs/article/grokking-concurrency/scala/part-3.md +0 -92
  458. package/lib/assets/docs/article/grokking-concurrency/scala/part-4.md +0 -109
  459. package/lib/assets/docs/article/grokking-concurrency/scala/part-5.md +0 -118
  460. package/lib/assets/docs/article/grokking-concurrency/scala/part-6.md +0 -82
  461. package/lib/assets/docs/article/grokking-concurrency/scala/part-7.md +0 -130
  462. package/lib/assets/docs/article/grokking-concurrency/scala/part-8.md +0 -128
  463. package/lib/assets/docs/article/grokkingfp/all/index.md +0 -368
  464. package/lib/assets/docs/article/grokkingfp/all/part-1-ch01-fp-introduction.md +0 -539
  465. package/lib/assets/docs/article/grokkingfp/all/part-1-ch02-pure-functions.md +0 -932
  466. package/lib/assets/docs/article/grokkingfp/all/part-2-ch03-immutable-data.md +0 -1137
  467. package/lib/assets/docs/article/grokkingfp/all/part-2-ch04-higher-order-functions.md +0 -1113
  468. package/lib/assets/docs/article/grokkingfp/all/part-2-ch05-flatmap.md +0 -1035
  469. package/lib/assets/docs/article/grokkingfp/all/part-3-ch06-option.md +0 -794
  470. package/lib/assets/docs/article/grokkingfp/all/part-3-ch07-either-adt.md +0 -880
  471. package/lib/assets/docs/article/grokkingfp/all/part-4-ch08-io-monad.md +0 -981
  472. package/lib/assets/docs/article/grokkingfp/all/part-4-ch09-streams.md +0 -935
  473. package/lib/assets/docs/article/grokkingfp/all/part-5-ch10-concurrency.md +0 -879
  474. package/lib/assets/docs/article/grokkingfp/all/part-6-ch11-application.md +0 -724
  475. package/lib/assets/docs/article/grokkingfp/all/part-6-ch12-testing.md +0 -635
  476. package/lib/assets/docs/article/grokkingfp/all/writing-plan.md +0 -721
  477. package/lib/assets/docs/article/grokkingfp/clojure/index.md +0 -276
  478. package/lib/assets/docs/article/grokkingfp/clojure/part-1.md +0 -676
  479. package/lib/assets/docs/article/grokkingfp/clojure/part-2.md +0 -652
  480. package/lib/assets/docs/article/grokkingfp/clojure/part-3.md +0 -629
  481. package/lib/assets/docs/article/grokkingfp/clojure/part-4.md +0 -706
  482. package/lib/assets/docs/article/grokkingfp/clojure/part-5.md +0 -760
  483. package/lib/assets/docs/article/grokkingfp/clojure/part-6.md +0 -730
  484. package/lib/assets/docs/article/grokkingfp/csharp/index.md +0 -246
  485. package/lib/assets/docs/article/grokkingfp/csharp/part-1.md +0 -820
  486. package/lib/assets/docs/article/grokkingfp/csharp/part-2.md +0 -980
  487. package/lib/assets/docs/article/grokkingfp/csharp/part-3.md +0 -990
  488. package/lib/assets/docs/article/grokkingfp/csharp/part-4.md +0 -958
  489. package/lib/assets/docs/article/grokkingfp/csharp/part-5.md +0 -956
  490. package/lib/assets/docs/article/grokkingfp/csharp/part-6.md +0 -748
  491. package/lib/assets/docs/article/grokkingfp/elixir/index.md +0 -203
  492. package/lib/assets/docs/article/grokkingfp/elixir/part-1.md +0 -721
  493. package/lib/assets/docs/article/grokkingfp/elixir/part-2.md +0 -847
  494. package/lib/assets/docs/article/grokkingfp/elixir/part-3.md +0 -994
  495. package/lib/assets/docs/article/grokkingfp/elixir/part-4.md +0 -983
  496. package/lib/assets/docs/article/grokkingfp/elixir/part-5.md +0 -1295
  497. package/lib/assets/docs/article/grokkingfp/elixir/part-6.md +0 -1058
  498. package/lib/assets/docs/article/grokkingfp/fsharp/index.md +0 -210
  499. package/lib/assets/docs/article/grokkingfp/fsharp/part-1.md +0 -723
  500. package/lib/assets/docs/article/grokkingfp/fsharp/part-2.md +0 -970
  501. package/lib/assets/docs/article/grokkingfp/fsharp/part-3.md +0 -981
  502. package/lib/assets/docs/article/grokkingfp/fsharp/part-4.md +0 -841
  503. package/lib/assets/docs/article/grokkingfp/fsharp/part-5.md +0 -920
  504. package/lib/assets/docs/article/grokkingfp/fsharp/part-6.md +0 -931
  505. package/lib/assets/docs/article/grokkingfp/haskell/index.md +0 -234
  506. package/lib/assets/docs/article/grokkingfp/haskell/part-1.md +0 -600
  507. package/lib/assets/docs/article/grokkingfp/haskell/part-2.md +0 -875
  508. package/lib/assets/docs/article/grokkingfp/haskell/part-3.md +0 -924
  509. package/lib/assets/docs/article/grokkingfp/haskell/part-4.md +0 -887
  510. package/lib/assets/docs/article/grokkingfp/haskell/part-5.md +0 -854
  511. package/lib/assets/docs/article/grokkingfp/haskell/part-6.md +0 -853
  512. package/lib/assets/docs/article/grokkingfp/index.md +0 -143
  513. package/lib/assets/docs/article/grokkingfp/java/index.md +0 -211
  514. package/lib/assets/docs/article/grokkingfp/java/part-1.md +0 -657
  515. package/lib/assets/docs/article/grokkingfp/java/part-2.md +0 -684
  516. package/lib/assets/docs/article/grokkingfp/java/part-3.md +0 -681
  517. package/lib/assets/docs/article/grokkingfp/java/part-4.md +0 -780
  518. package/lib/assets/docs/article/grokkingfp/java/part-5.md +0 -968
  519. package/lib/assets/docs/article/grokkingfp/java/part-6.md +0 -1337
  520. package/lib/assets/docs/article/grokkingfp/python/index.md +0 -258
  521. package/lib/assets/docs/article/grokkingfp/python/part-1.md +0 -452
  522. package/lib/assets/docs/article/grokkingfp/python/part-2.md +0 -967
  523. package/lib/assets/docs/article/grokkingfp/python/part-3.md +0 -1013
  524. package/lib/assets/docs/article/grokkingfp/python/part-4.md +0 -774
  525. package/lib/assets/docs/article/grokkingfp/python/part-5.md +0 -756
  526. package/lib/assets/docs/article/grokkingfp/python/part-6.md +0 -870
  527. package/lib/assets/docs/article/grokkingfp/ruby/index.md +0 -330
  528. package/lib/assets/docs/article/grokkingfp/ruby/part-1.md +0 -764
  529. package/lib/assets/docs/article/grokkingfp/ruby/part-2.md +0 -947
  530. package/lib/assets/docs/article/grokkingfp/ruby/part-3.md +0 -955
  531. package/lib/assets/docs/article/grokkingfp/ruby/part-4.md +0 -930
  532. package/lib/assets/docs/article/grokkingfp/ruby/part-5.md +0 -917
  533. package/lib/assets/docs/article/grokkingfp/ruby/part-6.md +0 -1421
  534. package/lib/assets/docs/article/grokkingfp/rust/index.md +0 -242
  535. package/lib/assets/docs/article/grokkingfp/rust/part-1.md +0 -643
  536. package/lib/assets/docs/article/grokkingfp/rust/part-2.md +0 -1069
  537. package/lib/assets/docs/article/grokkingfp/rust/part-3.md +0 -1003
  538. package/lib/assets/docs/article/grokkingfp/rust/part-4.md +0 -582
  539. package/lib/assets/docs/article/grokkingfp/rust/part-5.md +0 -714
  540. package/lib/assets/docs/article/grokkingfp/rust/part-6.md +0 -517
  541. package/lib/assets/docs/article/grokkingfp/scala/index.md +0 -171
  542. package/lib/assets/docs/article/grokkingfp/scala/part-1.md +0 -552
  543. package/lib/assets/docs/article/grokkingfp/scala/part-2.md +0 -955
  544. package/lib/assets/docs/article/grokkingfp/scala/part-3.md +0 -928
  545. package/lib/assets/docs/article/grokkingfp/scala/part-4.md +0 -751
  546. package/lib/assets/docs/article/grokkingfp/scala/part-5.md +0 -731
  547. package/lib/assets/docs/article/grokkingfp/scala/part-6.md +0 -876
  548. package/lib/assets/docs/article/grokkingfp/typescript/index.md +0 -273
  549. package/lib/assets/docs/article/grokkingfp/typescript/part-1.md +0 -570
  550. package/lib/assets/docs/article/grokkingfp/typescript/part-2.md +0 -1138
  551. package/lib/assets/docs/article/grokkingfp/typescript/part-3.md +0 -851
  552. package/lib/assets/docs/article/grokkingfp/typescript/part-4.md +0 -1096
  553. package/lib/assets/docs/article/grokkingfp/typescript/part-5.md +0 -726
  554. package/lib/assets/docs/article/grokkingfp/typescript/part-6.md +0 -991
  555. package/lib/assets/docs/article/practical-database-design/index.md +0 -121
  556. package/lib/assets/docs/article/practical-database-design/part1/chapter01.md +0 -297
  557. package/lib/assets/docs/article/practical-database-design/part1/chapter02.md +0 -527
  558. package/lib/assets/docs/article/practical-database-design/part1/chapter03.md +0 -566
  559. package/lib/assets/docs/article/practical-database-design/part2/chapter04.md +0 -933
  560. package/lib/assets/docs/article/practical-database-design/part2/chapter05.md +0 -1636
  561. package/lib/assets/docs/article/practical-database-design/part2/chapter06.md +0 -2725
  562. package/lib/assets/docs/article/practical-database-design/part2/chapter07.md +0 -2091
  563. package/lib/assets/docs/article/practical-database-design/part2/chapter08.md +0 -2114
  564. package/lib/assets/docs/article/practical-database-design/part2/chapter09.md +0 -2040
  565. package/lib/assets/docs/article/practical-database-design/part2/chapter10.md +0 -1396
  566. package/lib/assets/docs/article/practical-database-design/part2/chapter11.md +0 -1686
  567. package/lib/assets/docs/article/practical-database-design/part2/chapter12.md +0 -1426
  568. package/lib/assets/docs/article/practical-database-design/part2/chapter13.md +0 -1443
  569. package/lib/assets/docs/article/practical-database-design/part3/chapter14.md +0 -676
  570. package/lib/assets/docs/article/practical-database-design/part3/chapter15.md +0 -1634
  571. package/lib/assets/docs/article/practical-database-design/part3/chapter16.md +0 -1924
  572. package/lib/assets/docs/article/practical-database-design/part3/chapter17.md +0 -1717
  573. package/lib/assets/docs/article/practical-database-design/part3/chapter18.md +0 -2104
  574. package/lib/assets/docs/article/practical-database-design/part3/chapter19.md +0 -1132
  575. package/lib/assets/docs/article/practical-database-design/part3/chapter20.md +0 -1040
  576. package/lib/assets/docs/article/practical-database-design/part3/chapter21.md +0 -1391
  577. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter14-orm.md +0 -1000
  578. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter15-orm.md +0 -1309
  579. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter16-orm.md +0 -1175
  580. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter17-orm.md +0 -1593
  581. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter18-orm.md +0 -1192
  582. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter19-orm.md +0 -1025
  583. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter20-orm.md +0 -1762
  584. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter21-orm.md +0 -1456
  585. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter22-orm.md +0 -1887
  586. package/lib/assets/docs/article/practical-database-design/part4/chapter22.md +0 -974
  587. package/lib/assets/docs/article/practical-database-design/part4/chapter23.md +0 -2078
  588. package/lib/assets/docs/article/practical-database-design/part4/chapter24.md +0 -2448
  589. package/lib/assets/docs/article/practical-database-design/part4/chapter25.md +0 -3670
  590. package/lib/assets/docs/article/practical-database-design/part4/chapter26.md +0 -2925
  591. package/lib/assets/docs/article/practical-database-design/part4/chapter27.md +0 -3114
  592. package/lib/assets/docs/article/practical-database-design/part4/chapter28.md +0 -2706
  593. package/lib/assets/docs/article/practical-database-design/part4/chapter29.md +0 -2552
  594. package/lib/assets/docs/article/practical-database-design/part4/chapter30.md +0 -2188
  595. package/lib/assets/docs/article/practical-database-design/part4/chapter31.md +0 -1200
  596. package/lib/assets/docs/article/practical-database-design/part4/chapter32.md +0 -2109
  597. package/lib/assets/docs/article/practical-database-design/part5/chapter33.md +0 -1041
  598. package/lib/assets/docs/article/practical-database-design/part5/chapter34.md +0 -1618
  599. package/lib/assets/docs/article/practical-database-design/part5/chapter35.md +0 -1462
  600. package/lib/assets/docs/article/practical-database-design/part5/chapter36.md +0 -1301
  601. package/lib/assets/docs/article/practical-database-design/part5/chapter37.md +0 -1479
  602. package/lib/assets/docs/article/practical-database-design/part5/chapter38.md +0 -1707
  603. package/lib/assets/docs/article/practical-database-design/part5/chapter39.md +0 -2343
  604. package/lib/assets/docs/article/practical-database-design/study/study2-1.md +0 -1702
  605. package/lib/assets/docs/article/practical-database-design/study/study2-2.md +0 -1356
  606. package/lib/assets/docs/article/practical-database-design/study/study2-3.md +0 -2053
  607. package/lib/assets/docs/article/practical-database-design/study/study2-4.md +0 -2238
  608. package/lib/assets/docs/article/practical-database-design/study/study2-5.md +0 -2427
  609. package/lib/assets/docs/article/practical-database-design/study/study3-1.md +0 -2214
  610. package/lib/assets/docs/article/practical-database-design/study/study3-2.md +0 -2230
  611. package/lib/assets/docs/article/practical-database-design/study/study3-3.md +0 -2262
  612. package/lib/assets/docs/article/practical-database-design/study/study3-4.md +0 -2115
  613. package/lib/assets/docs/article/practical-database-design/study/study3-5.md +0 -2516
  614. package/lib/assets/docs/article/practical-database-design/study/study4-1.md +0 -2596
  615. package/lib/assets/docs/article/practical-database-design/study/study4-2.md +0 -2084
  616. package/lib/assets/docs/article/practical-database-design/study/study4-3.md +0 -1814
  617. package/lib/assets/docs/article/practical-database-design/study/study4-4.md +0 -1904
  618. package/lib/assets/docs/article/practical-database-design/study/study4-5.md +0 -2887
@@ -1,1707 +0,0 @@
1
- ---
2
- type: Article
3
- title: "第38章:API 設計とサービス連携"
4
- description: "本章では、基幹業務システムにおける API 設計の原則と、サービス間連携のパターンについて解説します。"
5
- tags: [article, practical-database-design, part5]
6
- status: stable
7
- generated: { by: human:kakimomokuri, at: 2026-03-30T08:34:28Z }
8
- ---
9
-
10
- # 第38章:API 設計とサービス連携
11
-
12
- 本章では、基幹業務システムにおける API 設計の原則と、サービス間連携のパターンについて解説します。RESTful API の設計、サービス間通信の方式、API ゲートウェイの活用、そしてインテグレーションテストの実践方法を学びます。
13
-
14
- ---
15
-
16
- ## 38.1 API 設計の原則
17
-
18
- ### RESTful API の設計
19
-
20
- REST(Representational State Transfer)は、Web API 設計の標準的なアーキテクチャスタイルです。
21
-
22
- ```plantuml
23
- @startuml
24
- title RESTful API の基本原則
25
-
26
- rectangle "REST の制約" as constraints {
27
- rectangle "クライアント-サーバー" as cs {
28
- note right
29
- 関心の分離
30
- 独立した進化
31
- end note
32
- }
33
-
34
- rectangle "ステートレス" as stateless {
35
- note right
36
- 各リクエストは独立
37
- セッション状態を保持しない
38
- end note
39
- }
40
-
41
- rectangle "キャッシュ可能" as cacheable {
42
- note right
43
- レスポンスにキャッシュ可否を明示
44
- パフォーマンス向上
45
- end note
46
- }
47
-
48
- rectangle "統一インターフェース" as uniform {
49
- note right
50
- リソース識別(URI)
51
- 表現によるリソース操作
52
- 自己記述メッセージ
53
- HATEOAS
54
- end note
55
- }
56
-
57
- rectangle "階層化システム" as layered {
58
- note right
59
- 中間サーバーの追加が可能
60
- ロードバランサー、キャッシュ等
61
- end note
62
- }
63
- }
64
-
65
- @enduml
66
- ```
67
-
68
- #### HTTP メソッドとリソース操作
69
-
70
- | HTTP メソッド | 操作 | 冪等性 | 安全性 | 使用例 |
71
- |-------------|-----|-------|-------|-------|
72
- | GET | 取得 | Yes | Yes | リソースの参照 |
73
- | POST | 作成 | No | No | 新規リソース作成 |
74
- | PUT | 置換 | Yes | No | リソース全体の更新 |
75
- | PATCH | 部分更新 | No | No | リソースの一部更新 |
76
- | DELETE | 削除 | Yes | No | リソースの削除 |
77
-
78
- ### リソース指向設計
79
-
80
- API はリソース(名詞)を中心に設計し、操作は HTTP メソッドで表現します。
81
-
82
- ```plantuml
83
- @startuml
84
- title リソース指向 API 設計
85
-
86
- package "販売管理 API" as sales_api {
87
- rectangle "/orders" as orders {
88
- rectangle "GET /orders" as get_orders
89
- rectangle "POST /orders" as post_order
90
- rectangle "GET /orders/{id}" as get_order
91
- rectangle "PUT /orders/{id}" as put_order
92
- rectangle "DELETE /orders/{id}" as delete_order
93
- }
94
-
95
- rectangle "/orders/{id}/lines" as order_lines {
96
- rectangle "GET /orders/{id}/lines" as get_lines
97
- rectangle "POST /orders/{id}/lines" as post_line
98
- }
99
-
100
- rectangle "/customers" as customers {
101
- rectangle "GET /customers" as get_customers
102
- rectangle "POST /customers" as post_customer
103
- rectangle "GET /customers/{id}" as get_customer
104
- }
105
-
106
- rectangle "/customers/{id}/orders" as customer_orders {
107
- rectangle "GET /customers/{id}/orders" as get_customer_orders
108
- }
109
- }
110
-
111
- note bottom of sales_api
112
- 【設計原則】
113
- ・リソースは名詞(複数形)
114
- ・操作はHTTPメソッドで表現
115
- ・階層構造で関連を表現
116
- ・クエリパラメータでフィルタリング
117
- end note
118
-
119
- @enduml
120
- ```
121
-
122
- #### 基幹業務システムの API エンドポイント設計
123
-
124
- ```plantuml
125
- @startuml
126
- title 基幹業務システム API エンドポイント
127
-
128
- package "販売管理 API" as sales {
129
- rectangle "/api/v1/sales" as sales_base {
130
- rectangle "受注: /orders"
131
- rectangle "出荷: /shipments"
132
- rectangle "売上: /sales"
133
- rectangle "請求: /invoices"
134
- rectangle "入金: /payments"
135
- }
136
- rectangle "/api/v1/sales/masters" as sales_masters {
137
- rectangle "顧客: /customers"
138
- rectangle "商品: /products"
139
- }
140
- }
141
-
142
- package "財務会計 API" as accounting {
143
- rectangle "/api/v1/accounting" as acc_base {
144
- rectangle "仕訳: /journals"
145
- rectangle "残高: /balances"
146
- rectangle "試算表: /trial-balances"
147
- }
148
- rectangle "/api/v1/accounting/masters" as acc_masters {
149
- rectangle "勘定科目: /accounts"
150
- rectangle "補助科目: /sub-accounts"
151
- }
152
- }
153
-
154
- package "生産管理 API" as production {
155
- rectangle "/api/v1/production" as prod_base {
156
- rectangle "製造指示: /work-orders"
157
- rectangle "発注: /purchase-orders"
158
- rectangle "在庫: /inventory"
159
- }
160
- rectangle "/api/v1/production/masters" as prod_masters {
161
- rectangle "品目: /items"
162
- rectangle "BOM: /bom"
163
- rectangle "工程: /processes"
164
- }
165
- }
166
-
167
- @enduml
168
- ```
169
-
170
- <details>
171
- <summary>OpenAPI 定義例</summary>
172
-
173
- ```yaml
174
- openapi: 3.0.3
175
- info:
176
- title: 販売管理 API
177
- version: 1.0.0
178
- description: 基幹業務システム - 販売管理 API
179
-
180
- servers:
181
- - url: https://api.example.com/api/v1/sales
182
- description: Production server
183
-
184
- paths:
185
- /orders:
186
- get:
187
- summary: 受注一覧取得
188
- operationId: getOrders
189
- parameters:
190
- - name: customerId
191
- in: query
192
- schema:
193
- type: string
194
- - name: status
195
- in: query
196
- schema:
197
- type: string
198
- enum: [DRAFT, CONFIRMED, SHIPPED, COMPLETED]
199
- - name: fromDate
200
- in: query
201
- schema:
202
- type: string
203
- format: date
204
- - name: toDate
205
- in: query
206
- schema:
207
- type: string
208
- format: date
209
- - name: page
210
- in: query
211
- schema:
212
- type: integer
213
- default: 0
214
- - name: size
215
- in: query
216
- schema:
217
- type: integer
218
- default: 20
219
- responses:
220
- '200':
221
- description: 成功
222
- content:
223
- application/json:
224
- schema:
225
- $ref: '#/components/schemas/OrderListResponse'
226
-
227
- post:
228
- summary: 受注登録
229
- operationId: createOrder
230
- requestBody:
231
- required: true
232
- content:
233
- application/json:
234
- schema:
235
- $ref: '#/components/schemas/CreateOrderRequest'
236
- responses:
237
- '201':
238
- description: 作成成功
239
- content:
240
- application/json:
241
- schema:
242
- $ref: '#/components/schemas/OrderResponse'
243
- '400':
244
- description: バリデーションエラー
245
- content:
246
- application/problem+json:
247
- schema:
248
- $ref: '#/components/schemas/ProblemDetail'
249
-
250
- /orders/{orderId}:
251
- get:
252
- summary: 受注詳細取得
253
- operationId: getOrder
254
- parameters:
255
- - name: orderId
256
- in: path
257
- required: true
258
- schema:
259
- type: string
260
- responses:
261
- '200':
262
- description: 成功
263
- content:
264
- application/json:
265
- schema:
266
- $ref: '#/components/schemas/OrderResponse'
267
- '404':
268
- description: 受注が見つからない
269
-
270
- components:
271
- schemas:
272
- OrderResponse:
273
- type: object
274
- properties:
275
- orderId:
276
- type: string
277
- customerId:
278
- type: string
279
- customerName:
280
- type: string
281
- orderDate:
282
- type: string
283
- format: date
284
- status:
285
- type: string
286
- enum: [DRAFT, CONFIRMED, SHIPPED, COMPLETED]
287
- totalAmount:
288
- type: number
289
- taxAmount:
290
- type: number
291
- lines:
292
- type: array
293
- items:
294
- $ref: '#/components/schemas/OrderLineResponse'
295
- _links:
296
- $ref: '#/components/schemas/Links'
297
-
298
- CreateOrderRequest:
299
- type: object
300
- required:
301
- - customerId
302
- - orderDate
303
- - lines
304
- properties:
305
- customerId:
306
- type: string
307
- orderDate:
308
- type: string
309
- format: date
310
- requestedDeliveryDate:
311
- type: string
312
- format: date
313
- lines:
314
- type: array
315
- items:
316
- $ref: '#/components/schemas/CreateOrderLineRequest'
317
- minItems: 1
318
-
319
- ProblemDetail:
320
- type: object
321
- properties:
322
- type:
323
- type: string
324
- title:
325
- type: string
326
- status:
327
- type: integer
328
- detail:
329
- type: string
330
- instance:
331
- type: string
332
- ```
333
-
334
- </details>
335
-
336
- ### バージョニング戦略
337
-
338
- API の互換性を維持しながら進化させるためのバージョニング戦略を検討します。
339
-
340
- ```plantuml
341
- @startuml
342
- title API バージョニング戦略の比較
343
-
344
- rectangle "URI パスバージョニング" as uri {
345
- note right
346
- /api/v1/orders
347
- /api/v2/orders
348
-
349
- 【メリット】
350
- ・明確で分かりやすい
351
- ・キャッシュしやすい
352
-
353
- 【デメリット】
354
- ・URIの変更が必要
355
- end note
356
- }
357
-
358
- rectangle "クエリパラメータ" as query {
359
- note right
360
- /api/orders?version=1
361
- /api/orders?version=2
362
-
363
- 【メリット】
364
- ・URIが変わらない
365
-
366
- 【デメリット】
367
- ・見落としやすい
368
- end note
369
- }
370
-
371
- rectangle "カスタムヘッダー" as header {
372
- note right
373
- X-API-Version: 1
374
- X-API-Version: 2
375
-
376
- 【メリット】
377
- ・URIがクリーン
378
-
379
- 【デメリット】
380
- ・テストしにくい
381
- end note
382
- }
383
-
384
- rectangle "Accept ヘッダー" as accept {
385
- note right
386
- Accept: application/vnd.company.v1+json
387
- Accept: application/vnd.company.v2+json
388
-
389
- 【メリット】
390
- ・HTTP標準に準拠
391
-
392
- 【デメリット】
393
- ・複雑
394
- end note
395
- }
396
-
397
- @enduml
398
- ```
399
-
400
- #### 推奨:URI パスバージョニング
401
-
402
- ```plantuml
403
- @startuml
404
- title URI パスバージョニングの運用
405
-
406
- rectangle "v1(現行)" as v1 {
407
- rectangle "/api/v1/orders" as v1_orders
408
- rectangle "/api/v1/customers" as v1_customers
409
- }
410
-
411
- rectangle "v2(新版)" as v2 {
412
- rectangle "/api/v2/orders" as v2_orders
413
- rectangle "/api/v2/customers" as v2_customers
414
- }
415
-
416
- note bottom of v1
417
- 【v1 → v2 移行】
418
- 1. v2を新規リリース
419
- 2. 並行運用期間
420
- 3. v1を非推奨化(Deprecation)
421
- 4. v1を廃止(Sunset)
422
-
423
- 【Deprecation ヘッダー】
424
- Deprecation: true
425
- Sunset: Sat, 01 Jan 2025 00:00:00 GMT
426
- end note
427
-
428
- @enduml
429
- ```
430
-
431
- ---
432
-
433
- ## 38.2 サービス間通信
434
-
435
- ### 同期通信(REST / gRPC)
436
-
437
- ```plantuml
438
- @startuml
439
- title 同期通信パターンの比較
440
-
441
- rectangle "REST over HTTP" as rest {
442
- rectangle "販売サービス" as sales_rest
443
- rectangle "在庫サービス" as inv_rest
444
-
445
- sales_rest --> inv_rest : HTTP/JSON
446
- }
447
-
448
- rectangle "gRPC" as grpc {
449
- rectangle "販売サービス" as sales_grpc
450
- rectangle "在庫サービス" as inv_grpc
451
-
452
- sales_grpc --> inv_grpc : HTTP/2 + Protocol Buffers
453
- }
454
-
455
- note bottom of rest
456
- 【REST】
457
- ・テキストベース(JSON)
458
- ・ブラウザから直接呼び出し可能
459
- ・広く普及、ツール豊富
460
-
461
- 【適用場面】
462
- ・外部公開API
463
- ・フロントエンド連携
464
- end note
465
-
466
- note bottom of grpc
467
- 【gRPC】
468
- ・バイナリプロトコル
469
- ・高速、低レイテンシ
470
- ・スキーマ定義必須
471
-
472
- 【適用場面】
473
- ・マイクロサービス間
474
- ・高性能要件
475
- end note
476
-
477
- @enduml
478
- ```
479
-
480
- <details>
481
- <summary>gRPC 定義例</summary>
482
-
483
- ```protobuf
484
- syntax = "proto3";
485
-
486
- package sales.v1;
487
-
488
- option java_package = "com.example.sales.grpc";
489
- option java_multiple_files = true;
490
-
491
- // 在庫サービス
492
- service InventoryService {
493
- // 在庫照会
494
- rpc GetStock(GetStockRequest) returns (StockResponse);
495
-
496
- // 在庫引当
497
- rpc AllocateStock(AllocateStockRequest) returns (AllocateStockResponse);
498
-
499
- // 引当解除
500
- rpc ReleaseStock(ReleaseStockRequest) returns (ReleaseStockResponse);
501
- }
502
-
503
- message GetStockRequest {
504
- string product_id = 1;
505
- string warehouse_id = 2;
506
- }
507
-
508
- message StockResponse {
509
- string product_id = 1;
510
- string warehouse_id = 2;
511
- int32 quantity = 3;
512
- int32 allocated_quantity = 4;
513
- int32 available_quantity = 5;
514
- }
515
-
516
- message AllocateStockRequest {
517
- string product_id = 1;
518
- string warehouse_id = 2;
519
- int32 quantity = 3;
520
- string order_id = 4;
521
- }
522
-
523
- message AllocateStockResponse {
524
- bool success = 1;
525
- string allocation_id = 2;
526
- string error_message = 3;
527
- }
528
- ```
529
-
530
- </details>
531
-
532
- ### 非同期通信(メッセージキュー)
533
-
534
- ```plantuml
535
- @startuml
536
- title 非同期通信パターン
537
-
538
- rectangle "販売サービス" as sales
539
-
540
- rectangle "メッセージブローカー" as broker {
541
- queue "受注キュー" as order_queue
542
- collections "売上トピック" as sales_topic
543
- }
544
-
545
- rectangle "在庫サービス" as inventory
546
- rectangle "会計サービス" as accounting
547
- rectangle "通知サービス" as notification
548
-
549
- sales --> order_queue : 受注メッセージ
550
- order_queue --> inventory : 在庫引当
551
-
552
- sales --> sales_topic : 売上イベント
553
- sales_topic --> accounting : 仕訳生成
554
- sales_topic --> notification : 通知送信
555
- sales_topic --> inventory : 在庫更新
556
-
557
- note bottom of broker
558
- 【Point-to-Point】
559
- ・1対1の通信
560
- ・キューで実現
561
- ・負荷分散可能
562
-
563
- 【Publish-Subscribe】
564
- ・1対多の通信
565
- ・トピックで実現
566
- ・イベント配信
567
- end note
568
-
569
- @enduml
570
- ```
571
-
572
- <details>
573
- <summary>Java 実装例(Spring AMQP)</summary>
574
-
575
- ```java
576
- // メッセージ送信
577
- @Service
578
- public class OrderMessagePublisher {
579
- private final RabbitTemplate rabbitTemplate;
580
-
581
- public void publishOrderCreated(OrderCreatedEvent event) {
582
- rabbitTemplate.convertAndSend(
583
- "sales.exchange",
584
- "order.created",
585
- event
586
- );
587
- }
588
-
589
- public void publishSalesCompleted(SalesCompletedEvent event) {
590
- rabbitTemplate.convertAndSend(
591
- "sales.topic.exchange",
592
- "sales.completed",
593
- event
594
- );
595
- }
596
- }
597
-
598
- // メッセージ受信
599
- @Component
600
- public class OrderMessageListener {
601
-
602
- @RabbitListener(queues = "inventory.order.queue")
603
- public void handleOrderCreated(OrderCreatedEvent event) {
604
- // 在庫引当処理
605
- log.info("Received order: {}", event.orderId());
606
- inventoryService.allocate(event);
607
- }
608
- }
609
-
610
- // 設定
611
- @Configuration
612
- public class RabbitMQConfig {
613
-
614
- @Bean
615
- public TopicExchange salesTopicExchange() {
616
- return new TopicExchange("sales.topic.exchange");
617
- }
618
-
619
- @Bean
620
- public Queue accountingQueue() {
621
- return new Queue("accounting.sales.queue", true);
622
- }
623
-
624
- @Bean
625
- public Binding accountingBinding(Queue accountingQueue,
626
- TopicExchange salesTopicExchange) {
627
- return BindingBuilder.bind(accountingQueue)
628
- .to(salesTopicExchange)
629
- .with("sales.*");
630
- }
631
- }
632
- ```
633
-
634
- </details>
635
-
636
- ### サーキットブレーカーパターン
637
-
638
- サービス間通信の障害を検知し、障害の連鎖を防ぐパターンです。
639
-
640
- ```plantuml
641
- @startuml
642
- title サーキットブレーカーの状態遷移
643
-
644
- [*] --> Closed : 初期状態
645
-
646
- Closed --> Open : 失敗が閾値を超過
647
- Closed --> Closed : 成功
648
-
649
- Open --> HalfOpen : タイムアウト後
650
- Open --> Open : リクエスト拒否
651
-
652
- HalfOpen --> Closed : 試行成功
653
- HalfOpen --> Open : 試行失敗
654
-
655
- note right of Closed
656
- 【Closed】
657
- 通常稼働
658
- リクエストを通す
659
- end note
660
-
661
- note right of Open
662
- 【Open】
663
- 障害検知
664
- 即座にエラー返却
665
- (Fail Fast)
666
- end note
667
-
668
- note right of HalfOpen
669
- 【Half-Open】
670
- 復旧確認中
671
- 限定的に試行
672
- end note
673
-
674
- @enduml
675
- ```
676
-
677
- ```plantuml
678
- @startuml
679
- title サーキットブレーカーの動作フロー
680
-
681
- |クライアント|
682
- start
683
- :サービス呼び出し;
684
-
685
- |サーキットブレーカー|
686
- if (回路状態?) then (Open)
687
- :即座にフォールバック;
688
- |クライアント|
689
- :フォールバック結果;
690
- stop
691
- else (Closed/HalfOpen)
692
- endif
693
-
694
- :下流サービス呼び出し;
695
-
696
- |下流サービス|
697
- if (処理成功?) then (yes)
698
- :正常レスポンス;
699
- |サーキットブレーカー|
700
- :成功をカウント;
701
- :Closedを維持/遷移;
702
- else (no)
703
- :エラー/タイムアウト;
704
- |サーキットブレーカー|
705
- :失敗をカウント;
706
-
707
- if (失敗数 >= 閾値?) then (yes)
708
- :Openに遷移;
709
- endif
710
- endif
711
-
712
- |クライアント|
713
- :結果を返却;
714
-
715
- stop
716
-
717
- @enduml
718
- ```
719
-
720
- <details>
721
- <summary>Java 実装例(Resilience4j)</summary>
722
-
723
- ```java
724
- // 設定
725
- @Configuration
726
- public class CircuitBreakerConfig {
727
-
728
- @Bean
729
- public CircuitBreakerRegistry circuitBreakerRegistry() {
730
- CircuitBreakerConfig config = CircuitBreakerConfig.custom()
731
- .failureRateThreshold(50) // 失敗率50%でOpen
732
- .waitDurationInOpenState(Duration.ofSeconds(30))
733
- .permittedNumberOfCallsInHalfOpenState(3)
734
- .slidingWindowType(SlidingWindowType.COUNT_BASED)
735
- .slidingWindowSize(10)
736
- .build();
737
-
738
- return CircuitBreakerRegistry.of(config);
739
- }
740
- }
741
-
742
- // サービス
743
- @Service
744
- public class InventoryServiceClient {
745
- private final RestTemplate restTemplate;
746
- private final CircuitBreaker circuitBreaker;
747
-
748
- public InventoryServiceClient(RestTemplate restTemplate,
749
- CircuitBreakerRegistry registry) {
750
- this.restTemplate = restTemplate;
751
- this.circuitBreaker = registry.circuitBreaker("inventoryService");
752
- }
753
-
754
- public StockResponse getStock(String productId) {
755
- Supplier<StockResponse> supplier = CircuitBreaker
756
- .decorateSupplier(circuitBreaker, () -> {
757
- return restTemplate.getForObject(
758
- "/api/v1/inventory/{productId}",
759
- StockResponse.class,
760
- productId
761
- );
762
- });
763
-
764
- return Try.ofSupplier(supplier)
765
- .recover(CallNotPermittedException.class,
766
- e -> getFallbackStock(productId))
767
- .recover(Exception.class,
768
- e -> getFallbackStock(productId))
769
- .get();
770
- }
771
-
772
- private StockResponse getFallbackStock(String productId) {
773
- // フォールバック: キャッシュから取得または推定値
774
- return new StockResponse(productId, 0, 0, 0, "UNKNOWN");
775
- }
776
- }
777
-
778
- // アノテーションベース
779
- @Service
780
- public class AccountingServiceClient {
781
-
782
- @CircuitBreaker(name = "accountingService", fallbackMethod = "fallback")
783
- @Retry(name = "accountingService")
784
- @TimeLimiter(name = "accountingService")
785
- public CompletableFuture<JournalResponse> createJournal(
786
- CreateJournalRequest request) {
787
- return CompletableFuture.supplyAsync(() -> {
788
- return restTemplate.postForObject(
789
- "/api/v1/accounting/journals",
790
- request,
791
- JournalResponse.class
792
- );
793
- });
794
- }
795
-
796
- public CompletableFuture<JournalResponse> fallback(
797
- CreateJournalRequest request, Throwable t) {
798
- log.warn("Fallback for createJournal: {}", t.getMessage());
799
- // 仕訳をキューに保存して後で再試行
800
- pendingJournalQueue.add(request);
801
- return CompletableFuture.completedFuture(
802
- JournalResponse.pending(request.getCorrelationId())
803
- );
804
- }
805
- }
806
- ```
807
-
808
- </details>
809
-
810
- ---
811
-
812
- ## 38.3 API ゲートウェイ
813
-
814
- API ゲートウェイは、クライアントと複数のバックエンドサービスの間に位置し、横断的な関心事を一元的に処理します。
815
-
816
- ```plantuml
817
- @startuml
818
- title API ゲートウェイアーキテクチャ
819
-
820
- rectangle "クライアント" as clients {
821
- rectangle "Webアプリ" as web
822
- rectangle "モバイルアプリ" as mobile
823
- rectangle "外部システム" as external
824
- }
825
-
826
- rectangle "API Gateway" as gateway {
827
- rectangle "認証・認可" as auth
828
- rectangle "レート制限" as rate
829
- rectangle "ルーティング" as routing
830
- rectangle "ログ・監視" as logging
831
- rectangle "変換・集約" as transform
832
- }
833
-
834
- rectangle "バックエンドサービス" as backend {
835
- rectangle "販売API" as sales
836
- rectangle "会計API" as accounting
837
- rectangle "生産API" as production
838
- }
839
-
840
- web --> gateway
841
- mobile --> gateway
842
- external --> gateway
843
-
844
- gateway --> sales
845
- gateway --> accounting
846
- gateway --> production
847
-
848
- note bottom of gateway
849
- 【API Gatewayの責務】
850
- ・認証・認可の一元化
851
- ・レート制限
852
- ・リクエストルーティング
853
- ・ログ集約
854
- ・レスポンス変換
855
- ・API集約
856
- end note
857
-
858
- @enduml
859
- ```
860
-
861
- ### 認証・認可の一元化
862
-
863
- ```plantuml
864
- @startuml
865
- title JWT 認証フロー
866
-
867
- |クライアント|
868
- start
869
- :認証リクエスト;
870
- note right
871
- POST /auth/login
872
- {username, password}
873
- end note
874
-
875
- |認証サービス|
876
- :認証情報検証;
877
- :JWTトークン発行;
878
- note right
879
- Header: {alg, typ}
880
- Payload: {sub, roles, exp}
881
- Signature
882
- end note
883
-
884
- |クライアント|
885
- :JWTトークン保存;
886
- :API呼び出し;
887
- note right
888
- Authorization: Bearer {token}
889
- end note
890
-
891
- |API Gateway|
892
- :JWTトークン検証;
893
- if (有効?) then (yes)
894
- :クレーム抽出;
895
- :認可チェック;
896
- if (権限あり?) then (yes)
897
- |バックエンドサービス|
898
- :リクエスト処理;
899
- :レスポンス返却;
900
- else (no)
901
- :403 Forbidden;
902
- endif
903
- else (no)
904
- :401 Unauthorized;
905
- endif
906
-
907
- |クライアント|
908
- :結果受信;
909
-
910
- stop
911
-
912
- @enduml
913
- ```
914
-
915
- <details>
916
- <summary>Java 実装例(Spring Security + JWT)</summary>
917
-
918
- ```java
919
- // JWT フィルター
920
- @Component
921
- public class JwtAuthenticationFilter extends OncePerRequestFilter {
922
- private final JwtTokenProvider tokenProvider;
923
-
924
- @Override
925
- protected void doFilterInternal(HttpServletRequest request,
926
- HttpServletResponse response,
927
- FilterChain filterChain)
928
- throws ServletException, IOException {
929
-
930
- String token = extractToken(request);
931
-
932
- if (token != null && tokenProvider.validateToken(token)) {
933
- Authentication auth = tokenProvider.getAuthentication(token);
934
- SecurityContextHolder.getContext().setAuthentication(auth);
935
- }
936
-
937
- filterChain.doFilter(request, response);
938
- }
939
-
940
- private String extractToken(HttpServletRequest request) {
941
- String bearerToken = request.getHeader("Authorization");
942
- if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
943
- return bearerToken.substring(7);
944
- }
945
- return null;
946
- }
947
- }
948
-
949
- // JWT プロバイダー
950
- @Component
951
- public class JwtTokenProvider {
952
- @Value("${jwt.secret}")
953
- private String jwtSecret;
954
-
955
- @Value("${jwt.expiration}")
956
- private long jwtExpiration;
957
-
958
- public String generateToken(Authentication authentication) {
959
- UserDetails userDetails = (UserDetails) authentication.getPrincipal();
960
-
961
- return Jwts.builder()
962
- .setSubject(userDetails.getUsername())
963
- .claim("roles", userDetails.getAuthorities().stream()
964
- .map(GrantedAuthority::getAuthority)
965
- .collect(Collectors.toList()))
966
- .setIssuedAt(new Date())
967
- .setExpiration(new Date(System.currentTimeMillis() + jwtExpiration))
968
- .signWith(SignatureAlgorithm.HS512, jwtSecret)
969
- .compact();
970
- }
971
-
972
- public boolean validateToken(String token) {
973
- try {
974
- Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token);
975
- return true;
976
- } catch (JwtException | IllegalArgumentException e) {
977
- return false;
978
- }
979
- }
980
-
981
- public Authentication getAuthentication(String token) {
982
- Claims claims = Jwts.parser()
983
- .setSigningKey(jwtSecret)
984
- .parseClaimsJws(token)
985
- .getBody();
986
-
987
- List<String> roles = claims.get("roles", List.class);
988
- List<GrantedAuthority> authorities = roles.stream()
989
- .map(SimpleGrantedAuthority::new)
990
- .collect(Collectors.toList());
991
-
992
- User principal = new User(claims.getSubject(), "", authorities);
993
- return new UsernamePasswordAuthenticationToken(
994
- principal, token, authorities
995
- );
996
- }
997
- }
998
- ```
999
-
1000
- </details>
1001
-
1002
- ### レート制限とスロットリング
1003
-
1004
- ```plantuml
1005
- @startuml
1006
- title レート制限アルゴリズム
1007
-
1008
- rectangle "Token Bucket" as token_bucket {
1009
- note right
1010
- ・バケットにトークンを蓄積
1011
- ・リクエスト時にトークン消費
1012
- ・バースト対応可能
1013
-
1014
- 設定例:
1015
- rate: 100/分
1016
- burst: 20
1017
- end note
1018
- }
1019
-
1020
- rectangle "Sliding Window" as sliding_window {
1021
- note right
1022
- ・時間枠内のリクエスト数をカウント
1023
- ・枠をスライドして計算
1024
- ・より正確な制限
1025
-
1026
- 設定例:
1027
- window: 1分
1028
- limit: 100
1029
- end note
1030
- }
1031
-
1032
- rectangle "Fixed Window" as fixed_window {
1033
- note right
1034
- ・固定時間枠でカウント
1035
- ・シンプルな実装
1036
- ・境界でバーストの可能性
1037
-
1038
- 設定例:
1039
- window: 1分
1040
- limit: 100
1041
- end note
1042
- }
1043
-
1044
- @enduml
1045
- ```
1046
-
1047
- <details>
1048
- <summary>Spring Cloud Gateway 設定例</summary>
1049
-
1050
- ```yaml
1051
- # application.yml
1052
- spring:
1053
- cloud:
1054
- gateway:
1055
- routes:
1056
- - id: sales-service
1057
- uri: lb://sales-service
1058
- predicates:
1059
- - Path=/api/v1/sales/**
1060
- filters:
1061
- - name: RequestRateLimiter
1062
- args:
1063
- redis-rate-limiter.replenishRate: 100
1064
- redis-rate-limiter.burstCapacity: 200
1065
- key-resolver: "#{@userKeyResolver}"
1066
- - name: CircuitBreaker
1067
- args:
1068
- name: salesCircuitBreaker
1069
- fallbackUri: forward:/fallback/sales
1070
-
1071
- - id: accounting-service
1072
- uri: lb://accounting-service
1073
- predicates:
1074
- - Path=/api/v1/accounting/**
1075
- filters:
1076
- - name: RequestRateLimiter
1077
- args:
1078
- redis-rate-limiter.replenishRate: 50
1079
- redis-rate-limiter.burstCapacity: 100
1080
-
1081
- default-filters:
1082
- - name: Retry
1083
- args:
1084
- retries: 3
1085
- statuses: BAD_GATEWAY,SERVICE_UNAVAILABLE
1086
- methods: GET
1087
- backoff:
1088
- firstBackoff: 100ms
1089
- maxBackoff: 500ms
1090
- factor: 2
1091
- ```
1092
-
1093
- ```java
1094
- // Key Resolver(ユーザー単位のレート制限)
1095
- @Configuration
1096
- public class RateLimiterConfig {
1097
-
1098
- @Bean
1099
- public KeyResolver userKeyResolver() {
1100
- return exchange -> {
1101
- String userId = exchange.getRequest()
1102
- .getHeaders()
1103
- .getFirst("X-User-Id");
1104
- return Mono.just(userId != null ? userId : "anonymous");
1105
- };
1106
- }
1107
-
1108
- @Bean
1109
- public KeyResolver apiKeyResolver() {
1110
- return exchange -> {
1111
- String apiKey = exchange.getRequest()
1112
- .getHeaders()
1113
- .getFirst("X-API-Key");
1114
- return Mono.just(apiKey != null ? apiKey : "default");
1115
- };
1116
- }
1117
- }
1118
- ```
1119
-
1120
- </details>
1121
-
1122
- ### ログ集約とモニタリング
1123
-
1124
- ```plantuml
1125
- @startuml
1126
- title 分散トレーシングとログ集約
1127
-
1128
- rectangle "クライアント" as client
1129
-
1130
- rectangle "API Gateway" as gateway {
1131
- rectangle "トレースID生成" as trace_gen
1132
- }
1133
-
1134
- rectangle "サービス群" as services {
1135
- rectangle "販売サービス" as sales
1136
- rectangle "在庫サービス" as inventory
1137
- rectangle "会計サービス" as accounting
1138
- }
1139
-
1140
- rectangle "観測基盤" as observability {
1141
- database "ログ集約\n(ELK/Loki)" as logs
1142
- database "メトリクス\n(Prometheus)" as metrics
1143
- database "トレース\n(Jaeger/Zipkin)" as traces
1144
- }
1145
-
1146
- rectangle "ダッシュボード" as dashboard {
1147
- rectangle "Grafana" as grafana
1148
- rectangle "Kibana" as kibana
1149
- }
1150
-
1151
- client --> gateway : リクエスト
1152
- gateway --> sales : traceId
1153
- sales --> inventory : traceId
1154
- sales --> accounting : traceId
1155
-
1156
- gateway --> logs
1157
- sales --> logs
1158
- inventory --> logs
1159
- accounting --> logs
1160
-
1161
- gateway --> metrics
1162
- sales --> metrics
1163
- inventory --> metrics
1164
- accounting --> metrics
1165
-
1166
- gateway --> traces
1167
- sales --> traces
1168
- inventory --> traces
1169
- accounting --> traces
1170
-
1171
- logs --> kibana
1172
- metrics --> grafana
1173
- traces --> grafana
1174
-
1175
- @enduml
1176
- ```
1177
-
1178
- <details>
1179
- <summary>Java 実装例(Micrometer + OpenTelemetry)</summary>
1180
-
1181
- ```java
1182
- // トレーシング設定
1183
- @Configuration
1184
- public class TracingConfig {
1185
-
1186
- @Bean
1187
- public Tracer tracer() {
1188
- return GlobalOpenTelemetry.getTracer("sales-service");
1189
- }
1190
- }
1191
-
1192
- // カスタムメトリクス
1193
- @Component
1194
- public class OrderMetrics {
1195
- private final MeterRegistry meterRegistry;
1196
- private final Counter orderCreatedCounter;
1197
- private final Timer orderProcessingTimer;
1198
-
1199
- public OrderMetrics(MeterRegistry meterRegistry) {
1200
- this.meterRegistry = meterRegistry;
1201
-
1202
- this.orderCreatedCounter = Counter.builder("orders.created")
1203
- .description("Number of orders created")
1204
- .tag("service", "sales")
1205
- .register(meterRegistry);
1206
-
1207
- this.orderProcessingTimer = Timer.builder("orders.processing.time")
1208
- .description("Order processing time")
1209
- .tag("service", "sales")
1210
- .register(meterRegistry);
1211
- }
1212
-
1213
- public void recordOrderCreated(String status) {
1214
- orderCreatedCounter.increment();
1215
- meterRegistry.counter("orders.created.by.status",
1216
- "status", status).increment();
1217
- }
1218
-
1219
- public void recordProcessingTime(long durationMs) {
1220
- orderProcessingTimer.record(Duration.ofMillis(durationMs));
1221
- }
1222
- }
1223
-
1224
- // 構造化ログ
1225
- @Slf4j
1226
- @Service
1227
- public class OrderService {
1228
-
1229
- public Order createOrder(CreateOrderRequest request) {
1230
- MDC.put("orderId", request.getOrderId());
1231
- MDC.put("customerId", request.getCustomerId());
1232
-
1233
- try {
1234
- log.info("Creating order", kv("action", "create_order_start"));
1235
-
1236
- Order order = processOrder(request);
1237
-
1238
- log.info("Order created successfully",
1239
- kv("action", "create_order_complete"),
1240
- kv("totalAmount", order.getTotalAmount()));
1241
-
1242
- return order;
1243
- } catch (Exception e) {
1244
- log.error("Failed to create order",
1245
- kv("action", "create_order_failed"),
1246
- kv("error", e.getMessage()), e);
1247
- throw e;
1248
- } finally {
1249
- MDC.clear();
1250
- }
1251
- }
1252
- }
1253
- ```
1254
-
1255
- </details>
1256
-
1257
- ---
1258
-
1259
- ## 38.4 API インテグレーションテスト
1260
-
1261
- ### テストコンテナによる統合テスト環境
1262
-
1263
- ```plantuml
1264
- @startuml
1265
- title テストコンテナアーキテクチャ
1266
-
1267
- rectangle "テスト実行環境" as test_env {
1268
- rectangle "JUnit 5" as junit
1269
- rectangle "テストクラス" as test_class
1270
- }
1271
-
1272
- rectangle "Testcontainers" as testcontainers {
1273
- rectangle "PostgreSQL\nコンテナ" as postgres
1274
- rectangle "RabbitMQ\nコンテナ" as rabbitmq
1275
- rectangle "Redis\nコンテナ" as redis
1276
- }
1277
-
1278
- rectangle "アプリケーション" as app {
1279
- rectangle "Spring Boot\nアプリケーション" as spring
1280
- }
1281
-
1282
- test_class --> spring : HTTP リクエスト
1283
- spring --> postgres : データアクセス
1284
- spring --> rabbitmq : メッセージング
1285
- spring --> redis : キャッシュ
1286
-
1287
- junit --> testcontainers : コンテナ起動
1288
- testcontainers --> postgres
1289
- testcontainers --> rabbitmq
1290
- testcontainers --> redis
1291
-
1292
- note bottom of testcontainers
1293
- 【Testcontainersの利点】
1294
- ・本番同等の環境でテスト
1295
- ・テスト間の分離
1296
- ・CI/CDでの再現性
1297
- ・自動クリーンアップ
1298
- end note
1299
-
1300
- @enduml
1301
- ```
1302
-
1303
- <details>
1304
- <summary>Java 実装例</summary>
1305
-
1306
- ```java
1307
- // テストコンテナ設定
1308
- @Testcontainers
1309
- @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
1310
- @ActiveProfiles("test")
1311
- public abstract class IntegrationTestBase {
1312
-
1313
- @Container
1314
- static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
1315
- .withDatabaseName("testdb")
1316
- .withUsername("test")
1317
- .withPassword("test");
1318
-
1319
- @Container
1320
- static RabbitMQContainer rabbitmq = new RabbitMQContainer("rabbitmq:3.12-management");
1321
-
1322
- @DynamicPropertySource
1323
- static void configureProperties(DynamicPropertyRegistry registry) {
1324
- registry.add("spring.datasource.url", postgres::getJdbcUrl);
1325
- registry.add("spring.datasource.username", postgres::getUsername);
1326
- registry.add("spring.datasource.password", postgres::getPassword);
1327
- registry.add("spring.rabbitmq.host", rabbitmq::getHost);
1328
- registry.add("spring.rabbitmq.port", rabbitmq::getAmqpPort);
1329
- }
1330
-
1331
- @Autowired
1332
- protected TestRestTemplate restTemplate;
1333
-
1334
- @Autowired
1335
- protected JdbcTemplate jdbcTemplate;
1336
-
1337
- @BeforeEach
1338
- void setUp() {
1339
- // テストデータのクリーンアップ
1340
- cleanupTestData();
1341
- }
1342
-
1343
- protected void cleanupTestData() {
1344
- jdbcTemplate.execute("TRUNCATE TABLE 受注明細 CASCADE");
1345
- jdbcTemplate.execute("TRUNCATE TABLE 受注 CASCADE");
1346
- }
1347
- }
1348
- ```
1349
-
1350
- </details>
1351
-
1352
- ### REST API エンドポイントのテスト
1353
-
1354
- ```plantuml
1355
- @startuml
1356
- title API テストの構造
1357
-
1358
- ' ノード間の間隔を調整
1359
- skinparam nodesep 50
1360
- skinparam ranksep 50
1361
-
1362
- rectangle "== Given(前提条件)\n\n・テストデータ準備\n・認証トークン取得\n・モックの設定" as given
1363
-
1364
- rectangle "== When(操作)\n\n・APIエンドポイント呼び出し\n・リクエストボディ設定\n・ヘッダー設定" as when
1365
-
1366
- rectangle "== Then(検証)\n\n・ステータスコード確認\n・レスポンスボディ検証\n・データベース状態確認\n・イベント発行確認" as then
1367
-
1368
- given --> when
1369
- when --> then
1370
-
1371
- @enduml
1372
- ```
1373
-
1374
- <details>
1375
- <summary>Java 実装例</summary>
1376
-
1377
- ```java
1378
- // 受注API統合テスト
1379
- class OrderApiIntegrationTest extends IntegrationTestBase {
1380
-
1381
- @Autowired
1382
- private CustomerRepository customerRepository;
1383
-
1384
- @Autowired
1385
- private ProductRepository productRepository;
1386
-
1387
- private String authToken;
1388
- private Customer testCustomer;
1389
- private Product testProduct;
1390
-
1391
- @BeforeEach
1392
- void setUpTestData() {
1393
- // 認証トークン取得
1394
- authToken = getAuthToken("test-user", "password");
1395
-
1396
- // テストデータ準備
1397
- testCustomer = customerRepository.save(
1398
- new Customer("CUS-001", "テスト顧客", "test@example.com")
1399
- );
1400
- testProduct = productRepository.save(
1401
- new Product("PRD-001", "テスト商品", new BigDecimal("1000"))
1402
- );
1403
- }
1404
-
1405
- @Test
1406
- @DisplayName("受注登録: 正常系")
1407
- void createOrder_Success() {
1408
- // Given
1409
- CreateOrderRequest request = CreateOrderRequest.builder()
1410
- .customerId(testCustomer.getCustomerId())
1411
- .orderDate(LocalDate.now())
1412
- .lines(List.of(
1413
- OrderLineRequest.builder()
1414
- .productId(testProduct.getProductId())
1415
- .quantity(10)
1416
- .build()
1417
- ))
1418
- .build();
1419
-
1420
- // When
1421
- ResponseEntity<OrderResponse> response = restTemplate.exchange(
1422
- "/api/v1/sales/orders",
1423
- HttpMethod.POST,
1424
- new HttpEntity<>(request, createAuthHeaders()),
1425
- OrderResponse.class
1426
- );
1427
-
1428
- // Then
1429
- assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED);
1430
- assertThat(response.getBody()).isNotNull();
1431
- assertThat(response.getBody().getOrderId()).isNotBlank();
1432
- assertThat(response.getBody().getStatus()).isEqualTo("DRAFT");
1433
- assertThat(response.getBody().getTotalAmount())
1434
- .isEqualByComparingTo(new BigDecimal("10000"));
1435
-
1436
- // データベース状態確認
1437
- Order savedOrder = orderRepository.findById(
1438
- response.getBody().getOrderId()
1439
- ).orElseThrow();
1440
- assertThat(savedOrder.getCustomerId()).isEqualTo(testCustomer.getCustomerId());
1441
- assertThat(savedOrder.getLines()).hasSize(1);
1442
- }
1443
-
1444
- @Test
1445
- @DisplayName("受注登録: バリデーションエラー")
1446
- void createOrder_ValidationError() {
1447
- // Given - 明細なしのリクエスト
1448
- CreateOrderRequest request = CreateOrderRequest.builder()
1449
- .customerId(testCustomer.getCustomerId())
1450
- .orderDate(LocalDate.now())
1451
- .lines(List.of()) // 空の明細
1452
- .build();
1453
-
1454
- // When
1455
- ResponseEntity<ProblemDetail> response = restTemplate.exchange(
1456
- "/api/v1/sales/orders",
1457
- HttpMethod.POST,
1458
- new HttpEntity<>(request, createAuthHeaders()),
1459
- ProblemDetail.class
1460
- );
1461
-
1462
- // Then
1463
- assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
1464
- assertThat(response.getBody().getTitle()).isEqualTo("Validation Error");
1465
- }
1466
-
1467
- @Test
1468
- @DisplayName("受注一覧取得: ページング")
1469
- void getOrders_Paging() {
1470
- // Given - 複数の受注を作成
1471
- for (int i = 0; i < 25; i++) {
1472
- createTestOrder("ORD-" + String.format("%03d", i));
1473
- }
1474
-
1475
- // When
1476
- ResponseEntity<PagedResponse<OrderSummary>> response = restTemplate.exchange(
1477
- "/api/v1/sales/orders?page=0&size=10",
1478
- HttpMethod.GET,
1479
- new HttpEntity<>(createAuthHeaders()),
1480
- new ParameterizedTypeReference<>() {}
1481
- );
1482
-
1483
- // Then
1484
- assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
1485
- assertThat(response.getBody().getContent()).hasSize(10);
1486
- assertThat(response.getBody().getTotalElements()).isEqualTo(25);
1487
- assertThat(response.getBody().getTotalPages()).isEqualTo(3);
1488
- }
1489
-
1490
- private HttpHeaders createAuthHeaders() {
1491
- HttpHeaders headers = new HttpHeaders();
1492
- headers.setBearerAuth(authToken);
1493
- headers.setContentType(MediaType.APPLICATION_JSON);
1494
- return headers;
1495
- }
1496
- }
1497
- ```
1498
-
1499
- </details>
1500
-
1501
- ### サービス間連携テスト
1502
-
1503
- ```plantuml
1504
- @startuml
1505
- title サービス間連携テストのアプローチ
1506
-
1507
- ' ボックスの定義
1508
- rectangle "Contract Testing" as contract
1509
- note right of contract
1510
- ・Pact / Spring Cloud Contract
1511
- ・プロバイダーとコンシューマーの契約
1512
- ・独立したテスト実行
1513
- end note
1514
-
1515
- rectangle "Component Testing" as component
1516
- note right of component
1517
- ・WireMockで外部サービスをモック
1518
- ・単一サービスの統合テスト
1519
- ・高速なフィードバック
1520
- end note
1521
-
1522
- rectangle "End-to-End Testing" as e2e
1523
- note right of e2e
1524
- ・全サービスを起動
1525
- ・Docker Composeで環境構築
1526
- ・本番同等のシナリオテスト
1527
- end note
1528
-
1529
- ' 配置(上から下に並べる)
1530
- contract -[hidden]down-> component
1531
- component -[hidden]down-> e2e
1532
-
1533
- @enduml
1534
- ```
1535
-
1536
- <details>
1537
- <summary>Java 実装例(WireMock)</summary>
1538
-
1539
- ```java
1540
- // WireMockを使用したサービス間連携テスト
1541
- @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
1542
- @AutoConfigureWireMock(port = 0)
1543
- class OrderServiceWithInventoryTest {
1544
-
1545
- @Autowired
1546
- private TestRestTemplate restTemplate;
1547
-
1548
- @Value("${wiremock.server.port}")
1549
- private int wireMockPort;
1550
-
1551
- @BeforeEach
1552
- void setUp() {
1553
- // 在庫サービスのモック設定
1554
- stubFor(get(urlPathMatching("/api/v1/inventory/.*"))
1555
- .willReturn(aResponse()
1556
- .withStatus(200)
1557
- .withHeader("Content-Type", "application/json")
1558
- .withBody("""
1559
- {
1560
- "productId": "PRD-001",
1561
- "quantity": 100,
1562
- "allocatedQuantity": 0,
1563
- "availableQuantity": 100
1564
- }
1565
- """)));
1566
-
1567
- stubFor(post(urlPathMatching("/api/v1/inventory/allocate"))
1568
- .willReturn(aResponse()
1569
- .withStatus(200)
1570
- .withHeader("Content-Type", "application/json")
1571
- .withBody("""
1572
- {
1573
- "success": true,
1574
- "allocationId": "ALLOC-001"
1575
- }
1576
- """)));
1577
- }
1578
-
1579
- @Test
1580
- @DisplayName("受注確定: 在庫引当成功")
1581
- void confirmOrder_InventoryAllocated() {
1582
- // Given
1583
- String orderId = createDraftOrder();
1584
-
1585
- // When
1586
- ResponseEntity<OrderResponse> response = restTemplate.exchange(
1587
- "/api/v1/sales/orders/{orderId}/confirm",
1588
- HttpMethod.POST,
1589
- new HttpEntity<>(createAuthHeaders()),
1590
- OrderResponse.class,
1591
- orderId
1592
- );
1593
-
1594
- // Then
1595
- assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
1596
- assertThat(response.getBody().getStatus()).isEqualTo("CONFIRMED");
1597
-
1598
- // 在庫サービスへの呼び出しを検証
1599
- verify(postRequestedFor(urlPathEqualTo("/api/v1/inventory/allocate"))
1600
- .withRequestBody(matchingJsonPath("$.productId", equalTo("PRD-001")))
1601
- .withRequestBody(matchingJsonPath("$.quantity", equalTo("10"))));
1602
- }
1603
-
1604
- @Test
1605
- @DisplayName("受注確定: 在庫不足")
1606
- void confirmOrder_InsufficientStock() {
1607
- // Given - 在庫不足のレスポンスを設定
1608
- stubFor(post(urlPathMatching("/api/v1/inventory/allocate"))
1609
- .willReturn(aResponse()
1610
- .withStatus(200)
1611
- .withBody("""
1612
- {
1613
- "success": false,
1614
- "errorMessage": "Insufficient stock"
1615
- }
1616
- """)));
1617
-
1618
- String orderId = createDraftOrder();
1619
-
1620
- // When
1621
- ResponseEntity<ProblemDetail> response = restTemplate.exchange(
1622
- "/api/v1/sales/orders/{orderId}/confirm",
1623
- HttpMethod.POST,
1624
- new HttpEntity<>(createAuthHeaders()),
1625
- ProblemDetail.class,
1626
- orderId
1627
- );
1628
-
1629
- // Then
1630
- assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CONFLICT);
1631
- assertThat(response.getBody().getDetail()).contains("在庫不足");
1632
- }
1633
-
1634
- @Test
1635
- @DisplayName("受注確定: 在庫サービスタイムアウト")
1636
- void confirmOrder_InventoryServiceTimeout() {
1637
- // Given - タイムアウトをシミュレート
1638
- stubFor(post(urlPathMatching("/api/v1/inventory/allocate"))
1639
- .willReturn(aResponse()
1640
- .withFixedDelay(5000) // 5秒遅延
1641
- .withStatus(200)));
1642
-
1643
- String orderId = createDraftOrder();
1644
-
1645
- // When
1646
- ResponseEntity<ProblemDetail> response = restTemplate.exchange(
1647
- "/api/v1/sales/orders/{orderId}/confirm",
1648
- HttpMethod.POST,
1649
- new HttpEntity<>(createAuthHeaders()),
1650
- ProblemDetail.class,
1651
- orderId
1652
- );
1653
-
1654
- // Then - サーキットブレーカーによるフォールバック
1655
- assertThat(response.getStatusCode()).isEqualTo(HttpStatus.SERVICE_UNAVAILABLE);
1656
- }
1657
- }
1658
- ```
1659
-
1660
- </details>
1661
-
1662
- ---
1663
-
1664
- ## 38.5 まとめ
1665
-
1666
- 本章では、API 設計とサービス連携のパターンについて解説しました。
1667
-
1668
- ### 学んだこと
1669
-
1670
- 1. **API 設計の原則**
1671
-
1672
- - RESTful API の制約と設計原則
1673
- - リソース指向設計(名詞ベース、HTTP メソッド)
1674
- - バージョニング戦略(URI パス推奨)
1675
-
1676
- 2. **サービス間通信**
1677
-
1678
- - 同期通信(REST、gRPC)の使い分け
1679
- - 非同期通信(メッセージキュー)
1680
- - サーキットブレーカーによる障害対策
1681
-
1682
- 3. **API ゲートウェイ**
1683
-
1684
- - 認証・認可の一元化(JWT)
1685
- - レート制限とスロットリング
1686
- - ログ集約とモニタリング
1687
-
1688
- 4. **API インテグレーションテスト**
1689
-
1690
- - テストコンテナによる統合テスト環境
1691
- - REST API エンドポイントのテスト
1692
- - サービス間連携テスト(WireMock)
1693
-
1694
- ### API 設計チェックリスト
1695
-
1696
- - [ ] リソースは名詞(複数形)で命名されているか
1697
- - [ ] HTTP メソッドが正しく使用されているか
1698
- - [ ] エラーレスポンスは Problem Detail 形式か
1699
- - [ ] バージョニング戦略が決定されているか
1700
- - [ ] 認証・認可が適切に実装されているか
1701
- - [ ] レート制限が設定されているか
1702
- - [ ] サーキットブレーカーが導入されているか
1703
- - [ ] 統合テストが整備されているか
1704
-
1705
- ### 次章の予告
1706
-
1707
- 第39章では、データ連携の実装パターンについて解説します。バッチ連携、リアルタイム連携、連携テーブルの設計など、具体的な実装パターンを学びます。