私たちのコードはひどいもので、私にはそれを修正する力がありません。ヘルプ![閉まっている]

StackOverflow https://stackoverflow.com/questions/3618581

質問

私たちのコードは最悪です。実は、それをはっきりさせておきます。私たちの 古い コードは最悪です。デバッグが難しく、理解している人も覚えている人もほとんどいない抽象的な概念がたくさんあります。ちょうど昨日、私は自分が担当していた分野でデバッグに 1 時間を費やしました 1年以上 そして、"うわ、これは本当に苦しい "と思っている自分に気づいた。 誰のせいでもない。最初はすべて完璧に理解できたはずだ。最悪の部分は通常、それがただうまくいくことです...ただし、コンフォートゾーンの外で何かをするように要求しない限り。

新しいコードはかなり優れています。私たちはそこでたくさんの良いことをしていると思います。それは明確で一貫性があり、(うまくいけば)保守可能です。継続的インテグレーションのために Hudson サーバーを実行し、単体テスト スイートの開始部分を準備しました。問題は、私たちの経営陣が新しいコードを書くことに集中していることです。古いコード (または古い新しいコード) に、切実に必要な TLC を与える時間はありません。常に、スクラム バックログ (開発者 6 人分) には約 140 項目と約 12 個の欠陥があります。そして、その数字はあまり変わっていません。私たちはできるだけ早く何かを追加しています。

では、古いコードの深みにはまり込んで長時間にわたるデバッグ セッションの頭痛の種を避けるにはどうすればよいでしょうか?すべてのスプリントには、新しい開発と重大な欠陥が満載です。具体的には...

  • メンテナンスとリファクタリングのタスクを十分に高い優先度で実行できるようにするにはどうすればよいでしょうか?
  • 新しいコードがすぐに腐ってしまうのを防ぐために採用している C++ 特有の戦略はありますか?
役に立ちましたか?

解決

経営陣は、機能を製品に組み込んで機能し続けることに重点を置いているかもしれません。この場合、古いものをリファクタリングするためのビジネスケースを作成する必要があります。つまり、時間と労力を X 投資することで、必要なメンテナンス時間を Z 期間にわたって Y 削減できるということです。あるいは、経営陣が根本的に無知である可能性もあり (このようなことは起こりますが、ほとんどの開発者が考えているよりも頻度は低くなります)、その場合は許可を得ることができません。

ビジネスの観点を見る必要があります。エンドユーザーにとっては、コードが醜いかエレガントかは関係なく、ソフトウェアが何をするかだけが問題です。悪いコードの代償として、信頼性が潜在的に低くなり、変更がさらに難しくなります。それがプログラマーに引き起こす精神的苦痛はほとんど考慮されていません。

リファクタリングの許可が得られない場合でも、いつでも自分で少しずつ試すことができます。バグを修正するときは必ず、内容を明確にするために少し書き直してください。これは、特にコードが動作することを確認する場合に、最小限の修正よりも高速であることが判明する可能性があります。そうでない場合でも、通常は、トラブルに巻き込まれることなく、バグ修正にもう少し時間をかけることができます。ただ、調子に乗らないでください。

毎回少しずつ改善されたコードを残すことができれば、ずっと気分が良くなるでしょう。

他のヒント

スタンドアップミーティング

整備士のところに行って、午前中にちょっとしたスタンドアップミーティングをするかもしれません。

ホイールのアライメントを調整してほしいと伝えた、 タイヤをローテーションし、オイルを交換した。私は「そういえば、私の ブレーキが少しソフトに感じた にある。[彼]はそれらを見てもらえますか?どのくらいで車を取り戻せますか? 仕事に戻らなきゃいけないの?

彼は私の車の下に頭を突っ込んできた。 ブレーキが漏れていると言ってきた オイルが漏れて故障し始めた。彼が必要とするのは 午前10時30分に到着する部品。彼の部下は昼食までには終わらないだろう。 午後1時30分までには車を取り戻さなければならない。 だからブッキングが固まっているので、彼は来ないだろう 他のどんなこともできる 今日もまた予約しなければならない。 を任命した。

他のこともできるかと尋ねると 私はブレーキを踏みに戻る。彼は私に言う。 からの運転は本当にさせられない。 ブレーキを直さずに 事故を引き起こす可能性があるからだ、 しかし、もし私が他の メカニックがレッカーを呼んでくれる。

車はまもなく完成するので 昼食の後、私は彼の部下に 遅めの昼食で車を取り戻す その1時間前だ。

