画面設計書とは

画面設計書(Screen Design Document)は、各画面の構成要素(UI部品・入力項目・ボタン)とその動作仕様(バリデーション・表示制御・画面遷移)を定義した設計書です。ワイヤーフレームと入力項目定義表・バリデーション定義表をセットで作成します。

基本設計フェーズの画面設計書はワイヤーフレームレベル(低精度モックアップ)で十分です。詳細なビジュアルデザイン(色・フォント・余白)は詳細設計フェーズで定義します。

💡 基本設計で定義すること vs 詳細設計で定義すること

基本設計:画面レイアウト・入力項目一覧・バリデーション種別・エラーメッセージ・画面遷移条件
詳細設計:UIコンポーネント詳細(プルダウン選択肢・ラベル文言)・CSS/スタイル定義・アニメーション仕様

① 画面レイアウト(ワイヤーフレーム)

ワイヤーフレームは画面を構成する主要ブロックの配置を定義します。基本設計段階では以下の要素を明示します。

  • ヘッダー/フッター:ロゴ・ナビゲーション・ログアウトボタンの有無
  • メインコンテンツ領域:検索フォーム・一覧テーブル・入力フォームの配置
  • サイドバー:メニュー・フィルタパネルの有無
  • ページネーション:一覧系画面でのページング位置(上部/下部)
  • ボタン配置:主要アクションボタン(登録・更新・削除・キャンセル)の位置

② 入力項目定義

各入力フォームに含まれる全入力項目を定義します。項目ごとにUI部品種別・データ型・最大長・必須/任意を明記します。

No.項目名論理名UI部品データ型最大長必須初期値備考
1商品コードproduct_codeテキスト文字列20文字必須英数字・ハイフンのみ
2商品名product_nameテキスト文字列100文字必須
3カテゴリcategory_idプルダウン整数必須m_categoryテーブルから取得
4単価unit_price数値入力数値(小数2桁)必須00円以上10,000,000円未満
5税区分tax_typeラジオボタン文字列必須10(標準税率)10=標準税率, 8=軽減税率, 0=非課税
6発売日release_date日付ピッカー日付任意本日過去日付も入力可
7商品説明descriptionテキストエリア文字列2000文字任意改行入力可
8公開フラグis_publicチェックボックス真偽値チェックなしチェックあり=公開

③ バリデーション定義

各入力項目に対してバリデーションルールを定義します。フロントエンド(ブラウザ側)とバックエンド(サーバー側)の両方でバリデーションを実装することが前提です。

