コース内容
トピック0:イントロダクション
なぜAIを学ぶ必要があるのか?全社員がAIを使うことを常識化することで、売上や給与の向上がどのくらい見込めるか?を説明します。
0/61
(※準備中)トピック2:効果的な質問の仕方とは?〜AIを活かすプロンプトの作り方〜
AIを活用する上で最も重要なのがプロンプトの作り方です。プロンプト次第でAIは嘘をつく(ハルシネーション)ことも、思い通りの出力をしないことも多々あります。現在AIを上手に仕事に活用している人たちは、ずばりプロンプトの作り方が上手な人たちです。AIを活かすプロンプトの作り方をこのトピックで徹底的に学びましょう。
東光ブロズAI活用レクチャー

 

L44:JavaScript応用(状態遷移表=State Machine)+非同期(擬似API)+リトライ/キャンセル+ログ設計(TRAINING ONLY/流用禁止)

【重要:本レッスンは訓練専用】

  • このレッスンで作る「サンプルHTML/CSS/JS」「状態遷移表」「擬似API」「リトライ/キャンセル実装」「ログ(イベント記録)」等は訓練専用です。通常業務でそのまま使用することは禁止します(コピペ流用禁止)。
  • 実サイト更新・実公開・実リポジトリ反映は禁止:本番環境/実CMS/実タグ/実URLには触れません(ローカルファイル・ダミーのみ)。
  • 実データ・個人情報・未公開情報は禁止(実案件名、実ページID、実在のSKU/取引先/条件などは書かない)。
  • 本番で必要になった場合は、訓練成果物を流用せず、情報を取り直し、別途レビュー/承認を経て新規作成してください。

L43で学んだ state → render → event → guard の最小構造を、非同期(擬似通信)でも破綻しない形に拡張します。
ポイントは「クリックイベント」ではなく、状態遷移(State Machine)を先に固定し、成功/失敗/空/キャンセル/タイムアウトを“仕様として再現可能”にすることです。

このページの使い方

1レッスン=1LP(1ページ)です。上から順に当日の時間割に沿って進めてください。
各項目の冒頭に EC事業部文房具カフェ事業部・準備室 の実施時間を併記しています。
※本レッスンはダミーのみで行います(実データ・個人情報・未公開情報は入力しない)。


このレッスンの狙い(到達状態)

  • 非同期UIを「イベントの寄せ集め」ではなく、状態遷移(state machine)として説明できる
  • loading/error/empty/canceled/timeout を、再現条件付きで実装できる(ランダム禁止推奨)
  • 二重実行・競合(古いレスポンスで上書き)を、requestId等のガードで止められる
  • リトライ(手動/自動)と復帰導線を持たせ、壊れても戻れるUIにできる
  • イベントログ(いつ何が起きたか)を残し、デバッグ/検収に耐える形にできる

受講ルール(共通)

  • 実データ禁止:実URL、実ページID、実アカウント、実顧客情報、未公開企画などは禁止
  • 訓練成果物の流用禁止:訓練で作ったコード/要件/テンプレを通常業務へコピペしない
  • 通常業務をしない:訓練日は講義・演習・レビュー・理解度確認に専念する
  • 命令系統の具体化をしない:役割は「作成担当」「レビュー担当」「承認担当」など抽象ロール
  • 相互レビュー2件以上:前日までの他者成果物に2件以上コメント(本ページの観点を使用)

今日の目標(できた範囲でOK)

受講者のレベル差があるため、強制の提出物は設けません。今日の目標を選び、できた範囲を「今日進めたこと」に記録してください。

  1. (A)TRN-JS44 Specヘッダ(v0.1):状態/例外/再現条件/完了条件を固定
  2. (B)状態遷移表(v0.1):状態×イベント×ガード×副作用(Side Effect)を表にする
  3. (C)擬似API+requestIdガード:競合(古い結果の上書き)を防ぐ
  4. (D)復帰導線:retry/cancel/入力修正の動線を作る(error/timeout/empty)
  5. (E)イベントログ(v0.1):時系列で追えるログ(再現→原因仮説→修正確認)を残す

結論:非同期UIは「状態遷移表」がないと壊れる

