日々常々

ふつうのプログラマがあたりまえにしたいこと。

趣味を仕事にしてはいけない

私の趣味はプログラミングです。職業はプログラマです。名刺にはシステムエンジニアとか書いていますが、私はプログラマです。そんな私、勉強すればするほど、仕事でやっている事と乖離していく気がしています。海外や日本の他の会社がどうかは知りませんが、私がこの業界で働き始めてから関わったプロジェクトは悉く大きな改善を嫌っていました。
大規模なシステムであればあるほど、ユーザと開発者の間には様々な人間が絡み、その間の人達を全員説得しなければならず、開発者側がどれだけ声を出してもユーザには届きません。そんなものはユーザは望んでいないと一蹴されてしまいます。おそらくユーザ側の改善要望も金銭やその他で煙に巻いているのでしょう。この間にいる人々が、システム開発の会社であるにもかかわらず、システム開発の仕事をしないのです。私が関わってきたシステムの大半は、既存システムの更新、改修です。今動いているこのシステムにちょっとこういうことをさせてくれ、とそんな具合です。ユーザからの要望を中身も知らない人(Cは知っているけれどもJavaを知らない人など)が受けて、自分の感覚で概算します。そこで見込まれた工数を元に伝言ゲームしつつそれぞれの取り分を差し引いてから開発者の元までたどり着きます。ここで行き着く先が運任せです。私が今まで見てきたJavaの技術者で、OOPが出来ている人は殆どいません。そういう人達が開発者として受け取ってしまうと、挙動を理解せずコピペや偶然を駆使したコードが出来上がります。その場では確かに動き、テストもその部分だけでよく、少しばかりパフォーマンスが落ちる程度で済みます。そしてそういうものに限って、安く済みます。なぜなら日本で言うプログラマは仕様を理解する必要が無く、これまた日本で言うシステムエンジニアはコードを理解する必要が無いからです。しかしこのコードはひたすら保守され、何年もバージョンアップを繰り返し、今後も使われていく事でしょう。

さて、ここに1998年に作られたJavaのコードがあります。この時点でJavaのバージョンは1.2です。*1このコードは保守され続け、現在も元気?に稼動しています。稼動中のサーバはJ2SE 5.0で、もちろんポーティングと呼ばれるバージョン変更に対する改修も何度かされています。このポーティング作業では、ユーザから中間層のどこで予算をケチったのか知りませんが、兎に角コンパイルエラーや警告が無く動けばいい、程度の修正が行われました。J2SE 5.0に多少触れた方なら判るかもしれませんが、以下のような修正が一例です。

【修正前】Vecter v = new Vecter();
 ↓
【修正後】Vecter<Object> v = new Vecter<Object>();

馬鹿か。ジェネリックス使う意味が全くないし、そもそもVecterである必要が無いような場所です。*2もちろんこの後ではしっかりキャストしながら使っています。他にも駄目な実装は山ほどあり、このコード全体に渡ってOOPの欠片も見えません。1クラスにあるのは大抵がpublicな1メソッドのみで、500行から酷いときには2000行に渡っています。中身もわからずこれこれこういった処理を追加追加としているうちにどんどん伸びていったのでしょう。追加したバージョンのコメントもちゃんと残されています。まとまった処理と処理が入れ子になってたりなんて日常茶飯事です。フィールド宣言時に生成したインスタンスを使わずに別のメソッドの戻り値を格納したりとかも。多少遅くても動けばいい、確かにそうだとは思います。でもわざわざ遅くする必要がどこにあるんだと思ったりもします。こういうことを繰り返した結果、ちょっとした修正でもどこまで影響するかわからなくなっていき、新しい処理追加でも、既存と同じように動くようにまずコピペを行い、そのクラスでは絶対に使わないインスタンスが溢れ返ったコードが出来る、を繰り返して十数バージョンを経過。途方も無く遅く、途轍も無く保守し辛く、一見するだけではなぜ動いているのか判らないシステムが出来上がりました。奇跡のシステムです。


そのようなシステムに対して修正しろと言われた私。修正内容を聞き、その程度ならば普通10行くらいで済むな、と当たりを付けてコードを開く。冗談抜きで眩暈がしました。暫し眺めてから、これならば0から書き直したほうが良いと判断しました。色々あって修正完了、過剰なまでのテストを行っておかしな部分も既存と同じ動きをしている事を確認し、リリースしました。そしたら問題が発生。何かやらかしたかと思ったら、パフォーマンスが上がっていることが問題になっていました。今回の修正は処理の追加であって、それによってパフォーマンスが落ちる事はあっても上がる事はないとのことです。駄目な実装を書き直したのだから当然といえば当然なのですが、これらを説明しようがない、余計な部分を修正するなということらしいです。次はパフォーマンスが上がって言い訳資料の作成か、パフォーマンスを落とす作業を行わねばらなら無いようです。

既存システムの改修では、明らかに駄目な部分があったとしても、そこに目をつぶって実装しなければなりません。既存システムに新しい処理を追加する場合は、既存部分と同程度の酷いパフォーマンスが求められます。似た処理が1時間かかっているなら、新しく作った処理が5分で終わってしまうと、新しく作った処理がおかしいという事です。処理件数分無駄にループしたりして処理時間を増やすと良いかもしれません。

この話はフィクションです。フィクションであって欲しいです。

*1:現時点での最新はJavaSE6です。Javaのバージョンは判りづらいですが、4世代前になります。

*2:VecterとArrayList他の違いをちゃんと見ていなかったので、勉強できたことには感謝はしています。