第二話「仕様書が読めない」
第二話「仕様書が読めない」
四月四日、木曜日。
入社三日目の朝、悠人は電車の中でスマートフォンを開き、昨夜読んでいたページを見返した。「システム開発の流れ:要件定義から保守まで」。矢印でつながれた箱がいくつか並んでいる図があって、「要件定義」「基本設計」「詳細設計」「実装」「テスト」「リリース」「保守」という言葉が書いてあった。
昨夜はこれを三回読んだ。読むたびに「わかった」と思ったが、今朝また読むと「わかったつもりだっただけかもしれない」という気持ちになる。概念は頭に入る。でもそれが実際の仕事の中でどう動いているかが、まだ見えない。地図を持っているが、地図の中のどこに自分が立っているのかわからない状態だ。
初日と二日目は研修だった。Pythonの基礎と、バージョン管理ツールの「Git」というものの説明。Gitは「ファイルの変更履歴を記録して、チームで共有する仕組み」らしかった。コマンドを打つたびにエラーが出て、隣の席の人に一度だけ聞いた。「ブランチって何ですか」。「木の枝みたいなもん」と言われた。意味がわかったような、わからないような返答だった。
今日から「OJT」が始まる、と昨日の研修終わりに人事担当者から告げられた。On the Job Training——実際の業務の中で学ぶ、ということらしい。配属先は「第三開発部」。担当はまだ知らない。
品川のビルに着いて、エレベームターで七階へ上がった。第三開発部は、研修会場があった六階より一つ上のフロアだった。
ドアを開けた瞬間、空気が変わった。
研修室の清潔な静けさとは違う、生きた職場の空気だった。キーボードの音が重なり合い、電話の声が遠くで聞こえ、モニターが何台も並んでいる。壁際にホワイトボードがあって、付箋がびっしり貼られている。赤い付箋と黄色い付箋が混在していた。赤は緊急、黄色は通常案件かもしれないと思ったが、確認する間もなかった。誰かが書いたらしい矢印と数字が、消されたり書き直されたりした跡が残っていた。ホワイトボードの端に「4/3 橘 #確認待ち」という文字があって、昨日の日付だった。
「桐島くん?」
声をかけてきたのは、三十代半ばくらいの男性だった。スーツではなくチェックのシャツにチノパン。眼鏡をかけていて、髪が少し長い。手にコーヒーのマグカップを持っている。
「はい、桐島悠人です。今日からお世話になります」
「真鍋です。このチームのPMをやってる。よろしく」
真鍋晃。悠人はその名前を頭に刻んだ。
「とりあえず席を案内するよ。荷物置いたら少し話しましょう」
案内された席は、窓から二列目だった。モニターが一台、キーボードとマウス、引き出し付きのデスク。引き出しを開けると空っぽだった。自分のものが何もない空間に、自分がこれから座り続けるのだという実感が、じわりと来た。隣の席には宮崎亜里沙のネームプレートがあった。向かいの席は空席だった。右斜め前の席はすでに主がいて、コードを打ちながら小声で独り言を言っている。
―――
荷物を置いて五分後、悠人は真鍋の席の横に椅子を引いて座った。真鍋はコーヒーを一口飲んでから、モニターを悠人の方に少し向けた。
「今うちのチームが抱えてる案件を説明するね。三つある」
画面にスプレッドシートが開いた。案件名、クライアント名、ステータス、担当者名が並んでいる。
「一個目が『橘物産の在庫管理システム改修』。これが今一番でかい。先月まで炎上してて、ようやく落ち着いたところ。二個目が新規の見積もり中の案件。三個目が保守契約の定期対応」
「炎上、というのは」
「納期に間に合わない、品質が足りない、客先との認識がずれてる、っていう状態が重なること。橘の案件はその三つが同時に起きた」
悠人はメモ帳を取り出してメモした。「炎上=納期・品質・認識のずれが重なる」。
「桐島くんには、まず橘の案件の仕様書を読んでもらいたい」
「仕様書、というのは」
「システムが何をするべきか、どう動くべきかを書いた文書。今回の案件で言えば、在庫管理の画面がどんな機能を持つか、データがどう流れるか、エラーが起きたときどうするか、そういうことが全部書いてある」
「読んで、何をするんですか」
「不具合の洗い出し。今回の炎上の原因の一つが、仕様書と実際のシステムの動きが食い違ってたことなんだよね。どこがずれてるか、仕様書を読みながらリストアップしてほしい」
悠人は一瞬、自分が正しく聞き取れたか確認したくなった。
「仕様書と……システムの、どこが違うかを、探すんですか」
「そう。難しく考えなくていい。書いてあることと動いてることが合ってるかどうか、一個一個確認するだけ。桐島くん、文学部でしょ。文章を正確に読む力は俺らより絶対ある。まずそこを使ってほしい」
「文章を正確に読む力」。その言葉を、悠人はしばらく頭の中で転がした。入社してから初めて、自分の出身が武器として言及された気がした。
「やってみます」
「行き詰まったら声かけて。でも最初の一時間は一人でやってみて」
真鍋はコーヒーを飲み干して、立ち上がりかけた。悠人は一つだけ聞いた。
「あの、一点確認させてください。この仕様書、最新版はv2.3ですか」
「そう。v2.3が現行版」
「過去のバージョンは参照できますか」
「できるよ。同じフォルダにv1.0からある。何で?」
「矛盾を見つけたとき、それが最初から仕様書に書かれていたのか、改訂の途中で生まれたのか、わかった方がいいかと思って」
真鍋は少し間を置いた。
「……なるほど。改訂履歴を追えば、どの段階で食い違いが生まれたかわかるか」
「はい。そこまで辿れるかはわかりませんが、参考にはなるかと」
「やってみて」
そう言って真鍋はコーヒーを飲み干した。
―――
悠人はデスクに戻り、真鍋から共有されたフォルダを開いた。
「橘物産_在庫管理システム_仕様書_v2.3.xlsx」というファイルがあった。Excelファイルだ。開いた。
シートが十四枚あった。「表紙」「改訂履歴」「システム概要」「機能一覧」「画面設計」「データベース設計」「API仕様」「エラーコード一覧」——タブが横に並んでいる。合計で何ページあるか数えると、印刷換算でおよそ八十ページ分あった。
最初の三秒で、何かがおかしいと気づいた。
十秒後、確信した。
日本語で書いてある。それは間違いない。一文一文、単語として読める。でも、意味がわからない。
「本機能は、ロット番号に紐づく在庫マスタの参照時、トランザクションの整合性を担保するため、楽観的ロックによる排他制御を実装する。更新競合が発生した場合、リトライ処理を最大三回実行し、三回目の失敗時にはロールバックしてエラーコード『E-4023』を返す」
「ロット番号」「在庫マスタ」「トランザクション」「楽観的ロック」「排他制御」「更新競合」「リトライ処理」「ロールバック」「エラーコード」。
九つの単語のうち、意味を知っているのはゼロだった。
悠人はスマートフォームを机の上に置いた。一つ一つ調べるしかない。
「トランザクション データベース 意味」と検索した。「データベースに対する一連の処理をひとまとまりとして扱う概念。全て成功するか、全て失敗するかのどちらかになる」という説明が出てきた。なるほど、と思った。でも「なるほど」は、読んだ直後の感覚で、五分後には揮発してしまう種類の「なるほど」かもしれない。
「楽観的ロック」を調べた。「複数のユーザーが同じデータを同時に更新しようとしたとき、衝突を事前に防ぐのではなく、更新時に衝突を検知して対処する方式」。
「悲観的ロック」という対義語もあるらしく、そちらも調べたら余計に混乱した。
「排他制御」を調べた。「複数のプロセスが同じリソースに同時アクセスすることで起こる問題を防ぐ仕組み」。
「楽観的ロック」と「排他制御」の関係がよくわからなくて、さらに調べた。十分経っていた。
悠人は一度、手を止めた。
このペースでは、仕様書の一行目を理解するだけで一日終わる。それでいいのか。いや、それではだめだ。でもわからないまま読み進めても、何も見つけられない。
どうするべきか。
悠人はメモ帳に、今わからなかった単語を全部書き出した。九つ。それから仕様書の次の行を読んだ。また知らない単語が出てきた。書き出した。また次の行。また知らない単語。
三十分後、メモ帳には知らない単語が三十一個並んでいた。
―――
「真鍋さん」と悠人は声をかけた。
真鍋は電話中だったが、指で「ちょっと待って」のジェスチャーをした。悠人は立って待った。二分後、電話が終わった。
「どうした」
「仕様書を読んでいるんですが……技術用語がほとんど意味がわからなくて」
悠人はメモ帳を差し出した。三十一個の単語リスト。
真鍋はそれを見て、少し眉を上げた。怒っているのか呆れているのか、表情からは読み取れなかった。
「全部調べた?」
「上から十個くらいは調べました。でも調べても、次の行でまた知らない単語が出てきて、それも調べてたらきりがなくて」
「うん」
「一語一語調べながら読むのか、それとも知らない単語は飛ばして全体を読むのか、どっちがいいか迷って……」
真鍋はコーヒーを一口飲んだ。考えているようだった。
「正直に言うと、その仕様書は熟練のエンジニアが読んでもわかりにくい書き方してる。前任が書いたやつで、俺も何度か読み直してる」
悠人は少し肩の力が抜けた。
「じゃあ、こうしよう。今日は全部読もうとしなくていい。仕様書の中に、日本語として変だと思う部分、矛盾してると思う部分だけをピックアップしてみて」
「技術的な意味がわからなくても、ですか」
「そう。『この文章、前の段落と言ってること矛盾してない?』とか、『この条件、どっちが正しいの?』みたいな違和感でいい。技術の話は後で俺が補足する」
悠人は少し考えた。
「それは……できそうです」
「やってみて。午後一で確認する」
―――
悠人はデスクに戻り、仕様書をもう一度開いた。
今度は違う目で読んだ。「意味を理解しよう」とするのをやめた。代わりに「文章として変なところ」を探した。
国文学科で四年間やってきたのは、まさにそれだった。文章を構造として読む。主語と述語の関係、指示語が何を指しているか、段落と段落の論理的なつながり。テクノロジーの知識はなくても、文章の読み方は知っている。
読み始めて十五分後、最初の違和感を見つけた。
仕様書の第三章、「在庫数量の更新処理」のセクション。
「3-1:出荷処理時、在庫数量から出荷数量を減算する。減算後の数量がマイナスになる場合、エラーコード『E-2001』を返し処理を中断する」
そのすぐ下、三行後に。
「3-4:緊急出荷フラグが立っている場合、在庫数量がゼロ以下であっても出荷処理を続行する」
悠人は鉛筆で両方の行に下線を引いた。
3-1は「マイナスになる場合は中断する」と言っている。3-4は「ゼロ以下でも続行する」と言っている。これは……矛盾している。どちらが正しいのか。「緊急出荷フラグ」という条件があるから3-4が例外なのかもしれないが、3-1にはその例外が書かれていない。
悠人はメモ帳に書いた。
「3-1と3-4が矛盾している可能性。緊急出荷フラグがある場合のマイナス在庫の扱いが不明確」。
続きを読んだ。第四章、「在庫マスタの管理」。
「4-2:商品コードは半角英数字八桁で構成される」
少し後に。
「4-7:商品コードの入力欄は最大十二文字まで入力可能とする」
八桁と十二文字。これも、どちらが正しいのか。あるいは八桁を超えるコードも存在するのか。テキストボックスが十二文字まで受け付けるなら、八桁を超えた入力はどう扱われるのか。書いていない。
メモ帳に書いた。「4-2は八桁と規定しているが4-7は十二文字まで許容。矛盾または仕様の抜けの可能性」。
読む速度が上がってきた。技術的な単語は依然として意味が分からないが、それを飛ばして「文章の整合性」だけを追いかけると、むしろよく見える。
第五章。
「5-3:検索結果の表示件数は最大五十件とし、それ以上はページングで対応する」
第七章。
「7-1:検索機能は全件検索を基本とし、ページングは実装しない」
五十件とページング、全件検索でページングなし。これは第五章と第七章が直接矛盾している。
メモ帳が埋まっていった。
―――
昼休みになった。悠人は自席でコンビニのサンドイッチを食べながら、メモ帳を見返した。
午前中で見つけた矛盾・不整合・不明確な記述は、九箇所だった。
技術的な意味はわからなくても、文章の骨格は読める。それを確かめながら読み進めた午前中だったが、一方で「これで本当に役に立っているのか」という不安もあった。自分が見つけた矛盾が、すでに把握済みのものばかりだったとしたら。あるいは技術的には矛盾していないのに、悠人が知識不足で矛盾に見えているだけだったとしたら。
どちらの可能性も、午前中ずっと頭の片隅にあった。
隣の席のエンジニア——三十代くらいの女性で、朝に「よろしく」とだけ言って以来ずっとモニターに向かっている——が、ふと画面から目を上げた。
「新人くん、仕様書読んでたの?」
「はい。矛盾しているところを探してました」
「橘の?」
「そうです。九箇所、見つけました」
女性の眉が少し上がった。
「九箇所?」
「多すぎましたか」
「……いや。ちょっと見せて」
悠人はメモ帳を差し出した。女性はそれを読んだ。読みながら何度か小さく頷いた。
「これ……3-1と3-4の矛盾、先月の炎上の原因の一個だよ」
「え」
「緊急出荷のときにマイナス在庫になって、それが後工程のシステムに影響して、一週間データがおかしくなった。仕様書の矛盾を誰も指摘しないまま実装したから」
悠人は静かに息を飲んだ。
「4-2と4-7の商品コードの件も、前から気になってたやつ。あと7-1のページングも」
「他のは……」
「3つは知らなかった。というか多分、誰も気づいてなかった」
女性は名前を言っていなかった。悠人が「あの、お名前を聞いていいですか」と聞くと、「宮崎」と言った。「宮崎亜里沙。入社五年目」。
「宮崎さんは、この仕様書、前から読んでたんですか」
「何十回も。でも技術的なところばかり見てたから、文章レベルの矛盾は……正直、見落としてた部分もある」
宮崎は少し間を置いて、言葉を選ぶように続けた。
「あなた、文系でしょ」
「はい、国文学科です」
「なるほどね」
それだけ言って、宮崎はモニターに向き直った。
―――
午後一時、真鍋に呼ばれた。
悠人はメモ帳を持って真鍋の席に行った。真鍋はメモ帳を受け取り、一項目ずつ読んだ。読む速度が途中から少し落ちた。
「九箇所か」
「午前中で見つけたのがこれだけで、午後もう少し読めばもっと出るかもしれません。あと、改訂履歴も少し見ました」
「何かわかった?」
「3-1と3-4の矛盾は、v2.0への改訂のタイミングで生まれているようでした。v1.xの頃はどちらも書かれていなくて、v2.0で3-4が追加されたとき、3-1との整合性が確認されなかったみたいで」
真鍋はメモ帳から目を上げた。
「それ、改訂履歴から読んだの?」
「はい。シート名が『改訂履歴』というのがあって、いつ、どこを、なぜ変えたかが書いてありました。ただ理由の欄が空白になっているところが多くて、推測の部分もあります」
真鍋はしばらく考えた。
「3-4が追加された理由、書いてなかった?」
「『顧客要望に基づき追加』とだけ書いてありました」
「そうか。あの時期、橘の担当者が変わって、新しい担当者が緊急出荷の要件を後から追加してきたんだ。それに対応して3-4を足したとき、3-1を修正するのを忘れたってことか」
真鍋が独り言のように言った言葉を、悠人は聞いていた。改訂履歴の日付と、炎上の時期が近いかどうか、後で確認しようと頭の片隅に置いた。
「3-1と3-4の件、気づいてたか」
「はい、最初に見つけました。これが原因の一部だったと、宮崎さんから聞きました」
「宮崎が言ったのか」
真鍋は少し考えるような顔をした。
「他の六箇所、うちのチームで把握してたのは三箇所だ。残り三箇所は……正直、新しい指摘だ」
悠人は何と言えばいいかわからず、「そうですか」とだけ言った。
「どうやって見つけた」
「技術用語の意味はほとんどわからないので、意味を理解しようとするのをやめて、文章として矛盾しているところだけを探しました。前の段落と言ってることが違う、とか、同じことを別の章で違う数字で書いてる、とか」
真鍋はしばらく無言だった。コーヒーカップを持ち上げて、中身が空なのに気づいてまた置いた。
「それは、俺には教えてもらわないとできない読み方だ」
悠人は少し戸惑った。謙遜なのか、本心なのか。
「いえ、技術の話は何もわかってないので……」
「わかってない人間が九箇所見つけた。わかってるつもりの人間が三箇所しか把握してなかった。それが今日の結果だ」
真鍋はメモ帳を悠人に返した。
「午後、このリストをExcelにまとめてくれるか。箇所、内容、矛盾の種類——仕様の抜けか、記述の矛盾か——と、もしわかれば改訂履歴との関連も。それだけ整理してくれれば十分」
「わかりました」
「できたら宮崎に確認してもらって。技術的な補足が必要なところは彼女が足してくれる」
―――
悠人がExcelを開いて入力し始めると、十分後に斜め前の席から声がかかった。
「桐島くん」
振り向くと、香坂凛がいた。悠人は少し驚いた。香坂も同じチームに配属されていたのか、と思ったが、よく見ると彼女のデスクは部屋の反対側にある。
「何してんの」
「仕様書の矛盾をまとめてます」
「橘の?」
「はい」
香坂は少し近づいてきて、Excelの画面を見た。
「何箇所?」
「今のところ九箇所。まだ読み切ってないので、増えるかもしれません」
「ふうん」
香坂はしばらく画面を見ていた。
「3-1と3-4の件、入ってる?」
「入ってます」
「7-1のページングは?」
「入ってます」
「4-2と4-7の商品コードは?」
「入ってます」
香坂は少し黙った。
「あと一個、5-9に仕様の抜けがある。在庫ゼロの商品を発注点管理の対象から除外する条件が書いてない。気づいてた?」
「……5-9は、まだそこまで読めていませんでした」
悠人はExcelに一行追加した。
「ありがとうございます。5-9、どういう問題ですか」
「在庫ゼロの商品は普通、自動発注の対象から外すべきなんだよ。欠品してる商品と販売終了した商品の区別をしないまま発注処理を走らせると、販売終了品を大量発注することになる。仕様書にその区別の条件が書かれてない」
悠人はメモした。「5-9:在庫ゼロ商品の発注点管理における除外条件の未記載。欠品と販売終了の区別が不明確」。
「それ、システム動かして気づいたんですか」
「仕様書読んで気づいた。実装する前に潰せる問題は潰す方がいい」
香坂はそれだけ言って、自分の席に戻っていった。
―――
十七時、悠人はExcelを真鍋に送った。最終的に十項目になっていた。九箇所の自分の分析と、香坂に指摘してもらった5-9の件。
メールを送信した直後に、真鍋から内線がかかってきた。
「今日のまとめ、受け取った」
「はい」
「今日の仕事、よかったよ」
それだけで電話が切れた。
悠人は受話器を置いて、しばらくモニターを見つめた。「よかったよ」。四文字。でもその四文字が、今日一日の疲れをすっと溶かした。
帰り支度をしながら、悠人は今日一日を振り返った。
技術の知識は、何も増えていない。「トランザクション」の意味は、まだ曖昧だ。「楽観的ロック」は明日もう一度調べないと忘れる。コードは一行も書いていない。
でも今日わかったことがある。仕様書を読む、ということは技術用語を全部理解することではなく、文章の整合性を確かめることでもある。そして自分には、その作業をする力がある。
それがどのくらい価値のある力なのかは、まだわからない。真鍋に「よかったよ」と言われたが、それが本当の意味での評価なのか、新人への気遣いなのか、区別がつかない。でも少なくとも今日、誰も把握していなかった矛盾を自分が見つけた。それは事実だ。
今日把握していなかった矛盾の原因が何年も前の炎上につながっていた、という話を宮崎から聞いたとき、悠人の中で何かが少し動いた。文章の矛盾を見つけることが、システムの障害を防ぐことに直接つながる。そういう連鎖が、この仕事にはある。
エレベーターを降りて、ビルを出ると夜の品川が広がっていた。昨日より少し遅い、十八時半。空はもう暗くなりかけていた。
スマートフォームを開いたら、知らない番号からメッセームジが来ていた。
「香坂凛です。5-9の件、追加されてましたね。明日、橘のシステムを実際に動かしてみますか。仕様書と実動作を対照させる作業、二人でやった方が早いと思うので」
悠人はしばらく画面を見つめた。
香坂凛から、自分に連絡が来ている。一緒にやろうと言っている。
第一話の昼、「わからなかったら聞いていいよ、でも自分で試してから」と言われた。それ以来、香坂から話しかけてきたのは今日の午後が初めてだった。今日の仕事を見ていて、何かを判断したのだろうか。何を、どう判断したのか。聞いてもいい気はしたが、それは明日でいい気もした。
「ぜひお願いします」と返信した。既読がついた。返事はなかった。でも、それで十分だった。
改札に向かいながら、悠人はメモアプリを開いた。
今日調べた技術用語のリストを見返す。トランザクション。楽観的ロック。排他制御。ロールバック。発注点管理。
全部、まだ完全にはわかっていない。
でも今日、仕様書の矛盾を十箇所見つけた。そのうち何箇所かは、誰も気づいていなかった。
コードは嘘をつかない。仕様書も、きちんと読めば嘘をつかない。書いてある言葉が互いに矛盾するとき、それは誰かが何かを見落としたサインだ。
そのサインを読む力は、たぶん自分にある。
山手線のドアが閉まった。車窓に夜の景色が流れ始めた。悠人は目を閉じずに、窓の外をじっと見ていた。
―――
【次回予告】
第三話「初めてのバグ」
翌日、香坂と二人で橘のシステムを動かし始めてすぐ、想定外の動作を見つけた。「ある条件のときだけ、在庫数がマイナスになる」。仕様書には書かれていない挙動。原因を探るためにコードを開く。文字と記号が画面いっぱいに広がっている。香坂は「ここから読めばいい」と一箇所を指さした。悠人には、そこに何が書いてあるのかさえわからなかった。




