見出し画像

そもそも「プログラムのバグ」ってなんだろう?

はい皆たそこんにちは。
ゼバ会です。

本日は、バグを出さないシステムを作るうえでの根本的な話をします。
むしろ最初にこれやんなかったらバグゼロは無理。
最初にやってないなら今すぐやれ。
そんくらい大事なこと。
皆さんにとってバグってなんでしょう? ってこと。

お客さんにとって、バグとは「コンピューターが自分に都合の悪い動きをすること」の総称です。
バグでイライラしてるお客さんに「それはバグではなく仕様です」とか言っても火に油を注ぐだけ。
お客さんは自分がバグだと感じたものがバグなのです。

では、開発チームにとっても、それがバグってことでいいのでしょうか?
いいわけないですね。

とりわけ新人だらけのチームでは、バグとは「システムから出てくるエラー」と定義されていることが多いように思います。
ベテランエンジニアにとっては「プログラムが自分が意図したとおりに動かないこと」でしょうか。
あるいは、営業チーム優位でエンジニアの発言権があまりないプロジェクトでは、「運用が回らなるような場合のこと」と定義されているケースもあります。

そう。
つまりバグの定義は社会的立場によって変わるのです。

世の中の「バグゼロは無理」と言ってる人達は、そのバグが「誰の目から見たバグか」を意識してない傾向があり、自分がバグだと信じているものがバグである、という定義で考えていることが多いです。
とりわけそういう人が上に立っているチームでは、時間経過とともに「誰か1人でもバグと称した現象をバグと呼ぶ」という運用に変わってきます。
で、そのバグを出した責任が下にどんどん押し付けられていき、最終的に新人が「数年先の未来を予測した完璧なシステムを組めなかった責任」なんてものを取らされるハメになるわけですよ。

んでしまいにゃ、下への重圧が重すぎることに気づいた誰かが、ある日「犯人探しは止めよう」とか言い出して?
バグ管理システムに報告されたバグの大部分が責任者不明になったりして?
たまたま貧乏くじを引いた人が責任とったりして?
誰の手にも負えない一番ヤバい闇バグとかはしまいにゃ放置?

どうすんのよ、それ。
自分のチームがそんなクソみたいな場所になってしまう前に、バグをちゃんと定義しましょう。
もちろん社会的に不変な定義はさすがにないですが、個人的におすすめなのはこの4つで分類する方法。

1. システムバグ
2. サービスフローバグ
3. アーキテクチャーバグ
4. アフォーダンスバグ

まぁ、これでなくても全然いいんですが、とにかく「分類」をしてください! 分類を!
要はバグが漏れなくダブりなく、いわゆるMECEに分類されてりゃなんでもいいんだから、十把一絡げに「全部バグ」とか絶対ダメ!!
ガキの使いじゃないんだから、仕事しよ?

とりあえず上記4つがそれぞれどういうものか、詳しく解説していきます。

1.システムバグ

いわゆる、プログラム言語やOSがエラーメッセージを出すバグ、あるいは見た目やデータなどが意図せず崩れることです。
要は顧客に見られるとプログラマーとして恥ずかしいもの。
ここ最近はヌルポレベルのポカミスを客に見せちゃうエンジニアはさすがに少なくなったけど、連想配列に対する key undefined が本番で発生しているくらいはまだまだ多いようです。

これは製造を直接担当したプログラマーの責任範囲です。

もしくはこのシステムバグは、「メソッドの不正値チェックが完璧なら理論上発生しないもの」という定義でもOKです。
だってそうでしょ?
システムバグは必ずメソッドの造りが原因で出るんだから、全てのメソッドがあらゆる入力に対して堅牢だったら絶対出ないんですよ。

当会では、まず真っ先にこれをゼロにすることを強くおすすめします。
この種類のバグは社員教育とコードルールで確実に防げるからです。

2.サービスフローバグ

マニュアルで定められた通りの操作ができない、という系統のバグ。
チームリーダーが「お客さんがどんな操作をしてもいいようにしろ」とか、「分かんないからとりあえず作って?」とか部下にゆっちゃう系のチームで発生します。
あるいは、「お客さんはこう操作すべき」という設計ができていなかったり、またはそのような設計を「サービス全体を把握していない人」に任せたりしても起こります。

