コードの一貫性とコードの改善の適切なバランスは何ですか?


53

最近、同僚とコードスタイルについて話し合いました。彼は、コードの外観(ブレースの配置、大文字の使用など)の場合と同じように、APIの使用法と使用している一般的なパターンは、コードベース全体ではなく、周囲のコードとできるだけ似ている必要があると主張していました。たとえば、C#でDAOクラスにメソッドを追加する場合、そのクラスの他のメソッドがそれを使用していない場合でも、コードをクリーンで維持しやすくするために、必要に応じてLINQを使用しようとします。しかし、私の同僚は、そのクラスの既存のスタイルに反するため、そのインスタンスでそれを使用すべきではないと主張し、したがって理解が難しくなります。

最初は私は彼の立場がかなり極端であると感じましたが、しばらく考え直した後、私は彼の主張を見始めています。架空のLINQの例では、同僚がLINQに慣れていないために、おそらくこのクラスには含まれていませんか?もしそうなら、もし私がそれを使わなかったなら、私の仲間の開発者にとって私のコードはより保守しやすいでしょうか?一方、このような手法を使用するとコードがよりきれいになると本当に信じている場合、周囲のコードと大幅に異なる場合でも使用すべきではありませんか?

私の同僚の議論の核心は、私たち全員が異なる方法でコードベースに同様の機能を実装しようとすると、私たちはそれぞれ私たちの方法が「最高」だと思うと、最終的にコード全体が難しくなることだと思う理解する。しかし、現時点では、既存のコードを盲目的にたどりすぎると、時間の経過とともに品質が徐々に低下していくと思います。

では、パターンはどの程度までコードスタイルの一部であり、一貫性を維持することと改善を行うことの間のどこに線を引くべきでしょうか。


14
では、誰もが「悪い」方法に自分自身を制限した場合、コード品質はどのように改善されるでしょうか?
イズカタ


LINQを記述するとき、LINQ to SQLを意味しませんか?はいの場合、私はあなたの友人に同意することができます。あなたがLINQについて話しているなら、私は彼に同意しません。誰もが最近LINQに精通している必要があります。彼らの選択ではありません。彼らはよく知っているように支払われます。
ピョートルペラ

@Peri私は基本的なLINQを意味しました-私の例はIEnumerable、DAOではなくsでの作業に関するものだったと思います。
ロバートジョンソン

2
ICYMI-このまさにトピックに関するディルバートコミック:dilbert.com/strips/2013-09-21
ジムベサンクール

回答:


53

より一般的な答えを与えるには:

このような場合、2つのプログラミングの "ベストプラクティス"が互いに対立します。コードの整合性は重要ですが、タスクを達成するための最良の方法を選択することです。このジレンマに対する正しい答えはありません。それはいくつかの要因に依存します:

  • 「正しい」方法はどれほど有益ですか?

    • 時々、新しく改善されたベストプラクティスは、パフォーマンスを劇的に向上させ、バグを排除し、プログラムをはるかに簡単にするなどです。そのような場合、新しい方法を使用することに強く傾倒します。一方、「正しい方法」は、構文上の砂糖、または実際には優れていないことを行う合意された慣用的な方法にすぎない可能性があります。その場合、おそらくコードの一貫性がより重要です。
  • 矛盾はどれほど大きな問題を引き起こすでしょうか?

    • 新しいコードはレガシーコードとどのように相互接続されていますか?新しいコードはライブラリの一部ですか?プログラムの多くの部分に渡されるオブジェクトを作成しますか?このような場合、一貫性は非常に重要です。新しいAPIを使用するか、一般的なことを行う新しい方法を使用すると、微妙に異なる結果が作成され、プログラムの他の場所の仮定が破られる可能性があります。 一方、かなり孤立したコードを記述している場合、不整合が問題になる可能性は低くなります。
    • コードベースの規模と成熟度は?何人の開発者がそれを理解し、それに取り組む必要がありますか?合意された一貫性のある標準は、大規模プロジェクトでははるかに重要です。
    • 最新の機能をサポートしていない古い環境でコードを実行する必要がありますか?

これらの問題のバランスに基づいて、どのルートを取るかについて正しい選択をする必要があります。私は個人的に一貫性のために一貫性の価値をほとんど見ていません。そして、そうするための多大な費用がない限り、最新の最良の方法を使うことを好みます。

もちろん、第三の選択肢があります:既存のコードを書き換えることが最善の方法を使用していますので、ということ一致しています。これが必要な場合もありますが、コストが高くなります。


