web-dev-qa-db-ja.com

レガシーコードを引き渡すためのベストプラクティス

数か月後に同僚が新しいプロジェクトに移り、私は彼のプロジェクトの1つを引き継ぎます。準備のため、私はすでにMichael FeathersのWorking Effectively With Legacy Codeを注文しました。

しかし、この本と、これまでに見つけたレガシーコードに関するほとんどの質問は、コードをそのまま継承する場合に関係しています。しかし、この場合、私は実際に元の開発者にアクセスすることができ、秩序だった引き渡しの時間があります。

私が継承するコードの背景:

  • 機能しています:既知のバグはありませんが、パフォーマンス要件が高まるにつれて、遠くない将来にいくつかの最適化が必要になります。
  • Undocumented:メソッドおよびクラスレベルでのドキュメントはほとんどありません。しかし、コードがより高いレベルで何をすることになっているのかはよく理解されています。なぜなら、私は何年もの間(ブラックボックスとして)そのAPIに対して書いてきたからです。
  • 上位レベルの統合テストのみ:APIを介して他のコンポーネントとの適切な相互作用をテストする統合テストのみがあります(これもブラックボックスです)。
  • 非常に低レベルで、速度が最適化されています:このコードはアプリケーションのシステム全体の中心であるため、その多くは、年と非常に低レベルです(一部は特定の構造体/レコード用の独自のメモリマネージャーがあります)。
  • コンカレントでロックフリー:私はコンカレントでロックフリーのプログラミングに非常に精通しており、実際にこのコードにいくつかの部分を提供していますが、これにより別のコードが追加されます複雑さの層。
  • 大きなコードベース:この特定のプロジェクトは1万行を超えるコードであるため、すべてを説明してもらうことはできません。
  • Delphiで書かれている:私はこれをそこに出すつもりですが、言語が質問に密接に関係しているとは信じていません。この種の問題は言語に依存しないと考えています。

