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


66

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

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

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

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

彼の出発までの時間をどのように費やすのが最適か疑問に思いました。ここにいくつかのアイデアがあります:

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

これにコメントして追加してください。このすべてを実行するのに十分な時間がないため、特に優先順位を付ける方法に興味があります。

更新:引き渡しプロジェクトが終了したので、以下の回答で自分の経験を使ってこのリストを拡張しました。


2
最適化された機能の理由を文書化することに集中してください!

コードがソース管理下にあることを望みます。その場合は、各変更に対して入力されたコメント(もしあれば)が役立ちます。
バーナード

Michael FeathersのLegacy Codeを効果的に使用することをお勧めします。修正が必要になる可能性が最も高いと思われるモジュールを中心に、これらのテストケースを作成する必要があります。今すぐ始めれば、期待を正しく得ることが容易になります。
ビルリーパー

リファクタリングの前の段階がありますが、どのインターネットが答えに乏しいと思われるのでしょうか?
sergiol

回答:


25

開発者にアクセスできるので、コードを尋ねます:

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

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

  • どのモジュールがバグを解決するのが最も困難でしたか。

  • 彼が最も誇りに思っているコードのビット。

  • 彼が本当にリファクタリングしたいコードのビットですが、時間がありませんでした。

これらの質問は、あなたに最も問題を引き起こす原因についての洞察を与え、おそらくより重要なことには、元の開発者の思考プロセスと展望のハンドルを与えます。


あなたが言及した部品を選ぶというアイデアが好きです。直観的には、トップダウンに従っていましたが、その方法では、コードの奥深くに埋もれた最も厄介な部分は、プロセスの非常に遅く、おそらく遅すぎるまで現れなかったかもしれません。あなたのやり方はもっと理にかなっていると思う。「文書化の方法」の部分について何か提案はありますか?UML?テキスト?
PersonalNexus

@PersonalNexus。このアプローチをドキュメントにも引き継ぐことができます。どのドキュメントが最も有用であり、どのドキュメントが信頼できないか古くなっているかを尋ねます(ドキュメントの95%が最後のカテゴリに分類されると信じてください!)。
ジェームズアンダーソン

17

引き渡しプロジェクトが終了したので、時間をかけて、自分に最適なものを含む自分自身の答えを書き上げると思います。

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

14

同様の状況にあったので、以下も検討する価値があると思います。

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

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

  • より多くのテストを書く:これは、システムの理解をテストするための本当に良い方法です。これにより、コードの領域をより詳しく見ることができます(または強制します)。コードにバグがないことを疑うほど確認するか、意図を理解したと思ったが実際には同僚が去る前に説明を求める必要がある

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

テストはドキュメントを書くよりも優先度が高いと私は考えます。テストにより、おそらくより多くの、またはより堅固な理解が得られるからです。

ペアプログラミングを使用したリファクタリングに関して、私が言う唯一のことは、これが底なしのピットになる可能性があるという危険性があることです。あなたはそれがあなたが意図したよりも多くの利用可能な時間を使用して終わることに気付くかもしれません。


さらに+1のテスト。十分なテストはありません。
サルダスリオン

10

質問にすでに答えがある場合は+1!

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

ズームイン、ズームアウト
これを行う利点は、彼があなたにそれを説明している間、彼がそれを文書化しようとしていなかったかもしれないいくつかの「ああ、はい、これもあります」瞬間をほぼ確実に持つことです彼自身で。そして、あなたの質問は、彼にとっては明らかだが誰にとってもそうでない部分に集中するのに役立ちます。この種のズームイン/ズームアウトの相互作用は、1対1でのみ可能であり、そのような何かを読み書きしようとすると、扱いにくいです。

ドキュメンテーション
あなたは両方とも独立してドキュメントを作成するべきだと思います-彼は一番下から始めなければなりません(あなたがそこに集まる時間がない場合)、あなたはあなたが理解したことに基づいて、一番上から始めるべきです彼のガイド付きツアーは、まるで他の誰かのためのものでした [以前の仕事では、「レガシー」コードを大量に引き継ぎ、自分自身を離れる前にそれを文書化する時間しかありませんでした:)]。