7
非常に良いバランスの取れた回答(+1)。私の経験では、各チームメンバーが他のチームメンバーが理解するのが難しいと感じる新しい異なるイディオムを自由に使用できる場合よりも、よく理解されているイディオムの比較的小さなセットに全員が同意すれば、チームの生産性が向上します。「最新のプラクティスを使用して一貫性を保つように既存のコードを書き換える」という文に関する小さな点:「最新」は自動的に「より良い」を意味するわけではありません。ケースごとに常に判断する必要があります。
ジョルジオ

1
@Giorgio、フィードバックをありがとう。最終ポイントの言語を微調整しました。

6
ジョルジオからの良い答えと良いコメント。この例では、チーム/文化に応じて、単独で開始するのではなく、調整されたチームの採用を可能にすることを検討する価値があります。これにより、メンテナンスに関するリスクの一部が軽減されます(全員が搭乗するため)。(つまり、チームが過去に作成したコードではなく、現時点での実際のスキルに重点を置きます。)
マット

+1。同意済み、徹底的かつバランスの取れた回答-さまざまなシナリオを十分に考慮してください。再び、ジョルジオからの良いコメント。
ロバートジョンソン

1
新しいイディオム、テクノロジーの採用に関して:新しいプロジェクトを始めることは、新しいものを紹介する良いポイントだと思います。その後、プロジェクト全体の期間中、コードのスタイルは可能な限り一貫性を保つ必要があります。私は最近、5年前のコードを掘り下げなければなりませんでしたが、チーム全体が共通のアーキテクチャと合意したイディオムに固執していたため、そのコードを自分のやり方で見つけられることを非常に嬉しく思いました(苦労なしではありません! )プロジェクトの開始時。
ジョルジオ

26

一貫性を保つことは、私の観点ではほとんど価値がありません。継続的な改善が必要です。

同僚の立場は、イノベーションを実際に妨げています。一貫性の引数は、たとえば、LINQ を使用するためにすべてのコードを移行する場合にのみLINQを使用できる状況になります。そしてまあ、私たちはこれのための時間がありませんか?

私はむしろ、一部のコードがまだforeachArrayListsを実行しており、他の部分がLINQ onを使用しIEnumerable<T>、時間の終わりまで物事を行う最も古い方法に固執するのではなく、矛盾があります。

関連性を保ち、物事の新しい方法を学ぶのは同僚の責任です。


3
「関連性を保ち、新しい方法を学ぶのは同僚の責任です。」:新しいコード(新しいモジュール)で新しいイディオムとライブラリを使用し、レガシーコードで一貫したスタイルを維持する可能性があります。
ジョルジオ

8

APIの一貫性は、パブリックAPIと内部APIの両方にとって非常に重要です。

コードの書式設定の一貫性は重要であり、すべての人に同じ書式設定ルールを使用した自動書式設定ツールによって実施することが理想的です。共有のバージョン管理されたコードベースでの生活を簡単にします。

命名規則は、ローカル変数などについても一貫している必要があります。

静的分析ツールを使用して、他の特定の規則と適切な慣行を実施する必要があります(ただし、このようなツールのデフォルトに盲目的に従わないでください、デフォルトは時々狂気に接することがあります)、しかし、何かがそれを要求する場合、正当化できる場合は、一時的に(通常はコメント内のディレクティブで)チェックします。

上記にリストされているものを除いて、関数/メソッドの内部で何が起こるかは、それ自体が良いコードである限り、何らかの形で一貫している必要はありません。わかりやすく、よくコメントされたコードは非常に重要ですが、その後、コンパイラーと静的分析ツールがそれが一貫性のあるコードであると考えれば、それは十分に一貫性があります。


LINQなどの新しい言語機能について(まったく新しいわけではありません)、考慮する必要がある唯一のことは、コードが使用されるすべての場所で新しい十分なバージョンの言語/ライブラリが使用されることです。疑わしい場合は、互換性があることがわかっている機能に固執します。もちろん、これはシステム全体にバージョンアップグレードをプッシュすることを妨げるものではないので、新しい素敵なものを使い始めることができます。

そして、コードを操作するすべての開発者は最新の状態に保つ必要があるため、.NET開発者はLINQを知っている必要があります。そうでない場合は、学習を余儀なくされるべきです。何らかの理由でこのビジネスの仕事をしています)。


6

これに対する答えは簡単です。

一貫性は最も重要です。

しかし、それは警告が付属しています...

あなたとあなたの同僚は、間違った種類の一貫性に夢中になっている可能性が高い

