俺が見たクソプログラム

kusakumo

kusakumo

私が会社に入ってから見た、クソなプログラム、もしくはクソ仕様を思い出して書いてみたい。

インストーラからインストールしたプログラムがDドライブのファイルを探し始めた

Cドライブの直下に「DATA」などというフォルダが作られて、訳の分からないファイルがいっぱい作られる、みたいなソフトが俺は大嫌いだ。なんて行儀が悪いんだろう。たかが一プログラムの分際で勝手にファイルシステムのルートにディレクトリを作らないで頂きたい。

で、作った人に何でそういうことをするのか聞くと、「インストールするパソコンがどんな環境か分からないので、Cドライブの直下にファイルを置くのが一番安全な方法なんだ(キリッ)」とか舐めたことを言う。

これは例えるならば、知人宅に遊びに行った時、勝手に家の前にデカイブルーシートを広げて、そこでバーベキューを始めるくらいのお行儀の悪さである。そして何故そんなことをするのかと問うたときに、「知人が昼飯を用意してくれてるかどうか分からないし、冷蔵庫の中身とキッチンの使い勝手もどうなってるか分からない。駐車場ならどこの家にもあるから、駐車場でバーベキューするのが一番安全な方法なんだ(キリッ)」って言ってるくらい筋が通らねえ行為だと思う。

それでも2万歩くらい譲って、まだ動くのであれば我慢できるが、たまに起動した瞬間、「エラー!!D:\work\業務A\プロジェクト一式\setting.dataにアクセス出来ません」などというメッセージが出てきて死ぬプログラムを見たときは液晶画面をぶち破って頭に被って会社の中を縦横無尽に走り回った末、社長室に飛び込んで脱糞したくなるくらいイライラしてくる。何食ったらこんなクソプログラムを作れるんだろう。で、プログラム作った人に聞くと、「俺のPCだと動くんだけどね・・・(お前のパソコンがおかしいんじゃねえの?)」という不満そうな顔をされる。舐めるな。

これも例えると、「ウチの家だと二階にあがって右手の部屋の中にある、机の隣の本棚に少年ジャンプがあって、それの120ページから『すごいよ!マサルさん』が始まってるんだけど、なんでお前んちはそうなってないの?何でジャンプ読んでないの?ジャンプを読まない家の事まで責任持てない」って言ってる様なもんである。

「私のホームページはここです」などとURLが書いてあって、よくよく読むと「c:\program files\homepagebuilder\data\index.html」などと書いてた・・・という笑い話があるが、これを、仮にもソフト屋と呼ばれる人たちが真面目な顔してやってしまうのがウチの職場である。

まあ、おおかたセットアップファイル作成プロジェクトの使い方がよく分かってないとかそういう理由だと思うが、よく分からんものをよく分からんまま適当に作って仕事を仕上げてしまおうという適当な発想が気に食わん。新しい事を勉強できない、勉強しようとする向上心すらない人間は技術者として失格である。さっさと退職しろ。

Win32API

開発はC#+WindowsForms。「Win32API」というstaticクラスがあって、なんじゃこれ?と思って見ると、「SendMessage」とか「FindWindow」とか「GetLastError」などの関数がDllImportされていた。
一番最初に立ち上がるFormクラスを見たら、WndProcをオーバーライドして、各ボタンのクリックイベントで「NYURYOKU_GAMEN」定数などを飛ばして画面遷移を管理していた。.NET Framework、CLRとは何だったのか・・・。メッセージボックスを出すのですらP/Invokeしてたよ。

iniファイルを簡単に読み込む方法

これも開発はC#+Windows Forms。「サーバーのアドレスはIniファイルから読むようにしてね」と言われた。「Iniファイル?C#で?xmlとかじゃダメなんですか?C#でiniファイル読むのキツイんですけど」と言うと、「Iniファイルは簡単に読めるよ。知らないの?しょうがないなー、サンプルソースがのったホームページ教えるから」と言われて、そのページを見たら案の定P/Invokeしてた。どんだけ好きなんだ。そもそも、iniファイルというのはWindows 3.1時代の遺産である。それからレジストリ地獄を経由して、ようやくxmlが産まれて普及したのに、いつまであんなクソ形式を使わなきゃならんのか・・・。

オッサンはIniファイルじゃないと理解できないらしい。ユーザーがIniファイルをテキストエディタでいじることを前提とした設計にしてる時点で間違ってると思うんだけど。

ちなみに、オッサンどものIniファイル好きは異常で、わざわざLinuxでもIniファイルを読み書きするライブラリを作ってた。拡張子はもちろんini。#を行頭につけるとコメントとして認識してくれる。一度読み込むとマップドファイルとしてメモリ上に残り続ける素敵な仕様です。