責任範囲はサービスの基礎設計者、もしくはプロジェクト最高責任者です。

どんなコンピューターシステムも、お客さんは必ず「一定の手順に則って」操作を行うことによって、望みの結果を手に入れます。
どんな風に使っても必ず望みの結果が得られる、お客さんが何をしてもいいシステムなんて絶対ありえません。

お客さんを「顧客満足の状態」にまで正しく導くのが最高責任者の仕事だし、そのために「お客さんにどういう操作をさせるか」を決めるのはお客さん自身でも最下層のプログラマーでもなく、最高責任者です。
そのことを分かってない人が設計したシステムは、このサービスフローバグが必ずどこかで発生します。

3.アーキテクチャーバグ

3つ目は、システムのアーキテクチャー(基礎設計)が要件と合ってないことで起こったバグ。
インフラ設計者が実態を予測できなかったことで、実装が必要以上に複雑になりすぎて発生します。

たとえば、個人的に過去に実際あった事例で、「1モデル = 1テーブルの原則」なんてものを適用しているチームがありました。
1つのモデルクラス内で、複数のテーブルに対する処理を書いてはならぬっちゅーんですよ。
当然ながらデータベーステーブルの結合なんて絶対御法度なわけです。
「だってその方がシンプルだから」だって。

だもんで、開発の最終工程たる「データの統計処理」を実装する段になって、複雑で危険な結合処理を現場判断で手組みするなんてことが行われてしまったのです。。。。です。。。です。。。(セルフエコー)
つまりシステムをシンプルするという目的は全く達成されていなかったし、ルールは本末転倒だったし、なんなら「最初から分かってる結論から逃げただけだよね?」ってなもんです。
(ちなみにそのチームは完成予定日の目前で解散しました)

システムのアーキテクチャーは、そのビジネス要件の「複雑さ」から紐解くものです。
要件が複雑なシステムにはより複雑なアーキテクチャーが求められるし、シンプルなシステムはシンプルなアーキテクチャーを採用すべきだし、その設計には「複雑なシステムを、いかにシンプルなコードで書けるようにするか」という考慮が求められます。

あと間違っても「流行ってるから最新のフレームワークにしてみよう」とか、そんなの絶対ダメ。最新のフレームワークを採用する企業カッコイイって認識も間違ってるから!!
そもそもフレームワークはどんなビジネスモデルを得意としているかで選ぶものだから!(そのへんの話はまた後日、、、)

それからもう1つ。
アーキテクチャーバグに関するよくあるトラブルの例で、入力エラーの場合にどうするかのルールが曖昧、なんて現場もよく見かけます。
プログラムというものは本質的に入力エラーを拒否するコードを絶対に書かざるをえないのであって、どんな入力であろうとも後続処理が正常作動するメソッドが、常に必ず絶対に書けるわけではありません。
たとえば日付文字列を unixtime に変換するコードは、不正な日付に対して必ずエラー値を吐かざるをえないわけで、これをどう処理するかルールを決めるのは現場ではなくインフラ設計者の仕事です。

経験の浅いインフラ設計者は、プログラムが正常に動かない状態をなんでもプログラムのせいにしてしまいがちです。
まぁ、そういうふうに考えるのが自然だからね。

でも現実には、「アーキテクチャーがしっかりしてれば防げたバグ」なんてものもあるわけで、そのようなアーキテクチャーにするには欲しい機能がなるだけ多く盛り込まれてるフレームワークを選ぶという視点が重要です。

4.アフォーダンスバグ

最後。
今回の4つの中でもっとも厄介なバグは、いわゆる「使い勝手が悪い」という種類のものです。
責任範囲は基本的にはデザイナーで、デザイナーはたとえ自分のせいじゃなくても積極的に使い勝手に関する責任をとるべきです。

が、この世のあらゆるアフォーダンスバグが全部デザイナーの設計不足のせいで起こるわけではなく、「新人が自分のタスクを理解していなかった」なんて理由でも発生します。
また、サービスフローが不完全だったり、アーキテクチャーがおかしかったりしても発生します。