彼の部下が朝8時に来て、こう言うんだ。 夕方まで働くことも多い。彼らはすべての休憩を獲得する そして、彼の部下は、その部下にふさわしい。 みんなと一緒に昼食をとる。

どれも私が聞きたかったことではありません。ホイール、タイヤ、オイルを準備して30分以内にそこから車で出発するということを聞きたかったのです。

私のメカニックは正直で正直でした。 あなたは経営陣に対して率直かつ誠実ですか? それとも、彼らが聞きたくないことを彼らに話すことを避けますか?

単体テスト

私は理解していないコード行には触れませんし、徹底的にテストしていないコードの新しい行をチェックインしません。(少なくとも意図的にではありません。)

あなたの質問は、文書化が不十分なコードの大規模なコーパスが単体テストなしでレビューを通過したことを示唆しているようです。あなたはそれに参加したかもしれないし、参加しなかったかもしれません。経営陣も含め、関係者全員がその責任を受け入れる必要があります。とにかく、終わったことは終わった。戻って変更することはできません。

しかし、今、この時代において、それは全員の責任です。 行為をやめる それがそもそも問題を引き起こしました。あなたは、理解するのが難しく、単体テストのないコードに 1 年間取り組んだと言いました。この一年間、皆さんは理解を深めようと懸命に努力し、 文書化してその理解を確認するために単体テストを何回書きましたか?

コードを苦労して少しずつ理解できるようになったとき、次回苦労しないようにするには、コメントをいくつ追加しましたか?

スクラムバックログ

個人的には、「スクラム バックログ」という用語は誤った呼び名だと思います。やるべきことのリストは単なるリスト、言ってみれば買い物リストです。整備士に行ったときにリストを持ってきました。メカニックとのスタンドアップミーティングは、実際にはスプリント計画のミーティングのようなものでした。

スプリント計画会議は交渉です。経営陣がその交渉なしでタイムボクシングをしているとしたら、彼らは何も管理していません。彼らは5ポンドの袋に10ポンドのクソを詰め込もうとしているだけであり、彼らにそう伝えるのはあなたの責任です。

スプリント計画会議に出席すると、一連の作業に取り組むことが期待されており、その準備をするのはあなたの責任です。準備とは、リストの各項目を完了するために何をしなければならないかをある程度把握することを意味します。これには、難解なコードを理解するのにかかる時間や単体テストの作成にかかる時間も含まれます。

誰かがあなたを準備する時間がない計画会議に招待した場合は、会議を辞退し、時間を確保できるようにいつスケジュールを変更するかを提案してください。

単体テストのない既存のコード本体があり、機能がそのコードの動作に影響を与える可能性がある場合は、影響を受ける可能性のある古いコードのすべてに対して単体テストを作成する必要があります。機能の作成に取り組むということは、その作業を行うことに取り組むことになります。他の機能に取り組む時間があまりにも足りない場合は、そう言ってください。他の機能にはコミットしないでください。

欠陥の修正を約束するということは、自分の作業をテストすることを約束することになります。明らかに、それは欠陥に対する単体テストを書くことを意味します。ただし、単体テストのない古いコードが含まれる場合は、まだ壊れていないものの、変更によって壊れる可能性があるものに対する単体テストを作成することも意味します。他にどのように修正をテストしますか?

欠陥リストのサイズが一定のままだと、チームは修正した分だけ後退します。現在、欠陥リストの縮小を妨げているリグレッションは単体テストによって防止されることを、理解する必要がある人に丁寧に説明してください。

コミットする機能が多すぎるために単体テストの作成に失敗した場合、 それは誰の責任ですか?

リファクタリング

コードをリファクタリングするときは、コードすべてをテストする必要があります。これは、コードすべてに対して単体テストを作成することを意味します。単体テストのない大量のコード本体がある場合は、それらの単体テストをすべて作成する必要があります。 前に リファクタリングをします。

これらの単体テストが準備されるまでは、リファクタリングを控えることをお勧めします。それまでの間、あなたがコミットする作業の見積もりに単体テストを含めることを主張すると、最終的にはすべての単体テストがそこに含まれることになります。そして、リファクタリングすることができます。

唯一の例外は、テスト容易性のためのリファクタリングです。コードの一部はテスト用に設計されていないため、単体テストを作成する前に依存関係挿入などのリファクタリングが必要な場合があります。単体テストを必要とする機能の作成に取り組むときは、コードをテスト可能にすることに取り組むことになります。機能を利用する際には、それを見積もりに含めてください。

コミットメント + 責任 = 力

