ふつーのプログラマです。主に企業内Webシステムの要件定義から保守まで何でもやってる、ふつーのプログラマです。

レインメーカー (23) 検証と検討

»

 2020 年2 月。
 新型コロナウィルスの影が、次第に日常に浸透し、ドラッグストアの棚からマスクが消えるという事態になっても、システム開発は続く。田代の妻は通勤時の感染を心配していたが、田代本人は右から左へと聞き流していた。ただでさえ問題が山積し、さらに増加しつつあるのだ。この上、得体の知れない風邪などを気にしている場合ではない。
 「つまりこういうことか」田代はこめかみを指で揉みながら言った。「単体テストでは発生していないエラーが、グルーの結合テストで発生して戻ってきたが、原因がわからない。再現もしない」
 「はい、そうなんですよお」布マスクで顔の下半分を隠したリオは、サラサラの髪の先端を指に巻き付けながら頷いた。「もー、あたしだと手に負えなくて。誰かにお任せしちゃってもいいですか?」
 いいわけねえだろ、お前の辞書には職責という言葉は載ってないのか、他のメンバーは全員お前の何倍もタスクを抱えてることぐらい知ってるだろうが。
 という心の中の叫びを押し殺し、田代は落ち着いた表情と声を作り上げた。
 「みんな手一杯なんだよな。もう少し調べてみてもらえないか」
 「でも......」リオはちらりと雨宮のデスクを見た。「今日中に戻せとグルーさんには言われてますし」
 「......」
 近頃、リオが雨宮からの影響を受けていることは田代も気付いていた。12 月のOptional で雨宮の意見が通ってしまったことを、田代は悔やんだ。あれ以来、リオと雨宮が話しこんでいる光景をよく見かけるようになった。田代より雨宮の方が頼りになる。そう考えるようになってしまったのだろうか。
 いっそのこと、リオが「使えないヤツ」であれば話が早かっただろうに、と田代は何度も考えた。だが「興味ない」と言い切るわりに、リオは妙に要領がいいところがあり、正しく指示を与えてやれば、それなりに結果を出してくる。指示を超えて独自の工夫を凝らすようなことは決してないが、他のメンバーのソースから必要な部分だけをコピー&ペーストして、仕様に合致したプログラムを組み上げる作業なら問題なくこなしてくれる。結局、業務システム構築の大部分は、そういった作業が占めるのだ。誰もがクリエイターである必要はない。
 それに数ヶ月、ミノカモ精機プロジェクトに携わってきたことで、リオの頭には、調達システムの仕組みや用語などがインプットされている。仕様変更などの指示が「曲げR の発注入力画面で、外R 指定したときの概算コスト算出ロジックが変更になったから、API 修正しておいて」だけで済むのは田代としても助かる。
 「ちょっと一緒に見てみようか」田代はリオに椅子を持ってきて隣に座るように指示した。「どのプロジェクトだっけ」
 ミノカモ精機の調達システムは、サブシステム毎にプロジェクトが分割している。それぞれのサブシステムは疎結合になっていて、間をつなぐのはAPI のみという建前になっているが、実際は、複数のサブシステムで、同じロジックが存在しているのが現状だ。たとえば消費税率の取得は、共通サブシステムにAPI が存在しているが、ほとんど利用されず、各サブシステム内にロジックが点在している。DRY 原則を無視した設計だが、実装を担当しているベンダーはジェイビーだけではなく、エースシステムもグルーも、実装面での指示はしない(というよりできない)ので、野放しになっている。
 リオが口にしたプロジェクトの最新版をGit から反映してから、田代はタスク表からリオが作業中のモジュールを見つけ、ソースを開いた。複数の部品の発注を行う際、各部品に設定されている最短納入期間から、発注の最大納期を表示するダイアログ用のロジックだ。それほど複雑な処理ではないので、リオに一任してある。
 「エラーって?」
 「あ、エラーっていうか、例外が出るわけじゃないんですけど」リオはモニタを見ながら言った。「日付が合わないらしいんです」
 田代は仕様書ファイルを開いた。グルーが作成したExcel ファイルだ。画面上で選択された複数の部品と、発注先メーカーの組み合わせで、それぞれの納期を取得し、ルールに則って最大納期を算出して返す、という単純なものだ。
 「グルーさんが合わないって言ってるのは、この返値の最大納期か。具体的にどう合わないって?」
 「それがはっきりしないんですよねえ」リオは首を傾げた。「予想の日付より前になったり、後になったりするらしくて。あ、もちろん合う場合もあるんですけど」
 「合わない場合のテストパターンをもらって、こっちで試してみた?」
 「はい。でもこっちでやると一致するんですよね」
 「メソッド名がajax で始まってるってことは、Ajax で呼び出す用か、これは」田代は仕様にざっと目を通した。「引数が部品ID とメーカーID の配列、納期......この最後の納期って何?」
 「画面で希望納期を入力できるので、それです」
 「ああ、あれか」
 詳細設計には、一部だが田代も加わっている。リオが言った機能は、直接設計したわけではないが、何かの関連で話に出たので記憶の片隅に残っていた。
 「つまり」田代は仕様の続きを読んだ。「各部品の標準納期、メーカーの最短納期、画面の希望納期の3 種類の日付を、なんやかんや判断して、最終的に最大納期を返すわけか。そう難しい話でもないね。面倒なのはnull の場合の判断だけか」
 部品マスタの標準納期と、メーカーの最短納期は、どちらもnull の場合があるし、画面の希望納期は省略可能だ。
 仕様を頭に入れると、田代はEclipse に切り替え、リオがコーディングしたソースを追いかけた。部品とメーカーは1:N になり得るので、メソッドに渡される引数は、"3:4,5"のような形式の文字列の配列となる。コロンの前が部品ID で、コロンの後がカンマ区切りのメーカーID だ。JSON で一つの文字列にして、受け取り側でMap にでも変換すればいいのに、と思ったが、それはこの際関係ない。配列をfor でループし、要素をコロンでsplit し、メーカーID はさらにカンマでsplit するだけだ。リオも正しくコーディングしている。
 背後に人の気配を感じ、田代は首をひねって後ろを見た。いつのまにか雨宮が立ってモニタを覗き込んでいる。田代の視線に気付くと、続けてください、とでも言うようにモニタを指した。田代は気にしないことにして、コードに意識を戻した。
 部品ID とメーカーID が得られた後は、それぞれのマスタから納期を取得する。田代はその部分を反転させてからリオに訊いた。
 「ここ、Dao からテーブルを読んでるわけだけど、レコードがない場合の処理はなくていいの?」
 「あー、特に仕様書には何も書いてなかったんで」
 仕様書になくてもnull に対するチェックはするものだ、と思ったが、口にするのはやめた。部品マスタもメーカーマスタもレコード自体を削除することは、運用上ほとんどないので、id でselect している以上、レコードが存在しない可能性はゼロに近い。システム管理者なら、コンソールからdelete 文を発行することはできるが、仮にレコードが取得できなかった場合、NullPointerException が発生するはずだ。
 部品マスタとメーカーマスタから、それぞれの納期が得られた後は、純粋にアルゴリズムの問題だ。田代は何重にもネストされたif とelse を読んでいった。若干、ムダな記述もあるが、見た限りでは正しく仕様をコードに落とし込めているようだ。
 「ユニットテストは?」
 「作ってます」
 ユニットテストは納品の義務がない。むしろ「不要なソースを入れるな」と言われているので、別のプロジェクトにまとめてある。田代はテスト用プロジェクトを開き、test パッケージの下を探した。
 「これか」田代はソースを開いた。「んーと、希望納期があるパターンとないパターン、部品マスタに納期が設定されているパターンとないパターン、メーカーマスタにある場合とない場合、か」
 「足りないですか?」
 「見たところ合ってるみたいだけど。これ、グルーさんが一致しないって言ってきたパターン?」
 「そうです」
 「実行してみるね」
 JUnit でユニットケースを実行してみると、全てのassert が正常に完了した。
 「問題ないな」田代は腕を組むと、オフィスの中を見回した。「滝沢くん、ちょっと来て」
 椅子に沈みこむようにコーディングをしていた滝沢は、億劫そうに身体を起こすと、田代の元にやってきた。
 「ちょっとこのテストケース見てみてくれるか」
 滝沢は田代とリオを交互に見た後、ユニットテストのソース名を口の中で反芻すると、頷いて自席に戻っていった。すぐにいくつかキーを叩いた後、モニタを見つめて言った。
 「特に問題は見つかりませんけど」
 田代が礼を言ってモニタに目を戻したとき、不意に雨宮が訊いた。
 「どうして滝沢さんに確認してもらったんですか」
 「一人が見ただけでは、見落しがあるかもしれないからですよ」田代は答えた。「それが何か?」
 「いえ」雨宮は小さく手を振った。「私は何分、実装経験がないものですから。失礼しました。それでグルー側はこの件について、どの程度の重要性と緊急性があると言っているんでしょうか」
 その問いはリオに向けられていた。リオは肩をすくめた。
 「あっちでも再現するパターンはわかってなくて、発生しないときは全然発生しないと言っていました。っていうか、発生しないときの方が多いみたいな口ぶりでしたねー。ただ、解消しないと結合テストが完了にできないってことで」
 「このポップアップの日付は、単なる目安の表示ですね」雨宮は指摘した。「この日付が発注書に出力される、ということもなかったはずです」
 「そうですが」雨宮の発言の意図がわからず、田代は困惑しながら訊いた。「それが何か?」
 「こういうのはどうでしょう。この件はクローズということにしてもらうよう、私からグルーに連絡しておきます」
 「無視するってことですか」
 「無視はしません。操作マニュアルか、画面のどこかにでも最大納期は参考値です、とか書いておけばいいんです」
 マジかよ。田代は呆気にとられた。
 「とにかく今はオンスケに戻すのが何よりも優先されるんです。そんな再現性の低い不具合にリソースを割くのは、時間のムダです。もしかすると本番稼働した後は、一度も発生しないかもしれないんですから」
 「毎日、発生するかもしれませんよ」
 「そんな仮定の話をされても」雨宮は笑うとリオを見た。「それに、もうすぐ17 時です。木内さんは、今日、予定があると聞いています。そろそろ切り上げるべきではないですか」
 「あ、いえ、あたしなら」リオが急いで言った。「そんなたいした予定でもないので......」
 「そういうことで遠慮してはいけない、と言ったでしょう」優しい声で雨宮は諭した。「定時で退社するのは当然の権利です」
 「ええ、まあ、でもあたしの担当ですから......」
 「わかりました」田代は強引に割り込んだ。「17 時まであと20 分です。それまでに原因がわからなければ、雨宮案で行くことにします」
 それでどうか、と訊くと、雨宮は眉をひそめた。
 「どうですかね。20 分で何かわかるとは思えませんが......」
 「俺の方でも見てみましょうか」成り行きを見守っていた迫田が申し出た。「気分転換に」
 「ぼくも手伝いますよ」西久保も手を挙げた。「同期ですから」
 滝沢と東浦も、それぞれ協力を申し出た。それを見た雨宮は顔をしかめた。
 「みなさん、そんなに余裕があるわけではないと思うんですが」
 「こういう不明点を放置しておくと」田代は言った。「いつかどこかで、思わぬ問題に発展することがあるんですよ。これは私の実装経験によるものです」
 「そうですか」雨宮は渋々頷いた。「そこまで仰るなら続けてください。ただし17 時になったら、これは私の方で巻き取らせていただきますので」
 田代はソースに目を戻した。単体テストでは正常で、結合テストでは異常値が出る。原因は何なのだろう。
 「リオちゃん」迫田が苦笑しながら言った。「もうちょっとコメント入れようよ」
 「インデントももう少し整えた方がいいですね」東浦も指摘した。「読みづらいです」
 「すいません......」
 「logger 入れておけばよかったのにな」西久保が言った。「そうすれば、どこで最大納期を出したのかわかる」
 「ごめんってば。今度、何かおごるから」
 「せめて」滝沢がボソボソと言った。「引数とreturn の直前ぐらいにはログが欲しかったね」
 「......すいません」
 「順に追ってみる」田代は全員に向かって言った。「おかしいところがあったら指摘してくれ。まず引数を評価している。最初の引数を部品ID とメーカーID に分解している。ここが違っていて、全然別の部品とかメーカーを取得しているってことはないか?」
 メンバーたちは一斉にソースに目を凝らし、次々に首を横に振った。
 「ないですね」
 「部品IDだけ、メーカーID だけのパターンでも、split した後に要素数が2 になっているかどうかをチェックしていますから」
 「あえて言うなら」滝沢が付け加えた。「分解したID をそのままint に変換してますが、数字以外が入っていた場合、例外になります」
 「それはありえないかな」東浦が言った。「画面でID を手打ちするわけじゃない。選択画面から選択するわけだから」
 「全角半角も同じ理由でありえないか」
 「よし、最初の引数はよさそうだ」田代はまとめた。「部品ID とメーカーID は正しく分解されている、としよう。次は希望納期か」
 「これってフロント側はdatePicker ですよね。手入力じゃなくて」
 「厳密に言えば手入力もできるけど、まあ、やらないよな」
 「やったとしても、共通ユーティリティの日付パーサでパースされるから、正しい日付でなければ、例外になるね」
 「あと10 分ですよ」時計を見ていた雨宮が宣言したが、誰もそちらを見ようとはしなかった。
 「あれかな、SimpleDateFormat で日付を厳密に判断するかどうかってやつ」
 「setLenient。あれはいまだにtrue かfalse か迷うんだよね」
 「それが問題になるのって、2/29 とかの境界値の場合だけど、このテストデータにはそういうのがない。それでも結果が違うんだから、それじゃないね」
 「そっか......」
 「リオちゃん、付いてきてる?」
 「あー、いえ、すいません」
 「引数が正しく評価されてるとしたら、DB かな」
 「主キーでの取得しかしていないから、間違いようがないでしょう、ここは」
 「null になる可能性は、まあないだろうしね」
 「となると、後は、この大量のif とelse の中の何かがおかしいってことになるのかな」
 「さっきカバレッジかけてみたけど、全部網羅できてましたよ」
 「うーん、わからんなあ」
 全員が沈黙した。
 「あと 5分です」勝ち誇ったような雨宮の声が響いた。
 「別の視点から見てみよう」田代は焦りを抑えながら言った。「単体テストと結合テストの違いはなんだ」
 「環境ですね」
 「具体的には」
 「単体テストはJUnit。結合テストは実際にブラウザからですね」
 「でもAjax で渡す引数と、ユニットテストから渡す引数に違いはない」
 「日本語のエンコードってこともないし」
 「でも何かが違う。そこにきっとヒントがある」
 「テスターの人数とか」
 「確か20 人ぐらいでやってるんだよな、あ」
 「あ」
 ほぼ同時に、全員が答えに行き着いた。
 「マルチスレッド」
 「え、まさか」東浦が上ずった声をあげた。「SimpleDateFormat をstatic 宣言してるんじゃ......」
 「日付のパースは共通ユーティリティだ。ソースってもらってたっけ?」
 「ないけどjar ファイルには含まれてるはず」
 「デバッグモードで止めてみればわかる」
 全員がPC に向かって競うようにキーを叩いた。文字列で渡される日付をパースする直前にブレークポイントを設定し、ユニットテストをデバッグモードで実行する。中断したら、共通ユーティリティの変数を選択してF3 キーでソースを参照する。
 「やっぱり」最初に確認を終えた迫田が歓声を挙げた。「これだ。Static になってる」
 「だからか。20 人が同時に同じテストをしてるんだ。このユーティリティを使うシーンも多いはず。共通ユーティリティなんだから」
 「で、たまたまタイミングが合うと、おかしな日付が返ってくる場合がある」
 すでに5 分は経過していたが、雨宮はタイムアウトを宣言しようとしなかった。
 「つまり、どういうことでしょう」
 「つまりですね」田代はため息をついた。「提供されている共通ユーティリティに問題があるってことです。木内さんの作ったロジックにではなく」
 「そんなことが......」
 「すぐ確認してもらえますか」田代は少し厳しい声で要請した。「確認できれば、木内さんも早く退社できるので」
 雨宮は気圧されたように頷くと、スマートフォンを出して通話を開始した。その姿を横目で見ながら、リオが深々と頭を下げた。
 「みなさん、ありがとうございました」
 「もう原因はわかったんだ」西久保が言った。「木内の責任じゃないよ。用事があるなら帰っていいんじゃないか」
 「大丈夫」リオは明るく笑った。「今日は予定をキャンセルして残業する」
 「珍しいこともあるもんだな。どういう風の吹き回し?」
 「ちょっとだけ、プログラミングの面白さがわかったからかな。まあ、いいじゃん」
 田代は満足感に包まれながら自席に戻っていくリオを眺めた。これでリオの態度も少しは変わるかもしれない。その思いにとらわれていた田代は、雨宮の厳しい視線に気付かなかった。