アフォーダンスバグは責任範囲が不明瞭になりやすく、開発現場では「ある程度仕方ないもの」と許容されてしまう傾向もあります。
ですが、長期的な視点で見たときのユーザーからの信頼喪失度は4種のバグの中で実は最大で、「長年に渡ってなんとなく顧客評価が低い」状態を生み出す原因となります。
だってそうでしょ?
使いづらいシステムは使いづらいのであって、それ以上にも以下にもならないのです!
「いかにもできそうだし、実際にできると書いてあることが、うまくできない」んだから、そりゃあ評判だって落ちるだろうよ。

アフォーダンスバグを防ぐには、
1.仕事に真摯でていねいなデザイナーを採用する
2.その人を、チーム一丸となって大事にする
の2つが重要です。
初級プログラマーは教育制度さえしっかりしてれば最悪替えが効くけど、本当に優秀なデザイナーってマジ替え効かないからね?

5.まとめと次の予告

まぁ、バグの定義はこんな感じ。
要は曖昧でさえなければ定義は何でもいいんですが、もし何も思いつかないようだったら一度上記の定義を採用してみてください。
確実に」、そう、確実に! 今までよりもバグが管理しやすくなるはずです。
要は定義があればいいんですよ、定義が!!

(最近は割とそうでもないかもだけど)私が新人だった30年前は、「不具合はとりあえず何でもプログラマーのせい」という風潮が今より強く、しかも私自身も若い頃は何でも抱え込むタイプだったので、どうしたらいいか分からなくなったことも1度や2度ではありません。
だったんですけど、時を経た今なら分かる。
システムにおいて末端の初級プログラマーは、システムバグが出ないようにコードを書いてさえいれば責任達成だったわけで、なんのこたぁない。過去に俺のせいにされたバグのうち、4分の3は俺のせいじゃなかったワケだ。
(プロダクトの責任者になった今では文字通り現実に全部俺のせいなんだけど、まぁ、あくまで30年前当時はね、、、)

もし、当時の風潮がそのまま残ってる企業なんてものが仮にあるとしたら、ぶっちゃけそんな会社エンジニアが辞めて当たり前です。

要は、「システムのバグをゼロにしていくこと」とは、つまり「誰がどんな責任を果たせばいいか、1人1人が自覚する」ということでもあるわけですからね。
そのへんしっかり定義して、堅牢なチームを作っていきましょう!!

さて次回予告。
バグをちゃんと定義した。責任範囲はしっかり決まった。
そこまでやってようやく、この問題に取りかかれるわけです。

「このプログラム、百点満点中で何点なの?」という話。
つまり、バグが具体的にどれくらい減ったのか、ちゃんと数値で評価する方法です。

バグ1つ1つについて、それがバグだと理解はできても、「システムの品質」を推しはかる基準がないチームは多いです。
それができなくてプログラマーの期末考課がうまくワークしない企業も割とあります。
割とあるってか、今の日本企業の98%はぶっちゃけできてません。
なぜかというと簡単な話で、プログラムの品質を「定性情報」だと、大多数の人が思い込んじゃってるからです。

定性情報ってのは、要は「芸術点」とか「感情の高まり」とかの、数値では表せない情報の総称のこと。
反対に数値化できる情報のことは「定量情報」といいます。
客観的な評価を行うには、定性情報ではなく定量情報である必要があります。
だから、定性情報であるプログラム品質は監視不可能、って理屈になるわけです。

でもさ、プログラムの品質って本当に定性情報なのかな?
数値化は無理? 絶対不可能?
だって基本1と0の羅列よ?

俺ならできるね。
なんならプログラムの品質だけじゃない、俺に定量化できない情報はないと言い切ってもいいよ。マジで。
「俺がいかに嫁を愛してるか」みたいな情報も数値化できる。

モノの本には「世の中には定量情報と定性情報の2種類がある」って書いてあるけど、ない!!! そんなものはない!!
この世の全ては「定量情報」と「定性情報と見なされがちな情報」の2つがあるだけ!

嘘だと思う? 定性情報の定量化なんて完全には絶対無理だと思う?
じゃあやってみようか?

てなわけで次回。
「定性情報の定量化 ~愛の大きさを数値で測る方法」でお送りします!!

この記事が気に入ったらサポートをしてみませんか?