web-dev-qa-db-ja.com

大規模なコードベースに慣れるための最良の方法は何ですか?

大規模なコードベースがすでに配置されている既存のチームに参加することは、気が遠くなる可能性があります。最善のアプローチは何ですか。

  • 広い;コードから、すべてがどのようにリンクするかについての一般的な概要を取得してみてください
  • 狭い;一度にコードの小さなセクションに焦点を合わせ、それらがどのように完全に機能するかを理解します
  • 進むにつれて開発および学習する機能を選択してください
  • 利用可能な場合(および最新の場合)、クラス図とumlから洞察を得るようにしてください
  • 完全に他の何か?

私は現在約2万行のC++アプリとライブラリに取り組んでいます(編集:物事の壮大な計画では小さいです!)。業界では、経験豊富なプログラマーによる紹介を受けると思います。しかし、そうでない場合は、できるだけ早く付加価値を開始するために何ができるでしょうか。

-
回答の概要:

  • デバッグモードでコードをステップスルーして、どのように機能するかを確認します
  • あなたよりもコードベースに精通している人とペアを組み、順番にコーディングする人と見たり話し合ったりする人になります。チームメンバー間でパートナーを交代させて、知識が広まるようにします。
  • 単体テストを作成します。コードがどのように機能すると思うかを主張することから始めます。期待どおりの結果が得られた場合は、おそらくコードを理解しているはずです。そうでない場合は、解決するパズルや質問をする必要があります。 (ドナルに感謝します、これは素晴らしい答えです)
  • 上記と同様の方法で、関数型コードの既存の単体テストを実行します
  • UML、Doxygenで生成されたクラス図、およびその他のドキュメントを読んで、コードの概要を理解してください。
  • 小さな編集やバグ修正を行ってから、徐々に積み上げていきます
  • メモを取り、飛び込んで開発を開始しないでください。乱雑なコードや不適切なコードを生成するよりも、理解に時間を費やす方が価値があります。

この投稿は 継承されたコードベースを使用して自分自身を理解するための最良の方法の部分的な複製です

73
RJFalconer

可能であれば、いくつかの小さなタスクから始めて、問題の周りのコードをデバッグします。デバッグモードでコードをステップスルーするのが、何かがどのように機能するかを学ぶ最も簡単な方法です。

24
Brian R. Bondy

もう1つのオプションは、関心のある機能のテストを作成することです。テストハーネスを設定することは、システムの依存関係とその状態が存在する場所を確立するための良い方法です。各テストは、システムが機能する必要があると考える方法についてのアサーションから始まります。そのように機能することが判明した場合、あなたは何かを達成し、それを再現するためのいくつかの実用的なサンプルコードを持っています。それがそのように機能しない場合は、解決するパズルと従うべき一連の質問があります。

17
user8599

まだ言及されていない人々に私が通常提案することの1つは、開発者になる前に、既存のコードベースの有能なユーザーになることが重要であるということです。新しい開発者が私たちの大規模なソフトウェアプロジェクトに参加するときは、コードに取り組む前に、エキスパートユーザーになるために時間を費やすことをお勧めします。

当たり前のことかもしれませんが、多くの人が進歩を始めたいと思っているので、コードにすぐに飛び込もうとしているのを見てきました。

10
Russell Bryant

これは、あなたがどのような学習者であり、どのようなプログラマーであるかに大きく依存しますが、次のようになります。

  • まず広い範囲-範囲とサイズのアイデアが必要です。良ければ、これにはdocs/umlのスキミングが含まれる場合があります。それが長期的なプロジェクトであり、すべてを完全に理解する必要がある場合は、実際にドキュメントを正しく読むことができます。繰り返しますが、ifそれらは良いです。
  • 狭い-扱いやすいものを選び、それを理解しようとします。コードの「味」を取得します。
  • 機能を選択します。自信がある場合は、今見た機能とは異なる機能を選択し、小さな変更を加え始めます。
  • 反復-物事がどれだけうまくいったかを評価し、初期のステップをより深く繰り返すことで利益が得られるかどうかを確認します。