彼の出発までの時間はどのように過ごすのが一番いいのだろうと思っていました。ここにいくつかのアイデアがあります:

  • すべてを私のマシンで構築するために取得します:すべてをソースコード管理にチェックインする必要がある場合でも、ファイルを一度チェックインするのを忘れていないので、一方、これはおそらくビジネスの最初の注文になるはずです。
  • その他のテスト:変更を加えるときに、導入するバグを早期に検出できるように、クラスレベルのユニットテストを増やしたいですが、現在のコードはテストできません(巨大なクラス、長いメソッド、相互依存関係が多すぎます)。
  • 何を文書化するか:まず、コードの中で理解しにくい領域に文書を集中させるのが最善だと思います。その低レベル/高度に最適化された性質のため。見た目が悪く、リファクタリング/リライトが必要なものがいくつかあるのではないかと思いますが、実際には、私が見逃している可能性があるという正当な理由でそこに出てきた最適化です(Joel Spolskyを参照すべきでないこと、パートI
  • 文書化の方法:いくつかの散文を伴うアーキテクチャのクラス図と重要な機能のシーケンス図が最良だと思います。
  • 誰に文書化するか:私は彼にドキュメンテーションを書いてもらうか、彼に説明してもらうのがいいので、ドキュメンテーションを書くことができると思いました。彼には明らかだが私には明らかでないものは、適切にカバーされないのではないかと心配です。
  • ペアプログラミングを使用したリファクタリング:これは時間の制約により実行できない場合がありますが、おそらく彼のコードの一部をリファクタリングして、より保守しやすくすることができます彼はまだ物事が彼らがそうである方法である理由についての意見を提供するためにまだいた間。

これにコメントして追加してください。これらすべてを行うには時間が足りないので、特に優先順位を付けることに興味があります。

更新:引き継ぎプロジェクトが終了したので、このリストを この答え での自分の経験で拡張しました。

68
PersonalNexus

開発者にアクセスできるので、コードは次のように尋ねます:-

  • どのモジュールがコーディング/実装が最も困難でしたか。どのような問題があり、どのように克服されましたか。

  • 最も多くのバグを生成したモジュール。

  • どのモジュールがバグの解決が最も困難になったか。

  • 彼が最も誇りに思っているコードの部分。

  • 彼が実際にリファクタリングしたいのはどのコードのビットですか?.

これらの質問は、何が最も問題を引き起こすのかについての洞察、そしておそらくもっと重要なことには、元の開発者の思考プロセスとパースペクティブのハンドルを提供します。

26
James Anderson

引き継ぎプロジェクトが終わったので、時間をかけて自分に合った答えを書いてみようと思います。

  • すべてをバージョン管理下に置く:ビルドに必要なすべてがバージョン管理下にあることを確認した後、私は古い開発者のハードドライブも検索し、展開に役立つ追加のスクリプトまたはユーティリティを探しました。 /またはアプリケーションをテストしましたが、チェックインされませんでした。
  • トップダウン:まず、主要なクラスの概要と、メインエリアの古い開発者によるガイド付きツアーを紹介します。次に、自分で残りの部分をさらに掘り下げ、意味のないことを//TODOマーカー。
  • 自分ですべてのドキュメントを書く:古い開発者に自分が書いたものをよく読んで正しいことを確認してもらいましたが、私は自分ですべてを書くことにしました。このようにして、古い開発者だけでなく、自分にとっても文章が意味をなすものであると確信します。
  • コメントのすべて:私は XMLドキュメントの要約 をすべてのクラスとすべてのメソッドに追加しました。このようにして、少なくともすべてのコードを確認し、コードで何が行われたかを要約するのに十分な理解があることを確認しました。また、IntelliSenseがこの情報を取得するので、要約メソッド/クラスを使用してメソッドを理解しやすくなりました。また、コードの中でまだ見なければならない領域を簡単に特定することもできました。
  • ソースに近いドキュメント:ソースコードとドキュメント間の接続を容易にするために、ほとんどのドキュメントをソースコード内に配置しています。さまざまなサブシステム間の相互作用を説明する高レベルのドキュメントの場合、この情報をコードの1箇所だけに置いても機能しなかったため、wikiを使用しました。文書はすべて電子的で全文検索可能でなければなりません。
  • Diagrams:基本的な概要として、さまざまなサブシステムのさまざまな粒度のクラス図を使用しました。コンカレントパーツについては、オブジェクト図と相互作用図が非常に役に立ちました。 トピックに関する他の質問 も参照してください。
  • ペアでのリファクタリング:私は古い開発者とリファクタリングを行ってコードの感触をつかみ、物事をより保守しやすくしましたが、これは時間がかかり、リスクの高いプロセスでした。リファクタリングツールとさまざまなパーツ間の厄介な依存関係の束。 Michael Feathersの効果的なレガシーコードの使用は、適切なツールサポートなしでのリファクタリングが依然として苦痛であるとしても、これのための本当に良い助けです。リファクタリング中、私は彼がマウスとキーボードを制御できるようにしました。彼にとってはずっと楽しかったので(最後の箇条書きも参照)、私は学んだことを自由に書き留めることができました。
  • コメントと変更の個別のチェックイン:overrideにコメントを書き込んで誤ってバグを導入した後、個別のチェックインでコメントと変更を行うように注意してきました。少しユーティリティを使用して、ソースコードからすべてのコメントを取り除いてから、何かをチェックインしました。そのため、コメントのみのチェックインの差分では、差異が0と表示されます。すべての変更(未使用のフィールドの削除など)は、古い開発者と慎重にピアレビューされ、まだ必要なものを削除していないことを確認しました。
  • 重要なパッセージの行ごとのウォークスルー:最も最適化された/複雑なパッセージについては、古い開発者と、場合によっては3人目の同僚と一緒に、コードを1行ずつ調べます。このようにしてコードを完全に理解し、より多くの人々がコードを吟味するにつれて、実際にはいくつかのバグと、さらに最適化できるいくつかのものを特定しました。
  • 迅速かつ古い開発者のモチベーションを維持する:私は、古い開発者の最終日が近づくにつれて(驚くほどではないが)、古い開発者の関心がますます低くなっていることに気付きました。したがって、最も重要なパーツが最初に渡されることを確認し、必要に応じて残りは自分で判断できるようにしておきます。私はまた、もっと楽しいこと(ペアプログラミング時のキーボードの制御など)を彼に任せて、自分で書くドキュメントのような退屈なこともやろうとしました。
  • 機能のリクエストを特定する:古い開発者に、人々が求めていたがまだ追加されていない機能のリストを尋ねると役に立ちました。追加するのが簡単に見えるものはいくつかありましたが、最初に考えた方法で実装すると他のものが壊れてしまうため、追加されなかったのには十分な理由がありました。
19
PersonalNexus

同じような状況にあったので、次のことも検討に値すると思います。

  • 展開を作成およびテストできることを確認します:製品を独自に展開します。最初から展開し、これが同一であることを確認します出発する人が行ったものに。これにより、スクリプトと指示が明確になり、バージョン管理システムにチェックインされていない成分などの偶発的な見落としを見つけることができます。 (これがになるとは言っていませんそれががある場合起こった、それは人が去る前に、今対処するのがはるかに簡単になるでしょう)

    (これは、たとえば継続的インテグレーションまたは継続的デプロイメントをすでに行っている場合など、あなたには関係がないかもしれませんが、念のために言及する価値があります...)

  • さらにテストを書く:これは、システムの理解度をテストするための本当に良い方法です。これにより、コードの領域をより詳しく調べることができ(または強制的に)、コードが疑わしいほどバグがないことを確認するか、または考えた領域が明らかになりますあなたは意図を理解しましたが、実際に同僚が去る前に説明を求めなければなりません

  • ドキュメントのペアライティング:これは、概要を書くための効果的な方法です。同僚に機能や領域を説明してもらい、あなたにドキュメントに自分の言葉で書いてもらうことをお勧めします。これは、2人で行うと非常に簡単であることがわかりました。

個人的には、テストを書くことの方が、ドキュメントを書くことよりも優先されます。テストを行うと、理解が深まるからです。

ペアプログラミングを使用したリファクタリングについて、私が言う唯一のことは、特に高レベルのテストしか得られなかったとすると、これがボトムレスピットになる可能性があるということです。 。最終的に、意図したよりも多くの時間を使用してしまう場合があります。

16
Clare Macrae

あなたの質問にすでにある答えの+1!

ガイド付きツアー
1万行のコードはたくさんありますが、他の人に「ガイド付きツアー」をしてもらうことはまだ不可能ではないと思います。あなたはコードの前で一緒に座って、彼はあなたを上から下へと旅に連れて行き、「レイヤー」を下に働きます。あなたは一気にそれを行う必要があります-一度にすべてがあなたの両方を殺すでしょう。

ズームイン、ズームアウト
これを行うことの利点は、彼があなたにそれを説明している間、彼がそれを彼に文書化しようとしていただけではないかもしれないいくつかの「ああ、そう、これもある」という瞬間があることです。自分の。そして、あなたの質問は、自明ではあるが他の誰にもではない自明な部分に焦点を合わせるのに役立ちます。この種のズームイン/ズームアウトの操作は1対1でのみ可能であり、そのようなものを読み書きしようとすると扱いにくいものになります。

ドキュメント
私はあなたが両方とも独立して文書化すべきであると思います-彼は一番下から始めるべきです(一緒にそこに行く時間がない場合)、そしてあなたは何に基づいて一番上から始めるべきです'彼のガイド付きツアーを理解し、まるで他人のようだった[前の仕事で、私は「レガシー」コードのロードを継承し、私を離れる前にそれを文書化する時間がありました:)]。

どこにあるの?
これのほとんどの目的は、物事が発生する場所についての感覚を得ることができるようにすることです。そのため、特定のバグや変更があった場合、集中する必要があるコード内の場所を非常にすばやく見つけることができます。古いバグのリストを取得して、問題がどこにあるのかを正確に予測できるかどうかを確認することで、自分でテストできます。

彼をポンポン乾かす
彼があなたを嫌うことになったかどうかは問題ではありません(笑)。あなたの仕事は、その人の脳から可能な限り多くの情報を入手することです。あなたがあなたの側で管理を得て、彼らが「彼が去る前にそれらの最後のいくつかのバグを修正するだけ」よりも知識の伝達を優先することを確認してください(一緒に修正しているのでない限り...)。

12
Benjol

私は次のことを提案します(すでに特定されているものに加えて)-まず、マネージャーに、この人とできるだけ一緒に仕事をする時間を与え、彼が変更を行う義務があるときはいつでも彼と一緒に座るようにしてください。あなたは彼がしていることすべてを知る必要はありませんが、できるだけ多くを捕まえようとします。彼と友達になることが最も重要です。

引き渡しをプロジェクトとして扱い、計画を立て、管理者を巻き込みます。

0-システムの使用方法を知っていることを確認してください。

1-ソリューションコンポーネントの明確なインベントリを作成し、各コンポーネントのソースとその場所(差分リポジトリ内)

2-さまざまなサーバーのパスワードを取得し、可能であれば管理します。すべての管理者アカウント情報があることを確認してください

3-範囲外の場合を除いて、各外部コンポーネントのライセンスを取得します(例:特別なdll、データベースなど)

4-開発者と顧客(システムがローカルの場合)からシステムの現在のステータスに関する書面のレポートを取得します。

5-ビジネスルール、計算式などのドキュメントを入手します。これを彼と一緒に行うことができます。メール、会議情報、ユーザー要件ドキュメント、設計ドキュメントなどを渡してもらいます。

6-ソフトウェアが応答する必要があるスケジュールされたイベント(毎月のジョブの実行、毎週のジョブの実行)のリストを取得する

7-バックアップ/復元手順を学ぶ

8-アプリケーションの構築に使用されるフレームワークを理解する

9-要求された/予期された/計画された変更と、保留中のユーザー要求のステータスを把握します。自分でそれらを行う方法を特定しようとし始めます。

10-テスト環境と開発環境がよく似ていることを確認します。

11-簡単に見つけることができない主な依存関係(他のシステム上またはコンポーネント間の依存関係)を特定しようとします。

12-各ソフトウェアの使用に必要なバージョンとそのベンダーの連絡先(必要な場合)を特定して文書化する

13-彼が使用していた特別なツールを特定します。

14-高レベルのシステムフローを取得します。ドキュメントライブラリの構築を開始します

15-アプリケーションのユーザーセキュリティを管理する方法を理解する

16-バグログを取得し、アクションと、アクションが古いデータにどのように影響したかを理解しようとします(該当する場合)。

17-時間がかかりすぎるプロセスと、必要に応じて何を監視する必要があるか(例:異常なファイルサイズ、重複ファイルのFTPなど)を把握します。

18-本番サーバーのクロックを確認する

19-構成がどこにあるかを特定し、各環境構成を実稼働環境と比較して、どのパラメーターが異なるのか、およびその理由を把握

20-この男の連絡先情報を取得する

21-システムが内部にある場合は、システムユーザーとのミーティングをスケジュールし(彼らが誰であるか、およびそれぞれが果たす役割を知る必要があります)、彼らに紹介されます。彼らがシステムについて、そしてもしあれば現在の問題について彼らが言わなければならないことを聞いてください。できるだけ早く(マネージャーの承認後)メールに含まれていることを確認してください

22-彼が去る1週間前にあなたの理解を評価し、あなたが危険だと思う問題を報告する

データベースがないとおっしゃっていたので、このリストは短くなりました。

幸運を。

9
NoChance

最初に、最も複雑でパフォーマンスが最適化された部品を検討します。最初にそれらの部分を文書化し、一度に1つずつ説明してから、それらの部分に対するテストを記述しようとします(パフォーマンステストの前後を含む)。これにより、新しい最適化によって状況が改善するか悪化するかを確認できます。 )、他の人にテストをレビューしてもらいます。このようにして、彼は文書化して説明し、その説明を使用してテストを作成し(彼は別の領域を文書化している間)、彼のレビューは、何をテストすべきかを理解するのに役立ちます。このようにして、アプリケーションの最も重要な部分のいくつかの追加のテスト収束と、特殊なパフォーマンス最適化のドキュメントも取得できます。

