前セツ
最近、シリーズものばかりで飽きてきたな。。。
どうも、え~すけさんですよ。
シリーズ4本目です。
- 「意見ください」って言ったやつ、公開しました
- 業務システムを1本まるごと作ったら 21人日が 3.75人日になった話
- AI に業務システムを作らせるとき、人が書く紙は2枚だけだった
- この記事 ← 転んだ話と、できてないこと
前の3本、我ながらわりといい話ばかりなんですよ。工数82%減とか、設計書が腐らないとか。
でも導入を検討する人にとって役に立つのって、どこで転ぶか、その穴がどれくらい深いか
のほうじゃないですか。
というわけで、踏んだやつ13件、見栄えのために減らさず全部出します。
自作フレームワークのバグ3件込みで。
※既に修正はしており、今もなお改善中でこの記事を下書き中にも裏で大きく修正をかけているので、情報としてもしかしたら古いかも知れない
内訳
| 出どころ | 件数 | 深さ |
|---|---|---|
| フレームワーク本体の不具合 | 3 | 半日/件。どれも外から使わないと出ない種類 |
| 書き間違い(道具が止めた) | 4 | 数分。理由も一緒に出るので調べる時間が要らない |
| 書き間違い(道具が止めなかった) | 2 | 半日。テストを書くまで出ない |
| 環境まわり(Docker・Flutter) | 4 | 数十分 |
一番怖かったのは3つ目です。あとで書きます。
A. フレームワーク本体の不具合(3件)
A-1 降順の指定が、黙って無視されていた
buildQuery が sortAscending の文字列 "false" を昇順として読んでました。
REST の契約は「クエリ文字列で送る」と決めてるので、
手引きどおりに書いたサーバが、降順を頼まれてるのに黙って昇順で返す。
画面には並びが出るので気づけません。
なんで中の試験で出なかったか:
リポジトリの中の試験は、クライアント側とサーバ側を別々に見てました。
契約の両端をつなぐ試験が無かった。
[画面側の試験] sortAscending: false を送る → OK
[サーバ側の試験] { sortAscending: false } を受ける → OK
↑ ここで文字列になることを誰も試していない
外から一気通貫で使って初めて出ました。
自分のフレームワークを自分で使ってなかったツケが、きれいに出たかたち。
対応: TypeScript と Java の両方を直して、共有フィクスチャに文字列の場合を足して
3言語で固定しました(v0.9.0 に収録)。
A-2 検証のパラメータ名を間違えても、黙って効かない
これが一番マズいやつでした。
- { type: pattern, value: "^[0-9]{6}$" } # 正しくは pattern:
validate も check も警告ゼロで通り、12A456 が6桁の規則を素通りしました。
検証の種類ごとに見るキーが違う(maxLength は value、pattern は pattern)んですが、
名前を間違えても解析もスキーマも通って、その検証が一度も効かない。
テストを書くまで誰も気づけません。
前回の記事で「hatake は知らないキーを黙って捨てるので strict を付けた」と書きましたが、
これは strict でも防げない。キーの名前としては正しいので。
対応: 新しい警告(validator-missing-param)を足しました。
何を書いてしまったかも名指しします。
※ 組み込みの検証だけを見ます。独自の検証は開いた文字列なので、
何を見るか枠組みが知らないため。
A-3 一覧にコードがそのまま出ていた
入力欄では「法人」「取引中」と出るのに、一覧では corp / active と生のコード。
同じ画面で同じ項目が2つの顔を持ってた。
気づいたきっかけが情けなくて、納品用のスクリーンショットに並んで初めて見えました。
デモでは気づいてない。
対応で悩んだところ: 列に options を書けるようにする案もあったんですが、
同じことを2か所に書かせると、片方だけ直したときに一覧と入力で違う字が出るので、
同じ画面の入力欄・検索条件から引く形にしました。DSL のキーは増やさない。
B. 書き間違いを、道具が止めてくれたもの(4件)
どれも動かす前に止まりました。「書けるけど意図どおり動かない」種類です。
| 何を書いたか | 道具が何と言ったか |
|---|---|
| 一括の上限を100件(1ページは50件) | 「選べるのは画面に出ている行だけなので、この上限は一度も効きません」 |
soft-delete という問いの印 |
「そんな問いはありません」(ask --kinds で正しい印を引け) |
| 採番を「枠組みの外」と書いた | 「numbering はサーバの担当です。区分が違います」 |
| 辞書の見出しを「区分」にした | 「employmentStatus に supplier が入っていません」 |
これ、全部数分で直ってます。理由も一緒に出るので、調べる時間が要らないのがデカい。
で、最後の1つは道具の言い分が正しくない例でもあります。
glossary の見出しを「区分」にしたせいで「在籍区分」まで巻き込んだだけで、
悪いのは辞書の書き方。
助言は好みなので、直すかどうかは人が決めるという設計がここで効きました。
これが警告(事実)だったら、間違った直しを強制されてた。
C. 道具が止めてくれなかったもの(2件・ここが本題)
| どう気づいたか | |
|---|---|
pattern の書き間違い(A-2) |
テストを書いて初めて出た |
守れない命名規則(naming.suffix.number: Amount) |
助言が鳴り続けて、こっちが折れた |
1つ目が今回いちばんの収穫です。
「AI が書いて、道具が検証して、警告ゼロ」でも、素通りする検証が作れてしまった。
これ、前回の記事で「AI First = AI が間違えたときに機械で気づける状態にすること」と
偉そうに書いた、その気づけない穴が自分のところに開いてたわけです。
しかも性質が悪いのは、画面は普通に動くことなんですよ。
6桁の規則が効いてないだけで、保存もできるし一覧にも出る。
テストを省いたら本番まで行きます。
教訓としては単純で、テストを省くな。
ただ「なぜ省いてはいけないか」が、抽象論じゃなく具体例で出たのはよかった。
2つ目は不具合じゃなくて教訓です。
守れない決めごとを書くと、助言が鳴りっぱなしになって、そのうち誰も読まなくなる。
決めごとは守れるものだけ書く。
D. 環境まわり(4件)
フレームワークと関係ないけど、実際に時間を溶かしたやつ。
| API が定義を見失って起動しない | Dockerfile がリポジトリと違う階層で置いてた。手元と同じ形に直した |
| 部署を消したらサーバごと落ちた | Express 4 は async の失敗を拾わない。包んで、制約違反は業務の言葉で返すようにした |
| 画面のアイコンが全部豆腐(□) |
pubspec.yaml に uses-material-design: true が無く、フォントが同梱されてなかった |
| テストが2回目から結果が変わる | postgres はデータ置き場をボリューム宣言してるので、作り直しても中身が残る(--renew-anon-volumes が要る) |
| 納品用のスクショが真っ白 | 「未ログインで撮る」件の判定が初期値と一致して、ページを開かずに撮ってた |
最後の2つ、エビデンスを作る側の落とし穴です。
どっちも見た目には成功してる(テストは緑、スクショは出力される)ので、
紙をよく見るまで気づきません。
「エビデンスも自動生成できます!」って前回書いたんですが、
生成できることと中身が正しいことは別でした。紙は目で見ましょう。
直し方の傾向
3つに分かれました。
| 道具が止めたもの | その場で直る(数分)。止めた理由も出るので、調べる時間が要らない |
| 道具が止めなかったもの | テストを書くまで出ない。だからテストを省くと危ない |
| 本体の不具合 | 外から一気通貫で使うと出る。中の試験は端ごとに見てるので、境目が抜ける |
3つ目、フレームワークを作ってる人には割と普遍的な話だと思ってます。
ユニットテストって、自分が切った境界の内側しか見ないんですよね。
バグは境界のつなぎ目にいる。
使ってみて分かった課題
ここからは「転んだ」じゃなくて「まだできてない・向いてない」の話です。
1. 枠組みが持たないものは、自分で書くことになる(約1,200行)
これは不具合じゃなくて決めごとなんですが、導入すると自分で作ることになります。
| 量 | |
|---|---|
| 認証・ログイン | 約 150 行 |
| 役割による本当の遮断 | 約 50 行 |
| 監査(誰が・いつ・何を) | 約 15 行 |
| 同時更新の弾き方 | 約 20 行 |
| 一括の中身(部分失敗の始末) | 約 100 行 |
| 納品用の設計資料を並べる紙 | 約 280 行 |
| 納品用のエビデンス(スクショ・API の記録) | 約 600 行 |
合計1,200行ほどが「枠組みの外」。
ただし案件をまたいで使い回せるものが大半です(認証・監査・エビデンスの道具は
2本目でほぼそのまま動くはず)。
判断材料: 1本目は枠組みの外を作る分が乗ります。効果が出るのは2本目から。
※ 画面の roles が止めるのは見せるかどうかだけです。API を直接叩けばデータは取れるので、
本当の遮断はサーバ側に書いてます。ここを誤解されると事故るので、
README にもデカく書きました。
2. 直ってないもの
| 困り方 | 回避したこと | |
|---|---|---|
hatake openapi が app 定義を読めない
|
画面が4枚あっても1枚ずつ切り出して渡す必要がある | API 一覧は Repository の契約から組んだ(むしろ正しい粒度だった) |
explain --roles --matrix --markdown が Markdown にならない |
幅を揃えた文字が出るだけ | コード囲みに入れて貼った |
hatake shot(定義から画面の写真)が未実装
|
エビデンスが作れない | ブラウザで撮る道具を自分で書いた(約200行) |
| 一覧の並べ替えできる列が定義から読めない | 設計書に出せない | 画面設計書には出ていない |
最後のやつ、定義には sortable: true って書いてあるのに、explain が言わないんですよ。
生成した設計書に「どの列が並べ替えられるか」が載ってない。
自分で作ったのに気づいてなかった。
※ここらへんは既に次のバージョン(0.9.1~で修正済み)
3. 学習コストがかかったところ
| 定義に書けることと書けないことの線 | 最初は「認証も定義で書けるのでは」と思う。hatake where に聞けば済むが、聞くことを知らないと分からない
|
問い(ask)の印を正しく書く |
それっぽい名前を書くと落とされる。ask --kinds を引く癖がつくまで数回転ぶ |
| 助言をどこまで当てるか | 全部当てると定義が膨らむ。好みなので判断が要るが、基準は自分で持つしかない |
| 解析後のモデルの名前が YAML と違う |
key → keyField、type → kind。アプリ側を書くときに一度つまずく |
1つ目、道具があっても「その道具を呼ぶことを知らない」と意味がないという話で、
これは MCP でだいぶマシになりました(AI が自分で where を引くので)。
ただ人間が使う場合は残ります。
4つ目は完全にこっちの設計ミスです。YAML のキーと内部モデルのプロパティ名を
揃えなかったやつ。直せるかは……1.0 の約束で公開 API を凍らせたので、
しばらく直せません。 出す前に気づきたかった。🫠
4. 向いていない案件
| なぜ | |
|---|---|
| 画面そのものが要件(凝った UI・独自の操作感) | 定義で書けるのは「業務画面の形」。外れると全部プラグインになる |
| 1〜2画面で終わる | 枠組みの外を作る分が回収できない |
| 納品物が要らない(社内ツール) | いちばん効くところが空振りする |
| 既存画面への部分導入 | この案件では試してない(移行の手順は未検証) |
5. 試していないこと
紙に書いてないことは、やってないのと同じなので並べます。
| 親子明細(受注入力のような画面) | 2本目でやる |
| 帳票(PDF)・ダッシュボード | 同上 |
| ウィザード(ステップ入力) | 同上 |
| 既存システムからの移行 | 未検証 |
| 複数人での同時開発 | 1人で作った |
| 性能(データ量・同時接続) | 48件・10人想定。測ってない |
| Flutter 以外の画面(Vue / React) | 枠組み側が未対応 |
| ブラウザの種類 | Chrome だけ |
デモでは8種類の画面が出ますが、実案件で使ったのは3種類(crud / master / detail)
だけです。帳票とダッシュボードは「動く」までしか確認してません。
性能を測ってないのは正直マズいと思ってます。48件のマスタで速いのは当たり前なので。
それでも良かったところ
課題を先に置いたので、最後に。
| 決めていないことが先に出る |
ask が6件返した。手で作ると実装が終わってから出てくる種類の話 |
| 黙って効かない書き方を止められる | 一括の上限が「一度も効かない」設定を、動かす前に言われた |
| 設計書とエビデンスが腐らない | 定義から作り直せる |
| 画面とサーバがズレない | 同じ定義で検証する。2か所に書くと必ずどちらかが古くなる |
| 道具が嘘をつかない | 「読めなかった登録が2件あります」と言って黙って落とさない |
最後のやつ、作ってるときは地味だと思ってたんですが、使う側になると効きました。
一覧が穴あきのまま「問題なし」と言われるより、ずっと信用できる。
道具に「分からなかった」と言わせるのは、たぶん設計として正しい。
まとめ
1本作ってみた結論はこんな感じです。
- 工数は減る。 ただし減るのは書く作業だけで、要件を書くのと業務を判断するのは残る
- 1本目は回収できない。 枠組みの外を1,200行書く。効くのは2本目から
- テストは省けない。 道具が止められない穴が実際にあった
- 自作フレームワークは、自分で外から使わないとバグが出ない。 3件出た
あと、これが一番の収穫かもしれないんですが、
「AI に何をさせないか」を決めるほうが、何をさせるかより効いた。
前書きを AI に埋めさせない、問いに AI が答えない、外のものを定義に書かせない。
この3つを守っただけで、「それっぽいけど誰も決めてない設計」が1つも残らなかったので。
次にやること
-
2本目の案件(受注入力:親子明細・計算項目・ウィザード・帳票・ダッシュボード)
→ 工数の表を実測に置き換える - Vue 版(Renderer が本当に差し替えられるかの検証)
-
hatake shot(定義から画面の写真)とopenapiの app 対応 - 性能を測る
見てもらえると
| フレームワーク | https://github.com/ASIL-E-Hatake/hatake |
| 実案件サンプル | https://github.com/ASIL-E-Hatake/hatake-example |
| プレイグラウンド(インストール不要) | https://asil-e-hatake.github.io/hatake/demo/?playground=1 |
| 工数・課題のまとめ | apps/master-maintenance-prj/docs/まとめ/ |
相変わらず意見募集してます。今回は「使ってください」でもいいかな……と思いつつ、
やっぱり 「ここは絶対にヤバい」 が一番ほしいです。
※正式リリース(Ver 1.0)ではなく、実際に使うために公開したレベルなので、使えるレベルかどうかと言われるとまだまだ足りてないのかなという認識だし、不具合もまだまだ出てきそうな気はする
特に 「1,200行も外に書くならフレームワーク要らなくない?」 みたいなやつ。
※言い訳としてはDB周りだったり認証とかはフレームワークがいじらないところのため仕方ないんだよ。。。
否定的な意見のほうが、たぶんこの畠はよく育ちます。🌱
※優しくね