あなたは自分が無力だと言います。責任を受け入れ、やるべきことに取り組むと、必要な力がすべて備わっていることがわかると思います。

追伸単一の欠陥を修正するために複数の単体テストを書いて「時間を無駄にしている」という人がいる場合は、その人に見せてください。 80:20 ルールに関するこのビデオを見て、彼らの脳に「欠陥クラスター」を叩き込みます。

あなたが提供する情報から多くを伝えることは困難です。新しいコードを作成する論理的な理由は、古いコードを置き換えるためであるという疑問がいくつかあります。そのような場合は、古いコードを放棄してください。

重大な欠陥がある古いコードでもあるのでしょうか?もしそうなら、彼らはどこから来たのでしょうか?古いコードには「重大な」欠陥はなく、通常はどんどん停止に近づいていくだけです。結局のところ、それは古いコードです。同じ古い欠陥と同じ古い制限があるはずであり、すぐに検討する必要があるものではありません。重大な欠陥は新しいコード欠陥です。古いコードで活発な開発が行われているようです。

最悪の古いコードの上に新しいコードをすべて書いていて、それを完全に修正する予定もないのであれば、申し訳ありませんが、自分を埋めるのに忙しすぎて自分を掘り出すことができない場合、できることは限られています。

後者の場合。自分がどこに向かっているのかを認識し、少し距離を置いてみる必要があります。最終的にはすべてが崩壊するでしょう。もしここに留まるつもりなら、価値ある戦いのために力を温存してください。

それまでの間、いくつかのデザインパターンをピックアップしてみてください。少なくとも新しいコードを古いコードから守るのに役立つものはいくつかありますが、それでも最終的には、悪いコードに対して良いコードを書くのは難しいだけです。

そして、あなたのスプリントはおそらく混乱しているように聞こえます。全体的な方向性は無いのでしょうか?それによって、どれだけのバックログがあるかが決まるはずです。状況は月ごとに変わる可能性がありますが、何らかの最終目標に向かって進んでいるという明確な感覚はありませんか?

そして、新しいコードは腐っていますか?それを防ぐには、意味のあるデザイン、意味のある方向性、そして仕事の品質とデザインのビジョンの両方に熱心に取り組む質の高いチームを用意する必要があります。それがあれば、規律が品質を維持します。申し訳ありませんが、あなたはすでに何の目的もなくコードを書いていることになります。基本的に蔓の上で腐っていました。

批判的ではなく、ただ正直になろうとしているだけです。深呼吸する。減速する。あなたにはそれが必要なようですね。あなたがここに書いたことを見てください。それは何も語らない。あなたはリファクタリング、スクラム、ショーストッパー、欠陥、古いコード、新しいコードについて話します。それはどういう意味ですか?それはすべてごちゃ混ぜです。

「新しい取り組みと従来のシステム」についてはどうでしょうか?"最新の理解などの観点から、スプリントサイクル初期のコードをリファクタリングする必要がある" ショーストッパーの実態は、「現在の企業イニシアチブの初期のコンポーネントはリリースされているが、問題が発生しており、新たな開発のために時間が予算化されていない」。

これらは意味のある概念となるでしょう。あなたは私たちに何も与えてくれませんでした。激しいのは分かります。私のスプリントもクレイジーです。多くの要件を事前に取得できなかったため、多くの back;pg 項目を追加しました (新しい要件の多くは、外部の規制機関とも争わなければならないことから生じており、通常のビジネス プロセスが常に利用できるわけではありません) )。

しかし同時に、やらなければならないことの大きさと、それをやるまでの時間に打ちのめされます。バックログに追加されたものはすべてそこに存在する必要があります。クレイジーなことですが、同時に、自分がこれまでどこにいたのか、どこに行く必要があるのか​​、そしてなぜ道がますます困難になっているのかについて非常に明確な考えを持っています。

一歩下がって、思考をクリアにして、自分がこれまでどこにいたのか、どこに行くのかを考えてみましょう。なぜなら、それを知っていても、それは明らかではないからです。同僚が理解できる内容を何も伝えられない場合、経営者とどこまで話ができるでしょうか?

古いコードはいつも最悪です。カーニハンやトンプソンのような名前の人が書いた例外もおそらくいくつかありますが、典型的な「オフィスで書かれたコード」のものは、時間が経つにつれて悪臭を放つようになります。開発者はより経験を積んでいきます。継続的インテグレーションなどの新しいプラクティスは状況を変えます。物は忘れ去られる。新しいメンテナは設計を理解できず、書き直しを望みます。したがって、これを通常のこととして受け入れてください。

