僕がCOBOLから学んだこと
SAStruts+DBFluteでの開発が終わり、またCOBOLで書かれたシステムの保守が始まる・・・。
あぁ、楽しかったSAStruts、楽しかったDBFlute、楽しかったJava。
ということで、この辺りで一度、COBOLから学んだことについてまとめてみようと思う。
僕が今、主にかかわっているシステムはクライアント側がVB(Windows)、サーバ側がCOBOL(UNIX)で出来ている。そして更にバックボーンには、メインフレームが構えている。メインフレーム側の構成は主にPL/1+JCLで、もちろんDBは階層型だ。
そんなシステムを2年近く保守してきた中で気付いたことを書いて行こうと思う。
カプセル化やスコープの重要性
今更何を言っているのかと思う方もいると思うけど、マジなんだ。僕が初めて学んだ言語はC言語でそれからC++、Javaと続き、その後LL言語にも手を出し始めた。C++を始めた時に幾つかオブジェクト指向の参考書を読んだけど、必ずと言っていいほどカプセル化の話が出てくる。しかし、知識としては理解できても体感として有難みを感じることは、あまり無かった。なぜなら、C言語を使った場合でも、ファイル分割やらスコープやらをある程度意識して組めばカプセル化、カプセル化とギャーギャー騒ぐほどの事でも無いだろうと思っていたからだ。
・・・しかし、僕はCOBOLに出会った。それは衝撃的な出会いだった。
全ての変数がグローバル。COPY句で定義された巨大な構造体の様なもの。そしてIFとMOVEで8割が構成されている巨大なコード*1。そこにはヒープ領域もスタック領域も無かった。もちろんクラスやスコープだって無い。そんなCOBOLのコードを修正することで、僕はカプセル化やスコープの重要性を初めて体感出来た。
言語の構造は言語の主とするデータ構造に似る(事が多い)
これもCOBOLをやっていなかったら体感できなかったと思う事。
COBOLの場合のデータ構造はCOPY句で定義された構造体と階層型のDBでロジックはメインとサブ(関数)のモジュールで構成されていて、同じサブが使い回しされる事はあまりない。
オブジェクト指向の言語だとデータ構造はクラスでリレーショナルDBを使う事が主流だ。ロジック部分もクラスで書かれ色々なクラスが連動して動く。O/Rマッパの話をするときにインピーダンス・ミスマッチの話とかが出ることもあるけど、やっぱりオブジェクト指向のクラスとリレーショナルDBのエンティティは似ている。
JavaScriptの場合なんかもロジックをJSON的に書くことが出来るし、Lispの場合は言わずもがなだ。
じゃあ、次の時代はというとやっぱりクラウドなんかなー。言語の仕様としてスケール関連が含まれていたりするんかなー。まぁ、僕は言語をツールとして使う側の人間なのでこの辺りの勉強はもう少し後でいいやと思っている。
こんな感じで言語の構造は言語の主とするデータ構造に似る(事が多い)とCOBOLをやった事で気付く事が出来た。
上の世代のプロマネの考え方
実はこれがCOBOLから学んだ一番大きな利益だと思う。とあるJava(Web)の案件でスケジュールがかなり遅れている事があった。致命的なレスポンスの問題や大幅な仕様変更も抱えていた。その時僕はPGの立場でアサインされていたのだけど、プロマネから必要ならPGを追加すると言われた事があった。もちろん、僕は断ったのだけど。
このPGを追加するという判断もCOBOLをやると多少理解できる。COBOLで書かれるプログラムは、バッチ処理が多くてINとOUTがハッキリしている事が多い。だからいざという時に人海戦術で何とかする事が出来る可能性が高い。Java等の場合でもINとOUTはハッキリさせないといけないのだけど、その粒度が細かい事や単純なバッチ処理では無い事が人海戦術をとる事を難しくしている。COBOLの場合は、その粒度がかなり大きいことや一方通行の単純なバッチ処理が多いので圧倒的に人海戦術が使い易い。だから上の世代のプロマネはPGの追加という判断を行うのだと思う。
確かにCOBOL時代のコーディングは簡単だったのだ。しかし、その感覚を未だ引きずっているから、まだコードもまともに書けないSIerの新人に1年目やそこらから企画や設計をさせる*2。結果、今のSIerは技術が空洞化している。特に30代の中間辺りはかなりヤバい人が目立つ。この技術がスカスカのSE(自称)からは距離を取った方が良いというのもCOBOLが教えてくれたことの一つだ。
まとめ
最後にPGとかSEでなくて、プログラマとしての立場からまとめると、
COBOL=飯の種
それ以上でもそれ以下でもない。COBOLは何の感動も生まない。
さて、Python+Google App Engineでアプリでも作るかな。
jarで複数のmainを扱う
javaで作った複数のバッチ処理を一つのjarにまとめようと思ったのですが、他のjarライブラリー等を含めた実行可能jarだと特殊なクラスローダ経由で実行する為、実行できるメインのクラスが一つしか設定出来ないらしい。(eclipseで作ったjar)
ほぼ同じコードやライブラリーを使っているので複数のjarを作るのも野暮ったい感じがしたので、以下の様なエントリー用のクラスを作って一つのjarにまとめました。
public class EntryPoint { public static void main(String[] args) { String[] sendArgs = new String[args.length - 1]; for (int i = 0; i < sendArgs.length; i++) { sendArgs[i] = args[i + 1]; } String className = args[0]; try { Class<?> main = Class.forName(className); Object[] vargs = {sendArgs}; main.getMethod("main", new Class[] { String[].class }) .invoke(null, vargs); } catch (Eception e) { e.printStackTrace(); } } }
上記のクラスを実行可能jarのメインのクラスに設定して以下の様に実行すればOK。
java -jar Hoge.jar packagename.MainClassName real args
JASRACとクラウド
最近、JASRACがクラウドを利用することは違法だと言っている記事やブログを見かけて、著作権等について少し考えてみたのでメモ。
ここで最初に疑問に思ったのが、なぜ音楽(映像)業界は未だにどのCDも値段がほとんど同じなのかという事。
僕達のようにプログラムを作る事を仕事にしている人種だと様々なライセンス形態があるのが当たり前に思っている。商用利用に限り有料だとか、1サーバライセンスで50人まで利用できるよとか。値段についてもCD1枚が数千円〜数百万円と大きな差があったりする。
音楽のCDだってある程度の値段のバラツキがあったて良いと思うし、むしろその方が自然だと思う。素敵な曲であればより多くのお金を払っても聞きたいと思うし、ありふれた様な曲であっても100円くらいなら買うかもしれない。この辺りがJASRAC等が中央集権的なやり方で管理している弊害なのかも知れない。
話はクラウドに戻るけど、JASRACがクラウド利用は、違法だとか言いだすのは可笑しな話だと思う。本来であればそれは、曲を作ったり、歌を唄った人達(もしくは組織)が個人個人で決めることだと思う。
さらに言えば、チャリティー利用に限り無料だよとか、いやいや俺たちはどんな利用目的にしたって金を取るぜ(キリッ とか、柔軟なライセンスであって良いと思う。もちろん個人のクラウド利用はOKだよとかもね。
それを実現するには、ライセンスを簡単にカスタマイズ出来て、そのライセンスの元に曲を任意の値段で登録できるような非常に薄い仕組み(ソーシャル的な)が必要だと思う。利用する側もその仕組み上でその曲がどんなライセンスで提供されているのかを直ぐに検索出来たりして。
ちょっと現実離れしているかもしれないけどやっぱり上に書いたような事が理想系だと思う。そして緩やかではあるけど、JASRACに限らず、中央集権によって中間マージンを取る様な仕組みは徐々に衰退していくんじゃないかなと思う。それはソーシャルかつフラットで無駄のない仕組みへのシフトチェンジであるとも思う。
個人的には中間マージンを取る奴らは、消えてくれないかなwと思っていたり。コードも書けないのにSE気取りの奴らとかね。
最後は、愚痴になってしまったけど、こんな事考えてみたりした。
インターセプターでトークンを管理する
SAStrutsで2重更新を防止する一番簡単な方法は、トークンを使う方法ですね。
やはり、色々な所で必要になる機能なのでインターセプターで処理したい所です。
実装方法は、最終的には下記のサイトのまるパクリになりました。
http://d.hatena.ne.jp/kuwalab/20080217/1203253826
以下は最初に自前で実装した時に少し躓いたのでメモ。
上記サイトの方法では、Interceptor内でrequestをコンテナから取得するようにしていますが、僕が最初に実装しようとした時はDIで取得するようにしていました。
しかし、DIの方法だと何故かisTokenValidを実行した際にrequestにトークンが保存されていない為、チェックに引っ掛かりませんでした。
ちなみにこれは、HotDeploy時の話です。CoolDeployの時どうなるかは為していませんが、HotとCoolで挙動が変わる実装方法もどうかと思ったので、最終的に上記サイトの方法になりました^^;
HOT Deployについて
SAStrutsでの開発は、HotDeployが非常に便利なんですが稀にイメージと違った動作をする事がある。今回もちょっとはまったのでメモ。
taglib用のstaticメソッドの中で、SingletonS2ContainerFactoryから取得したセッションスコープのコンポーネントを取得してローカル変数に代入しようとしたところキャストエラーが発生した。デバッグで追いかけてみても同じクラス間の代入でエラーが発生しているようにしか思えない。
!?!?という状態になりました。
Google先生に聞いてみたところ、Seasarのメーリングリストに気になるスレッドが。
http://ml.seasar.org/archives/seasar-user/2008-October/015959.html
要するに通常のクラスローダでロードしたクラスにHotDeploy用のクラスローダでロードしたクラスを代入しようとした為にキャストエラーが発生していた。もちろんこれは、CoolDeployの時は発生しない。原因を特定するのに半日も掛かりましたorz
HotDeployは、便利なのですが本番の動作(CoolDeploy)と動作が違ってくるのはやはり問題な気がします。