株式会社豆蔵のブログ - TECH PLAY

TECH PLAY

株式会社豆蔵

株式会社豆蔵 の技術ブログ

110

はじめに # 本記事では、GitHub Copilotのエージェント(Agents)およびインストラクション(Instructions)の設定方法について説明します。 Agents(エージェント)とは 特定のタスクや分野に特化した専門家としてCopilotをカスタマイズする機能です。 たとえば、バックエンド開発用、フロントエンド開発用など、異なる専門性を持つ複数のエージェントを定義し、状況に応じて使い分けることができます。 Issueにアサインしたり、VS Code上で選択して利用します。 Instructions(インストラクション)とは Copilotに対する共通のルールや制約を定義する機能です。 コーディング規約、命名規則、プロジェクト固有のベストプラクティスなどを記載し、すべての開発者が一貫したコード生成の支援を受けられるようにします。 エージェントと併用され、VS CodeでのコーディングやPull Requestのレビューなど、あらゆる場面で適用されます。 適用順序 # 以下の順序でルールが適用されます。競合するルールがある場合、数字の小さいルールが優先されます。 選択したエージェント(例: agents/backend.agent.md ) マッチするインストラクション(例: instructions/typescript.instructions.md ← applyToパターンに一致) 全体のインストラクション( copilot-instructions.md ) ファイルの配置 # GitHub Copilotが認識できるよう、下記のように配置します。 .github/ agents/ xxx.agent.md : 特定の分野(ロールなど)に合わせて定義するエージェントファイル(e.g. backend, frontend, test) copilot-instructions.md : 全体に適用されるルールや制約を定義するファイル instructions/ xxx.instructions.md : 特定の分野(テクノロジーなど)に合わせて定義するファイル。(e.g. typescript, python, react)※サブフォルダーで分類したくなりますが、フォルダー分けすると読み込まれません。 --> Caution AGENTS.mdについて .github/AGENTS.md (ディレクトリ直下)は GitHub CLI用 のファイルです。 VS Codeでは読み込まれませんので注意してください。 VS Codeでは agents/ ディレクトリ内の *.agent.md ファイルのみが有効です。 --> Information ワークスペースでの配置 VS Codeでマルチリポジトリ(複数のリポジトリを同時に開いて作業)する場合、 設定ファイルは ワークスペースのルートディレクトリ の .github/ に配置する必要があります。 各リポジトリに個別の設定を使いたい場合は、リポジトリごとに別のVS Codeウィンドウで開いてください。 .github/agents/sample.agent.md : ワークスペースルートに配置すると選択できます repo-A/.github/agents/sample.agent.md : 各リポジトリ配下のエージェントは読み込まれません repo-B/.github/agents/sample.agent.md ヘッダー部の用途 # 定義ファイルのヘッダー部に設定できるプロパティの一部を紹介します。 エージェント --- name: Backend Agents(TypeScript) description: This custom agent implements backend features using TypeScript. model: GPT-5.2 --- ※エージェント選択画面(VS Code) プロパティ 設定時 未設定時 name エージェント名として使用 拡張子を除いたファイル名をエージェント名として使用 description エージェントの説明として使用 空欄 model 使用するAIモデルを指定 デフォルトモデル インストラクション --- applyTo: "src/**/*.ts" # e.g. src配下のtsファイルを対象 --- プロパティ 設定時 未設定時 applyTo 指示を適用するファイルのパターンを指定(globパターン) すべてのファイルに適用 --> Information applyToの指定例 **/*.ts - すべてのTypeScriptファイル src/** - srcディレクトリ配下のすべてのファイル **/*.{js,ts} - JavaScriptとTypeScriptファイル 定義例 # エージェントおよびインストラクションの定義例を以下に示します。 これらを組み合わせることで、プロジェクトやタスクに最適化されたCopilotの動作を実現できます。 エージェント:バックエンド開発者 # .github/agents/backend-specialist.agent.md --- name: Backend Developer Agent description: NestJSを使用したバックエンド開発の専門家 --- # 役割 あなたはNestJSとTypeScriptを使用したバックエンド開発の専門家です。 # 技術スタック - **フレームワーク**: NestJS 11.x - **言語**: TypeScript 5.x - **データベース**: PostgreSQL - **ORM**: TypeORM - **テスト**: Jest # コーディング規約 - ヘキサゴナルアーキテクチャを遵守してください - DTOには必ずバリデーションデコレータを付与してください - 例外処理は適切なHTTPステータスコードを返すカスタム例外を使用してください # テスト方針 - 単体テストはすべてのServiceクラスに対して作成してください - テストカバレッジは80%以上を目標としてください 全体インストラクション:プロジェクト共通規約 # .github/copilot-instructions.md # コーディング規約 ## 共通ルール - **言語**: 日本語でコメントとドキュメントを記載してください - **命名規則**: - クラス名: PascalCase - 関数名・変数名: camelCase - 定数: UPPER_SNAKE_CASE - **インデント**: スペース2文字 - **文字列**: シングルクォートを使用 ## 禁止事項 - `any`型の使用は原則禁止(型定義を適切に行うこと) - `console.log`のコミットは禁止(ロガーを使用すること) - 機密情報のハードコードは厳禁 ## セキュリティ - 外部入力は必ずバリデーションを行うこと - SQLインジェクション対策を実施すること - 認証・認可が必要なエンドポイントにはガードを設定すること 分野別インストラクション:TypeScript専用ルール # .github/instructions/typescript.instructions.md --- applyTo: "**/*.ts" --- # TypeScript固有のルール ## 命名規則 - ファイル名: kebab-case ## 型定義 - 明示的な型注釈を優先してください - Utility Typesを活用してください(`Partial`, `Pick`, `Omit`など) - 複雑な型は`type`エイリアスで定義してください ```typescript // Good type UserProfile = { id: string; name: string; email: string; }; type UserProfileUpdate = Partial<Pick<UserProfile, 'name' | 'email'>>; // Bad const updateUser = (data: any) => { ... }; ``` ## 非同期処理 - `async/await`を使用してください(Promiseチェーンは避ける) - エラーハンドリングは`try-catch`で行ってください ## インポート順序 1. 外部ライブラリ 2. 内部モジュール(絶対パス) 3. 相対パス ```typescript // 外部ライブラリ import { Injectable } from '@nestjs/common'; import { Repository } from 'typeorm'; // 内部モジュール import { UserEntity } from '@/entities/user.entity'; import { CreateUserDto } from '@/dto/create-user.dto'; // 相対パス import { UserService } from './user.service'; ``` 運用上の注意事項 # VS Codeでのキャッシュ管理 # エージェントやインストラクションのファイルを変更した場合、初回ロードした内容がキャッシュされます。 変更を反映するには、以下のいずれかの操作が必要です。 チャットで変更したファイルを明記して再読み込みを促す(例: sample.agent.mdを変更したので再読み込みしてください ) 新しいチャットを開始する VS Codeを再起動する GitHubでのファイルサイズ制限 # エージェントファイルの文字数が30,000文字(バイト数ではなく、ヘッダー部は含まない)を超えると選択できなくなります。 適切な粒度でファイルを分割してください。 GitHub IssueでCopilotをアサイン後に表示されるダイアログ
前回の記事「無料のOSSツールSysONで始めるSysMLv2モデリング(3)〜 Part Definitionの作成」では、Part Definitionを作成しました。 /blogs/2026/01/22/sysmlv2-tool-syson-partdef/ 本記事では、Part Usageを作成します。 本記事で使用する SysONは前回同様、v2025.8.0です。 SysONは現在も進化中ですので最新リリースの挙動とは異なる可能性があります。 ご了承ください。 モデリングの題材は、SysMLv2の仕様書 A Annex: Example Modelから拝借します。 "Figure 63. Variant engine4Cyl"を作成してみましょう。 新規のPart Usageを作成する # General Viewを右クリックして表示されるコンテキストメニューから "Structure" > "New Part"を選択すると、General Viewに "part1"が追加されます。 要素を追加する方法はもう1つあります。 左サイドバーのツリーでパッケージなどの要素の右にあるケバブアイコン(︙)をクリックします。 表示されたダイアログで Partを選択し、"CREATE"ボタンを押下することで指定した要素の中に新たな要素を追加できます。 追加した要素を General Viewにドラッグ&ドロップすれば、グラフィカル記法で表示できます。 Part DefinitionとPart Usageの間にdefinitionを作成する # 前回の記事の手順でPart Definitionを作成し、"Engine"に名前を変更します。 次に、Part Usageを作成し、"engine"に名前を変更します。 "engine"を選択し、4つの辺の外に表示された三角(>)を"Engine"までドラッグ&ドロップすると、コンテキストメニューが表示されます。 コンテキストメニューで"New Feature Typing"を選択すると、Part DefinitionとPart Usageの間にdefinitionを作成できます。 definitionは白抜き三角と2つの点が付いた線であらわします。 もう1セット、Part Definitionの"Cylinder"と Part Usageの"cylinders"も作成しましょう。 Part Usage間にcomposite-feature-membershipを作成する # "engine"と"cylinders"間にcomposite-feature-membershipを作成します。 "engine"を選択し、4つの辺の外に表示された三角(>)を"cylinder"までドラッグ&ドロップし、コンテキストメニューを表示します。 コンテキストメニューで"Add as nested Part"を選択すると、Part Usage間にcomposite-feature-membershipを作成できます。 "cylinders"から"engine"にドラッグ&ドロップの操作をした場合、コンテキストメニューで"Become nested Part"を選択すると同様に作成できます。 左サイドバーのツリー上で、”cylinders”を"engine"にドラッグ&ドロップすることによっても作成できます。 composite-feature-membershipは黒塗りひし形の付いた線であらわします。 Part Usage間にnoncomposite-feature-membershipを作成する # "engine"と"cylinders"間のrelationshipをnoncomposite-feature-membershipにします。 noncomposite-feature-membershipはusageが参照的であることをあらわします。 したがって、参照されている側のusageの設定を変更します。 参照されている"cylinders"を選択して、右サイドバーのDetailsにあるAdvancedタグを選択します。 ここにある Is Compositeのチェックを外してください。 すると Is Referenceにチェックが付き、エディタ上の"cylinders"のステレオタイプが"«ref part»"に変わります。 これと共に、"engine"と"cylinders"の間のrelationshipがnoncomposite-feature-membrship(白抜きのひし形)に変わります。 戻す場合は、Is Compositeにチェックを付けます。 UsageにMultiplicityを設定する # ”cylinders”のMultiplicityを"4..8"に設定します。 "cylinders"を選択して、F2キーやEditで直接編集できるようにします。 次に、"cylinders"を"cylinders[4..8]"に変更します。 すると、左サイドバーのツリーの"cylinders"内にMultiplicityRangeが追加されます。 MultiplicityRangeの中にはLiteralIntegerが2つあり、1つのValueは”4”、もう1つは"8"が設定されます。 "cylinders"を編集した際、"cylinders[4..8] : ShapeItems::Cylinder"に変わることがあります。 このとき ShapeItems Libraryの"Cylinder"がdefinitionとして選択されている状態になっています。 この場合は以下の手順で修正できます。 右サイドバーのDetailにある Typed byで設定されている"Cylinder"を削除 左サイドバーのツリーにある"cylinders"内の"FeatureTyping"をモデルから削除 "cylinders[4..8]"と"Cylinder"の間にdefinitionを再作成 Part Usage間にsubsettingを作成する # "engine"と"engine4Cyl"の間にsubsettingを作成します。 Part Usageを作成し、名前を"engine4Cyl"に変更します。 ”engine4Cyl”を選択して外側に表示された三角(>)を"engine : Engine"までドラッグ&ドロップします。 表示されたコンテキストメニューで”New Subsetting”を選択します。 subsettingは白抜き三角が付いた線であらわします。 Part Usage間にredefinitionを作成する # "cylinders[4]"のPart Usageを作成し、"cylinders[4..8]"との間にredefinitionを作成します。 "cylinders[4]"を選択し、外側に表示された三角(>)を”cylinders[4..8]”までドラッグ&ドロップします。 表示されたコンテキストメニューで"New Redifinition"を選択します。 redefinitionは白抜き三角と1本線が付いた線であらわします。 Viewを完成させる # "cylinder1[1]", "cylinder2[1]", "cylinder3[1]", "cylinder4[1]"の4つのPart Usageを作成します。 作成した4つのPart Usageと"cylinders[4]"の間にsubsettingを作成します。 また、先の4つのPart Usageに加えて、"cylinders[4]"と"engine4Cyl"の間にcomposite-feature-membershipを作成します。 "engine4Cyl"と"cylinders[4]"の間のcomposite-feature-membershipを選択します。 右クリックでコンテキストメニューを表示し、”Show/Hide” > "Hide"を選択します。 ”Engine”と"Cylinder"の2つのPart Definitionを(モデルから削除ではなく)ダイアグラムから削除すると、下図のようになります。 題材と「全く同じ」とはいきませんが、等価なモデルが作成できました。 次回予告 # 本記事では、Part Usage要素を作成し、構造をモデル化しました。 次回は、振る舞いのモデル要素である Action Definitionと Action Usageを作成します。
はじめに # 弊社では様々なメーカのロボットを使用してシステムを構築しています。ロボットコントローラとの通信部分は「出来て当たり前」の機能です。ここのインテグレーションコストを抑え、ビジョンやハンドといったシステム固有の機能開発にフォーカスしたいという課題がありました。 一方で、産業用ロボットコントローラのプロトコル仕様はPDFで配布されていることが多く、LLMへの入力にはマークダウン化が必要です。マークダウン化しても理解にはドメイン知識を要したり、Webに活用事例のような情報が少なくLLMの学習データが不足していたりと、別途コンテキストの入力が必要なケースも多いです。 そこで今回、コントローラ通信プロトコルとクライアントの使用方法を Agent Skills として整備し、LLMにコントローラ通信コードを書かせる取り組みを行いました。 今回は安川ロボットのHSES(High-Speed Ethernet Server)プロトコル向けにスキルを作成し、Rust製クライアント moto-hses と組み合わせて検証しました。 通信仕様やクライアントの使用方法をAgent Skillsの形式で提供することで、Webに活用事例がなくてもLLMが適切なコードを生成してくれます。まだまだ内容は成熟していませんが、スキルを活用・改善してゆくことでコントローラとの通信コードはLLMが自動で実装してくれつつあります。また、通信の障害が発生した際にパケットデータと通信プロトコルを照合してデバッグするといった使い方も可能であり、コード生成から保守までLLMへ任せられるようになってきました。 安川電機が提供する標準SDK # 安川電機のロボットコントローラと通信する手段としてメーカからは以下の3つのSDKが提供されています。 項目 MotoCom32 / MotoComES MotoPlus YMConnect 概要 PCからEthernet経由でロボットコントローラへアクセスするための従来型通信SDK。外部PC上で実行。 コントローラ内部で動作するユーザアプリをC言語で開発するための組込みSDK。 MotoComの後継。クロスプラットフォーム対応の新世代通信SDK。外部PC上で実行。 対応OS Windows(32bit/64bit) 専用RTOS(ロボットコントローラ内で動作) Windows 10+ / Ubuntu 22.04+ 対応言語 C / C++ / VB6 / .NET C C++17 / C# (.NET 10) 動作場所 外部PC(ホスト側) コントローラ内(組込み側) 外部PC(ホスト側) 通信方式 Ethernet(TCP/IP) 内部API(コントローラOSと直接連携) Ethernet(TCP/IP) 主な用途 監視・I/O制御・ジョブ起動など外部制御 高速制御・カスタム動作・外部通信タスク 監視・I/O制御・ジョブ起動など外部制御 有償 / 無償 有償(USBドングルによるHWライセンス。実行環境ごとに必要) 有償(開発ライセンスのみ。実行環境は不要) 無償(Apache License 2.0) 特徴 Windows専用、歴史が長く安定だが新機能は更新停止傾向。 最も自由度が高く、リアルタイム処理・外部通信も可能。 マルチプラットフォーム・モダンAPI設計。 配布元 Yaskawa Electric(販売契約が必要) Yaskawa Electric(契約した開発者のみ) GitHub MotoPlusの場合は、コントローラ内部で動作するアプリとPC側の通信クライアントをそれぞれ自身で開発する必要があります。そのため、提供されている通信クライアントとしてはMotoComとYMConnectの2択となります。 YMConnectは比較的最近(2024年)に公開されたSDKです。C++17以降や.NET 10以降を使用可能なモダンなプロジェクトならYMConnectが良さそうですが、既存のレガシーシステムではMotoComを使用し続けているケースも多いのではないでしょうか。YMConnectの活用事例はまだほとんど見かけません。しかし、 YMConnectのDiscussions を見ると少しずつ不具合報告も挙がってきているので、徐々に採用実績も増えてくるのではないかと思います。 一方で安川ロボットのコントローラは High-Speed Ethernet Server (HSES) というサーバー機能を提供しており、通信プロトコルも公開されています( FS100 HSES Manual (PDF) )。 MotoCom(恐らくYMConnectも)はHSESの通信クライアントとして安川から提供されたSDKであり、同等のクライアントは内製することができます。 今回は上位アプリケーションがRustであったこと、レガシーシステムでも使用したいこと、LLM駆動の開発に必要なモックサーバー機能が欲しかったことから、自作したRustクライアントを使用しています。 moto-hses: Rust製HSESクライアント # moto-hses は、安川ロボットコントローラのHSES (High-Speed Ethernet Server) プロトコルに対応したRust製の非同期通信クライアントライブラリです。 --> moto-hses自体もLLMで開発 実はこのクライアント自体もLLMで開発しました。プロトコル仕様PDFをマークダウン化したドキュメントと、リファレンスとなる別言語のクライアントコードをコンテキストとして入力しています。LLMに対するガードレールや自動フィードバックの仕組みを整備しながら開発を進めました。同様のアプローチでC#向けクライアントなども作成できそうです。この開発プロセスについては、機会があれば別の記事で紹介したいと思います。 特徴 # 型安全 : Rustの型システムを活用した安全なAPI設計 非同期処理 : Tokioランタイムを使用した非同期UDP通信 スレッドセーフ : SharedHsesClient による複数タスクからの並行アクセスに対応 テスト容易性 : モックサーバー ( moto-hses-mock ) による統合テストが可能 --> モックサーバーの重要性 安川が提供するロボットシミュレータ(MotoSim EG-VRC)はHSESサーバー機能を有していません。そのため、これまでは実機のロボットコントローラを使用して通信検証する必要がありました。moto-hsesのモックサーバーを使えばローカル環境やCIで通信コードのテストが可能です。ローカルで完結して通信検証できることは、LLMへ自動でフィードバックする仕組みを構築する上でも非常に重要な要素となります。 クレート構成 # クレート 説明 moto-hses-proto プロトコル定義とシリアライゼーション moto-hses-client Tokioベースの非同期UDPクライアント moto-hses-mock テスト用のローカルモックHSESサーバー 対応コマンド # 現在、以下のロボット制御コマンドに対応しており、逐次追加中です。 コマンドNo コマンド名 0x70 アラームデータ読み出し 0x71 アラーム履歴読み出し 0x72 ステータス情報読み出し 0x73 実行中ジョブ情報読み出し 0x75 ロボット位置データ読み出し 0x78 I/Oデータ読み書き 0x79 レジスタデータ読み書き 0x7A〜0x7E 各種変数(B/I/D/R/S型)読み書き 0x82 アラームリセット / エラーキャンセル 0x83 ホールド / サーボON/OFF 0x84 ステップ / サイクル / 連続切替 0x86 スタートアップ(ジョブ起動) 0x87 ジョブ選択 その他、ファイル操作コマンド(削除、保存、一覧取得)や複数データの一括読み書きコマンドにも対応しています。 基本的な使い方 # use moto_hses_client::HsesClient; use moto_hses_proto::AlarmAttribute; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // クライアント作成 let client = HsesClient::new("192.168.0.3:10040").await?; // アラームデータ読み出し let alarm = client.read_alarm_data(1, AlarmAttribute::All).await?; println!("Alarm Code: {}", alarm.code); println!("Alarm Name: {}", alarm.name); // アラームリセット client.reset_alarm().await?; println!("Alarm reset completed"); Ok(()) } Agent Skills によるLLM支援 # Agent Skills は、AIコーディングエージェントに特定のドメイン知識や使用方法を教えるためのフォーマットです。スキルは、SKILL.md(エージェントへの指示)、references/(参考ドキュメント)、scripts/(自動化スクリプト)で構成されます。 今回、moto-hsesを活用するために以下の3つのスキルを作成しました。 スキル 説明 hses-protocol HSESプロトコル仕様。メッセージ構造、コマンドフォーマット、エラーコードなど moto-hses-usage moto-hsesクレートの使用ガイド。クライアント操作、コマンドリファレンスなど hses-packet-analysis HSESパケットの解析ガイド。通信障害時のデバッグに活用 スキルのインストール # 作成したスキルは GitHubリポジトリ で公開しています。Vercelが提供するスキルインストーラー add-skill を使用して、プロジェクトにスキルを導入できます。 # Cursorの場合 npx add-skill masayuki-kono/agent-skills -s hses-protocol moto-hses-usage hses-packet-analysis -a cursor -y # Claude Codeの場合 npx add-skill masayuki-kono/agent-skills -s hses-protocol moto-hses-usage hses-packet-analysis -a claude-code -y インストールすると、プロジェクトに以下のようなディレクトリ構造でスキルが配置されます。 .agents/ └── skills ├── hses-packet-analysis │ └── SKILL.md ├── hses-protocol │ ├── references │ │ ├── data-types.md │ │ ├── error-codes.md │ │ ├── protocol-overview.md │ │ └── ... │ └── SKILL.md └── moto-hses-usage ├── references │ ├── examples │ │ ├── alarm_operations.rs │ │ ├── job_start.rs │ │ ├── read_status.rs │ │ └── ... │ └── protocol-commands.md └── SKILL.md Cursorの場合は .cursor/skills/ 配下にシンボリックリンクが作成され、AIエージェントがスキルを参照できるようになります。add-skillの詳しい使い方については 公式リポジトリ を参照してください。 スキルをインストールすると、AIエージェントがHSESプロトコルを理解し、moto-hsesを使った適切なコードを生成できるようになります。 Agent Skillsを使ったコード生成デモ # スキルの効果を検証するため、Cursor Agentにコードを生成させました。生成したコードは moto-hses-examples リポジトリで公開しています。 生成プロンプト # 以下のシンプルなプロンプトを入力しました。 moto-hsesを使用したRustサンプルアプリケーションを開発してください。アプリ起動時にサーボをONにして、指定したジョブを起動してください。ロボットコントローラのIPアドレスはコマンドライン引数で指定できるようにしてください。 生成されたアプリケーション # 上記プロンプトから、Cursor Agentが以下の機能を持つアプリケーションを自動生成しました。 コマンドライン引数でロボットコントローラのIPアドレスとジョブ名を指定 ロボットコントローラへ接続 サーボをONに設定 指定されたジョブを選択して起動 起動状態を確認して結果を表示 実行例 # # ロボットコントローラ(192.168.0.18)に接続し、ジョブ "TEST" を起動 cargo run -- 192.168.0.18 TEST 実行すると以下のような出力が得られます。 [2026-01-26T21:50:24Z INFO moto_hses_examples] Connecting to robot controller: 192.168.0.18:10040 [2026-01-26T21:50:24Z INFO moto_hses_examples] ✓ Successfully connected to controller [2026-01-26T21:50:24Z INFO moto_hses_examples] Reading initial status... [2026-01-26T21:50:24Z INFO moto_hses_examples] ✓ Status read successfully [2026-01-26T21:50:24Z INFO moto_hses_examples] - Running: false [2026-01-26T21:50:24Z INFO moto_hses_examples] - Servo ON: true [2026-01-26T21:50:24Z INFO moto_hses_examples] - Alarm: false [2026-01-26T21:50:24Z INFO moto_hses_examples] - Error: false [2026-01-26T21:50:24Z INFO moto_hses_examples] Turning servo ON... [2026-01-26T21:50:24Z INFO moto_hses_examples] ✓ Servo ON command sent successfully [2026-01-26T21:50:25Z INFO moto_hses_examples] ✓ Servo is now ON [2026-01-26T21:50:25Z INFO moto_hses_examples] Selecting job 'TEST'... [2026-01-26T21:50:25Z INFO moto_hses_examples] ✓ Job 'TEST' selected successfully [2026-01-26T21:50:25Z INFO moto_hses_examples] Starting job 'TEST'... [2026-01-26T21:50:25Z INFO moto_hses_examples] ✓ Job start command sent successfully [2026-01-26T21:50:25Z INFO moto_hses_examples] ✓ Job 'TEST' started successfully 自作のクライアントライブラリであり、Web上に活用事例がほとんど存在しない状況でも、Agent Skillsによってドメイン知識を補完することで、LLMが適切なコードを生成できることが確認できました。 Agent Skillsを使ったパケット解析デモ # 次に、通信障害時のデバッグにスキルを活用する例を紹介します。hses-packet-analysis スキルは、tsharkでパケットをキャプチャし、hses-protocol スキルのプロトコル仕様と照合してレポートを出力します。このようにスキル間で連携することで、複雑な解析タスクにも対応できます。 障害シナリオの作成 # 検証のため、Status Reading(0x72)コマンドの応答パケットをモックサーバー側で意図的に不正なデータに書き換えて返信してみます。 Status Reading の Data 1 フィールドは 4バイト(32ビット)ですが、有効なステータスビットは下位8ビットのみ使用されます。 ビット 内容 Bit 0 Step モード Bit 1 One Cycle モード Bit 2 Continuous モード Bit 3 Running(動作中) Bit 4 Speed Limited Bit 5 Teach モード Bit 6 Play モード Bit 7 Remote モード Bit 8-31 未使用(常に0であるべき) 仕様違反の内容 Data 1 の上位バイト(Bit 16-23)に値 0x01 を設定し、定義された値域を超過させます。 期待値: [0x00][0x00][0x00][0x00] (上位3バイトは常に0) 実際: [0x00][0x00][0x01][0x00] (3バイト目に0x01) ↓ ↓ ↓ ↓ Bit Bit Bit Bit 0-7 8-15 16-23 24-31 ↑ 不正な値 この状態で先ほど生成したアプリケーションを実行すると、以下のエラーログが出力されます。 [2026-01-27T21:18:54Z INFO moto_hses_examples] Connecting to robot controller: 192.168.0.18:10040 [2026-01-27T21:18:54Z INFO moto_hses_examples] ✓ Successfully connected to controller [2026-01-27T21:18:54Z INFO moto_hses_examples] Reading initial status... [2026-01-27T21:18:54Z ERROR moto_hses_examples] ✗ Failed to read status: Protocol error: deserialization error: Invalid status word value Error: ProtocolError(Deserialization("Invalid status word value")) Invalid status word value エラーが発生しました。ここで hses-packet-analysis スキルを使ってLLMにパケット解析をしてもらいましょう。 解析プロンプト # 以下のプロンプトを入力しました。 cargo run -- 192.168.0.18 TEST が失敗します。パケット解析してマークダウンに結果を出力して。 解析結果 # 以下の解析レポートが出力されました。スキルはパケットキャプチャを実行し、プロトコル仕様と照合して問題箇所を特定しています。 --> レポートの構成 出力されるレポートには、プロトコル検証結果、シーケンス図、パケット詳細(バイナリ解析)、推奨対応を含みます。今回は Status Data 1 の bit 16 に不正な値がセットされているという仕様違反を原因として特定しました。 HSES Protocol Analysis Report # Generated: 2026-01-28 06:19:36 Capture File: hses_capture_20260128_061936.pcap Export File: hses_export_20260128_061936.txt 1. Summary # Metric Value Total Packets 2 Requests 1 Responses 1 Errors 0 (protocol level) Duration 0.000136 sec Issue Detected: Application error "Invalid status word value" - the robot controller returned a status value with an unexpected bit set (bit 16) that is not defined in the protocol specification. 2. Protocol Validation # Check Result Details Magic bytes ✅ Pass Both packets start with "YERC" (0x59455243) Header size ✅ Pass All headers are 32 bytes (0x0020) Reserved (byte 8) ✅ Pass Value is 0x03 Reserved (bytes 16-23) ✅ Pass Value is "99999999" Division ✅ Pass 0x01 (Robot) ACK field ✅ Pass Request=0x00, Response=0x01 Block number ✅ Pass Request=0, Response=0x80000000 (single) Request/Response pairs ✅ Pass 1 request matched with 1 response Service code match ✅ Pass Response service (0x81) = Request service (0x01) + 0x80 Command ID ✅ Pass 0x72 (Status reading) is valid Response status ✅ Pass 0x00 (Normal reply) Payload validity ⚠️ Warning Status word contains undefined bit 16 Payload Analysis Issue # The response payload contains status data with an unexpected value: Expected: Status Data 1 should only use bits 0-7 (bits 8-15 are reserved) Received: 0x00010000 (bit 16 is set) Consequence: moto-hses library rejects this value as "Invalid status word value" 3. Sequence Diagram # sequenceDiagram participant C as Client participant R as Robot Controller C->>R: Status Reading (0x72) Instance=1 R-->>C: Status=0x00 (OK), Data=0x00010000 Note over C: Deserialization failed:<br/>Invalid status word value 4. Communication Sequence # # Time (sec) Direction Command Instance Status Description 1 0.000000 Request Status Reading (0x72) 1 - Read Status Data 1 2 0.000136 Response Status Reading - 0x00 (OK) Returned status=0x00010000 5. Protocol Errors # No protocol-level errors detected. However, an application-level deserialization error occurred. # Time Command Issue Meaning 2 0.000136 Status Reading Status word bit 16 set Robot returned status data with undefined bit, causing deserialization failure Root Cause Analysis # The robot controller returned Status Data 1 with value 0x00010000 , which has bit 16 set. According to the HSES protocol specification: Status Data 1 (Command 0x72, Instance 1) bit definitions: Bit Meaning 0 Step mode 1 One-cycle mode 2 Continuous mode 3 Running 4 Speed limited 5 Teach mode 6 Play mode 7 Remote mode 8-15 Reserved Bit 16 is not defined in the specification. The moto-hses library strictly validates status values and rejects undefined bits. Possible causes: Newer firmware version with extended status bits not yet documented Controller-specific extension to the protocol Memory/data corruption on the controller 6. Packet Details # Packet 1 - Request # Field Value Description Time 0.000000 Start of capture Type Request ACK=0x00 Magic YERC 0x59455243 Header Size 32 0x0020 Payload Size 0 No payload Division Robot 0x01 Request ID 1 Session ID Block Number 0 Request block Command ID 0x0072 Status reading Instance 1 Status Data 1 Attribute 0 Default Service 0x01 Get_Attribute_All Raw Hex: 59455243 2000 0000 03 01 00 01 00000000 3939393939393939 7200 0100 00 01 0000 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ Padding │ │ │ │ │ │ │ │ │ │ │ │ └─ Service (Get_Attribute_All) │ │ │ │ │ │ │ │ │ │ │ └─ Attribute │ │ │ │ │ │ │ │ │ │ └─ Instance (1) │ │ │ │ │ │ │ │ │ └─ Command ID (Status reading) │ │ │ │ │ │ │ │ └─ Reserved "99999999" │ │ │ │ │ │ │ └─ Block Number (0) │ │ │ │ │ │ └─ Request ID (1) │ │ │ │ │ └─ ACK (Request) │ │ │ │ └─ Division (Robot) │ │ │ └─ Reserved (0x03) │ │ └─ Payload Size (0) │ └─ Header Size (32) └─ Magic "YERC" Packet 2 - Response # Field Value Description Time 0.000136 136μs after request Type Response ACK=0x01 Magic YERC 0x59455243 Header Size 32 0x0020 Payload Size 8 Status data Division Robot 0x01 Request ID 1 Matches request Block Number 0x80000000 Single response Service 0x81 Get_Attribute_All + 0x80 Status 0x00 Normal reply Added Status Size 2 Added Status 0x0000 No error Payload Data: 00000100 00000000 │ └─ Status Data 1 part 2: 0x00000000 └─ Status Data 1 part 1: 0x00010000 (bit 16 set - UNEXPECTED) Raw Hex: 59455243 2000 0800 03 01 01 01 00000080 3939393939393939 81 00 02 00 0000 0000 | 00000100 00000000 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ Payload (8 bytes) │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ Padding │ │ │ │ │ │ │ │ │ │ │ │ │ └─ Added Status (0x0000) │ │ │ │ │ │ │ │ │ │ │ │ └─ Padding │ │ │ │ │ │ │ │ │ │ │ └─ Added Status Size (2) │ │ │ │ │ │ │ │ │ │ └─ Status (0x00 = OK) │ │ │ │ │ │ │ │ │ └─ Service (0x81 = 0x01 + 0x80) │ │ │ │ │ │ │ │ └─ Reserved "99999999" │ │ │ │ │ │ │ └─ Block Number (0x80000000 = single) │ │ │ │ │ │ └─ Request ID (1) │ │ │ │ │ └─ ACK (Response) │ │ │ │ └─ Division (Robot) │ │ │ └─ Reserved (0x03) │ │ └─ Payload Size (8) │ └─ Header Size (32) └─ Magic "YERC" 7. Recommendations # Investigate controller firmware - Check if the robot controller has a newer firmware that uses extended status bits Update moto-hses library - Consider relaxing status validation to ignore unknown bits (mask with 0x00FF for Status Data 1) Contact Yaskawa - If the issue persists, consult Yaskawa support about the meaning of bit 16 in Status Data 1 シンプルなプロンプトから、パケットのバイナリデータをプロトコル仕様と照合し、原因を特定してくれました。このように、Agent Skillsを活用することで通信障害のデバッグ作業もLLMに任せることができます。 まとめ # 本記事では、安川ロボットコントローラのHSES通信クライアント(moto-hses)とAgent Skillsを組み合わせた取り組みを紹介しました。 コード生成 : moto-hses-usage スキルにより、LLMがmoto-hsesを使った適切な通信コードを自動生成 パケット解析 : hses-packet-analysis スキルにより、通信障害時のデバッグをLLMに委任 産業用ロボットのプロトコル仕様はPDFとして配布されていたり、ドメイン知識が必要だったりとLLMには扱いにくい情報ですが、Agent Skillsの形式に整備すればこの課題を解決できます。コード生成から保守・デバッグまで、一貫してLLMに任せられる環境が整いつつあります。 今後の展望 # 各社ロボットコントローラがROS2のようなフレームワークに対応し、共通I/Fで利用できるようになる未来も想定されますが、コントローラ側の歩み寄りが必要であり現実的には難しいと考えています。また、各社ロボットには様々な独自仕様(溶接のような用途別の機能など)があり、共通I/Fでは吸収しきれない部分も存在します。 コントローラのI/Fが異なっていてもスキルが提供されれば、必要とするアプリケーションの開発をLLMが行うことは可能です。各社ロボットコントローラに対する様々なスキルを作成してゆき、ロボットシステム開発においてLLMが担える部位を増やしてゆきたいと考えています。
前回の記事では、新しいプロジェクトとPackage要素を作成しました。 /blogs/2026/01/15/sysmlv2-tool-syson-pkg/ 本記事では、構造定義の要の1つである Part Definitionを作成します。 執筆時点における SysONの安定版は v2025.12.0が最新ですが、本記事では前回同様 v2025.8.0を使用します。 最新リリースの挙動は一部異なる可能性がありますのでご了承ください。 モデリングの題材は、SysMLv2の仕様書 A Annex: Example Modelから拝借します。 "Figure 59. Axle and its Subclass FrontA"を作成してみましょう。 新規のPart Definitionを作成する # 前回と同じように General Viewを表示し、右クリックで表示されるコンテキストメニューから "Structure" > "New Part Definition"を選択します。 すると、General Viewに Part Definitionが表示されます。 Part Definitionの名前を変更する # 作成した Part Definitionの名前を"Axle"に変更しましょう。 名前を変更する方法は2つあります。 後述しますが、この2つの方法はくわしくみると動作が異なります。 変更方法その1 # 1つは右サイドバーで変更する方法です。 対象の要素(PartDefinition1)を選択すると右サイドバーに Detailsが表示されます。 その Declared Nameの欄に表示されている名前を直接編集します。 変更方法その2 # もう1つは要素のコンテキストメニューやファンクションキーで変更する方法です。 コンテキストメニューを表示して上部に並んでいるアイコンの中で最も左にあるペンアイコンをクリックします。 ペンアイコンをクリックすると、要素内に表示された名前を直接編集できるようになります。 コンテキストメニューで、ペンアイコンではなく "Edit" > "Edit"を選択しても同様に名前を直接編集できるようになります。 要素を選択して F2キーを押下しても同様に名前を直接編集できます。 Part DefinitionにAttributeを追加する # 次は、"Axle"の attributesに"mass"を追加しましょう。 "Axle"を選択してコンテキストメニューを表示し、"Structure" > "New Attribute"を選択します。 "Axle"にattributes区画が表示され、その区画に"attribute1"が追加されます。 追加された"attribute1"を選択し、その名前を"mass :> ISQBase::mass"に変更します。 コンテキストメニューかファンクションキーを用いた方法で変更した場合、右サイドバーの Detailsに Subsetsの項目があらわれ、そこに massが表示されます。 "attribute1"の名前を左サイドバーの Detailsにある Declared Nameで変更した場合、図の見た目は同じですが Detailsに Subsetsの項目はあらわれません。 これはどういうことでしょうか。 前者(コンテキストメニューなどで変更)の場合は、subsetsの記号(:>)が解釈されて massが ISQBase::massの subsetsになります。 一方後者(Declared Nameで名前を変更)の場合は、単純に名前が"mass :> ISQBase::mass"に変更されます。 この違いは図の見た目だけではわからないため注意してください。 Part Definition間にSubclassificationを設定する # Axleと同様の手順でもう1つ Part Definitionを作成して名前を"FrontAxle"にします。 "FrontAxle"を選択した時に要素の上下左右に表示される三角(>)の位置にマウスをあわせるとマウスのポインタが十字(+)に変わります。 この状態で"Axle"にドラッグ&ドロップすると、relationshipを選択するコンテキストメニューが表示されます。 ここで、"New Subclassification"を選択すると、Subclassificationをあらわす白抜き矢印の線が表示されます。 加えて、"FrontAxle"の名前が"FrontAxle :> Axle"に変更されます。 Subclassificationを設定するもう1つの方法があります。 それは、"FrontAxle"をコンテキストメニューもしくはファンクションキーで"FrontAxle :> Axle"に変更する方法です。 変更すると、"FrontAxle"の表示が変わるとともに、Axleとの間に Subclassificationをあらわす線が表示されます。 "FrontAxle"に"steering"の attributeを追加します。 SysMLv2仕様書の"Figure 59. Axle and its Subclass FrontA"と等価な図ができました。 テキスト記法を用いたPart Definitionの追加 # ここまで作図でモデルを作成してきましたが、Packageと同様テキスト記述を用いたモデル作成もできます。 part def Axle { attribute mass:>ISQ::mass; } part def FrontAxle :> Axle { attribute steeringAngle :> ISQ::angularMeasure; } 作成された Axleと FrontAxleを General Viewにドラッグ&ドロップします。 attribute区画を表示するにはまず、Part Definitionの名前の右にマウスカーソルをあわせた際に表示される目のアイコンをクリックします。 表示された"Manage Visibility"コンテキストメニューの"attribute"にチェックを入れます。 次回予告 # 本記事では、Part Definition要素を作成し要素間に Subclassificationを設定しました。 次回は、Part Usageを作成し、Part Definitionとの関連付けを行います。
1. はじめに # 先日、業務日誌について書いた投稿がこちらになります。 /blogs/2026/01/06/businessdiary/ ただ、 ここは技術ブログなので、記事だけだと片手落ちな気がする。 自分は技術者なんだから、せっかくだから何か作りたい。 と思いましたので、業務日誌を題材にアプリを作りました。 (あくまで学習用のサンプルアプリになりますが) また、最近、社内研修で要件定義、設計、文章の書き方などを 学びましたので、練習を兼ねてこれらも実施しました。 そこで、本記事では、業務日誌アプリを題材に 要件定義〜設計をどのように整理したかを中心に紹介します。 私と同じようにアプリを作成するエンジニアの方向けに、設計の良し悪しではなく、作業の過程について共有できればいいなと思っています。 なお、実装したアプリそのものについては、本記事では割愛し、別記事で公開したいと思います。 2. アプリを開発する # まず、今回のゴールとしては、業務日誌を作成するアプリの必要最低限の機能のみを開発します。 前回のブログでSlackを使用して業務日誌を作成していることに触れていることも踏まえ、 今回はSlackのアプリを作成してみます(技術要素は別途、以下で整理します)。 開発は以下の手順で進めます。 要件定義 設計 製造・テスト(ブログ上では詳細割愛) 2-1. 要件定義 # 本記事で中心となる内容で、少し記述量が多くなってしまいましたが、 よろしければお付き合いいただければと思います😓 要件定義では、要望→要求→要件→仕様の順に作成していきます。 2-1-1. 要望を書いてみる。 # まず、要望ですが、要望とは「システム(今回はアプリ)で実現したいこと」となります。 とりあえず、業務日誌アプリでできそうなことを思いつくまま書き出してみます。 --> Information 業務日誌を自動で作成してほしい。 手書きは面倒なので、アプリで自動生成してほしい。 業務日誌を自動で報告してほしい。 Slackのチャネル投稿するなど、報告を自動化したい。 決められた時間に業務日誌を作成・報告してほしい。 定時前などスケジュールに基づいて業務日誌を作成・報告してほしい。 業務日誌の体裁を調整したい。 業務日誌のテンプレートを作成して、日誌の体裁を整えたい。 作業は随時登録したい。 業務日誌に記載する作業は、業務中につど登録したい。 (日誌を作成時に考えるのは、効率的ではないので、事前に登録しておきたい) 作業の状況を管理したい。 作業状況が分かるようにしたい。 登録した作業は保管しておきたい。 アプリを停止、再開した後も作業が参照できるようにしたい。 作成した業務日誌は保管しておきたい。 アプリを停止、再開した後も業務日誌が参照できるようにしたい。 業務日誌の要約したい。 作成済みの複数日の業務日誌を要約して、週報、月報、あるいは、評価面談用の資料としたい。 フィードバックがほしい。 作成した業務日誌の内容についてフィードバックがほしい。 (AIとかにレビューさせるとかできるかも) 2-1-2. 要求を書いてみる。 # 次に、要求ですが、要求とは「要望の内、実現するものとして採用されたもの」となります。 今回は、業務日誌アプリとして必要な最低限な要望のみを要求として選択します。 よって、要求は以下のとおりとします。 --> Information 作業を登録したい。 業務中に実施する作業を登録できるようにします。 登録した作業を確認したい。 登録した作業が確認できるようにしたい。 作業のステータスを設定したい。 登録済みの作業に対して、作業ステータスが設定できるようにします。 作業ステータスは、以下のとおりとします。 未着手 作業中 完了 業務日誌を作成したい。 登録済みの作業から業務日誌を作成します。 業務日誌には「当日実施した作業一覧」と「翌日実施する作業予定一覧」が登録されています。 登録した作業を保存しておきたい。 登録した作業が消失しないようにします。 作成した業務日誌を保存しておきたい。 作成した業務日誌が消失しないようにします。 1.-4.はいいかと思います。5.6.はちょっと違うような気もしますが、いったんよしとします。 登録と永続化って大抵はセットなので、どこかで1つにしたほうがいいとは思うのですが。 2-1-3. 要望のうち、要求に含めないもの。 # 要望として挙げたもののうち、要求としないものについても、一応明記するようにします。 --> Information 業務日誌の自動生成 業務日誌の生成はアプリの機能としますが、生成処理の起動は手動で行うこととします。 業務日誌の自動報告 報告は手動で行うこととします。 業務日誌のスケジュール生成 必須機能ではないので、対象外とします。 業務日誌のテンプレート 今回は業務日誌のテンプレートは決め打ちとします。 業務日誌の要約 必須機能ではないので、対象外とします。 業務日誌へのフィードバック 必須機能ではないので、対象外とします。 2-1-4. 要件を書いてみる。 # 続けて、上記の要求を基に要件を定義してみます。 要件とは「完成したシステムが実現することを定義したもの」となります。 --> Information ユーザーは、アプリの画面から作業が登録できなければならない。 ユーザーは、アプリの画面上で、登録した作業の一覧を確認できなければならない。 ユーザーは、アプリの画面から、登録済みの作業に対して、定義された作業のステータスを設定できなければならない。 ユーザーは、アプリに業務日誌の作成を指示できなければならない。 アプリは、登録済みの作業を基に業務日誌を生成し、その内容をユーザーに提示しなければならない。 ユーザーがアプリを停止、再開しても、停止前に登録した作業が参照できなければならない。 ユーザーがアプリを停止、再開しても、停止前に作成した業務日誌が参照できなければならない。 2-1-5. 仕様を書いてみる。 # 最後に、仕様を定義してみます。 仕様とは「網羅的に記述された要件」となります。 --> Information 作業の登録 ユーザーは、画面から作業内容を入力する。 アプリは、ユーザーが入力した作業内容に加え、以下の内容を合わせて登録する。 作業ID 登録日 作業ステータス 作業IDは、作業を一意に特定できる識別子とする。 登録時点の現在日を登録日として登録する。登録日の書式はyyyy/MM/dd とする。 登録日は、ユーザーが作業登録を実行した時点の日本標準時(JST)に基づく日付とする。 また、作業のステータスを未着手として設定する。 作業内容は必須入力とし、前後の空白文字を除去した結果が空文字列となる場合は無効とする。 作業内容が未入力の場合、アプリは登録が失敗した旨のメッセージを表示して、処理を終了する。 作業内容として入力可能な文字数の上限は100文字とする。この時、全半角は考慮せず、どちらも1文字として扱うこととする。 作業の一覧確認 ユーザーはアプリへ登録済みの作業の一覧を表示するように指示する。 アプリは画面上に登録済みの作業の一覧を表示する。 一覧は登録した順序(作業ID)の昇順で表示する。 一覧には作業内容、登録日、作業ステータスを表示する。 作業ステータスの変更 ユーザーは、対象となる作業を指定し、作業ステータスを変更できる。 作業ステータスは、未着手、作業中、完了の3つとする。 ユーザーが存在しない作業(作業ID)を更新しようとした場合、アプリは設定が失敗した旨のメッセージを表示して処理を終了する。 ユーザーが規定のステータス以外に更新しようとした場合、アプリは設定が失敗した旨のメッセージを表示して処理を終了する。 アプリはユーザーが入力した作業IDと作業ステータスで指定された作業のステータスを更新する。 ステータス間の遷移に制約は設けないこととする。ユーザーが指定したステータスを必ず設定するようにする。 業務日誌の生成 ユーザーは画面上から、アプリに対して業務日誌の生成を指示する。 アプリはユーザーの指示を受け、登録済みの作業から業務日誌を作成する。 業務日誌には以下の項目で構成される。 生成日 当日実施した作業の一覧 翌日実施する作業予定の一覧 生成日は、業務日誌を生成時の現在日を表示する。 生成日の表示形式は yyyy年MM月dd日(WeekDay)とする ※WeekDayは曜日で、月、火、水..といった値となる。 生成日は、日誌作成時点の日本標準時(JST)に基づく日付とする。 当日実施した作業の一覧には、次の条件をすべて満たす作業を含める。 当日中に作業ステータスを更新している。 作業ステータスが作業中、あるいは、完了である。 翌日実施する作業予定の一覧には、次の条件をすべて満たす作業を含める。 作業ステータスが未着手、あるいは、作業中のどちらかである。 作業の保存 ユーザーが作業を登録した際に、アプリは作業を永続化する。 ユーザーが作業の一覧を確認する際に、アプリは作業の一覧を永続化された作業から生成する。 ユーザーが作業のステータスを設定した際に、アプリは永続化された作業のステータスを更新する。 業務日誌の保存 アプリは業務日誌を生成した時に、生成した業務日誌を永続化する。 2-2. 設計 # 2-2-1. 方式設計 アプリ全体の設計方針について記載します。 設計フェーズなので、具体的な技術要素についても記載します。 --> Information アプリケーションはSlackアプリとして実装します。 アプリにUIが必要ですが、デスクトップアプリを作るのはちょっと大げさだと感じました。 業務では、Slackを利用していますので、Slackで業務日誌を作成できると、 作成→報告が一箇所でできるのでベターかと思いました Bolt for JavaScriptフレームワークを使用します。 データを永続化するために、DBを利用します。DBはSQLiteを採用します。 今回はローカルで動作するサンプルですので、 軽量なインメモリデータベースで十分だと思います。 永続化層にO/RマッパーとしてDrizzle ORMを採用します。 https://orm.drizzle.team/ これは個人的な好みです。 開発言語はTypeScript(JavaScript)を使用します。 前述のBoltフレームワークではPython、JavaScriptが利用できますが、 あいにく、Pythonは不得手ですので、得意なJavaScriptを使用します。 Denoは使用しないこととします。 Bolt for JavaScriptではDenoが利用でき、個人的にもDenoは嫌いではないのですが、 Denoがそこまで浸透しているかが不明ですので、今回はいったん見送ります。 2-2-2. 機能設計 仕様の5と6、登録した作業、業務日誌の保存(永続化)は それぞれ、1と4にマージします。 結果として機能が4つとなりますので、それぞれについて記載します。 --> Information 作業を登録する 作業内容の入力 作業内容はアプリのDMにメッセージとして入力します。 作業内容の検証 作業内容が未入力の場合、エラーメッセージを表示します。 エラーメッセージはアプリからの返信として表示します。 作業内容が100文字を超過する場合、エラーメッセージを表示します。 エラーメッセージはアプリからの返信として表示します。 作業内容の登録 作業内容の登録はSlackアプリのコマンドを実行することで起動します。 作業内容をDBに保存します。 保存する内容は、入力した作業内容、登録日、初期作業ステータス(未着手)になります。 作業を確認する 作業一覧を表示する。 コマンドを実行することで作業の一覧を表示するようにします。 作業の一覧の各項目は、作業内容、ステータス、設定ボタンの4項目とします。 ステータスは変更できるように、セレクトボックスで表示します。 ステータスの初期値は登録済みの作業ステータスの値となります。 作業の一覧は登録順(ID順)の昇順とします。 作業が未登録の場合は、エラーメッセージを表示します。 エラーメッセージはアプリからの返信として表示します。 作業ステータスを設定する 作業ステータスの更新 作業一覧に表示されている、設定ボタンを押下することで、 作業ステータスの値を選択している値に設定します。 業務日誌を生成する 業務日誌を生成する。 業務日誌は、文章(テキスト)とします。 業務日誌には、当日実施した作業の一覧、および、翌日実施した作業の一覧を含めます。 当日実施した作業の一覧は、作業ステータスが作業中、あるいは、完了となっている作業となります。 翌日実施した作業の一覧は、作業ステータスが未着手、あるいは、作業中となっている作業とします。 該当する作業が存在しない場合は、作業の一覧ではなく、テキスト”作業が存在しません”を業務日誌に含めるようにします。 コマンドを実行することで業務日誌を生成します。 生成した業務日誌は、アプリからの返信として表示します。 業務日誌の保存 生成した業務日誌はDBへ保存します。 登録内容は、業務日誌ID、登録日、業務日誌の3項目とします。 2-3. 図 # 設計の練習を兼ねて、作図も行います。 2-3-1. ユースケース図 2-3-2. ドメインモデル 2-3-4. ロバストネス図 3. 作成したアプリについて # アプリを作成したので、ここでは動作結果のみを記載します。 ※アプリ自体については別の記事で言及できればと考えています。 3-1. 機能の動作確認 # 3-1-1. 作業を登録する # まずは、作業を登録します。 /task_add コマンドに、引数として作業内容を設定して送信。 登録に成功するとメッセージが返信されます。 3-1-2. 作業を確認する # 次に、登録した作業を/task_listコマンドで表示します。 一覧表示は引数なしのコマンドとなります。 一覧が登録順に表示されます。 また、ステータスが更新できるようにステータスをセレクトボックスで表示し、更新処理を実行するためのボタンを配置しました。 なお、動作確認用に3つのタスクを登録しています。 3-1-3. 作業ステータスを設定する # さらにステータスを変更してみます。 3つの作業のうち、1つを作業中に、もう1つを完了に変更します。 アプリ上でステータスを変更して、更新ボタンをクリックすると、 ステータスが更新され、メッセージが返信されます。 3-1-4. 業務日誌を作成する # 最後に業務日誌を生成してみます。 こちらは/businessDiary_createコマンドを実行します。 コマンドの受け付けに対して、応答を返した後、 生成された業務日誌が表示されます。 当日の作業一覧に作業中、あるいは、完了の作業が表示されます。 また、翌日の作業予定一覧に未着手、あるいは、作業中の作業が表示されます。 4. まとめ # 本記事では、業務日誌を題材に、アプリケーションの要件定義、設計、実装を行ってみました。個人の学習の一環として取り組んだ内容の整理になりますが、 同じように設計に悩みながらアプリを作っている方の参考になれば幸いです。 実際に取り組んでみた所感としては、以下のように感じました。 業務外の作業なので、所々手抜きもあるのですが、 それを別にしても、まだまだ至らない点があるので、こういった作業を通じて、能力向上ができればなと思いました。 また、こういったサンプル程度のアプリでも、実際に要件定義・設計すると、 結構なボリュームになったなと感じています。 ただ、アプリの開発自体は(体感としては)スムーズに進んだようにも思えましたので、こういった要件定義、設計のプロセスというのは無駄ではないと思いました。 以前、ローコードツールを使用した開発を行っていましたが、ツールの「生成した成果物(コード)= 設計書」という思想の影響で、設計を行わずに実装することが多かったです。 ですが、今回のように設計 → 実装の流れで作業すると、ローコードでなくても、事前に設計を実施してから実装に着手したほうが作業が捗るように感じました。理由としては、実装中にトライ・アンド・エラーで作業するよりも、事前に設計を文書化するほうが、仕様をよりよく理解できるためだと思います。 業務日誌アプリについては、今後、技術習得も兼ねて、機能拡張していければと考えています。また、採用した技術要素についても、別途記事として公開できればと考えています。
前回の記事「無料のOSSツールSysONで始めるSysML v2モデリング(1) 〜 はじめてのSysON」では、SysONをインストールして Webブラウザでホーム画面を表示しました。 /blogs/2026/01/08/sysmlv2-tool-syson-intro/ 本記事では、新しいプロジェクトとパッケージを作成してみましょう。 本記事では Release 2025.8.0を使用しています。 最新版ではUIや挙動が異なる可能性がありますのでご了承ください。 ホーム画面はプロジェクトブラウザ画面とも呼びます。 プロジェクトブラウザ画面の上側にはプロジェクトを作成するアイコンが並びます。 その下側には既存のプロジェクトのリストが表示されます。 プロジェクトを作成する # 新しい SysMLv2プロジェクトを作るには、"Create a new project"にある左から2番目の"SysMLv2"と記載されたアイコン(SysMLv2テンプレート)を選択します。 選択すると、プロジェクトエディタ画面が表示されます。 エディタ画面は、画面上部の「ツールバー」、左側の「左サイドバー」、右側の「右サイドバー」、左右サイドバーの間にある「エディタ」の4つから構成されます。 プロジェクト名を変更する # プロジェクト名は、ツールバーの中央にある"SysMLv2"です。 まずはプロジェクトの名前を変更しましょう。 ツールバーにあるプロジェクト名横のケバブボタン(︙)をクリックし"Rename"を選択すると、"Rename the project"のダイアログが表示されます。 今回は"SysMLv2.trial"と入力して"RENAME"ボタンを押下します。 ビューを表示する # 左サイドバーのツリーで"General View"を選択すると、エディタに図を描く画面が表示されます。 グラフィカル記法でモデルを作成する場合は、ここに図を描いていきます。 ビューを追加する # 新たにビューを追加したい場合は、左サイドバーのツリーにあるパッケージなどの要素に付いているケバブアイコン(︙)をクリックします。 表示されたコンテキストメニューから"New representation"を選択するとビューを追加するためのダイアログが表示されます。 このダイアログで名前を入力しビューの種類を指定して"CREATE"ボタンを押すとビューを追加できます。 プロジェクトブラウザ画面に戻る # プロジェクトブラウザ画面に戻る場合は、画面上部ツールバーの右端にあるハンバーガーボタン(≡)をクリックして"Projects"を選択します。 ツールバーの左端にある立方体のアイコンをクリックしても、プロジェクトブラウザ画面に戻ります。 新規のPackage要素を作成する # 最初に Packageを作成してみます。 中央のエディタで空きスペースを右クリックすると、図に配置できる要素のカテゴリ一覧がコンテキストメニューに表示されます。 "Structure"を選択すると、コンテキストメニューの表示が図に配置できる"Structure"の要素の一覧に切り替わるので、"New Package"を選択します。 すると、エディタに Package要素が表示され、左サイドバーのツリーに Package要素が追加されます。 このとき、左サイドバーのツリーをみると、新しく追加した"Package1"は"General View"がある"Package1"の中に追加されていることがわかります。 右サイドツリーの"Details"にある"Declared Name"にも"Package1"と記載されています。 ここでもうひとつ、”Package1”を作成したのと同じ手順で"Package2"を追加します。 次は、左サイドバーのツリーにある"Package2"をツリーにある"Package1"の中にドラッグ&ドロップで移動します。 その後、"Package1"を右クリックしてコンテキストメニューを表示します。 表示されたコンテキストメニューから "Related Elements" > "Add existing nested elements"を選択します。 すると、"Package1"の中に"Package2"が表示されます。 このとき、"Package1"の外に表示されている"Package2"に変化はありません。 SysMLv2仕様をみると、"Package1"と"Package2"の間に owned-membershipを表示するのがよさそうです。 今後のリリースで owned-membershipを表示するように変更されるかもしれません。 Packageをビューから削除する # "General View"には"Package2"が2つ表示されています。 このうち"Package1"の外にある"Package2"をビューから削除します。 "Package2"を選択した状態で右クリックしてコンテキストメニューを表示します。 コンテキストメニューの上部に並んでいるアイコンの中で左から4つ目にある四角に斜線が入ったアイコンをクリックします。 "Package2"はビューから削除されますが、左サイドバーのツリーには"Package2"が残っています。 Packageをビューに配置する # 左サイドバーのツリーの"Package2"をエディタにドラッグ&ドロップしてください。 ふたたび、ビューに"Package2"が表示されます。 PackageをImportする # 左サイドバーのツリーでPackage右側のケバブアイコン(︙)をクリックします。 表示されたコンテキストメニューの"New object"を選択すると"Create a new object"のダイアログが表示されます。 ダイアログの"Object type"で"Namespace Import"を選択します。 すると、ツリーで先に選択したPackageの中に”Namespace Import”が追加されます。 追加された”Namespace Import”を選択すると右サイドバーの"Details"にその詳細が表示されます。 左サイドバーに表示される"Datails"の"Imported Namespace"でImportするPackageを選択するとImportの設定は完了です。 図のPackageを右クリックし、コンテキストメニューから "Related Elements" > "Add existing nested elements"を選択します。 Packageの中に表示された点線のPackageがImportをあらわします。 左サイドバーの"Details"にある"Visibility"でImportされたPackageの可視性を変更できます。 Packageをモデルから削除する # "Package1"をモデルから削除します。 "Package2"をビューから削除したのと同様の手順でコンテキストメニューを表示します。 表示したコンテキストメニュー上部のアイコンの中で、今度は左から2つ目にあるゴミ箱アイコンをクリックします。 すると、削除してよいかを確認するダイアログが表示されます。 ”DELETE”ボタンを押下すると"Package1"の中にあった"Package2"ごと左サイドバーのツリーから削除され、"Package1"と"Package2"がビューから消えます。 テキスト記法を用いたPackageの追加 # SysONは SysML v2の特徴であるテキスト記法を扱うこともできます。 左サイドバーのツリーで、"Package1"の右にあるケバブアイコン(︙)をクリックして、表示されたメニューから"New objects from text"を選択します。 すると、上部に"Enter or paste SysMLv2 text to create new objects in the model"と記載されたダイアログが表示されます。 ダイアログに以下を入力して"CREATE OBJECTS"のボタンを押下します。 package Package2 { package 'Package 3' { } } package 'パッケージ' { } 左サイドバーのツリーに"Package2", "Package3", "パッケージ"の3つのパッケージが追加されます。 続けて追加しない場合は"CLOSE"ボタンでダイアログを閉じます。 テキスト記法では、パッケージ名をシングルクオート(')で囲むと日本語や半角スペースを入れた文字列を使うことができます。 次回予告 # 本記事では、新しいプロジェクトを作成し、パッケージを追加しました。 次回は Part Definition要素を作成します。
はじめに # アジャイルグループの石田です。 第1回:導入 の続編です。前回は、 スクラムガイド拡張パック を参考に、AIがスクラムを強化する可能性の一つとして「経験的プロセス制御」の強化について触れました。 スクラムマスターとして、スクラムというプロセスにAIを活用することで、チームが実践するスクラムの三本柱「透明性・検査・適応」をより強化することができます。 透明性へのアプローチ # 本記事では、三本柱の第一歩である「透明性」に着目します。ここでいう透明性とは、単に見えるようにすることではなく、チームが正しい判断(検査・適応)を行うための材料を揃えることに他なりません。 今回はAIにデータの分析そのものを依頼するのではなく、「可視化のためのツール作成(コーディング)をAIに任せる」というアプローチを紹介します。 具体的には、JiraのデータをGoogle Apps Script (GAS)で取得・加工し、可視化するプロセスをAIと共に実装した事例をご紹介します。 なぜAIに「可視化ツール」を作らせるのか # スクラムマスターがチームの状態を正しく観測するために、またチームメンバー自身が自分たちを客観視するために、定量的なデータは不可欠です。 Jiraなどのプロジェクト管理ツールには標準的なレポート機能が備わっていますが、現場では「もう少しこの切り口で見たい」「外部スプレッドシートの情報と突き合わせたい」といった、標準機能ではカバーしきれないニーズが頻繁に発生します。 Jiraには強力なAPIが用意されており、データを自由に扱うことが可能ですが、開発専任ではないスクラムマスターにとって、ゼロからツールを開発するのは学習コストや時間の面でハードルが高いのが現実です。 そこで活用したいのが、生成AIにコードを書かせ、「スクラムマスター専属のエンジニア」として振る舞わせる方法です。これにより、技術的な壁を取り払い、スクラムマスターとしての機動力を劇的に高めることができます。 実際のプロダクトコードにAI生成コードをそのまま使うことには保守性の観点から慎重な議論が必要ですが、チーム内部で使う一時的なツールやダッシュボードを作るという観点では、積極的に活用してこそ価値が発揮される領域だと考えます。 ここから先は、実際に業務で行った生成AIでのチーム可視化の実例をご紹介します。 実践例1:Four Keysによる開発スピードと安定性の可視化 # Four Keysとは # まずは、今回可視化の対象とした「Four Keys」について簡単に触れておきます。 Four Keysは、GoogleのDevOps Research and Assessment(DORA)チームが提唱した、ソフトウェア開発チームのパフォーマンス(デリバリー能力)を測定するための4つの指標です。 デプロイの頻度 (Deployment Frequency): 本番環境へのリリースの頻度。 変更のリードタイム (Lead Time for Changes): コードがコミットされてから本番環境で稼働するまでの時間。 変更障害率 (Change Failure Rate): デプロイが原因で障害が発生した割合。 サービス復元時間 (Time to Restore Service): 障害発生から復旧までの時間。 これらは、開発の「スピード(1と2)」と「安定性(3と4)」を示す指標です。 これらの指標を計測することで、チームが速く、かつ安定して価値を届けられているかを客観的に把握できます。 指標の定義は明確ですが、いざ自分たちの環境で計測しようとすると、いくつかの壁にぶつかりました。 まず、変更のリードタイム(開発着手からリリースまでの時間)はJiraのステータス遷移履歴から計算可能ですが、標準のレポート機能だけで算出するのは難しく、APIによるデータ取得と計算処理が必要になります。 また変更障害率については、今回のプロジェクトでは商用障害をGoogleスプレッドシートで管理しているため、そのデータとJiraのリリース情報を突き合わせて計算する必要がありました。 このように散在するデータを集計し、Four Keysダッシュボードを構築するためにGoogle Apps Script (GAS)を採用しました。そして前述の通り、そのコード作成は生成AIに任せました。 1. Jiraから「スピード」を抽出する まず、Jira APIを通じてチケットデータを取得するスクリプトをAIに作成させました。 プロンプトのポイントは、「ステータスの遷移履歴」に着目させたことです。 プロンプトのイメージ: 「Jiraの特定のプロジェクトから、完了したチケット情報を取得したい。各チケットが『In Progress』になった日時と、そのチケットを含む リリースが完了になった日時 を抽出し、その差分をリードタイムとして計算するGASの関数を書いてください。」 これにより、チケットごとのリードタイムと、月ごとのリリース回数(デプロイ頻度)が自動集計できるようになりました。 2. スプレッドシートから「安定性」を計算する 次に、障害管理をしているスプレッドシートへのアクセスです。 こちらは、月ごとの障害発生件数をカウントし、先ほど算出したデプロイ回数と突き合わせることで「変更障害率」を算出させます。 これらを最終的に一つのスプレッドシート上のグラフとして描画することで、チームの「Four Keys」が日次で更新されるダッシュボードが完成しました。 こうして最新のFour Keysをチーム全員がいつでも見られる状態にしたことで、自分たちのリリース頻度や、それに伴う品質への影響(障害)がひと目でわかるようになり、チームの「スピード」と「安定性」が透明化されました。 実践例2:リリース必達案件における「加速」の可視化 # 2つ目は、少しスクラムの枠を超えた対応についてです。 プロジェクトの特性上、リリース日が固定されている「必達案件」があり、その対応に追われていました。本来のスクラムであれば、ベロシティの実績に基づいてスコープを調整すべきですが、この案件ではスコープも固定されており、従来のベロシティのままではリリースに間に合わないことが判明しました。 そこで現実的な対応として、開発者の稼働(人数や時間)を一時的に増やし、ペースアップを図るという決断をしました。 しかし、単に稼働を増やしたといっても、それによって開発スピードがどれだけ上がったのか、今のペースで本当に期日に着地できるのかは、従来のバーンダウンチャートだけでは直感的に分かりづらい状態でした。 「頑張ってはいるが、間に合うかどうかわからない」という不安な状態は、チームの士気を下げてしまいます。 そこで、ここでもAIを活用しました。 Jira APIから取得した「日々の消化ポイント数(実績)」をベースに、残作業を消化するのにあと何日かかるかを計算し、「予測完了日」の推移をプロットするスクリプトをAIに作成させました。 これにより、稼働を上げたあとにグラフの傾きが急になり(消化ペースが上がり)、予測完了日がリリース日手前まで近づいてくる様子が可視化されました(下の図はイメージです)。チームとステークホルダーに対し「現在の加速具合なら○日に終わる」という明確な見通しを提示できたことで、漠然とした不安を払拭し、開発メンバーが自信をもって仕事を進める手助けをすることができました。 AIがもたらす「スクラムマスターの機動力」 # これまで「こういうデータがあったらいいな」と思っても、技術的なスキル不足や時間の制約で諦めていた可視化が、AIペアプログラミングによって数時間で実現可能になりました。 透明性は、鮮度が命です。 問題が起きそうだと感じた時、すぐにその状況を可視化するツールを自分自身の手で作れることは、チームを守るスクラムマスターにとって強力な武器になります。 「見えない不安」を即座に「見える課題」に変えられる機動力こそが、AIを活用する最大のメリットかもしれません。 まとめと次回予告 # 本記事では、AIを活用してGASを書くことで、Jiraやスプレッドシートに眠るデータを掘り起こし、チームに必要な透明性を素早く、低コストで実現した事例を紹介しました。 これは、スクラムガイド拡張パックで示唆されている「AIによる経験的プロセス制御の強化」を実践するための第一歩です。 しかし、透明性はゴールではありません。見えたデータを元にどう判断し、行動を変えるかが重要です。 次回の第3回「検査・適応」では、透明性とはまた違った視点、あるいは可視化された情報を元にした意思決定の場面でのAI活用についてご紹介します。
昨年の 2025 年 1 月に Kubestronaut の称号を得たのに続き、同年 12 月に GOLDEN Kubestronaut の称号を得たので、その記録をまとめます。 流れは以下です。 GOLDEN Kubestronaut とは: GOLDEN Kubestronaut について簡単に記述 本記事のスコープ: 本記事で記載する範囲について記述 試験の特徴と関係性: GOLDEN Kubestronaut の取得に必要な試験の特徴と関係性について記述 学習方法: 私の学習方法について記述 終えてみて: GOLDEN Kubestronaut の取得を終えてみての所感を記述 各試験への取り組み: それぞれの試験ごとに、取り組みや所感を記述 GOLDEN Kubestronaut とは # GOLDEN Kubestronaut とは、すべての CNCF 認定資格と LFCS に合格すると得られる称号です。GOLDEN Kubestronaut の前段階に Kubestronaut があり、それはその中の 5 つに合格すると称号が得られます。 以下が、Kubestronaut の要件と、GOLDEN Kubestronaut に追加で必要なものです(私が受験した順に記載しています)。 Kubestronaut 要件 Certified Kubernetes Application Developer (CKAD-JP) Certified Kubernetes Administrator (CKA-JP) Certified Kubernetes Security Specialist (CKS-JP) Kubernetes and Cloud Native Associate (KCNA-JP) Kubernetes and Cloud Native Security Associate (KCSA) GOLDEN Kubestronaut 追加要件 OpenTelemetry Certified Associate (OTCA) Istio Certified Associate (ICA) Cilium Certified Associate (CCA) Certified Argo Project Associate (CAPA) GitOps Certified Associate (CGOA) Prometheus Certified Associate (PCA) Certified Backstage Associate (CBA) Kyverno Certified Associate (KCA) Certified Cloud Native Platform Engineering Associate (CNPA) Linux Foundation Certified System Administrator (LFCS-JP) この様に、Kubestronaut だけで 5 個、GOLDEN Kubestronaut には合計 15 個の認定が必要になります。Kubestronaut の称号は 5 つの認定のいずれかを失効すると消失するのですが、GOLDEN Kubestronaut の称号は生涯有効です。 なお、上記の要件は、CNCF に新たな認定試験が追加になるとアップデートされます。具体的には、2026/03/01 に GOLDEN Kubestronaut の要件に以下の試験が追加になるとアナウンスされています。ただ、一度 GOLDEN Kubestronaut に到達すれば、その後に要件が追加されたとしても、それに新たに合格する必要はありません。 Certified Cloud Native Platform Engineer (CNPE) 余談ですが、各試験の料金は、頻繁に行われるセールやクーポンを使うことで、概ね正規料金の 40%〜50%オフにできます。 本記事のスコープ # 本記事では、主に、Kubestronaut から GOLDEN Kubestronaut へのステップアップに追加で必要な認定試験について取り上げます。Kubestronaut までに必要な認定試験については、すでに多くの情報が公開されているので、このレポートの中では割愛します。 試験の特徴と関係性 # 試験の特徴 # 追加要件の試験を総合的に見ると、その特徴は、以下のようであると思います。 クラウドネイティブ関連が広くカバーされている: それぞれの試験を個別に見ると、その殆どは、特定のプロダクトに関する知識やスキルが問われる(CGOA と CNPA は例外)。しかし全体をまとめてみると、セキュリティを始め、オブザーバビリティやガバナンス。また、GitOps とデリバリー、そして IDP など、クラウドネイティブに関する主要な要素が広くカバーされている。 ほとんどは選択式試験(ただし英語): 現在のところ、ICA と LFCS、そして今後追加になる CNPE 以外は、選択式試験。そのため各試験は、英語がそれなりに読めれば、比較的容易。ただ CGOA と CNPA は、特定のプロダクトを対象としない反面、その問題文が理念や考え方を問われるややこしいものになるため、若干、英語のリーディング能力が問われる。 試験の関係性 # それぞれの試験で扱うプロダクトや技術領域に類似や関連があり、ある試験で得た情報が他の試験で役立ちます。各試験が対象とする技術領域と、私が受験した順番の中で感じた各試験の関連は以下のような感じです。 ちなみに、"()"の数字が私の受けた順番で、以下のようにしました。 興味のあるものを先に受ける: オブザーバビリティには興味があったので OTCA は先に受けました。PCA も同じ領域ですが、Prometheus 固有のクエリ言語(PromQL)を覚えるのが面倒そうだったので、後に回しました。 難易度が高そうな実技試験を先に受ける: 実技試験は選択式よりも難易度が高いので、実技試験の ICA は先にしました。LFCS も実技試験ですが、ほかと趣が違うので、後にしました。 関連が強い試験は続けて受ける: 同じ技術領域である ICA と CCA、同じく GitOps を扱う CAPA と CGOA は続けて受けました。 知識や情報の少ない試験は後にする: 知識が薄かった PCA, CBA, KCA や、後で要件に加わって情報が少なかった CNPA は後回しにしました。 全体を通してみて、私が感じた中では、CKS の学習で得た知識が最も多く他の試験で役立ちました。 その一方で、CNPA は他の多くの試験で得られる知識が広く必要でした。これは裏を返すと、「CNPA を先に受験すれば、そこで得た知識は他の多くの試験で役に立つ」ということになります。CNPA を先に受けるか後にするかは人それぞれかと思いますが、CNPA は試験問題の英文が難しいので、私のように英語が苦手な人は後にしたほうが良いかもしれません。 学習方法 # 学習方法は、基本は Kubestronaut 要件の認定資格を受験したときと同じで、以下のパターンでした。 e-learning: KodeKloud や Udemy で提供されているそれぞれの試験対策のコースを受講。 模擬試験: KodeKloud や Udemy の試験対策コースに付帯されている模擬試験を受けるともに、Udemy で追加の模擬試験コンテンツを購入して実施。 ハンズオン: 手持ちの Linux PC で k8s 環境を作って試験カリキュラムに含まれる内容を実践。また、一部の試験については、Killercoda でハンズオン環境が提供されているので、そちらも活用。 リファレンス参照: 試験対象のプロダクトのリファレンスを参照し、試験カリキュラムに含まれる部分をチェック。 e-learning # 基本的に、KodeKloud や Udemy で提供されているそれぞれの試験対策のコースを受講しました。それ以外にも、Linux Foundation や Tetrate Academy の e-learning など、試験に関係しそうな無料コンテンツがあれば見ておきました。 難点として、日本語字幕付きのものはほとんど無かったです。Kubestronaut 要件までの認定資格関連の e-learning の中には日本語字幕つきものもありましたが、今回はほぼ英語のみでした。序盤に受けた試験はある程度知っている技術領域のものだったので、受けた e-learning の内容の理解も追いつくことができました。しかし徐々に、知識の少ない領域の試験になってきて、学習効率が落ちてきました。 そこで、追加 10 個の半分の 5 つ取ったところで、 動画の音声を文字起こししてまとめる という学習法をとりました。音声の文字起こしは、Vibe コーディングで作った、Whisper を使った文字起こしアプリを使いました。 文字起こしアプリを使って、まず動画の各レッスンを視聴直後にテキスト化し、その後で AI を使って、その英文を補正してから日本語に翻訳するとともに要約。それをセルフホストしている Wiki に転記してさっと読み直しました。この方法は、レッスン直後に復習できるのが効果的でした。難点は動画を視聴するのに比べて 1.5 倍くらい時間がかかることですが、それよりも理解を深める方を重要視しました。 この「動画視聴」→「文字起こし」→「自然な英語に整形」→「翻訳&要約」→「Wiki に転記して復習」の流れができたことで、学習のパターンが固まりました。 アプリを作り始めた当初は、同時通訳して e-learning の動画と同時に見るのを理想としたのですが、以下の理由でそれは断念し、アプリの用途は文字起こしのみに限定しました。 翻訳が若干遅れる 標準英単語ではない専門用語の文字起こしに難がある 翻訳したターミナルと動画を同時に見てられない 若干面倒だったのは、起こしたテキストの整形につかった ChatGPT が、テキストが多いと雑に返すようになって使えなくなることでした。目安として、動画の長さが 15 分を超えるとそれに陥ることが多かったです。その場合は、いったん課金している Claude Code に自然な英語への整形をやらせて、その結果を小分けにして ChatGPT に翻訳させました。 模擬試験 # KodeKloud や Udemy の試験対策コースにはだいたい模擬試験が含まれているので、まずそれは実施しました。その他に、Udemy に模擬試験のみのコンテンツもあるので、それもいくつか購入して受験しました。模擬試験は、基本的に、本試験よりも難易度の低いものがほとんどでしたが、心の準備にはなりました。 最近は、Golden Kubestronaut ができたことで、関連する模擬試験のコースが充実してきたように思います。しかし、学習を始めた初期は、適当な模擬試験のコンテンツが無かったり、あったはずのコンテンツが公開終了してしまったりしたものがありました。その対策用に、Vibe コーディングで、AI に試験問題を作成させるアプリを作りました。 そのアプリは受験期間の序盤こそ使っていたのですが、AI が生成する試験問題が簡単すぎるのと、次第に Udemy の模擬試験のコンテンツが充実してきたので、後半は使う必要がなくなりました。 ハンズオン # OTCA と、試験の直接的な対象となるプロダクトが存在しない CGOA と CNPA 以外は、手持ちの Linux PC で環境を作って、カリキュラムの範囲を確認しました。 Kubestronaut 要件を受験したときには、CKAD や CKA のカリキュラムにクラスタのインストールやアップデートがあったので、確認のための k8s 環境そのものを構築していて手間でした。しかし今回はその必要がなく、minikube や kind のような簡易環境を使って各試験ごとに簡単に環境を作れて楽でした。 LFCS については、クラウドネイティブ関連のプロダクトではなく、Linux 環境の操作を実践することになります。LFCS のカリキュラムに、仮想マシンを作る libvirt が含まれていたので、libvirt で仮想マシンを作って、その上で全体を実践しました。 リファレンス参照 # これは、他の 3 つと比べて、かけた時間は少ないです。文字起こしを導入する以前の ICA, CCA, CAPA あたりまでは、リファレンスを参照して e-learning で捉えきれなかった内容を補完していました。 文字起こしの導入以降は e-learning で理解が十分になったので、それほど、リファレンスまで参照する必要はなくなりました。e-learning の中では説明されない設定項目や、デフォルト値などの仕様が問われることも多少あるので、タイミング的に受験まで日が空くときには、関係しそうなところをチェックしたりしました。 終えてみて # GOLDEN Kubestronaut の称号を得るには、追加要件の試験数が多く、その殆どが英語の試験ということで、到達は難しいだろうと思っていました。しかし、試験の難易度自体はそれほど高くなく、根を詰めれば、それぞれの試験を 1〜2 週間ほどでクリアできると思います。また、試験問題の英文についても、さすがに 10 個受けたら慣れました。 Kubestronaut に到達した時は、k8s のスキルはもとより、特に CKS の学習によってクラウドセキュリティの知識を得られたと感じました。そして今回、GOLDEN Kubestronaut の追加要件に関する学習を通じて、GitOps や、プログレッシブデリバリー。または、オブザーバビリティや IDP など、クラウドネイティブのプラットホームに関する知識を広げることができたと感じています。 この先、GOLDEN Kubestronaut の要件には CNPE が追加になることがすでに明らかになっています。カリキュラムを見るに、おそらく、今回の追加要件の中で学んだプロダクトに関する実技が問われるものになるのではないかと予想します。私はすでに GOLDEN Kubestronaut の称号を得たので、追加でそれに合格する必要はないのですが、是非、チャレンジしてみたいです(情報が集まるまで待って)。 各試験への取り組み # 2025 年 1 月に、Kubestronaut の取得に必要な 5 つの認定資格をクリアしました。その後少しして、GOLDEN Kubestronaut のプログラムが追加になりました。そこで再び、2025 年 7 月から 12 月までかけて、GOLDEN Kubestronaut に必要な 10 個の認定資格をクリアしました。 当初は、2025 年度いっぱいかけてゆっくり取り組むつもりだったのですが、以下の理由により、後半は計画を前倒しして 2025 年の年内に終わらせました。 あまり時間をかけると逆に忘れてしまう 2026/03/01 に CNPE が要件へ加わると難易度が結構高くなりそう 年末年始をゆっくり休みたい OpenTelemetry Certified Associate (OTCA) # 受験日: 2025/07/06 学習日数: 5 日 使った教材: OpenTelemetry Foundations: Hands-On Guide to Observability e-learning OpenTelemetry Certified Associate (OTCA) Practice Exams 模擬試験 公開終了 GOLDEN Kubestronaut を目指すかどうかは決めてはいませんでした。ただ、Kubestronaut の特典で 50%オフのクーポンがあったこともあり、試しに、追加要件の中で興味があった OpenTelemetry を受験しました。 e-learning は量も短めで、CKS の Cilium の学習の中で Hubble に触っていたので、理解は容易でした。学習内容は、メトリクスと OpenTelemetory の基礎。平日の間に e-learning と合わせて模擬試験を実施して、そのまま週末に受験して合格しました。 ざっと学習した程度で合格はできたので、難易度はあまり高くないように感じました。他の試験もこれくらいの難易度なら、すべての認定を取ることはできるだろうと思い、ここで GOLDEN Kubestronaut を目指すことにしました。 Istio Certified Associate (ICA) # 受験日: 2025/08/23 学習期間: 48 日 使った教材: Istio Hands-On for Kubernetes e-learning (日本語字幕あり) Learn Istio Fundamentals e-learning 無料 https://killercoda.com/ica ハンズオン OTCA は試しにさらりと受けたのですが、ICA は、実技試験のため難易度が高いと予想し、時間をかけて準備しました。e-learning やハンズオンに加えて、理解の薄いところはリファレンスを翻訳して理解を深めました。 Istio は、以前に受けた CKS のカリキュラムに含まれてはいるものの、CKS ではどちらかというと Cilium の方が使われるので、Istio そのものについてはあまり学習していませんでした。とは言え、同じくサービスメシュ関連のプロダクトである Cilium の理解があったので、スムーズに学習できました。また、先に OTCA を受験していたので、Kiali や Jaeger あたりのオブザーバビリティに関連するプロダクトの理解も容易でした。 その一方で分かり難かったのは、Istio のトラフィック制御の基本である VirtualService や DestinationRule です。名前と振る舞いがうまく繋がらず、理解に苦しみました。その辺りは Istio 用語として割り切りました。 試験については、ICA には、同じ実技試験の CKA/CKAD/CKS の試験に付帯する Killer.sh のような試験ミュレータはありません。模擬試験としては、Killercoda のハンズオンが助けになりました。 いざ受験の申し込みをしようという段階で、ICA のカリキュラムが更新になるというハプニングがありました(ICA の申込ページをよく見たらそのアナウンスがされてました)。夏季休暇の直前に受験を予定していたのですが、その日がちょうどカリキュラムの切り替え期間の中に当たってしまって、受験ができなくなりました。そのため、受験を延期して夏季休暇後に受験しましたが、アップデート内容のチェックと、覚えたことを忘れないようにするのがちょっと面倒でした。 試験自体は、大筋に変更はなかったので、問題はなかったです。試験の難易度は、CKA や CKAD の同等かすこし低目と感じました。 Cilium Certified Associate (CCA) # 受験日: 2025/09/23 学習期間: 31 日 使った教材: Introduction to Cilium (LFS146) e-learning 無料 Prep Course - Cilium Certified Associate (CCA) Certification e-learning CCA は、CKS の学習のときの Cilium に触れた印象で、ややこしいイメージを持っていました。その印象の主な原因は、Cilium のリファレンスの構成の煩雑さかなと思います。 それはそれとして、e-learning での学習において、CKS と ICA で得た知識が助けになりました。CKS で、CiliumNetworkPolicy や mTLS、Hubble などについては学習済みで、さらに、Falco の学習で得た eBPF の知識が助けになりました。また、ICA については、Istio の Ambient モードの方式が Cilium の方式に近そうなので、Istio の Ambient モードを多少理解していたことが役立ちました。 なお、購入予定だった Udemy の模擬試験コンテンツが公開終了になってしまったのが CCA での誤算でした。心の準備をしたかったので、ICA の学習期間の途中の夏季休暇の間に模擬試験アプリを作っておいて、ここで活用しました。また、ICA の時のように e-learning の後にリファレンスを見て理解を深めようと思ったのですが、冒頭に書いたように、リファレンスの構成がややこしくて思うように整理できませんでした。 試験問題の中には結構細かい内容を問われるものもありましたが、そういった問題の数はそれほど多くなかったかと思います。 Certified Argo Project Associate (CAPA) # 受験日: 2025/10/12 学習期間: 19 日 使った教材: Argo Workflows: The Complete Practical Guide : Unlock DevOps e-learning Argo CD Essential Guide for End Users with Practice e-learning Mastering Argo Rollouts: Progressive Delivery in Kubernetes e-learning https://killercoda.com/argo ハンズオン CAPA は、Argo の 4 つのプロダクト(Workflows, CD, Rollouts, Events)をまとめて題材とする試験です。これについては、試験対策用の e-learning のコースは見つかりませんでした。ただ、Workflows, CD, Rollouts のプロダクトそのものを扱う e-learning が Udemy にあったので、その中の試験カリキュラムに該当するレッスンを視聴して学習しました。Events については e-learning が無かったので、試験カリキュラムの範囲をリファレンスを見て学習しました。もともと Events は全体の中での割合が低いので、問題はないと判断しました。 個人的に、4 つのプロダクトの中で馴染みがあるのは Argo CD と Argo Workflows で、その 2 つ学習は容易でした。とは言え、普段はプライベートでの表面的な利用のみなので、Argo CD の Projects や RBAC など、突っ込んだテーマをここで学びました。Rollouts は初見ですが、プログレッシブデリバリーの知見が多少はあったので、理解は難しくなかったです。ICA で学んだトラフィックシフトの知識が、Rolleouts のトラフィック制御をイメージするのに役立ちました。 CAPA の厄介っどころとしては、「覚えたことがどのプロダクトのものだったかわからなくなる。」という点でした。4 つのプロダクトを同時に学ぶので、仕様の細かい点などは、どのプロダクトのものだったのか曖昧になってしまいました。 e-learning 後、ハンズオンは Argo CD と Workflows については killercoda のコンテンツが充実しているので、まずはそれでざっと実施しました。Rollouts と Event については、手元に環境を作ってハンズオンをしました。模擬試験のコンテンツは見当たらなかったので、CAPA でも念の為、自作の模擬試験アプリで心の準備をしました。 なお Argo Workflows については、 こちらの記事 もご覧いただけます。 GitOps Certified Associate (CGOA) # 受験日: 2025/10/19 学習期間: 7 日 使った教材: Prep Course - GitOps Certified Associate (CGOA) e-learning Introduction to GitOps (LFS169) e-learning https://www.udemy.com/course/certified-gitops-associate-cgoa/ 模擬試験 公開終了 CGOA は、特定のプロダクトを対象とするものではなく、GitOps というテーマを題材とするものです。直前の CAPA で GitOps のプロダクトである Argo CD を学んだ時点で、GitOps に関する知識はおおよそ習得しました。そのため油断して、e-learning と模擬試験をサラリとやって、そのまま試験に望みました。 その結果、合格はしたものの、正答率は 15 個の試験の中で一番低かったです。その原因は、GitOps の理解というより、英語力だと思われます。前述した通り、特定のプロダクトを対象としない CGOA では、プロダクトの特徴や仕様を問われる様な単純な問題が無い代わりに問われる内容が比較的複雑で、問題の英文の理解が難しかったです。CGOA で、「特定のプロダクトを対象としない試験は意外と厄介」と気づきました。 Prometheus Certified Associate (PCA) # 受験日: 2025/11/09 学習期間: 21 日 使った教材: Prep Course - Prometheus Certified Associate (PCA) Certification e-learning Prometheus Certified Associate Practice Exams 模擬試験 PCA が題材とする Prometheus は、これまで何度か、触ってみようとしたことはありました。その度に、「PromQL のややこしさ」がどうにも面倒そうで、深く追求することは避けてきました。しかし、ここに至っては避けることができないので取り組みました。 GCOA の受験で自分の英語力のなさを痛感したので、GCOA をパスしたその日に文字起こしアプリを作成して、この PCA の学習から使い始めました。その結果、e-learning での理解度がかなり向上しました。 PCA の受験では、先に受験した OTCA で得たメトリクスやエクスポーターの知識が役立ちました。Prometheus にはメトリクスの収集の他にもアラートのトリガーや通知の特徴がありますが、その辺りの仕組みは理解しやすかったです。ただ、Histgram と Summary の違い、Relabel Config の振る舞いや演算子など、細かい点がちらほらあるので、その辺はリファレンスを参照して頭に入れておきました。 そして肝心の、PCA の特徴である独自言語の PromQL については、ローカルに作った Prometheus の環境でのハンズオンを通じて理解を深めました。Prometheus の Expression Browser を使って実践し、何度もクエリの記述エラーを吐き出しながら、言語仕様を理解しました。 Certified Backstage Associate (CBA) # 受験日: 2025/11/23 学習期間: 14 日 使った教材: Prep Course - Certified Backstage Associate (CBA) Certification e-learning Introduction to Backstage: Developer Portals Made Easy (LFS142) e-learning 無料 Certified Backstage Associate (CBA): Tests December 2025 模擬試験 CBA は、Backstage という IDP( Internal Developer Portal)を構築するためのプロダクトを題材とするもので、他の試験とはちょっと趣が違っていました。CBA の学習で得た Platform as a Product の考え方は、この後の、CNPA で大きく役立ちました。 Backstage 自体は monorepo 構成の React アプリであり、デザインシステムに Material UI が使われています。そのため、CBA では、IDP の理念や Backstage での IDP 機能とともに、Material UI を使った React アプリの実装に関する知識が問われます。私は Material UI や React アプリの知見があったので、それは問題がなかったです。e-learning に中にもアプリ構築のセッションがあり、他の試験対策講座とはちょっと雰囲気が違ってました。 React アプリの Backstage はローカルでそのまま起動できるので、比較的、実践が容易でした。プラグインの実装やデザインのカスタマイズなどを試して、実装方法を理解しました。 なお Backstage については、 こちらの記事 もご覧いただけます。 Kyverno Certified Associate (KCA) # 受験日: 2025/12/07 学習期間: 14 日 使った教材: Prep Course - Kyverno Certified Associate (KCA) Certification e-learning KCA - Kyverno Certified Associate - Mock Exams 模擬試験 KCA は、確か、学習を始めた当初は e-learning や模擬試験のコンテンツが無かったと記憶しています。そのため、受験の順番を後ろにしていました。その時点では、Kyverno のプロダクトサイトを見て学習するつもりでいたのですが、GOLDEN Kubestronaut ができたからかいつの間にかコンテンツができていたので、それらを利用しました。 KCA の学習では、CKS の学習で得たポリシーの知識が役に立ちました。CKS で扱われたのは OPA/Gatekeeper ですが、考え方や仕組みは類似しているので、理解の助けになりました。OPA/Gatekeeper ではポリシーの記述に Rego が使われていて理解が難しいのですが、Kyverno のポリシーの記述は基本的に yaml と json で、理解しやすかったです。e-learning の講師の口調もゆっくりで、理解しやすかったです。 試験前には手元に k8s の環境を作ってハンズオンをしました。ポリシーの仕様の確認とともに、各コントローラの振る舞いをチェックしました。バックグラウンドスキャンやレポート生成の動きが若干ややこしいので、実際に動かしてその様子を確認しました。 Certified Cloud Native Platform Engineering Associate (CNPA) # 受験日: 2025/12/13 学習期間: 6 日 使った教材: Prep Course - Certified Cloud Native Platform Engineering Associate (CNPA) e-learning CNPA- Cloud Native Platform Associate - Mock Exams 模擬試験 CNPA は、学習を始めた時点では要件になく、後から追加になりました。KCA と同様、当初は e-learning や模擬試験のコンテンツが無く、LFCS よりも後の最後に受験する予定でした。その後、コンテンツができたので、予定を変更して、LFCS よりも先に受験しました。ここに来て、なんとか年内に終わらせたい気持ちが強まり、KCA から一週間で臨みました。 CNPA は、CGOA 同様、特定のプロダクトを対象としない試験です。対象の範囲は結構広くて、GitOps や DevSecOps のような開発・運用に関する理解や、Platform as a Product の理解など、様々な領域を知っておく必要がありました。ここまでに受けた試験の中では、CKS, CGOA, CBA で得た知識が役立ちました。 ちなみに、e-learning の講師がとても早口で理解がしにくかったです。AI を使って翻訳と要約をして、やっとその内容を理解できる感じでした。 そして、CNPA の試験受験で苦労したのは、 問題数の多さ と 問題の英文の難しさ でした。まず、「問題数の多さ」については、他の選択式の試験が 90 分で 60 問であるのに対し、CNPA は 120 分で 85 問でした。e-learning の中で「問題数は 60 問」と説明されていたので、それは表示のバグで実際には 60 問で終わるのかと思ったら、それ以降も終わることなく続いて結局 85 問フルに回答しました。その結果、集中力が乱れ、また、回答を見直す時間はあまり取れませんでした。次に、「問題の英文の難しさ」ですが、特定のプロダクトを対象としない試験であるために、その分、英文が長く難しいです。他の試験と比べて、問題と選択肢の文章の長さが 1.5〜2 倍くらいあったと思います。CNPA の難易度は、英語の得手不得手でだいぶ違うと感じました。 CNPA に至るまで半年勉強してきたので余裕だろうと思っていたのですが、e-learnig と試験の双方で、思いの外手こずりました(主に英語で)。 Linux Foundation Certified System Administrator (LFCS-JP) # 受験日: 2025/12/28 学習期間: 15 日 使った教材: Linux Foundation Certified Systems Administrator - LFCS e-learning https://killercoda.com/lfcs ハンズオン 最後に受験したのは LFCS です。これは Linux そのものの実技を問う試験です。普段から Linux(Ubuntu)は使っていますが、個人利用の範囲ではあまり深い使い方はしないので、足りない部分を e-learning と手持ちの Linux PC でのハンズオンで学習しました。 受験時には、CKAD,CKA,CKS と同様に、killer.sh の試験シミュレータを事前に 2 回使えます。本番対策に非常に有効でした。1 回目は受験の一週間前に使いました。過去の経験で「killer.sh の試験シミュレータの難易度は本番より若干難しめ」と感じるところなので、出題範囲とともに、本番の難易度を予想しました。実際そのとおりだったかと思います。そして受験の前日に 2 回目を使って、(心の準備は)万端で試験に臨みました。 LFCS の試験の特徴としては、他の実技試験(CKAD,CKA,CKS,ICA)と違って、試験中にネット上のマニュアルを参照できません。そのため参照できるのはターミナル上の man と help です。試験対策に、man の操作に慣れておくのと、想定される問題に関する man や help へのたどり着き方を覚えておくと良いと思います。 また、問われている対象が明確に分かるなら、man と help で調べられるのですが、「あれはなんだったか」というようなおぼろげな状況では man と help にたどりつけません。そんな状況に備え、例えば以下のような方法で、対象にたどりつく術を身に着けておくと良いと思います。 Tab 補完の候補であたりをつける 例えば日付に関する問題なら、time や date などと打って Tab 補完すると候補が列挙されるので、そこからあたりをつける。 man の SEE ALSO であたりをつける とりあえず関連しそうなものの man を表示して、man の最後の"SEE ALSO"の候補であたりをつける。 etc 配下を grep で総当り検索 etc 配下を grep の R オプションで階層的に関連しそうなキーワードでテキスト検索して、それらしいファイルを探す。 試験にはそれなりの手応えで全問回答できたので、試験終了の時点で合格を確信しました。24 時間以内にくるはずの通知がなかなか来ずに変だなと思いましたが、ちょっと遅れて合格通知が来ました。その後すぐ年内には GOLDEN Kubestronaut の通知も来て、心置きなく年越しを迎えられました。
はじめに # こんにちは。 最近、個人開発でNuxt.jsを使ったWebアプリ開発をしています。サーバーサイドをどうしようかと検討したところ、Supabaseというフルスタックバックエンドサービスが話題になっていることを知りました。 公式サイト: https://supabase.com/ どうやらFirebaseの代替として注目を集めているバックエンドサービスで、モダンなアプリケーション開発に必要な機能を包括的に提供しているようです。 Nuxt.jsにSupabaseを導入して認証まで意外と簡単にできたので、自分のメモがてら紹介しようと思います。 本記事ではNuxt.jsにSupabaseを導入する方法、そしてメールアドレスによる認証機能の実装方法を紹介します。 Supabaseとは # Supabaseは、PostgreSQLをベースにしたオープンソースのBaaS(Backend as a Service)プラットフォームです。このプラットフォームはリアルタイムデータベース、認証、ストレージなど多様な機能を提供しています。 Supabaseを使えば、バックエンドを自分で開発することなく、すぐにデータベースやユーザー認証を導入でき、フロントエンドの開発だけに集中できます。 SQLが使えるのでデータ管理がしやすく、オープンソースで自由度が高いです。 何より(制限はありますが)無料プランで利用可能なところが魅力的です。 Supabaseの各機能の詳細については、公式ドキュメントや多くの解説記事がありますのでぜひ併せて参照してみてください。個人的には、これほど多機能でありながら導入が驚くほどスムーズで、開発者にとって非常に使い勝手の良いサービスだと感じました。 Supabase導入方法 # それではNuxt.jsにSupabaseを導入してみましょう。まず前提として、下記は既に行っているとします。 公式サイト でユーザー登録をしていること プロジェクトを立ち上げて使用するデータベースがSupabase内にあること まだの方はSupabaseと調べれば色々と出てきますので試してみてください。思ったよりも簡単に登録できると思います。 supabaseを導入前の開発環境が下記になっているとします。 package.json "dependencies": { "@nuxt/scripts": "0.12.1", "@nuxt/ui": "4.0.1", "@tailwindcss/vite": "^4.1.18", "nuxt": "^4.2.2", "tailwindcss": "^4.1.18", "vue": "^3.5.26", "vue-router": "^4.6.4" }, "devDependencies": { "nuxt-icon": "1.0.0-beta.7", "typescript": "^5.9.3" } この状況で、下記コマンドを実行してsupabaseをインストールします。 (※パッケージ管理ツールとしてはpnpmを使用していますが、npmやyarnでも問題ありません) pnpm install @nuxtjs/supabase @supabase/supabase-js インストールしたら、nuxt.config.tsに @nuxtjs/supabase を追加します。 nuxt.config.ts import tailwindcss from "@tailwindcss/vite" export default defineNuxtConfig({ compatibilityDate: '2025-07-15', devtools: { enabled: true }, css: ['./app/assets/css/main.css'], vite: { plugins: [tailwindcss()], }, modules: [ '@nuxtjs/supabase', // これを新しく入れる '@nuxt/ui', 'nuxt-icon', ] }) 次に、Supabaseで作成したプロジェクトのProject URLやAPI Keyを取得します。「Project Settings > Data API」や「Project Settings > API Keys」を確認してみましょう。 Project Settings > Data API Project Settings > API Keys .envファイルを新規作成して、確認したProject URLやAPI KEYを追加します。 .env SUPABASE_URL=<Project URL> SUPABASE_KEY=<Publishable key> --> Information envで設定しているプロパティ名はデフォルトの名称を使用しています。 https://supabase.nuxtjs.org/getting-started/introduction#options もしプロパティ名を別の名前にしたい場合は、nuxt.config.tsにて下記のようにsupabaseのオプションを設定してください。 nuxt.config.ts export default defineNuxtConfig({ // ... supabase: { // Options } } これでSupabaseの導入は完了です。それではNuxt.jsでログインページを作成していきましょう。 メールアドレスによる認証の実装 # これから認証方法の実装に入りたいと思います。 Supabaseの認証方法はGoogleログイン認証やGitHubログイン認証など数多くありますが、今回はサクッと簡単に作りたいのでメールアドレス認証で作ろうと思います。 ページの作りとしては、 こちらのソースコード が非常に参考になりましたので、こちらをベースに解説したいと思います。 Nuxt.js × Supabaseでは、(ログインしていない場合)デフォルトで /login にリダイレクトします。そのためpagesディレクトリには下記を作成する必要があります。 vueファイル 説明 login.vue ログインや新規登録をするページ index.vue ログインした後に遷移するページ またログアウトする機能も必要ですが、そちらはcomponentsディレクトリにAppHeaderコンポーネントを用意してヘッダーにログアウト機能を追加します。 vueファイル 説明 AppHeader.vue ヘッダーコンポーネント。ログアウト機能を追加します。 app.vue # pagesディレクトリに色々作成しないといけないので、まずapp.vueを下記のようにします。 app.vue <template> <UApp> <NuxtLayout> <NuxtPage></NuxtPage> </NuxtLayout> </UApp> </template> layouts/default.vue <template> <div> <AppHeader /> <UMain> <slot /> </UMain> </div> </template> --> Information <UApp> や <NuxtLayout> などはNuxtUIというライブラリのUIコンポーネントです。 下記では特に断りなくNuxtUIのコンポーネント群を使用しています。 ログインページ # 次にログインページを作成します。下記がlogin.vueの全体像です。 login.vue <script setup lang="ts"> import type { AuthError } from '@supabase/supabase-js'; /** Supabaseクライアントのインスタンス */ const supabase = useSupabaseClient(); /** ログインユーザー情報 */ const user = useSupabaseUser(); /** 通知(トースト)機能の利用 */ const toast = useToast(); /** 表示モードの切り替え(in: ログイン、up: 新規登録)*/ const sign = ref<'in' | 'up'>('in'); watchEffect(() => { // ユーザーが認証済み(ログイン中)の場合、トップページへリダイレクト if (user.value) { return navigateTo('/'); } }); // フォームの入力項目定義 const fields = [ { name: 'email', label: 'Email', type: 'text' as const, placeholder: 'メールアドレスを入力してください', required: true, }, { name: 'password', label: 'Password', type: 'password' as const, placeholder: 'パスワードを入力してください', }, ]; /** * メールアドレスとパスワードによるログイン処理 * * @param email メールアドレス * @param password パスワード */ const signIn = async (email: string, password: string) => { const { error } = await supabase.auth.signInWithPassword({ email, password, }); if (error) { displayError(error); } }; /** * 新規ユーザー登録処理 * * @param email メールアドレス * @param password パスワード */ const signUp = async (email: string, password: string) => { const { error } = await supabase.auth.signUp({ email, password, }); if (error) { displayError(error); } else { toast.add({ title: 'Sign up successful', icon: 'i-lucide-check-circle', color: 'success', }); await signIn(email, password); } }; /** * 認証エラーをトースト通知として表示 * * @param error Supabaseから返却される認証エラーオブジェクト */ const displayError = (error: AuthError) => { toast.add({ title: 'Error', description: error.message, icon: 'i-lucide-alert-circle', color: 'error', }); }; /** * フォーム送信時のハンドラー * * @param payload フォームから渡される入力データ(emailやpassword) */ async function onSubmit(payload: any) { const email = payload.data.email; const password = payload.data.password; if (sign.value === 'in') { // ログインの場合 await signIn(email, password); } else { // 新規登録の場合 await signUp(email, password); } } </script> <template> <UContainer class="h-[calc(100vh-var(--ui-header-height))] flex items-center justify-center px-4" > <UPageCard class="max-w-sm w-full"> <UAuthForm :title="sign === 'in' ? 'ログイン' : '新規登録'" icon="i-lucide-user" :fields="fields" @submit="onSubmit" > <template #description> {{ sign === 'up' ? '既にアカウントをお持ちの方は' : '新規登録の場合は' }} <UButton variant="link" class="p-0" @click="sign = sign === 'up' ? 'in' : 'up'"> こちら </UButton> </template> <template #submit> <div class="flex items-center justify-center"> <UButton type="submit" class="justify-center cursor-pointer w-80"> {{ sign === 'up' ? '新規登録' : 'ログイン' }} </UButton> </div> </template> </UAuthForm> </UPageCard> </UContainer> </template> コードを上から順を追って解説していきます。 最初にsupabaseクライアントの準備とログイン状態に応じたリダイレクト処理を行います。 /** Supabaseクライアントのインスタンス */ const supabase = useSupabaseClient(); /** ログインユーザー情報 */ const user = useSupabaseUser(); /** 通知(トースト)機能の利用 */ const toast = useToast(); /** 表示モードの切り替え(in: ログイン、up: 新規登録)*/ const sign = ref<'in' | 'up'>('in'); watchEffect(() => { // ユーザーが認証済み(ログイン中)の場合、トップページへリダイレクト if (user.value) { return navigateTo('/'); } }); またログインフォーム(UIコンポーネント UAuthForm )に渡すための入力項目を定義します。 // フォームの入力項目定義 const fields = [ { name: 'email', label: 'Email', type: 'text' as const, placeholder: 'メールアドレスを入力してください', required: true, }, { name: 'password', label: 'Password', type: 'password' as const, placeholder: 'パスワードを入力してください', }, ]; 次にSupabaseのauthライブラリを用いた認証部分の実装をします。 ログイン処理では signInWithPassword メソッド、新規登録には signUp メソッドを使用して、引数にはemailとpasswordを指定します。 /** * メールアドレスとパスワードによるログイン処理 * * @param email メールアドレス * @param password パスワード */ const signIn = async (email: string, password: string) => { const { error } = await supabase.auth.signInWithPassword({ email, password, }); if (error) { displayError(error); } }; /** * 新規ユーザー登録処理 * * @param email メールアドレス * @param password パスワード */ const signUp = async (email: string, password: string) => { const { error } = await supabase.auth.signUp({ email, password, }); if (error) { displayError(error); } else { toast.add({ title: 'Sign up successful', icon: 'i-lucide-check-circle', color: 'success', }); await signIn(email, password); } }; エラー時にはトースト通知として表示するようにメソッドを作っています。 /** * 認証エラーをトースト通知として表示 * * @param error Supabaseから返却される認証エラーオブジェクト */ const displayError = (error: AuthError) => { toast.add({ title: 'Error', description: error.message, icon: 'i-lucide-alert-circle', color: 'error', }); }; フォームの送信ボタンが呼ばれたら、表示モードの状態に合わせて上記の signIn メソッドと signUp メソッドが呼ばれるようにします。 /** * フォーム送信時のハンドラー * * @param payload フォームから渡される入力データ(emailやpassword) */ async function onSubmit(payload: any) { const email = payload.data.email; const password = payload.data.password; if (sign.value === 'in') { // ログインの場合 await signIn(email, password); } else { // 新規登録の場合 await signUp(email, password); } } 最後にNuxtUIを利用してログイン用のテンプレートを作成します。表示モードに合わせてログインか新規登録を切り替えるようにしました。 <template> <UContainer class="h-[calc(100vh-var(--ui-header-height))] flex items-center justify-center px-4" > <UPageCard class="max-w-sm w-full"> <UAuthForm :title="sign === 'in' ? 'ログイン' : '新規登録'" icon="i-lucide-user" :fields="fields" @submit="onSubmit" > <template #description> {{ sign === 'up' ? '既にアカウントをお持ちの方は' : '新規登録の場合は' }} <UButton variant="link" class="p-0" @click="sign = sign === 'up' ? 'in' : 'up'"> こちら </UButton> </template> <template #submit> <div class="flex items-center justify-center"> <UButton type="submit" class="justify-center cursor-pointer w-80"> {{ sign === 'up' ? '新規登録' : 'ログイン' }} </UButton> </div> </template> </UAuthForm> </UPageCard> </UContainer> </template> 最終的に出来上がったテンプレート部分が下記になります。 メインページ # 次にログイン後に遷移するメインページを作成します。今回は例としてユーザーが書いたブログ記事の一覧を表示するページを作成しています。 index.vue <script setup lang="ts"> import type { Database } from '#build/types/supabase-database'; import type { TableColumn } from '@nuxt/ui'; /** Supabaseクライアントのインスタンス */ const client = useSupabaseClient<Database>(); /** ログインユーザー情報 */ const user = useSupabaseUser(); /** * 記事一覧の取得 */ const { data: articles } = await useAsyncData( 'articles', async () => { const { data } = await client .from('article') .select('*') .eq('uuid', user.value!.sub) .order('regist_date'); return data ?? []; }, { default: () => [] } ); /** * テーブルのカラム定義 */ const columns: TableColumn<any, any>[] = [ { accessorKey: 'id', header: 'ID' }, { accessorKey: 'regist_date', header: '日付' }, { accessorKey: 'title', header: 'タイトル' }, { accessorKey: 'abstract', header: '概要' }, ]; </script> <template> <UContainer> <UPageSection title="記事一覧" description="最新記事を表示します" headline="ブログ"> <div class="flex justify-center items-center"> <div v-if="articles.length > 0"> <UCard variant="subtle"> <UTable :data="articles" :columns="columns"> </UTable> </UCard> </div> </div> </UPageSection> </UContainer> </template> コードを上から順を追って解説していきます。 最初にログインページと同じようにsupabaseクライアントを行います。 /** Supabaseクライアントのインスタンス */ const client = useSupabaseClient<Database>(); /** ログインユーザー情報 */ const user = useSupabaseUser(); 今回はSupabaseで作成したarticleテーブルのデータを表示する機能を実装します。そのため、Supabaseクライアントを生成する際に自動生成した型定義ファイルを適用して「Database型」を指定しています。こうすることでテーブル名やカラム名に入力補完が効くようになり、開発効率が格段にアップします。 --> Information 型定義ファイルはSupabase CLIを利用することによって生成できます。 まず下記コマンドを実行してSupabaseのログインと初期化をします。 npx supabase login npx supabase init その後、下記コマンドを実行すると、型定義ファイルが生成されます。 npx supabase gen types typescript --project-id "<project_id>" --schema public > .\app\types\database.types.ts 次に記事一覧を取得する機能を実装します。ログインユーザー情報 user にあるuuidを user.value!.sub で取得して、下記のようにユーザーに紐づいている記事を取得するようにしました。 また記事一覧をテーブル形式で表示するために、テーブルのカラムを定義しています。 accessorKey はarticleテーブルのカラムと一致するように設定して、 header はテーブルのヘッダーに表示する名称を設定します。 /** * 記事一覧の取得 */ const { data: articles } = await useAsyncData( 'articles', async () => { const { data } = await client .from('article') .select('*') .eq('uuid', user.value!.sub) .order('regist_date'); return data ?? []; }, { default: () => [] } ); /** * テーブルのカラム定義 */ const columns: TableColumn<any, any>[] = [ { accessorKey: 'id', header: 'ID' }, { accessorKey: 'regist_date', header: '日付' }, { accessorKey: 'title', header: 'タイトル' }, { accessorKey: 'abstract', header: '概要' }, ]; 最後にテンプレート部分を作成します。 <template> <UContainer> <UPageSection title="記事一覧" description="最新記事を表示します" headline="ブログ"> <div class="flex justify-center items-center"> <div v-if="articles.length > 0"> <UCard variant="subtle"> <UTable :data="articles" :columns="columns"> </UTable> </UCard> </div> </div> </UPageSection> </UContainer> </template> ヘッダーコンポーネント # 最後にログアウト機能を実装します。こちらの機能はヘッダー部分(components > AppHeader.vue)に実装しました。 AppHeader.vue <script setup lang="ts"> /** Supabaseクライアントのインスタンス */ const client = useSupabaseClient(); /** ログインユーザー情報 */ const user = useSupabaseUser(); /** * ログアウト処理 */ const logout = async () => { await client.auth.signOut(); navigateTo('/login'); }; </script> <template> <UHeader :toggle="false"> <template #left> <span class="font-bold text-lg">Demo</span> </template> <template #right> <UButton v-if="user" variant="link" class="cursor-pointer" @click="logout"> ログアウト </UButton> <UButton v-if="!user" variant="link" to="/login"> ログイン </UButton> </template> </UHeader> </template> ログアウト処理はかなり単純で、ただsupabaseクライアントで signOut メソッドを使って実装するだけです。あとはテンプレート部分にログアウトボタンを追加することで、ログアウトできてしまいます。 メインページと合わせて実際に出来たページがこちらになります。 以上でメールアドレスによる認証が実装できました。 メールアドレスによる認証の検証 # それでは実際に画面上で新規登録してみましょう。 ログインページでメールアドレスとパスワードを入力して新規登録ボタンを押すと、認証メールが届きます。 こちらの「Confirm your mail」のリンクを押すと、ユーザー登録が完了し、アプリのメインページにリダイレクトします。 またユーザ登録が完了しているかは、Supabaseで作成したプロジェクトの「Authentication > Users」で確認できます。データが列として入っている場合は登録が完了しています。まだリンクでの認証が済んでいない場合は、Last Sign Inの列でWaiting for verificationと表示されます。 まとめ # 今回はNuxt.jsとSupabaseを組み合わせたauth認証の実装を解説しました。特に意識したところもなく、簡単にサクッと実装できたのが今回の驚きでした。 バックエンドの開発工数を最小限に抑えつつ、安全な認証を簡単に実装できるのはかなり魅力的ですね。 今回はメールアドレスによる認証のみ解説しましたが、他にもGoogleやGitHubなどの認証も簡単に導入できます。 よかったらそちらも試してみてください。 補足:ログインしないで閲覧できるページがほしい場合 # 基本的に、紹介した方法でNuxt.jsとSupabaseを利用した認証できます。しかし、こちらの方法だとログインをしていない場合、必ずログインページにリダイレクトされてしまいます。ですが、たまにログインしないでも閲覧できるページもほしい場合があると思います。 その時の設定方法も、実は非常に簡単でnuxt.config.tsに下記を付け足せばよいです。 export default defineNuxtConfig({ // ~~~省略~~~ supabase: { redirectOptions: { login: '/login', callback: '/confirm', include: [], exclude: ['/'], // ここの部分がログインしなくても閲覧できるページ cookieRedirect: false, }, }, // ~~~省略~~~ }) こちらを設定すると、 exclude の部分で設定したページについてはログインする必要はありません。 ぜひお試しください! 参考文献 # Supabase公式サイト Nuxt Supabase導入公式サイト ログインフォームを作る際にこのサイトで紹介しているDemoのソースコードが非常に参考になりました。 Todo list example using Supabase and Nuxt 3 Supabaseを布教したい Supabaseとは?初心者向けに分かりやすく解説! Supabase + Nuxt 3でチャットアプリを作ってみた Nuxt + Supabase で Googleログイン機能を作ってみる 話題のSupabaseでサクッと認証機能をつくってみた! こちらはNext.jsによる実装ですが、参考になりました。
2025年9月、SysML Version 2.0(SysML v2)が正式リリースされました。 「SysML v2を試してみたい」と思っても対応しているツールは高価だったり、汎用の描画ツールで SysML v2のモデルを作成してみてもいまいちピンとこなかったりといった経験はないでしょうか。 本記事では「SysML v2のグラフィカル記法がどんなものか試してみたい」という時におすすめのツール SysONをご紹介します。 SysONとは # SysON(読みは シスオン または スィスオン )は、SysML v2の主にグラフィカル記法を作成、編集するためのツールです。 この名前は、「システムにオンする」と「システムモデリングの新しいシーズン(seasonとsysonはやや音が似ている)」というのが由来だそうです。 SysONのソースコードは GitHub で公開されています。 ライセンスは EPL-2.0です。 GitHubのリポジトリ名(eclipse-syson / syson)からわかるとおり、このツールは Eclipse財団の SysONプロジェクトで開発・保守されています。 この SysONプロジェクトはフランスの OBEO社と CEA(フランス原子力・代替エネルギー庁)が主導し、実開発は OBEO社が担っています。 ちなみに、「OSSツール、フランス、Eclipse財団」といえば、UML2モデリングツールである Papyrus を思い浮かべる方もいるかもしれません。 日本では認知度の低いツールですので知らない方も結構いらっしゃるのではないかと思います。 実はこの Papyrusの開発も SysONと同じ OBEO社が担っています。 Papyrusは SysML v1をサポートしているので、SysML v1を使いたいなら Papyrus、SysML v2を使いたいなら SysONという棲み分けになっているのかなと思います。 SysONの構成 # SysONは Webアプリケーションです。 ユーザーはクライアントPCの Webブラウザで SysONサーバーにアクセスします。 ユーザーが Webブラウザで行ったモデルに対する操作は SysONサーバーで実行されます。 複数のユーザーによるモデリングが可能ですし SysML v2仕様には REST APIの要件もありますので、Webアプリケーションは妥当だと思います。 しかしその一方、ネットワーク環境によっては動作が遅くすぐに表示が更新されないといったデメリットもあるため、モデリングの操作に慣れてくるとストレスを感じることもあるかもしれません。 マニュアルに記載されているサポートする Webブラウザは Google Chromeと Firefoxの最新安定版です。 Safari、Microsoft Edge、Operaなど他のブラウザを用いる場合は使えるかどうか検証してからがよいでしょう。 英語ですが、SysONの ユーザーマニュアルに該当するドキュメント もあります。 インストール # 事前準備 # まずはどのリリースをインストールするかを決めましょう。 リリースは Eclipse SysONの Webサイト に記載されています。 GitHubの Tags を確認するといくつもの Tagがありますが、末尾に ".0" が付いているものが安定版の位置づけになります。 本記事では、安定版である v2025.8.0をインストールします。 インストール方法は マニュアル(v2025.8.0) に記載されています。 マニュアルにはインストール方法が4つ記載されていますが、大きく分けるとローカルテスト用と本番用の2タイプです。 セキュリティを気にしないならばローカルテスト用、セキュリティを考慮すべき環境ならば本番用の方法でインストールしましょう。 本記事は SysML v2を試しに使ってみることを想定していますので、 Basic Local Test Setup のインストールを行います。 SysONのローカルテスト用インストールには Docker Engineを使用します。 Docker Desktopは有償ですが、Docker Engineは Apache License 2.0ですので無料で利用できます。 ここでは Docker Engineのインストール方法は割愛します。 筆者は Windows11とその WSL2(Debian/Linux)に Docker Engineをインストールしました。 Docker Engineのインストールが完了したら SysONのインストールを開始します。 docker-compose.ymlを取得する # Webブラウザで GitHubにある SysONの Webページ にアクセスして、docker-compose.ymlをダウンロードします。 curlコマンドを用いて docker-compose.ymlをダウンロードする場合は以下の通りです。 curl -OL https://raw.githubusercontent.com/eclipse-syson/syson/refs/tags/v2025.8.0/docker-compose.yml dockerを起動する # Docker Engineのサービスを起動するにあたって、現状の確認をしましょう。 serviceコマンドで dockerサービスの状態を確認します。 sudo service docker status dockerサービスが起動していない場合は以下のメッセージが表示されます。 Docker is not running ... failed! Docker Engineのサービスを起動します。 sudo service docker start 再び、サービスの状態を確認してみましょう。 Docker is running. dockerサービスが起動しました。 先程ダウンロードした docker-compose.ymlファイルのあるフォルダで以下のコマンドを実行します。 docker compose up SysONサーバーが bootすると、コンソールログの一部に以下のロゴが出力されます。 app-1 | _____ ____ _ __ app-1 | / ___/ __ __ _____ / __ \ / | / / app-1 | \__ \ / / / // ___// / / // |/ / app-1 | ___/ // /_/ /(__ )/ /_/ // /| / app-1 | /____/ \__, //____/ \____//_/ |_/ app-1 | /____/ app-1 | app-1 | :: Spring Boot :: (v3.5.0) app-1 | 起動が正常に完了すると、以下のメッセージが表示されます。 app-1 | 2025-12-01T06:45:59.914Z INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/' app-1 | 2025-12-01T06:45:59.937Z INFO 1 --- [ main] org.eclipse.syson.SysONApplication : Started SysONApplication in 18.896 seconds (process running for 19.808) Tomcat started on port 8080 (http) は Webサーバーである Apache Tomcatが起動したことをあらわします。 SysONサーバーが起動したら、いよいよ Webブラウザから SysONサーバーアクセスしてみましょう。 最初の画面 # Webブラウザを起動し、 http://localhost:8080 にアクセスします。 以下のホーム画面が表示されれば準備完了です。 ちなみにこの画面の Existing Projectsのリストにある "Batmobile"は、あのアメコミヒーローが使っている車を題材にしたサンプルです。 終了する # SysONサーバーを起動したシェルで Ctrl + Cすると SysONサーバーが終了します。 dockerサービスを停止する場合は、以下のコマンドで停止します。 sudo service docker stop 次回予告 # ここまでで SysONを使ってモデリングする準備が整いました。 次回からはいよいよ、SysONを使った SysML v2のモデリング操作をみていきましょう。
1. はじめに # まず、この記事を書こうと思ったきっかけですが、次の2点になります。 最近読み始めた書籍『 ソフトウェアエンジニアガイドブック 』で、著者が「業務日誌をつけること」を勧めているから。 私自身も業務日誌をつけているので、改めて理由(動機)を考えてみましたが、単に習慣でつけているだけで、目的意識があって業務日誌をつけていないと考えたため。 ですので、この記事で次の2点を自分なりにまとめてみます。 業務日誌をつけることで何が嬉しいのか、また、逆に何が嬉しくないか。 業務日誌をつけるためのポイント。 エンジニアの方はプロジェクトで業務日誌をつけられている方も多くいらっしゃるかと思いますが、 そうでない方にも、この記事を通じて、業務日誌に興味を持っていただければと幸いです。 2. 業務日誌をつけることで何が嬉しいのか😄 # こちらについて、書籍の内容と私自身の考えについて記載します。 1. 書籍に書かれていた業務日誌を勧める理由(要約) # まず、書籍に書かれていた内容を要約すると、以下の3つです。 作業が管理しやすくなる。 作業の一覧を作成しておくと、作業の優先順位がつけやすい。 また、作業が割り込んできた時にも、作業の調整がしやすくなる。 一日の終わりに仕事を終えることに満足感がある。 その日の作業内容を記録することで、一日の仕事を客観的に捉えることができる。 業績評価に利用できる。 自分の過去の作業を振り返ることができる(半年前の作業とかはすぐには思い出せない)。 面談などで上司に説明する際の資料となる(成果を効率的に説明できる)。 2. 上記に対する私の所感 # 上述のお勧めの理由に関する私の所感としては、以下のとおりです。 1.の「作業を管理しやすくなる」というのは実感があります。作業を列挙すると優先順位が決めやすくなります。 2.の「仕事を終えることに満足感がある」についても分かります。作業が数日に渡る場合でも、その日ごとの作業内容が分かるので、作業が進んでいるように感じられます。 3.の「業績評価に利用できる」については、そういった発想自体がなかったので、これは試してみたいと思います。 3. 私が業務日誌を勧める理由 # 次に、私自身が業務日誌を勧める理由を挙げたいと思います。 1日の作業を始めやすくなる。 事前に作業予定を立てておくと、当日、何から作業を始めればいいかがわかりやすくなると思います。 とくに、休日を挟むなどして時間が空いた場合に効果的だと思います。 成果を意識しながら、作業へ取り組むようになる。 業務日誌には、作業結果(成果)を記載することになります。 ですので、作業時に成果を出さないと、業務日誌に記載する内容が欠落することになります。 すると、作業時に成果を出すことを意識して作業に取り組むように意識づけることになると思います。 インサイト(気づき)が得られる。 毎日、作業の記録をつけていると、色々と思うところがあったりもします。 上述のように、作業に対して、明確な成果がないことに気づくこともあります。 また、優先度の低い着手中の作業が、延々と残っていることに気づく場合もあります。 3. 業務日誌をつけることで何が嬉しくないか😖 # ここまでは、業務日誌の良い点について記載してきました。 しかし、実際に業務日誌をつけ始めると、以下に挙げるような問題が発生することもあると思います。 1. 業務日誌をつけることが負担になる # 業務が忙しいときほど、業務日誌を書く時間を確保するのが難しくなります。 つい後回しにしてしまい、気づけば数日分まとめて書く羽目になることも少なくないと思います。 私も社会人1年目の時に、OJT担当の先輩に言われて、業務日誌をつけていました。 ただ、炎上したプロジェクトの開発中、 夜23時過ぎの退社前に業務日誌を書くのは嬉しくなかったです。 2. 何を書けばいいかはっきりしない # 「TODO」「優先度」「進捗」など、どこまで細かく書けばよいのか迷うことがあります。 TODOリストとの違いも曖昧 [1] で、単なる作業の羅列になってしまうことも。 上述の業務日誌(社会人1年目)は、部内限定公開のブログサービスを使用していました。 ただ、ブログ(フリーフォーマット)だったので、何をどのように書くか、よく悩んでいたように思います。 3. 何のために書いているのか分からないことも # 業務の中で指示されて業務日誌をつけることもありますが、 目的や理由が明確でないと、モチベーションが続かないかもしれません。 上述の業務日誌(社会人1年目)の場合、 先輩曰く、「毎日業務日誌をつけることでインサイト(気づき)が得られるから」ということでした。 ただ、それでも上記の要因があったので、 正直、業務日誌をつけるのが苦痛に感じられることも多々ありました。 4. 業務日誌をつけるためのポイント✍️ # 最も重要なのは、業務日誌をつけることが負担とならないこと、に尽きると思います。 そのために、以下のようなポイントを押さえておくといいかもしれません。 1. 記載内容は事前に決めておく(テンプレ化する。) # 毎日、書くことになるので、内容は事前に決めておくといいと思います。 私は、「本日の作業内容」と「明日の作業内容」を書くようにしています。 2. 書きすぎない。 # 多くのことを書こうとすると、負担感が出ますので、 必要最低限なことだけを書くようにしたほうがいいと思います。 私は基本的に、「本日の作業内容」と「明日の作業内容」を記載していますが、 必要がある場合のみ、次の内容を追加で記載しています。 作業の成果物(誰かと作業を共有する必要がある場合のみ) 進捗度(作業が日をまたぐ場合) 完了予定日(作業に明確な締切がある場合) 3. 誰かと共有する。 # 誰かに読んでもらう前提があると、付け忘れしにくくなります。 ですので、読んでもらう必要がないとしても、業務日誌を共有するようにするといいと思います。 私も業務日誌をSlackでチームリーダーにメンションしています。 (都度リアクションをくれるので、とても助かっています😊) なお、業務日誌はテキストベースが無難かと思っています。 理由としては、その日ごとに記載内容を微妙に変えたいことがあるためです。 その辺りを踏まえると、Slackで業務日誌を作成するのは悪くないと思っています。 誰かと共有するのも簡単ですので。 5. まとめ📒 # 業務日誌をつけることには、いくつかの利点があるはずです。 ですので、業務日誌をつけておいて損はないはずです。 とはいえ、業務日誌をつけるのは難しい面もあると思うので、 継続するための工夫も必要かと思います。 この記事を読んでいただいて、業務日誌をつけることに興味を持たれましたら、 ぜひ試してみていただければと思います。 💭少し脱線しますが、私個人の見解としては、 TODOリストが「やるべき作業を管理するためのもの」だとすると、 業務日誌は「その作業が業務として意味を持っているかを見直すためのもの」 だと言えるかもしれません。 一口に作業と言っても、業務(仕事として)行うのであれば、 ちゃんと意味のある作業に取り組む必要があるはずです。 ↩︎
あけましておめでとうございます。 2025年もご愛読いただきありがとうございました。本年も豆蔵デベロッパーサイトをよろしくお願いします。 記事数・執筆者数 # この3ヶ月で49本の記事が投稿され、記事数は843になりました。新たに4名が執筆デビューし、累計75名になりました。 テーマ別の記事 # ロボット # /robotics/twincat/introduction-chapter2/twincat-introduction-chapter2/ /blogs/2025/12/10/ceres-solver/ /robotics/bizen/bizen_introduction/ ローカル LLM # /blogs/2025/10/14/local_rag_on_lm_studio/ /blogs/2025/10/15/local_rag_on_lm_studio_part2/ プログラミング言語 # /blogs/2025/10/16/csharp_di/ /blogs/2025/12/09/jspecify/ Q Developer # /blogs/2025/11/12/qdev_beginner_day1/ /blogs/2025/11/17/qdev_beginner_day2/ /blogs/2025/11/21/qdev_beginner_day3/ /blogs/2025/11/28/qdev-aidd-spec-kit/ /blogs/2025/12/11/amazon_q_collaborative_writing/ 仕様駆動開発 # /blogs/2025/12/16/github-spec-kit-iac-entry/ /blogs/2025/12/24/kiro-sphinx-sdd/ CI/CD # /blogs/2025/11/16/github-immutable-releases/ /blogs/2025/11/17/cd-pipeline-for-ubuntu-desktop/ テスト # /blogs/2025/12/17/kiro_ide_pbt/ /blogs/2025/12/19/edu-user-dept-training-1/ パブリッククラウド # /blogs/2025/12/12/google_cloud_entry/ /blogs/2025/12/22/aws-controltower-deepdive/ /blogs/2025/12/22/aws-controltower-deepdive/ /blogs/2025/12/23/aws_all_certified_2025/ /in-house-project/sss/webhook-with-sqs/ モデリング # /blogs/2025/12/05/modeling-forum-2025-report/ アーキテクチャ # /blogs/2025/12/08/hexagonal_questions/ アジャイル # /blogs/2025/12/04/scrum-ai-1/ /blogs/2025/12/18/sushi/ GitHub Copilot # /blogs/2025/10/30/intro-to-github-copilot-cli/ 開発環境構築 # /blogs/2025/10/13/write-java-with-vscode-2025/ 個人開発 # /blogs/2025/10/13/python-game/ /blogs/2025/12/01/porting-an-electron-app-to-tauri2/ /blogs/2025/12/03/customize-markdown-preview-style-with-agent-skills/ 書籍紹介 # /blogs/2025/12/02/think-again/ ヘルスケア # /blogs/2025/12/25/Vitality/ アドベントカレンダー2025 # アドベントカレンダー2025が開催され、バラエティ豊かな19記事が公開されました。公開された各記事は本記事内でも紹介しています。 /events/advent-calendar/2025/ さいごに # 以上、2025年度第3四半期のサマリーでした。 よかったら フィード の購読、 X や Bluesky でのフォローもお願いします。 Facebook でも本サイトの注目記事をはじめ豆蔵に関するイベントを紹介しています。 note にも時々本サイト関連の記事が掲載されています。
これは 豆蔵デベロッパーサイトアドベントカレンダー2025 第25日目の記事です。 ※本件はテック系の記事ではありません。 食事を気にしていても週一でバーガーキングのワッパーは食べる石原です。 デベロッパーの皆さん、歩いてますかー! 本件は普段の生活の中で以下が思い当たる方を対象としています。 仕事はリモートワーク 休日は家にいる時間の方が多い 別段運動する習慣もなし 1日の平均歩数は1,000歩以下 ジャンキーで美味しいものを食べるのが大好き 「体を動かしたい」という気持ちはあるが、行動に移せずにいる これらはすべて、数ヶ月前までの私そのものです。 そんな私が現在(2025年12月時点)では以下のような生活に変わりました。 毎日12,000歩のウォーキング、またはジムでの筋トレを継続 「歩くこと」が全く苦にならなくなった 食生活で総カロリーやPFCバランスを自然と意識するように 体重は2kg減 食欲は以前よりさらに増して健康的に 今回は、私がこのような変化に至った経緯と、「運動したいけど一歩が出ない」と同じ悩みを持つ皆さんに、ぜひ共有したいエピソードを書いていこうと思います。 きっかけはVitality # 2025年9月末、総務の方から全社向けに「Vitalityプログラム」の参加者募集の案内が届きました。 どうやら健康経営の一環として外部サービスを導入し、社員の健康を促進したいという試みのようです。 元々「体を動かしたい」と思ってはいたものの、きっかけがなくて動けなかった自分。そんな私の背中を強烈に押したのは、案内の中にあったこの一言でした。 「ランキング表彰を実施し、忘年会で豪華景品を授与予定です!」 これを見た瞬間、「やるしかねぇ!」と思った自分は即日で参加を表明し、2025年10月から私のウォーキング生活が幕を開けたのです。 Vitalityとは? # 住友生命が提供する健康増進プログラムで、豆蔵が導入したのは「 Vitalityスマートプログラム(福利厚生タイプ) 」です。 詳細については公式HPに譲りますが、簡単に言うと「歩数や心拍数をアプリで計測してポイントを貯める」仕組みです。貯まったポイントに応じて、一週間ごとに以下のような特典(リワード)がもらえます。 スターバックスの500円クーポン 各コンビニの500mlペットボトルのお茶 / ローソンの飲むヨーグルト 各種団体への寄付 など デイリーで獲得できるポイントは(イベントを除いて)最大 60pt 。 取得条件は以下の通りです。(各項目のうち最も高いポイントのみが適用され、重複獲得は不可) 私の目標は至ってシンプル。 「毎日60ptを死守していれば、入賞できるはず!」 そう信じて、12月の忘年会まで「毎日60pt」を取り続ける生活が始まりました。 (結果的にはほぼ1万2000歩を歩くことで取得しました) 社内での取り組み # 豆蔵社内ではVitality参加者に向けて、Slackに専用チャンネルを開設し、定期的にランキングを発表する取り組みが行われました。 ランキングの名前について、希望者についてはあだ名が設定できたので、私は「汗かいた後のビールは最高🍺」で登録しました。 用意したアイテム # 「1日1,000歩」から脱却するために、私が実際に揃えた「三種の神器(+α)」を紹介します。 1. スマートウォッチ(ウェアラブルデバイス) # スマートフォンでも歩数は測れますが、 心拍数 は計測できません。Vitalityのポイント効率を考えると、「歩数」を稼ぐよりも「高強度の運動(心拍数上昇)」を30分行う方が圧倒的にタイパが良いです。 (歩数だと大体30分で4000歩、1万2000歩なら1.5時間が必要) 元々「スマートウォッチはいらない派」だったのですが、いざ付けてみると自分の活動が可視化され、モチベーション維持に大きく貢献してくれました。未導入の方には強くおすすめします! 2. ランニング・ウォーキングシューズ【最重要】 # ここへの投資が一番重要と言っても過言ではありません。 運動不足の人が普通のスニーカーで長時間歩くと、高い確率で足腰を痛めます(経験談)。最近のシューズはクッション性が凄まじいので、まずはここから新調しましょう。 以下は私が実際に購入した靴の紹介です。 Fresh Foam X 880v14 GORE-TEX® (New Balance) 黒スニーカーなので普段使いもOK。GORE-TEX素材なので、急な雨でも足元が快適なのが最高です。 Cloudmonster (On) クッション性が異次元です。「雲の上を歩く」ような感覚で、長距離を歩く予定の人には全力でおすすめします。 3. YouTube プレミアム # ウォーキングの時間を「運動の時間」ではなく「娯楽の時間」に変えてくれる魔法のツールです。 オフライン再生 と バックグラウンド再生 ができるため、通信量を気にせず動画を「聴きながら」歩けます。 Tips: 「スマート一時保存機能」をオンにしておけば、お気に入りのチャンネルの新着動画が自動でダウンロードされるので、家を出る前の準備も不要になります。 4. その他の小物 # 帽子: 寝起きの爆発した髪を隠してくれる頼れる相棒。蒸れやすいので通気性重視で選びましょう。 動きやすい服装: 基本は何でもOKですが、軽いアウターがあると体温調節がしやすく、脱いでも荷物にならないので便利です。 ワイヤレスイヤホン: 動画視聴のお供に。ただし、歩道が狭い場所では安全のために「片耳視聴」や「外音取り込みモード」を活用しましょう。 毎日歩くコツ # 2ヶ月間、ほぼ毎日1万歩以上を歩き続けて見えてきた、習慣化のポイントをまとめます。 1. 動画視聴の時間を歩く時間に # 普段、家で1時間以上じっくり動画を見ている方に朗報です。その時間をそのまま歩く時間にしましょう。 YouTube Premiumなどの機能を使い、動画をあらかじめダウンロードして「聴きながら歩く」だけで、いつの間にかウォーキングが完了します。 最初は「画面を見ないと楽しめないのでは?」と思っていましたが、やってみると音声だけで満足できるコンテンツは意外と多いものです。 気になる動画を見つけたら その場で視聴せずに 、ぜひダウンロードして歩きながら聴いてください。 2. 「シューズ」への投資を惜しまない # 「歩くだけなら普段の靴でいいや」と思っていませんか? 私はそれで失敗しました。 専用ではないスニーカーで歩き始めた結果、以下のような事態に。 物理的な故障: わずか2週間でスニーカー2足のアウトソールが剥離。 身体のバグ: 歩くたびにアキレス腱周辺に痛みが発生。 「歩く」というタスクを継続するための 最重要ハードウェア は靴です。悪いことは言いません、快適なウォーキング・ランニングシューズを1足用意しましょう。これだけで継続率は格段に上がります。 3. 「分割」して難易度を下げる # 1時間連続で歩こうとするとハードルが高いですが、「朝に30分、夜に30分」のように分割すると、精神的な負荷がグッと下がります。 特に 朝のウォーキング は、体内時計をリセットし睡眠の質を向上させる効果もあるため、エンジニアの健康管理には特におすすめです(冬の朝は少し気合が必要ですが!)。 4. 色んなところを歩く # 自分のお気に入りの道を毎日歩くのもおつなものですが、時には別の場所を歩くと新たな発見や気づきがあって良いものです。 遊歩道: 近くにあったらまず歩いてみたい道No.1。新たな隠れ家を見つけた子供のような嬉しさを感じます。 駅(特に普段歩いていかない所): ちょっと離れた駅まで歩くと、知らない道に出会えます。「意外と近いぞ」という気づきが、移動の選択肢を広げてくれます。 大型商業施設: イオンやコストコ、アウトレットなど。歩きながらウィンドウショッピングも楽しめます。 公園、神社、寺など: 季節を感じられるスポットはメンタルにも良い影響があります。 5. 歩く速さを変えてみる # 歩き慣れてきたら、スピードを変えてみるのも1つの楽しみです。 もちろんスピードを速めるほど身体への負荷は高くなるのですが、歩きながら自分でどうすれば速く、楽に歩けるかを考えながら色々試行錯誤するだけでマンネリ化は大分減ります。 6. 雨の日でも歩く # 余程の嵐とかは別ですが、多少の雨なら撥水加工が施されたウェアを用意しておくだけで傘をささずに歩けます。(GORE-TEX素材の靴もおすすめ) 後は1日雨でも時間によって強弱は結構あるので、時々雨の様子を確認しながら歩くと意外と歩けるイメージがあります。 どうしても無理そうな時はおとなしく家で筋トレとか有酸素運動をしましょう。(私は家でエアロバイク漕いでました) ウォーキングを始めて実感したメリット・デメリット # メリット # 体力が劇的に向上した(HPの底上げ) 以前はたまに出社するだけで、午前中のうちに「残りHP 30%」という感覚でした。しかし最近では、満員電車に揺られてもそこまで疲れを感じません。 数値で見る身体の変化: 体重-2kg、VO2Max(最大酸素摂取量)が「平均以下」から「平均以上」へ向上、安静時心拍数も低下。「ただ歩くだけ」でも心肺機能は確実に鍛えられるようです。 活動量の増加: 1日1〜2時間をウォーキングに充てていますが、体力がついた分、活動できる時間も増えました。「朝に江ノ島ツーリング→帰宅後に銭湯→夜はウォーキング」といったアクティブな休日もこなせるようになり、使った時間以上のリターンを感じています。 睡眠の質が改善: 不規則だった生活リズムが整い、夜になると自然と眠りにつけるようになりました。 「近所の解像度」が上がった これまで見落としていた近所の風景を知れるのも楽しみの一つです。実際、隣駅まで歩いている途中で偶然新しいジムのオープンを知り、それがきっかけで筋トレも始められました。 デメリット # 出費の増加 シューズやウェアを揃え始めると、こだわりたいものがどんどん増えていきます。さらに活動範囲が広がると欲しいガジェットも増え、お財布への攻撃力は意外と高めです(本人は満足していますが!)。 アキレス腱の痛み 最近の悩みは、歩き始めのアキレス腱の痛みです。体が温まると和らぎますが、冷えや疲労の蓄積も影響しているようです。シューズやフォームを試行錯誤していますが、時には「適切な休養」も重要なタスクだと痛感しています。 エピローグ # 毎日1万2000歩歩いた結果、忘年会では見事2位にランクイン! いただいた 豪華賞品 は以下でした。 Vitalityタオル Vitalityマルチラージバッグ (SUMITOMOの文字が入った)ブランケット 【参加賞】豆蔵オリジナルスクイーズボトル(個人的にはこれが一番嬉しかった) これってほぼ全部住友生命からもらったグッズ... 今回手にしたウォーキング習慣、それこそが最大の賞品だったのかもしれません。 忘年会が終わったらウォーキングも少し落ち着こうかと思っていた矢先、社内の方からお声がけをいただき、「 第12回東京エクストリームウォーク100 」に来年の5月出場することにしました! 小田原から東京の有明まで、100kmを制限時間26時間で歩き抜く過酷な大会なので、今以上に歩けるように準備したいと思っています。 今からならまだ間に合いますので(ちなみに私は初参加です)、ご興味ある方はぜひ一緒に挑戦しましょう!
これは 豆蔵デベロッパーサイトアドベントカレンダー2025 第24日目の記事です。 はじめに # AWSは2025年11月18日、AIエージェント型IDE Kiro(https://kiro.dev) の一般提供を発表しました。 筆者は以前プレビュー版を使っての レビュー記事 を執筆しました。 それ以来Kiroのファンとなり、現在は実業務でKiroを使用しています。 AIエージェント型IDE「Kiro」の登場により、個人開発やプロトタイピングの速度は劇的に向上しました。 しかし、開発規模が大きくなるにつれて、「AIへの指示(コンテキスト)」をどのように管理するかという新たな課題も生まれています。 筆者は、この課題を解決するためにドキュメントビルドツール「Sphinx」を導入しました。 この試みは今のところうまくいっています。今回は、その開発スタイルを紹介します。 1. 従来のKiro開発における「規模の壁」 # Kiroは非常に優秀ですが、ある程度規模の大きい開発プロジェクトに適用しようとすると、以下の2点でコンテキスト管理の限界に直面します。 ① requirements.md の肥大化と混乱 Kiroの基本的な使い方は、 .kiro/specs ディレクトリ内の requirements.md に要件を記述することです。 しかし、機能が増えるにつれてこのファイルは数百行・数千行に膨れ上がり、AIが文脈を見失ったり、人間側もメンテナンスが困難になります。 ② ディレクトリ分割のジレンマ これに対する策として、 .kiro/specs ディレクトリ内に機能ごとのサブディレクトリを作り、そこに requirements.md を分散させる方法があります。 しかし、これには 「鶏と卵」の問題 があります。開発初期の要求分析段階では、どのような機能分割が最適かはまだ見えていません。 Kiroと会話しながら要件を詰めたい段階で、事前にディレクトリ構造をカチッと決めるのは不向きであり、柔軟性を損ないます。 2. 解決策:Sphinxによる構造化ドキュメント管理 # そこで提案したいのが、Python製ドキュメントツールとして有名な Sphinx を、要求仕様書や設計書の管理・ビルド基盤として採用する方法です。 Sphinxは単なるマニュアル作成ツールではありません。テキストベースで構造化されたドキュメントを管理できるため、Kiroとの親和性が極めて高いのです。 3. Sphinx導入の5つのメリット # 要求仕様書や設計書をSphinxプロジェクトとして管理することで、具体的に以下の効果が得られます。 人間にとっての可読性向上(HTML/PDF化) 複数のテキストファイルをビルドし、見やすいHTMLやPDFとして出力できる 開発者やステークホルダーは、コードのようなテキストファイルではなく、整理された「仕様書」としてブラウザで全体像を確認できる 文書構造によるコンテキスト整理 Sphinxの toctree 機能を使えば、ファイルを機能やレイヤーごとに分けて管理しつつ、1つの体系的なドキュメントとして統合できる Kiroに指示を出す際も「今回は auth.rst (認証機能)を参照して」と明確にスコープを限定できる テキストベースだからKiroが読める Sphinxのソースコードはプレーンテキストであるため、Kiroはプロジェクト内のドキュメントを直接読み込み、理解できる 「仕様書そのもの」がAIへのプロンプトとして機能する 図解(画像)によるコンテキスト共有 Sphinxプロジェクト内に配置した画面モックアップ、ER図、分析モデルなどの画像をKiroは認識できる 「この図に従って実装して」と指示することで、テキストだけでは伝わりにくいニュアンスを共有可能となる --> Caution 画像サイズが大きすぎると読み込めない場合があります。(筆者の実体験より) 概要から詳細仕様への自動生成フロー 人間が「システムの概要」や「業務フロー」をざっくりと書き、それをベースにKiroへ「各機能のユースケース記述を作成して」と依頼できる AI自身にドキュメントを書かせ、仕様を固めてから実装に移る「上流工程の自動化」が可能になる 4. 実践:Kiro × Sphinx # 実際にKiroへどのように指示を出せばよいか、具体例を紹介します。 4.1. 新規にプロジェクトを作成する場合の初期プロンプト例 # Specモードで下記のプロンプトを打ち込みます。 アルバムアプリを作成したい。 docs/requirements内にSphinxで要求仕様書を作成して欲しい。 HTMLのテーマはsphinx-rtd-themeを使用して。 PodmanでビルドできるようにDockerfileとHTML, PDFビルド用のバッチファイルを作成して。 Dockerfileのベースイメージはsphinxdoc/sphinx-latexpdfを使用して。 Kiroは要求仕様書を作成するためのプロジェクトを開始します。 ある程度、要求仕様書に書く内容がイメージできている場合は、文書の構成を指示しても良いでしょう。 requirements.mdと要求仕様書は日本語で書いて ドキュメント構成は下記のようにして index.rst # 全体目次 ├ overview/ │ └ index.rst # システム概要 ├ usecase/ │ ├ index.rst # ユースケース目次 │ ├ uc01-login # UC01_ログインする | ├ uc02-browse # UC02_アルバムを閲覧する | ├ uc03-upload # UC03_コンテンツをアップロードする | ├ uc04-edit # UC04_コンテンツを編集する | ├ uc05-delete # UC05_コンテンツを削除する | └ uc06-manage-users # UC06_ユーザーを管理する ├ screen/ │ ├ index.rst # 画面仕様目次 │ ├ login.rst # ログイン画面 │ ├ main.rst # メイン画面 │ ├ edit.rst # 編集画面 │ └ manage-users.rst # ユーザ管理画面 └ changelog/ └ index.rst # 改訂履歴 --> Information 要求仕様書に書く内容は、プロジェクトにより変わってくると思います。 絶対この構成でなければならないというものではないので、柔軟に対応しましょう。 上記の指示で作成された仕様書が下記です。 何も要件を入力していないですが、AIが勝手に想像して仕様を書いてくれています。 バッチファイルは軽微な修正が必要でしたが、HTMLやPDFにビルドするときれいに出力されます。 PDFにはスタイルの不自然なところがありますが、Kiroと相談しながら進めれば、専門的なTexの知識がなくても修正は可能です。 4.2. 要求仕様書の修正プロンプト例 # 要求仕様書の修正は、手書きで修正可能なほか、 下記のようにSpecモードで要件を列挙して修正させることも可能です。 docs/requirements内のアルバムアプリの仕様ですが、下記のようにしたい ユーザー認証はGoogleアカウントを使用すること。 管理者権限のあるユーザーのみ、ログイン可能なユーザーを追加・削除ができること。 管理者権限のあるユーザーは、バックエンドアプリケーションの設定ファイルで可能なこと。 写真だけでなく、動画もアップロード可能であること。 アップロード可能なファイルの上限は100MBであること。 アップロード可能なファイルの拡張子はJPG, PNG, HEIC, MP4, MOVであること。 ファイルのメタ情報から日付を取得し、『/data/pict/<YYYYMMDD>』というパターンのディレクトリを作成し、その中にファイルを保存すること。 ファイルのサムネイル画像を作成し、『/data/thumb/<YYYYMMDD>』というパターンのディレクトリを作成し、その中にサムネイル画像を保存すること。 写真の一覧はサムネイル画像を表示すること。 サムネイル画像のサイズは縦幅、横幅が300ピクセル以下となること。 4.3. 設計書の作成プロンプト例 # 要求仕様書が書けたら設計書も作成します。Specモードで下記の指示を出します。 docs/requirements内のアルバムアプリの仕様に基づいて、 docs/design内にSphinxでアーキテクチャ設計書を作成して欲しい。 フロントエンドはAngular、バックエンドはASP.NET Coreで。 実行環境と開発環境はPodmanコンテナ上で動くこと。 上記の指示で作成された設計書が下記です。 Dockerイメージにsphinxcontrib-mermaid拡張機能がインストールされていたため、ドキュメントをビルドするとKiroがMermaidで描いた図も表示されました。 4.4. 実装フェーズでのプロンプト例 # 実装フェーズでは、Specモードで下記のように指示を与えます。 docs\requirementsの要求仕様書と、 docs\designの設計書を参考に、 アルバムアプリのログイン機能を実装して これだけの指示で、Kiroはログイン機能に必要な情報を探し出してrequirements.mdを作成してくれます。 これ以降は、下図のフローに従って実装まで進めていくだけです。 まとめ # Sphinxを導入することで、要求仕様書や設計書を「人間が読みやすい形式」と「AIが処理しやすい形式」の両方で管理できるようになります。 今回ご紹介した手法であれば、開発規模の大きなプロジェクトでもKiroを扱いやすくなるのではないでしょうか。 本記事を今後の開発の参考にしていただければ幸いです。
これは、 豆蔵デベロッパーサイトアドベントカレンダー2025 第23日目の記事です。 はじめに # 2022年12月12日に「 AWS認定資格を12個すべて取得したので勉強したことなどをまとめます 」という記事を投稿してから3年が経ちました。 この記事では、その後の3年間でどのような変化があったか、そして新しく追加された認定区分についてまとめます。 --> Information 秘密保持契約(NDA) があるため、詳細な試験内容については触れることができませんので、ご了承ください。 3年間の振り返り # 2022年10月にAWS認定12冠を達成してから、3年間が経過しました。この間、いくつかの認定が有効期限を迎え、更新が必要になりました。 認定の更新について # AWS認定は有効期限が3年です。2022年に取得した認定は、2025年には更新が必要になります。 今回更新対象となった資格は、5資格です。 プロフェッショナル2資格の更新 プロフェッショナル2資格(ソリューションアーキテクト、DevOpsエンジニア)は下位資格の更新も含むため、期限となる6月より余裕をもって1月に更新しました。 プロフェッショナルレベルの認定は、下位のアソシエイトレベルの認定(Solutions Architect – Associate、Developer – Associate、SysOps Administrator – Associate)も同時に更新されるため、一度の更新で複数の認定を維持できるメリットがあります。 AWS Certified Solutions Architect – Professional 内容は以前と変わらず、Organizationを中心としたアーキテクチャ、セキュリティ、運用など幅広い知識を問われました マルチアカウント戦略やガバナンス、コスト最適化、災害復旧など、エンタープライズレベルの設計に関する問題が多く出題されました 問題文は相変わらず長文で、要件を整理しながら読む必要がありました AWS Certified DevOps Engineer – Professional こちらも以前と変わらず、ソリューションアーキテクトとセットで受験すると勉強した知識などを活かせました CI/CDパイプラインの設計、インフラストラクチャの自動化、モニタリングとログ管理などが主な出題範囲でした 廃止となるはずだったCode Commitが出てきて「今更これを問う意味はあるのか?」と疑問に思いましたが、撤回されたので意味ありました 専門知識3資格の再取得 専門知識3資格(セキュリティ、機械学習、高度なネットワーキング)は準備期間に余裕を持たせ、有効期限を気にせず失効後に順次再取得しました。 専門知識資格はプロフェッショナル資格と異なり、下位資格の更新には含まれないため、個別に更新する必要があります。 高度なネットワーキングは苦手で 再受験キャンペーン にお世話になりました。 AWS Certified Security – Specialty 受験したタイミングではSCS-C02でしたが、以前と特に変わったと思う点はありませんでした IAM、セキュリティグループ、ネットワークACL、WAF、GuardDuty、Security Hubなど、セキュリティに関する幅広い知識が問われました マルチアカウント環境でのセキュリティガバナンスや、コンプライアンス要件を満たすための設計に関する問題も多く出題されました SCS-C03では生成AI関連のセキュリティも増えるようなので、カバーする範囲が増えそうです AWS Certified Machine Learning – Specialty 2026年3月31日に廃止が発表されました 内容は以前と変わらず、機械学習が中心でした Amazon SageMakerを中心とした機械学習パイプラインの構築、モデルの訓練とデプロイ、モニタリングなどが主な出題範囲でした データの前処理、特徴量エンジニアリング、モデルの評価方法など、機械学習の基礎知識も必要でした AWS Certified Advanced Networking – Specialty 今回の更新で一番内容が変わっていた気がします 以前はDirect ConnectやVPN接続が中心でしたが、今回はAWS Global Accelerator、CloudFront、Route 53などのグローバルネットワークサービスに関する問題が増えていました マルチリージョン環境でのネットワーク設計や、ハイブリッドクラウド環境での接続性に関する問題も多く出題されました Transit GatewayやGateway Load Balancerなど、比較的新しいサービスに関する問題も増加していました 廃止になった専門知識3資格 廃止となり、取得日から3年たった日に無効化されていきました。 これらの資格は、新しい認定区分への統合や、AWS認定プログラムの再編成により廃止されました。 有効期限が切れるまでは認定として有効でしたが、更新の機会はなく、自然に失効していきました。 AWS Certified Database – Specialty AWS Certified Data Analytics – Specialty AWS Certified SAP on AWS – Specialty 3年間で得た経験 # 2022年の記事では「実際にAWSを触ってシステムを構築したわけでもないので、今後は実際のシステム構築で使える技能を付けていきたい」と書きました。 この3年間で、実際のプロジェクトでAWSを活用する機会はありましたが、まだ簡単なアプリケーションの方式設計程度にとどまっています。 実務でのAWS活用 実際のプロジェクトでは、以下のような場面でAWS認定で学んだ知識が役立ちました: 既存システムの理解 すでに動いているAWSシステムを理解する際に、認定で学んだ知識が大いに役立ちました どのAWSサービスが使われているか、サービス間がどのように連携しているかを理解する際に、認定で学んだ各サービスの特徴や使い方の知識が参考になりました システムの構成図やドキュメントを読む際に、AWS認定で学んだ知識があることで、理解がスムーズになりました システムの動作確認や調査 既存システムの動作確認やトラブルシューティングの際に、認定で学んだ知識が役立ちました IAMロールやセキュリティグループの設定を確認する際にも、認定で学んだ知識が理解の助けになりました 設計レビューやドキュメント理解 他のメンバーが設計したAWS構成や、既存システムのドキュメントを理解する際に、認定で学んだ知識が役立ちました 認定で学んだベストプラクティスやセキュリティの知識があることで、設計の意図や注意点を理解しやすくなりました 認定知識と実務のギャップ 認定で学んだ知識と実務には、いくつかのギャップがあることも実感しました: 実務では複数のサービスを組み合わせる必要がある 認定試験では個別のサービスの知識が問われますが、実務では複数のサービスを組み合わせてシステムを構築します サービス間の連携や、データフローの設計など、より実践的な知識が必要だと感じています コストとパフォーマンスのバランス 認定試験では「最適な解決策」を選ぶ問題が多いですが、実務ではコストとパフォーマンスのバランスを考慮する必要があります 実際のプロジェクトでは、予算の制約や、既存システムとの互換性など、試験では考慮されない要素も重要です 実際の構築・運用経験の不足 認定で学んだ知識は主に設計や概念に関するもので、実際の構築や運用の経験はまだ不足しています 今後は、実際にAWSを使ってシステムを構築し、運用する経験を積んでいきたいと考えています 新認定区分について # 2022年以降、AWS認定には新しい区分が4つ追加されました。そのうち3つはすでに取得済みで、デベロッパーサイトの記事にもしています。 2024年3月23日: AWS Certified Data Engineer - Associate 2024年9月26日: AWS Certified AI Practitioner 2024年12月6日: AWS Certified Machine Learning Engineer - Associate 今回話題に挙げるのは、4つ目の新認定区分である生成AIデベロッパープロフェッショナルです。 AWS Certified Generative AI Developer – Professional # AWS Certified Generative AI Developer – Professional は、Amazon BedrockなどのAWSサービスを使用した、本番環境に対応するAIソリューションの構築およびデプロイにおける高度なスキルを証明するプロフェッショナルレベルの認定です。 試験の概要 カテゴリ : Professional ベータ試験期間 : 205分 ベータ試験形式 : 85問、択一選択問題および複数選択問題 ベータ試験料金 : 150 USD(日本では22,000円(税込み)) ベータ対象言語 : 英語および日本語 なお、再受験キャンペーンは使えませんが、通常の半額バウチャは使えます。 対象となる受験者 この認定は、2年以上のクラウド経験があり、キャリアを高めたいと考えている開発者に最適です。 対象となる受験者は、以下の要件を満たしている必要があります: AWSで、またはオープンソーステクノロジーを使用して本番環境グレードのアプリケーションを構築した2年以上の経験 一般的なAI/MLまたはデータエンジニアリングの経験 生成AIソリューションの実装における1年の実務経験 AWSコンピューティング、ストレージ、ネットワーキングサービスの経験 AWSセキュリティのベストプラクティスとID管理についての理解 AWSのデプロイとInfrastructure as Codeツールの経験 AWSモニタリングおよびオブザーバビリティサービスについての知識 AWSコスト最適化原則の理解 ベータ試験について ベータ試験なので機械学習エンジニア-アソシエートやAIプラクティショナーの時と同じく認定ガイドに沿って準備を進めました。 ベータ試験は通常の試験とは異なり、試験内容や形式が確定する前の段階で受験する試験です。 AWS認定では、標準バージョンの試験で問題が使われる前にベータ試験を使用して試験問題の質が検証されます。 ベータ試験の合格者は新しい認定の最初の取得者になります。 最初の5,000名の試験参加者には、合格時に特別なEarly Adopterバッジが贈られます。 そのため、認定ガイドをしっかりと確認し、出題範囲を理解した上で準備することが重要です。 準備方法 ベータ試験の準備として、以下のような方法で学習を進めました: 認定ガイドの確認 出題範囲と各ドメインの重み付けを確認し、重点的に学習すべき領域を把握しました 生成AIデベロッパープロフェッショナルの場合、Amazon Bedrock、Amazon SageMaker、AWS Lambda、Amazon API Gatewayなどが主な対象サービスでした 公式ドキュメントとハンズオン Amazon Bedrockの公式ドキュメントを読み込み、主要な機能や使い方を理解しました AWS Skill Builderの関連コースや、ハンズオンラボで実際にサービスを触ってみました 生成AIアプリケーションの構築パターンや、ベストプラクティスを学習しました 関連認定の知識の活用 AI PractitionerやMachine Learning Engineer – Associateで学んだ知識を活用しました Solutions Architect – Professionalで学んだアーキテクチャ設計の知識も役立ちました セキュリティやモニタリングに関する知識も、生成AIアプリケーションの設計に必要でした 実務経験の活用 実際のプロジェクトでは簡単なアプリケーションの方式設計程度しかできていませんが、その経験が問題の理解に少しは役立ったと思います ただし、実務では限定的な経験にとどまっているため、認定ガイドでカバーされている範囲を広く学習する必要がありました 受験してみた 受験してみました。 しっかり準備したつもりでしたが、思っていた内容と異なっていました。 試験の難易度と特徴 問題数と時間 205分で85問という構成で、1問あたり約2.4分の時間配分が必要でした 問題文と選択肢が非常に長文で、文章から構成図をイメージするのに時間がかかりました 複数のサービスを組み合わせた複雑なシナリオが多く、全体像を把握するのに時間がかかりました 出題内容の特徴 Amazon Bedrockを中心とした生成AIアプリケーションの構築に関する問題が多く出題されました 本番環境での運用を考慮した設計(スケーラビリティ、セキュリティ、コスト最適化など)が問われました 複数の選択肢が正解に見える問題が多く、ベストプラクティスに基づいた判断が求められました エラーハンドリングやモニタリング、ログ管理など、運用面での考慮事項も多く出題されました 時間配分の課題 ギリギリまで時間がかかり、見直しの時間がほとんど取れませんでした 文章を読むのが遅いのを直さなければいけないと、いつも感じています 長文の問題を素早く理解し、要点を整理する能力が重要だと実感しました 結果と今後の対策 X(旧Twitter)などでは合格報告をよく見かけますが、残念ながら不合格でした。 正式リリースまでに、以下の点を改善して準備を進めたいと思います: 長文問題への対応 問題文を素早く読み、要点を整理する練習を重ねる 構成図やアーキテクチャ図を素早くイメージできるようにする 実践的な知識の強化 Amazon Bedrockを使った実際のアプリケーション構築経験を積む 本番環境での運用を考慮した設計パターンを学習する 関連サービスの深い理解 AWS Lambda、Amazon API Gateway、Amazon CloudFrontなど、生成AIアプリケーションでよく使われるサービスの詳細な理解を深める セキュリティ、モニタリング、コスト最適化などの観点から、ベストプラクティスを学習する 認定取得のモチベーション維持 # 3年間、認定を維持し続けるためには、継続的な学習が必要です。 以下のような方法でモチベーションを維持してきました: 継続的な学習方法 # 定期的なAWSサービスのキャッチアップ AWSの公式ブログや、re:Inventのセッション動画を定期的に視聴して、新しいサービスや機能をキャッチアップしています AWS Skill Builderのコースを活用して、体系的に知識を更新しています 特に生成AI関連のサービス(Amazon Bedrock、Amazon Qなど)は、頻繁にアップデートがあるため、継続的な学習が必要です 実務でのAWS活用 実際のプロジェクトでAWSを使うことで、認定で学んだ知識を実践で活用し、理解を深めています 実務で直面した課題を解決する過程で、新しい知識やベストプラクティスを学んでいます 認定で学んだ知識が実務で役立つことを実感することで、学習のモチベーションが維持されます 新しい認定区分への挑戦 新しい認定区分が追加されると、新しい知識を学ぶ機会として積極的に挑戦しています ベータ試験に参加することで、新しい認定の最初の取得者になることを目指しています 新しい認定区分への挑戦は、学習のモチベーションを高める良いきっかけになります モチベーションの源泉 # また、 2026 Japan All AWS Certifications Engineers のクライテリアを満たすことが大きなモチベーションとなっています。 2023年、2024年、2025年と3年連続で対象となり、引き続きすべてのAWS認定資格を保持し続けることが目標です。 この目標を達成するためには、以下のような取り組みが必要です: 認定の更新計画 各認定の有効期限を管理し、更新が必要な認定を事前に把握しています プロフェッショナル資格は下位資格も更新されるため、優先的に更新するようにしています 専門知識資格は個別に更新する必要があるため、計画的に準備を進めています 新しい認定区分への対応 新しい認定区分が追加されたら、できるだけ早く取得するようにしています ベータ試験に参加することで、早期に取得できる可能性があります 新しい認定区分への対応は、すべてのAWS認定資格を保持し続けるために必要です コミュニティとの交流 X(旧Twitter)や技術ブログなどで、同じ目標を持つ人たちと情報交換をしています 認定取得の経験や、学習方法などを共有することで、モチベーションを維持しています コミュニティとの交流は、学習の継続を支える重要な要素です まとめ # 2022年にAWS認定12冠を達成してから3年が経過し、いくつかの認定の更新が必要になりました。 また、この間に新しい認定区分が追加され、AWS認定の選択肢が広がりました。 認定を取得することはゴールではなく、継続的な学習のきっかけとして活用していきたいと考えています。 今後も、新しい技術や認定区分にチャレンジし続けていきたいと思います。
これは 豆蔵デベロッパーサイトアドベントカレンダー2025 第22目の記事です。 こんにちは!AWSの世界を探求する皆さん。 突然ですが、 AWS Control Tower 使っていますか? 今私が携わっているプロジェクトにおいてAWS Control Tower(以降Control Tower)を導入したアカウント運用の話があり、個人ではあまり使う機会が少ないサービスだと感じたので、この機会に使っていく中で判明した挙動について書き留めておこうと思います。 そもそもControl Towerってどんなサービスなの?という話を軽くしておくと、 AWS Control Towerは、AWSのベストプラクティスに基づいたマルチアカウント環境(ランディングゾーン)を自動的にセットアップし、継続的なガバナンスを提供するサービスになっています。 この記事で紹介するのは主にControl Towerの「Account Factory」と「Account Factory Customization(以降AFC)」による「アカウント作成」の挙動についてです。 プロジェクトとして、Account Factoryの処理をAWS CLIコマンドを直接たたくことで実現する必要があったため、AWSマネジメントコンソール(以降マネコン)からアカウント作成を実行した時の裏側で走る処理について、AWS CloudTrail(以降CloudTrail)のイベント履歴を追うことでAWS CLIコマンドで実現する方法を明確にしていきました。 そこで以降では「Account Factory」と「AFC」の具体的な処理フローについてまとめていきたいと思います。 また、AWS CLIコマンドではマネコン上で操作した時と同じように再現はできないことも合わせてお伝えしていきたいと思います。 前提 # 冒頭にて本記事での内容について述べましたが、以下については詳しくふれません。 そのため、ある程度AWSになれていて、AWS Organizations(以降Organizations)やAWS IAM Identity Center(以降Identity Center)などのアカウント・ユーザー管理系サービスの知識、用語の理解がある方向けの内容になっています。適宜注釈や参照リンク、軽い説明は混ぜていきますが、ご了承ください。 Control Towerの開始方法や操作、関連用語 Organizationsの機能やIdentity Centerの機能と操作、関連用語 AWS Service Catalogについての機能や操作、関連用語 また、検証にあたり以下については設定済み・リソースがあるという前提とOrganizationsとIdentity Centerを絡めた組織的なアカウント運用・管理を前提にした内容で記事を書いています。 AWSルートアカウントからIdentity Centerを有効化し、AWSルートアカウントにAdmin権限でアクセスできるユーザーを設定している 参照: 管理アクセスを持つユーザーを作成する Control Towerのランディングゾーンを開始している AWSルートアカウントで有効化したIdentity CenterとControl Towerの間でアクセス制御統合をしていること AWS Service Catalog(以降Service Catalog)の製品「AWS Control Tower Account Factory」が存在していること AFCを利用するためのブループリント [1] ハブアカウントが存在する 参照: カスタマイズのための設定 1. Account Factoryの正体は「Service Catalog製品」 # Control Towerを知っている方や使ったことがある方はご存じだと思いますが、アカウント作成を実行するにはControl Towerのコンソール画面にある「Account Factory」から操作を行います。 実はこれ、Control Tower独自の機能というよりも、 Service Catalog というサービスをラッピングしたものなんです。 大まかに何をしているのか # Control Towerの管理アカウント(ランディングゾーンを開始したアカウントのこと)で Service Catalog のコンソールを開いてみてください。「製品」のリストに 「AWS Control Tower Account Factory」 という製品があるはずです。 マネコン上からControl Towerで「アカウント作成」ボタンを押すことは、裏側では 「Service Catalogの『AWS Control Tower Account Factory』という製品を起動している」 こととイコールになります。 後ほどより具体的に説明していきます。 なぜ Service Catalog なのか? # ここでなぜわざわざControl TowerからService Catalogを介してアカウントを作成するのか疑問に思った方もいると思います。普通にOrganizationsからアカウント作ればいいのでは?と思いますよね。 このようにアカウントを作成することにはメリットがあります。(でなければわざわざサービスとして提供しなくてもいいですからね。。) 権限の分離 本来、アカウント作成やIAM設定には強力な権限(AdministratorAccess相当)が必要です。しかし、経理担当者や各プロジェクトリーダーにそんな強権を渡したくないですよね? Service Catalogを使えば、 「この『Account Factory製品』を使う権限」だけをユーザーに渡せばOK です。(正確にはControl Towerを操作する権限を渡しておけばOkです。) つまり、管理アカウントにログインするユーザーに、OrganizationsやIdentity Centerを操作する権限は付与しなくてよいということになります。 コントロールとベースラインの適用 Control Towerを経由することで、単にアカウントを作成するだけでなく、組織的な管理下に置かれた「統制の効いた」アカウントとして払い出すことができます。これは、企業が複数のアカウントを安全かつ効率的に運用するために不可欠な要素です。 具体的には、アカウント作成時に「コントロール(旧ガードレール) [2] 」や「ベースライン [3] 」と呼ばれるセキュリティ設定やログ設定が自動的に適用されます。これにより、管理者は個々のアカウント設定を確認する手間を省くことができ、常にポリシー(AWSのベストプラクティスに基づくセキュリティ基準のこと)に準拠した状態を維持できます。 2. アカウント作成時の「裏側の挙動」 # では、実際にアカウント作成ボタンを押したとき、裏側でどのようなフローが走っているのか、CloudTrailのイベント履歴を元に正確なフローを見ていきましょう。 以下の処理は、主にSTS(Security Token Service)を使用して一時的かつ強力な権限にスイッチしながら行われます。 また、各リソースの作成確認(Describe、List系のコマンド)は随時並行して処理が走っています。 STEP 0: 設定と製品の確認 # まず初めに、 DescribeAccountFactoryConfig が実行され、現在のControl TowerにおけるAccount Factoryの設定情報が取得されます。 これに基づき、以下の手順でService Catalog製品の確認が行われます。 SearchProductsAsAdmin 所有者が「AWS Control Tower」であるService Catalog製品を検索します。 DescribeProduct 検索で見つかった製品(Account Factory)の詳細を取得します。 この時、製品の中身(AWS CloudFormationテンプレート、以降CloudFormationテンプレート)が新しいバージョンになっている場合、 CreateProvisioningArtifact が実行され、製品の更新処理が走ることがあります。 STEP 1: Account Factory製品の起動 (ProvisionProduct) # Control Towerにおけるアカウント作成の実体である ProvisionProduct が実行されます。 これにより、「AWS Control Tower Account Factory」製品の起動が開始されます。 STEP 2: 管理アカウントへの登録 (CreateManagedAccount) # 製品の起動の中で、作成されたアカウントをControl Towerの管理下に置くための CreateManagedAccount 処理が走ります。 これにより、単なるOrganizationsのアカウントとしてだけでなく、Control Towerによって管理・監視される「Managed Account」として登録されます。(作成時にしてたOU配下に登録されます。) STEP 3: ユーザーとグループのセットアップ (CreateUser) # Identity Centerにおいて、新規作成されたアカウントへアクセスするためのユーザー作成、グループへの追加などの処理が行われます。 STEP 4: ベースラインとコントロールの適用 # AWS CloudFormation StackSets(以降CloudFormation StackSets)が発動し、STEP 0で確認されたベースラインやコントロール(各種セキュリティ設定やログ設定など)が、アカウントに対してデプロイされます。 STEP 5: アクセス権限の割り当て (CreateAccountAssignment) # 最後に、新規作成されたアカウントに対して、Identity Centerの許可セット(Permission Set)とユーザー(またはグループ)の割り当てが実施され、ユーザーがログイン可能な状態になります。 上記のようなステップを踏んで実際の「Account Factory」の処理が進みます。 あまり複雑になりすぎないよう簡潔にまとめましたが、Service Catalog製品の起動からベースラインなどの適用まで一貫して実施されていることがお分かりいただけたかと思います。 3. Account Factory Customization (AFC) # 続いて、Account Factoryの拡張版ともいえるAFCについてのフローを見ていきましょう。 「Control Towerの標準設定だけじゃ足りない!アカウント利用開始時にIAMロールや必要なAWSリソース構成も最初から入れておきたい!」というような、 AWSが用意しているデフォルトのService Catalog製品で展開されるリソースに加えて独自の設定内容をアカウント作成時に適用したいという要望に応えるのが Account Factory Customization (AFC) です。 Account FacotryがAWSマネージドな処理で、AFCがカスタマーマネージドな処理というとらえ方でよいかと思います。(厳密には違いますが、イメージはそんな感じです。) AFCの仕組み:Service Catalog on Service Catalog # AFCを使うと、Account Factory実行時に使用されるデフォルトのブループリントとは別に、 「追加のカスタムブループリント」 を指定できるようになります。 ※補足をしておくと、Account Factory時にはAWS内部的にデフォルトのブループリントが使用されています。それと対比して、AFC時に使うブループリントをここではカスタムブループリントと呼んでいます。 公式リファレンスにも表記がされているのですが、例のごとく「ブループリント=デフォルトのブループリント」だったり、「ブループリント=カスタムブループリント」だったり表記ゆれがあるので、明確に区別しておきます。 この「ブループリント」ですが、実態は Service Catalog製品として登録されたCloudformatinoテンプレート です。 管理アカウント、あるいは「ハブアカウント」にあるカスタムブループリントを、デフォルトのブループリントを実行した後に適用してくれます。 つまり、Control Towerがアカウント新規作成時にデフォルトで作成してくれるリソースを維持しつつ、独自に追加したいリソースも入れることができるということです。 ※カスタムブループリントは公式的に「ハブアカウント」に置くことが推奨されています。 AFC実行時の裏側の挙動 # さて、ここでも背後の挙動を追ってみましょう。通常のAccount Factoryとは少し異なる動きを見せます。 STEP 0(設定確認)までは通常時と同様ですが、その後の動きに特徴があります。 CreateManagedAccount(の実行) AFCの場合、通常の ProvisionProduct は実行されずに、 CreateManagedAccount が実行されます。 このリクエストパラメータには、通常のAccount Factoryの情報に加え、「blueprints」(事前にハブアカウントに作成しておいたService Catalog製品の情報、カスタムブループリントのこと)が含まれています。 IdCユーザー関連処理 通常と同様に、新規作成アカウントへアクセスするためのIdentity Centerユーザー作成処理などが走ります。 ベースラインとカスタムブループリントの適用 CloudFormation StackSetsによって、標準のコントロールやベースライン(デフォルトのブループリント)が適用されます。 これは推測になってしまいますが、 指定したカスタムブループリントはこのタイミングで適用される と考察しています。 なぜこのような考察に留まってしまったのかは以下の「ブラックボックスな部分」にまとめました。 アクセス権限の割り当て 最後にユーザーやグループへのアクセス権限割り当てが行われます。 ブラックボックスな部分 興味深い点として、カスタムブループリントの適用に関する明確なAPI呼び出し(例:ハブアカウントからの製品取得など)がCloudTrail上では確認できませんでした。 しかし、事実としてハブアカウント上のService Catalogではカスタムブループリント製品が実行された形跡が残っているため、CreateManagedAccount実行の背後で別の処理(製品の取得など)が走り、適用のタイミングとしてはデフォルトのブループリント適用の後にカスタムブループリントを適用しているのではと考察しました。 何度か試して確認ができなかったので、CloudTrailのイベント時系列から上記のような処理になるのではないかと予想しています。 4. プロジェクトでの実例と直面した壁 # ここからは、実際のプロジェクトで直面した課題とその解決策についてお話しします。 今回のプロジェクトでは、 Control Towerを開始した管理アカウント(アカウントA)とは別のAWSアカウント(アカウントB)から、AFC機能を使ってアカウントを作成したい という要件がありました。 試みたこと # 当初は、「APIが用意されているはずだから、クロスアカウントでもSTSでスイッチロールしてコマンドを叩けば大丈夫だろう」と安直に考えていました。 しかし、現実はそう甘くありませんでした…。 AFC実行用のCLIコマンドが存在しない まず、AFCの処理フロー等価である CreateManagedAccount というCLIコマンドが存在しません。 Control TowerのAPIリファレンス を探しても相当するコマンドは見つかりませんでした。 Service Catalogコマンドの限界 CLIでAccount Factoryを実行するために servicecatalog provision-product コマンドを利用することは可能です。 しかし、このコマンドでは product-id (製品ID)を 1つしか指定できません 。 つまり、通常の「AWS Control Tower Account Factory」製品を指定すると、AFCで利用したい「カスタムブループリントの製品ID」を同時に渡すことができないのです。 そのため、「デフォルトブループリントの適用→カスタムブループリントの適用」という連動した動きが再現できなくなります。 デフォルトブループリントを適用した後にもう一度カスタムブループリントを指定してコマンドを実行すれば?と思うかもしれませんが、これだと新規作成アカウントの情報が連携できていないので、カスタムブループリントの内容がアカウントB上で実行されるだけになります。 クロスアカウントの制約 さらに、クロスアカウントで実行する場合、ハブアカウントに存在しているService Catalog製品(カスタムブループリント)の情報が取得できないという制限もありました。 ハブアカウントからカスタムブループリント製品を管理アカウント側に共有(厳密には製品を管理するポートフォリオを共有)して試してみましたが、これもうまくいかなかったです。(そもそもSearchProductsAsAdmin CLIコマンドにおいて共有した製品が管理アカウント上で認識できなかったです。。) 辿り着いた解決策 # 最終的に、API(CLI)ベースで要件を満たすために以下のアプローチを採用しました。 通常のAccount Factoryでアカウントを作成 まず、 provision-product コマンドを使用して、標準のAccount Factory製品を起動し、Control Tower管理下のアカウントを作成します。これだけならアカウントBからでも実行可能です。 CloudFormation StackSetsでカスタマイズを適用 アカウント作成が完了した後、別途 CloudFormation StackSets を使用して、AFCで適用したかったカスタムリソース(IAMロールなど)を新アカウントに適用します。 一発でAFCを実行することはできませんでしたが、手順を分割することで「Control Tower管理下の統制の効いたアカウント」かつ「独自のカスタマイズが施されたアカウント」をAPIベースで作成することができました。 5. Control Towerのメリットと「手の届かない」部分 # ここまで、Account Factoryの挙動やカスタマイズについて深掘りしてきました。 Control Towerは、セキュリティのベストプラクティスに沿った環境を簡単に構築・維持できる非常に強力なサービスです。ボタン一つ(あるいはコマンド一つ)で、ログ集約やアクセス制御が整ったアカウントが手に入るのは素晴らしいことです。 しかし、その「自動化」と「標準化」の裏返しとして、 手の届かない部分 も存在します。 Control Towerの限界(変更できない設定) Control Towerによって自動作成・管理されるリソースの中には、ユーザー側で設定変更ができない(または推奨されない)ものがあります。 全ては挙げれませんが、私が実際に設定変更をしようとしてできなかったものとして以下の2点があります。 CloudTrail用S3バケットの設定 ログアーカイブアカウントに作成されるS3バケットのライフサイクルポリシーなどを自由に変更することができません。要件に合わせてログ保存期間を変えたい場合など、柔軟な対応が難しいことがあります。 AWS Configアグリゲーター 組織全体のConfigルールを集約するアグリゲーターも自動生成されますが、この設定もユーザーが自由にカスタマイズすることは難しい部分です。 一度Control Towerによって自動で作られたアグリゲーターを削除してみましたが、ドリフト検出されて常に警告がでてやや鬱陶しかったです。。 その他にも、Control Towerによって作成・管理されているCloudformationテンプレートで展開されているリソースには手を加えない方が無難でしょう。 これらの「手の届かない部分」があることを理解した上で、Control Towerの標準機能でどこまでカバーし、どこからは独自の実装(例えば別途S3バケットを作る、独自のConfigルールを追加するなど)で補うかを判断することが、Control Towerとうまく付き合っていくコツだと感じました。 まとめ # 本記事では、AWS Control TowerのAccount FactoryとAFC機能について、その裏側で実行されている処理フローを解説してきました。 Account Factoryの実体は、 Service Catalog製品 として提供されており、アカウント作成のリクエストは、Service Catalogを経由して AWS Organizations や AWS CloudFormation StackSets に連携されます。 これらの一連の処理によって、アカウント作成からセキュリティ設定(コントロールとベースライン)の適用、Identity Centerへのユーザー登録までが自動化されています。 Account Factory Customization (AFC) も同様に、Service Catalog製品として登録した (カスタム)ブループリント を利用することで、標準の設定に加えて独自のリソースを自動的にデプロイする仕組みを提供しています。 Control Towerは一見ブラックボックスに見えるかもしれませんが、その裏側で動いているのは、IAM(Identity Centerを含む)、CloudFormation、Service Catalogといった基本的なAWSサービスです。 この構造を理解しておくことで、エラー発生時のトラブルシューティングや、より高度なカスタマイズが必要になった際の対応力が大きく向上するはずです。 Control Towerは頻繁にアップデートが行われており、APIによる運用の柔軟性も徐々に向上していくと予想しています。 特にAFC機能については、現状ではAPI連携において一部制約がありますが、将来的にはCLIやSDKを通じたよりシームレスな自動化が可能になることを期待したいところです。 引き続き最新の動向をウォッチし、より効率的なマルチアカウント運用を目指していきたいと思います! 注釈 # ブループリント (Blueprint) : AWSアカウントの構築やカスタマイズに使用される、事前に構成されたテンプレート(実態は主にCloudFormationテンプレート)。 ↩︎ コントロール (Controls) : AWS環境全体(OU単位)に適用されるガバナンスルール(旧称: ガードレール)。予防的コントロール(SCP)と発見的コントロール(Config/AWS Lambda)などがあります。 ↩︎ ベースライン (Baseline) : OUなどのターゲットに適用されるリソースとその設定のグループ。 ↩︎
少し公開が遅くなってしまいましたが、これは 豆蔵デベロッパーサイトアドベントカレンダー2025 第15日目の記事です。 はじめに # 豆蔵は長年にわたり、ロボットシステム開発の支援およびコンサルティングを行ってきました。 オリジナルロボット「BEANus」シリーズなどで培ってきた技術力は、単なるメカニクスの制御にとどまらず、高度なソフトウェア技術との融合にあります。 今回、三井化学株式会社と共同開発した中食(なかしょく)工場向け食品盛り付けロボット美膳®(びぜん)は、まさにその結晶です。 詳細なプレスリリースは こちら をご覧ください。 私は、主にソフトウェアアーキテクトとして美膳®の開発に携わりました。 今回、ロボット開発では珍しいクリーンアーキテクチャ(Clean Architecture)を採用し、ドメイン中心設計を実現しました。 本記事では、食品盛り付けロボット美膳®の紹介と、それを支えるソフトウェアアーキテクチャについて紹介します。 美膳®の紹介 # 美膳®は、中食業界で深刻化する労働力不足を解消するために開発された、食品盛り付けロボットシステムです。 豆蔵がシステム設計、メカ・エレキ設計、そしてAI・ビジョン・モーションを含むソフトウェア開発を担当し、三井化学が高機能樹脂素材の提供やロボットハンドの開発、製造・販売を担当するという、両社の強みを活かした共同開発によって生まれました。 美膳®が解決したい社会課題 # 下図に示すように、中食工場では多くの盛り付け作業が人手で行われており、労働力不足や人件費高騰が深刻な問題となっています。 このような背景から、盛り付け工程の自動化が強く求められています。 画像提供:株式会社豆蔵 美膳®で出来ること # 美膳®は、弁当や惣菜の盛り付け作業を自動化します。 具体的には、以下のような高度な作業を高速かつ正確に行います。 食材の認識とピッキング : 番重(食材コンテナ)内にランダムに置かれた食材を、AIビジョンで瞬時に認識し、最適な把持位置を判断してピッキングします。 容器への追従盛り付け : ベルトコンベア上を流れる容器の位置・姿勢・速度をカメラを使ってリアルタイムに認識し、ロボットアームが追従しながら正確な位置に食材を盛り付けます。 双腕による協調動作 : 左右のアームが互いの状況をリアルタイムに共有し、上流での作業漏れを下流でカバーしたり、作業負荷を分散させたりするなど、双腕ならではの柔軟な連携により生産性を最大化します。 特徴 # 美膳®には以下の大きな特徴があります。 1. 業界最速レベルの生産性 中食工場での人の作業スピードは1時間あたり約2,000食と言われていますが、美膳®はこの人の作業と同等の生産能力(2,000食/時)を実現しました。従来の盛り付けロボットの多くが1,200食/時程度であったのに対し、大幅な生産性向上を達成しています。 2. 迅速な段取り替え 多品種少量生産が求められる中食工場では、頻繁なライン変更が必要です。美膳®はキャスター付きで移動が容易であり、ロボットハンドも簡単に交換できる設計になっています。これにより、生産品目が変わっても短時間でラインを切り替えることができます。 3. 軽量・コンパクト 三井化学の高機能樹脂素材を採用することで、軽量化と高剛性を両立しました。また、双腕ロボットでありながら小型化を実現しており、既存の盛り付けラインの限られたスペースにも導入しやすくなっています。 4. 人との協働 非接触の外装センサーを搭載することで、人が近づくと自動で減速・停止する機能を備える予定です。これにより、安全柵なしで人とロボットが同じ空間で作業することが可能になります。 --> Information ※本機能は現在開発中であり、現行品には搭載されていません。 ソフトウェアアーキテクチャの紹介 # 私はソフトウェアアーキテクトとして、この美膳®の開発に携わりました。 よって、ここからはソフトウェアアーキテクチャの概要について説明します。 美膳®における設計思想 # 美膳®は単にメカが動くだけでなく、AIによる認識、複雑なモーション制御、そしてそれらを統合するシステム全体が高度に連携して動作しています。 このシステムの核となるのは、 「食品を認識し、把持し、盛り付ける」という「食品盛り付け業務(ドメイン)」 です。 このドメイン知識をシステムの中心に据え、特定のハードウェアといった技術的詳細に依存しない設計を目指しました。 アーキテクチャ設計においては、以下の点を重視しました。 ドメイン中心 : 「食品盛り付け」という業務ロジックを最重要視し、技術的詳細から分離すること 保守性 : 長期間にわたる運用と機能追加に耐えうる構造であること テスト容易性 : ハードウェアに依存せず、ロジック単体でのテストが可能であること 独立性 : フレームワークやセンサ・インジケーターなどの外部要素への依存を最小限に抑えること 特に、独立性を重視した理由は、 美膳®には食品盛り付けロボットシステムのプラットフォームとしての役割 も期待されており、将来的に新しいセンサ技術などが登場した際に、容易に置き換えられる柔軟性が求められたためです。 以上より、次節で説明する クリーンアーキテクチャ(Clean Architecture) の思想を取り入れた設計を採用しました。 クリーンアーキテクチャとは # クリーンアーキテクチャ(Clean Architecture)は、Robert C. Martin (Uncle Bob) 氏によって提唱されたソフトウェア設計思想です。 同心円状の図で表現されることが多く、外側から内側に向かってのみ依存関係を持つ「依存性のルール(Dependency Rule)」が最大の特徴です。 The overriding rule that makes this architecture work is The Dependency Rule. This rule says that source code dependencies can only point inwards. Nothing in an inner circle can know anything at all about something in an outer circle. (出典: The Clean Architecture | The Clean Code Blog ) このアーキテクチャにおいて、最も内側に位置するのは「エンティティ(Entities)」や「ユースケース(Use Cases)」といった ドメイン(ビジネスロジック) です。 データベースやWebフレームワーク、UI、そしてロボットにおけるデバイスといった詳細な技術要素は、すべて外側に配置されます。 つまり、 「ドメインが詳細(インフラ)に依存するのではなく、詳細がドメインに依存する」 という構造を作ることが、クリーンアーキテクチャの核心です。 これにより、技術の流行り廃りやハードウェアの変更といった外的要因から、システムの核となるビジネスロジックを守ることができます。 具体的な設計の紹介 # システム物理配置 # システムの物理配置図を以下に示します。 ステレオタイプ<<app>>の要素がソフトウェアの実行単位となります。 よって、以下の3つが主要なソフトウェアの実行単位となります。 名前 説明 GUIApp GUIを有するアプリケーションである。ユーザ向けのGUIを提供する。コントローラPC上で実行され、操作パネルのタッチパネル上に表示される。 ControllerApp 本システムのコアアプリケーションである。機能的にはシステムの状態制御や登録データの管理、画像処理を行う。 その手段として、コントローラPCに接続されたデバイスの制御、Databaseの操作を行う。 また、GUIAppから接続可能なサーバー機能を有する。また、生産運転中に限り、画像処理結果を供給するビジョンサーバー機能を有する。 MotionController ロボットモーション制御を主に担うアプリケーションである。また、DIO接続デバイスや安全基盤との結合も担う。モーション制御に関する機能を持つサーバー機能を有し、ControllerAppがクライアントとして接続される。また、生産運転実行中はControllerAppのビジョンサーバーに接続し、画像処理結果を取得する。 --> Information GUIAppとControllerAppが何故別々の実行単位なのか 非機能要件で将来的に操作パネルをタブレット端末など別デバイスに変更する可能性があるため、GUI部分を分離している。 --> Information コントローラPCとロボットコントローラが分かれている理由 PoC段階でロボットコントローラとして KEBA社 のコントローラを使用していたため。 コンポーネント構成 # 美膳®のソフトウェアコンポーネント設計について解説します。 全体は、クリーンアーキテクチャのように同心円の表記ではありませんが、同様の思想に基づいて設計されています。 クリーンアーキテクチャの同心円にて中心方向に依存が向かうのと同様に、依存方向は下に向かっており、下層にはEntitesやInteractorなどのドメインロジックが配置されています。 コンポーネント 説明 ControllerApp 関連コンポーネントを結合し、実行可能にするアプリケーションコンポーネント。 ControllerAPI 外部(GUIAppや上位システム)との通信を担うAPI層。 Adapter 外部サービス(ビジョン・モーションなど)の実装コンポーネント。 Controllers メインのビジネスロジックを束ねるコンポーネント。 Controller ユースケース(Interactor)を統合・制御するコンポーネント。一般的なクリーンアーキテクチャのController(Interface Adapters)とは異なり、ここでは複数のInteractorを束ねる「アプリケーションサービス」に近い役割を担う。 StateMachine システムの状態遷移を管理するコンポーネント。Interactorで実現される機能に対して横断的にシステム状態遷移を実現する。 Port Adapterのインターフェース定義コンポーネント。外部サービスのインターフェースとなる。 Interactor ユースケースに応じたビジネスロジックフロー(機能)を実現する中心的なコンポーネント。 Entities ドメインモデルやデータ構造を定義するコンポーネント。 VisionController 画像処理関連機能を有するコンポーネント。 VisionAPI 画像処理機能を外部に提供するAPI。 MotionControllerAPI MotionControllerの機能を外部に提供するAPI。REST APIによるMotionControllerへの指令送信や状態取得をラップする。 Common 再利用性の高い共通で使用される汎用的なコンポーネント群。ロギング、数値計算、スレッド制御などの機能を集約している。 この構成における重要なポイントは、 Port (インターフェース) と Adapter (実装) の分離 です。 例えば、ビジョンシステムやモーション制御といった外部要素は、Portコンポーネントで定義されたインターフェースを通じてのみアクセスされます。 実体である Adapterは、このインターフェースを実装する形で提供されます。 これにより、Interactorなどのビジネスロジックは、具体的なカメラの機種やロボットコントローラの通信プロトコルを知る必要がなくなります。 結果として、ビジネスロジックが分離され、ハードウェアの変更が容易になり、テストの効率化と保守性の向上を実現しています。 おわりに # 今回は、中食工場向け盛り付けロボット美膳®の概要と、その裏側にあるソフトウェアアーキテクチャについてご紹介しました。 ロボット開発はハードウェアとソフトウェアが密接に関わるため複雑になりがちですが、適切な設計パターンを適用することで、もっと楽しく、効率的に開発できるようになります。 この記事が、日々ロボット開発に奮闘されているエンジニアの皆さんのヒントになれば嬉しいです。 豆蔵では、こうしたモダンな設計思想を取り入れたロボット開発を推進しています。 「ちょっと話を聞いてみたい」「ウチのロボットも何とかして」という方は、ぜひお気軽にご連絡ください。
これは 豆蔵デベロッパーサイトアドベントカレンダー2025 第19日目の記事です。 こんにちは&はじめまして、教育グループのやさぐれ豆ぱんだこと、おのでらです。 ユーザー部門(ビジネス部門)の皆様、ユーザーテスト(受け入れテスト)の依頼が来るたびに、 正直、こう思ったことはありませんか? 「情シスがちゃんとテストしたはずなのに、なんで私たちが改めてテストしなければいけないの?」 忙しい業務の合間を縫ってのテスト作業。「バグがないか確認するだけなら、プロである情報システム部門(以下、情シス)だけで完結してほしい」「これって二度手間じゃないの?」 ……そう感じてしまう気持ち、とてもよく分かります。 しかし、実は 「皆様がやらなければならない、代わりのきかない理由」 があるのです。 その理由を体感していただくために、少しだけ 「2つのチェック」 にお付き合いください。 チェック1:間違い探し # まず、以下の2つの画像を見比べてみてください。 「クマの設計書と完成イメージ [1] 」と、それを元に「実際に作られたクマの完成品(成果物)」です。 (↑クマの設計書) (↑クマの完成品(成果物)) この2つを見比べて、違う箇所を探してみてください。 「ここが違う」「あそこの色が違う」……いくつか見つかりましたか? 見つかった方は、どこが違うか心の中でメモしておいてください。 チェック2:目的の確認 # では次に、全く別の視点で考えてみてください。 そもそも、この「クマ」は何のために作ったのでしょうか? 実は、以下のような要件(目的)があったとします。 【目的】 会社の受付に置き、来訪されるお客様からの「会社の好感度」や「知名度」を上げるためのマスコットを作りたい。 この目的を聞いた上で、改めて先ほどの「ブロックのクマ」を見てください。 そして、 「これを自社の受付に置くべきかどうか」 を判断してみてください。 いかがでしょうか? 「おもちゃのようなブロックを受付に置くのは、会社のイメージに合わないのでは?」 「好感度を上げるという目的には、もっと洗練されたデザインの方がいいのでは?」 「なぜクマなの?というかパンダだよね?頼んでないクリスマスツリーもついてきてるよね?」 「いやいや、ウチもうマスコットキャラクター居るし」 おそらく、多くの人が 「この目的には適していない」 と感じたのではないでしょうか。 ここで種明かし:2つのテストの違い # さて、皆様には今、2種類のチェックを行っていただきました。 実はこの2つが、そのまま「情シス」と「ユーザー部門」の役割の違いを表しています。 1つ目のチェック=「システムテスト(情シス)」 # 最初に行った「間違い探し」は、 情報システム部門が実施する「システムテスト」 です。 これは「元々の設計書と見比べて、設計書通りに正しく作られているか」を確認する作業です。 情シスは、設計書通りにブロックが組まれているか(バグがないか)は完璧にチェックできます。しかし、それが「受付に置くのにふさわしいか」までは判断できません。 2つ目のチェック=「ユーザーテスト(皆様)」 # 次に行った「目的の確認」こそが、 皆様、ユーザー部門の皆様が実施する「ユーザーテスト」 です。 ユーザーテストで重要なのは、設計書通りかどうかのチェックではありません。 「要件定義で挙げた課題(好感度アップ)が本当に解決するのか」「このシステムは今の業務や目的に適しているのか」 を確認することです。 --> ちなみに「間違い探し」の箇所は 口の色がピンクじゃなくて赤 体の色が茶色じゃなくて白黒(≒クマじゃなくてパンダ) 舌が長い 左耳が長い 設計書に無い「クリスマスツリー」が作られている(誰だ、途中で要件追加したのは!?) まとめ:だから、皆様の「視点」が必要です # 1つ目のチェックで「設計通り完璧なクマ」ができていたとしても、2つ目のチェックで「受付にはふさわしくない」と判断されれば、ビジネスとしては失敗です。 そして、「これは受付に置けないな」と判断できるのは、普段その業務を行い、顧客と接している ユーザー部門の皆様だけ なのです。 「情シスがテストしたのに……」と感じることもあるかと思いますが、これからのユーザーテストでは、ぜひ 「業務のプロとしての視点」 を大切にしてください。 「バグを探す」のではなく、 「このシステムは、私たちの仕事を本当に良くしてくれるか?」 という視点で触っていただくことが、プロジェクト成功の鍵となります。 --> お知らせ 今回ご紹介した「クマの事例」は、 ユーザー部門向け研修 でお伝えしている内容のほんの一部です。 この研修では、単なる「テストの手順」や「要件定義のコツ」といったテクニック論ではなく、 なぜ、ユーザー部門がプロジェクトに関わらなければならないのか なぜ、情シス任せではプロジェクトが失敗するのか という 「本質的な役割と責任」 について深く掘り下げて解説します。 「システム導入のたびに『やらされ感』を感じている」というユーザー部門の方はもちろん、 「ユーザー部門にもっと当事者意識を持ってほしい」と感じている情報システム部門の方 にも、ぜひご覧いただきたい内容です。 お互いの「視点」を合わせ、プロジェクトを成功に導くために。 詳細は以下のリンクからご確認ください。 ▼ 研修の詳細・お申し込みはこちら https://www.mamezou.com/services/hrd/user_department_training ※本記事の画像作成には、ヨシリツ株式会社の知育玩具「[LaQ(ラキュー)]」を使用しています。 https://www.laq.co.jp/ ↩︎
これは 豆蔵デベロッパーサイトアドベントカレンダー2025 第18日目の記事です。 はじめに # 生成AIの進歩等により、人間にはますます知識よりも知恵が必要だと感じるビジネスソリューション事業部アジャイルグループの岸本大輔です。 アジャイル開発宣言が公開されてもうすぐ四半世紀。人によっては「まだまだこれから」「もうあたりまえ」あるいは「今となっては古い」など様々な意見があるようですが、重要なのは「よりよい方法を見つけだそうとし続けている」ことだと思います。 SAFeやLessやScrum@ScaleやDA等、アジャイルをスケールする工夫もそれぞれ進化しています。用語やこだわりポイントは多少違いますが、お互いリスペクトしながら参考にされているので少し抽象化して見ると似ている部分も多いですね。経済学や心理学等、様々な分野の知見もうまく活かしながら「よりよい方法」を見つけだそうとし続け、永遠のβ版になっている印象です。 それでも「スクラムのイベントが形骸化している」という悩みを持つチームもあります。「アジャイル」「スクラム」「リーン」などの名前ややり方だけではなく「何のために?」「どうなると幸せ?」について考えていると、ソフトウェア開発以外でも似たようなことがたくさんあり、それらを見つけて参考にするのが「気付き」や「刺激」になると思います。 ということで今回はお鮨屋さんを舞台に、アジャイルについて考えてみたいと思います。アジャイル初心者向けの知識習得には適していませんが、スクラムマスタやアジャイルコーチの考え方の引き出しを増やすための「気付きのきっかけ」になるとうれしいです。 以前、 よりよい方法を見つけだそうとし続けている: 自由があればよりよく進化する でも、「何でもアジャイルに見える例」をいくつかご紹介いたしましたが、今回のお話は お鮨屋さんに行くたびにアジャイルについて考えてしまう症状 が出てしまう可能性がございますので、あらかじめご了承いただけますようお願いいたします。 人生に必要な知恵はすべて幼稚園の砂場で学んだ # ちょっと昔の本ですが、タイトルがキャッチ-で覚えていらっしゃる方も多いのではないでしょうか? 実際、幼稚園の砂場で多くのことを学んでいたと思います。人生(そしてアジャイル)について。 昼寝の時間までのタイムボックス。こんなこともあったのでは? 砂場で「山を作りたいな~」「おもしろそうぼくも作る~」「わたしも~」みんなでモブワーク。 「ぼくは水をかける」「じゃあわたしは山を固めるね」「ぼくはトンネル掘るね~」「じゃあわたしは反対側から掘るわ」と自己管理。 「砂の固め方が弱くてつぶれちゃったね」「水かけすぎちゃってごめんね」ってふりかえり。 「じゃあ次はもっと大きい山にしてトンネル2本掘ろうか?」「楽しみ~♪」って次に何をするかの計画を相談。 そしてミルクを飲んでみんなでお昼寝♪ アジャイルに必要な知恵はすべて鮨屋のカウンターでも学んだ # みなさんお鮨はお好きでしょうか? お鮨屋さんではテーブル席で握りセットを頼みますか? それともやはりカウンターで一貫ずつ頼みますか? 例えば2人でテーブル席に座って、メニューで握りの「松セット」「竹セット」「梅セット」の写真と価格を見て、どれにするか選んだ場合、それぞれ一人前の個数やネタの種類や価格がはっきりしていて、全て揃ってからまとめて配膳(リリース)されます。なんだかウォーターフォールっぽいですね。 いきなりまとめて出てくるので、もし一貫食べて期待外れでもどうしようもありません。 ではカウンターに座った場合はどうでしょうか? 「飲み物は何にされますか?」みたいな感じで会話が始まり「今日は天然ひらめの縁側が入ってますよ~」ってことで「じゃあ塩炙りで」と答えつつネタケースに目を走らせる。 食べたいものから順番に食べたいタイミングで注文し、お腹がふくれて満足すればいつでもごちそうさま♪ もし期待外れなら早々に店を出ることもできます。 他のお客さんも、それぞれお気に入りのお鮨を頬張っています。 カウンターの中で握っている鮨職人さんは、周りの何人かのお客さんの注文を聞いて、基本的には注文された順番でお客さんに提供しますが、炙ったり多少時間がかかる注文は前後することもあります。 でもなぜかそれで揉めることはあまり無いんですよね~ 鮨職人さんの状況がお客さんたちに全部見えている(見える化されている)のが大きいんだろうなぁと思います。 もちろん聞こえる化も有効です。他のお客さんが注文してる時に割り込んで注文したりしないですよね?(自粛的排他制御?) 他のお客さんが「このウニおいしい~」って言ってるとウニが食べたくなるし、ネタケースを見てトロサーモンが少なくなってたら次に頼もうと思っていた寒ブリやめて、先にトロサーモンを頼んでみたり... 優先順位は自然に次々変わっていきますよね~ お客さんが食べる速度と、鮨職人さんの握る速度。だいたい3~5人ぐらいのお客さんを相手に握れる感じでしょうか。 ネタ等の都合により多少前後することはあっても、注文の順番は結構重要です。 それぞれのお客さんごとにプロダクトバックログがありつつ、それらを時系列でマージして1人の鮨職人さんが握るイメージ。 赤だしやお茶やお酒類などの注文は、鮨職人さん以外の店員さんが非同期で持ってきてくれることが多いですね。 注文するお客さんはそれぞれプロダクトオーナー。握ってくれる鮨職人さんは開発者。親方(店主)はスクラムマスターという感じでしょうか? (店を拡大したい場合、「カウンター5席&鮨職人さん1人」の単位で増やしていけば大規模アジャイル?) 「またこの鮨屋で食べたいなぁ」と思うか思わないかは、何で変わるでしょうか? # お鮨の味はもちろん、価格や店の雰囲気や鮨職人さんの対応等、全ての顧客体験が影響しますよね? ネタが新鮮で調理器具や食器も清潔で衛生上問題が無いというのはもちろん、頼んだお鮨の味が期待以上においしいという「体感できる価値」が品質。 鮨職人さんが特に気をつけるべきことはなんでしょうか? 食中毒等の発生防止や身だしなみ等、衛生面。 お客さんに快適に過ごしていただく言葉遣いや振る舞い等、接客面。 観光地の近くのお店であれば、英語での観光地紹介も多少はできた方がよさそうですね。 そしてもちろんカウンターに立つにふさわしい鮨職人としての調理スキルや品位。 でも、もしも「お客様と鮨職人さんの間に入ってやたら管理したがるタイプの親方がいる鮨屋」だったら? # 親方が気になることはなんでしょうか? 一貫の米粒の数が360~370になっていることでしょうか? 鮨職人さんが握ってお客さんの前に出したヒラメの握りを「ちょっとリリースしても問題がないか検査します」と言って横取りして米粒を数えたりしますでしょうか? 顕微鏡で一貫一貫、お客さんの目の前で確認し「菌はいません。安心して召し上がってください」と言いたいでしょうか? それでお客さんは安心しますでしょうか? 逆に不安になるのではないでしょうか? 鮨職人さんがカウンターでお客様に鮨を握っている「今」 親方が本当にやるべきことは何でしょうか? # もちろん食品衛生法や食品表示法、水産物の規格基準や労働安全衛生関連等の遵守が必要です。そしてHACCPに沿った衛生管理も2021年6月以降義務化されています。 特にお鮨屋さんは生魚を扱うため、食中毒リスクが高く、徹底した衛生管理が必須です。 でもお客さんの体験品質も重要ですよね。 完了の定義、準備完了の定義、受入基準のように分けるとこんな感じでしょうか? 完了の定義(店全体での品質基準)  法令・安全基準   食品衛生法遵守:調理場の衛生、従業員の健康管理、食材保管温度。   HACCP対応:工程ごとの危害要因分析と管理基準。   アレルゲン・原材料表示:テイクアウトや宅配時の必須情報。  店舗体験(ユーザーエクスペリエンス)   清潔なカウンターと器具。   鮨職人の所作が美しく、雰囲気が落ち着いている。   提供タイミングはお客様のペースに合わせる。 準備完了の定義(握り始める前に満たす必要がある条件)  ネタが規定温度で保管されている。  調理器具が洗浄・消毒済み。  鮨職人の手洗い・衛生確認完了。  注文内容が明確で、お客様の好み(わさび有無など)確認済み。 受入基準(鮨ネタごとの品質基準)  「ユーザーストーリーごとの受入条件」に近い考え方。  お客さん個人ごとにネタに対する期待値は異なりますが、それに対してどの程度超えられるのかが重要。  おいしさを数値的に表すのは難しいですね。同じ鯛でも産地や季節や個体によって異なりますし...  鯛(白身魚)   鮮度:透明感と弾力あり。   温度:冷蔵0~5℃。   切り付け:筋目を活かした美しい断面。  うなぎ   加熱:中心温度75℃以上で1分以上。   タレ:焦げすぎず均一な照り。   提供:温かいうちに出す。  ウニ   色:鮮やかな黄色~オレンジ。   匂い:海の香り。異臭なし。   盛り付け:崩れないよう丁寧に。 店内の清掃や、シャリやネタの準備は、もちろん暖簾を上げる前に完了させますが、開店から時間がたてば、ネタの補充や鮨職人の休憩なども必要になります。 一般の飲食店でも「大きな声で店員に指示する店主がいるお店はちょっと落ち着かない」と思われる方が多いと思いますが、落ち着いた静かなお鮨屋さんならなおさらですよね。 熟練した鮨職人さんは状況さえ把握すれば何をすべきかもわかります。ですので状況に「気付いてもらう」だけで十分です。もし何をすべきかわからない時はその場は親方が対応し、閉店後に反省会。 親方は静かに目や耳で店内の状況を観察しながら、目配せや目立たない振る舞いで、阿吽の呼吸で鮨職人さんたちとコミュニケーションをとり、絶えずよりよい顧客体験になるよう配慮されています。 この心地よさはおいしい日本酒も効いてるのかなと思いつつ、そろそろ満腹です。ごちそうさま♪ おわりに # 海外でも人気のお鮨。一人前の鮨職人さんになるには10年以上の修業が必要と言われていますが、最近では年齢や性別関係なく専門の学校で短期間に効率よく技術習得もできるようですね。 ここでもよりよく流れるように進化するという「コンストラクタル法則」が当てはまりそうです。 確かな技術の上で、さらにお客さんに満足いただけるように、自分たちで自由に工夫する。そのフィードバックはリアルタイムに返ってくる。 よりよい方法を見つけだそうとし続ける自由は誰も奪えない。 お鮨屋さんのカウンターで鮨職人さんが握ったお鮨を、お客さんがおいしそうに食べているのを見ていると、アジャイルについてもいろいろ考えてしまいます。 もうすぐ2026年。みなさまにとってよりよい年になりますように!
これは 豆蔵デベロッパーサイトアドベントカレンダー2025 第17日目の記事です。 1. はじめに:なぜ今、PBTを試すのか # プロパティベーステスト(以下 PBT)は、 仕様から抽出された「満たすべき性質(property)」を任意の入力・状態・操作系列に対して検証する テスト手法です。PBT は、従来の事例ベーステストと 相互補完的な関係にある ことが知られています [1] 。 正直、この説明だけでピンと来る人は多くないのではないでしょうか。私自身も、以前から興味はあったものの、満たすべき挙動の形式化が難しい、実装コストが高そうと感じて手を出せずにいました。 しかし、2025年11月17日に GA となった Kiro では、IDE 機能として 「プロパティベーステストによる仕様の正確性検証」 が導入されました [2] 。この新機能により、PBT 導入のハードルが下がったように見えたため、 実際に手を動かして体験してみることにしました。 Kiro の PBT 機能については、公式ドキュメント「 Correctness with Property-based tests 」を参照してください。 2. なぜ PBT なのか:EBT との決定的な違い # 書籍『実践プロパティベーステスト』 [3] では、PBT の特徴を次のように説明しています。 テストのための例をたくさん書いたり、コードに投げるためのランダムなデータを生成したりするのではなく、コードに潜む思いもよらなかった新しいバグを見つけるための手法である 具体例で考えてみましょう。従来の事例ベーステスト(EBT)では「1 と 3 を足したら 4 になる」のような特定の例を確認します。一方 PBT では「どんな数字を 2 つ足しても、順番を変えて足した結果と同一になる」という普遍的な性質を定義します。 左図は EBT、右図は PBT のイメージです。EBT はテストケースを手動で作成し検証する一方、PBT はプロパティを定義してランダムな入力で検証します。 つまり、EBT は 予測可能なバグ に強く、PBT は 予測できなかったバグ を発見できる可能性があります。この違いは、後半の UI 表示テストで実感することになります。 3. 題材に「チケット管理」を選んだ理由 # Kiro + PBT の解説記事として、「部屋移動ゲーム」を題材にした Medium 記事 [4] があります。 このゲームは、以下の構造により PBT に非常に向いています。 状態 × 操作 × 不変条件(Property) 同じ構造は、 業務アプリケーション にも頻出すると考え、 今回はその一例である、「チケット管理」を題材とすることにしました。 チケット管理には以下の特徴があります。 状態遷移の制約 終端状態の不変条件 再実行・順序依存性 異常系の保証 これらは 事例ベーステストでは拾いにくいが、PBT と相性が良い性質 です。 そのため、実務への応用を意識してチケット管理を題材に選びました。 4. 仕様:極めてシンプルなチケット管理 # 今回は、あえて仕様を極限まで単純にしました。 チケットの状態 # Status = { Open, InProgress, Done } 上記の3つのみ 許可される状態遷移 # Open → InProgress InProgress → Done 上記以外の遷移はすべて無効 Done は終端状態であり、どの操作も受け付けない この最小仕様を、Kiro に入力していきます。 5. Kiro による Property-Based Testing の実行 # 5-1. 要件文書(requirements.md)の生成 # まず、Kiro IDE に以下の要件を入力します。 - GUI ベースの簡易チケット管理アプリを作成する - 永続化は不要、検証用の最小アプリとする - チケットは必ず3状態のいずれかを持つ - 状態は「未対応→対応中→完了」の一方向のみ遷移可能 - 完了状態から他状態へは遷移できない - 状態更新はボタン押下で切り替える - 機能は作成・一覧・状態更新に限定 - 状態遷移ルールを不変条件として PBT で検証したい 以下のような要件文書が出力されました。 受入基準が EARS 記法 [5] (「Easy Approach to Requirements Syntax: 要件定義の構文ルール)で明確に言語化 されています。 要件文書の抜粋 ### 要件3 **ユーザーストーリー:** ユーザーとして、チケットの状態を更新したい。作業の進捗を正確に反映するため。 #### 受入基準 1. WHEN ユーザーが未対応チケットの状態更新ボタンを押した時 THEN Ticket_System SHALL そのチケットを対応中状態に変更する 2. WHEN ユーザーが対応中チケットの状態更新ボタンを押した時 THEN Ticket_System SHALL そのチケットを完了状態に変更する 3. WHEN チケットが完了状態の時 THEN Ticket_System SHALL 状態更新ボタンを無効化する 4. WHEN 状態遷移が実行される時 THEN Ticket_System SHALL 未対応から対応中、対応中から完了の順序のみを許可する 5. WHEN 完了状態のチケットに対して状態変更が試行された時 THEN Ticket_System SHALL その操作を拒否し現在の状態を維持する 特に注目したのは、無効な遷移は拒否される、完了状態では操作できない、状態遷移の順序制約といった 後続の Property 定義につながる記述 が明確になっていた点です。 5-2. 設計文書(design.md)と Property 定義 # 設計書生成時、Kiro は次のことを宣言しました。 設計文書の前半部分を作成しました。次に、受入基準の分析を行ってから正確性プロパティを定義します。 出力結果の抜粋は以下でした。 Property が設計成果物として明示的に出力 されています。 設計文書の抜粋 ### プロパティ1: チケット作成時の初期状態 *任意の*有効なタイトルに対して、新しいチケットを作成すると、そのチケットは常に未対応状態で作成される ### プロパティ2: チケット作成時のリスト追加 *任意の*チケットリストと有効なタイトルに対して、新しいチケットを作成すると、リストのサイズが1増加し、新しいチケットがリストに含まれる ### プロパティ3: チケット表示内容の完全性 *任意の*チケットに対して、そのチケットをレンダリングした結果には、タイトルと現在の状態情報が含まれる ### プロパティ4: 有効な状態遷移の実行 *任意の*チケットと有効な遷移(未対応→対応中、対応中→完了)に対して、状態更新操作を実行すると、チケットの状態が期待される次の状態に変更される ### プロパティ5: 無効な状態遷移の拒否 *任意の*チケットと無効な遷移に対して、状態更新操作を実行しても、チケットの状態は変更されない ### プロパティ6: 完了状態での操作無効化 *任意の*完了状態のチケットに対して、状態更新ボタンは無効化され、操作が実行できない ### プロパティ7: システム不変条件の維持 *任意の*操作(作成、状態更新)の実行後、システム内の全てのチケットは有効な状態(未対応、対応中、完了のいずれか)を持つ 結果として、状態遷移だけでなく、初期状態の不変性、表示内容の完全性、システム全体の不変条件など、 人が明示的に頼んでいない Property まで含めて 7 件 が定義されました。 5-3. 実装計画(tasks.md)と Property のトレーサビリティ # 以下のような実装計画が出力されました。 実装計画の抜粋 - [ ] 2. ビジネスロジック層 - [ ] 2.1 状態遷移ロジックのテスト作成 - **プロパティ4: 有効な状態遷移の実行** (要件 3.1, 3.2, 3.4) - **プロパティ5: 無効な状態遷移の拒否** (要件 3.5, 4.2) - _要件: 3.1, 3.2, 3.4, 3.5, 4.2_ - [ ] 2.2 状態遷移関数の実装 - 有効な遷移の判定ロジック - 状態更新処理の実装 - テスト実行と通過確認 - _要件: 3.1, 3.2, 3.4, 3.5_ tasks.md では、Property、要件、テスト、実装タスクが対応付けられており、 「なぜこのテストが存在するのか」 が追跡可能になっていました。 また、TDD によるテストファーストの原則を採用したため、以下の流れが自然に形成されています。 テスト作成 → 実装 TDDを用いたAI駆動開発については、以下の記事も参照してください。 https://developer.mamezou-tech.com/blogs/2025/11/28/qdev-aidd-spec-kit/ 5-4. 実装と PBT の具体例 # 状態遷移の Property は、fast-check [6] を用いた PBT として実装しました。 記述されたテストコードサンプルを提示します。任意のタイトル、任意の有効状態に対して、 遷移の性質が必ず成立すること を検証しています。 TypeScript と fast-check によるテストコード例 test('未対応から対応中への遷移が正しく実行される', () => { fc.assert( fc.property(validTitleArb, (title) => { const ticket: Ticket = { title, status: TicketStatus.PENDING }; // 未対応から対応中への遷移は有効 const isValid = isValidTransition(ticket.status, TicketStatus.IN_PROGRESS); const nextStatus = getNextStatus(ticket.status); expect(isValid).toBe(true); expect(nextStatus).toBe(TicketStatus.IN_PROGRESS); }), { numRuns: 100 } ); }); 5-5. 動作確認 # 完成した画面にいくつかチケットを登録したり、エラーを発生させてみて、動作確認を行いました。 6. まとめ:Kiro で PBT を実装して分かったこと # 正直に言うと、 状態遷移だけでは PBT の凄さは分かりにくい と感じました。 今回の状態遷移のルールは単純なため、事例ベーステストでも十分に確認できてしまうからです。 しかし、UI 表示に関する Property で状況が一変します。 想定外だった発見 # チケットタイトル表示の Property テストでは、 連続する空白が HTML によって正規化されることや、 前後の空白・空白のみのタイトルの扱いが曖昧であることなど、 仕様として意識していなかった問題 が検出されました。 これらは、手動テストや事例ベーステストでは、まずテスト観点として挙がらなかったと思います。 この経験から、 PBT の価値は「網羅的に試すこと」ではなく、 「人が想定していなかった入力や前提を炙り出すこと」 にあると実感しました。 7. おわりに # Kiro を使うことで、以下のことを実感しました。 PBT 導入の心理的・実装的ハードルは確実に下がった。 Property を中心に仕様・設計・テストをつなげられる。 今回は単体レベルでしたが、 結合テストやシステムテストでの活用 も価値がありそうです。 今回使用したリポジトリは以下で公開しています。 (予告なく公開停止する可能性があります) https://github.com/hironori-maruoka/kiro-pbt-sample Takuto Wada. Property-based Testing の位置付け / Intro to Property-based Testing . Speaker Deck. ↩︎ Amazon Web Services. Kiro:生成 AI で IDE とコマンドライン機能を強化する新ツールが一般提供開始 . AWS ブログ, 2025. ↩︎ Fred Hebert, Leonid Rozenberg. 実践プロパティベーステスト ― PropErとErlang/Elixirではじめよう . ラムダノート, 2023. ↩︎ Matheus Evangelista. Building Smarter with Kiro: A Hands-On Look at Property-Based Testing . Medium, 2025. ↩︎ Alistair Mavin. EARS: The Easy Approach to Requirements Syntax . ↩︎ fast-check. fast-check . ↩︎