役に立つかもしれないいくつかのランダムなもの...

  • それについてチームと話し合ってください。「古いコードはクソだ」ということを (明白な理由から) 回避しながら、経験や懸念を共有し、コンセンサスがどうなるかを確認してください。おそらくあなたは一人ではありません。
  • マネージャーのことは忘れてください。このレベルの詳細をユーザーに公開しないでください。新しいものと新しいものについて考える必要はありません。古いコードなので、理解してもおそらく理解できないでしょう。これはチームが取り組むべき問題であり、必要に応じて PO に認識させる必要があります。
  • 物を捨てられるかもしれないという可能性を受け入れてください。その古いコードの一部は、おそらくもう使用されなくなったか、そもそもユーザーに採用されなかった機能に関連していると考えられます。これを機能させるには、さらに上のレベルに進み、コードが実際にユーザーまたはビジネスの価値を提供するのと、コードが実際に提供するのはどこなのかという観点から考える必要があります。それは誰も決断を下す勇気のない単なる泥の塊です。あえて挑んだ者が勝つ。
  • アーキテクチャの一貫性に対する見方を緩和してください。動作中のシステムを新しいコードで利用する方法は常にどこかにあり、それにより、既存のものを壊さない程度に古いものを維持しながら、より新しく、よりスマートなアプローチにゆっくりと移行できる可能性があります。

全体として、この種の状況で勝つには、コーディング スキルよりも、賢明な選択と人間的側面の処理が重要です。

それが役立つことを願っています。

「古いコード」に関係するバグやコード変更の数を追跡し、それを次回のチーム会議でマネージャーまたは同僚の開発者に提示することをお勧めします。これを理解すれば、「古いコード」をリファクタリングして「新しいコード」と同等にするにはさらに多くのことを行う必要があることを彼らに納得させるのに十分簡単であるはずです。

「古いコード」の最も理解しにくい部分を文書化することも賢明です。これらは、承認を得たら最初にリファクタリングする必要がある「古いコード」の部分でもあります。

試してみたいこと:クラスを、たとえば、最悪の 10%、最良の 10%、および残りにグループ化します。次の四半期のバグの大半は、最初のセットで発見されるでしょう」と言いながら、リストを経営陣に提出する。 長さに基づく、 循環的複雑さ, 、テストカバレッジ - 便利で快適なツールであれば何でも。それから、座って見守ってください - そして正しいことをしてください。これで、ある程度の信頼性が得られ、「バグやメンテナンスのコストを削減するために、悪いコードを改善するためにリソースを投資したいのですが、そのエネルギーをどこに投資すればよいかわかります。」というときに、ある程度の活用力が得られます。

新しいコードがどのように機能するか、クラスと関数が相互にどのように関連しているかを示す図やスケッチを作成できます。FreeMind または Dia を使用することもできます。そして、私はコードを文書化してコメントすることに間違いなく同意します。私もかつてこれで悩んだことがありました。私は自分の言語用に J2ME のフォント クラスを作成しました。もしかしたらあなたのコードにも見られるかもしれないこれらの理由により、これはひどいものでした。

  • コメントやドキュメントはありません
  • オブジェクト指向性が低い
  • 不正な変数/関数名
  • ...

しかし、数か月後、もう一度すべてを書かなければならなくなりました。今では、時には非常に長い、意味のある変数名を使用することを学びました。コードを書くよりもコメントを書きます。また、プロジェクトのクラスとそれらの関係に図を使用します。

それが本当の答えかどうかはわかりませんが、私にとっては間違いなく役に立ちました。また、古いコードの場合は、機能を思い出したときに実際に全体を読み直してコメントを追加する必要があるかもしれません。

お役に立てば幸いです。

プロダクトオーナーに相談してください!古いコードのリファクタリングに時間を費やすことで、この障害が取り除かれれば、新しい機能に関するチームの速度が向上するというメリットがもたらされることを説明します。

上記の優れたアプローチ以外にも、次のアプローチを試すこともできます。

将来のコードをクリーンに保つため

  • 少なくとも意味のある部分については、ペアプログラミングを試してください。これは、コードをレビューしてリファクタリングするための効果的な方法です。
  • 「完了」の定義をリファクタリングしてみてください。その後、それは見積もりプロセスの一部となり、それに応じて割り当てられます。したがって、完了の定義には次のものが含まれる可能性があります。コード化、単体テスト、機能テスト、パフォーマンステスト、コードレビュー、リファクタリング、統合 (または同様のもの) が行われます。

