コーディングの経験はほとんどありません。作業を始めた後は、ほとんどの場合、他の人のコードに取り組み、既存の機能に新しい機能を追加するか、既存の機能を変更します。実際のコードを書いた人は、私の会社ではもう機能しません。私は彼のコードを理解し、自分の仕事をするのに苦労しています。コードを変更しようとするたびに、何らかの形で作業機能を台無しにしています。他の人のコードを操作する際に注意すべきことは何ですか?
コーディングの経験はほとんどありません。作業を始めた後は、ほとんどの場合、他の人のコードに取り組み、既存の機能に新しい機能を追加するか、既存の機能を変更します。実際のコードを書いた人は、私の会社ではもう機能しません。私は彼のコードを理解し、自分の仕事をするのに苦労しています。コードを変更しようとするたびに、何らかの形で作業機能を台無しにしています。他の人のコードを操作する際に注意すべきことは何ですか?
回答:
コードには単体テストがありますか?そうでない場合は、追加を開始することを強くお勧めします。この方法で、新しい機能/バグ修正をテストの失敗として記述し、テストが合格するコードを変更できます。ビルドするものが多ければ多いほど、追加したコードが他の何かを壊していないという自信が高まります。
完全に理解していないコードの単体テストを作成すると、そのコードを理解するのに役立ちます。もちろん、機能テストがまだ存在しない場合は追加する必要があります。私の印象では、OPの質問からはすでに存在していたということです。その点で私が間違っている場合、これらの機能テストはあなたの最初のステップでなければなりません。
Eagle76dkは、この作業を行うためにマネージャーを迎え入れることについて素晴らしい点を示しています。詳細はEagle76dkの投稿にあります。
さらに、これらのテストを作成する際には、コードの動作ではなく、メソッドが達成しようとしたビジネス動作を検証するようにテストを作成することをお勧めします。また、コードに表示されるビジネス行動が正しいものであるとはまったく考えないでください。アプリケーションが何をすべきかを伝えることができる人がいる場合、それは多くの場合、コードが示すことよりも価値があります。
単体テストについて言及した別の回答に加えて、変更を簡単に元に戻すことができるように、すべてがバージョン管理されていることを確認することをお勧めします。そして、コードを保守しやすくするために小さな変更を加えます。
私の意見では、他の人のコードを学習する最も速い方法は(特に、変更が説明するような予期しない動作を引き起こす場合)、デバッガを使用してコードをステップ実行することです。
プログラムのメインループ/メインメソッドと思われるものをステップスルーすることから始めます。使用にステップをし、ステップアウトの異なる方法が何をするか見るために機能します。これにより、コードの一般的な構造がわかります。
その後、プログラムのさまざまな部分をより深いレベルでステップスルーして学習することにより、分割して征服します。ほとんどのデバッガでは、変数とその現在の値を調べることができます。それらがいつどのように変化するかを研究します。
関心のある動作をトリガーするメソッドにブレークポイントを設定します。たとえば、プログラム内のテキストを変更しようとして、テキストが元の値に戻り続ける場合、テキストが変更されるすべての場所にブレークポイントを設定するか、これらすべての変更を1つのメソッドに移動します。呼び出しスタックを使用して、このメソッドの呼び出し元などを確認します。
コードの行を変更すると、他の場所で予期しない変更が発生し、その行にブレークポイントを設定し、たとえばスコープ内の現在の変数の値を確認したり、ステップインを使用したり、呼び出しスタックを使用して呼び出しが来ました。
これを行うことで、コードの構造を驚くほど早く学習し始めます。私はあなたが私の最初のプログラミングの仕事であなたと同じように始めました。何年も前に書かれ、何年もの間多くの人々によって変更された多くのコードでした。他の人が同時にコードを扱っているので、コードは私のものではありませんでした。その時点ですべてを書き直すことはできませんでした。そのすべてのコードのテストを書くのに数ヶ月から数年かかりました。デバッガは本当に私を救った、それなしでコードをどのように学んだかわからない...
他の人のコードが悪臭を放つと仮定するのは早すぎないでください。
しかし、常に疑わしい。
しかし、他の開発者のコードを理解するには時間がかかります。システムの複数の部分で関数またはオブジェクトを使用するほど、注意する必要があります。症状に近い問題を解決できる場合、それが役立つ場合があります。たとえば、データが配信された後、他の何かが発生する前に、フェンスの問題オブジェクト側の別のオブジェクトからの着信データを正規化します。
あるものを変更すると、別のものが予期せず壊れる場合、それは悪い兆候です。他の経験豊富な開発者が助けを求めている場合は、問題の原因となっているものを調べてもらうことをお勧めします。少なくとも、デバッグを見ているものをいくつか拾うことができます。
理想的な世界では、特定の開発者によって書かれたすべてのコードは、ユニットテストなどの自動ツールと、ユーザーが期待どおりの結果を得るために実行するユースケーススクリプトの両方を使用して、十分に文書化され、構造化され、包括的にテストされます。
ただし、最初に学ぶことは、私たちは理想的な世界に住んでいないということです!
多くの開発者は自分のコードを適切に文書化しません。ビジネスロジックと無関係なコードを混ぜる場合でも、彼らが行う唯一のテストは、通常のユースケースと思われるものをすばやく実行することです。
このようなコードを使用する場合、最初に行う必要があるのは、それが何を意味するのかを確立することです。コメントがある場合、彼らはあなたに手がかりを与えるかもしれませんが、それを頼りにしないでください。私の経験では、多くのコーダーは自分自身を説明するのが苦手で、コメントを残しても意味がないかもしれません。ただし、あなたが会社で唯一のコーダーでない限り、誰かが少なくともコードの目的とその目的を基本的に理解している必要があります。周りに聞いてください!
単体テストがある場合、それらはあなたの人生を非常に簡単にします。そうでない場合は、コードベースの学習の一環として、既に存在するコードの単体テストを作成する必要があります。通常、既存のコードに適合するように単体テストを作成すると、コードがそのまま機能すると考える単体テストになります(実際にはバグであると想定して動作するように記述されるため、これは良いプラクティスとは見なされません正しい)が、少なくともそれはあなたにベースラインを提供します。後で正しいと思った動作が実際に間違っていることがわかった場合は、ユニットテストを変更して、コードが現在示している結果ではなく、期待される結果をテストできます。単体テストを取得したら、変更を加えて、変更による副作用を評価できます。
最後に、文書化されていないコードを扱う際に持っている最良のリソースは、エンドユーザーに尋ねることです。彼らはコードについて何も知らないかもしれませんが、アプリケーションに何をしてほしいかを知っています。要件収集はプロジェクトの最初の段階であり、開発されるシステムの見込みユーザーと話すことは常に重要な部分です。それは、たまたますでに構築されたばかりの新しいプロジェクトの要件取得段階を実行していると考えてください。
よく書かれ、十分に文書化されたコードであっても、部外者が理解するのは難しい場合があることに留意してください。コードは本質的に、それを書いた人が当時どのように考えていたかを表現したものであり、誰もが独自の独自の思考プロセスを持っています。あなたは少し忍耐強く、探偵になることを学ぶ必要があります。他の人の思考プロセスに入ることは困難ですが、既存のコードのメンテナンスを行うプログラマにとって不可欠なスキルです。ほとんどのコーディング(約70%)は既存のコードの維持に関連しているため、学ぶことは重要なスキルです。
ああ、そして今、あなたは、文書化されていない、テストされていない、ごちゃ混ぜのコードが引き起こす痛みを目にしました。:)前任者の間違いから学び、コードに十分なコメントを付け、すべてのモジュールに明確に定義された責任を負わせ、最初に記述する(TDD方法論の)ユニットテストの包括的なセットがあることを確認します。少なくとも開発中のコードと一緒に。
書いていないコードを読む能力は非常に価値のあるスキルであり、おそらくコードを書くよりも価値があることを覚えておいてください。残念ながら、これは広く控えめであり、学校で教えられていない。
私が言おうとしているのは、最初にコードを読んだときにコードを常に理解しているとは限らないということです(最初に完璧なコードを書かないのが普通であるように)。外国のコードを取得するのに時間がかかることを受け入れた場合、余分な努力を払ってもかまいません。簡単な要約:
単体テストは理想的ですが、常に現実的ではありません。特に、重度の官僚主義を持つ大規模な組織で働く場合。
バージョン管理システムを適切に使用する方法を学びます。既存のものを壊すことは決してないでしょう(実際には決してそうではありませんが、良い安全策です)。
すぐに理解できないからといって、それが悪いと思い込まないでください。それが機能するという理由だけで良いと思い込まないでください。重要なことは、以前のメンテナーのコードのスタイルを理解し、追加した行を彼のスタイルに適合させることです。メンテナはあなたに感謝します。
残念なことに、一部の企業では、コードを読むことの難しさを過小評価する可能性があります。これは、厳格なプロセスを持つ大企業で一般的です。多くの場合、(暗黙的に)クリーンなものを書くのに時間をかけるよりも、迅速に動作するコードをプッシュすることを好みます。この点に関してあなたのチームがどこに立つかを決めるのはあなた次第です。
最後に、コードの読み取りがスキルであることを決して忘れないでください。あなたがそれをやるほど、あなたはそれをより良く得るでしょう。別の言い方をすれば、それを上手に使うには、何度も練習するしかありません。前述のように、コードを読むことは、書くことよりもあなたの仕事の大部分を占めます。
意図せずに破損する問題に関するあなたの問題から判断すると、コードは自動化されたテストでカバーされていないと仮定します。ステップ#0は、Michael Feathersによる「レガシーコードを効果的に使用する」をすぐに注文して読むことです。それは非常に貴重です。
私が提案する基本的な手順:
テストのフレーバー(ユニット、統合など)を指定することは意図的に省略します-何らかの種類の自動テストカバレッジを取得します。
(そして、はい、レイアウトと命名の観点からコーディングスタイルに従います)
前述のように、実世界へようこそ。以前の回答にのみ同意できます。私は時間の見積もりについての私の実務経験で答えを広げたいだけです。
上司を明確にするための良い提案です。他の開発者の考え方を学ぶのに時間がかかります。通常、現在のソリューションは多くの場合、開発者の年齢と経験に依存することを経験します。
運がよければ、手元のタスクを分析する必要があり、ドキュメントを理解することは大いに役立ちます(しかし、これは多くの場合そうではありません)。
私の経験では、他のコードを変更するときは、現在のタスクに関係しないコードを変更しないようにしてください。より良い解決策を知っているか、より直感的な方法で記述できますが、変更すると次のような問題が発生することがよくあります。
しかし、あなたが違うと思う何かを見たら、あなたの上司に話すことをheしないでください(それはあなたが考えることができることだけを示します)。
最後に、ソリューションを作成するのに十分な時間があることを確認してください。より高速なソリューションには経験が必要です。しかし、これがエラーやメンテナンス不可能なコードの最初/主要な理由であるため、高速なソリューションはほとんどありません。
それは、人に対して操作を実行するようなものだと考えてください。
修正する必要のある問題を内側から見ると、ほとんどの動脈などが意図したとおりに設定されていないことに気づきます。したがって、自分に合った外観になるまでそれらを切り刻み、問題を修正します。
驚くべきことに、患者はほとんどすぐに死にます。
レガシーアプリケーションは同じです。それらにはすでに作業方法があります。ソフトウェアのさまざまなコンポーネントとそれらが互いにどのように関連しているかを理解し、同じように機能するように変更を加える必要があります。あなたの創造性を発揮させるのはエキサイティングではありませんが、個人的なプロジェクトでそれを行うことができます。
上級エンジニアに毎週月曜日に1時間ほど座って、システムのさまざまな側面を説明してもらいます。彼が言ったことをメモし、そのメモを上司とあなたの上司にメールで送信して、上司が何か追加するものがあるかどうかを確認します。この方法で非常に迅速に速度を上げる必要があります。
物事を壊さない方法については、まずシステムが何をするのかを理解してください。前にテスト-変更を加えます-後でテストします。魔法の公式はありません。あなたが経験を積むにつれて、あなたは良くなる-または解雇されると思います!
私が実際に見ていないことの1つは、ここで触れました- 島で働いてはいけません。
あなたがあなたの服装で唯一のプログラマーでない限り、あなたよりも多くの経験を持っている人がいるはずです。
質問をする。それらの多くは。
他の誰かを「困らせる」ことを心配しないでください(理由の範囲内で)-通常の開発サイクル中に、後で実稼働環境で火を消す必要があるよりも、誰かが質問を1つまたは2つ中断します。
何かをチェックインする準備ができたら、メンターに確認してください。彼らは何かが他の何かを壊すかどうかだけでなく、もっと重要なのはなぜかをあなたに伝えることができるはずです。また、コードを確認すると、メンターはより優れたプログラマーになり、システムをよく見ることができます。
覚えておいてください-あなたは、新しい従業員がする必要があるようにシステムを学習しているだけでなく、プログラマになる方法を学習しているのです。
そして5年後、次のニューガイがあなたをメンターとして使うことを奨励します。
コードのデバッグに関しては、常に理由があります。数日間、同じ愚かなバグを見つけて修正しようとしていて、何も進展していない場合、次の1つ以上を考え始めようとします。
私はこのコードがどのように機能するかを理解するのに十分ではありません
このコードを書いた男は、彼が何をしていたのか分かりませんでした
魔法が関与している:非常に黒い魔法
それらはすべてあきらめる形です。解毒剤は、コンピューターが決定論的であることを常に覚えておくことです。コンピューターが何をするかには常に理由があります。コードは魚の缶詰の干潮のような匂いがし、リングイネの巨大なボウルに似ていますが、容赦なく合理的で心を開いておくと、それを理解できます。
可能であれば単体テストを作成する場合でも、変更するコードを含む小さなアプリケーションを作成する場合でも、ロジックを調べて理解し、文書化する必要があります。
コードがほとんど動作する場合(動作するように聞こえます)、そのモジュールのコードの書式設定のスタイルは、それがあなたのスタイルであるかどうかに関係なく保持されます。物事を均一に保ちます。ただし、良いコメントは決してスタイルを損ないません。
生産を中断することなく、このコードを変更およびテストできるテストシステムとテストプラットフォームをお勧めします。
ライブラリの作業をしていない限り、コードの要素をライブラリに削除できるなら、私はそれをするでしょう。
時間の経過とともに、ロジックを理解したら、書き直してテストできます。
このアドバイスは、使用している言語、テストベッドを取得する機能、およびその他の制約によって決まります。
上記では、コードの詳細だけでなく、システムの目的を理解する必要があると述べました。注文入力システムを作成するのに十分な経験を持つプログラマーは、一般に、製品の選択、請求書のフォーマット、および支払いの処理を含む「前進」部分に慣れています。行き詰まるのは、ユーザーが「気にしない」と判断してトランザクションのバックアウトを開始したとき、または支払い処理でエラーを犯して「戻る」ボタンを押したときです。その時点で、多くのプログラマーが混乱に陥ります。なぜなら、コードが「どこからともなく現れる」のを見て、なぜそこにあるのかわからないからです。
要するに、「通常のフロー」だけでなく、誰かがミスをしたり考えを変えたりする場合に必要なすべてのバックトラッキングを理解する必要があります。これは、一部のコードが特定のアカウント特権でしか実行できないスーパーバイザーオーバーライドではさらに悪化します。
誰かが1年に10,000行のコードを記述し、アプリケーションに10年間の「寿命」がある場合、他の誰かの作業を担当するプログラマーは100,000行のコードを理解する必要があります。これを1ページあたり50行で除算すると、2000ページになります。プログラムが設計パターンに従って記述されている場合、プログラマーは、1つの「ブロック」を理解することで、残りのほとんどを少なくとも一般的に理解できることに気付くでしょう。そうでない場合は、最後のすべての行を読む必要があります。
一部のプログラマーは「言われたとおりにやる」だけで、スパゲッティを書きます。彼らは「全体像」を決して理解しません。ユーザーが苦情を言うと、単に修正します。このような状況では、適切なパターンにできる限り移行することをお勧めします。最終的に、これは「壊れていない」ものを再コーディングすることを意味する場合があります。心配する必要はありません。それがあなたのプロジェクトである限り、次第に保守性が向上するようにしてください。
ここには本当にいい答えがあります。しかし、優れたデザインパターンにどれだけ精通していれば、既存のコードを(十分に記述された)読み、読み取り可能なコードを書くことができるかを言及する価値があると思います。
もちろんSomethingFactory
、既存のコードでに遭遇すると、非常に混乱する可能性がありますが、これは実際にはファクトリーパターンに従いません。しかし、チームとフレームワークが許す限り、このようなケースを最小限に抑えることが有益な場合があります。
設計パターンに従うこと(ビジネスニーズが許す場合)により、コードの重複を大幅に減らすことができ、その結果、将来の変更のバグを減らすことができます。
デザインパターンに関する優れた情報源は次のとおりです。
http://sourcemaking.com/design_patterns
そしてもちろん本
http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612
メソッド間の制御の流れを追跡することは、ビジネスロジックのメンタルマップを作成する上で非常に重要です。
私たちのソリューションは、レガシーシステムに接近するときに利用できる数少ない信頼できる情報の1つが、実行中のシステム自体であるという認識に基づいています。このアプローチでは、実行トレースを具体化し、ロジックプログラミングを使用してそれらのテストを表現します。
すべてのコードパスを分析するには、ワークフローデータモデルを生成するのが最善の方法です。
実際には、従来の科学的ワークフローではコードレビューが扱いにくくなります。このようなワークフローの起源は、ソフトウェアエンジニアリングのプラクティスが開発中に適用されなかった可能性があることを意味しており、コードベースが事実上難読化されています。静的分析はデータフロー分析の手法を十分に開発しましたが、現実のワークフローでの動作をサポートすることはできません。たとえば、データの処理方法を決定するために構成ファイルをロードする必要がある場合や、動的コード評価を使用する場合などです。
ワークフローを視覚化することは理想的です。
視覚的な開発に役立つ一般的なモチーフは、ワークフローをグラフとして表示することです。これにより、リソースと実行の根本的な複雑さからユーザーが保護されます。
参照資料