コードのメンテナンス:一貫性を保つために新しいコードを拡張する際に悪いパターンを維持するかどうか?


45

プロジェクトの既存のモジュールを拡張する必要があります。私はそれが行われた方法が好きではありません(コピー/貼り付けられたコードのような、アンチパターンがたくさんあります)。多くの理由で完全なリファクタリングを実行したくありません。

したほうがいい:

  • 次のメンテナーとの混乱を避け、コードベースとの一貫性を保つために、間違っていると感じたとしても、既存の規則を使用して新しいメソッドを作成しますか?

または

  • コードに別のパターンを導入している場合でも、私が気分が良いものを使用してみてください?

最初の回答後に編集された精度:

既存のコードは混乱ではありません。簡単に理解できます。しかし、良いデザインで回避できる多くの定型コードを導入しています(その結果、コードを追跡するのが難しくなるかもしれません)。私の現在のケースでは、古き良きJDBC(インボードのスプリングテンプレート)DAOモジュールですが、すでにこのジレンマに遭遇しており、他の開発者フィードバックを探しています。

時間がないので、リファクタリングしたくありません。そして、時間が経っても、完全に機能するモジュール全体にリファクタリングが必要であることを正当化するのは困難です。リファクタリングのコストは、そのメリットよりも重いでしょう。覚えておいてください:コードは乱雑でも複雑でもありません。そこにいくつかのメソッドを抽出して、ここで抽象クラスを紹介することはできません。それは設計上の欠陥です(極端な「愚かなシンプルを保つ」の結果だと思います)

したがって、質問はそのように尋ねることもできます:
開発者として、あなたは簡単な愚かな退屈なコードを維持することを好みますか、またはあなたの場所で愚かな退屈なコードを行うヘルパーを持っていますか?

最後の可能性の欠点は、いくつかのことを学ばなければならず、完全なリファクタリングが完了するまで、簡単な愚かな退屈なコードを維持しなければならないことです)


非常に興味深い質問です!
フィリップ

1
簡単で退屈な愚かなコードを維持することは、定義上簡単です。私はむしろ簡単な生活をして、毎日早く出発したいです。
すぐに

ええ、しかし私は退屈な愚かなコードを行うのが面倒です:)私はこの部分を私のためにする何かを構築するために2または3日間一生懸命働くことを好むでしょう!
ギヨーム

1
愚かで退屈なのはいつ混乱したのですか?
エリックReppen 14年

こんにちはErik、時には因数分解されたコードの方が読みやすい場合があります。同じことが何十回もあり、コードは簡単です。それについて考えることなく連続して読むことができ、直線的にデバッグすることができます。隠れた複雑さはありません。
ギヨーム14年

回答:


42

リファクタリングは小さなステップで行うのが最適であり、できればコードをカバーする単体テストがある場合に限ります。(あなたはまだテストしていないのであれば、最初にそれらを書くために努力し、それまで、最も簡単な、最も確実なのスティックは、好ましくはリファクタリングを自動化。Aは、この中に大きな助けとなる効果的なレガシーコードを使用した作業のマイケル羽で。)

一般に、触れるたびにコードを少し改善することを目指します。ボーイスカウトルールRobert C. Martinによって造られた)に従って、コードを見つけたときよりもきれいにしておきます。新しいコードを追加するときは、既存の不正なコードから分離するようにしてください。たとえば、長いメソッドの途中に埋めるのではなく、別のメソッドへの呼び出しを追加して、新しいコードをそこに配置します。このようにして、既存のコードベース内でクリーンな(コードの)島が徐々に大きくなります。

更新

リファクタリングのコストは、そのメリットよりも重いでしょう。[...]開発者として、あなたは簡単な愚かな退屈なコードを維持することを好みますか、またはあなたの場所で愚かな退屈なコードをするヘルパーを持っていますか?

ここで重要な点だと思うことを強調しました。リファクタリングのコストとメリットを評価する前に、それを検討する価値があります。あなたの場合のように、私たちのほとんどはリファクタリングのためのリソースが限られているので、それらを賢く使用しなければなりません。最小限の労力で最大限の利益をもたらすリファクタリングに貴重な時間をかけましょう。

創造的な心として、もちろん完璧で美しくエレガントなコードを作成し、私の理想に似ていないものをすべて書き直すことを好むでしょう。長期にわたってお金の価値を最大限に引き出すことを考えるべきです。