古いコードをクリーンアップするには:

  • 単体テストは、リファクタリングを行って、物事がどのように機能するかを理解するのに役立ちます。
  • 大規模なリファクタリングについてはビジネスケースを作成する必要があるというコメントに私も同意します。ただし、小規模なリファクタリングは簡単に見積もりに含めることができ、すぐに利益が得られます。つまり:私は 1 つの作品を書き直すのに 2 時間を費やしますが、とにかくバグを探すのにその時間を費やすことになります。

また、製品所有者とスクラムマスターに古いコードと新しいコードの速度を個別に取得してもらい、それに応じて使用することを検討することもできます。

必要な新機能があり、邪魔になる大量のコードの塊を明確に示すことができれば、管理者の許可を得て、古いコードを必要な新機能を備えた新しいコードに置き換えることができるかもしれません。これを行うと、触れる予定のないソフトウェア部分の古いインターフェイスに合わせて、やや見苦しい shim レイヤーを作成する必要がありました。また、既存のコードを実行し、新しいコードを実行して、シム層を通して確認できる新しいコードを確認できるテスト ハーネスは、アプリケーションの残りの部分をだまして何も変わっていないと思わせることができます。再加工した部分を再加工することで、パフォーマンスの大幅な向上、必要な新しいハードウェアとの互換性、アプリケーション用のスペースの管理に関する現場サイトの専門知識のニーズの軽減、および新しいコードを示すことができました。 だった はるかにメンテナンスしやすくなります。最後の点はユーザーにとっては重要ではありませんでしたが、再作業による他の利点は、多少の痛みを伴うデータベース変換のメリットをユーザーに「売り込む」のに十分な魅力的でした。

もう一つのより控えめな成功事例:私たちは文字通り何年もの歴史を持つまともなトラブル追跡システムを持っていました。私たちのアプリケーションのサブシステムは、メンテナンス プログラマーが疲れ果てるほどのスピードで有名でした。明らかに(私の心の中では)大規模な書き直しが必要だったのですが、経営陣はそれについて熱心ではありませんでした。私たちはトラブル追跡データの履歴を掘り下げて、このモジュールの保守に費やされたスタッフのレベルを示すことができました。その努力にもかかわらず、そのモジュールに対する毎月のトラブル チケットは一定の割合で届き続けました。そのような実際のデータに直面すると、そのサブシステムの再作業に人員を割り当てることに長らく固執してきたマネージャーでも、そのモジュールの再作業にスタッフを割り当てるメリットがわかるようになります。

以前と同様のアプローチは、そのモジュールの入力と出力をそのままにすることでした。良いニュースは、派手な新しいデータ構造を持つ新しいコードに仮想メモリを投入することで、モジュールのパフォーマンスが顕著に向上したということです。悪いニュースは、元の実装の何が問題だったのかを実際に理解する前に再実装がほぼ完了し、ほとんどの場合は機能しましたが、一部のトランザクションで失敗する日があったことです。最初のカットではそれらのバグが忠実に再現されていましたが、再加工されたコードではバグがより理解しやすくなったため、実際の問題を実際に修正するチャンスが得られました。振り返ってみると、問題を引き起こしたデータを収集し、再加工されたバージョンでその問題が再現されないよう細心の注意を払っていた方が賢明だったのかもしれません。しかし実のところ、書き直しがかなり進むまでは誰も問題を理解していませんでした。そのため、書き直すことでユーザーのパフォーマンスが向上し、現在のプログラマの理解も向上し、最終的に本当の問題を解決できるようになりました。

失敗例:さらにもう 1 つ信じられないほど醜いモジュールがあり、それが常に問題となっていました。残念なことに、私は、少なくとも名目上のリリース スケジュールの期間内では、この特定の惨めで悪党の巣窟への事実上のインターフェイスを理解できるほど賢くありませんでした。もっと時間があれば、システムのその部分を再加工するための適切な計画も見つけられただろうと信じたいです。そしておそらくそれを理解すれば、ユーザーが望む改善点を特定して、それに適合させることもできたでしょう。リライト。ただし、すべての箱に賞品が入っているという保証はできません。ボックスがまったくわかりにくい場合、その一部を切り取ってその部分をきれいなコードに置き換えることは困難です。そのモジュールを担当していた男はおそらく攻撃計画を立てるのに最も適した立場にあった人物だが、頻繁に起こる墜落と現場からの支援要請を「雇用の確保」とみなした。経営陣は、変化を求める人のために彼を緩和する必要があるということを本当に認識していなかったように思いますが、おそらくそれが必要だったのでしょう。

ドリュー

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top