Legacy code事件簿

17
Legacy Code Legacy Code 事件簿 事件簿 2013 2013 - - 06 06 - - 22 22 by munch by munch

description

「『レガシーコード改善ガイド』討論・品評会 #1 」  http://bit.ly/ZJeM1b で発表した資料です

Transcript of Legacy code事件簿

Page 1: Legacy code事件簿

Legacy Code Legacy Code 事件簿事件簿20132013--0606--22 22 by munchby munch

Page 2: Legacy code事件簿

もくじ

• 第一話「メインフレーム舐めるなよ(キリッ」

• 第二話「キーワードは【不定】」

• 第三話「ココはSingletonでしょ」

• 第四話「間違っちゃいないけど、間違ってる」• 迷宮入り「オレが至高のレガシーコードを見せてやる(キリッ」

Page 3: Legacy code事件簿

注意

• 以下の話は厳密には実際のシステムとは同じものではありません。⇒ 人に聞いた話や、その記憶ベースの話なので。

Page 4: Legacy code事件簿

第一話 「メインフレーム舐めるなよ(キリッ」

• 概要とある基幹系ダウンサイジング(※)プロジェクトでのお話。既存のCOBOLのシステムのロジックをそのまま踏襲してJavaで作り変えたら・・・

(参考)ダウンサイジングのイメージ図

メチャ高っ!でも、早っ!

それなりのお値段で

それなりに

やるやるやるやる事事事事(=(=(=(=業務業務業務業務))))一緒一緒一緒一緒ならならならなら、、、、安安安安いいいい方方方方ががががイイイイイイイイじゃじゃじゃじゃんんんん!!!!

(※)ダウンサイジング・・・COBOLとかで作られた基幹系システムをJavaとかOSSとかを使って、システムのマイグレーションをするタイプの

   プロジェクトの事です

Page 5: Legacy code事件簿

第一話 「メインフレーム舐めるなよ(キリッ」

• 状況ダウンサイジングPJの場合、「現新(比較)」が重要になるので、

基本的に既存の構成、ロジックを踏襲します。ですが、既存のロジックは既存の環境に適用した形(=めちゃくちゃ性能が良いメインフレーム前提のロジック)で書かれているので、それをそのまま移植してしまうと問題が発生する場合があります

• 例:SELECT文で(SORTすらせずに)DBから全件データを取得し、メモリ上でSORTをかけて、外部結合(的な処理)をさせるような事をしてる場合もあります

それをそのままそれをそのままそれをそのままそれをそのままJavaでででで実装実装実装実装してしまうとしてしまうとしてしまうとしてしまうと、、、、、、、、、、、、帰帰帰帰ってこないってこないってこないってこないPGになるになるになるになる可能性可能性可能性可能性がありますがありますがありますがあります。。。。

⇒⇒⇒⇒    タチタチタチタチがががが悪悪悪悪いのがいのがいのがいのが、、、、本番本番本番本番とかのとかのとかのとかの件数件数件数件数がががが大大大大きいところできいところできいところできいところで爆発爆発爆発爆発するところするところするところするところ

Page 6: Legacy code事件簿

第一話 「メインフレーム舐めるなよ(キリッ」

• 対応DBからデータ取得する場合は、素直にSELECT文にORDER BY句をつけましょう。あと、ロジックでゴリゴリ外部結合させるような事はせず素直にLEFT OUTER JOIN とかを使いましょう

上記は一例です。

• 「既存システムが本質的に何をしたいか」をコードから読み取って、それを新しい技術ではどう実現するのがふさわしいのか、を考えるのが大切です

Page 7: Legacy code事件簿

第二話「キーワードは【不定】」

• 概要とある基幹系ダウンサイジングプロジェクトでのお話(またかよ)例の如く「現新(比較)」をしてたら、合う時があったり、なかったり・・・

(参考)イメージ図

既存のシステム

新規のシステム

どうもどうもどうもどうも現行現行現行現行システムシステムシステムシステム((((既存既存既存既存システムシステムシステムシステム))))がががが、、、、動動動動かすたびかすたびかすたびかすたびにににに違違違違うううう結果結果結果結果をををを出出出出してくるようだしてくるようだしてくるようだしてくるようだ・・・・・・・・・・・・

⇒⇒⇒⇒    いわゆるいわゆるいわゆるいわゆる「(「(「(「(結果結果結果結果))))不定不定不定不定」」」」問題問題問題問題

1回目 1回目○1回目 1回目

2回目 2回目×

Page 8: Legacy code事件簿

第二話「キーワードは【不定】」

• 状況前ページの通り、現行システムが動くたびに違う出力をしてくるわけですが、「じゃ、そもそも今のシステムおかしいんじゃね?」という疑問が湧きますね。では、なぜ大丈夫だったのでしょうか?

• パターンパターンパターンパターン1111 「 「 「 「やっぱおかしいんじゃねやっぱおかしいんじゃねやっぱおかしいんじゃねやっぱおかしいんじゃねーーーーかかかか!」!」!」!」⇒ はい、現行システムのバグです。これはどうしようもない。。。Orz

• パターンパターンパターンパターン2222 「 「 「 「現行現行現行現行システムシステムシステムシステムではおかしくないけどではおかしくないけどではおかしくないけどではおかしくないけど((((またそのまたそのまたそのまたそのパターンパターンパターンパターン?)」?)」?)」?)」⇒ これは、ちょっと第一話のパターンとは違います。ダウンサイジング   の場合、基本的に現行の仕組みを踏襲するのが「吉」になる事が   多いのですが、、、詳しくは次ページに。

Page 9: Legacy code事件簿

第二話「キーワードは【不定】」• (パターン2の続き)

下記のように最終的なアウトプットについてだけではなく、中間のワークファイルについても基本的に合わせておくのが良いです。

現行処理現行処理現行処理現行処理1111 現行処理現行処理現行処理現行処理2222 現行処理現行処理現行処理現行処理3333

新処理新処理新処理新処理1111 新処理新処理新処理新処理2222 新処理新処理新処理新処理3333

中間結果中間結果中間結果中間結果1111 中間結果中間結果中間結果中間結果2222 最終結果最終結果最終結果最終結果

中間結果中間結果中間結果中間結果1111 中間結果中間結果中間結果中間結果1111 最終結果最終結果最終結果最終結果

それぞれのタイミングで比較す

べし。

Page 10: Legacy code事件簿

第二話「キーワードは【不定】」• (パターン2の続き)

ただ、、、現行の中間結果の並び順が(後続の処理に影響が無いという理由で)結構イイ加減だったりした場合、そこで合わなくなります。。。

現行処理現行処理現行処理現行処理1111

新処理新処理新処理新処理1111中間結果中間結果中間結果中間結果1111123333,CCDD…123555,AABB…124111,EEFF…

中間結果中間結果中間結果中間結果1111123555,AABB…123333,CCDD…124111,EEFF…

現行では始めの3桁しか使ってなかったりして、その後の順番はテキトーだったり。。。

でも、新処理は基本的にテーブルを利用してるから、PK指

定すると並び順が厳密になる。。。

Page 11: Legacy code事件簿

第二話「キーワードは【不定】」

• 対応 結局パターン1と同じく、現行のシステムを「一意の並び順になるように」 修正してもらいます。そうしないと現新比較が出来ないので。。。

 ⇒ 第一話の続きになりますが、   「新しい技術で実現しようとしたこと」を更に現行の   システムへフィードバックして、「正しい答え(期待値)」を   (無理矢理にでも)作り出していく事が大切です。

Page 12: Legacy code事件簿

第三話 「ココはSingletonでしょ」

• 概要とあるWeb系のPJでマスタデータを使った入力値チェック(=入力された

コードがマスタ上に存在しないとエラーにする)をお願いしたら。。。。

(参考)イメージ図

画面からコードを入力!

マスタデータマスタデータマスタデータマスタデータ

マスタデータを取ってきて、入力チェック!

(注)このマスタデータは滅多な事では変わりません。後、量

も高々数千件程度です。

Page 13: Legacy code事件簿

第三話 「ココはSingletonでしょ」

(参考)クラス図

ではではではではサンプルコードサンプルコードサンプルコードサンプルコードをどうぞをどうぞをどうぞをどうぞ!!!!

⇒⇒⇒⇒    http://bit.ly/1bRHUTU

一番マズかったクラス

Client

AbstractValidator

HogeDac

マスタデータマスタデータマスタデータマスタデータ

DataLoader

DataTable

Hoge1Validation

これもあまりイケてない

Page 14: Legacy code事件簿

第三話「ココはSingletonでしょ」」

• 対応 サンプルコードの通り、マスタデータの取得部分をSingleton(チック)に して、メモリ上にチェック用のマスタデータを保持させておくのが吉でした。

 ⇒ 一歩間違えば(システムレベルでの)グローバル変数   になってしまい、扱い所が難しいSingletonパターンですが

   上手く使えば幸せになれるんじゃないでしょうか。

Page 15: Legacy code事件簿

第四話 「間違っちゃいないけど、間違ってる」

• 概要とあるWeb系のPJで仕様が追加されて、「バッチ用の日付」を処理しないといけなくなったんで、Dateクラスを拡張してクラスを作ってみたら。。。

(参考)クラス図

これもこれもこれもこれもサンプルコードサンプルコードサンプルコードサンプルコードをどうぞをどうぞをどうぞをどうぞ!!!!

⇒⇒⇒⇒    http://bit.ly/11J54pX

大失敗したやつ後で改修して作ったクラス

TroubleMain DateUtilDate

MyBadDate MyGoodDateHogeBizLogic

Page 16: Legacy code事件簿

第四話 「間違っちゃいないけど、間違ってる」

• 対応 サンプルコードの通り、Dateクラスを拡張させるまでは良かったのですが ちょっと考えが浅はかでした。。。インスタンスがどれ位生成されている のかという事の想像力が足りませんでした。。。orz

 ⇒ Javaを書き始めて6年位経っていた時にやらかした失敗です。

    なまじテストを書いてたり、それなりにJavaの事が分かって

    来てたので、「これならいけるハズ」と見事に落とし穴にハマって    しまいました。。。

Page 17: Legacy code事件簿

迷宮入り「オレが至高のレガシーコードを見せてやる(キリッ」

• 状況 とあるJavaのシステムで1クラスで10万ステップオーバーのクラスが 存在していたそうです。。。

• 対策

⇒⇒⇒⇒    打打打打つつつつ手手手手なしなしなしなし((((キリッキリッキリッキリッ