実装は使い捨てです。テストスイートの品質と包括性に応じて、さまざまな程度で簡単にオーバーホールできます。「これはプロパティである必要がありますか?」、「下位レベルの構造の代わりにLINQを使用するコードを薄くするべきではありませんか?」疑わしい価値がある。測定値を実装レベルでの一貫性の値に結び付けるのは困難です。このレベルで尋ねるより良い質問は、「このコードは宣伝どおりに機能しますか?」です。TL; DR実装の一貫性は、「小さな心」がホブゴブリンを使用する場所です。

ここで一貫性がそれほど重要ではないのはなぜですか?通常、実装には少数の貢献者がいます。ほとんどのメソッドは書かれており、二度と触れません。残りのコードのうち、2つの貢献者を持つメソッドの数はほぼ確実に過半数です。このパターンは無限に続きます。このコンテキストでは、一貫性はそれほど重要ではありません。コードの有効期間がかなり短い(数年)場合、積極的な一貫性から得られる利益は、おそらく要因ではありません。

これは、実装に夢中になるべきだということではありません。むしろ、素敵な、きれいな、シンプルなデザインは、方法ごとに愚かなボイラープレートの一貫性のある方法よりも、将来の仮想的なメンテナーにとって桁違いに価値があると言うことです。これは私たちを本当のポイントに連れて行きます...

APIは使い捨てではありません。

これはすべて、APIコードレベル、Webサービス、SDKなどです。これらは一貫している必要があります。このさまざまな一貫性による生産性の向上は、いくつかの理由で非常に大きくなります。

統合テスト:

APIの一貫性を維持する場合、統合テストのスイートを作成できます。これらにより、開発者は実装の詳細を自由に交換し、即座に検証を行うことができます。共同作業のクズをLINQに切り替えたいですか?統合テストは実行されますか?また、実稼働への準備を行う際の検証も提供します。コンピューターは高速であるため、1台のラップトップで日常的なタスクを実行する1,000人のテスターの作業を実行できます。組織の人員を大幅に増やすことに相当します。

生産性

APIが一貫している場合、APIの他の部分の使用について学んだことをたどるだけで、APIの使用方法を推測できます。これは、APIが自然で一貫した「ルックアンドフィール」を提供するためです。これは、クライアントがドキュメントを選別する時間を短縮することを意味します。オンボーディングは簡単で安価です。APIを開発した人々に尋ねられる質問は少なくなります。一貫性は誰もが勝者になる

このシナリオで一貫性が重要なのはなぜですか?APIには実装の正反対の問題があるためです。それらを使用する人の数は、通常、実装に貢献する人の数よりもはるかに多くなります。少しの一貫性から得られるわずかな利益は増加し、その一貫性を維持するためのコストは償却されます。

結論

一貫性は高価です。一見すると、生産性が低下します。開発者を制約し、彼らの生活をより困難にします。問題を解決する方法に制限があり、最適でない方法で問題を解決することがあります。これは、多くの場合、彼らが理解していない、考えが悪い、または彼らが内密ではない(契約、より大きな組織的または組織間のポリシー)ためです。

Raymond Hettingerは、Pythonプログラマのチーム向けにPEP8スタイルガイドを使用することに関するPycon 2015の講演でいくつかの優れたポイントを挙げました。彼は、コードの一部に対する文体の一貫性への執着が、コードレビュー担当者が深刻なロジックと設計上の欠陥を見逃す原因になることを示しました。彼の仮説は、文体の矛盾見つけるのは簡単だと要約できます。コードの実際の品質を判断するのは難しい

ここでのポイントは重要です。一貫性が重要な場所を特定し、積極的に保護します。重要ではない場合は、時間を無駄にしないでください。一貫性の価値を測定する客観的な方法を提供できない場合(上記の場合、「実効人員」、生産性の関数としてのコスト)、リターンが大きいことを実証できない場合は、あなたの組織。


4

LINQに不慣れですか?もしそうなら、もし私がそれを使わなかったなら、私の仲間の開発者にとって私のコードはより保守しやすいでしょうか?

C#言語はまだ進化しています。人々がC#1からの変更を学ばなかった場合、彼らは見逃しているでしょう:

  • ジェネリック
  • パーシャル
  • 匿名メソッド
  • イテレータ
  • Nullable型
  • 自動プロパティ
  • 匿名型
  • 拡張メソッド
  • ing
  • ラムダス
  • 非同期メソッド