ありがちな事故(非同期で一気に増える)

  • 二重実行:loading中の連打で同じ処理が2回走る
  • 競合:Aの結果が遅れて返ってきて、Bの結果を上書きする(順序問題)
  • 復帰できない:error/timeout/empty から戻るボタンがない
  • 原因不明:ログがなく、いつ何が起きたか追えない

今日の最小ルール(これで壊れにくい)

  1. 状態は列挙する(idle/loading/success/empty/error/canceled/timeout)
  2. 状態遷移表で「起きうる遷移だけ」を許可する
  3. requestId(世代)で古い結果を捨てる(競合ガード)
  4. 復帰導線を必ず置く(retry / 条件変更 / close)
  5. ログを残す(デバッグと検収の共通言語)

標準テンプレ(TRAINING ONLY)

A) TRN-JS44 Specヘッダ(v0.1)

【TRN-JS44 Specヘッダ(v0.1:訓練専用・流用禁止)】
Spec-ID:TRN-JS44
版:v0.1
状態:DRAFT / REVIEW / FINAL(訓練内)

UI対象(ダミー):

* 例:リスト取得(擬似API)+フィルタ+再試行
  目的(1行):
* 例:非同期UIを「状態遷移表」で固定し、競合・二重実行・復帰不能を防ぐ練習

範囲(やる/やらない):

* やる:state machine設計/擬似API/retry/cancel/ログ(ダミー)
* やらない:実API接続、実サイト更新、実公開、実運用データ反映

状態(この中から使う):

* idle / loading / success / empty / error / canceled / timeout

再現条件(必須:ランダム禁止推奨):

* success:条件A(例:カテゴリ=all)
* empty:条件B(例:カテゴリ=empty)
* error:条件C(例:失敗スイッチON)
* timeout:条件D(例:遅延スイッチON+タイムアウト短)
* canceled:条件E(例:loading中にCancel押下)

例外(最低3つ):

* 二重実行(loading中の連打)
* 競合(古いレスポンスの上書き)
* 復帰不能(error/timeout/emptyから戻れない)

ログ(残すもの):

* 時刻(相対でOK)
* イベント名(FETCH_START / FETCH_OK / FETCH_FAIL 等)
* requestId
* 状態(from→to)
* 入力条件(ダミー)
* エラーメッセージ(あれば)

完了条件(採点可能):

* 状態遷移表があり、実装がそれに従っている
* requestId等で競合が防げる
* retry/cancelが機能し、復帰できる
* ログで再現→原因→確認が追える
* 実データ混入がない(訓練専用の明記あり)

B) 状態遷移表(State Machine:最小形)

※「イベントが来たら何が起きるか」を表に固定します。

From(状態) Event(入力) Guard(許可条件) To(状態) Side Effect(副作用) ログ
idle FETCH_CLICK 常にOK loading requestId++ / 擬似API開始 FETCH_START
loading FETCH_OK requestId一致 success / empty データ反映 FETCH_OK
loading FETCH_FAIL requestId一致 error / timeout エラー表示 FETCH_FAIL
loading CANCEL_CLICK 常にOK canceled 以後の結果を無視(requestId更新) FETCH_CANCEL
error/timeout/empty RETRY_CLICK 常にOK loading 再試行 FETCH_RETRY
success/empty/error/timeout/canceled RESET_CLICK 常にOK idle 初期化 RESET

ダミー課題(どれか1つでOK)

JS-44A(易):リスト取得+empty+retry(競合は扱わない)

状況(ダミー):
- 「読み込み」ボタンで擬似データを表示
- empty条件がある(カテゴリ=empty)

要求:

* 状態:idle/loading/success/empty/error
* error/emptyの復帰導線(retry or reset)
* ランダム禁止(再現条件を固定)

JS-44B(中):競合ガード(requestId)+cancel

状況(ダミー):
- フィルタを切り替えて連続で読み込み
- 先に押した方の結果が遅れて返ってくる場合がある

要求:

* requestIdで古い結果を捨てる(上書き防止)
* cancelでloadingを止める(以後の結果を無視)

JS-44C(難):timeout(擬似)+復帰(retry)+ログ強化

状況(ダミー):
- 「遅延スイッチON」で擬似応答が遅くなる
- 「タイムアウト短」でtimeoutにする