それらをカバーした後に時間があれば、次に、年を経て最も頻繁に変更が必要であるが、文書化された最初のグループにないアプリケーションの部分を使用して、同様のプロセスを実行します。

次に、残っているものをすべて文書化します。

6
HLGEM

心中お察しします。

いくつかの提案:

  1. 退社するプログラマーとの会話をすべて録音してください!
  2. 「大きな」問題の背後にある動機を尋ねます。 APIを理解するのは良いことですが、内部の決定のためにDigを作成してください。なぜ、コードがそのままパーティション分割されたのですか?責任は何ですか。
  3. 本当にコードを研究する努力をしてください。メンテナンスとサポートの任務を引き受けるとき、「進行中にコードを研究する」というプレッシャーが時々あります。できれば抵抗し、実際にコードを研究してください。
  4. シナリオを探します。あなたはAPIを知っています-コードがどのように動作するかを見てください。頭に浮かぶ例は、Faxモジュールです。 APIのユーザーとして、ページ画像を準備し、コードにコマンドを送信してページを送信する必要があることを理解していました。このシナリオがどのように実行されるかを確認するために、コードをたどって離れるプログラマーに頼みます。次に、もちろん、「受信ページ」シナリオに進みます。
  5. 80/20-最初に、より一般的なシナリオをカバーするようにしてください。
  6. 書き直しを検討してください。コードが古く、インターフェースが明確に定義されている場合、テクノロジーがそれを正当化するのに十分なほど変更されている可能性があります。
  7. 私はこれを言うのが嫌いですが、新しい仕事を探すことを検討してください。