9
Draemon

厳密な回転でペアリングします。

可能であれば、ドキュメント/コードベースを確認しながら、厳密なローテーションでペアリングを採用するようにしてください。つまり、2人が一定期間(たとえば2時間のセッション)一緒に座ってからペアを切り替えると、1人はそのタスクに取り組み続け、もう1人は別のパートナーと別のタスクに移動します。

ペアで両方の知識を習得し、ローテーションが発生したときにチームの他のメンバーに提供することができます。これの良い点は、新しいペアがまとめられると、タスクに取り組んだ人(この場合はコードを調査する)が概念をより簡単に理解できる方法で要約して説明できることです。時間の経過とともに、誰もが同じレベルの理解を得る必要があり、うまくいけば、「ああ、ジョンだけがコードのそのビットを知っている」症候群を回避する必要があります。

あなたのシナリオについて私が言えることから、これには十分な数(3ペア)がありますが、分散している場合、または同じタイムスケールで作業していない場合、それが可能になる可能性はほとんどありません。

7
Grundlefleck

その上でDoxygenを実行して最新のクラス図を取得してから、しばらくの間広めることをお勧めします。これにより、コードに近づいて汚れたときに使用できる全体像がわかりやすくなります。

6
Paul Nathan

私はそれがあなたがどんなタイプの学習者であるかに完全に依存することに同意します。そうは言っても、私は最初から非常に大きなコードベースを持っていた2つの会社にいました。通常、私は次のように動作します。

可能であれば、関数型コードを調べる前に、すでに作成されている単体テストを実行します。これらは一般的に非常に役立ちます。それらが利用できない場合、私は次のことを行います。

まず、実装をほとんど無視し、ヘッダーファイルのみ、またはクラスインターフェイスのみを調べます。各クラスの目的が何であるかを理解しようとしています。次に、最も重要と思われる領域から始めて、実装を1レベル深く掘り下げます。これを測定するのは難しいので、時々私はファイルリストの一番上から始めて下に向かって進んでいきます。私はこれを幅優先学習と呼んでいます。この最初のステップの後、私は通常、残りのコードを詳細に調べます。最初の幅優先探索は、インターフェイスレベルから得たアイデアを固め/修正するのに役立ちます。次に、深さ方向の外観は、システムの実装に使用されたパターンと、さまざまな設計アイデアを示します。深さ優先とは、基本的にデバッガーを使用してプログラムをステップ実行し、各関数にステップインしてその動作を確認することなどを意味します。これは明らかに大規模なシステムでは不可能ですが、20kLOCはそれほど多くありません。 :)

4
user29227

システムに精通している別のプログラマーと協力して、新しい機能を開発したり、バグを修正したりします。これは私が見た中で最もうまくいく方法です。

3
Avdi

これを特定のタスクに結び付ける必要があると思います。時間があるときは、気分に合ったアプローチを選んでください。

やらなければならないことがあるときは、自分自身に焦点を絞り、それを成し遂げてください。

2
KevDog

まず、コードの経験があるチームメンバーがいる場合は、コードの概要を説明するように手配する必要があります。各チームメンバーは、専門分野に関する情報を提供する必要があります。複数の人に説明してもらうことは通常価値があります。なぜなら、他の人よりも説明が上手な人もいれば、他の人よりも理解が上手な人もいるからです。

次に、プレッシャーなしでしばらくの間コードを読み始める必要があります(上司がそれを提供する場合は数日または1週間)。多くの場合、プロジェクトを自分でコンパイル/ビルドし、プロジェクトをデバッグモードで実行できるため、コードをステップ実行できます。次に、足を濡らし、小さなバグを修正し、小さな機能強化を行います。すぐに中規模のプロジェクト、そして後で大きなプロジェクトの準備が整うことを願っています。あなたが行くにつれてあなたのチームメイトに頼り続けてください-しばしばあなたはあなたを指導してくれる人を特に見つけることができます。