リファクタリングの利点は、長期的にコードを理解、維持、修正、拡張するための時間と労力が十分に節約された場合にのみ現れます。そのため、たとえコードのpieceい部分がめったに、またはまったく触れられていない場合、既知のバグはなく、予見可能な将来において、それに触れる必要のある機能については知りません。安心して。


7
「コードはすでにひどいものであり、それを維持し続けるかもしれない...」というtrapに陥りやすいのは、優れたプログラマーはそうではありません。素敵な答え。
sevenseacat

これが最も安全なアプローチである可能性が最も高い(テストのおかげでコードが機能することが保証されている)が、それでも質問で言及されている問題が発生する。別のパターンがコードに導入されています。一般に、すべてのリファクタリングに時間をかけて(TDDを行う場合は、中間ステップで最適)、中間の矛盾した状態にならないようにする必要があると思います。終了したら、コードをソース管理にコミットします。
スティーブンジュリス

2
@Steven、余裕があれば一度にすべてをリファクタリングしても問題ありません。しかし、ほとんどの実際のプロジェクトでは、すべてを停止し、リファクタリングのためだけに数日または数週間連続して過ごすことはできません。幸運にも、それをサポートするマネージャーがいる場合でも、プロジェクトを進める必要があります。
ペテルトレック

1
@Steven、それは依存します-上記の私の更新を参照してください。
ペテルトレック

1
@PéterTörök:素晴らしい更新です!考慮に入れる実世界の要因の完全な説明。
スティーブンジュリス

4

リファクタリングする時間はなく、コードは保守可能であるため、一貫性を保ちます。次回は、リファクタリングを見積もりに含めるようにしてください。


3

一貫性を保つことは、周囲のコードが良好な状態にある場合にのみ次の開発者を支援します。手元のコードを理解し、変更を追加するための適切な「拡張ポイント」を見つけるのにどれくらい時間がかかったかを考えてください。現在の傾向に従うと、次の人は既存のコードだけでなく、変更を加えなければならない新しいコードを理解する必要があります。

コードを意味のある関数にリファクタリングすると、次の人は何が起こっているのかを理解しやすくなり、変更を追加するのに必要な労力が減ります。このように考えてください。次の男はあなただと仮定します。このコードブロックを再訪するとき、今見ているのと同じ混乱、またはより論理的に構築された何かを見たいとき、何を望みますか?


3

一貫性には高い優先順位があります。明らかに彼らの権利念頭に置いて誰もがどこでもどこでも代わりにコピー&ペースト定型のエレガントなDRYソリューションを好むだろう、しかし、あなたは本当に一貫して適用1つを有するに同じコードベースでは2つの異なるアプローチを好むでしょうか?誰かがさらに賢いソリューションを発明し、それを一貫性なく適用した場合はどうなりますか?次に、同じことを行う3つの異なる方法があります。

開発者が何かをするための「より良い方法」を見つけたが、それをコードベースに一貫して適用していないことに起因する厄介なコードを見てきました。新しいパターンを徐々に適用する計画的で調整された戦略の一部である場合、それは機能する可能性がありますが、実装されたすべてのパターンには一貫性がなく、システム全体を悪化させるリスクがあります。

各ステップをコードベース全体に一度に適用できるように、小さなステップでリファクタリングを検討することもできます。例えば。各反復でボイラープレートの小さな部分をヘルパー関数に抽出します。時間が経つにつれて、ヘルパークラスのすべてのボイラープレートになります。設計されていないが成長しているため、見苦しいかもしれませんが、すべてのコードが1か所にあるので、今すぐ修正できます。


+1「その後、同じことを行う3つの異なる方法があります。」これは、私が取り組んできたすべてのエンタープライズプロジェクトで見ました。あなたがリファクタリングしたいと決めたcodeいコードの世話をしようとしている別のコードがまだないことを確認するためにコードを精査するまで、リファクタリングを試みないでください。少なくともコードを完全に読むまでは、定型的な規約に従うことをお勧めします。
TK-421

1

重複コードを排除するリファクタリングは優れたリファクタリングであり、期限が差し迫っている場合を除き、延期すべきではありません。一度リファクタリングに費やした時間は、将来の実装で得られる時間で簡単に埋め合わせられます。リファクタリングのおかげで、内部の動作はもう見えないので、理解するのが難しくなり、従うのが難しくなります。