5
user18254

いくつかの大きなコードを理解する最善の方法は、トップダウンのアプローチだと思います。最初に全体像を理解してから、コンポーネントを1つずつ徐々に掘り下げていきます。

次に、掘り出しの各レベルで、最も注意が必要な部分に優先順位を付けるように依頼します。彼にできる限り説明してもらいますが、常に自分で文書化してください。

自分で文書化することの最も良い点は、後で戻ってくるときに、彼があなたに説明したときと同じ認知状態を思い出すのに問題がないことです。 あなたが書いたことは、他の人が書いたことよりもはるかに簡単に理解できます。私の経験では、同じコードの一部を文書化している2人は、似たようなテキストの一部を生成しません。

これによって、「何をどのように文書化するか」という問題も解決されると思います。彼がすべてを説明したら、コードに戻ったときに何を文書化するかを自分で決め、それらの部分だけを文書化できます。

アイデアは、最初に(彼の存在下で)コードを完全に理解してから、後で(彼の不在下で)コードを理解できるようにするすべてのことを記述/実行することです。

コードを完全に理解することで、全体像を把握する必要があり、各コンポーネントがこの全体像とどのように関連しているかを理解する必要があります。各ピースが全体にどのように追加されるかを追跡することは、特に役立ちます。孤立して何かを理解しようとしないでください。そのコンテキストを見失ってはいけません。

