🐷

YAMLを共通言語にしたら、チームの”翻訳”コストが下がった話 🗣️

に公開

はじめに 👋

突然ですが、あなたのチームでは、デザイナー、PM、エンジニアがスムーズに意思疎通できていますか?

多くの場合、それぞれの専門用語や視点の違いから、微妙な認識のズレが生まれがちです。私たちはこれを「職種間の言語の壁 🧱」と呼んでいます。この壁は、手戻りや無駄な確認作業といった「翻訳コスト 💸」を生み出す原因になります。

そこで今回提案したいのが、画面要件をYAMLで定義し、チームの「共通言語」として運用する手法です。

この手法の目的は、単なるドキュメント管理の効率化ではありません。構造化されたYAMLを唯一の正(Single Source of Truth)とすることで、職種間の言語の壁を取り払い、チーム全体のコミュニケーションを円滑にすることにあります。

この記事では、具体的なYAMLの書き方から、チームの共通言語をどう育てるか、その実践方法をサンプルを交えてご紹介します。


なぜYAMLなのか? 🤔

チームの「共通言語」として、なぜYAMLが適しているのでしょうか。

  • 構造が明確 🏗️: インデントで階層を表現するため、誰が見ても要件の構造を同じように解釈できます。自然言語の曖昧さを排除できます。
  • 人間にも機械にも優しい 😊🤖: 人が読み書きしやすく、同時にプログラムでの処理も容易です。これにより、ドキュメントの自動生成やテストへの応用が可能になります。

実践: YAMLで画面要件を定義する ✍️

それでは、具体的な画面の要件をYAMLで定義してみましょう。今回は、シンプルな「ユーザープロフィール編集画面」を例にします。

screenName: "Edit User Profile"
tags: ["user", "profile", "form"]
description:
  ja: "ユーザーが自身のプロフィール情報を編集・更新する画面です。"
  en: "A screen where users can edit and update their profile information."
path: "/users/profile/edit"

layout:
  form:
    components:
      - id: "profileFieldSet"
        type: "fieldSet"
        label:
          ja: "プロフィール情報"
          en: "Profile Information"
        components:
          - id: "usernameInput"
            type: "input"
            label:
              ja: "ユーザー名"
              en: "Username"
            required: true
            placeholder:
              ja: "例: 山田 太郎"
              en: "e.g., Taro Yamada"
            validation: "maxLength:20"
            note:
              ja: "登録後に変更することはできません。"
              en: "Cannot be changed after registration."
          - id: "bioTextarea"
            type: "textarea"
            label:
              ja: "自己紹介"
              en: "Bio"
            required: false
            placeholder:
              ja: "あなたのことを教えてください"
              en: "Tell us about yourself"
            validation: "maxLength:200"
          - id: "bioCharCount"
            type: "display"
            label:
              ja: "現在の文字数"
              en: "Current character count"
            value:
              calculation: "length(bioTextarea.value)"
      - id: "locationSelect"
        type: "select"
        label:
          ja: "居住地"
          en: "Location"
        required: true
        options:
          - value: "hokkaido"
            ja: "北海道"
            en: "Hokkaido"
          - value: "tokyo"
            ja: "東京都"
            en: "Tokyo"
          - value: "osaka"
            ja: "大阪府"
            en: "Osaka"
          - value: "fukuoka"
            ja: "福岡県"
            en: "Fukuoka"
          - value: "other"
            ja: "その他"
            en: "Other"
  actions:
    components:
      - id: "submitButton"
        type: "button"
        label:
          ja: "更新する"
          en: "Update"
        style: "primary"
        action:
          ja: "システムへプロフィールの更新をリクエストする"
          en: "Request to update the profile"
        transition: "/users/profile"
        hover:
          type: "tooltip"
          text:
            ja: "プロフィール情報を保存します"
            en: "Save profile information"
        disabled:
          condition: "usernameInput is empty"
          note:
            ja: "ユーザー名が入力されると有効になります"
            en: "Enabled when username is entered"
      - id: "cancelButton"
        type: "button"
        label:
          ja: "キャンセル"
          en: "Cancel"
        style: "secondary"
        transition: "back"

errorHandling:
  "401":
    transition: "/login"
    message:
      ja: "再度ログインしてください。"
      en: "Please log in again."
  "403":
    transition: "/dashboard"
    message:
      ja: "この操作を行う権限がありません。"
      en: "You do not have permission to perform this action."
  "404":
    transition: "back"
    message:
      ja: "データが見つかりませんでした。"
      en: "Data not found."
  "500":
    transition: "/error"
    message:
      ja: "サーバーでエラーが発生しました。時間をおいて再度お試しください。"
      en: "A server error occurred. Please try again later."