キャッチスロー

全ての関数の内部で無条件にtry-catchしてた。catchするのはもちろん「Exception」。で、catchしたあとログを吐いてまたスローしてた。しかもcatchしたあと「throw ex」でまたスローするからそのたびに記録されたスタックトレースが消去されてどこでエラーが起こってるのかデバッガでは全然わからなかった。Exceptionに付いてるスタックトレースを「車輪の再発明」するのはなんでだろ。
結局、このコードはデバッグを困難にするだけなので全関数から消去した。そのときも、「MainWindow」というクラスから派生した30個くらいのすべてのクラスで同名でまったく同じ名前の関数が定義されてたりして、本当大変な作業だった。ポリモーフィズムとは何だったのか。インターフェイスとは何だったのか。オブジェクト指向とはなんだったのか・・・。

ちなみに、書いた人は派遣の人でもうすでに居なかったからこのコードの真意は聞けなかった。ただ、その人は「近年まれに見る優秀な人材」としてかなりヨイショされてた記憶がある。俺ははっきり「この人のコード見たけどクソ以外の何者でもなかったですよ」と言ったのだが、「そんなはずは無いんだけどなあ・・・」などと上司が言っていた。せめて成果物を見てからクソか優秀か判断してくれ。

GOTO文の多用

「GOTO文を多用するな」とは古くから言われて来た最低限のルールで、どの会社も広く周知されている事だと思う。ただこれには、「エラー処理や二重ループをbrakeしたいときには使っても良い」という意見も根強い。まあどちらも一般論としては正しいと思う。

しかしこれを拡大解釈する人がいて、「GOTO文を多用するなとか言う人がいっぱい居るけど、エラー処理なんかはむしろ使った方が可読性が増すんだよね」などと良いながら、非エラー処理も何でもかんでもGOTO文を使いまくる人が居た。当然可読性など無いも同然だった。

特に最近の言語だと、エラー処理なんかは全部try-catchで済むし、二重ループを抜けるbrakeですら、私はまず使わないと思う。C#なんかだとLinqでコレクションから必要な要素だけを抜き出してforeachできるので特殊な条件でbrakeしたりする必要性自体ない。最近の潮流を取り入れ続けてる言語は全部似たようなこと出来るだろう。だからGOTOの必要性なんてどんどん薄れていく。

GOTO文を使うようなもっともらしい場面として私が思いつくのは、よほどパフォーマンスが要求されるところくらいじゃないだろうか。Cで組み込み系とか、デバイスドライバとかならまた違うだろうけどね。

あえて正規化しないDBも必要

普通、リレーショナルデータベースモデルでモデル設計するときはリレーションを正規化する。あえて正規化しない場合というのは、正規化された状態だと、多くのテーブルの内積をとらなければならず、パフォーマンス的に問題がでてくる、というパターンだろう。

たとえば、データベースの設計とパフォーマンス (SQL Server Compact)にはこんな事が書いている。

通常、多数のクエリで 5 個または 6 個以上のテーブルを結合する必要がある場合は、非正規化を検討してください。

5~6個という根拠がどこから出てくるのか分からないが、まあ、私も大体そんなイメージだ。どんなRDBMSを使うにせよ。しかし、DBスキーマ設計の変更というのは、開発が進んでからやるとダメージが大きいので、ここは皆さん頭を痛めていることだろう。とりあえず教科書通りに正規化した状態でプログラムを書き、パフォーマンスが出なければインデックスを張り直したり、SQL文を見直したり、なんだりかんだりと試行錯誤して、それでダメなら非正規化するか・・・って感じになるのが普通だと思うが、多くの現場ではそんな悠長なことはやってられないと思うので、最初からもうある程度非正規化した状態で進めてしまうか?という検討もしたりするだろう。少なくとも俺はそうする。

と、まあ、ここまで頭を使うのは、やはり管理対象をどのようにモデリングするかというのソフトの根幹に関わる重要なことであるからだが、それを全然理解してくれない人も居る。

いつだったか言われたのは、「DBの正規化は止めて下さい」ということであった。なぜならば、DBをユーザーが直に触ってデータを入れるような運用になっているから、リレーションを貼ったり制約を作ったりするとユーザーが理解できなくなる、ということだった。以前使っていたシステムのスキーマを見ると、なるほど。リレーションは一本もないどころか、主キーすらない。全く同じレコードが複数ある状態でどうやって「運用」していたのだろうか。逆に非常に興味深い。

しかしそれは、ユーザーがDBを直に触らなくてはならない、という仕様がそもそも間違いなのでは?と主張しまくり、なんとか押し通すことができたのでよかった。