私の意見では、リファクタリングされたコードを追跡するのは難しいというのは一般的な誤解です。これは通常、リファクタリングされた結果だけではなく、リファクタリングされているものに精通している人々の議論です。新規参入者にとって、リファクタリングされた結果はより明確になります。

バグ/機能は、後で中央の場所で修正/実装することができ、アプリケーションのどこでも自動的に利用できます。これは、通常非常に過小評価されている大きな利益です。一般に、コンポーネントの完全なリファクタリングにはそれほど時間がかかりません。(数か月ではなく日数)これをバグのために失われた時間と比較すると、リファクタリングできたコードを理解する必要があるため、リファクタリングのコストは最小限になります。

PéterTörökの返信に関連する更新:「時間がかかるため」リファクタリングを延期するのではなく、後でリファクタリングする時間が長くなりますか?リファクタリングは、より頻繁に行われる場合、長くはかからないはずです。

製品に何も追加しないコードを書くのに数日かかることを上司に説明する方法は難しく、それはまったく別の質問です。:)


1
「製品に何​​も追加しないコードを書くのに数日費やすことを上司に説明する方法は難しく、まったく別の質問です。」ナイストライ;-)残念ながら、実生活でもこれを解決する必要があります。それが小さなステップで行くことがより実用的である理由です。2時間のタスクの一部として30分のリファクタリングを行うことができます。マネージャーはそれについて知る必要さえありません。リファクタリングに2日間費やしたOTOHが見過ごされることはめったにありません。
ペテルトレック

@PéterTörök:投稿を少し更新しました。もちろん、リファクタリングに時間をかけることが許されない現実世界の状況がまだあります。しかし、理論的には常に時間を稼ぐと信じています。(作業中のコードが近い将来サポートされなくなることがわかっている場合を除く)
スティーブンジュリス

彼らが言うように、理論的には、実践と理論の間に大きな違いはありません。しかし、実際には... :-)現実の生活では、リファクタリングに費やされた費用を常に取り戻せるとは限りません。これに関する私の答えを拡張しました。
ペテル

1
重複したコードを削除するリファクタリングは常に良いとは限りません。今日のビジネスルールでは2つの方法が同一である可能性がありますが、明日ではありません。例えば、AcmeLockerBank一つは持っているかもしれないgetRow(int itemIndex)戻っ方法index % 5AcmeButtonPanel同一の方法を持っているかもしれませんがロッカーボタンボードの両方の番号のものと同じ方法であるため、今日のロッカーバンクにインデックスが1000を超えるアイテムはないが、一部のボタンパネルにはある場合、将来のロッカーはインデックスに1000-1999の範囲の異なる行間隔を使用します...
supercat

1
...ロッカーバンクとボタンバンクに個別のgetRowメソッドがある場合、ロッカーバンクに追加の動作を追加するのは簡単ですが、機能が共通のメソッドにマージされている場合はより困難になる可能性があります。
スーパーキャット

0

簡単に拡張できる独自のスタイルで新しいコードを導入しながら、古いコードのファサードとして機能する新しいインターフェイス/クラスを作成することはできませんか?


0

正しい方向に進んでください。切り取りと貼り付けの代わりに関数を使用します。これにはリファクタリングは必要ありませんが、将来のリファクタリングの基礎を開始できます。


0

開発者として、あなたは簡単な愚かな退屈なコードを維持することを好みますか、またはあなたの場所で愚かな退屈なコードをするヘルパーを持っていますか?

修正された質問がわかりません。私としては、ほとんどの人は「愚かな退屈なコード」を維持したくないと思います。ヘルパーの意味がわかりません、ごめんなさい。

ポスターは、今のところ大きな変更を加えないことで彼ら自身の質問に答えました。良い選択。開発者のbusiness慢に、ビジネスに最適なものを知っているという問題があります。あなたは上司よりもよく知っているので...ずるい上の大きなリファクタリング?有能なマネージャーなら誰でもメリットを評価できます。

リファクタリングがオプションではない場合、質問はそれを行うための正しい時間、場所などに関する議論になります。一貫性は非常に重要です。それでも、長寿命のコードはしばしば「更新」の恩恵を受けます。他の人はこれについて議論しています...

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