Big Rewritesに関する質問 を読むだけで、自分が回答したかった質問を思い出しました。
古いJavaで記述された恐ろしいプロジェクトがStruts 1.0を使用して受け継がれています。関係に一貫性がないか、関係がまったくないか、主キーまたはフィールドが主キーではないが、一意ではないテーブルさえあります。どういうわけか、ほとんどのアプリは「動作する」だけです。ほとんどのページは再利用され(貼り付けられたコードをコピー)、ハードコードされます。これまでプロジェクトに取り組んだことのある人なら誰でも、それを何らかの形で呪いました。
今、私は長い間、この恐ろしいアプリケーションの全面的な書き直しを上級管理職に提案することを考えていました。私はゆっくりと個人的な時間に取り組んでいますが、これを実現するためのいくつかの専用リソースに値するものだと本当に感じています。大きな書き換えに関する記事を読んだとき、私は考え直しました。そして、私が上司に私の書き換えをサポートするように説得したい場合、それは良くありません。 (私はかなり小さな会社で働いているので、提案は承認される可能性があります)
TL; DRいつ大きな答えが書き直され、それをサポートするためにどのような引数を使用できますか?
申し訳ありませんが、これは長くなるでしょうが、それは複数の書き換えプロジェクトでの建築家と開発者の両方としての個人的な経験に基づいています。
次の条件では、何らかの書き換えを検討する必要があります。その後、どちらを行うかを決める方法についてお話します。
これらのことはかなり自明です。完全なリライトと増分リビルドのどちらを決定するかは主観的であり、したがってより政治的に課せられます。私が確信をもって言えることは、それを決してと断定的に述べることは、良いアイデアは間違っているということです。
システムを段階的に再設計できる場合で、そのようなプロジェクトに対するプロジェクトスポンサーシップを完全にサポートしている場合は、そうする必要があります。しかし、ここに問題があります。多くのシステムは段階的に再設計することはできません。これを防ぐために私が遭遇した理由のいくつかを以下に示します(技術的および政治的)。
完全に書き換えを行うよりも、増分再調査の総コストが常に高いことを覚えておいてください。ただし、組織への影響は通常は小さくなります。私の意見では、書き換えを正当化でき、スーパースターの開発者がいる場合は、そうします。
それを完了するまで政治的意志があると確信できる場合にのみ、それを行ってください。これは、エグゼクティブとエンドユーザーの両方の賛同を意味します。それがなければ失敗します。これがJoelが悪い考えだと言っている理由だと思います。エグゼクティブおよびエンドユーザーの賛同は、多くの建築家にとって双頭のユニコーンのように見えます。あなたはそれを積極的に販売し、それが完了するまで継続的にキャンペーンを続ける必要があります。それは難しいことであり、成功を望んでいない人に評判を賭けることについて話しています。
成功のためのいくつかの戦略:
私は2つの大きな書き換えに参加しました。最初は小さなプロジェクトでした。 2つ目は、ソフトウェア会社の主要製品でした。
いくつかの落とし穴があります:
書き換えが実際の答えになることはほとんどありません。何も失うことなく、多くのリスクなしに、コードの多くをリファクタリングできます。
次の場合、書き換えが答えになることがあります。
しかし、リファクタリングを使用した遅いアプローチを強くお勧めします。それはリスクが少なく、顧客を満足させます。
次の場合は、書き換えの時間です。
アプリケーションを書き換えるコスト+書き換えられたアプリケーションを維持するコストは、現在のシステムを長期にわたって維持するコストよりも低くなります。
現在のものを維持することをより高価にするいくつかの要因:
//Here be dragons.
コメントがコード全体に渡っています。プロジェクトのアーキテクチャーに根本的な変更が必要な場合は、再起動するのにおそらくです。
それでも、新しいプロジェクトで再利用する価値のあるコードが大量に存在する可能性があります。
ただし、公正な警告に注意してください。現在のプロジェクトでは、ビジネスルールがテストされ、無数の人手による実際の使用で洗練されています。これは、ゼロから始めたプロジェクトには当てはまりません。
時間枠や直感は、このような抜本的な対策の適切な尺度とは思えません。この一連の行動に参加するには、明確、防御可能、およびよく理解されているの理由が必要です。
私はクラミイの答えとジョエルの意見には同意しますが、書き換えを行うことが適切な場合があります。長寿命のアプリケーション(10〜20年以上と言っています)では、時間の経過とともにメンテナンスがますます高価になります。これは、迅速なメンテナンスパッチのために元のアーキテクチャが犠牲になっているため、コードがますますスパゲッティになっているためです。また、古い技術の開発者は、より希少で高価になります。最後に、ハードウェアは古くなり始め、古いアプリケーションを実行するための新しいハードウェア、オペレーティングシステム、フレームワークなどを見つけることはますます難しくなります。また、ビジネスは進化し、ほとんどの場合、古いシステムは組織のビジネスニーズを満たすことができず、真新しいシステムでも対応できなくなります。
そのため、継続的なメンテナンスコストのすべてと、新しいシステムがビジネスにもたらす潜在的なメリットを、最初から物を書き直すコストと比較検討する必要があります。書き換えのコストについての見積もりではvery悲観的になる。ほとんどの場合、コストがかかり、思ったよりも時間がかかります。
やめる!書き換えはほぼ never 答えです。多くの場合、リファクタリングの方が適しています。
もちろん、書き換えが正当化されるのは回回あります:
書き換えよりもリファクタリングを推奨する理由を理解するには、書き換えに何が関係しているかを考えてください。絶対です:
既存のアプリケーションの機能のニュアンスを理解します。これがカプセル化するすべての微妙なビジネスルール、それが動作する環境(人間と技術の両方)、および現在のソリューションの利点と欠点を考慮に入れると、通常、これは簡単なことではありません。多くの場合、この情報が存在する唯一の場所(存在する場合)は、既存のアプリケーションのソースコード内です。残念なことに、書き換えを実行する主な理由の1つは、既存のコードの理解と保守が難しいことです。
この機能(またはその更新バージョン)を、テスト済みで信頼できる新しいアプリケーションで再現します。既存のコードは開発者には理解されない場合がありますが、通常はそのユーザーにはよく理解されています。現在のビジネスニーズを満たしていない可能性がありますが、少なくともさまざまな状況下でのアプリケーションの動作を知ることができます。
リファクタリングの大きな利点は次のとおりです。
また、書き換えを行うと、新しいコードベースに多くの新しいバグや混乱がもたらされることが保証されていることにも注意してください。
この図は、コードベースの品質とアプリケーションのビジネス価値の関数です。
このグラフは、レガシーソフトウェアのリエンジニアリングが正当化される時期と正当化されない時期を示すガイドのふりをしています。たとえば、ソフトウェアのビジネス価値が高く、コードの品質が低い場合、リエンジニアリングが正当化されます。
私のキャリアでは、大きな書き直しが答えになる唯一の状況だと思います。
会社の合併、システム機能の大きな重複。多くのシステムが統合されて廃止され、他のシステムはまだ処理中です。
私は今も生きている他社からシステムを受け継ぎました。巨大なコードベースがあり、私たちの部門と非常によく似た複数の部門をサポートしていましたが、デザインとフレームワークはまったく異なります。それを使用して残っているビジネスセクターは1つだけです。これにより、ゾンビ状態でこれを存続させるのに十分なお金を稼ぐことができます。古い専門知識はすべてなくなり、ドキュメントはありません。サポートの負担は高く、毎週失敗しています。私たちの会社はこのビジネスの特定のセクターをサポートしたことがなく、そのため機能や専門知識がないため、会社のシステムに統合されていません。
これは、書き換えが必要なケースの1つであるように見えます。この巨大なものを理解し、このビジネスに特化した機能のビットを引き出し、既存のシステムに追加する必要のある部分を書き直さなければならないようです。これが完了すると、既存のシステムがこの新しいセクターをサポートできるようになり、この獣は悲惨な状態から抜け出すことができます。そうでなければ、正気を失うことになります。
私は、Y2Kを処理するようにアップグレードされたいくつかのDOSアプリケーションがあり、Windows 16ビットアプリとして書き直され、さらに1つの「小さな」機能を備えた32ビットアプリとして書き直された(最終的には1人の顧客)が全体の構造に影響を与えました。
16ビットコードを32に移動することは、1か月で1人で行うことができたかもしれませんが、NOOOOOOOOO、それを書き直す必要がありました。このことは他の産業に適応することができ、開始する前でも完全な仕様と疑似コードを持っているでしょう。仕様は作成されましたが、実際のコードを書くのに時間がかかりませんでした。それは遅くリリースされ、16ビットの「最初の」よりも多くのバグが含まれていました(v.3.0にあり、ついに誰かが新しいバグを報告することなくほぼ1週間で完了できるようになりました)。
同じアプリケーションを3〜4回書き換えると、いくつかの改善がもたらされると思いますが、GUIフロントエンドをそれほど正当化できるとは思いません。
これは、テクニカルサポートの責任者としての最初のIT職でした。配布用のソフトウェアを開発しない方法についての本を書くべきです。明らかに私たちは多くの間違いを犯しましたが、アプリケーションを書き直し続けたという事実は、無能さをさらに悪化させました。
私はあなたのケースと非常に似たケースがあり、コードだけがStrutsを使用していませんでした。代わりに私がやったことは、特に安っぽく、多くの問題を引き起こしている対象地域でした。このターゲットを絞ったアプローチにより、段階的に改善されました。
2年間にわたって、私たちは拡張作業と一緒にビットやピースのリファクタリングに取り組みました。私たちは常に「硬化」タスクをプロジェクト計画に取り入れました。うまく機能しなかった特定の領域に焦点を当てることで、費用を最大限に活用できました。うまくいったものは私たちが一人にした。また、この作業が通常の開発の過程で行われ、リリースされたことも重要です。大きな書き換えの問題は、1年以上続いてから、戻ってくるまでにすべてのものが変更され、いくつかの厄介なバグが解消され、ROIが失われます。
私たちは全部を書き直したことはありません。ただし、新しい作業にそのプラットフォームを使用するのをやめ、大きな新しいプロジェクトに新しい新鮮なプラットフォームを売り込みました。それが承認され、妥当な時間で素晴らしい製品を提供しました。
そこで、私は自分の机に座って、1つの大きなaspxファイルとその背後にあるデータベースの絶対的な混乱のコードを書き直し、MS AccessインターフェースをMsSQLに置き換えました。
このASPプログラムには、次のようなものが散らかっています
include(close.aspx)
内部には、最後に開いているデータベース接続を閉じるコードが1行あります。少し変更を加える必要がある場合、それは悪夢モードでカルトーの5つの同時ゲームをプレイするようなものです。
私は、機能を複製し、カスタマイズして業界の他の人々に販売できる製品を作るために雇われました。問題は、これが過去10年間にすべてのビジネスニーズを満たすために作成されたということです(とにかく、そのうちの5から6シグマと言っていいでしょう)。
製品を販売したくない場合、おそらく彼らが望むことのほとんどを行うので、彼らは書き直す必要はなかったでしょう-おそらくエレガントではありませんが、お金を使うことは賢明ではありませんでしたニースコードを作成する際に「同じことをしてください」
既存のソリューションは拡張されません。
MS Access、あなたを見ています。
Joel Spolskyはこれに関して優れた記事を持っています: 絶対にしてはいけないこと、パートI
あなたが言うことができるタイトルから、それはちょっと一方的なものです(彼はなぜコードをスローしてはいけないのかについて話します)IMO、それには多くの真実があります、私は最近いくつかの開発者が言ったExcelの25周年でchannel9ビデオを見ました、どのように今日でもソースを調べた場合、リビジョンを確認すると、20年前に作成されたExcelのコードに戻ることになります。
100%確信することはできません(Netscapeでも間違いがある場合(Joels記事から))[〜#〜] i [〜#〜] Joelの記事は神から送られたものだと感じました。悲観的になる可能性があり、コードを捨てるのが大好きです。いつでも2度書いた方が良いと思いますが、これが実現したのは、たった今コストがかかるだけです。
具体的な答えを与えるために、私はコストと値の完全な比較を行う必要があります分析と言います。
私の現実の世界:これまでにv0.6を開発しているSilverlightアプリには、コードを非常に複雑にする非同期呼び出しの混乱があります。私は Reactive Extensions を発見したので、今週はほとんどのコードを書き直したいのですが、ここで顧客に何を伝えますか?プログラムは完全に正常に動作しますが(メモリリークはあります)、気にしませんか?何かやり直したいので、あと2〜3週間かかっているとは言えません。しかし、私はコードを分岐して、書き直す /それをfree時間でプレイします。
ちょうど私の2セント大丈夫です!?
「Xに行くならここから始めない」という古典的なジョークがあります。
私は一度仕事に就きましたが、雇用主の主な動機は、才能を持ってビジネスクリティカルなアプリの長期に渡る書き換えを開始することでした。私が尋ねることができなかった質問は、なぜあなたはなぜ最初にこのような状況に終わったのですか?原因が原因であったかどうか、それは危険信号であるはずでした
獣を維持し、段階的にリファクタリングするための機能を追加するためのあまりにも多くの圧力、
部門の能力が少なすぎる、
増分作業のためのクライアントまたは経営陣からの賛同が少なすぎる、
または何でも、そしてこれは問題が耐え難いレベルに達するまで衰退を引き起こします。
したがって、大規模な書き換えはおそらく非常に悪い考えであるという点で、ジョエルに同意します-大規模な書き換えが必要と思われる理由の背後にある根本的な理由がすべて明確である場合を除きますを処理すると、やがて問題を繰り返す可能性が高くなります。
これは、書き換えによって組織が競争力のあるEdgeを提供する戦略を追求できる場合、または現在のアーキテクチャでは対応できない方法で顧客により良いサービスを提供できる場合の答えです。
代わりに、書き換えが頻繁に発生し、管理の心配が軽減されます。
これらの心配のほとんどは実現せず、実現したとしても対処できます。しかし、最後の1つは最悪です。それは本質的にです:私たちは理由がありません。
はい、車のように、システムは摩耗の兆候を示し始めます。これは、定期的なサービスによって軽減できます。あなたは彼らが少し予防的なメンテナンスがいかに長い道のりを行くかについて彼らが言うことを知っています。投資として、ルーチンサービス(つまり、リファクタリングと標準化)は、ほとんどの場合、書き換えよりもコストがかかりません。
ただし、最終的には書き換えが必要になることを予想する必要があります。日付を設定し、それを暫定的に計画しますが、日付は、次のような説得力のある理由があるまで、他の戦略的目標を実現するために近づきます...
近年では、タイムリーまたはコストのかかる方法で彼らのニーズに対応できなかったため、大きなアカウントを獲得する機会を失っています。私たちのシステムは、カスタマイズをプラグインできる(現在のようにハードコーディングされていない)拡張可能なアーキテクチャを使用して書き換えられます。これにより、特別なニーズを持つ顧客に対応する時間とコストが劇的に減少します。より多くのアカウントを獲得し、現在の顧客のニーズにより適切に対応します。
書き換えを正当化する主な理由は、プラットフォームの変更にあると思います。たとえば、WindowsデスクトップGUIアプリケーションがあり、会社の所有者が次のバージョンをWebベースのアプリケーションにすることを決定した場合。いつもとは限りませんが、私の経験では、元の開発者が非常にモジュール化された再利用可能なコードを記述していない限り、ほとんどの場合、これを書き換える必要があります(ほとんど起こりません)。
Joelによると、大きな書き換えは1つの最悪の戦略的ミスです。
...最初から始めるとき、絶対に理由がないことを覚えておくことは重要です自分よりも良い仕事をするつもりであると信じる初めて。まず、バージョン1に取り組んだのと同じプログラミングチームもいないので、実際には「より多くの経験」はありません。古い間違いのほとんどを再び犯し、元のバージョンにはなかったいくつかの新しい問題を導入するだけです。
古いマントラを1つ構築して捨てるは、大規模な商用アプリケーションに適用すると危険です。実験的にコードを書いている場合は、より良いアルゴリズムを考えたときに、先週書いた関数を破棄したくなるかもしれません。それはいいです。クラスをリファクタリングして使いやすくすることもできます。それも結構です。しかし、プログラム全体を捨てることは危険な愚かであり、Netscapeが実際にソフトウェア業界の経験を持つ大人の監督を持っていたなら、彼らはそれほどひどく足を踏み入れなかったかもしれません。
決して、常にリファクタリングします-真実は、コードがあなたによって書かれたかどうかです-あなたはこれ以上何もできません。
テクノロジーを変更したい場合を除いて、コードには構造がありません(私はかなり前にいくつかのPHP Webサイトで作成者がinclude/class/functionではなくspahgettiをコピーして貼り付けた)で見ました)または、ひどく書かれた他の人から何かを引き継いだ。
すべてをブラックボックスとして設計する必要があります。モジュール化されたシンプルなAPI、内部の内容...それはそれほど重要ではありません:)スパゲッティがある場合、ブラックボックス内で閉じることができるので、適切なコードを汚染することはありません。
完全に新しいテクノロジーに移行する場合は、目的の機能を提供する必要があります。
「完全に新しい」:書き換えを計画しているが同じプラットフォームを使用する場合は、リファクタリングと賢明な再構築がほぼ間違いなく優れたソリューションです。ここで使用されている「プラットフォーム」はややあいまいです。言語、およびおそらくOS(LinuxからWindowsへの拡張、またはその逆が頭に浮かぶ)を含めることを検討してください。
「必要な機能を提供するために必要」:2000年頃、Java C++から主要なサーバーコンポーネントを書き換えて、すぐに使えるスレッド化、オブジェクトキャッシュを有効にするプロジェクトを開始しました。とクライアント制御のトランザクション。当時は、サポートしなければならなかったはずのC++のスレッドライブラリが複数あり、データベースコードの多くをスレッド対応にするには、ほぼ完全な書き直しが必要でした。クライアント制御のトランザクションについては、 ..古いアーキテクチャでは起こりません。
それでも、現在のシステムの動作に関する詳細な知識があり、11年間の寿命で非常に多くのいぼを開発していなかった比較的クリーンなコードであったことを除いて、私が書き直したかどうかはわかりません。
さて、私は既存のコードベースを捨てるだけの架空のシナリオを想像できます(バッキーボールの重量と体積がゼロであり、見過ごされている機能やバグを追加するために何週間または何ヶ月も生産性を失ってもかまわないという架空の状況。システムへの修正、およびシステムが非常に些細で組織に嫌われている場所で、サーバー全体とノートブックをノートパッド++とネットブックで10分で置き換えることができ、全員の生産性とモラル全体を向上させることができます。)
ほとんどすべての現実のシナリオでは、適切なリファクタリングをお勧めします。 ^ _ ^。文書化されていない法的要件およびビジネス要件がポップアップし始め、ギリギリの事柄がギリギリにハッキングされると、書き直しに隠れて予想外のコストがかかりすぎる傾向があります。
==より良いもののための適切なリファクタリング、およびもの==
通常の古いインクリメンタルアプローチによるレガシーコードのリファクタリング
抽象化による分岐
オープンクローズの原則と共通のビジネスロジック/永続化レイヤー
ある程度、プレゼンテーション、ビジネス、永続化レイヤーを分離して、レガシーソリューションと完全に下位互換性のある新しいアプリを作成するか、少なくともレガシーソリューションによって入力されたデータを処理できる場合があります。私はおそらくこのアプローチをお勧めしませんが、時々それは時間/スケジュール/リソース/必要な新機能の妥当な妥協です。
リファクタリングとリライトの領域には3つ目のカテゴリがあると思います...そして、それは言語バージョン、コンパイラ、およびライブラリを更新しています...時々、最新のコーディング手法を採用するだけで大きなメリットが得られる場合があります。
C#を例にとると、v7のコードはv2よりもずっとクリーンで安全で簡潔です。Elvisやnullの合体演算子などは、非常に便利です。
コンパイラの切り替えも、古いコードに新しい命を吹き込むかもしれません。ですから、作業や実装を簡単にする新しいライブラリーがあるかもしれません...ネットワーキングは、さまざまな実装の困難さの好例です。
また、組み込みLinuxシステム...新しいツールのインストールについて考えてください。svnからgitに切り替えます。またはシステムにViを追加するなど.
それは常にリファクタリング対リライトである必要はありません。あなたのアーキテクチャはおそらく改善の必要がありますが、それは機能します...たぶんあなたはあなたのコードがどのように書かれたかなどを考える必要があるだけです。
最初からやり直すポイントを決定するには、現在のプロジェクトを継続することの価値が、最初からやり直すことの価値を下回る場所を見つける必要があります。
これが非常に難しいのは、実際にプロジェクトを開始するまで、新しいプロジェクトでチームの開発速度を正確に見積もるためです。そうは言っても、新しいプロジェクトでの開発速度の非常に保守的な見積もりを使用すると、プロジェクトが投資に見合う価値のある投資であると見積もられた場合、新たに始めるビジネスケースがあります。
私の測定基準では、書き換えを正当化するために2つの条件を満たす必要があります。
それでも、書き換えの範囲を制限する必要があります。たとえば、ある企業では、モジュール性について知らないCプログラマを念頭に、C++で記述されたレガシーソフトウェアを使用していました。最終結果は、複数のクラスとDLLにまたがる有限状態マシンの形のspeghettiコードでした。コードに組み込まれた仮定とは大きく異なる新しい要件があり、同社の特許を取得した顧客への付加価値の一部となる予定でした。
コードに他の機能を実装することに時間を費やした後、いくつかのswitchステートメントのどれを変更する必要があるかを判断するのにどれくらい時間がかかるかについて、本当に良い考えがありました。私の提案は、次のコードのセクションを書き直すことでした。巨大な有限状態マシン-既存のコードを拡張するよりも時間がかかりません。私は1つに統合することができましたDLL以前は3つでしたが、オブジェクト指向の構造を提供し、重要な新しい機能をより簡単に実行できるようにするとともに、新しい機能を追加します。
書き換えを必要とするライブラリを使用する他の3つのアプリケーションがあったため、これらのプログラムを完全に書き換える必要はありませんでした。スコープはライブラリと、ライブラリを既存のソフトウェアにバインドするために必要なものに限定されていました。私の見積もりはそれほどずれていなかったし、その仕事はそれで代償を払った。再設計の直後に、私は新しい機能を追加するように命じられました。古い構造で1週間かかったとしたら、新しい構造では1日しかかかりませんでした。
OPはプロジェクトの範囲を示していませんが、私が取った主な手がかりは「古い[libs]を使用して古い[language/dialect]で書かれた」ものでした。実際、私がこれまでに携わってきたほとんどのプロジェクトでは、コンパイラー/インタープリター/オペレーティングシステムの更新に対応することがコードベースを維持する上で重要なタスクであることに気づきました。
要するに、私は段階的に書き換えを計画し、最初にlibsの更新を優先します。途中で他の最適化をこっそりと実行できるかもしれませんが、一部の変更を後のフェーズに延期することを計画しているという事実は、スケジュールを維持し、「行き詰まる」のを回避するための優れた方法です。