要求:

* timeout状態を持つ(message/復帰導線)
* ログに requestId / 状態遷移 / 条件 を残す

サンプル(訓練用:JS-44B/C相当)

※このサンプルは訓練用の型です。実務に流用しないでください。

1) HTML(index.html想定:抜粋)

<!-- TRAINING ONLY: TRN-JS44(流用禁止) -->
<div class="trn">
  <h2>TRN-JS44:非同期UI(擬似API)+状態遷移+ログ(ダミー)</h2>

※実データ禁止。実API接続禁止。これは訓練用ダミーです。

 

“` <label><input id=”failSwitch” type=”checkbox”> 失敗にする(error)</label> <label><input id=”slowSwitch” type=”checkbox”> 遅延にする(timeout再現用)</label> <button id=”fetchBtn” type=”button”>読み込み(ダミー)</button> <button id=”cancelBtn” type=”button”>Cancel</button> <button id=”retryBtn” type=”button”>Retry</button> <button id=”resetBtn” type=”button”>Reset</button> “`

 

 

 

 

 

     

    イベントログ(訓練用)

     

     

     

    2) JS(script.js想定:抜粋)

    /* TRAINING ONLY: TRN-JS44(流用禁止) */
    
    const $ = (sel) => document.querySelector(sel);
    
    const els = {
    category: $("#category"),
    failSwitch: $("#failSwitch"),
    slowSwitch: $("#slowSwitch"),
    fetchBtn: $("#fetchBtn"),
    cancelBtn: $("#cancelBtn"),
    retryBtn: $("#retryBtn"),
    resetBtn: $("#resetBtn"),
    statusBar: $("#statusBar"),
    statusLive: $("#statusLive"),
    errorBox: $("#errorBox"),
    list: $("#list"),
    logBox: $("#logBox"),
    };
    
    const state = {
    status: "idle", // idle | loading | success | empty | error | canceled | timeout
    data: [],
    errorMessage: "",
    requestId: 0,      // 送信した世代
    activeRequestId: 0, // 画面が受理する世代(競合ガード)
    lastQuery: { category: "all", fail: false, slow: false },
    log: [],
    t0: Date.now(),
    };
    
    function nowMs() {
    return Date.now() - state.t0;
    }
    
    function addLog(type, meta = {}) {
    const item = {
    t: `${nowMs()}ms`,
    type,
    requestId: state.activeRequestId,
    status: state.status,
    meta,
    };
    state.log.push(item);
    // 長くなりすぎ防止(訓練用)
    if (state.log.length > 80) state.log.shift();
    }
    
    function setLive(text) {
    els.statusLive.textContent = text;
    }
    
    function render() {
    const isLoading = state.status === "loading";
    els.fetchBtn.disabled = isLoading;
    els.cancelBtn.disabled = !isLoading;
    els.retryBtn.disabled = isLoading || !(state.status === "error" || state.status === "timeout" || state.status === "empty");
    els.resetBtn.disabled = isLoading;
    
    // ステータス文言
    const s = state.status;
    let msg = "";
    if (s === "idle") msg = "待機中(ダミー)";
    if (s === "loading") msg = "読み込み中…(ダミー)";
    if (s === "success") msg = `表示中(${state.data.length}件:ダミー)`;
    if (s === "empty") msg = "該当なし(empty:ダミー)";
    if (s === "error") msg = "失敗(error:ダミー)";
    if (s === "timeout") msg = "タイムアウト(ダミー)";
    if (s === "canceled") msg = "キャンセル済み(ダミー)";
    
    els.statusBar.textContent = msg;
    
    // エラー表示
    if (s === "error" || s === "timeout") {
    els.errorBox.hidden = false;
    els.errorBox.textContent = state.errorMessage || "エラー(ダミー)";
    setLive(`エラー:${state.errorMessage || "ダミー"}`);
    } else {
    els.errorBox.hidden = true;
    els.errorBox.textContent = "";
    }
    
    // リスト表示
    els.list.innerHTML = "";
    if (s === "success") {
    for (const x of state.data) {
    const li = document.createElement("li");
    li.textContent = x;
    els.list.appendChild(li);
    }
    }
    
    // emptyは説明文だけ(リスト空のまま)
    if (s === "empty") {
    // 何もしない(statusBarが表示される)
    setLive("該当なし(ダミー)");
    }
    
    if (s === "loading") setLive("読み込み中(ダミー)");
    
    // ログ表示
    els.logBox.textContent = state.log
    .map((r) => `${r.t}\t${r.type}\t(id=${r.requestId})\tstatus=${r.status}\t${JSON.stringify(r.meta)}`)
    .join("\n");
    }
    
    // 擬似API(外部通信禁止:setTimeoutのみ)
    function fakeApi(query) {
    return new Promise((resolve, reject) => {
    const baseDelay = query.slow ? 1800 : 500; // 遅延スイッチでtimeout再現しやすく
    setTimeout(() => {
    if (query.fail) {
    reject(new Error("擬似失敗(failSwitch=ON)"));
    return;
    }
    if (query.category === "empty") {
    resolve([]);
    return;
    }
    if (query.category === "few") {
    resolve(["Dummy Item A", "Dummy Item B"]);
    return;
    }
    resolve(["Dummy Item 01", "Dummy Item 02", "Dummy Item 03"]);
    }, baseDelay);
    });
    }
    
    // タイムアウト(擬似):一定msで失敗にする(Promise.race)
    function withTimeout(promise, timeoutMs) {
    return Promise.race([
    promise,
    new Promise((_, reject) => {
    setTimeout(() => reject(new Error(`擬似タイムアウト(${timeoutMs}ms)`)), timeoutMs);
    }),
    ]);
    }
    
    function getQuery() {
    return {
    category: els.category.value,
    fail: !!els.failSwitch.checked,
    slow: !!els.slowSwitch.checked,
    };
    }
    
    async function startFetch(isRetry = false) {
    // Guard:二重実行防止
    if (state.status === "loading") return;
    
    const query = state.lastQuery = getQuery();
    state.status = "loading";
    state.errorMessage = "";
    state.data = [];
    state.requestId += 1;
    state.activeRequestId = state.requestId;
    
    addLog(isRetry ? "FETCH_RETRY" : "FETCH_START", { query });
    render();
    
    const myId = state.activeRequestId;
    
    try {
    // timeoutは固定値(訓練):slow ONのときtimeoutしやすく
    const timeoutMs = query.slow ? 800 : 2000;
    
    ```
    const data = await withTimeout(fakeApi(query), timeoutMs);
    
    // 競合ガード:古い結果は捨てる
    if (myId !== state.activeRequestId) {
      addLog("FETCH_IGNORED", { reason: "stale-response", myId });
      return;
    }
    
    state.data = data;
    state.status = data.length ? "success" : "empty";
    addLog("FETCH_OK", { count: data.length });
    render();
    ```
    
    } catch (e) {
    if (myId !== state.activeRequestId) {
    addLog("FETCH_IGNORED", { reason: "stale-error", myId });
    return;
    }
    const m = (e && e.message) ? e.message : "不明なエラー(ダミー)";
    state.errorMessage = m;
    state.status = m.includes("タイムアウト") ? "timeout" : "error";
    addLog("FETCH_FAIL", { message: m });
    render();
    
    ```
    // エラー時の最小復帰:フォーカスをretryへ(訓練)
    els.retryBtn.focus();
    ```
    
    }
    }
    
    function cancelFetch() {
    if (state.status !== "loading") return;
    // 「以後の結果を無視」するためにactiveRequestIdを進める
    state.activeRequestId = state.requestId + 1;
    state.requestId = state.activeRequestId;
    state.status = "canceled";
    addLog("FETCH_CANCEL", {});
    render();
    
    els.fetchBtn.focus();
    }
    
    function retryFetch() {
    if (!(state.status === "error" || state.status === "timeout" || state.status === "empty")) return;
    startFetch(true);
    }
    
    function resetAll() {
    if (state.status === "loading") return;
    state.status = "idle";
    state.data = [];
    state.errorMessage = "";
    state.lastQuery = { category: "all", fail: false, slow: false };
    addLog("RESET", {});
    render();
    els.fetchBtn.focus();
    }
    
    els.fetchBtn.addEventListener("click", () => startFetch(false));
    els.cancelBtn.addEventListener("click", cancelFetch);
    els.retryBtn.addEventListener("click", retryFetch);
    els.resetBtn.addEventListener("click", resetAll);
    
    // Enterでも読み込み(訓練:操作性)
    document.addEventListener("keydown", (ev) => {
    if (ev.key === "Enter" && document.activeElement === els.fetchBtn) {
    ev.preventDefault();
    startFetch(false);
    }
    });
    
    render();

    品質ゲート(OK/差戻し/要相談:v1.0)

    判定 基準 次アクション 記録
    OK 状態遷移表があり、loading/error/empty/canceled/timeoutが再現条件付きで動く。requestIdで競合が止まり、retry/resetで復帰できる。ログで追える。 次工程(検収観点/要件整合)へ 結果=OK、根拠(再現条件とログ)
    差戻し 状態が増えたのに表がない/競合が止まらない/復帰導線がない/再現条件がランダムで検収不能/ログがない v+0.1で修正(不足を埋める) 差戻し理由(どこ/なぜ/完了条件)
    要相談(停止) 実データ混入、実API/実サイト更新を誘導、通常業務に流用する意図がある、権利/法務/安全に触れる断定がある 作業停止→相談(抽象ルート) 停止理由、混入箇所、再開条件

    ChatGPTに投げるプロンプト(コピペ用)

    1) 状態遷移表(State Machine)を作る

    【L44 プロンプト①:状態遷移表(訓練用)】
    
    前提(安全):
    
    * 教育訓練用ダミー。実データ・実URL・未公開情報は禁止。
    * 訓練成果物は流用禁止。実API接続はしない(setTimeout等の擬似のみ)。
    
    入力:
    
    * L42で作ったUI要件(State表+例外表+A11y要件)
    * 選んだ課題(JS-44A/B/C)
    
    出力形式(必須):
    
    * 状態一覧(enum)
    * イベント一覧
    * 状態遷移表(From/Event/Guard/To/SideEffect/Log)
    * 再現条件(success/empty/error/timeout/canceled)

    2) requestIdガード+擬似APIの骨格を作る

    【L44 プロンプト②:非同期の骨格(訓練用)】
    
    前提:
    
    * 外部通信禁止(fetchしない)。擬似APIはPromise+setTimeoutのみ。
    * stateとrenderを分け、状態遷移表どおりに実装する。
    * 競合防止:requestId(世代)で古いレスポンスを無視する。
    
    入力:
    
    * あなたの状態遷移表
    * UI要件(抜粋)
    
    出力形式:
    
    * HTML(ボタン/フィルタ/メッセージ/ログ領域)
    * JS(state/render/event/guard/requestId/擬似API)
    * TRAINING ONLY/流用禁止の明記

    3) 復帰導線(retry/cancel/timeout)とログを強化する

    【L44 プロンプト③:復帰+ログ(訓練用)】
    
    入力:
    
    * あなたのHTML/JS
    * L44の品質ゲート
    
    出力:
    
    * 足りない状態(timeout/canceled等)があれば追加案
    * 復帰導線(retry/reset/cancel)を仕様→実装で揃える修正
    * ログ項目(時刻/イベント/requestId/状態/条件/結果)を満たす実装案
    * 自己判定(OK/差戻し/要相談)と理由

    相互レビュー観点(L44専用)

    • 訓練専用の担保:流用禁止が明記され、実在情報が混入していないか
    • 状態遷移表:表があり、実装が表どおりに見えるか(増えた状態を放置していないか)
    • 競合・二重実行:requestId等で競合が止まり、loading中の連打が止まるか
    • 復帰導線:error/timeout/empty/canceled から戻れるか
    • 再現性:success/empty/error/timeout が再現条件付きで検収できるか(ランダム禁止推奨)
    • ログ:何が起きたか追えるログになっているか(時刻・id・状態・条件)

    レビューコメントテンプレ(コピペ用)

    【L44 相互レビューコメント】
    対象(TRN-JS44):
    版:
    
    1. 良い点(1つ):
    
    *
    
    2. 状態遷移表はある?実装は従ってる?
    
    * OK / 要改善
      不足(1つ):
    *
    
    3. 競合/二重実行は止められる?
    
    * OK / 要改善
      再現手順(問題が出るなら):
    *
    
    4. 復帰導線(retry/cancel/timeout)はある?
    
    * OK / 要改善
      不足(1つ):
    *
    
    5. ログで追える?(時刻/イベント/requestId/状態/条件)
    
    * OK / 要改善
      不足(1つ):
    *
    
    6. 次の一手(v+0.1で直すなら):
    
    * 

    本日の流れ(タイムライン)

    目次(クリックで移動)

    1. 出席・当日選択カリキュラムの内容確認
    2. 時間差相互評価(2件以上コメント)
    3. 休憩
    4. 自分への受領レビュー確認・改善方針メモ
    5. L44 レクチャー本編(講師説明・質疑込み)
    6. 昼休憩
    7. 個人演習①:Spec→状態遷移表→骨格実装
    8. 休憩
    9. 個人演習②:競合/復帰/ログ強化→v+0.1改善
    10. 休憩
    11. 復習:共有できる形に整形(できた範囲でOK)
    12. 質問・コメント・感想の提出(指定スレッド)

    1) 出席・当日選択カリキュラムの内容確認

    【実施時間】

    対象 時間
    EC事業部 08:30–09:10
    文房具カフェ事業部/準備室 10:00–10:40

    この時間にやること

    1. 今日の目標(A〜E)を選ぶ(できた範囲でOK)
    2. ダミー課題(JS-44A/B/C)を1つ選ぶ
    3. 注意点を1行で書く(例:状態遷移表から書く/競合を止める/流用禁止)

    セルフ棚卸し(コピペ用)

    【L44 セルフ棚卸し】
    1) 今日選ぶダミー課題:
    - JS-44A / JS-44B / JS-44C
    
    2. 自分が弱い点(1つ):
    
    * (例:状態の洗い出し/競合ガード/復帰導線/ログ設計)
    
    3. 今日の目標(1行):
    
    * 

    2) 時間差相互評価(前日までの他者成果物に2件以上コメント)

    【実施時間】

    対象 時間
    EC事業部 09:10–10:00
    文房具カフェ事業部/準備室 10:40–11:30

    この時間にやること

    • 前日までの他者成果物を2件選び、L44レビュー観点でコメントする
    • 「動いてる」より、状態遷移表・再現条件・復帰・ログを見る

    3) 休憩

    【実施時間】

    対象 時間
    EC事業部 10:00–10:15
    文房具カフェ事業部/準備室 11:30–11:45

    休憩:学習作業なし


    4) 自分への受領レビュー確認・改善方針メモ(講師レビュー含む)

    【実施時間】

    対象 時間
    EC事業部 10:15–10:45
    文房具カフェ事業部/準備室 11:45–12:15

    改善方針メモ(コピペ用)

    【L44 改善方針メモ】
    受領した指摘の要点(最大3つ):
    1)
    2)
    3)
    
    ## 直す理由(状態遷移が曖昧/競合が止まらない/復帰導線不足/ログ不足 等):
    
    直し方(どこを改善する?):
    
    * Spec(再現条件/完了条件):
    * 状態遷移表:
    * 競合/二重実行ガード:
    * 復帰導線(retry/cancel/reset):
    * ログ(項目/粒度):
    
    今日の最優先ルール(1行):
    
    * 

    5) 当日選択カリキュラム実施:L44レクチャー本編(講師説明・質疑込み)

    【実施時間】

    対象 時間
    EC事業部 10:45–12:00
    文房具カフェ事業部/準備室 12:15–13:30

    ここからが「読む/聞く」パート

    非同期UIは「頑張って書く」ほど事故ります。
    先に状態遷移表で“起きうること”を固定し、実装は表に従って作ります。
    午後は、ダミー課題を選び、競合/復帰/ログまで揃えます。


    6) 昼休憩

    【実施時間】

    対象 時間
    EC事業部 12:00–13:00
    文房具カフェ事業部/準備室 13:30–14:30

    昼休憩:学習作業なし


    7) 個人演習①:Spec→状態遷移表→骨格実装

    【実施時間】

    対象 時間
    EC事業部 13:00–14:30
    文房具カフェ事業部/準備室 14:30–16:00

    演習①のやり方(必須)

    1. TRN-JS44 Specヘッダ(v0.1)を埋める(再現条件・完了条件まで)
    2. 状態遷移表(v0.1)を作る(From/Event/Guard/To/SideEffect/Log)
    3. 骨格実装:state/render/event/guard を作る
    4. 擬似API(Promise+setTimeout)を入れる(外部通信禁止)

    提出用フォーマット(演習①:コピペ用/できた範囲でOK)

    【L44 演習① 提出(できた範囲でOK)】
    Spec-ID:TRN-JS44
    ダミー課題:
    
    ## (1) Specヘッダ(v0.1):
    
    ## (2) 状態遷移表(v0.1):
    
    (3) 骨格実装メモ(state/render/event/guard):
    
    * 

    8) 休憩

    【実施時間】

    対象 時間
    EC事業部 14:30–14:45
    文房具カフェ事業部/準備室 16:00–16:15

    休憩:学習作業なし


    9) 個人演習②:競合/復帰/ログ強化→v+0.1改善

    【実施時間】

    対象 時間
    EC事業部 14:45–15:45
    文房具カフェ事業部/準備室 16:15–17:15

    演習②のやり方(必須)

    1. 競合を再現し、requestId等で止める(古い結果を捨てる)
    2. error/timeout/empty/canceled から復帰できる導線(retry/reset)を揃える
    3. ログ(時刻/イベント/requestId/状態/条件/結果)を満たす
    4. 品質ゲートで自己判定(OK/差戻し/要相談)し、差戻しならv+0.1で直す

    提出用フォーマット(演習②:コピペ用/できた範囲でOK)

    【L44 演習② 提出(できた範囲でOK)】
    Spec-ID:TRN-JS44
    
    ## (1) 競合/二重実行の再現手順:
    
    ## (2) ガード実装(requestId等):
    
    ## (3) 復帰導線(retry/cancel/reset):
    
    ## (4) ログ(抜粋:3〜8行):
    
    (5) 品質ゲート判定:
    
    * 判定(OK/差戻し/要相談):
    * 根拠(1行):
    
    (6) 任意:v+0.1の改善ログ(何を/なぜ/どう直す):
    
    * 

    10) 休憩

    【実施時間】

    対象 時間
    EC事業部 15:45–16:00
    文房具カフェ事業部/準備室 17:15–17:30

    休憩:学習作業なし


    11) 復習:共有できる形に整形(できた範囲でOK)

    【実施時間】

    対象 時間
    EC事業部 16:00–16:30
    文房具カフェ事業部/準備室 17:30–18:00

    最終チェック(コピペ用)

    【L44 最終チェック】
    - 訓練専用(流用禁止)が明記されている
    - 実データ/実URL/実APIが混入していない
    - 状態遷移表があり、実装が従っている
    - success/empty/error/timeout/canceled が再現条件付き
    - requestId等で競合が止まる
    - retry/reset/cancelで復帰できる
    - ログで追える(時刻/イベント/requestId/状態/条件/結果)

    12) 講師への質問・コメント・感想の提出(指定スレッド)

    【実施時間】

    対象 時間
    EC事業部 16:30–17:00
    文房具カフェ事業部/準備室 18:00–18:30

    提出先(参考)

    EC事業部・文房具カフェ事業部:ChatWork の指定スレッド/準備室:Slack の指定スレッド

    提出テンプレ(コピペ用)

    【L44 提出(本人レポート)】
    
    1. 今日の学習内容(要約:3行)
    
    *
    *
    *
    
    2. 今日進めたこと(TRAINING ONLY:流用禁止)
    
    * 選んだ課題(JS-44A/B/C):
    * Specヘッダ:
    * 状態遷移表:
    * 競合ガード(requestId):
    * 復帰導線(retry/cancel/reset):
    * ログ(満たした項目):
    * 品質ゲート判定:
    
    3. 一番工夫した点(1つ)
       -(例:状態遷移表から書いた/競合再現→requestIdで止めた/timeout復帰を作った 等)
       理由:
    
    *
    
    4. 次に改善したい点(1つ)
    
    *
    
    ## 理由:
    
    5. 質問(最低1つ)
    
    * 

    ページ先頭へ戻る

    上部へスクロール