項目名バリデーション種別ルールエラーメッセージID
商品コード必須チェック入力必須ERR001
商品コードフォーマットチェック英数字・ハイフンのみ(正規表現: ^[A-Za-z0-9\-]+$ERR010
商品コード文字数チェック1文字以上20文字以内ERR020
商品コード重複チェックDBに同一コードが存在しないこと(新規登録時のみ)ERR030
単価必須チェック入力必須ERR001
単価数値チェック数値(整数または小数)であることERR011
単価範囲チェック0以上10,000,000未満ERR021
商品名必須チェック空白のみは不可(trim後に空文字チェック)ERR001
商品名文字数チェック1文字以上100文字以内ERR020

④ エラーメッセージ定義

エラーメッセージIDに対応するメッセージ文言を定義します。メッセージは具体的に何が問題かを伝え、ユーザーが修正できるようにします。

メッセージIDメッセージ文言表示タイミング
ERR001「{項目名}」を入力してください。フォーカスアウト時 / 送信ボタン押下時
ERR010「{項目名}」は半角英数字とハイフン(-)のみ使用できます。フォーカスアウト時
ERR011「{項目名}」は数値を入力してください。フォーカスアウト時
ERR020「{項目名}」は{最小}文字以上{最大}文字以内で入力してください。フォーカスアウト時
ERR021「{項目名}」は{最小}以上{最大}未満の数値を入力してください。フォーカスアウト時
ERR030この{項目名}は既に登録されています。別の値を入力してください。送信ボタン押下時(サーバー側チェック)

⑤ 表示制御・活性・非活性条件

特定の入力値によって他の入力項目の表示・非表示・活性/非活性が変わる場合、その条件を明示します。

制御対象項目制御種別条件制御内容
軽減税率説明欄表示/非表示税区分 = 8(軽減税率)表示する(非表示→表示)
発売日活性/非活性公開フラグ = チェックなし非活性(入力不可)
削除ボタン表示/非表示ユーザーロール = 管理者以上表示する(一般ユーザーには非表示)

Python Tips — 入力定義からバリデーションコードを生成する

入力項目定義をYAMLやJSONで管理しておき、Pythonスクリプトでバリデーションコードを自動生成することで、設計書とコードの乖離を防げます。

Python — 入力定義YAMLからDjango Formコードを生成
"""
入力項目定義YAMLからDjango Formクラスを自動生成するスクリプト。
pip install pyyaml
"""
import yaml

# 入力項目定義(実際はYAMLファイルから読み込む)
FIELD_DEFINITIONS = """
fields:
  - name: product_code
    label: 商品コード
    type: CharField
    max_length: 20
    required: true
    validators:
      - type: regex
        pattern: "^[A-Za-z0-9\\\\-]+$"
        message: "半角英数字とハイフン(-)のみ使用できます。"
  - name: product_name
    label: 商品名
    type: CharField
    max_length: 100
    required: true
  - name: unit_price
    label: 単価
    type: DecimalField
    max_digits: 10
    decimal_places: 2
    required: true
    min_value: 0
    max_value: 9999999.99
  - name: category_id
    label: カテゴリ
    type: ChoiceField
    required: true
    choices_source: "m_category"
  - name: description
    label: 商品説明
    type: CharField
    widget: Textarea
    max_length: 2000
    required: false
  - name: is_public
    label: 公開フラグ
    type: BooleanField
    required: false
"""


def generate_django_form(yaml_str: str, form_class_name: str = "ProductForm") -> str:
    """入力定義YAMLからDjango Formクラスコードを生成する"""
    definition = yaml.safe_load(yaml_str)
    fields = definition.get("fields", [])

    lines = ["from django import forms", "from django.core.validators import RegexValidator", ""]
    lines.append(f"class {form_class_name}(forms.Form):")

    for field in fields:
        name = field["name"]
        ftype = field.get("type", "CharField")
        label = field.get("label", name)
        required = field.get("required", False)

        # フィールド定義生成
        kwargs = [f'label="{label}"', f'required={required}']

        if ftype == "CharField":
            if "max_length" in field:
                kwargs.append(f'max_length={field["max_length"]}')
            if field.get("widget") == "Textarea":
                kwargs.append("widget=forms.Textarea")

        elif ftype == "DecimalField":
            kwargs.append(f'max_digits={field.get("max_digits", 10)}')
            kwargs.append(f'decimal_places={field.get("decimal_places", 2)}')
            if "min_value" in field:
                kwargs.append(f'min_value={field["min_value"]}')
            if "max_value" in field:
                kwargs.append(f'max_value={field["max_value"]}')

        elif ftype == "ChoiceField":
            kwargs.append("choices=[]  # TODO: populate from model")

        # バリデーターの追加
        validators = field.get("validators", [])
        if validators:
            validator_strs = []
            for v in validators:
                if v["type"] == "regex":
                    pattern = v["pattern"].replace("\\\\", "\\")
                    msg = v.get("message", "入力形式が不正です。")
                    validator_strs.append(
                        f'RegexValidator(r"{pattern}", "{msg}")'
                    )
            if validator_strs:
                kwargs.append(f'validators=[{", ".join(validator_strs)}]')

        kwargs_str = ", ".join(kwargs)
        lines.append(f"    {name} = forms.{ftype}({kwargs_str})")

    return "\n".join(lines)


if __name__ == "__main__":
    code = generate_django_form(FIELD_DEFINITIONS, "ProductForm")
    print(code)

    # ファイルに出力
    with open("product_form.py", "w", encoding="utf-8") as f:
        f.write(code)
    print("\nproduct_form.py を生成しました")

設計書とコードの同期管理

入力項目定義をYAMLで管理し、Djangoフォーム・TypeScript型定義・OpenAPI仕様書を自動生成するパイプラインを構築することで、設計書変更時の実装漏れを防ぐことができます。

定義チェックリスト

チェック項目確認ポイント
□ 全入力項目が定義されているかフォーム内の全入力項目が入力項目定義表に記載されているか
□ バリデーションが全項目に定義されているか必須チェック・フォーマット・文字数・範囲チェックが漏れなく定義されているか
□ エラーメッセージが定義されているか全バリデーションエラーに対応するメッセージが定義されているか
□ 表示制御条件が定義されているか条件付き表示・活性制御の条件が全て明記されているか
□ 二重送信防止が考慮されているか登録・更新ボタンの二重送信防止方法が定義されているか
□ 入力補助が考慮されているかプレースホルダー・ツールチップ・入力例の有無が検討されているか