私はC#の AvSolコーディングガイドライン を調べていましたが、ほぼすべてに同意しますが、他の人が特定の規則についてどのように考えているかを知りたいと思っています。
AV1500
メソッドは7つのステートメントを超えてはなりません。7つを超えるステートメントを必要とするメソッドは、実行しすぎているか、責任が多すぎます。また、コードが何をしているかを理解するために人間の心が正確なステートメントを分析することも必要です。自己説明的な名前を使用して、複数の小さく焦点を絞ったメソッドに分類します。
あなたのほとんどはこのルールに従っていますか?新しいメソッドを作成することで節約できるものがほとんどない場合でも(コードは [〜#〜] dry [〜#〜] です)、読みやすさが大幅に向上します。そして、あなたの数はまだ7と少ないのですか?私は10に向かってより傾向があります。
私はこのルールをいたるところで違反していると言っているのではありません。逆に、私の方法は95%小さく、焦点を絞っていますが、このルールに違反してはいけないと言って本当に驚かされました。
私は本当に、誰もがこの規則に決して違反しないと考えていることを知りたいだけです(これはコーディング標準の「1」です。つまり、絶対にこれを行わないことを意味します)。しかし、そうでないコードベースを見つけるのは難しいと思います。
これは私にとって「標準的なにおい」です。特定の制限があるコーディング標準を目にするたびに、私は心配しています。ほとんどの場合、メソッドが標準の許容値よりも大きくする必要がある場合(行の長さ/カウント、変数の数、出口点の数など)に遭遇します。基準はガイドラインに近く、適切な判断を下すための十分な余裕を持たせる必要があります。誤解しないでください。標準を持つことは良いことですが、「プロキシによるマイクロ管理」になるべきではありません。
通常、ものを小さなメソッドに分割することをお勧めします。しかし、重要なことは、意味のあるものを分割することです。
分割しても意味がない場合は、分割しないでください。これは多くの場合、一部のプロシージャまたはGUIコードに当てはまります。
Steve McConnellCode Complete に記載されていますが、短いメソッドを使用する場合、必ずしも生産性が向上するとは限りません。分割しても意味がない場合は、コードに複雑さを加えてもメリットはありません。
いつものガイドラインと同様に、制約が存在する理由を覚えておくことをお勧めします。そうすれば、それが適用されないときに学ぶことができます。ほとんどのコードでは、メソッドは短いか、DRYまたは 関心の分離 に問題がある可能性があります。しかし、そうでない場合は問題ありません。 。
それは経験則として見なされるべきです。
「80(100,120)列以下のテキスト」、「メソッドごとに1つの出口点」、「2レベル以下のネスト」などは、コードの匂いのインジケーターのしきい値と呼んでいます。あなたがそれらに時々違反したとしても、それは必ずしもコードが悪いことを意味するわけではありません。一貫して違反していることに気付いた場合は、コードの臭いがするので、少し間を置いてアプローチを見直してください。
私にとって、最も重要な基準は、「このコードは理解可能ですか?」、「反復的ですか?」、「論理的な場所で分割されていますか?」、「疎結合ですか?」です。まだいくつかありますが、基本的な考え方は、ドナルドクヌースのアドバイスを思い出すことで要約できると思います。
メソッド内のステートメントの数を実際に数えるために時間を費やしたことはありませんが、1つの明確な目的を明確に実行するメソッドを作成するよう努めています。あなたのコードがクリーンで読みやすく、そして [〜#〜] dry [〜#〜] と Single Responsibility の原則に従っている限り、あなたはおそらくあなたの仕事をしたでしょう。 7ステートメントの制限を強制するためだけにメソッドを任意に分割すると、コードの可読性や保守性が低下する可能性があると思います。
これらの種類のルールは、文字どおりにとるべきではありません。彼らは「メソッドは短くあるべきです」と言ったかもしれません。ただし、「1ページ未満」と解釈した人もいれば、「最大2行」と解釈した人もいます。
私は仮定します彼らはあなたに大まかな考えを与えるために「7つのステートメント」と言ったと思います(私は彼らが「約7」と言ったはずだと思います)。たまに9が必要な場合は、気にしないでください。しかし、20を打つと、このルールに適した球場にいないことがわかります。
7は完全に任意の数値で、まったく意味がありません。
循環的複雑度 はステートメントの数よりも大きな問題です。単一のメソッドに100のステートメントが含まれるコードを見たことがありますが(これはひどいと思いました)、循環的複雑度は1で、実際に実行されたのは1つだけです。たくさんのステップがありました。小さいメソッドに分割することについて説明しましたが、これらのメソッドはこの1つのメソッドによってのみ呼び出されます。
これはかなり極端なケースですが、重要なのは、コードDRYおよび低い循環的複雑度を維持する必要があることです。これは、メソッドの行数よりも重要です。
たとえば、switch/caseステートメントを見てみましょう。 7つ以上の可能な値がある場合、評価を複数のメソッドに分割する必要がありますか?もちろん、それはばかげたことでしょう。
ステートメントの数を7未満に保つために、コードを人工的により多くのメソッドに分割すると、コードがさらに悪化します。
ガイドラインはである必要があります各メソッドは1つの処理を実行し、コードをDRYに保つ必要があります。
まあ、それは少し異なります。データベースにアクセスするコードをたくさん書いています。例外処理のボイラープレートコードは、多くの場合7ステートメントを超える長さです。最良のガイドラインは、関数に1つの目的があることを確認することです
すべてがトレードオフです。提案されたアプローチの問題-各メソッドが短くなるようにいくつかのメソッドとクラスにリファクタリングすること-は、さまざまな理由で、極端に解釈するとコードが読み取り不能になることです。
7つのことを行うメソッドfoo()
を想像してみてください。あなたは7つのものが多すぎると主張するかもしれません。多分多くの場合あなたは正しいです。一方、これら7つのことは密接に関連している可能性があります。ロジックはスムーズに流れ、散文のように読むことができます。実際に必要なときにそれを理解するのに問題はないかもしれません。最終的にはるかに悪いことは、これらの7つのものを大きなソースツリー全体に分散させることです。そのため、foo()
を見ると、7つの異なる場所を調べないと、それが何をするのかわかりません。
多くの人がこのようなルールを頭に抱いており、結果は私がOOスパゲッティと思っているものです。すべてが、独自の小さなメソッドまたはクラスでボックス化され、アトミックな小さなマイクロトランザクションで囲まれています。あらゆる場所で発生しますが、そのようなコードベースに慣れて、それが何をしているかを知ることは不可能です。
それは悪いガイドラインではありません。メソッドとクラスが十分にグループ化され、相互に関連付けられている限り、メソッドとクラスを分割することを後悔したことはありません(自分が多すぎるとは知りませんでした)。
トリックは、垂直に分割しないことです(ある時点でメソッドをつまんで、新しいメソッドを開始するだけです)。トリックは、単体テストと同様に、最初からこのようなルールを念頭に置いて、実際に優れた設計を行い、メソッドの途中で3つまたは4つのステートメントを別のメソッドに渡すことで、メソッドを呼び出すことで、自分より優れていることを説明します。コードの途中にある3つまたは4つのステートメント。
この種の分割は、たとえそれが恣意的で1回だけ使用されたとしても、コードの新しい明確性により、後でより良いリファクタリングにつながる可能性がありますが、これは小さなクラスにも当てはまります。
単体テストと同じように考えてください。事実の後に単体テストを追加しようとすると、難しく、時には不可能に思えますが、最初から設計すると、実際にすべてのコードが改善されます。
概要? 「7文未満を使用する」のデザインの匂いと「7文を超える文を使用した」のコードの匂いとを比較する場合は、コードの匂いをなくしたいと思います。
うわー!あなたの方法は非常に小さくなければならないと大まかに言っている単純なガイドラインでそのような激しい議論を見つけるとは決して思っていませんでした。彼らは常にガイドラインを明確にすることを望んでいる開発者なので、私は7を選択します。
一部の皆さんは、文書の冒頭ですでに免責事項を引用しています。ただし、明確にするために、このドキュメントは、より優れたコードを記述し、より優れたシステムを設計するためのガイドラインをまとめたものです。ガイドラインがレベル1としてマークされている場合でも、何かがルールであることを述べたことはありません。これらのレベルは、このドキュメントをしばらく使用してきた多くの人々の集合的な意見にすぎません。
私はまた、専門家であると主張したことがありません。しかし、私はこの職業に15年間携わっており、約4年のC++経験と11年のC#経験があります。もともとは、Industrial Strength C++に基づいていましたが、それ以来、コミュニティからの意見を取り入れて改良しています。
とにかく、私が提起しようとしていた点は、自分で考え続ける必要があるということです。 7つのステートメントのガイドラインが役に立たないと思う場合は、単に長くするだけです。ヘック、私はたまにそのガイドラインに違反しています。私はそれを意識的に違反し、その結果を受け入れます。
まず、それはガイドラインではなく、ルールです。ガイドラインといいますので、そのように扱ってください。これは、(いつものように)あなた自身の判断も必要であることを意味します
それとは別に、この制約に準拠していない優れたコードの例はたくさん考えられます。これは単なるガイドラインですが、不十分です。
例外処理を混合に追加すると、ばかげたことになります。
「try、catch、finally」の後、メソッドごとに4つのステートメントが残ります。
20のフィールドフォームのメソッド「validateForm」も考慮してください。個別のメソッドですべての個別の検証を処理しても、呼び出す20のフィールド検証メソッドがあります。これらのガイドラインによると、「validateTopOfScreen」、「validateMiddleOfScreen」、「validateBottomOfScreen」などの無意味な分割が発生します。
問題は、「ルール」と「ガイドライン」を融合させることです。ルールは遵守されることを意図しています-ガイドラインは、あなたが何をしているか、そしてそれが本当により良い方法で実際に実行できるかどうかを検討させるためのアドバイスです。
平均して、ほとんどのプログラミングはおそらくガイドラインに従うことで改善されると思いますが、ガイドラインに従うことが独断的に従うと、解決することを意図したよりも多くの問題を引き起こす場合が常にあります。それが規則としてではなくガイドラインとして提示されている理由です。
以前の回答者は、ガイドラインの作成者がそれらを独断的に適用することを決して意図していないことを示し、彼らの文書にその影響についての記述を含めました。
私の上の声明に同意します。これは単なるガイドラインであり、完璧な世界ではすべてがオブジェクトであり、すべてのプログラムで再利用され、世界は美しい場所です。これは常に正しいとは限らず、多くのオーバーヘッドやリソースの無駄につながることもあります。それも覚えておく必要があります。
悪いルール。例外処理、データベースフィールドの設定、検証のためのコードを使用して、ほとんどのメソッドを7つのステートメントの下に配置するにはどうすればよいですか。ラムダ関数をインライン化しないでください。
コードの行は、複雑さの任意の数です。拡張メソッドを使用すると、次のようなコードを作成できます
Parallel.ForEach(regions, region => { Console.Write(region.Resorts.Where(x => x.name == "Four Seasons").OrderBy(x => x.RegionId).ThenBy(x => x.ResortId).ThenBy(x => x.name).ToList()); });
上記のコメントに同意します。私にとって7は任意であり、Rubyを使用する一部の言語では有用かもしれませんが、C#、Java、C++などの言語では、この "7行"の規則に疑問があります。例を挙げましょう。現在のアプリケーションには22個のテキストフィールドがあり、サーバー側の検証を行っています。メソッドはvalidateInput()と呼ばれ、checkEmailFormat()などの複雑なものを検証しない限り、私の設定は1つのメソッド自体のすべてのフィールドを検証します。つまり、基本的に、validateInputメソッドのコードは108行であり、複雑な検証が時々呼び出されます。
ここで、各フィールドを検証するために25のメソッドを呼び出したと想像してください。新しい開発者が入ってきた場合、彼はメインメソッドに出入りして25のメソッドをジャンプする必要があります。彼は大きなプロジェクトで迷子になることは間違いない。
私のコードを明確にするために私が本当にやっていることは、これらの4行が元々何をしているかを基本的に言うきれいなコメントを提供することです-
validateInput(UserObj user){
//名を検証する....... ......
//姓の検証...... ......
//電子メールを検証する..... //複雑すぎて電子メール形式をチェックできない通常の表現checkEmailFormat(); .... .....
等々.. }