これは、ウィキペディアの記事にある一般的な機能のほんの一部です。私が指摘しているのは、開発者が学ばなければ、コードベースは空のままになるということです。開発者が継続的に改善し、コードベースが進化し、完全なテストスイートでサポートされることを望みます。.NET 1でプロパティを手動で実装するのがいかに悪かったのか覚えていますか。

Linqは生活を楽にします。できる限り使用してください。チームメンバーの意欲を高めることができます。

では、パターンはどの程度までコードスタイルの一部であり、一貫性を維持することと改善を行うことの間のどこに線を引くべきでしょうか。

改善は段階的です。私にとって、読みにくく保守性の低い古いスタイルのコードを保持することは意味がありません。あなたのチームメンバーは、たとえそれが書けなくても、少なくとも何が起こっているのかを解決できるはずです。


2
私はあなたが言っていることに心から同意しますが、私の質問は新しい言語機能とそれらを学ぶ開発者の責任ではなく、コードベースの比較的小さな領域内でさまざまな方法で同様の問題を解決するというより一般的な質問です。LINQは、問題を解決する別の方法を使用する良い例だからです。私の同僚は新しい言語機能を喜んで使用しますが、それは彼が取り組んでいるコードの粒度に反しない場合のみです。
ロバートジョンソン

@RobertJohnson同僚に指摘すると、保守性が一貫性よりも優先されるため、既存のコードの「粒に反する」何かがあったとしても、保守性が高い場合はそれを行うべきです。古い滞在DAOを使用することは、Linqよりも保守性が高いとは思いません。
アンディ

3

一貫している必要がありますが、必ずしも古いコードと一致している必要はありません。つまり、チームは何かを行う正しい方法に同意し、新しいコードが作成されたり、大幅な変更が行われたりするたびにその方法を使用する必要があります。

そうすれば、一貫性の利点のほとんどを享受できます(特に、誰がコードを書くかは関係ありません)が、チームが別の方法で明確な利点を見つけた場合でも改善できます。

理想的な世界では、すべての古いコードを新しい正しい方法に適合するように書き直します。これは経済的に実行可能ではありませんが、技術的に意味があります(または、新しい方法はより良い方法ではありません)。そして、あなたの長期計画はそれをアップグレードすることです。それが価値がない場合は、新しい方法で気にしないでください。言い換えると、正しい方法であると宣言することを検討する新しい方法には明確な利点がなければなりません。


1

プロジェクトのコードスタイルに従うことが重要だと思います。命名規則、インデントなど。

同僚がそれらを理解していないか、プロジェクトで以前に使用されたことがないという理由だけで、新しい言語構成要素またはデザインパターンの使用を制限する必要があることに同意しません。

もちろん、これらのものはそれらを使用するのに十分な理由があるはずです。必要に応じて、パフォーマンスまたは簡潔さ。


マイナスは何ですか?
オズ

0

私は、現在の設計パターンを盲目的にたどることに非常に注意します。もちろん、目に見えるマイナス面がない場合は、常にコードベース全体で同様のパターンをたどろうとする必要があります。

しかし、大多数の開発者が既存の悪いパターンを追跡するのが「ベストプラクティス」であると感じる状況に陥るのは、あまりにも簡単です。

一方、一貫性は重要です。膨大なコードベースを扱う場合、開発者がコードベースの隅々まで読んでいない場合でも、何を期待すべきかを理解できるように、同様のパターンに従うことは非常に役立ちます。

したがって、可能な場合は開発者が従うべきパターンに関するガイドラインを確立し、更新することが最善だと思います。このように、新しいコードは他の新しいコードと一貫性があります。


-1

私たちはだれでも実行できる、かなり非公式の定期的な技術会議を開催しています。新しいテクニックを見つけたら、会議で発表します。一般的には、同僚がアイデアをどれだけ受け入れて理解しているかをよく感じます。これは、コードに含めるのが賢明かどうかを判断するのに役立ち、他の人がそのスタイルを支援する必要がある場合は、他の人がそれを解読するのに役立ちます。誰も車輪を再発明しなかったとしても、私たちはまだログ上のものをドラッグしているでしょう。


ダウン票は何のためにありましたか?
アリ

私はダウンボーターではありませんでしたが、これは実際に質問の対象になっていないようです。コーディングスタイルの問題を議論するのではなく、あらゆるものに適用できるチームプロセスです。また、「車輪を再発明した」のではなく、「車輪を発明した」という意味ではありませんか?

丸太が車輪の一種であるかどうかはセマンティクスだと思いますが、回転し、摩擦を減らし、地面と連続的に接触し、丸い表面を持っています。私が意味するもののより良い例があると確信しています-読者のための演習としてそれを残します。
アリ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.