最後に、上記の作業を終えたら、積極的に管理してください。単体テストのカバレッジが必要な部分を自分で決定します。どの部品を最適化する必要がある(または最適化できる)か、コンポーネントをリファクタリングする方法などです。システムを知っていれば、彼がいなくなったらすべての決定を下せると信じてください。

5
treecoder

きちんとしたドキュメントが無理なく手軽に購入したい場合 Pascal Analyzer(PAL) Delphiプロジェクトでこれを使用しましたが、それはすばらしいことでした。ドキュメントの機能が製品に分割されている可能性があります。 (Pascal Browser)に精通していないため、両方(<300 USD)を購入する必要があるかもしれませんが、PALは、関数が呼び出されている場所などで変数が使用されている場所を理解したり、コードであらゆる種類の潜在的な問題を見つけたりするための優れたツールでした。

PALを使用して、コードがどのように構造化されているかを把握し、さらに私の経験が何かあれば、おそらく約1000の改善点のリストを提案します。リストを操作すると、コードの品質が向上し、コードが大幅に簡略化され、将来の生活が楽になります。 Delphi自体は、最近のバージョン(過去5年ほど)でリファクタリングをサポートしています。私がそれを行っていたときに本当に正しく機能するには、dprファイルにすべてを含める必要がありました。

ユニットテストが必要な場合は、 DUnit をダウンロードして、元のコーダーでいくつかのテストの作成を開始します。これは、おそらく少なくとも一部の時間を使用する建設的な方法です。

3
mcottle

バックエンドデータベースについては言及していませんが、データベースがあると仮定すると、

  1. 特に列とPK-FKが文書化されたデータモデルを取得する
  2. SQLトレースを設定し、アプリケーションの使用中に発生したすべてのクエリを記録します。クエリの実行順序は、アプリケーションのフローについての良いアイデアを提供し、デバッグにも役立ちます
2
NRS

私のアーキテクトがオーストラリアに引っ越し、過去8年間の会社にいたときと同じように、多くの遺産を残したのと同じ状況です。彼は彼が請負業者であった前の建築家からの遺産のものを自己継承しました。

あなたと他の人はすでに良い点について述べましたが、彼が去った後に直面した問題は、あなたがよりよく準備できるかもしれないということです...

1)(技術者)彼が扱っている顧客の連絡先の詳細。

2)ソフトウェアライセンスの購入に使用したアカウント、毎年更新する必要のあるキー、更新に必要なプロセス/コスト。

3)サードパーティのソフトウェアライブラリ/コンポーネントおよび製品と統合する製品のセットアップのドキュメント。 ITがスペースを空け、誤った命令が渡されたために失われたマシンを戻すために4日間苦労しました。

4)彼がソースコードをソフトウェア預託会社、例えばエスクローに預金するために使用される文書/ステップ。

5)まだ長いリストがありますが、あなたには当てはまらない場合もあります実際の人を置き換えることができるドキュメントの量は少ないので、彼の詳細を手元に置いて、素敵な言葉で頑張ってください:)

また、これが初めてかどうかもわかりません。私にとって、私は5/6の雇用者と協力してきましたが、常に、悪いドキュメントまたはまったくドキュメントのないコードを継承してきました。だから、すべてのドキュメントと一緒に、ポジティブを保つだけです:)

2
Surjit Samra