あなたが苦労している場合でも、自分自身に過度の負担をかけないでください-それは正常です。大規模なコードベースを理解するには、長い時間、場合によっては数年かかることがあります。実際、何年経っても、コードの一部がまだ少し怖くて不透明な場合がよくあります。プロジェクト間でダウンタイムが発生すると、それらの領域を掘り下げることができ、数回試行した後でもそれらの部分を理解できることがよくあります。

幸運を!

私も同じような状況でした。私はあなたがこのように行くと思います:

  • データベース駆動型アプリケーションの場合は、データベースから開始して、各テーブル、そのフィールド、および他のテーブルとの関係を理解し​​てください。
  • 基になるストアで問題がなければ、ORMレイヤーに移動します。これらのテーブルには、コードで何らかの表現が必要です。
  • それが終わったら、これらのオブジェクトがどこからどのように来ているかに移ります。インターフェース?どのインターフェース?検証はありますか?データストアに移動する前に、どのような前処理が行われますか?

これにより、システムに慣れることができます。単体テストを記述または理解しようとすることは、whatがテストされており、whyでテストする必要があることをよく知っている場合にのみ可能であることを忘れないでくださいonly =そのように。

また、データベースを対象としない大規模なアプリケーションの場合は、別のアプローチをお勧めします。

  • システムの主な目的は何ですか?
  • この問題を解決するためのシステムの主要なコンポーネントは何ですか?
  • 各コンポーネント間でどのような相互作用がありますか?コンポーネントの依存関係を表すグラフを作成します。すでに取り組んでいる人に聞いてください。これらのコンポーネントは相互に何かを交換している必要があるので、それらも理解してみてください(IOはFileオブジェクトをGUIに戻す可能性があるなど)
  • これに慣れたら、特に依存度が最も低いコンポーネントに飛び込みます。次に、そのコンポーネントがさらにクラスに分割される方法と、それらが互いにどのように相互作用するかを調べます。このようにして、合計で1つのコンポーネントのコツをつかむことができます
  • 次に依存度の低いコンポーネントに移動します
  • 最後に、すでに取り組んだ他の多くのコンポーネントに通常依存するコアコンポーネントに移動します
  • コアコンポーネントを見ていると、前に調べたコンポーネントを参照している可能性があるので、心配しないでください。

最初の戦略の場合: たとえば、このstackoverflowサイトの例を見てみましょう。データストア、何が保存されているか、どのように保存されているか、それらのアイテムがコード内でどのように表現されているか、UIのどこに表示されているかを調べます。それらはどこから来て、データストアに戻った後にどのような処理が行われるのか。

2つ目は ワードプロセッサの例を見てみましょう。どのようなコンポーネントがありますか? IO、UI、ページなど。これらはどのように相互作用していますか?さらに学習しながら進んでください。

安心する。書かれたコードは誰かの考え方であり、論理と思考スタイルを凍結し、その考え方を読むには時間がかかります。

2
Mohsin Shafique

チームに2週間(2週間ある場合)バグ修正を依頼してください。彼らは誰かにその責任を負わせて喜んでくれるでしょう、そしてその期間の終わりまでにあなたはおそらくそれをかなりよく知っているであろうライブラリで問題解決に多くの時間を費やしたでしょう。

2
Leigh Caldwell

ユニットテストがある場合(私はそうではないと思います)。小さく始めて、ユニットテストが失敗しないことを確認してください。コードベース全体を一度に見つめると、目が釉薬になり、圧倒されます。

単体テストがない場合は、必要な機能に焦点を当てる必要があります。アプリを実行して、機能が影響するはずの結果を確認します。次に、アプリが変更したいものをどのように作成するかを理解するために、コードを調べ始めます。最後にそれを変更し、結果が希望どおりに表示されることを確認します。

あなたはそれがアプリとライブラリだと言いました。まずアプリを変更し、ライブラリをユーザーとして使用することに固執します。次に、ライブラリを学習した後、変更するのが簡単になります。

