COBOL屋の呪縛

今回の日本出張ではいくつかのプロジェクトの状況をみてきた。で、思ったこと。

COBOL時代のデータ構造を引きずることで、生産性や保守性が落ちている」

フラグだらけのマスター

本物のコードをだすわけにはいかないので、すごく簡略化した例で説明したい。あるシステムを利用できるユーザのマスターテーブルがあるのだけど、そいつには「なんちゃらサービス利用可否フラグ」みたいなのがたくさんついているのね。

この方式の問題は以下の通り。

  • テスト負荷
    • フラグがあるということはそれをチェックするif文があるということ。
    • if文があればテスト件数は最低2件は増える。
    • 入れ子になれば、4件、8件...と増えていく。andやorでも同じ。
  • コードの冗長性
    • 「あるユーザがサービスAを使えるか」を調べる処理と「あるユーザがサービスBを使えるか」を調べる処理はほぼ同様になることは明らか。
    • 「サービスAを使えるユーザ」を調べる処理と「サービスBを使えるユーザ」を調べる処理もほぼ同様になることは明らか。
    • テスト負荷が高くて冗長性も多いということは、生産性や保守性が落ちて行くということ。
  • サービス追加時の負荷
    • ユーザ管理テーブルにカラムを追加し、検索SQLを書いて、テストして... 
    • テーブル構造とソースと同期を取らないといけないから、後戻りも大変。

COBOL屋の呪縛

で、こういう「大福帳」みたいなテーブルを設計するのって、RDBの知識が足らないCOBOL世代[*1]なのね。データはシーケンシャルレコードに詰め込んで保存しておけ、と叩き込まれた世代。レコード設計とテーブル設計は全然別のものなんだけど、その違いがわかってない。正規化されたテーブルを見ると「性能が下がる」とか言い出しちゃう。

正規化で別テーブルにするという概念がないから、オブジェクト指向の概念も当然、ない。にも関わらず、Javaとかで開発を進めてしまう。複雑なSQLでデータ検索して、Javaなのにカラム単位で代入していって、メソッドの引数もプリミティブ型ばかり...要はJavaの皮をかぶったCOBOLになってしまう。行数がふくれあがって、if文だらけで、インターフェースが粗雑だから入力チェックも重くなる。つまりテストが増える。ちうか、激増する。そして「テスト自動化なんて無理」と言い出す。

オブジェクト指向だと


多対多の関係にあるユーザとサービスを用意すれば良いだけのこと。Railsならusers, services, user_servicesの3テーブルで実装するでしょ。

class User < ActiveRecord::Base
  has_many :user_services
  has_many :services, :through => :user_services
end

class Service < ActiveRecord::Base
  has_many :user_services
  has_many :users, :through => :user_services
end

class UserService < ActiveRecord::Base
  belongs_to :user
  belongs_to :service
end

#あるユーザが使えるサービス一覧
User.find(id).services

#あるサービスを使えるユーザ一覧
Service.find(id).users

大福帳方式と違って、サービス追加時にテーブルをいじくる必要はない。servicesテーブルにレコードを追加して、そのサービスを使えるユーザをuser_servicesテーブルに登録するだけでよい。「あるサービスを使えるユーザ」「あるユーザが使えるサービス」を調べるコードは「ほぼ同じ」ではなく「全く同じ」だが、行数はとても少ない。ちうか、一行。

呪縛から逃れるには?

どんなに優れたフレームワークでも、そこにあるデータ構造が腐っていたら、そのフレームワークの効果を享受できない。Railsであっても、大福帳テーブルでは意味がない。

となると、作り替えなのかな...

古いJavaアプリ(Tomcat以前のJ2EE直呼び、およびJBoss利用)をRailsで書き換えるというプロジェクトがあったのだけど、コードの行数は一桁(二桁減に近い、一桁)減ってしまった。減った行数もすごいけど、冗長性がほとんどなくなったことのほうが嬉しかった。その分、テスト負荷がへるわけだし、保守性も向上する。

まあ、これはJavaで数万行(もう少しで10万行)という小規模な対象だったから作り替えも簡単だったのだけど、100万行単位のを相手に「作り替えましょう」と言い出す勇気は正直なところ、ない。このあたりどうすればよいのかは考え中。

おまけ: COBOL屋の負の遺産チェックポイント

  • テーブルの項目数が妙に多い
  • やたらと「フラグ」がある
  • FILLERというカラムがある

*1:および、その知識を引き継いだ世代