(続)

 この物語はフィクションです。実在する団体名、個人とは一切関係ありません。また、特定の技術や製品の優位性などを主張するものではありません。

Comment(6)

コメント

yupika

ここにきてリオが悪いやつじゃないの、逆に悲しすぎる;;
でもコピペもセンスだからコピペで組めるってことはそこそこ適正あるんだよな
そういうひとがこういうタイミングで論理的な考えを実行に移せるとわかるとプログラムってめっちゃ面白くなるから
こういうタイプが何かの拍子に目覚めるのはあるあるというか、納得はかなりいく…。
それに比べて雨宮…

匿名D

せっかく手懐けたのが尻尾をふって元気よく向こうに戻っていっちゃったら、
そりゃ気に食わないだろうなあ。
手懐けようとした動機そのものが不純だけど。


自分はフェミニズムを押し通すために進行をないがしろにするくせに、
リオ嬢の助っ人にスタッフが名乗りを上げるのにケチをつけるなんて、
笑止もいいところ。
誰しも自分の居場所を確保するのに必死になるものだけど、
優先順位を間違ったり、逆恨みしちゃダメだよね。
もしかして田代氏じゃなくて、リオ嬢に矛先が向くのかしら。
そっちのほうが始末が悪そう。

ななし~

非同期処理のstaticのやらかし、胃が痛いです...(T_T)

匿名

前々回を読み返して気付いたのですが、
雨宮さんってエースシステムからの出向か…

匿名

みんなでワチャワチャ言いながら確認して、ほぼ同時に正解に辿り着く瞬間って気持ちいいよね。

匿名

ここで、staticおじさん降臨?

コメントを投稿する