ポイント:仕様をプログラムにしないための工夫 ✨

仕様書が複雑になりすぎて、それ自体がデバッグ対象のプログラムのようになってしまうのは、避けるべきアンチパターンです。このYAML定義は、そうならないための3つの重要な原則に基づいています。

1. 構造とコンテンツ(自然言語)を分離する

labelやplaceholderなど、ユーザーの目に触れるテキストはすべてjaenのプロパティで定義します。また、validationはmaxLength:20のように、自然言語を避けて構造的に記述します。これにより、仕様の「構造」と「文言」が完全に分離され、国際化対応が容易になるだけでなく、仕様書そのものの可読性も向上します。

2. 振る舞いは「宣言的」に書く

disabledの条件をcondition: "usernameInput is empty"と書いたり、valuecalculation: "length(bioTextarea.value)"と定義している点に注目してください。これは状態や要求を宣言しているだけで、「どのように実現するか」には言及していません。これにより、仕様書がシンプルに保たれ、デバッグが必要になる事態を避けています。

3. AI時代のドキュメント連携:idからtagsへ 🔗

かつて、ドキュメント同士を紐づけるには、ファイル名や固有のidを直接記述する必要がありました。しかし、この方法はドキュメントの独立性を損ない、変更に弱いという欠点がありました。

AIエディタの登場で、この常識は変わります。tagsこそが、AIが仕様の文脈を理解するための最大のヒントになります。tagsにuserprofileと記述しておくことで、AIアシスタントに「この画面に関連するAPI仕様を教えて」と尋ねれば、AIは文脈を理解し、関連するドキュメントを見つけ出してくれます。これにより、各ドキュメントの独立性を保ちながら、AIを介して必要な時にだけ関連性を引き出せます。


Markdownへの変換:伝わる形への「翻訳」 📖

YAMLを「原文」として、誰にとっても分かりやすいMarkdown形式に「翻訳」します。重要なのは、このMarkdownは**YAMLという「原文」からスクリプトで自動生成される「翻訳版」**だということです。これにより、情報の鮮度が常に保たれます。

画面名: ユーザープロフィール編集

  • Tags: user, profile, form
  • 概要: ユーザーが自身のプロフィール情報を編集・更新する画面です。
  • パス: /users/profile/edit

🖼️ 画面要素

ラベル 種類 必須 補足情報
ユーザー名 入力欄 バリデーション: maxLength:20
Note: 登録後に変更不可
自己紹介 テキストエリア バリデーション: maxLength:200
現在の文字数 表示 計算ロジック: 自己紹介の文字数を表示
居住地 プルダウン 選択肢: 北海道, 東京都, 大阪府, 福岡県, その他

🔘 アクション

ラベル スタイル アクション内容 補足情報
更新する primary システムへプロフィールの更新をリクエストする Hover: プロフィール情報を保存します
Disabled: ユーザー名が空の場合
キャンセル secondary 前画面へ戻る

➡️ 画面遷移

  • 更新するボタン押下時 → /users/profile (プロフィール画面へ)
  • キャンセルボタン押下時 → 前の画面に戻る

🚨 エラー時の挙動

  • 401 (Unauthorized): /login へ遷移、「再度ログインしてください。」
  • 403 (Forbidden): /dashboard へ遷移、「この操作を行う権限がありません。」
  • 404 (Not Found): 前の画面に戻り、「データが見つかりませんでした。」
  • 500 (Internal Server Error): /error へ遷移、「サーバーでエラーが発生しました。時間をおいて再度お試しください。」

まとめ:AIと共に開発する未来へ 🚀

この手法の最大の価値は、YAMLという共通言語が、人間とAIの共同作業を加速させる点にあります。

  • 🎨 デザイナーが考える「必須項目」
  • 💻 エンジニアが実装する required: true
  • 📈 PMが定義する「未入力では登録不可」というルール

これらはすべて、YAMLで定義された required: true という一つの事実を指します。そして、この「事実」の定義は、もはやエンジニアだけの仕事ではありません。非エンジニアでもこのYAMLにルールを定義し、生成AIに依頼しながらプロダクトを構築できます。

もし自分の書いたYAMLに自信がなければ、まずAIに「このYAMLをMarkdownにして」と依頼し、人間が読める形でレビューすればよいのです。

YAMLは、チーム内の言語の壁を越えるだけでなく、人間とAIの間の言語の壁をも越えるための強力なツールとなります。仕様書にidを振って管理するのではなく、AIが文脈を読んでくれる新しい開発スタイルが、この手法から見えてくるはずです。

あなたのチームでも、YAMLを「共通言語」として導入し、よりスムーズで未来的な開発体制を築いてみてはいかがでしょうか。

Discussion