@k2works/claude-code-booster 6.1.0 → 6.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (622) hide show
  1. package/lib/assets/.claude/skills/practicing-getting-start-tdd/SKILL.md +3 -7
  2. package/lib/assets/docs/article/index.md +16 -41
  3. package/lib/assets/docs/assets/js/extra.js +5 -1
  4. package/lib/assets/docs/assets/js/mathjax.js +27 -0
  5. package/lib/assets/docs/index.md +1 -1
  6. package/lib/assets/mkdocs.yml +6 -7
  7. package/lib/assets/ops/docker/mkdoc/Dockerfile +19 -19
  8. package/lib/assets/package.json +1 -1
  9. package/package.json +1 -1
  10. package/lib/assets/docs/article/functional-desgin-ppp/all/01-immutability-and-data-transformation.md +0 -484
  11. package/lib/assets/docs/article/functional-desgin-ppp/all/02-function-composition.md +0 -528
  12. package/lib/assets/docs/article/functional-desgin-ppp/all/03-polymorphism.md +0 -546
  13. package/lib/assets/docs/article/functional-desgin-ppp/all/04-data-validation.md +0 -309
  14. package/lib/assets/docs/article/functional-desgin-ppp/all/05-property-based-testing.md +0 -329
  15. package/lib/assets/docs/article/functional-desgin-ppp/all/06-tdd-and-functional.md +0 -507
  16. package/lib/assets/docs/article/functional-desgin-ppp/all/07-composite-pattern.md +0 -307
  17. package/lib/assets/docs/article/functional-desgin-ppp/all/08-decorator-pattern.md +0 -300
  18. package/lib/assets/docs/article/functional-desgin-ppp/all/09-adapter-pattern.md +0 -345
  19. package/lib/assets/docs/article/functional-desgin-ppp/all/10-strategy-pattern.md +0 -312
  20. package/lib/assets/docs/article/functional-desgin-ppp/all/11-command-pattern.md +0 -295
  21. package/lib/assets/docs/article/functional-desgin-ppp/all/12-visitor-pattern.md +0 -331
  22. package/lib/assets/docs/article/functional-desgin-ppp/all/13-abstract-factory-pattern.md +0 -328
  23. package/lib/assets/docs/article/functional-desgin-ppp/all/14-abstract-server-pattern.md +0 -374
  24. package/lib/assets/docs/article/functional-desgin-ppp/all/15-gossiping-bus-drivers.md +0 -165
  25. package/lib/assets/docs/article/functional-desgin-ppp/all/16-payroll-system.md +0 -187
  26. package/lib/assets/docs/article/functional-desgin-ppp/all/17-video-rental-system.md +0 -321
  27. package/lib/assets/docs/article/functional-desgin-ppp/all/18-concurrency-system.md +0 -296
  28. package/lib/assets/docs/article/functional-desgin-ppp/all/19-wa-tor-simulation.md +0 -295
  29. package/lib/assets/docs/article/functional-desgin-ppp/all/20-pattern-interactions.md +0 -283
  30. package/lib/assets/docs/article/functional-desgin-ppp/all/21-best-practices.md +0 -303
  31. package/lib/assets/docs/article/functional-desgin-ppp/all/22-oo-to-fp-migration.md +0 -346
  32. package/lib/assets/docs/article/functional-desgin-ppp/all/index.md +0 -388
  33. package/lib/assets/docs/article/functional-desgin-ppp/clojure/01-immutability-and-data-transformation.md +0 -282
  34. package/lib/assets/docs/article/functional-desgin-ppp/clojure/02-function-composition.md +0 -389
  35. package/lib/assets/docs/article/functional-desgin-ppp/clojure/03-polymorphism.md +0 -393
  36. package/lib/assets/docs/article/functional-desgin-ppp/clojure/04-clojure-spec.md +0 -359
  37. package/lib/assets/docs/article/functional-desgin-ppp/clojure/05-property-based-testing.md +0 -361
  38. package/lib/assets/docs/article/functional-desgin-ppp/clojure/06-tdd-in-functional.md +0 -392
  39. package/lib/assets/docs/article/functional-desgin-ppp/clojure/07-composite-pattern.md +0 -538
  40. package/lib/assets/docs/article/functional-desgin-ppp/clojure/08-decorator-pattern.md +0 -404
  41. package/lib/assets/docs/article/functional-desgin-ppp/clojure/09-adapter-pattern.md +0 -408
  42. package/lib/assets/docs/article/functional-desgin-ppp/clojure/10-strategy-pattern.md +0 -494
  43. package/lib/assets/docs/article/functional-desgin-ppp/clojure/11-command-pattern.md +0 -575
  44. package/lib/assets/docs/article/functional-desgin-ppp/clojure/12-visitor-pattern.md +0 -576
  45. package/lib/assets/docs/article/functional-desgin-ppp/clojure/13-abstract-factory-pattern.md +0 -484
  46. package/lib/assets/docs/article/functional-desgin-ppp/clojure/14-abstract-server-pattern.md +0 -471
  47. package/lib/assets/docs/article/functional-desgin-ppp/clojure/15-gossiping-bus-drivers.md +0 -334
  48. package/lib/assets/docs/article/functional-desgin-ppp/clojure/16-payroll-system.md +0 -410
  49. package/lib/assets/docs/article/functional-desgin-ppp/clojure/17-video-rental-system.md +0 -459
  50. package/lib/assets/docs/article/functional-desgin-ppp/clojure/18-concurrency-system.md +0 -484
  51. package/lib/assets/docs/article/functional-desgin-ppp/clojure/19-wator-simulation.md +0 -748
  52. package/lib/assets/docs/article/functional-desgin-ppp/clojure/20-pattern-interactions.md +0 -576
  53. package/lib/assets/docs/article/functional-desgin-ppp/clojure/21-best-practices.md +0 -527
  54. package/lib/assets/docs/article/functional-desgin-ppp/clojure/22-oo-to-fp-migration.md +0 -541
  55. package/lib/assets/docs/article/functional-desgin-ppp/clojure/index.md +0 -241
  56. package/lib/assets/docs/article/functional-desgin-ppp/elixir/01-immutability-and-data-transformation.md +0 -392
  57. package/lib/assets/docs/article/functional-desgin-ppp/elixir/02-function-composition.md +0 -383
  58. package/lib/assets/docs/article/functional-desgin-ppp/elixir/03-polymorphism.md +0 -384
  59. package/lib/assets/docs/article/functional-desgin-ppp/elixir/04-data-validation.md +0 -204
  60. package/lib/assets/docs/article/functional-desgin-ppp/elixir/05-property-based-testing.md +0 -277
  61. package/lib/assets/docs/article/functional-desgin-ppp/elixir/06-tdd-and-fp.md +0 -303
  62. package/lib/assets/docs/article/functional-desgin-ppp/elixir/07-effects-and-pure-functions.md +0 -173
  63. package/lib/assets/docs/article/functional-desgin-ppp/elixir/08-error-handling-strategies.md +0 -177
  64. package/lib/assets/docs/article/functional-desgin-ppp/elixir/09-io-and-external-systems.md +0 -263
  65. package/lib/assets/docs/article/functional-desgin-ppp/elixir/10-concurrency-patterns.md +0 -278
  66. package/lib/assets/docs/article/functional-desgin-ppp/elixir/11-command-pattern.md +0 -157
  67. package/lib/assets/docs/article/functional-desgin-ppp/elixir/12-visitor-pattern.md +0 -185
  68. package/lib/assets/docs/article/functional-desgin-ppp/elixir/13-abstract-factory-pattern.md +0 -613
  69. package/lib/assets/docs/article/functional-desgin-ppp/elixir/14-abstract-server-pattern.md +0 -738
  70. package/lib/assets/docs/article/functional-desgin-ppp/elixir/15-gossiping-bus-drivers.md +0 -300
  71. package/lib/assets/docs/article/functional-desgin-ppp/elixir/16-payroll-system.md +0 -429
  72. package/lib/assets/docs/article/functional-desgin-ppp/elixir/17-video-rental-system.md +0 -328
  73. package/lib/assets/docs/article/functional-desgin-ppp/elixir/18-concurrency-system.md +0 -475
  74. package/lib/assets/docs/article/functional-desgin-ppp/elixir/19-wator-simulation.md +0 -532
  75. package/lib/assets/docs/article/functional-desgin-ppp/elixir/20-pattern-interactions.md +0 -296
  76. package/lib/assets/docs/article/functional-desgin-ppp/elixir/21-best-practices.md +0 -349
  77. package/lib/assets/docs/article/functional-desgin-ppp/elixir/22-oo-to-fp-migration.md +0 -404
  78. package/lib/assets/docs/article/functional-desgin-ppp/elixir/index.md +0 -248
  79. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/01-immutability-and-data-transformation.md +0 -393
  80. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/02-function-composition.md +0 -461
  81. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/03-polymorphism.md +0 -504
  82. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/04-data-validation.md +0 -425
  83. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/05-property-based-testing.md +0 -391
  84. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/06-tdd-functional.md +0 -696
  85. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/07-composite-pattern.md +0 -451
  86. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/08-decorator-pattern.md +0 -488
  87. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/09-adapter-pattern.md +0 -488
  88. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/10-strategy-pattern.md +0 -436
  89. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/11-command-pattern.md +0 -437
  90. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/12-visitor-pattern.md +0 -348
  91. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/13-abstract-factory-pattern.md +0 -318
  92. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/14-abstract-server-pattern.md +0 -605
  93. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/15-gossiping-bus-drivers.md +0 -364
  94. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/16-payroll-system.md +0 -359
  95. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/17-video-rental-system.md +0 -423
  96. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/18-concurrency-system.md +0 -376
  97. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/19-wator-simulation.md +0 -412
  98. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/20-pattern-interactions.md +0 -300
  99. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/21-best-practices.md +0 -333
  100. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/22-oo-to-fp-migration.md +0 -341
  101. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/index.md +0 -274
  102. package/lib/assets/docs/article/functional-desgin-ppp/haskell/01-immutability-and-data-transformation.md +0 -307
  103. package/lib/assets/docs/article/functional-desgin-ppp/haskell/02-function-composition.md +0 -313
  104. package/lib/assets/docs/article/functional-desgin-ppp/haskell/03-polymorphism.md +0 -371
  105. package/lib/assets/docs/article/functional-desgin-ppp/haskell/04-data-validation.md +0 -266
  106. package/lib/assets/docs/article/functional-desgin-ppp/haskell/05-property-based-testing.md +0 -263
  107. package/lib/assets/docs/article/functional-desgin-ppp/haskell/06-tdd-functional.md +0 -292
  108. package/lib/assets/docs/article/functional-desgin-ppp/haskell/07-composite-pattern.md +0 -404
  109. package/lib/assets/docs/article/functional-desgin-ppp/haskell/08-decorator-pattern.md +0 -328
  110. package/lib/assets/docs/article/functional-desgin-ppp/haskell/09-adapter-pattern.md +0 -391
  111. package/lib/assets/docs/article/functional-desgin-ppp/haskell/10-strategy-pattern.md +0 -296
  112. package/lib/assets/docs/article/functional-desgin-ppp/haskell/11-command-pattern.md +0 -312
  113. package/lib/assets/docs/article/functional-desgin-ppp/haskell/12-visitor-pattern.md +0 -335
  114. package/lib/assets/docs/article/functional-desgin-ppp/haskell/13-abstract-factory-pattern.md +0 -341
  115. package/lib/assets/docs/article/functional-desgin-ppp/haskell/14-abstract-server-pattern.md +0 -388
  116. package/lib/assets/docs/article/functional-desgin-ppp/haskell/15-gossiping-bus-drivers.md +0 -186
  117. package/lib/assets/docs/article/functional-desgin-ppp/haskell/16-payroll-system.md +0 -228
  118. package/lib/assets/docs/article/functional-desgin-ppp/haskell/17-video-rental-system.md +0 -253
  119. package/lib/assets/docs/article/functional-desgin-ppp/haskell/18-concurrency-system.md +0 -372
  120. package/lib/assets/docs/article/functional-desgin-ppp/haskell/19-wator-simulation.md +0 -447
  121. package/lib/assets/docs/article/functional-desgin-ppp/haskell/20-pattern-interactions.md +0 -334
  122. package/lib/assets/docs/article/functional-desgin-ppp/haskell/21-best-practices.md +0 -412
  123. package/lib/assets/docs/article/functional-desgin-ppp/haskell/22-oo-to-fp-migration.md +0 -478
  124. package/lib/assets/docs/article/functional-desgin-ppp/haskell/index.md +0 -174
  125. package/lib/assets/docs/article/functional-desgin-ppp/index.md +0 -90
  126. package/lib/assets/docs/article/functional-desgin-ppp/rust/01-immutability-and-data-transformation.md +0 -459
  127. package/lib/assets/docs/article/functional-desgin-ppp/rust/02-function-composition.md +0 -472
  128. package/lib/assets/docs/article/functional-desgin-ppp/rust/03-polymorphism.md +0 -434
  129. package/lib/assets/docs/article/functional-desgin-ppp/rust/04-data-validation.md +0 -282
  130. package/lib/assets/docs/article/functional-desgin-ppp/rust/05-property-based-testing.md +0 -256
  131. package/lib/assets/docs/article/functional-desgin-ppp/rust/06-tdd-and-functional.md +0 -850
  132. package/lib/assets/docs/article/functional-desgin-ppp/rust/07-composite-pattern.md +0 -393
  133. package/lib/assets/docs/article/functional-desgin-ppp/rust/08-decorator-pattern.md +0 -392
  134. package/lib/assets/docs/article/functional-desgin-ppp/rust/09-adapter-pattern.md +0 -348
  135. package/lib/assets/docs/article/functional-desgin-ppp/rust/10-strategy-pattern.md +0 -340
  136. package/lib/assets/docs/article/functional-desgin-ppp/rust/11-command-pattern.md +0 -365
  137. package/lib/assets/docs/article/functional-desgin-ppp/rust/12-visitor-pattern.md +0 -388
  138. package/lib/assets/docs/article/functional-desgin-ppp/rust/13-abstract-factory-pattern.md +0 -370
  139. package/lib/assets/docs/article/functional-desgin-ppp/rust/14-abstract-server-pattern.md +0 -401
  140. package/lib/assets/docs/article/functional-desgin-ppp/rust/15-gossiping-bus-drivers.md +0 -309
  141. package/lib/assets/docs/article/functional-desgin-ppp/rust/16-payroll-system.md +0 -306
  142. package/lib/assets/docs/article/functional-desgin-ppp/rust/17-video-rental-system.md +0 -313
  143. package/lib/assets/docs/article/functional-desgin-ppp/rust/18-concurrency-system.md +0 -324
  144. package/lib/assets/docs/article/functional-desgin-ppp/rust/19-wator-simulation.md +0 -320
  145. package/lib/assets/docs/article/functional-desgin-ppp/rust/20-pattern-interactions.md +0 -313
  146. package/lib/assets/docs/article/functional-desgin-ppp/rust/21-best-practices.md +0 -345
  147. package/lib/assets/docs/article/functional-desgin-ppp/rust/22-oo-to-fp-migration.md +0 -358
  148. package/lib/assets/docs/article/functional-desgin-ppp/rust/index.md +0 -243
  149. package/lib/assets/docs/article/functional-desgin-ppp/scala/01-immutability-and-data-transformation.md +0 -337
  150. package/lib/assets/docs/article/functional-desgin-ppp/scala/02-function-composition.md +0 -357
  151. package/lib/assets/docs/article/functional-desgin-ppp/scala/03-polymorphism.md +0 -366
  152. package/lib/assets/docs/article/functional-desgin-ppp/scala/04-data-validation.md +0 -373
  153. package/lib/assets/docs/article/functional-desgin-ppp/scala/05-property-based-testing.md +0 -524
  154. package/lib/assets/docs/article/functional-desgin-ppp/scala/06-tdd-functional.md +0 -566
  155. package/lib/assets/docs/article/functional-desgin-ppp/scala/07-composite-pattern.md +0 -372
  156. package/lib/assets/docs/article/functional-desgin-ppp/scala/08-decorator-pattern.md +0 -336
  157. package/lib/assets/docs/article/functional-desgin-ppp/scala/09-adapter-pattern.md +0 -526
  158. package/lib/assets/docs/article/functional-desgin-ppp/scala/10-strategy-pattern.md +0 -450
  159. package/lib/assets/docs/article/functional-desgin-ppp/scala/11-command-pattern.md +0 -416
  160. package/lib/assets/docs/article/functional-desgin-ppp/scala/12-visitor-pattern.md +0 -388
  161. package/lib/assets/docs/article/functional-desgin-ppp/scala/13-abstract-factory-pattern.md +0 -407
  162. package/lib/assets/docs/article/functional-desgin-ppp/scala/14-abstract-server-pattern.md +0 -485
  163. package/lib/assets/docs/article/functional-desgin-ppp/scala/15-gossiping-bus-drivers.md +0 -400
  164. package/lib/assets/docs/article/functional-desgin-ppp/scala/16-payroll-system.md +0 -351
  165. package/lib/assets/docs/article/functional-desgin-ppp/scala/17-video-rental-system.md +0 -333
  166. package/lib/assets/docs/article/functional-desgin-ppp/scala/18-concurrency-system.md +0 -739
  167. package/lib/assets/docs/article/functional-desgin-ppp/scala/19-wator-simulation.md +0 -633
  168. package/lib/assets/docs/article/functional-desgin-ppp/scala/20-pattern-interactions.md +0 -521
  169. package/lib/assets/docs/article/functional-desgin-ppp/scala/21-best-practices.md +0 -442
  170. package/lib/assets/docs/article/functional-desgin-ppp/scala/22-oo-to-fp-migration.md +0 -697
  171. package/lib/assets/docs/article/functional-desgin-ppp/scala/index.md +0 -243
  172. package/lib/assets/docs/article/getting-start-docker-kubernetes/01-container-and-docker-basics.md +0 -341
  173. package/lib/assets/docs/article/getting-start-docker-kubernetes/02-container-deployment.md +0 -785
  174. package/lib/assets/docs/article/getting-start-docker-kubernetes/03-practical-container-build-deploy.md +0 -466
  175. package/lib/assets/docs/article/getting-start-docker-kubernetes/04-multi-container-application.md +0 -878
  176. package/lib/assets/docs/article/getting-start-docker-kubernetes/05-kubernetes-introduction.md +0 -585
  177. package/lib/assets/docs/article/getting-start-docker-kubernetes/06-kubernetes-deploy-cluster.md +0 -620
  178. package/lib/assets/docs/article/getting-start-docker-kubernetes/07-kubernetes-advanced.md +0 -621
  179. package/lib/assets/docs/article/getting-start-docker-kubernetes/08-kubernetes-packaging.md +0 -518
  180. package/lib/assets/docs/article/getting-start-docker-kubernetes/09-container-operations.md +0 -546
  181. package/lib/assets/docs/article/getting-start-docker-kubernetes/10-optimal-container-image.md +0 -640
  182. package/lib/assets/docs/article/getting-start-docker-kubernetes/11-continuous-delivery.md +0 -607
  183. package/lib/assets/docs/article/getting-start-docker-kubernetes/12-container-use-cases.md +0 -463
  184. package/lib/assets/docs/article/getting-start-docker-kubernetes/13-case-monolith-compose-vs-kustomize.md +0 -346
  185. package/lib/assets/docs/article/getting-start-docker-kubernetes/14-case-event-driven-kustomize-vs-helm.md +0 -324
  186. package/lib/assets/docs/article/getting-start-docker-kubernetes/15-case-escqrs-axon-kustomize-vs-helm.md +0 -297
  187. package/lib/assets/docs/article/getting-start-docker-kubernetes/16-case-escqrs-kafka-kustomize-vs-helm.md +0 -256
  188. package/lib/assets/docs/article/getting-start-docker-kubernetes/17-case-comparison-summary.md +0 -141
  189. package/lib/assets/docs/article/getting-start-docker-kubernetes/18-case-load-testing.md +0 -303
  190. package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-a-dev-tools-setup.md +0 -274
  191. package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-b-orchestration-environments.md +0 -530
  192. package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-c-tips.md +0 -519
  193. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-01-comic.png +0 -0
  194. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-02-comic.png +0 -0
  195. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-03-comic.png +0 -0
  196. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-04-comic.png +0 -0
  197. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-05-comic.png +0 -0
  198. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-06-comic.png +0 -0
  199. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-07-comic.png +0 -0
  200. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-08-comic.png +0 -0
  201. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-09-comic.png +0 -0
  202. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-10-comic.png +0 -0
  203. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-11-comic.png +0 -0
  204. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-12-comic.png +0 -0
  205. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/overview-comic.png +0 -0
  206. package/lib/assets/docs/article/getting-start-docker-kubernetes/index.md +0 -82
  207. package/lib/assets/docs/article/getting-start-docker-kubernetes/outline.md +0 -220
  208. package/lib/assets/docs/article/getting-start-tdd/clojure/01-todo-list-and-first-test.md +0 -175
  209. package/lib/assets/docs/article/getting-start-tdd/clojure/02-fake-it-and-triangulation.md +0 -171
  210. package/lib/assets/docs/article/getting-start-tdd/clojure/03-obvious-implementation-and-refactoring.md +0 -144
  211. package/lib/assets/docs/article/getting-start-tdd/clojure/04-version-control-and-conventional-commits.md +0 -97
  212. package/lib/assets/docs/article/getting-start-tdd/clojure/05-package-management-and-static-analysis.md +0 -308
  213. package/lib/assets/docs/article/getting-start-tdd/clojure/06-task-runner-and-ci-cd.md +0 -250
  214. package/lib/assets/docs/article/getting-start-tdd/clojure/07-protocols-and-records.md +0 -140
  215. package/lib/assets/docs/article/getting-start-tdd/clojure/08-multimethods-and-design-patterns.md +0 -139
  216. package/lib/assets/docs/article/getting-start-tdd/clojure/09-namespaces-and-module-design.md +0 -136
  217. package/lib/assets/docs/article/getting-start-tdd/clojure/10-higher-order-functions-and-composition.md +0 -123
  218. package/lib/assets/docs/article/getting-start-tdd/clojure/11-persistent-data-and-pipeline.md +0 -147
  219. package/lib/assets/docs/article/getting-start-tdd/clojure/12-error-handling-and-spec.md +0 -170
  220. package/lib/assets/docs/article/getting-start-tdd/clojure/index.md +0 -65
  221. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter01.md +0 -241
  222. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter02.md +0 -253
  223. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter03.md +0 -211
  224. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter04.md +0 -101
  225. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter05.md +0 -265
  226. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter06.md +0 -204
  227. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter07.md +0 -223
  228. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter08.md +0 -258
  229. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter09.md +0 -183
  230. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter10.md +0 -175
  231. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter11.md +0 -201
  232. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter12.md +0 -220
  233. package/lib/assets/docs/article/getting-start-tdd/csharp/index.md +0 -83
  234. package/lib/assets/docs/article/getting-start-tdd/elixir/01-todo-list-and-first-test.md +0 -96
  235. package/lib/assets/docs/article/getting-start-tdd/elixir/02-fake-it-and-triangulation.md +0 -104
  236. package/lib/assets/docs/article/getting-start-tdd/elixir/03-obvious-implementation-and-refactoring.md +0 -118
  237. package/lib/assets/docs/article/getting-start-tdd/elixir/04-version-control-and-conventional-commits.md +0 -105
  238. package/lib/assets/docs/article/getting-start-tdd/elixir/05-package-management-and-static-analysis.md +0 -97
  239. package/lib/assets/docs/article/getting-start-tdd/elixir/06-task-runner-and-ci-cd.md +0 -80
  240. package/lib/assets/docs/article/getting-start-tdd/elixir/07-structs-and-protocols.md +0 -119
  241. package/lib/assets/docs/article/getting-start-tdd/elixir/08-pattern-matching-and-guards.md +0 -117
  242. package/lib/assets/docs/article/getting-start-tdd/elixir/09-module-design-and-behaviours.md +0 -113
  243. package/lib/assets/docs/article/getting-start-tdd/elixir/10-higher-order-functions-and-pipeline.md +0 -187
  244. package/lib/assets/docs/article/getting-start-tdd/elixir/11-stream-and-lazy-evaluation.md +0 -151
  245. package/lib/assets/docs/article/getting-start-tdd/elixir/12-error-handling-and-with.md +0 -154
  246. package/lib/assets/docs/article/getting-start-tdd/elixir/index.md +0 -35
  247. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter01.md +0 -211
  248. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter02.md +0 -255
  249. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter03.md +0 -227
  250. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter04.md +0 -188
  251. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter05.md +0 -276
  252. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter06.md +0 -199
  253. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter07.md +0 -170
  254. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter08.md +0 -184
  255. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter09.md +0 -231
  256. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter10.md +0 -198
  257. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter11.md +0 -221
  258. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter12.md +0 -224
  259. package/lib/assets/docs/article/getting-start-tdd/fsharp/index.md +0 -71
  260. package/lib/assets/docs/article/getting-start-tdd/go/01-todo-list-and-first-test.md +0 -222
  261. package/lib/assets/docs/article/getting-start-tdd/go/02-fake-it-and-triangulation.md +0 -311
  262. package/lib/assets/docs/article/getting-start-tdd/go/03-obvious-implementation-and-refactoring.md +0 -348
  263. package/lib/assets/docs/article/getting-start-tdd/go/04-version-control-and-conventional-commits.md +0 -121
  264. package/lib/assets/docs/article/getting-start-tdd/go/05-package-management-and-static-analysis.md +0 -281
  265. package/lib/assets/docs/article/getting-start-tdd/go/06-task-runner-and-ci-cd.md +0 -242
  266. package/lib/assets/docs/article/getting-start-tdd/go/07-encapsulation-and-polymorphism.md +0 -402
  267. package/lib/assets/docs/article/getting-start-tdd/go/08-design-patterns.md +0 -430
  268. package/lib/assets/docs/article/getting-start-tdd/go/09-solid-principles-and-module-design.md +0 -408
  269. package/lib/assets/docs/article/getting-start-tdd/go/10-higher-order-functions-and-composition.md +0 -234
  270. package/lib/assets/docs/article/getting-start-tdd/go/11-immutable-data-and-pipeline.md +0 -304
  271. package/lib/assets/docs/article/getting-start-tdd/go/12-error-handling-and-type-safety.md +0 -419
  272. package/lib/assets/docs/article/getting-start-tdd/go/index.md +0 -83
  273. package/lib/assets/docs/article/getting-start-tdd/haskell/01-todo-list-and-first-test.md +0 -288
  274. package/lib/assets/docs/article/getting-start-tdd/haskell/02-fake-it-and-triangulation.md +0 -346
  275. package/lib/assets/docs/article/getting-start-tdd/haskell/03-obvious-implementation-and-refactoring.md +0 -266
  276. package/lib/assets/docs/article/getting-start-tdd/haskell/04-version-control-and-conventional-commits.md +0 -191
  277. package/lib/assets/docs/article/getting-start-tdd/haskell/05-package-management-and-static-analysis.md +0 -322
  278. package/lib/assets/docs/article/getting-start-tdd/haskell/06-task-runner-and-ci-cd.md +0 -318
  279. package/lib/assets/docs/article/getting-start-tdd/haskell/07-algebraic-data-types-and-type-classes.md +0 -421
  280. package/lib/assets/docs/article/getting-start-tdd/haskell/08-pattern-matching-and-guards.md +0 -399
  281. package/lib/assets/docs/article/getting-start-tdd/haskell/09-module-design-and-smart-constructors.md +0 -470
  282. package/lib/assets/docs/article/getting-start-tdd/haskell/10-higher-order-functions-and-currying.md +0 -443
  283. package/lib/assets/docs/article/getting-start-tdd/haskell/11-function-composition-and-point-free.md +0 -401
  284. package/lib/assets/docs/article/getting-start-tdd/haskell/12-monad-and-error-handling.md +0 -640
  285. package/lib/assets/docs/article/getting-start-tdd/haskell/index.md +0 -49
  286. package/lib/assets/docs/article/getting-start-tdd/index.md +0 -93
  287. package/lib/assets/docs/article/getting-start-tdd/integration/01-language-overview.md +0 -384
  288. package/lib/assets/docs/article/getting-start-tdd/integration/02-test-framework-comparison.md +0 -358
  289. package/lib/assets/docs/article/getting-start-tdd/integration/03-tdd-pattern-comparison.md +0 -454
  290. package/lib/assets/docs/article/getting-start-tdd/integration/04-type-system-comparison.md +0 -418
  291. package/lib/assets/docs/article/getting-start-tdd/integration/05-dev-environment-comparison.md +0 -339
  292. package/lib/assets/docs/article/getting-start-tdd/integration/06-learning-roadmap.md +0 -299
  293. package/lib/assets/docs/article/getting-start-tdd/integration/index.md +0 -69
  294. package/lib/assets/docs/article/getting-start-tdd/java/01-todo-list-and-first-test.md +0 -243
  295. package/lib/assets/docs/article/getting-start-tdd/java/02-fake-it-and-triangulation.md +0 -270
  296. package/lib/assets/docs/article/getting-start-tdd/java/03-obvious-implementation-and-refactoring.md +0 -194
  297. package/lib/assets/docs/article/getting-start-tdd/java/04-version-control-and-conventional-commits.md +0 -124
  298. package/lib/assets/docs/article/getting-start-tdd/java/05-package-management-and-static-analysis.md +0 -391
  299. package/lib/assets/docs/article/getting-start-tdd/java/06-task-runner-and-ci-cd.md +0 -281
  300. package/lib/assets/docs/article/getting-start-tdd/java/07-encapsulation-and-polymorphism.md +0 -635
  301. package/lib/assets/docs/article/getting-start-tdd/java/08-design-patterns.md +0 -402
  302. package/lib/assets/docs/article/getting-start-tdd/java/09-solid-principles-and-module-design.md +0 -319
  303. package/lib/assets/docs/article/getting-start-tdd/java/10-higher-order-functions-and-composition.md +0 -197
  304. package/lib/assets/docs/article/getting-start-tdd/java/11-immutable-data-and-pipeline.md +0 -176
  305. package/lib/assets/docs/article/getting-start-tdd/java/12-error-handling-and-type-safety.md +0 -214
  306. package/lib/assets/docs/article/getting-start-tdd/java/index.md +0 -61
  307. package/lib/assets/docs/article/getting-start-tdd/node/01-todo-list-and-first-test.md +0 -253
  308. package/lib/assets/docs/article/getting-start-tdd/node/02-fake-it-and-triangulation.md +0 -271
  309. package/lib/assets/docs/article/getting-start-tdd/node/03-obvious-implementation-and-refactoring.md +0 -178
  310. package/lib/assets/docs/article/getting-start-tdd/node/04-version-control-and-conventional-commits.md +0 -121
  311. package/lib/assets/docs/article/getting-start-tdd/node/05-package-management-and-static-analysis.md +0 -323
  312. package/lib/assets/docs/article/getting-start-tdd/node/06-task-runner-and-ci-cd.md +0 -244
  313. package/lib/assets/docs/article/getting-start-tdd/node/07-encapsulation-and-polymorphism.md +0 -336
  314. package/lib/assets/docs/article/getting-start-tdd/node/08-design-patterns.md +0 -331
  315. package/lib/assets/docs/article/getting-start-tdd/node/09-solid-principles-and-module-design.md +0 -294
  316. package/lib/assets/docs/article/getting-start-tdd/node/10-higher-order-functions-and-composition.md +0 -208
  317. package/lib/assets/docs/article/getting-start-tdd/node/11-immutable-data-and-pipeline.md +0 -216
  318. package/lib/assets/docs/article/getting-start-tdd/node/12-error-handling-and-type-safety.md +0 -304
  319. package/lib/assets/docs/article/getting-start-tdd/node/index.md +0 -56
  320. package/lib/assets/docs/article/getting-start-tdd/php/01-todo-list-and-first-test.md +0 -268
  321. package/lib/assets/docs/article/getting-start-tdd/php/02-fake-it-and-triangulation.md +0 -209
  322. package/lib/assets/docs/article/getting-start-tdd/php/03-obvious-implementation-and-refactoring.md +0 -257
  323. package/lib/assets/docs/article/getting-start-tdd/php/04-version-control-and-conventional-commits.md +0 -150
  324. package/lib/assets/docs/article/getting-start-tdd/php/05-package-management-and-static-analysis.md +0 -419
  325. package/lib/assets/docs/article/getting-start-tdd/php/06-task-runner-and-ci-cd.md +0 -330
  326. package/lib/assets/docs/article/getting-start-tdd/php/07-encapsulation-and-polymorphism.md +0 -380
  327. package/lib/assets/docs/article/getting-start-tdd/php/08-design-patterns.md +0 -461
  328. package/lib/assets/docs/article/getting-start-tdd/php/09-solid-principles-and-module-design.md +0 -468
  329. package/lib/assets/docs/article/getting-start-tdd/php/10-higher-order-functions-and-composition.md +0 -190
  330. package/lib/assets/docs/article/getting-start-tdd/php/11-immutable-data-and-pipeline.md +0 -274
  331. package/lib/assets/docs/article/getting-start-tdd/php/12-error-handling-and-type-safety.md +0 -316
  332. package/lib/assets/docs/article/getting-start-tdd/php/index.md +0 -84
  333. package/lib/assets/docs/article/getting-start-tdd/python/01-todo-list-and-first-test.md +0 -210
  334. package/lib/assets/docs/article/getting-start-tdd/python/02-fake-it-and-triangulation.md +0 -256
  335. package/lib/assets/docs/article/getting-start-tdd/python/03-obvious-implementation-and-refactoring.md +0 -208
  336. package/lib/assets/docs/article/getting-start-tdd/python/04-version-control-and-conventional-commits.md +0 -96
  337. package/lib/assets/docs/article/getting-start-tdd/python/05-package-management-and-static-analysis.md +0 -283
  338. package/lib/assets/docs/article/getting-start-tdd/python/06-task-runner-and-ci-cd.md +0 -199
  339. package/lib/assets/docs/article/getting-start-tdd/python/07-encapsulation-and-polymorphism.md +0 -217
  340. package/lib/assets/docs/article/getting-start-tdd/python/08-design-patterns.md +0 -181
  341. package/lib/assets/docs/article/getting-start-tdd/python/09-solid-principles-and-module-design.md +0 -139
  342. package/lib/assets/docs/article/getting-start-tdd/python/10-higher-order-functions-and-composition.md +0 -131
  343. package/lib/assets/docs/article/getting-start-tdd/python/11-immutable-data-and-pipeline.md +0 -125
  344. package/lib/assets/docs/article/getting-start-tdd/python/12-error-handling-and-type-safety.md +0 -135
  345. package/lib/assets/docs/article/getting-start-tdd/python/index.md +0 -55
  346. package/lib/assets/docs/article/getting-start-tdd/ruby/01-todo-list-and-first-test.md +0 -240
  347. package/lib/assets/docs/article/getting-start-tdd/ruby/02-fake-it-and-triangulation.md +0 -247
  348. package/lib/assets/docs/article/getting-start-tdd/ruby/03-obvious-implementation-and-refactoring.md +0 -237
  349. package/lib/assets/docs/article/getting-start-tdd/ruby/04-version-control-and-conventional-commits.md +0 -121
  350. package/lib/assets/docs/article/getting-start-tdd/ruby/05-package-management-and-static-analysis.md +0 -296
  351. package/lib/assets/docs/article/getting-start-tdd/ruby/06-task-runner-and-ci-cd.md +0 -257
  352. package/lib/assets/docs/article/getting-start-tdd/ruby/07-encapsulation-and-polymorphism.md +0 -288
  353. package/lib/assets/docs/article/getting-start-tdd/ruby/08-design-patterns.md +0 -338
  354. package/lib/assets/docs/article/getting-start-tdd/ruby/09-solid-principles-and-module-design.md +0 -205
  355. package/lib/assets/docs/article/getting-start-tdd/ruby/10-higher-order-functions-and-composition.md +0 -184
  356. package/lib/assets/docs/article/getting-start-tdd/ruby/11-immutable-data-and-pipeline.md +0 -246
  357. package/lib/assets/docs/article/getting-start-tdd/ruby/12-error-handling-and-type-safety.md +0 -407
  358. package/lib/assets/docs/article/getting-start-tdd/ruby/index.md +0 -83
  359. package/lib/assets/docs/article/getting-start-tdd/rust/01-todo-list-and-first-test.md +0 -220
  360. package/lib/assets/docs/article/getting-start-tdd/rust/02-fake-it-and-triangulation.md +0 -273
  361. package/lib/assets/docs/article/getting-start-tdd/rust/03-obvious-implementation-and-refactoring.md +0 -242
  362. package/lib/assets/docs/article/getting-start-tdd/rust/04-version-control-and-conventional-commits.md +0 -101
  363. package/lib/assets/docs/article/getting-start-tdd/rust/05-package-management-and-static-analysis.md +0 -221
  364. package/lib/assets/docs/article/getting-start-tdd/rust/06-task-runner-and-ci-cd.md +0 -173
  365. package/lib/assets/docs/article/getting-start-tdd/rust/07-encapsulation-and-polymorphism.md +0 -151
  366. package/lib/assets/docs/article/getting-start-tdd/rust/08-design-patterns.md +0 -154
  367. package/lib/assets/docs/article/getting-start-tdd/rust/09-solid-principles-and-module-design.md +0 -119
  368. package/lib/assets/docs/article/getting-start-tdd/rust/10-higher-order-functions-and-composition.md +0 -103
  369. package/lib/assets/docs/article/getting-start-tdd/rust/11-immutable-data-and-pipeline.md +0 -114
  370. package/lib/assets/docs/article/getting-start-tdd/rust/12-error-handling-and-type-safety.md +0 -121
  371. package/lib/assets/docs/article/getting-start-tdd/rust/index.md +0 -83
  372. package/lib/assets/docs/article/getting-start-tdd/scala/01-todo-list-and-first-test.md +0 -120
  373. package/lib/assets/docs/article/getting-start-tdd/scala/02-fake-it-and-triangulation.md +0 -116
  374. package/lib/assets/docs/article/getting-start-tdd/scala/03-obvious-implementation-and-refactoring.md +0 -108
  375. package/lib/assets/docs/article/getting-start-tdd/scala/04-version-control-and-conventional-commits.md +0 -132
  376. package/lib/assets/docs/article/getting-start-tdd/scala/05-package-management-and-static-analysis.md +0 -205
  377. package/lib/assets/docs/article/getting-start-tdd/scala/06-task-runner-and-ci-cd.md +0 -195
  378. package/lib/assets/docs/article/getting-start-tdd/scala/07-case-classes-and-traits.md +0 -148
  379. package/lib/assets/docs/article/getting-start-tdd/scala/08-pattern-matching-and-sealed-traits.md +0 -115
  380. package/lib/assets/docs/article/getting-start-tdd/scala/09-packages-and-module-design.md +0 -84
  381. package/lib/assets/docs/article/getting-start-tdd/scala/10-higher-order-functions-and-composition.md +0 -113
  382. package/lib/assets/docs/article/getting-start-tdd/scala/11-collections-and-lazy-evaluation.md +0 -103
  383. package/lib/assets/docs/article/getting-start-tdd/scala/12-error-handling-and-type-safety.md +0 -101
  384. package/lib/assets/docs/article/getting-start-tdd/scala/index.md +0 -65
  385. package/lib/assets/docs/article/grokking-concurrency/all/index.md +0 -403
  386. package/lib/assets/docs/article/grokking-concurrency/all/part-1-ch02-sequential.md +0 -563
  387. package/lib/assets/docs/article/grokking-concurrency/all/part-2-ch04-05-threads.md +0 -478
  388. package/lib/assets/docs/article/grokking-concurrency/all/part-3-ch06-multitasking.md +0 -529
  389. package/lib/assets/docs/article/grokking-concurrency/all/part-4-ch07-parallel-patterns.md +0 -429
  390. package/lib/assets/docs/article/grokking-concurrency/all/part-5-ch08-09-synchronization.md +0 -519
  391. package/lib/assets/docs/article/grokking-concurrency/all/part-6-ch10-11-nonblocking-io.md +0 -444
  392. package/lib/assets/docs/article/grokking-concurrency/all/part-7-ch12-async.md +0 -474
  393. package/lib/assets/docs/article/grokking-concurrency/all/part-8-ch13-mapreduce.md +0 -386
  394. package/lib/assets/docs/article/grokking-concurrency/clojure/index.md +0 -106
  395. package/lib/assets/docs/article/grokking-concurrency/clojure/part-1.md +0 -107
  396. package/lib/assets/docs/article/grokking-concurrency/clojure/part-2.md +0 -100
  397. package/lib/assets/docs/article/grokking-concurrency/clojure/part-3.md +0 -121
  398. package/lib/assets/docs/article/grokking-concurrency/clojure/part-4.md +0 -122
  399. package/lib/assets/docs/article/grokking-concurrency/clojure/part-5.md +0 -117
  400. package/lib/assets/docs/article/grokking-concurrency/clojure/part-6.md +0 -88
  401. package/lib/assets/docs/article/grokking-concurrency/clojure/part-7.md +0 -99
  402. package/lib/assets/docs/article/grokking-concurrency/clojure/part-8.md +0 -119
  403. package/lib/assets/docs/article/grokking-concurrency/csharp/index.md +0 -91
  404. package/lib/assets/docs/article/grokking-concurrency/csharp/part-1.md +0 -96
  405. package/lib/assets/docs/article/grokking-concurrency/csharp/part-2.md +0 -122
  406. package/lib/assets/docs/article/grokking-concurrency/csharp/part-3.md +0 -100
  407. package/lib/assets/docs/article/grokking-concurrency/csharp/part-4.md +0 -111
  408. package/lib/assets/docs/article/grokking-concurrency/csharp/part-5.md +0 -98
  409. package/lib/assets/docs/article/grokking-concurrency/csharp/part-6.md +0 -60
  410. package/lib/assets/docs/article/grokking-concurrency/csharp/part-7.md +0 -83
  411. package/lib/assets/docs/article/grokking-concurrency/csharp/part-8.md +0 -91
  412. package/lib/assets/docs/article/grokking-concurrency/fsharp/index.md +0 -55
  413. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-1.md +0 -79
  414. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-2.md +0 -102
  415. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-3.md +0 -93
  416. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-4.md +0 -109
  417. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-5.md +0 -103
  418. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-6.md +0 -92
  419. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-7.md +0 -120
  420. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-8.md +0 -106
  421. package/lib/assets/docs/article/grokking-concurrency/haskell/index.md +0 -238
  422. package/lib/assets/docs/article/grokking-concurrency/haskell/part-1.md +0 -95
  423. package/lib/assets/docs/article/grokking-concurrency/haskell/part-2.md +0 -95
  424. package/lib/assets/docs/article/grokking-concurrency/haskell/part-3.md +0 -90
  425. package/lib/assets/docs/article/grokking-concurrency/haskell/part-4.md +0 -105
  426. package/lib/assets/docs/article/grokking-concurrency/haskell/part-5.md +0 -98
  427. package/lib/assets/docs/article/grokking-concurrency/haskell/part-6.md +0 -94
  428. package/lib/assets/docs/article/grokking-concurrency/haskell/part-7.md +0 -110
  429. package/lib/assets/docs/article/grokking-concurrency/haskell/part-8.md +0 -117
  430. package/lib/assets/docs/article/grokking-concurrency/index.md +0 -66
  431. package/lib/assets/docs/article/grokking-concurrency/java/index.md +0 -92
  432. package/lib/assets/docs/article/grokking-concurrency/java/part-1.md +0 -307
  433. package/lib/assets/docs/article/grokking-concurrency/java/part-2.md +0 -333
  434. package/lib/assets/docs/article/grokking-concurrency/java/part-3.md +0 -220
  435. package/lib/assets/docs/article/grokking-concurrency/java/part-4.md +0 -212
  436. package/lib/assets/docs/article/grokking-concurrency/java/part-5.md +0 -111
  437. package/lib/assets/docs/article/grokking-concurrency/java/part-6.md +0 -68
  438. package/lib/assets/docs/article/grokking-concurrency/java/part-7.md +0 -100
  439. package/lib/assets/docs/article/grokking-concurrency/java/part-8.md +0 -100
  440. package/lib/assets/docs/article/grokking-concurrency/python/index.md +0 -303
  441. package/lib/assets/docs/article/grokking-concurrency/python/part-1.md +0 -238
  442. package/lib/assets/docs/article/grokking-concurrency/python/part-2.md +0 -417
  443. package/lib/assets/docs/article/grokking-concurrency/python/part-3.md +0 -226
  444. package/lib/assets/docs/article/grokking-concurrency/python/part-4.md +0 -298
  445. package/lib/assets/docs/article/grokking-concurrency/python/part-5.md +0 -314
  446. package/lib/assets/docs/article/grokking-concurrency/python/part-6.md +0 -296
  447. package/lib/assets/docs/article/grokking-concurrency/python/part-7.md +0 -313
  448. package/lib/assets/docs/article/grokking-concurrency/python/part-8.md +0 -359
  449. package/lib/assets/docs/article/grokking-concurrency/rust/index.md +0 -260
  450. package/lib/assets/docs/article/grokking-concurrency/rust/part-1.md +0 -107
  451. package/lib/assets/docs/article/grokking-concurrency/rust/part-2.md +0 -119
  452. package/lib/assets/docs/article/grokking-concurrency/rust/part-3.md +0 -125
  453. package/lib/assets/docs/article/grokking-concurrency/rust/part-4.md +0 -174
  454. package/lib/assets/docs/article/grokking-concurrency/rust/part-5.md +0 -157
  455. package/lib/assets/docs/article/grokking-concurrency/rust/part-6.md +0 -93
  456. package/lib/assets/docs/article/grokking-concurrency/rust/part-7.md +0 -132
  457. package/lib/assets/docs/article/grokking-concurrency/rust/part-8.md +0 -154
  458. package/lib/assets/docs/article/grokking-concurrency/scala/index.md +0 -59
  459. package/lib/assets/docs/article/grokking-concurrency/scala/part-1.md +0 -77
  460. package/lib/assets/docs/article/grokking-concurrency/scala/part-2.md +0 -111
  461. package/lib/assets/docs/article/grokking-concurrency/scala/part-3.md +0 -92
  462. package/lib/assets/docs/article/grokking-concurrency/scala/part-4.md +0 -109
  463. package/lib/assets/docs/article/grokking-concurrency/scala/part-5.md +0 -118
  464. package/lib/assets/docs/article/grokking-concurrency/scala/part-6.md +0 -82
  465. package/lib/assets/docs/article/grokking-concurrency/scala/part-7.md +0 -130
  466. package/lib/assets/docs/article/grokking-concurrency/scala/part-8.md +0 -128
  467. package/lib/assets/docs/article/grokkingfp/all/index.md +0 -368
  468. package/lib/assets/docs/article/grokkingfp/all/part-1-ch01-fp-introduction.md +0 -539
  469. package/lib/assets/docs/article/grokkingfp/all/part-1-ch02-pure-functions.md +0 -932
  470. package/lib/assets/docs/article/grokkingfp/all/part-2-ch03-immutable-data.md +0 -1137
  471. package/lib/assets/docs/article/grokkingfp/all/part-2-ch04-higher-order-functions.md +0 -1113
  472. package/lib/assets/docs/article/grokkingfp/all/part-2-ch05-flatmap.md +0 -1035
  473. package/lib/assets/docs/article/grokkingfp/all/part-3-ch06-option.md +0 -794
  474. package/lib/assets/docs/article/grokkingfp/all/part-3-ch07-either-adt.md +0 -880
  475. package/lib/assets/docs/article/grokkingfp/all/part-4-ch08-io-monad.md +0 -981
  476. package/lib/assets/docs/article/grokkingfp/all/part-4-ch09-streams.md +0 -935
  477. package/lib/assets/docs/article/grokkingfp/all/part-5-ch10-concurrency.md +0 -879
  478. package/lib/assets/docs/article/grokkingfp/all/part-6-ch11-application.md +0 -724
  479. package/lib/assets/docs/article/grokkingfp/all/part-6-ch12-testing.md +0 -635
  480. package/lib/assets/docs/article/grokkingfp/all/writing-plan.md +0 -721
  481. package/lib/assets/docs/article/grokkingfp/clojure/index.md +0 -276
  482. package/lib/assets/docs/article/grokkingfp/clojure/part-1.md +0 -676
  483. package/lib/assets/docs/article/grokkingfp/clojure/part-2.md +0 -652
  484. package/lib/assets/docs/article/grokkingfp/clojure/part-3.md +0 -629
  485. package/lib/assets/docs/article/grokkingfp/clojure/part-4.md +0 -706
  486. package/lib/assets/docs/article/grokkingfp/clojure/part-5.md +0 -760
  487. package/lib/assets/docs/article/grokkingfp/clojure/part-6.md +0 -730
  488. package/lib/assets/docs/article/grokkingfp/csharp/index.md +0 -246
  489. package/lib/assets/docs/article/grokkingfp/csharp/part-1.md +0 -820
  490. package/lib/assets/docs/article/grokkingfp/csharp/part-2.md +0 -980
  491. package/lib/assets/docs/article/grokkingfp/csharp/part-3.md +0 -990
  492. package/lib/assets/docs/article/grokkingfp/csharp/part-4.md +0 -958
  493. package/lib/assets/docs/article/grokkingfp/csharp/part-5.md +0 -956
  494. package/lib/assets/docs/article/grokkingfp/csharp/part-6.md +0 -748
  495. package/lib/assets/docs/article/grokkingfp/elixir/index.md +0 -203
  496. package/lib/assets/docs/article/grokkingfp/elixir/part-1.md +0 -721
  497. package/lib/assets/docs/article/grokkingfp/elixir/part-2.md +0 -847
  498. package/lib/assets/docs/article/grokkingfp/elixir/part-3.md +0 -994
  499. package/lib/assets/docs/article/grokkingfp/elixir/part-4.md +0 -983
  500. package/lib/assets/docs/article/grokkingfp/elixir/part-5.md +0 -1295
  501. package/lib/assets/docs/article/grokkingfp/elixir/part-6.md +0 -1058
  502. package/lib/assets/docs/article/grokkingfp/fsharp/index.md +0 -210
  503. package/lib/assets/docs/article/grokkingfp/fsharp/part-1.md +0 -723
  504. package/lib/assets/docs/article/grokkingfp/fsharp/part-2.md +0 -970
  505. package/lib/assets/docs/article/grokkingfp/fsharp/part-3.md +0 -981
  506. package/lib/assets/docs/article/grokkingfp/fsharp/part-4.md +0 -841
  507. package/lib/assets/docs/article/grokkingfp/fsharp/part-5.md +0 -920
  508. package/lib/assets/docs/article/grokkingfp/fsharp/part-6.md +0 -931
  509. package/lib/assets/docs/article/grokkingfp/haskell/index.md +0 -234
  510. package/lib/assets/docs/article/grokkingfp/haskell/part-1.md +0 -600
  511. package/lib/assets/docs/article/grokkingfp/haskell/part-2.md +0 -875
  512. package/lib/assets/docs/article/grokkingfp/haskell/part-3.md +0 -924
  513. package/lib/assets/docs/article/grokkingfp/haskell/part-4.md +0 -887
  514. package/lib/assets/docs/article/grokkingfp/haskell/part-5.md +0 -854
  515. package/lib/assets/docs/article/grokkingfp/haskell/part-6.md +0 -853
  516. package/lib/assets/docs/article/grokkingfp/index.md +0 -143
  517. package/lib/assets/docs/article/grokkingfp/java/index.md +0 -211
  518. package/lib/assets/docs/article/grokkingfp/java/part-1.md +0 -657
  519. package/lib/assets/docs/article/grokkingfp/java/part-2.md +0 -684
  520. package/lib/assets/docs/article/grokkingfp/java/part-3.md +0 -681
  521. package/lib/assets/docs/article/grokkingfp/java/part-4.md +0 -780
  522. package/lib/assets/docs/article/grokkingfp/java/part-5.md +0 -968
  523. package/lib/assets/docs/article/grokkingfp/java/part-6.md +0 -1337
  524. package/lib/assets/docs/article/grokkingfp/python/index.md +0 -258
  525. package/lib/assets/docs/article/grokkingfp/python/part-1.md +0 -452
  526. package/lib/assets/docs/article/grokkingfp/python/part-2.md +0 -967
  527. package/lib/assets/docs/article/grokkingfp/python/part-3.md +0 -1013
  528. package/lib/assets/docs/article/grokkingfp/python/part-4.md +0 -774
  529. package/lib/assets/docs/article/grokkingfp/python/part-5.md +0 -756
  530. package/lib/assets/docs/article/grokkingfp/python/part-6.md +0 -870
  531. package/lib/assets/docs/article/grokkingfp/ruby/index.md +0 -330
  532. package/lib/assets/docs/article/grokkingfp/ruby/part-1.md +0 -764
  533. package/lib/assets/docs/article/grokkingfp/ruby/part-2.md +0 -947
  534. package/lib/assets/docs/article/grokkingfp/ruby/part-3.md +0 -955
  535. package/lib/assets/docs/article/grokkingfp/ruby/part-4.md +0 -930
  536. package/lib/assets/docs/article/grokkingfp/ruby/part-5.md +0 -917
  537. package/lib/assets/docs/article/grokkingfp/ruby/part-6.md +0 -1421
  538. package/lib/assets/docs/article/grokkingfp/rust/index.md +0 -242
  539. package/lib/assets/docs/article/grokkingfp/rust/part-1.md +0 -643
  540. package/lib/assets/docs/article/grokkingfp/rust/part-2.md +0 -1069
  541. package/lib/assets/docs/article/grokkingfp/rust/part-3.md +0 -1003
  542. package/lib/assets/docs/article/grokkingfp/rust/part-4.md +0 -582
  543. package/lib/assets/docs/article/grokkingfp/rust/part-5.md +0 -714
  544. package/lib/assets/docs/article/grokkingfp/rust/part-6.md +0 -517
  545. package/lib/assets/docs/article/grokkingfp/scala/index.md +0 -171
  546. package/lib/assets/docs/article/grokkingfp/scala/part-1.md +0 -552
  547. package/lib/assets/docs/article/grokkingfp/scala/part-2.md +0 -955
  548. package/lib/assets/docs/article/grokkingfp/scala/part-3.md +0 -928
  549. package/lib/assets/docs/article/grokkingfp/scala/part-4.md +0 -751
  550. package/lib/assets/docs/article/grokkingfp/scala/part-5.md +0 -731
  551. package/lib/assets/docs/article/grokkingfp/scala/part-6.md +0 -876
  552. package/lib/assets/docs/article/grokkingfp/typescript/index.md +0 -273
  553. package/lib/assets/docs/article/grokkingfp/typescript/part-1.md +0 -570
  554. package/lib/assets/docs/article/grokkingfp/typescript/part-2.md +0 -1138
  555. package/lib/assets/docs/article/grokkingfp/typescript/part-3.md +0 -851
  556. package/lib/assets/docs/article/grokkingfp/typescript/part-4.md +0 -1096
  557. package/lib/assets/docs/article/grokkingfp/typescript/part-5.md +0 -726
  558. package/lib/assets/docs/article/grokkingfp/typescript/part-6.md +0 -991
  559. package/lib/assets/docs/article/practical-database-design/index.md +0 -121
  560. package/lib/assets/docs/article/practical-database-design/part1/chapter01.md +0 -297
  561. package/lib/assets/docs/article/practical-database-design/part1/chapter02.md +0 -527
  562. package/lib/assets/docs/article/practical-database-design/part1/chapter03.md +0 -566
  563. package/lib/assets/docs/article/practical-database-design/part2/chapter04.md +0 -933
  564. package/lib/assets/docs/article/practical-database-design/part2/chapter05.md +0 -1636
  565. package/lib/assets/docs/article/practical-database-design/part2/chapter06.md +0 -2725
  566. package/lib/assets/docs/article/practical-database-design/part2/chapter07.md +0 -2091
  567. package/lib/assets/docs/article/practical-database-design/part2/chapter08.md +0 -2114
  568. package/lib/assets/docs/article/practical-database-design/part2/chapter09.md +0 -2040
  569. package/lib/assets/docs/article/practical-database-design/part2/chapter10.md +0 -1396
  570. package/lib/assets/docs/article/practical-database-design/part2/chapter11.md +0 -1686
  571. package/lib/assets/docs/article/practical-database-design/part2/chapter12.md +0 -1426
  572. package/lib/assets/docs/article/practical-database-design/part2/chapter13.md +0 -1443
  573. package/lib/assets/docs/article/practical-database-design/part3/chapter14.md +0 -676
  574. package/lib/assets/docs/article/practical-database-design/part3/chapter15.md +0 -1634
  575. package/lib/assets/docs/article/practical-database-design/part3/chapter16.md +0 -1924
  576. package/lib/assets/docs/article/practical-database-design/part3/chapter17.md +0 -1717
  577. package/lib/assets/docs/article/practical-database-design/part3/chapter18.md +0 -2104
  578. package/lib/assets/docs/article/practical-database-design/part3/chapter19.md +0 -1132
  579. package/lib/assets/docs/article/practical-database-design/part3/chapter20.md +0 -1040
  580. package/lib/assets/docs/article/practical-database-design/part3/chapter21.md +0 -1391
  581. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter14-orm.md +0 -1000
  582. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter15-orm.md +0 -1309
  583. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter16-orm.md +0 -1175
  584. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter17-orm.md +0 -1593
  585. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter18-orm.md +0 -1192
  586. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter19-orm.md +0 -1025
  587. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter20-orm.md +0 -1762
  588. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter21-orm.md +0 -1456
  589. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter22-orm.md +0 -1887
  590. package/lib/assets/docs/article/practical-database-design/part4/chapter22.md +0 -974
  591. package/lib/assets/docs/article/practical-database-design/part4/chapter23.md +0 -2078
  592. package/lib/assets/docs/article/practical-database-design/part4/chapter24.md +0 -2448
  593. package/lib/assets/docs/article/practical-database-design/part4/chapter25.md +0 -3670
  594. package/lib/assets/docs/article/practical-database-design/part4/chapter26.md +0 -2925
  595. package/lib/assets/docs/article/practical-database-design/part4/chapter27.md +0 -3114
  596. package/lib/assets/docs/article/practical-database-design/part4/chapter28.md +0 -2706
  597. package/lib/assets/docs/article/practical-database-design/part4/chapter29.md +0 -2552
  598. package/lib/assets/docs/article/practical-database-design/part4/chapter30.md +0 -2188
  599. package/lib/assets/docs/article/practical-database-design/part4/chapter31.md +0 -1200
  600. package/lib/assets/docs/article/practical-database-design/part4/chapter32.md +0 -2109
  601. package/lib/assets/docs/article/practical-database-design/part5/chapter33.md +0 -1041
  602. package/lib/assets/docs/article/practical-database-design/part5/chapter34.md +0 -1618
  603. package/lib/assets/docs/article/practical-database-design/part5/chapter35.md +0 -1462
  604. package/lib/assets/docs/article/practical-database-design/part5/chapter36.md +0 -1301
  605. package/lib/assets/docs/article/practical-database-design/part5/chapter37.md +0 -1479
  606. package/lib/assets/docs/article/practical-database-design/part5/chapter38.md +0 -1707
  607. package/lib/assets/docs/article/practical-database-design/part5/chapter39.md +0 -2343
  608. package/lib/assets/docs/article/practical-database-design/study/study2-1.md +0 -1702
  609. package/lib/assets/docs/article/practical-database-design/study/study2-2.md +0 -1356
  610. package/lib/assets/docs/article/practical-database-design/study/study2-3.md +0 -2053
  611. package/lib/assets/docs/article/practical-database-design/study/study2-4.md +0 -2238
  612. package/lib/assets/docs/article/practical-database-design/study/study2-5.md +0 -2427
  613. package/lib/assets/docs/article/practical-database-design/study/study3-1.md +0 -2214
  614. package/lib/assets/docs/article/practical-database-design/study/study3-2.md +0 -2230
  615. package/lib/assets/docs/article/practical-database-design/study/study3-3.md +0 -2262
  616. package/lib/assets/docs/article/practical-database-design/study/study3-4.md +0 -2115
  617. package/lib/assets/docs/article/practical-database-design/study/study3-5.md +0 -2516
  618. package/lib/assets/docs/article/practical-database-design/study/study4-1.md +0 -2596
  619. package/lib/assets/docs/article/practical-database-design/study/study4-2.md +0 -2084
  620. package/lib/assets/docs/article/practical-database-design/study/study4-3.md +0 -1814
  621. package/lib/assets/docs/article/practical-database-design/study/study4-4.md +0 -1904
  622. 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章では、データ連携の実装パターンについて解説します。バッチ連携、リアルタイム連携、連携テーブルの設計など、具体的な実装パターンを学びます。