何だ?
このほとんどの目的は、どこで何かが起こっているのかを把握できるようにすることです。そのため、特定のバグまたは修正が与えられた場合、集中する必要があるコード内の場所を非常にすばやく見つけることができます。古いバグのリストを取得し、問題がどこにあるかを正確に予測できるかどうかを確認することで、自分自身をテストできます。

彼を乾かし
ます彼があなたを憎んでいるかどうかは関係ありません(笑)、あなたの仕事は、その人の脳から可能な限り多くの情報を引き出すことです。あなたがあなたの側で管理を得て、彼らが「彼が去る前にそれらの最後のいくつかのバグをただ修正する」よりも知識移転を優先することを確かめてください(あなたがそれらを一緒に修正しているのでなければ...)。


コードの私の理解をテストするために自分でいくつかの古いバグを修正しようとするための+1
PersonalNexus

1
「彼があなたを憎んでいるかどうかは関係ありません」-注意、「それは小さな世界です」;)
retracile

また、ワードドキュメントを開き、大量のスクリーンショットを含む、すべての生き物をドキュメント化します。あなたが情報過多の状態にあるとき、それは私に多くの時間を節約しました!
ベン・パワー

7

次のことをお勧めします(すでに特定されているものに加えて)-まず、マネージャーに、できる限りこの男と仕事をする時間を与え、彼が変更を行う仕事をするたびに彼と一緒に座るようにしてください。あなたは彼がしていることすべてを知る必要はありませんが、できる限りキャッチしようとします。最も重要なのは彼と友達になることです。

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

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週間前に理解度を評価し、リスクと思われる問題を報告する

データベースがないと述べたので、このリストは短くなりました。

幸運を。


@SSamra:アップリフティングコメントをありがとう。私はそれが必要でした。:)
NoChance

非常に網羅的で、そうでなければ見逃していたかもしれないいくつかの重要なポイントを含みます。例えば、管理者と私たちの(内部)顧客を巻き込みます。
PersonalNexus

5

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

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

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


5

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

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

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

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

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

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

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


どのように文書化するのですか?プレーンテキスト?ウィキ?ソースコード内のコメント?
C69

ドキュメントを書いていたときに持っていたコードと同じ理解を復元することを可能にするもの。
ツリーコーダー

5

心中お察しします。

いくつかの提案:

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

私はすべての会話を録音するというアイデアが好きなので、彼がいなくなった後、私は彼の元の言葉に戻ることができます。提案#7、ただし、オプションではない;-)
PersonalNexus

3

適切なドキュメントが必要な場合、Pascal Analyzer(PAL)のコピーを無理なく購入したいのですが、Delphiプロジェクトでこれを使用しましたが、すばらしいものでした。そのため、両方を購入する必要があります(<300 USD)が、PALは、関数が呼び出される場所などで変数が使用されている場所を理解し、コードに関するあらゆる種類の潜在的な問題をピックアップするための優れたツールでした。

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

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


2

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

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

一般的には良い点ですが、私の特定のケースではデータベースはありません。
PersonalNexus

1
それは他の誰かを助けるかもしれ
NRS

2

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

あなたと他の人はすでに良い点を述べていますが、ここに彼が去った後に直面した問題があります...

1)(技術者)取引している顧客の連絡先の詳細。

2)ソフトウェアライセンス、毎年更新する必要があるキー、およびそれらを更新するためのプロセス/コストを購入したアカウント。

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

4)エスクローなどのソフトウェアデポジット会社にソースコードをデポジットするために使用するドキュメント/ステップ。

5)まだ長いリストがありますが、あなたにも当てはまらないかもしれません

また、これがあなたにとって初めてかどうかもわかりません。私にとって、私は5/6の雇用主と仕事をしており、常に悪いドキュメントまたはドキュメントがまったくないコードを継承しています。したがって、すべてのドキュメントと一緒に肯定的なままにしてください:)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.