[{"content":"7/11(土) に参加させていただいたSRE Next 2026に参加してきました。\n拝聴したセッション 誰のためのリライアビリティ？ 登壇者: 木浦幹雄 さん\n資料URL: https://speakerdeck.com/kur/reliability-for-whom\nユーザーの体験を最重要視するデザイナーの視点から考えると、 SREはSLOなどの数値を守ることに焦点が当てられがちだが、なんのために数字を守ろうとしているのかを考えるべきではないのかという話がありました。\nまた、ペルソナを属性だけで捉えるのではなく、どのタイミングで利用してもらうかまでを考える必要があるという話があり、 その視点でを意識したことなかったので今度から意識してみようと思いました。\nTerraform共通モジュールをチーム横断で“変えられる”運用へ ― リリースと適用の分離 登壇者: 中間 啓介 さん\n資料URL: https://speakerdeck.com/kekke_n/terraformgong-tong-moziyuruwotimuheng-duan-de-bian-erareru-yun-yong-he-ririsutoshi-yong-nofen-li\nTerraformの共通モジュールをGitのタグを用いてバージョン管理することで、チーム横断でも安心してモジュールを変更できる運用を実現した話でした。\n個人的にはGitのタグを使ったバージョン管理っていうのはTerraformに限らず社内で使っているライブラリとかで使っている共通のモジュールとかでも考え方だと思いました。\nタグを使ったバージョン管理っていうのはOSSなどのライブラリを連想するパターンが多いと思いますが、自分たちで開発するものにおいても有用なんだなということに気づくことができました\nSREはどこまでDBを見るべきか？— インフラ改善の先に現れたDB課題と、外部DBRE支援の実践 登壇者: 中楯 直希 さん\n資料URL: なし\nSREとしてDBをどのようにみていき、対処していくべきか(DBRE)という話をするセッションでした。\nデータ量が増えることによって、クエリ遅延が発生した時に全文検索の性能改善にpg_trgmというpsqlのプラグインを導入して改善した話があり、プラグインの存在を知ることができました。(弊社ではその問題を独自のインデックスを構築して改善しましたが、pg_trgmを使った方が柔軟に対応できるのかもと思えました。)\nまた正規化の話もあり、正規化するとパフォーマンスが悪くなる(JOINが増えるから)ので正規化するのをやめるっていうのも一つだよという話があり、正規化にはデータ容量を減らすメリットはあるけど、パフォーマンスのデメリットがあることを再認識させらレました。\n月間400万ジョブを支えるGitHub Actions self-hosted runnerの信頼性 登壇者: azrsh さん\n資料URL: https://azr.sh/slides/github-actions-self-hosted-runner-reliability-at-mercari/1\n大量に動き続けるGithub Actionsのself-hosted runnerが詰まりがちになってたのを、ライブラリの責務の境界の部分が原因になっていたのを突き止めて、改善したことを紹介するセッションでした。\nその中でCIに期待されることについて紹介している部分があり、私が無意識で期待していたことだったので言語化されました。\nまとめ SREというものが何かあまりわかっていない状況での参加でしたが、Github ActionsのSelf Hosted Runnerなど手を出したことがない領域で工夫されているお話を聞けて勉強になりました\n参考 SRE Next 発表資料まとめ 番外編 スポンサーブースも楽しく回らせていただきました！\nメルカリさんのブースでは、弊社でのk8sの運用方法について相談したところめちゃめちゃクリティカルな解決策をいただけて、めちゃめちゃ助かりました。ありがとうございました！(近いうちに導入予定です)\nまた、GENEROSITYさんのブースではプリクラ風の写真を撮れるようになっており、撮影していただきました！\n","date":"2026-07-14","dateDisplay":"2026年7月14日","permalink":"https://phasiblog.netlify.app/posts/20260714_sre_next_attend_report/","summary":"SRE Next 2026 感想戦","title":"SRE Next 2026 参加レポート"},{"content":"Compositeパターン 概要 ツリー構造(深さは均一じゃなくていい)で表現できるオブジェクトを扱うためのパターン\nディレクトリとファイルなど再帰的に表現できるものに使う。\n共通のインターフェースを用意して、ツリーの親が子の計算を集計するという処理を再帰的に行う。\n使い方 カテゴリーと商品(カテゴリーはネストする)で表現する\n// 共通のインターフェース trait CategoryItem { fn get_price(\u0026amp;self) -\u0026gt; u32; } // CategoryはCategoryItemを複数持つ struct Category { name: String, items: Vec\u0026lt;Box\u0026lt;dyn CategoryItem\u0026gt;\u0026gt;, } // Categoryに対してCategoryItemを実装 impl CategoryItem for Category { fn get_price(\u0026amp;self) -\u0026gt; u32 { self.items.iter().map(|item| item.get_price()).sum() } } // Productは末端なのでそのまま struct Product { name: String, price: u32, } impl CategoryItem for Product { fn get_price(\u0026amp;self) -\u0026gt; u32 { self.price } } こうすることで\ncategory1.get_price() // category1の子の合計金額を返す とすると再帰的に計算されてそのcategory以下のすべての商品の合計金額が返ってくる。\n使い所 ネストする形のオブジェクト(モデルなど)を定義した時とかに使える。\n参考 https://refactoring.guru/ja/design-patterns/composite ","date":"2026-06-30","dateDisplay":"2026年6月30日","permalink":"https://phasiblog.netlify.app/posts/20260630_design_pattern_composite/","summary":"デザインパターンを復習 + 言語化してみた→Composite","title":"【復習デザインパターン】Compositeパターン"},{"content":"所有権 Rustのメインのシステムの１つ。 所有権のシステムによってRustはメモリ安全性を実現している\nRustの所有権には以下の規則がある\n値には所有者が存在する いかなる時も所有者は1つのみ 所有者がスコープから外れたら値は破棄される スコープ 変数はスコープの中でのみ有効\nprintln!(x); // error: xはスコープ外なので参照できない { let x = String::from(\u0026#34;hello\u0026#34;); println!(x); // OK: xはスコープ内なので参照できる } println!(x); // error: xはスコープ外なので参照できない スコープを抜けるとStringの値が破棄される。\n破棄されるということは、メモリが解放されるということ。\nRustはこの仕組みを自動的に行ってくれるので、C言語のように手動でメモリを解放する必要がない。\n→ メモリ安全性が担保される。\nムーブ Stringはヒープ領域に値を保持している。\nそのため、別の変数に値を移動させると所有権が移動する。\nlet x = String::from(\u0026#34;hello\u0026#34;); let y = x; // ムーブが発生する(xからは参照できなくなる) println!(x); // compile error: xは参照できない Stringの場合はcloneメソッドを使うことで、値をコピーすることができる。\nlet x = String::from(\u0026#34;hello\u0026#34;); let y = x.clone(); // cloneを使うことで値をコピーできる println!(x); // OK: xは参照できる Copyトレイト 別の変数に代入したときに、所有権をムーブさせない仕組み。\nスタックに保存される系の値(数値やboolなど)にはCopyトレイトが実装されており、所有権がムーブされないようになっている。\n必要なら自分でCopyトレイトを実装することもできる。\nlet x = 5; let y = x; // Copyトレイトが実装されているので、所有権はムーブされない println!(x); // OK: xは参照できる 参照と借用 通常、別の変数に代入すると所有権が移動する。\nしかし、参照だけを渡すことで、所有権を移動させずに値を使うことができる。\n参照は\u0026amp;を使って作ることができる。\n参照を作成することを借用と呼ぶ。\nlet x = String::from(\u0026#34;hello\u0026#34;); let y = \u0026amp;x; // 参照を渡すことで、所有権を移動させずに値を使うことができる println!(x); // OK: xは参照できる println!(y); // OK: yは参照できる 参照は変数の所有権を移動させないので、参照を作った変数はスコープを抜けても破棄されない。\nlet x = String::from(\u0026#34;hello\u0026#34;); { let y = \u0026amp;x; // 参照を作る println!(y); // OK: yは参照できる } // yはスコープを抜けるが、xは破棄されないので、参照は有効 println!(x); // OK: xは参照できる println!(y); // compile error: yはスコープ外なので参照できない 可変参照 参照は不変参照と可変参照の2種類がある。\n先ほどの例のlet y = \u0026amp;x;は不変参照である。\n可変変数の参照 + 変更できる権利を持つ = 可変参照\nlet mut x = String::from(\u0026#34;hello\u0026#34;); let y = \u0026amp;mut x; // 可変参照を作る y.push_str(\u0026#34; world\u0026#34;); // 可変参照を使って値を変更する println!(y); // OK: yは参照できる 可変参照は同時に複数作ることはできない。 可変参照があるときにはその変数の不変参照も作れない\nlet mut x = String::from(\u0026#34;hello\u0026#34;); let y = \u0026amp;mut x; // 可変参照を作る let z = \u0026amp;mut x; // compile error: 可変参照は同時に複数作ることはできない let w = \u0026amp;x; // compile error: 可変参照があるときにはその変数の不変参照も作れない 可変参照がデータの書き込みを行える間、元の変数は参照できない。 (可変参照はデータを同期しているわけではないため)\nlet mut x = String::from(\u0026#34;hello\u0026#34;); let y = \u0026amp;mut x; // 可変参照を作る println!(x); // compile error: 可変参照があるときにはその変数の不変参照も作れない (可変参照がスコープを抜けると、元の変数は参照できるようになる)\nlet mut x = String::from(\u0026#34;hello\u0026#34;); { let y = \u0026amp;mut x; // 可変参照を作る y.push_str(\u0026#34; world\u0026#34;); // 可変参照を使って値を変更する println!(y); // OK: yは参照できる: hello world } // yはスコープを抜けるので、xは参照できる println!(x); // OK: xは参照できる NIL(Non-Lexical Lifetimes) コンパイラが所有権のルールをチェックする際に、どこまでその値が有効かを判断する仕組み\nlet mut y = String::from(x); let a = \u0026amp;mut y; let b = \u0026amp;mut y; println!(\u0026#34;a: {a}, b: {b}\u0026#34;); ↑これはコンパイルエラーだけど\n↓これはコンパイルエラーじゃない\nlet x = \u0026#34;hello\u0026#34;; let mut y = String::from(x); let a = \u0026amp;mut y; let b = \u0026amp;mut y; println!(\u0026#34;b: {b}\u0026#34;); これ以上その参照が使用されなくなったら、借用が終了する\n関数と所有権の組み合わせ 関数の引数に代入するとき、戻り値を変数に代入するときにも所有権のルールが適用される。\nfn main() { let x = String::from(\u0026#34;hello\u0026#34;); let doubled_x = double_string(x); // double_stringに所有権が移動する println!(x); // compile error: xは参照できない println!(doubled_x); // OK: doubled_xは参照できる } fn double_string(s: String) -\u0026gt; String { s + \u0026amp;s // sの所有権は関数内で破棄されるが、戻り値として返すことで所有権を呼び出し元に移動させる } 参照を引数にすることで、所有権を移動させずに値を使うことができる。\nfn main() { let x = String::from(\u0026#34;hello\u0026#34;); let doubled_x = double_string(\u0026amp;x); // double_stringに所有権が移動しない println!(x); // OK: xは参照できる println!(doubled_x); // OK: doubled_xは参照できる } fn double_string(s: \u0026amp;String) -\u0026gt; String { s + \u0026amp;s // sの所有権は関数内で破棄されないので、呼び出し元のxは参照できる } 可変参照を引数にすることで、所有権を移動させずに値を変更することができる。\nfn main() { let mut x = String::from(\u0026#34;hello\u0026#34;); double_string(\u0026amp;mut x); // double_stringに所有権が移動しない println!(x); // OK: xは参照できる } fn double_string(s: \u0026amp;mut String) { s.push_str(\u0026#34; world\u0026#34;); // sの所有権は関数内で破棄されないので、呼び出し元のxは参照できる } 参考 https://doc.rust-jp.rs/book-ja/ch04-01-what-is-ownership.html ","date":"2026-06-27","dateDisplay":"2026年6月27日","permalink":"https://phasiblog.netlify.app/posts/20260627_rust_ownership/","summary":"Rustの学習まとめ","title":"【Rust】所有権"},{"content":"Container・Presentationパターン 概要 フロントエンドのコンポーネントにおけるデザインパターン。\nデータ取得・副作用・アプリケーション状態の管理とUI表示の責務を分けることで関心の分離を実現する。\nコンポーネントのパーツの再利用性を高めることができる。\n使い方 bad\nconst UserProfile = () =\u0026gt; { const [user, setUser] = useState\u0026lt;User | null\u0026gt;(null); useEffect(() =\u0026gt; { fetchUser().then(setUser); }, []); if (!user) return \u0026lt;div\u0026gt;Loading...\u0026lt;/div\u0026gt;; return ( \u0026lt;div\u0026gt; \u0026lt;h1\u0026gt;{user.name}\u0026lt;/h1\u0026gt; \u0026lt;p\u0026gt;{user.email}\u0026lt;/p\u0026gt; \u0026lt;/div\u0026gt; ); }; 表示と取得・状態が全部同じコンポーネントに集まってる。\n取得ロジックのテストや状態管理のテストなどがやりにくい。\nまた、複雑化したときにコンポーネントが肥大化しやすい。\ngood\nconst UserProfileContainer = () =\u0026gt; { const [user, setUser] = useState\u0026lt;User | null\u0026gt;(null); useEffect(() =\u0026gt; { fetchUser().then(setUser); }, []); return \u0026lt;UserProfile user={user} /\u0026gt;; }; const UserProfile = ({ user }: { user: User | null }) =\u0026gt; { if (!user) return \u0026lt;div\u0026gt;Loading...\u0026lt;/div\u0026gt;; return ( \u0026lt;div\u0026gt; \u0026lt;h1\u0026gt;{user.name}\u0026lt;/h1\u0026gt; \u0026lt;p\u0026gt;{user.email}\u0026lt;/p\u0026gt; \u0026lt;/div\u0026gt; ); }; コンテナ: 状態や副作用、ロジックを持つコンポーネント プレゼンテーション: 状態や副作用、ロジックを持たないUI表示に特化したコンポーネント(厳密には、表示や見た目のためだけの状態は持っても良い)\n使い所 UIとロジックを分けることで再利用性が上がる 状態を持たないため純粋にUIだけを評価できる → テストが書きやすくなる\nコンテナ: vitestなどのテストでロジックのテストが書きやすい プレゼンテーション: StorybookなどのテストでUIのテストが書きやすい レイヤードアーキテクチャやDDDなどのプレゼンテーション層などとの違い レイヤードアーキテクチャやDDDなどでもプレゼンテーション層などで表示とロジック(とその他)を分けているが、 それらとの違いは? → そもそも考えているスコープが違う\nアーキテクチャの方がもっと広い → アプリケーション全体において ビジネスロジック と コード を繋ぎ合わせる\nコンテナプレゼンテーションパターン → フロントのコンポーネントにおける表示とロジックの分離\n参考 https://zenn.dev/morinokami/books/learning-patterns-1/viewer/presentational-container-pattern https://zenn.dev/buyselltech/articles/9460c75b7cd8d1 https://zenn.dev/akfm/books/nextjs-basic-principle/viewer/part_2_container_presentational_pattern ","date":"2026-06-24","dateDisplay":"2026年6月24日","permalink":"https://phasiblog.netlify.app/posts/20260624_design_pattern_container_presentation/","summary":"デザインパターンを復習 + 言語化してみた→コンテナプレゼンテーションパターン","title":"【復習デザインパターン】Container・Presentationパターン"},{"content":"6/12(金)に開催されたTSKaigi アフターパーティーに参加してきました。\n拝聴したセッション 翻訳辞書にも型が欲しい TypeScriptで考えるのi18n 登壇者: 黒髙 未知可 さん\n資料URL: https://speakerdeck.com/everypr/deng-tan-zi-liao-fan-yi-ci-shu-nimoxing-gahosii-ypecriptdekao-erui18n\nNext.jsにおいて型安全にi18nを管理するnext-intlについて紹介するセッションでした。\nlocaleのkeyの形が場所によって違うケースとかが問題になりやすいという話があり、自分の開発や職場の開発でもありがちかもと思って共感していました。\n{ \u0026#34;book\u0026#34;: { \u0026#34;title\u0026#34;: \u0026#34;the book\u0026#34; }, \u0026#34;movie\u0026#34;: { \u0026#34;filmTitle\u0026#34;: \u0026#34;the movie\u0026#34; } } Nextはあまり触れていないけど、それ以外のライブラリを探して実践してみるのはありかもと思えた。\nただ、TSで型をつけるとモジュールやファイルが増えてしまうというトレードオフはあるので、localeの実装が必要なグローバルなプロダクトでないと、そこまでやる必要はないのかもと思えた。\nneverthrow is not for meを再考する 登壇者: 我らが Rinrin\n資料URL: https://www.docswell.com/s/rin2yh/Z4N4NW-rethinking-neverthrow-is-not-for-me\nneverthrow(TSのResult型を実現するライブラリ)について、確かに関数型っぽくなるけど、独特の記法や認知負荷が高いと一度は敬遠していたものの、今一度考えてみて使い方を工夫することで、それを乗り越えたという話だった。\n不便なAPIがある = 使いづらいではなく、\n使いづらいAPIは使わない ラッパーを作って使いやすくする という工夫をすることで、その課題を乗り越えられるという話があった。\nまた、AI時代だからと言って自作をすると管理コストが肥大化してしまう可能性があるという話を聞いて、(もちろんサプライチェーン攻撃とのトレードオフになるが)そのコストの大きさを考えると責任が大きいライブラリなどは自作するのではなく、ライブラリを使う方がいいのかもと思えた。\nまた、neverthrowを含む関数型TSが使える部分って、ライブラリに try/catch 前提の動作が組み込まれていることが多く、フロントエンドは適していないという話があり、Nuxtを触ってる身からすると共感できる部分が多かった。\nType SafeなCSSで実現する統一感のあるスタイリング 登壇者: 長谷川 駿 さん\n資料URL: https://www.docswell.com/s/WN_Tech-PR/KE1Y1D-2026-06-12-194556\nCSS + 型 の実現方法について紹介するセッションでした。\nライブラリとしてはvanilla-extractというライブラリが候補としては紹介されており(結局採用はしてなかった)、初耳だった。\nメインはPandaCSSというライブラリの紹介だった。React Tokyo Fesで紹介しているポスターで CSS + 型 のライブラリとしては認識していたが、\nセッションでデザイントークン(CSS変数など)の指定忘れで型エラーが出るという話があり、すごく便利に思えた。\n私は開発の中でCSS変数で定義しているのに、離れたコンポーネントでは同じ色やfontSizeなどを忘れてそのまま書いちゃうことがあるあるで、CSSだからしょうがないって割り切ってた部分があり、その部分の課題にドンピシャで刺さる話だった。\nただし、私のメインが今Vue.jsなのでデザインシステムがすでに用意されている中であえてその枠組みを破ってもいいのかどうかについては、まだ検討の余地がありそうだと感じた。(Reactに関しては絶対使いたい)\nprotovalidate-es を導入してみた 登壇者: 辻 佳佑 さん\n資料URL: https://speakerdeck.com/bengo4com/20260612-tskaigi2026-afterparty-introducing-protovalidate-es\nSSoTの実現方法の一つとしてValidatorを.proto(gRPCで使われる定義ファイル)から生成するprotovalidate-esというライブラリの紹介でした。\n実際のバリデーションを行うときの型とリクエストの時の型が違うことがあり、それはmappingの仕組みを導入することで解決できるという話があり、\n私が今、hey-apiからzodのバリデーションを生成しているため、この話はすごく参考になった。\nまた、Vue.jsにはRegleというバリデーションライブラリがあることを知った。zod + vueの状態で頑張って実装してるのでもしかしたら、Regleを使った方が楽に実装できるのかもと思えた。\nアンチパターンを避ける型駆動開発 登壇者: 芹澤 和也 さん\n資料URL: https://speakerdeck.com/seriseri/antipatanwobi-keruxing-qu-dong-reactzui-shi-hua-tskaigi2026-ahutapatei\nReact Compilerの実現にあたって、どのような課題があったか、そしてそれをどのように解決したかを紹介するセッションでした。\n副作用や非決定性などについて、設計から解決するという話があり、設計ってコードの課題解決としてあんまり意識したことなかったので、設計の役割について改めて考えさせられた。\nまとめ TSKaigiの時も思ったが、Biomeが登場してすぐだった去年の時点と比べて、Biomeが成熟 + oxlintが登場してきたこともあって、Linterを使った課題解決の話が多くなってきた印象があった。\nAI導入というより、TSそのものの話が多く、TSについて大変勉強になった。\n","date":"2026-06-17","dateDisplay":"2026年6月17日","permalink":"https://phasiblog.netlify.app/posts/20260617_tskaigi_after_party_attend_report/","summary":"TSKaigi アフターパーティー 感想戦","title":"TSKaigi アフターパーティー 2026 参加レポート"},{"content":"Proxyパターン 概要 名前通り、あるモジュールへの仲介役を提供するパターン\n使い方 モジュールをラップして、処理を挟み込むパターン。\n通常のラップと似てるけど、処理を前後に挟みたいという意図があるのが特徴。\n使い所 モジュールの前後に処理を挟みたい場合 Logger キャッシュ 認証 アクセス制御 参考 https://refactoring.guru/ja/design-patterns/proxy ","date":"2026-06-09","dateDisplay":"2026年6月9日","permalink":"https://phasiblog.netlify.app/posts/20260609_design_pattern_proxy/","summary":"デザインパターンを復習 + 言語化してみた→Proxyパターン","title":"【復習デザインパターン】Proxyパターン"},{"content":"Builderパターン 概要 複雑なオブジェクトに対して、たくさんのsetterを用意して、オブジェクトの生成を簡単にするためのパターン\n例 bad\n(rustで表現しづらいのでTSで)\nclass User { name: string; age: number; email: string; address: string; phoneNumber: string; constructor(name: string, age: number, email: string, address: string, phoneNumber: string) { this.name = name; this.age = age; this.email = email; this.address = address; this.phoneNumber = phoneNumber; } } // 初期化処理が絶望 const user = new User(\u0026#39;Alice\u0026#39;, 30, \u0026#39;alice@example.com\u0026#39;, \u0026#39;123 Main St\u0026#39;, \u0026#39;555-1234\u0026#39;); good\nキーワード引数を使うという手もあるが\u0026hellip;\nclass User { name: string; age: number; email: string; address: string; phoneNumber: string; setName(name: string): this { this.name = name; return this; } setAge(age: number): this { ... } setEmail(email: string): this { ... } setAddress(address: string): this { ... } setPhoneNumber(phoneNumber: string): this { ... } } const user = User.new() .setName(\u0026#39;Alice\u0026#39;) .setAge(30) .setEmail(\u0026#39;alice@example.com\u0026#39;) .setAddress(\u0026#39;123 Main St\u0026#39;) .setPhoneNumber(\u0026#39;555-1234\u0026#39;); どの値がどのインスタンス変数に対応しているのかがわかりやすくなった\n使い所 キーワード引数の機能がない言語を使っているパターン Javaとかはこのパターンがよく使われる 注意点 普通にキーワード引数があるときは、キーワード引数を使う方がシンプルでわかりやすい 参考 https://refactoring.guru/ja/design-patterns/builder ","date":"2026-05-31","dateDisplay":"2026年5月31日","permalink":"https://phasiblog.netlify.app/posts/20260531_design_pattern_builder/","summary":"デザインパターンを復習 + 言語化してみた→Builderパターン","title":"【復習デザインパターン】Builderパターン"},{"content":"2026/05/22,23開催で羽田空港にある巨大なイベント会場で開催されてた。\n勉強になることもたくさんあったので、参加レポートとしてまとめです！\n拝聴したセッション 「関数型プログラミング」を分解する.ts 登壇者: おーみーさん\nセッションURL: https://2026.tskaigi.org/talks/3\n資料URL: https://tsk-2026-aumy.vercel.app/1\n正直、関数型プログラミングをちゃんと理解していないので、理解を深める機会になればと思って参加したセッションでした。\n関数型プログラミングについて整理をした後に、\n一部の概念はTSだと実現できないこと、\nそして、それでも擬似的に再現する方法を紹介するセッションでした。\n結局関数型プログラミングが何を目的にやってるかを立ち返って、その目的のために、TSでできることを紹介してくれたのがすごく良かった。\n特に、「継続」という概念が初めて知った概念ですごく面白かった。\n継続は計算の残りの部分で、コールバックによって表現されると、「継続渡しスタイル」と呼ぶ 継続渡しスタイルとしてJSのPromiseチェーンなどがこれを実現している 継続渡しスタイルはコールバック地獄になりやすいので、async/awaitは手続き的なスタイルで書けるようにしている RustのOptionもand_thenを使えば継続渡しスタイルになるが?演算子を使えば手続き的なスタイルで書けるようにしている 個人的にはTSの例だけじゃなく個人的にRustの学習もしていることもあって、RustのOptionなどについても理解を深められる機会になった。\n業務に残された「よくない型」で考える「TypeScriptの難しさ」 登壇者: Sajiさん\nセッションURL: https://2026.tskaigi.org/talks/5\n資料URL: https://speakerdeck.com/sajikix/ye-wu-nican-sareta-liang-kunaixing-dekao-eru-typescriptnonan-sisa\n業務でよくない型ってどういうのだろう?、そして仕事で使ってるTSのコーディングの観点を見直す機会になればと思って参加。\nどうしてもasや@ts-ignoreなどの型について妥協してしまうケースを分類して、どのように対処すればいいのかを紹介するセッションでした。\n7つのパターンに分解してくれていて、ちゃんとそれぞれのケースについて具体的な解決策を紹介してくれていたのがすごく良かった。\nTSの言語の仕組みとしての問題や、その問題がバージョンアップによって徐々に改善されていってるというのが印象的でした。(ちゃんとバージョンアップしていかないとと思えた。)\nまた、チェックリストも用意してくれてこれからの業務でも活用したいと思えた。\n権限チェックの一貫性を型で守る TypeScript による多層防御 登壇者: 北川 直昭さん\nセッションURL: https://2026.tskaigi.org/talks/9\n資料URL: https://speakerdeck.com/mnch/quan-xian-tietukuno-guan-xing-woxing-deshou-ru-typescript-niyoruduo-ceng-fang-yu\nこれからTSでバックエンドを少し書くことになりそうなので、実運用でどういう権限、型管理をするべきかの参考にしたいと思い拝聴。\n権限チェックがfrontend, backend, DBで同じルールがあるが、それぞれで定義すると保守のリスクがあるため、SSoT(Single Source of Truth)で管理するという話だった。\nSSoTという概念は初めて知ったが、1つのルールを一箇所で管理して、それを他にも流用するというものらしい。\nfrontend, backendはわかるがDBでどう実現するんだと思っていたが、psqlのplv8というJSを実行する拡張機能を使うことで検証を行うことを可能にしていることが印象的だった。\n個人的にはTSが構造的型付けというのもあり、別にそれぞれで定義してもいいだろうとは思っていたが、別のセッションで同じ構造のデータを間違って渡してしまっていたケースなどの紹介があり、確かにSSoTで管理するのは保守の観点からも良さそうだなと思えた。\nTypeScriptのclassはなぜこうなったのか — 歴史・落とし穴・そして使いどころを探る 登壇者: kosuiさん\nセッションURL: https://2026.tskaigi.org/talks/16\n資料URL: https://kosui.me/slides/2026/tskaigi/1\n私はTSのclassの挙動があまり好きでなく、あまり使わないようにしているのですが、どうしてこういう挙動になっているのかを知りたいと思い拝聴。\n以下の３つの問題点をベースに問題を整理して、いつ使えばいいかを紹介するセッションでした。\n構造的部分型との相性が悪い 問題: そもそもTSが同じ構造なら型エラーにならないため、classに名前をつけても意味がない 対策: BrandedTypeを使用する 型が消去されてしまう 問題: オブジェクト(広義)としてのプロパティが同じなら、オブジェクト{}とclassでランタイム上は区別がつかない(型消去) 対策: 型消去されないようなオブジェクトのプロパティを用意して、Discriminated Unionを使用する prototypeベースのJS/TSの相性も悪い 問題: JS/TSのthisは諸問題の原因になる 対策: thisを使わないようにする classの使い所については以下のように整理されていた\nCustom Error: Errorクラスを継承してtry/catchをする慣習のためclassを使った方が都合がいい(Error.isErrorもあるし) Symbol.disposeで処理後にリソースを解放するとき: usingを使ったリソース管理のためにclassを使うと都合がいい また、classを書くのはFWによっても異なると紹介されていた。Angularなどでは使うのは避けられないが、React, Vueなどは使わなくていいと紹介されていた。\n私の業務ではVueを使用しており、一部モデルなどでclassを使用しており、あんまり使わない方がいいのかもと思った。\nビジネスモデルから紐解く、AI+型駆動開発 登壇者: omoteさん\nセッションURL: https://2026.tskaigi.org/talks/18\n資料URL: https://speakerdeck.com/hirokiomote/hisinesumoterukaraniu-jie-ku-ai-plus-xing-qu-dong-kai-fa\n私は最近業務でAIと設計をし、実装させるということを行なっており、そのための知見を得るために拝聴。\nプロダクトを以下の4つに分類し、それぞれどこを中心に型を設計していけばいいのかを考えるセッションでした。\nSaaS型 データ依存型 API中心型 マーケットプレイス型 新規プロダクトの設計となれば特に意識する必要があると感じた。\n私が今携わっているプロダクトはマーケットプレイス型だと思ったので、今それが中心になっているかを改めて考える機会になった。\nTS 7: How We Got There 登壇者: Jake Bailey\nセッションURL: https://2026.tskaigi.org/talks/37\n資料URL: https://jakebailey.dev/talk-tskaigi-2026/1\nMircrosoftのTSの開発者本人から話が聞ける貴重な機会だと思い参加。\ntsgoのリリースが近づいている中、どのような経緯でTSの実装をTSからGolangに切り替えたのかという経緯が聞けるセッションだった。\n並列処理やVSCode(Electron)のメモリ制限などの問題があったのがきっかけだった話は初めて聞いて面白かった。\nまた開発の中で、思ったより速度改善されなかった、そしてそれをどう乗り越えて速度を上げることができたのかという開発裏話が聴けたのも印象的だった。\n実際にVSCodeのビルドをts5とts7を比較する実演タイムがあり、 3分以上かかっていたビルドが、15秒程度になっていたのは衝撃的だった。\n個人的にwebpackのビルドがめちゃめちゃ遅いので、それも解決できそうに思えた。\n400超のデータポイントを型で制す —— UPSIDERの与信審査エンジンを支えるTypeScriptの「柔軟性」と「結合力」 登壇者: 泉雄介さん\nセッションURL: https://2026.tskaigi.org/talks/39\n資料URL: なし\n大規模なデータを扱うプロダクトでどのようにしてTSを利用しているのかが気になって参加。\n400以上ある特徴量をどうTSで管理しているかを紹介するセッションでした。\n400以上の特徴量を1つの型で管理しているという部分が衝撃的だった。\nまたAI導入後の開発チーム体制についての言及も参考になった。\nRubyも検討したが、型があるTSの方がいいと判断 慎重に作業する部分が変わった: コーディングからレビューやテストにシフト 仕様書はPRDで管理していた チーム人数が10~20人から1 pizzaになった PRも巨大になった(旧体制からはギャップを感じる) 私が所属している組織でもAIによって開発体制が大きく変わっている最中であるため、AI導入後の開発体制の話が参考になりました。\nReact の props は値の集合ではない — UI の状態を宣言するコンポーネント設計 登壇者: nabeliwoさん\nセッションURL: https://2026.tskaigi.org/talks/41\n資料URL: https://nabeliwo.github.io/slides/talks/20260523_tskaigi-2026_react-props/1\npropsは値の集合ではないというタイトルに惹かれて参加。\npropsの型設計には問題があって、あり合えない組み合わせを防げないという話だった。\nDiscriminated Unionを使うことで、あり合えない組み合わせを防げるようになると紹介されていた。\nまた、非同期データについてはSuspesnceなどを使用するようにとも紹介されていた。\n個人的には、validationで防ぐものかと思っていたが、型で防げた方が型情報だけでわかるのでこっちの方が絶対いいと思った。\nまた、VueにもSuspenseがあるか確認したらちゃっかりあった。これをVueでも使っていきたいと思った。\n型プラグインシステムの実装に使われるテクニック 登壇者: elecdeerさん\nセッションURL: https://2026.tskaigi.org/talks/42\n資料URL: https://speakerdeck.com/teamlab/tskaigi-typed-plugin-system\n型システムについて理解を深めたくて参加。\nライブラリなどで使われる型実装のテクニックを紹介するセッションでした。\n業務ではあんまり使いづらそうだが、ライブラリがどういう思想で型を導入しているかをしれて面白かった。\nAuth.jsからBetter Authへの移行に見る「型とランタイム」の設計思想の変化 登壇者: 宇根昇汰さん\nセッションURL: https://2026.tskaigi.org/talks/43\n資料URL: https://speakerdeck.com/nowaki28/tsservertohahe-tatutanoka-korekaratounarunoka\n3連続セッションでなんとなく知らないライブラリだったが認証っていつの時代も大事なので、ふらっと拝聴。\nAuth.jsがBetterAuthに移行が推奨されており、どのような変更があるかどうかのセッションだった。\n思想自体が自分で定義するのではなくSSoTに沿ったもので他のセッションでもあったが、SSoTがだいぶ主流になってるんだと感じた。\ntsserverとは何だったのか、これからどうなるのか 登壇者: 中村遼大さん\nセッションURL: https://2026.tskaigi.org/talks/51\n資料URL: https://speakerdeck.com/nowaki28/tsservertohahe-tatutanoka-korekaratounarunoka\n私はZedのLSPが整ってない頃にLSP拡張機能を作ろうとしたことがあるLSPオタクなので、聞いてみたいと思って参加。\nts6まではtsserverでLSPと非互換だったが、ts7からはtsgoを直接--lspを指定すればLSPを起動することができるようになったことを紹介するセッションだった。\ntsserverはなんとなく単語は知ってたが、typescript-language-serverは馴染み深かった。\nそれが、まさかtypescript-language-serverがtsserverをラップしているだけのものだったとは知らなかった。\nまた、tsserverがなんでLSP非互換なのかという歴史的背景も知れて面白かった。\nそして、ts7からはtsserverがなくなり、vueなどの旧式のAPIを使っていたツールチェーンが対応に追われてしまうという話があり、Vueユーザーとしてはもう少しts7を使うのは待たないといけないかもなと思った。\nNode.js+TypeScriptにおけるCJS/ESM相互運用の最新ポイント 登壇者: 桐生直輝さん\nセッションURL: https://2026.tskaigi.org/talks/56\n資料URL: https://speakerdeck.com/grainrigi/esmxiang-hu-yun-yong-nozui-xin-pointo\n個人的にもESMやらCJSやらでごちゃごちゃ煩わしく思っていたため、どうやって運用すればいいかの知見を得るために参加。\ntsconfigでmodule=nodenextを指定すると、基本的に気にしなくて良くなるらしい。\nこの問題の元凶の紹介もあり、top level awaitというほとんど使われない機能のせいでrequireが同期的に動かなくなってしまっため、esm側がrequireでのimportを禁止したのが原因だと紹介があって、数年越しに理由を知れて興味深かった。\nenum よ、さようなら 登壇者: takuma-ruさん\nセッションURL: https://2026.tskaigi.org/talks/57\n資料URL: https://speakerdeck.com/teamlab/tskaigi-goodbye-enum\n私はenumアンチ(tsのバージョンで挙動違ったりするので)なので、共感しそうだなと思って拝聴。\nenumが使わない方がいいことを前提に、なんでenumが微妙なのか、そしてこれから残り続けてしまうことを紹介するセッションでした。\nenumが微妙な理由は以下の通りと紹介された\nenum数行で生まれるJSコードが長すぎる(バンドルサイズが大きい) 途中でTSが方針転換し、enumが生きづらい世界に ただし後方互換のため、enumは残り続けることが紹介されていた。\n歴史的背景も知れて面白かったです。\ninferと仲良くなる10分間 登壇者: infixerさん\nセッションURL: https://2026.tskaigi.org/talks/58\n資料URL: https://speakerdeck.com/ryokatsuse/infertozhong-liang-kunaru10fen-jian\n初心者向けのinfer解説のセッションでした。\ninfer日頃そんなに使わないので、ちょうどいい具合に思い出せてよかったです。\nいつテストを書くか？―ソフトウェア開発における安心と不安について考える 登壇者: lacolacoさん\nセッションURL: https://2026.tskaigi.org/talks/63\n資料URL: https://docs.google.com/presentation/d/e/2PACX-1vSuTOMT21i3AsVT0xiy9wZV1h2ZytSbFKjEFzcslLvmv2sHQ2VNgPRGXiEQid32557D1wxlB_XmlIpT/pub?slide=id.SLIDES_API405771716_0\nAIの登場のなかいつテストを書いた方がいいんだろうという疑問を持ってたので、テストの書き方についての知見を得るために拝聴。\nそもそもソフトウェアは変更のしやすさがソフトであると紹介した上で、その変更しやすさに必要なものは何か、そしてテストはそれにどういう役割を果たすのかを紹介するセッションでした。\n変更のしやすさについて以下の2つの視点から紹介されていた\n予期的変更容易性: 「この変更やばそうだな\u0026hellip;」と思わないこと 経験的変更容易性: 変更中に「しんどい\u0026hellip;」ってならないこと テストはこれらの変更のしやすさを担保するための手段の1つであると紹介されていた。\nテストの種類によってどこに作用するかが変わっており、以下のように紹介されていた。\nE2E/結合テスト: 予期的変更容易性に作用する 単体テスト : 経験的変更容易性に作用する また、テストを書くということにも副次的なメリットがあり、書いている時の書きづらさ = どこかおかしいってなるので、これってプログラムの構造のFBになってるという話もあり、衝撃だった。\n経験則的に、テストを書くと対象がいいコードか悪いコードかわかるなと思っていたが、それがフィードバックになっていたという話を聞いて点と点が繋がった。\nテストがあると品質が安定するという話はよくある話だが、メンタル面で変更しやすさを分解して、テストがある意味を紹介してくれたのが斬新で自分の中でのテストに対する考え方が変わった。\n聞きたかったセッション tscからtsgoへ ── DenoのTypeScript基盤はどう変わったか 登壇者: maguroさん\nセッションURL: https://2026.tskaigi.org/talks/2\n資料URL: https://www.docswell.com/s/magurotuna/59NRVP-tskaigi-2026\nVueの非公式だがtsgoに対応したVueのツールチェーンを紹介していたらしい。\nまだ安定版なので使えないと思うが、Vueのlanguage toolsはts 7.1のリリースを待ってから実装するらしいのでかなり時間かかりそう。\n業務ではまだ使えないが、安定版になったら検討してもいいかもしれない。\n次世代リンターで探る、tsgo 時代における型認識カスタムルールの現実解 登壇者: Yuta Takahashi\nセッションURL: https://2026.tskaigi.org/talks/65\n資料URL: https://speakerdeck.com/ytakahashii/exploring-type-aware-custom-rules-in-the-tsgo-era-through-the-lens-of-next-generation-linters-09ba0a80-5ff0-4d08-84bf-8a15a2179af3\nLinterが大好きなので、tsgoでどう変わってくんだろうと思って聞いてみたかった。\n資料を見る感じ、やっぱり今のtsのeslint pluginが一番今は安定してそう。\nLSPの時もそうだったが、やっぱりts側がコンパイル以外のところでの型認識をどうするか(ts7.1)が固まらないと、他も動きづらいんだろうなと思う。\nESLintは重いので早く、tsgoに対応してほしい。あとBiomeとOxlintにVueのtemplate構文をサポートしてほしいが、もう少し待ちそうです。\nまとめ 個人的には去年とはまた違う視点が多かった気がする。\nBrandedTypeを使ってるケースが増えていたように思えて、型の安全性を高めるために工夫している人が多い印象だった。\n","date":"2026-05-26","dateDisplay":"2026年5月26日","permalink":"https://phasiblog.netlify.app/posts/20260528_tskaigi_attend_report/","summary":"TSKaigi 感想戦","title":"TSKaigi 2026 参加レポート"},{"content":"契約プログラミングとは ざっくり プログラムが仕様に沿ってるかを担保するためのプログラミング手法\nその機能(supplier)とそれを呼び出す側(client)で、お互い満たすべき内容を契約として定義(表明)して、契約を満たすようにコードを書く\n手法 3つの表明がありそれぞれを満たす必要がある\n事前条件: clientがsupplierを呼び出すときに満たすべき条件 事後条件: supplierが結果をclientに返すときに満たすべき条件 不変条件: supplierが呼び出されている間に満たすべき条件 実現方法 契約プログラミングに対応している言語(Kotlinとか)では、アノテーションなどで事前条件や事後条件を定義できる。 しかし、対応してない言語でも、validation関数を用意して、呼び出す前に事前条件を満たしているかを確認するなどの方法で実現できる。\n事前条件 型で縛る validation関数を用意して、事前条件を満たしているかを確認する // 型で数字であることを保証する fn pay_by_card(amount: u32) { // validationで金額が1以上であることを保証する if amount \u0026gt;= 1 { panic!(\u0026#34;金額は1以上でなければなりません\u0026#34;); } // 支払い処理 } 事後条件 事前条件と同様で、\n型で縛る validation関数を用意して、事後条件を満たしているか // 戻り値の型で数字であることを保証する fn calc_price(orders: Vec\u0026lt;Order\u0026gt;) -\u0026gt; u32 { let total_price = orders.iter().map(|order| order.price).sum(); // validationで合計金額が0以上であることを保証する if total_price \u0026lt; 0 { panic!(\u0026#34;合計金額は0以上でなければなりません\u0026#34;); } total_price } 不変条件 モデルがあった場合、コンストラクタなどで不変条件を満たすようにする\nstruct AdultUser { name: String, age: u32, } impl AdultUser { fn new(name: String, age: u32) -\u0026gt; Self { // validationで年齢が0以上であることを保証する if age \u0026gt;= 18 { panic!(\u0026#34;年齢は18以上でなければなりません\u0026#34;); } User { name, age } } } 防御的プログラミングとは 契約プログラミングと同じで、プログラムが仕様に沿っているかを保証するためのプログラミング手法\nしかし、契約プログラミングと違って、契約を満たすためのコードをsupplier側で書くのではなく、client側で書く\nつまり、呼び出す側で確認を挟みまくる必要がある\nこれはsupplierで書いた内容の検証を呼び出す側で行うことになるため、冗長になりがち\nしかし、supplierが信用できないパターン(外部モジュールなど)では、契約プログラミングよりも防御的プログラミングの方が適している\nまとめ 契約プログラミングも防御的プログラミングも、プログラムが仕様に沿ってるかを担保するためのプログラミング手法である。\n防御的プログラミングは冗長になる場合が多いので、自分でsupplierを開発している場合は契約プログラミングが用いられるケースが多い。\n参考 https://qiita.com/yoshitaro-yoyo/items/bb8cc631276380b68c13 https://zenn.dev/snamiki1212/scraps/76a5044109dc56 https://speakerdeck.com/7pairs/pycon-jp-2025 ","date":"2026-05-04","dateDisplay":"2026年5月4日","permalink":"https://phasiblog.netlify.app/posts/20260504_contract_programing/","summary":"知らない単語なので1から勉強します","title":"契約プログラミング・防御的プログラミング"},{"content":"概要 凝集度: 1つのモジュールがどれだけ１つの責務に集中できているか\n結合度: モジュール同士の依存関係がどれだけ強いか\n理想的なのは高凝集・低結合\nつまり理想なのは、\n1つのモジュールが1つの責務に集中している モジュール同士の依存関係が弱い 凝集度 モジュールが1つの責務に集中している度合い\n1つのモジュール内に複数のメソッドがあってもそれが同じ責務に関するものであれば高凝集になる\n凝集度にはレベルがある。(レベルが上がるほど高い)\nLV1. 偶発的凝集(最悪) 一番悪い例\n関連性のない要素が集まっている\nなんも関連性がないものが集まっている状態\nLV2. 論理的凝集 ラベリングの一部が同じであるが、関連性のない要素が集まっている\n〇〇関連の要素を集めたシリーズ。\nこれがエスカレートすると、なんでも集まっちゃったなんでもモジュールが生まれてしまい、結局スコープが少し狭いだけの偶発的凝集になってしまう。\nLV3. 時間的凝集 実行タイミングが同じものが集まっている。\n初期化処理などでありがち。 あとは、ボタンクリックした時のhandleClickの中とかもそうかも。\n例えば、\nfn initialize() { loadConfig(); initializeDb(); loadCache(); loadUser(); } これがエスカレートすると結局そのタイミングにすることがどんどん増えていって、なんでもモジュールになってしまう。\nLV4. 手順的凝集 実行時に順番に実行されるものが集まっている。\n時間的凝集に近いが、そのモジュール内での実行順が大事になっているかどうかがポイント。\n例えば、\nfn login(user_id: i32) { check_user_exists(user_id); create_session(user_id); redirect_to_user_page(user_id); } この例は同じタイミングで特定の順番での実行が大事だが、 sessionを作成するのと、リダイレクトするのは、関連性が低い。\nこれがエスカレートすると、結局なんでもモジュールになってしまい、テストがしづらくなる\nLV5. 通信的凝集 同じデータに関する処理を集めた状態。\n手順的凝集や時間的凝集と似ているが、同じデータを扱う処理が集まっていることがポイント。\n例えば、\nfn handle_order(food: Food) { log_order(food); send_order_to_kitchen(food); add_order_to_receipt(food); think_about_food(food); } この例は、順番もタイミングも大事にしてなくて、とりあえずfoodに関する処理が集まっている状態。\nRailsはこれに陥りやすい\n例えば: Userに関するメソッドを集めたmodelは、Userに関するものなんでも集めてしまうことが多い。\n役割がバラバラになる + 影響範囲が大きいため、 再利用・テストやメンテナンスがしにくくなる。\nLV6. 逐次的凝集 手順の中で出力が次の入力として使われるような構造になったモジュール。\n手順的凝集の中で、さらに出力と入力の関係があるものが逐次的凝集。\n例えば、\nfn login(user_id: i32) { let user = fetch_user(user_id); let user = update_last_login_time(user); create_session(user); } この例のように手順をまとめる用途なら問題ない。(広く見れば同じ責務に関するものが集まっているとも言える) ただ、update_last_login_timeとcreate_sessionと狭く見れば責務が違うものが集まっているとも言える。\n責務が違うものが集まってると、他の低いLVの凝集と同じようにテストがしづらくなる\nLV7. 機能的凝集(完成系) 一番理想的で、1つのモジュールが明確に1つの責務に集中している状態。\n// これは逐次的凝集 fn handle_create_session(user_id: i32) { validate_user_id(user_id); let user = fetch_user(user_id); let user = update_last_login_time(user); create_session(user); } // これは機能的凝集 fn validate_user_id(user_id: i32) { // user_idのバリデーションをする処理 } // これは機能的凝集 fn fetch_user(user_id: i32) -\u0026gt; User { // user_idからユーザーを取得する処理 } // これは機能的凝集 fn update_last_login_time(user: User) -\u0026gt; User { // ユーザーの最終ログイン時間を更新する処理 } // これは機能的凝集 fn create_session(user: User) { // セッションを作成する処理 } handle_create_session以外は機能的凝集で、1つの責務に集中している状態。 それぞれが単一の責任のため可読性が高いし、テストもしやすい。\n機能の一部を変更しても他の機能に影響を与えないため、保守性も高い。\nまた、細かく分離されているので再利用もしやすい。\n高凝集のいいところ 単一の責任のため可読性が高い 単一の責任のためテストしやすい 単一の責任のため保守性が高い(メンテナンス性が高い) 単一の責任のため再利用性が高い 結合度 モジュール同士がどれだけ強く依存しているかの度合い\n結合度にもレベルがある。(レベルが上がるほど低い)\nLV1. 内容結合(最悪) モジュール同士の結びつきが強い。\nモジュールが別のモジュールの内部にアクセスする状態。\n例えば、\nstruct User { id: i32, name: String, } impl User { pub fn get_name(\u0026amp;self) -\u0026gt; \u0026amp;str { \u0026amp;self.name } } fn update_user_name(user: \u0026amp;mut User, new_name: String) { user.name = new_name; } この例はupdate_user_nameがUserの内部にアクセスしている状態。\nimplにupdate_nameを定義して、update_user_nameをなくすことで内容結合を解消できる。\nLV2. 共通結合 別々のモジュールが同じグローバルの状態に依存している状態。\nグローバル変数の状態によって挙動が変わったりするため、思わぬ挙動を引き起こす可能性 → バグ\nフロントで言うとRedux, Vuexのstoreとかもこれに当てはまるかも。\nLV3. 外部結合 外部の直接的な値ではなく、ルール・フォーマットなどに依存している結合。\nAPIレスポンスや外部のファイルを読むときに発生しやすい。\n// 実務で結構ありそうな形式を再現するためにTypeScriptをここだけ採用 const fetchUser = async () =\u0026gt; { const response = await fetch(\u0026#34;/api/user\u0026#34;); const data = await response.json(); return data.user; // APIのレスポンスのフォーマットに依存している状態 } このコードの場合は、APIのレスポンスのフォーマットに依存している状態。\nレスポンスの形式が変わったり、APIのエンドポイントが変わったりすると、fetchUserのコードも変更する必要がある。\nAPIのレスポンスとUserの構造を変換するための関数を作ることで、外部結合を解消できる。(Factoryパターンなどもこの辺りの解消に役立つ)\nLV4. 制御結合 実行する処理の内容が外部のフラグやモードに依存している状態。\n例えば、\nfn main() { let user = User { id: 1, name: \u0026#34;Alice\u0026#34;.to_string() }; saveUser(\u0026amp;user, true); // 更新 saveUser(\u0026amp;user, false); // 作成 } fn saveUser(user: \u0026amp;User, is_update: bool) { if is_update { // update user } else { // create user } } この例はsaveUserがis_updateという外部のフラグに依存している状態。\n論理的凝集の一種とも言える。\nフラグがさらに増えていくと、なんの処理をするのかがわかりづらくなってしまう\nこの場合はcreateUserとupdateUserの二つの関数に分けることで外部結合を解消できる。\nLV5. スタンプ結合 構造体の一部を用いて処理をしたいのに、全部渡してしまっている状態。\n不要な情報も渡してしまうため、モジュール同士の結びつきが強くなってしまう。\n構造体の構造が変わったときに、必要ないとしても問題がないかを確認しなければならないコストが発生する。\nstruct User { id: i32, name: String, email: String, } fn send_user_email(user: \u0026amp;User) { send_email(user.email, USER_EMAIL_TEXT); } この例は、sendUserEmailがUserの構造体の一部であるemailを使いたいのに、構造体全体を渡してしまっている状態。\nもしUserの構造が変わったときに、sendUserEmailに影響がないかを確認する必要がある。\nsend_user_emailの引数をemail: \u0026amp;strにすることで、スタンプ結合を解消できる。\nLV6. データ結合 引数として必要なデータを渡している状態。 外部から値を渡さなければいけない状態でもっとも結合度が低い状態。\n例えば、\nstruct User { id: i32, name: String, email: String, } fn send_user_email(email: \u0026amp;str) { send_email(email, USER_EMAIL_TEXT); } ただどうしても、emailには依存してしまうため、Userの構造が変わったときに、emailがなくなっていないかを確認する必要がある。\nLV7. メッセージ結合(理想) 引数のないメソッド。(メソッド内でも何にも依存していない)\n低結合のいいところ モジュールが独立する 独立した処理になるのでテストしやすい 独立した処理なので変更がしやすい(保守性が高い) チーム開発しやすい(依存がないので、他の人のコードに影響されない) スケーラビリティが高い(モジュールを追加しても、既存のモジュールに影響がない) 参考 https://zenn.dev/ngs/articles/f3192adc45f11a https://speakerdeck.com/sonatard/coheision-coupling ","date":"2026-05-03","dateDisplay":"2026年5月3日","permalink":"https://phasiblog.netlify.app/posts/20260503_coupling_and_cohesion/","summary":"何回調べても体に染みつきません。書き残すことでできるだけ記憶に残したい。","title":"凝集度と結合度"},{"content":"スタックとヒープ 両方ともメモリの領域のことで、OSによって論理的に領域を分けられ、用途ごとに別々の領域が使われるのようになっている\nざっくり ヒープ:\nよく想像するメモリ 動的に領域を確保できる 番地とセットで扱う(参照渡しとかで渡すメモリ番地はヒープの番地) スタック:\n関数や実行をLIFO形式で管理する領域 関数実行後にどこに戻るかなどを管理できるようにしている 無限ループで関数を実行するとスタックがいっぱいになってエラーになる(スタックオーバーフロー) ヒープ 動的に領域を確保できるメモリ領域。 ただし、動的に領域を確保するので速度はスタックより遅い\n動的に領域を確保し、その番地を変数に格納することで、ヒープの領域を利用できる\n実行時に値が決まるものがヒープに格納されることが多い (例: 長さが変わる配列や、構造体など)\nスタック 関数の実行を管理するためのメモリ領域。 LIFOで関数の実行を管理している。\n関数を読み込んだタイミングで、実行順にスタックに実行コードが積み込まれる\n中に関数が含まれていた場合、それが展開されてスタックに積み込まれる\nまた静的な値はヒープを使わず、スタックに格納されることが多い(厳密には言語による)\n参考 https://doc.rust-jp.rs/book-ja/ch04-01-what-is-ownership.htmll ","date":"2026-05-03","dateDisplay":"2026年5月3日","permalink":"https://phasiblog.netlify.app/posts/20260503_stack_and_heep/","summary":"Rustの学習まとめ","title":"スタックとヒープ"},{"content":"数値型 整数型 整数のデータ型は範囲 + bit数で表される\n範囲は以下の通り\nu(unsigned integer): 0以上の整数(2のn乗-1まで) i(signed integer): 負の数も含む整数(-2のn乗から2のn乗-1まで) bit数は8, 16, 32, 64, 128の5種類がある\nそれを組み合わせて、u32やi64などの表現できる\nもしくは、PCのアーキテクチャに合わせたサイズのisizeとusizeもある\n※ 注意点\nデバッグモードでは範囲を超えた時にエラーになるが、リリースモードでは範囲を超えたときに値が巻き戻る(オーバーフローする)ので注意\n例: u8における256(u8は最大が256)\ndebug: panic!を起こす release: 0として扱われる 浮動小数点型 浮動小数点数のデータ型は似た感じで、f + bit数という表現になる\nf32とf64の二種類のレパートリーになる\nf64が基本でいい(速度に差がないのに精度がいいから)\n真偽値型 真偽値のデータ型はboolで表される\ntrueとfalseの二種類の値を取ることができる\n文字型 1文字を表すデータ型はcharで表される\n文字列は\u0026quot;\u0026quot;で囲うが、charは''で囲う必要がある\n※ 文字列型は上級編で\nタプル型 複数の値をまとめて返すことができるデータ型\nRustは関数の戻り値は1つなので、複数の値を返したいときに便利\n1つのタプル内のデータ型はバラバラでもいい\n// 本来こういうデータは構造体の方がいいけど、例として let result: (u8, f64, bool) = (24, 60.2, false); // 分割代入ができる let (age, weight, has_license) = result; // タプルの要素にアクセスするには、インデックスを使う println!(result.0); // 24 配列型 いわゆる配列のデータ型\n全部の要素は同じデータ型でなければならない\nまた、配列の長さは固定になる(コンパイル時に決まる)\n※ 長さを変えたい場合は、ベクタ型(Vec)を使う(上級編で)\n// 定義方法1-1: 定義時点で配列の長さが5で固定される(型は自動推測) let array1 = [1, 2, 3, 4, 5]; // 定義方法1-2: 型注釈を使って配列の長さを指定する // `[型; 長さ]`という形式で指定する let array2: [u8; 3] = [10, 20]; // 定義した型に対して要素数に過不足はNG // 定義方法2: 一括で同じ値の配列を定義 let array3 = [0; 5]; // 長さ5の配列で、全ての要素が0になる // アクセスはインデックスを使う(0から始まる) array1[0]; // 1 // array1[10]などのようにインデックスは範囲外になると、実行時にエラーになるので注意 // 配列の長さは`len`メソッドで取得できる println!(array1.len()); // 5 参考 https://doc.rust-jp.rs/book-ja/ch03-02-data-types.html ","date":"2026-05-01","dateDisplay":"2026年5月1日","permalink":"https://phasiblog.netlify.app/posts/20260501_rust_types/","summary":"Rustの学習まとめ","title":"【Rust】データ型について(初級)"},{"content":"条件分岐 if式 ifは式である\nifの結果を変数に代入できる\nifの後は()で条件式を括る必要がない\nそれ以外は普通のif文と同じ\nlet age = 24; let age_group = if age \u0026lt; 20 { \u0026#34;未成年\u0026#34; } else if age \u0026lt; 65 { \u0026#34;成人\u0026#34; } else { \u0026#34;高齢者\u0026#34; }; 繰り返し loop式 loopを使用すると無限ループになる\nloopももちろん式である\nlet mut count = 0; let final_count = loop { count += 1; if count == 5 { break count * 2; // breakの後に値を指定することで、loop式全体の値を指定できる } }; breakは一番内側のループを抜ける(外側には影響しないので安心)\nこの特性はloop以外のループ構文でも同様\nwhile loopの条件付きバージョン(もちろん式)\nlet mut count = 0; let final_count = while count \u0026lt; 5 { count += 1; }; for式 いわゆるforで式である\n書き方は\nfor value in iterable { // 繰り返し処理 } let numbers = [1, 2, 3, 4, 5]; for n in numbers { println!(\u0026#34;{}\u0026#34;, n); } 参考 https://doc.rust-jp.rs/book-ja/ch03-05-control-flow.html ","date":"2026-04-29","dateDisplay":"2026年4月29日","permalink":"https://phasiblog.netlify.app/posts/20260429_rust_flows/","summary":"Rustの学習まとめ","title":"【Rust】制御フローの書き方"},{"content":"Flyweightパターン 概要 共通部分を切り出して、同じものを使い回すことで、メモリ使用量を減らすパターン(正規化と似ている)\n例 bad\ntype Tree = { position: { x: number; y: number }; color: string; length: number; } // 大量の木を生成 const tree1 = { position: { x: 1, y: 2 }, color: \u0026#39;green\u0026#39;, length: 10, }; const tree2 = { position: { x: 1, y: 2 }, color: \u0026#39;green\u0026#39;, length: 10, }; //... colorやlengthが同じ値を持っているが、それぞれの木で同じ値を持っているため、メモリの無駄遣いになっている\ngood\ntype TreeType = { color: string; length: number; } type Tree = { position: { x: number; y: number }; type: TreeType; } const oakType = { color: \u0026#39;green\u0026#39;, length: 10, } const tree1 = { position: { x: 1, y: 2 }, type: oakType, }; const tree2 = { position: { x: 1, y: 2 }, type: oakType, }; //... 使い所 メモリ使用量を減らしたいとき 繰り返しの多いデータが大きいほど効果が大きい(当たり前) 注意点 共有部分を切り出すと、コードが複雑になる可能性がある データが追いづらくなったり、変更が難しくなったりする可能性がある 参考 https://refactoring.guru/ja/design-patterns/flyweight ","date":"2026-04-29","dateDisplay":"2026年4月29日","permalink":"https://phasiblog.netlify.app/posts/20260429_design_pattern_flywegith/","summary":"デザインパターンを復習 + 言語化してみた→Flyweightパターン","title":"【復習デザインパターン】Flyweightパターン"},{"content":"Singletonパターン 概要 そのクラスのインスタンスが1つしか存在しないことを保証するパターン\n例 クラスでの例\nclass DBConnection { private static instance: DBConnection | null = null; private constructor() { // プライベートコンストラクタ } public static getInstance(): DBConnection { if (!DBConnection.instance) { DBConnection.instance = new DBConnection(); } return DBConnection.instance; } } 関数型での例\nconst getDBConnection = (() =\u0026gt; { let connection: DBConnection | null = null; return () =\u0026gt; { if (!connection) { connection = new DBConnection(); } return connection; }; })(); Good インスタンスが1つしか存在しないことを保証できる リソースの節約ができる グローバルにアクセスが可能 More グローバルで状態を持つため、テストがしづらい 依存関係が隠れやすい マルチスレッドの時に、複数のインスタンスが生成される可能性がある 使い所 フロントエンドでグローバルな状態を定義するとき エッジ環境(独立した環境)で、グローバルな状態を定義するとき(DB接続など) Logger, 環境変数取得, DB接続など 注意 デメリットも多いため、使う時は本当に必要かを考える必要がある DIやContextなどの他のパターンで代替できないかを考えると良いかも\n参考 https://refactoring.guru/ja/design-patterns/singleton ","date":"2026-04-24","dateDisplay":"2026年4月24日","permalink":"https://phasiblog.netlify.app/posts/20260424_design_pattern_singleton/","summary":"デザインパターンを復習 + 言語化してみた→Singletonパターン","title":"【復習デザインパターン】シングルトンパターン"},{"content":"関数 書き方 golang + tsっぽい書き方の印象があります(結局よくある形)\n変数名と同じく関数名はスネークケースで書くのが推奨らしい\n// 引数・戻り値なし(厳密には違うけどそれは後述する) fn main() { // 処理 } // 引数・戻り値あり fn add_num(a: i32, b: i32) -\u0026gt; i32 { a + b // rubyと同じで末尾のreturnは省略することができる } 式 or 文 前提: 言語に問わず共通概念として\nその関数が式の時、その関数の呼び出しは値を持つ その関数が文の時、その関数の呼び出しは値を持たない その中で値を持たないという表現方法が言語によって異なってくる\nTSではjsに型制約がないから、とりあえず値として使えないようにする → void\nRustでは()型を返すことで、値を持たないことを表現する → ()\n()型はunion型と呼び、その値しか持たない型のことを指す\n// これは`文` fn main() { // 処理 // 実質的に`()`がreturnされる } // これは`式` fn add_num(a: i32, b: i32) -\u0026gt; i32 { a + b } 参考 https://doc.rust-jp.rs/book-ja ","date":"2026-04-23","dateDisplay":"2026年4月23日","permalink":"https://phasiblog.netlify.app/posts/20260423_rust_func/","summary":"Rustの学習まとめ","title":"【Rust】関数の書き方"},{"content":"1. コメント jsとかと同じ感じで良くある形\n// これがコメントになります 2. 変数 変数(定数)の定義にはletを使います\nletの後にmutをつけるとそれが変数になります\nlet単体だと定数です\nlet x = 1; x = 2; //←これはエラーになる let mut y = 1; y = 2; //←これはOK 再定義することで完全に上書きすることができる(それまでの値は破棄される)\nそれをシャドーイングと呼ぶ\nmutと違ってスコープ外から変に値が変更されないという嬉しいポイントがある\nlet x = 1; let x = x + 1; println!(x); // 2 { let x = x + 1; println!(x); // 3 } println!(x); // 2 3. 定数 jsと同じ感じでconstを使って定義する\nconstには型を明示的に指定してあげる必要があるのに注意\nconst MAX_LENGTH: u32 = 100; (慣習的に大文字スネークケースである(他の言語と一緒))\n4. 不変変数と定数の違い letで定義できる不変変数とconstで定義できる定数の違いは以下の通り (tsとかだとconstで表現して明示的に大文字スネークケースにして使い分けてるけど、rustだと用意されたもので使い分けれるのでいいね)\n値が決まるタイミングが違う 不変変数: 実行のタイミングで確定する 定数: コンパイル時に確定する 型指定 不変変数: 不要(コンパイラが勝手に推測してくれる) 定数: 必須 再定義(シャドーイング) 不変変数: できる 定数: できない 参考 https://doc.rust-jp.rs/book-ja ","date":"2026-04-19","dateDisplay":"2026年4月19日","permalink":"https://phasiblog.netlify.app/posts/20260419_rust_var/","summary":"Rustの学習まとめ","title":"【Rust】変数定義の書き方"},{"content":"前置き これは個人的なデザインパターンの学習ログです わかりづらいかもしれませんが、万人が理解できるように書いていないのでご了承ください\n概要 同じ目的だけどやり方がいくつかある場合に、やり方を切り替えられるようにするパターン\nお会計をするときに支払い方法という共通の目的でもやり方はいくつかあるが、それらを切り替えられるようにするイメージ\n現金 クレカ QRコード 例 Bad 支払い方法に応じて条件分岐しちゃう\nconst pay = (way: \u0026#39;cash\u0026#39; | \u0026#39;card\u0026#39; | \u0026#39;qr\u0026#39;, price: number) =\u0026gt; { if (way === \u0026#39;cash\u0026#39;) { // 現金で支払う処理 } else if (way === \u0026#39;card\u0026#39;) { // クレカで支払う処理 } else if (way === \u0026#39;qr\u0026#39;) { // QRコードで支払う処理 } } Good type PayStrategy = (price: number) =\u0026gt; void const payByCash: PayStrategy = (price) =\u0026gt; { // 現金で支払う処理 } const payByCard: PayStrategy = (price) =\u0026gt; { // クレカで支払う処理 } const payByQr: PayStrategy = (price) =\u0026gt; { // QRコードで支払う処理 } このように方法(Strategy)を分けて定義すると以下のように、支払い方法を切り替えやすくなる\nconst pay = (payStrategy: PayStrategy, price: number) =\u0026gt; { payStrategy(price) } また、同じ支払い方法を固定で使い続けようとする場合以下のようにもできる(context)\nconst generatePayContext = (payStrategy: PayStrategy) =\u0026gt; (price: number) =\u0026gt; { payStrategy(price) } const payByCashContext = generatePayContext(payByCash) payByCashContext(1000) // 現金で1000円支払う Bridgeパターンとの違い 目的が違う Strategyパターン: 同じ目的だけどやり方がいくつかある場合に、やり方を切り替えられるようにするパターン\nBridgeパターン: 変化する可能性がある2つの軸を分離するパターン\n(関数型だとより同じに見えやすいが)\n見分け方 Strategy: 1つアルゴリズムを選ぶだけ\nBridge: 2つの軸を組み合わせる(n x mが実現できる)\n参考 https://refactoring.guru/ja/design-patterns/strategy ","date":"2026-04-18","dateDisplay":"2026年4月18日","permalink":"https://phasiblog.netlify.app/posts/20260418_design_patter_strategy/","summary":"デザインパターンを復習 + 言語化してみた→Strategyパターン","title":"【復習デザインパターン】ストラテジーパターン"},{"content":"Adapterパターン 概要 インターフェースの違うオブジェクトを繋ぎ合わせるパターン\n例 VanillaShake\ninterface VanillaShake { eat(): void; } Drink\ninterface Drink { drink(): void; } haveMeals\nconst haveMeals = (food: Food, drink: Drink) =\u0026gt; { food.eat() drink.drink() } この引数に直接VanillaShakeを渡すことはできない\nvanillaShakeAdapter\nconst vanillaShakeAdapter = (vanillaShake: VanillaShake) =\u0026gt; ({ drink: () =\u0026gt; vanillaShake.eat() }) このメソッドにより、インターフェースの違うVanillaShakeをDrinkとして扱えるようになる\nhaveMeals(food, vanillaShakeAdapter(vanillaShake)) 使い所 すでに出来上がっていて変更コストが高いメソッドやクラスを別のインターフェースに当て嵌めたい時 外部ライブラリなどで本体のコードを触りづらい時 Bridgeパターン Adapterは2つの異なるinterfaceを繋げるパターン。\nしかし、Bridgeパターンは処理の中身を外から注入するパターン\nBridgeを使わないと以下のようになってしまう\n// リモコン const tvController = { sendIr: () =\u0026gt; { console.log(\u0026#34;IR signal sent\u0026#34;) // 赤外線を送る処理 }, turnOn: () =\u0026gt; { sendIr() console.log(\u0026#34;turn on tv\u0026#34;) } } // 物理スイッチ const tvSwitch = { turnOn: () =\u0026gt; { console.log(\u0026#34;turn on tv\u0026#34;) } } const radioController = { sendIr: () =\u0026gt; { console.log(\u0026#34;IR signal sent\u0026#34;) // 赤外線を送る処理 }, turnOn: () =\u0026gt; { sendIr() console.log(\u0026#34;turn on radio\u0026#34;) } } const radioSwitch = { turnOn: () =\u0026gt; { console.log(\u0026#34;turn on radio\u0026#34;) } } 実行命令を送る方法(リモコンや物理スイッチ)が増えるとデバイス分の命令方法の定義が必要になる デバイスが増えると、同じような命令方法でも再度定義が必要になる\nデバイスの動作(機能)と命令方法(実装)を分離して、命令にを外から注入するようにすれば、デバイス x 命令の定義が必要なくなる\ninterface Device = { turnOn: () =\u0026gt; void; } const tv: Device = { turnOn: () =\u0026gt; { console.log(\u0026#34;turn on tv\u0026#34;) } } const radio: Device = { turnOn: () =\u0026gt; { console.log(\u0026#34;turn on radio\u0026#34;) } } const createController = (device: Device) =\u0026gt; ({ turnOn: () =\u0026gt; { console.log(\u0026#34;IR signal sent\u0026#34;) // 赤外線を送る処理 device.turnOn() } }) const createSwitch = (device: Device) =\u0026gt; ({ turnOn: () =\u0026gt; { device.turnOn() } }) const tvController = createController(tv) const tvSwitch = createSwitch(tv) const radioController = createController(radio) const radioSwitch = createSwitch(radio) 参考 https://www.techscore.com/tech/DesignPattern/Adapter/ https://refactoring.guru/ja/design-patterns/adapter ","date":"2026-04-09","dateDisplay":"2026年4月9日","permalink":"https://phasiblog.netlify.app/posts/20260408_design_patter_adapter/","summary":"デザインパターンを復習 + 言語化してみた→Adapterパターン","title":"【復習デザインパターン】アダプタパターン・ブリッジパターン"},{"content":"概要 ハッシュ化 = 復元できないように値を変換すること\n暗号化 = 鍵を使って内容を読めなく変換するが、その鍵で復元ができる\nハッシュ化 ハッシュ関数を通して別の値に変換すること\n非可逆なのでパスワードに使う\n暗号化 鍵を使って特定の値を読めないように変換すること\n鍵があれば読めない値を読める値に変換できる\n","date":"2026-04-07","dateDisplay":"2026年4月7日","permalink":"https://phasiblog.netlify.app/posts/20260407_secret_vs_hash/","summary":"そういえば、ハッシュ化と暗号化の違いってなんだっけ？ってなったので備忘録として残す","title":"ハッシュ化と暗号化の違い"},{"content":"登場人物(?) Iterator 要素を順番にアクセスするためのオブジェクト\n最低限以下の要素が必要\n次の要素が存在するか 次の要素が何か Aggregate(Iterable) Aggregate内の要素を順番にアクセスするためのIteratorを生成するためのオブジェクト\n概要(ざっくりイメージ) Aggregator内の要素を順番に取り出すためのメソッドがIterator\nIterator Iteratorには、以下の二つを持つオブジェクトである必要がある\n次の要素が存在するか 次の要素が何か dartでの例\nclass Iterator\u0026lt;T\u0026gt; { bool hasNext() { // 次の要素が存在するか } \u0026lt;T\u0026gt; next() { // 次の要素が何か } } Iteratorはこれだけを提供する\nhasNextやnextのロジックはなんでもいい\n(hasNextやnextのメソッド名は言語によって変わるため注意)\ndartのclassで実装しているが、 jsのオブジェクトでもいい。\nとにかくこの2種類のメソッドを提供するオブジェクトであれば、Iteratorと呼べる\nAggregator Aggregator自身が持ってる要素に順番にアクセスするためのIteratorを生成するためのオブジェクト\n内部構造を隠して、Iteratorを生成して返すためのメソッドを提供する\n(中身が配列じゃなくても、Iteratorを生成して返すことができる)\n(呼び出し側は気にしない)\nclass Aggregator\u0026lt;T\u0026gt; { List\u0026lt;T\u0026gt; items; Iterator\u0026lt;T\u0026gt; createIterator() { // Iteratorを生成して返す return Iterator\u0026lt;T\u0026gt;(items); } } 具体例 宝くじ(Lottery)で例える\nclass Lottery {} Iteratorは購入者に対して宝くじを返すためのオブジェクト(定員さん)\nclass LotteryStaff { List\u0026lt;Lottery\u0026gt; lotteries; LotteryStaff(this.lotteries); bool hasNext() { // 次の宝くじが存在するか } Lottery next() { // 渡す宝くじがどのくじか // くじの山から上から取ってもいいし、下からとってもいい(自由に差し替えられる) } } Aggregateは宝くじ売り場\n宝くじがたくさん用意されている 定員さんがいる(Iterator) class LotteryShop { List\u0026lt;Lottery\u0026gt; lotteries; LotteryStaff staff; LotteryShop(this.lotteries) { staff = LotteryStaff(lotteries); } LotteryStaff createIterator() { // 定員さんを生成して返す return staff; } 使い所(まとめ) 基本的には配列などのコレクションで十分だが、\n取り出し方を工夫したい時 や それを共通化したい時\nには役に立ってくれるだろう\n参考 https://www.techscore.com/tech/DesignPattern/Iterator/Iterator1 ","date":"2026-03-31","dateDisplay":"2026年3月31日","permalink":"https://phasiblog.netlify.app/posts/20260331_design_pattern_iterator/","summary":"デザインパターンを復習 + 言語化してみた→イテレータパターン","title":"【復習デザインパターン】イテレータパターン"},{"content":"はじめに 前回の記事の続きの記事になります\nマニフェストファイル リソース 14までは前回記事をご覧ください\n15. PodDisruptionBudget(PDB) 対象のPodが最低限起動していることを保証するリソース\nkubctl drainなどによってPodが一気に消えるケースがあり、Podが消えすぎないようにするためのリソース\n16. Pod Podを定義するためのリソース\n基本的には直接使うことはあまりない\nDeployment, StatefulSet, DaemonSetなどの振る舞いも含まれた上位互換のリソースがあるため\n17. ReplicaSet Podを複数起動するためのリソース\n基本的には直接使うことはあまりない\nDeployment, StatefulSet, DaemonSetなどのローリングアップデートなど細かい振る舞いも含まれた上位互換のリソースがあるため\n18. HeadlessService ServiceにおけるClusterIPの亜種\n普通のServiceのClusterIPは、ClusterIP(仮想のIP)を割り当てて、Serviceの対象になるPodのどれかにリクエストを振り分けるロードバランシングを行う\nHeadlessServiceは、仮想のIPを持たずに、実際にServiceの対象になるPodにIPを割り当てる\nStatefulSetなどのロードバランシングされたくないPodに対して利用されることが多い\nHelm Clusterの動作を支えているものを深ぼっていく\n1. 概念 機能は大きく3つ\nGomplateを用いたk8sのマニフェストをテンプレートとして扱える(外から埋め込める値を定義できる) k8sのマニフェストの塊をパッケージ化して管理できる パッケージ単位でリリース管理できる 2. Chart k8sのマニフェストのパッケージのことを指す\n3. Values Chartのテンプレートに埋め込む値を定義するためのファイル\n4. Namespace k8sのリソースをグルーピングするための概念\n別々のNamespaceに同じ名前のリソースを作成することができる\nまた、別のNamespaceのリソースに干渉することはできない\n5. Release Chartを丸ごとリリースすることを指す\n6. Helm Hooks Chartの中で、特定のタイミングで実行されるリソースを定義できる\n例えば、ローリングアップデートの前に実行されるリソースを定義することができる\n参考 https://qiita.com/reoring/items/82f023e387d038c07e0f https://qiita.com/yuta_vamdemic/items/4f21fc955c0ced6f33d6 https://qiita.com/goroneko/items/ab451647b7fa5acd1b80 ","date":"2026-03-14","dateDisplay":"2026年3月14日","permalink":"https://phasiblog.netlify.app/posts/20260314_k8s_init_3/","summary":"k8sのそもそもの概念を自分なりにまとめてみた v3","title":"k8sざっくり入門(3)"},{"content":"はじめに 注意: これは2026/03/13時点の内容です。すでに古くなってる可能性はあります。\nClaudeとCodexの両刀使いとなったわたくしは、AI関連のファイルをできるだけいろんなAIから参照しやすいように共通化する方法を考えていました。\nCLAUDE.mdとAGENTS.mdもその一つで共通のファイルを作ってシンボリックリンク経由で参照するという方法を行った。\nしかしskillsに関してはその方法が通じない。その苦悩を記す。\nディレクトリのシンボリックリンクは辿れない CLAUDE.mdなどの場合はシンボリックリンクは正常に動作しますが、skillsに関してはディレクトリのため、うまく認識できませんでした。\nこの現象はClaudeでもCodexでも同じ。\nClaude CodeとCodexのSkillsの置き場所が違う claude code: ./.claude/skills/ codex: ./codex/skills/ or ./.agent/skills/ 同じ中身をコピーしないとうまく実現できないです。 結構不便。\n思うこと SKILLSの規格は揃えてるんだったら、その置き場所も含めて揃えてほしい。\nあと一歩惜しいから不便なんだよな。\n参考 https://code.claude.com/docs/ja/overview https://developers.openai.com/codex/skills/ ","date":"2026-03-13","dateDisplay":"2026年3月13日","permalink":"https://phasiblog.netlify.app/posts/20260313_init_commonly_skills/","summary":"20260313時点ではCodexとClaudeの両方でskillsを使えるように共通化するのは難しい","title":"Agent SkillsをいろんなAIで使えるようにするための壁"},{"content":"はじめに 前回の記事の続きの記事になります\nマニフェストファイル リソース 1~9は前回記事をご覧ください\n10. ConfigMap Podに対して設定値(設定ファイル)を提供するためのリソース\nDeploymentなどのリソースからConfigMapをvolumeとしてmountして利用されることが多い\n11. Secret ConfigMapと似ているが、機密情報をPodに提供するためのリソース\nほとんど同じだが設計上区別することが多い。\nあとは標準出力で隠されるなどの違いもある\n12. PersistentVolume Podに対して永続的なストレージを提供するためのリソース\n利用の際はPersistentVolumeClaimを利用してmountされる\nStorageClassに要求するストレージなどを設定できる\n13. StorageClass PersistentVolumeが何をもとに作成されるかを定義するためのリソース\n14. PersistentVolumeClaim PersistentVolumeを利用するためのリソース\nPersistentVolumeへ要求するストレージやポリシーを設定できる\n(備考: StatelfulSetには勝手にPersistentVolumeやPersistentVolumeClaimが作成される)\nk8sの根幹 Clusterの動作を支えているものを深ぼっていく\nControl Plane Clusterの中を管理する司令塔\nMaster Node (Control Plane Node←こっちが最近の呼び方らしい)\nControl Planeが動いているNodeを指す\nWorker Node Podが動いているNodeを指す 通常のNodeはこいつのことを指してる\nkubelet Worker Nodeに常在するPodをコントロールするControl Planeの派遣隊\nPodの監視、Podの起動や停止などを行う\nまた、現状をControl Planeに報告する役割も担う\nPodの機能 Probe(プルーブ) Pod内のコンテナ内の状態をkubeletが監視するための機能\nReadiness Probe コンテナがリクエストを受け付ける準備ができているかを監視するための機能\n失敗したらkubeletはそのコンテナをServiceの対象から外す(Clusterネットワークから隔離する)\nLiveness Probe コンテナが起動しているかを監視するための機能\n失敗したらkubeletはそのコンテナを再起動する\nStartup Probe 起動に時間がかかるコンテナの起動を監視するための機能\n起動が終了するまで他のProbeの動作を止めることができる\n(起動に時間かかってLiveness Probeが失敗してしまうケースを防止するための機能)\n参考 https://qiita.com/oguogura/items/68741b91b70962081504 https://zenn.dev/hono8944/articles/kubernetes-secret-intro#configmap-vs-secret https://kubernetes.io/ja/docs/concepts/storage/storage-classes/ https://qiita.com/ohtsuka-shota/items/f7c9e0cc603bf50f655f ","date":"2026-03-06","dateDisplay":"2026年3月6日","permalink":"https://phasiblog.netlify.app/posts/20260306_k8s_init_2/","summary":"k8sのそもそもの概念を自分なりにまとめてみた v2","title":"k8sざっくり入門(2)"},{"content":"はじめに そもそもEBSについて\n詳細 EBS EC2内で利用できるブロックストレージサービス\nブロックストレージサービスとは、容量を増やしていく系のストレージではなく、ブロックを付け加えていくサービス\n複数のEC2間での共有はできない\nUSBメモリのようなイメージ\nEFS EC2内で利用できるファイルストレージサービス\nファイルストレージサービスとは、ファイル単位で保存するストレージサービス\n複数のEC2間での共有が可能\nオンプレのNASのようなイメージ\nS3 S3ともごっちゃになりそうなので、S3ができることを改めて整理\nオブジェクトストレージと呼ばれ、オブジェクト単位で保存するストレージサービス\nオブジェクトの中の一部の変更はできない\nHTTP経由で直接オブジェクトを取得できる\n参考 https://qiita.com/yoneyama_g/items/8db74f462b0cb7e8e621 https://zenn.dev/junc/articles/4aef12f12cd2ee ","date":"2026-03-03","dateDisplay":"2026年3月3日","permalink":"https://phasiblog.netlify.app/posts/20260303_ebs_efs/","summary":"EBS/EFSについて知らなかったので、調べてみた。","title":"AWSのEBS/EFS入門"},{"content":"はじめに そもそもk8sは概念が難しい\n勉強会で複数回説明を聞いてやっと腑に落ちたので、脳内の整理のために自分なりにまとめてみる\nk8sの概念 種類 Cluster Master Node Node Pod 1. Cluster typoに注意(clustorではなくcluster)\nk8sの一連の塊を指す\nk8sの中で一番大きな概念\n2. Master Node k8sのNodeやPodの管理を司るNode\nPodやNodeの数の増減やそれ以外の包括的な管理を行うNode\nAWSのEKSでは基本的にはデフォルトで用意されているため、特に設定は不要\n3. Node Podの実行を行うマシンのことを指す\nAWSのEKSではEC2インスタンスのことを指す\n4. Pod コンテナの集合体のことを指す\n複数のコンテナのまとまりを指す(docker-composeにイメージが近い)\n起動も停止も一心同体にしたいものをPodにまとめると良い\nそうでないケースは1つのPodに1つのコンテナを配置する方がいい\nマニフェスト マニフェストファイルとは 宣言的にNodeの状態やPodの状態を定義できるファイル\n設定内容のリソース(kind)を指定して、細かく設定を記述していく\n代表的なリソース 1. Deployment どこNodeでもいいからPodを起動してくれるリソース\n逆にどのNodeでPodが起動するかわからない\n(Node内に複数のPodが立ち上がるケースがある)\n2. DemonSet 1つのNodeに必ず1つのPodを起動してくれるリソース\nNodeが立ち上がったら、まずこのリソースのPodが優先的に立ち上がるようになってる\n3. StatefulSet StatefulなPodを立ち上げる\nそのPodの中のVolumeはPodが削除されても残る(再度同じPodを立ち上げるときに同じVolumeをマウントすることができる)\n4. Service Podの通信を管理するリソース\nいくつか種類がある\nClusterIP: クラスター内で通信のために公開する NodePort: クラスター外から通信のために公開する LoadBalancer: クラスター外から通信のために公開する(AWSのALBなどの外部のロードバランサーと連携して公開する) ExternalName: ? 5. HorizontalPodAutoscaler Podの数を自動で増減させるリソース\nPodのコントロールをするリソースなのではなく、DeploymentなどのPodの数の設定値を自動で増減させるリソース\n(Podのコントロールをするわけでないので注意)\n6. ConfigMap Podの中の設定ファイルを管理するリソース\n7. Secret Podの中の非公開の設定ファイルを管理するリソース\n8. Ingress Podへの外部からのアクセスを管理するリソース\n外部とServiceをつなぐ役割を持つリソース\n9. Pod Disruption Budget Deploymentで定義されたPodの立ち上がる最低の数(これ以上は少なくなれない数)を定義するリソース\nPodの数がこの数と一致すると、Podの削除などができなくなる\n出典 https://qiita.com/tadashiro_ninomiya/items/6e6fea807b2a16732b5b https://zenn.dev/sasakiki/articles/a71d9158020266 ","date":"2026-03-03","dateDisplay":"2026年3月3日","permalink":"https://phasiblog.netlify.app/posts/20260303_k8s_init/","summary":"k8sのそもそもの概念を自分なりにまとめてみた","title":"k8sざっくり入門"}]