トップダウンアプローチから、アプリにはおそらくすべてのアクションを制御するメインループまたはメインGUIがあります。アプリケーションの主な制御フローを理解することは価値があります。アプリのメインフローの概要を理解するために、コードを読む価値があります。 GUIアプリの場合は、どの画面があるか、ある画面から別の画面に移動する方法を示す紙を作成します。コマンドラインアプリの場合、処理方法。

企業でも、このアプローチを採用することは珍しくありません。多くの場合、アプリケーションがどのように機能するかを完全に理解している人は誰もいません。そして、人々はあなたを案内する時間がありません。彼らは特定の事柄についての特定の質問を好むので、あなたは自分で掘り下げて実験しなければなりません。次に、特定の質問を受け取ったら、アプリケーションのその部分の知識のソースを分離して質問することができます。

2
Cervo

ソースコードのリバースエンジニアリングツールを検討することをお勧めします。私が知っている2つのツールがあります:

どちらのツールも、ソフトウェア内のモジュール間の関係のグラフを生成する静的分析を含む同様の機能セットを提供します。

これは主に、コールグラフと型/クラスの品位で構成されています。この情報を表示すると、コードの各部分が互いにどのように関連しているかをよく理解できるはずです。この情報を使用して、最も関心があり、最初に理解/変更する必要があるパーツの実際のソースを掘り下げることができます。

2
Doug

「問題ドメイン」を理解することから始めます(それは給与システムですか?在庫ですか?リアルタイム制御など)。ユーザーが使用する専門用語を理解していないと、コードを理解できません。

次に、オブジェクトモデルを見てください。ダイアグラムがすでに存在する場合や、ダイアグラムをリバースエンジニアリングする必要がある場合があります(手動で、またはDougが提案するツールを使用して)。この段階で、データベース(存在する場合)を調査することもできます。オブジェクトモデルに従う必要があるが、従わない場合もあります。これを知っておくことが重要です。

変更履歴またはバグデータベースを確認してください。頻繁に発生する領域がある場合は、最初にそのビットを調べてください。これは、それがひどく書かれているという意味ではありませんが、それは誰もが使用するビットです。

最後に、いくつかのメモを保管してください(私はウィキが好きです)。

  • 既存の人はそれを使用して、あなたの仮定をサニティチェックし、あなたを助けることができます。
  • 後で参照する必要があります。
  • チームの次の新しい男は本当にあなたに感謝します。
2
Robin Bennett

Doxygenのようなツールを使用してクラス図を取得し、最初に全体像を理解する必要があるというすべての回答が好きです。私はこれに完全に同意します。

とは言うものの、これはコードが最初にどれだけうまく因数分解されているかに大きく依存します。それが巨大な混乱であるならば、それは学ぶのが難しいでしょう。きれいで、適切に整理されていれば、それほど悪くはないはずです。

1
dicroce

テストカバレッジツールを使用して、その機能がどこにあるか、またはそれが多くのモジュールにどのように分散しているかについて何も知らずに、関心のある機能のコードを見つける方法については、 この回答 を参照してください。

1
Ira Baxter

コードに飛び込むだけでも少し圧倒されるかもしれません。設計に関するドキュメントをできるだけ多く読むようにしてください。これにより、各コンポーネントの目的と構造が説明されることを願っています。既存の開発者がそれを理解できるのであれば最善ですが、それが常に可能であるとは限りません。

コードの高レベルの構造に慣れたら、バグを1つか2つ修正してみてください。これは、実際のコードを理解するのに役立ちます。

1
Dave Turvey

(今後の恥知らずなマーケティング)

nWire をチェックアウトする必要があります。これは、大規模なコードベースをナビゲートおよび視覚化するためのEclipseプラグインです。多くのお客様は、主要なフローの視覚化を印刷することにより、新しい開発者に侵入するためにそれを使用しています。

0
zvikico