コーディングガイドライン:メソッドには7つ以上のステートメントを含めないでください。


78

私はC#のAvSolコーディングガイドラインに目を通し、ほぼすべてに同意しましたが、特定のルールについて他の人がどう考えているかを知りたいと思います。

AV1500

メソッドは7つのステートメントを超えてはなりません。7つを超えるステートメントを必要とするメソッドは、処理が多すぎるか、責任が多すぎます。また、人間の心が正確なステートメントを分析して、コードが何をしているかを理解する必要があります。わかりやすい名前で、複数の小さくて焦点を絞った方法に分けてください。

あなたのほとんどはこのルールに従っていますか?読みやすさを大幅に向上させることは別として、新しいメソッドを作成すること(コードはまだDRYです)から節約できることはほとんどありませんか?そして、あなたの番号はまだ7と低いですか?私はもっ​​と10に向かう傾向があるでしょう。

私はあちこちでこの規則に違反していると言っているわけではありません。反対に、私の方法は95%小さくて集中していますが、この規則に違反してはいけないと言って本当に衝撃を受けました。

私は本当に誰もがこの規則に違反しないと思うことを知りたいだけです(コーディング標準の「1」です-これを絶対にしないでください)。しかし、そうでないコードベースを見つけるのに苦労すると思います。


48
彼らcaseは一言で声明を数えswitchますか?とにかく、それはばかげた、役に立たない要件に過ぎません。それを書いた人はプログラミングについて何も知らない。
SKロジック

86
コーディング標準で「1」である必要がある唯一のルールは、「すべてのコーディングガイドラインを一粒の範囲で取ります」というルールでなければなりません。
マイクナキス

6
@ SK-logic 1027も悪くありません-空の文字列をヌル文字列と同等に扱う必要がある場合、欠損データを処理しなければならないコードを書くのは楽しいはずです。
quant_dev

25
このガイドラインを読むとき、次のコードベースがいっぱいになることを期待します。void DoSomething(){DoSomethingFirstSevenLines(); DoSomethingSecondSevenLines(); DoSomethingThirdSevenLines(); 等; }
タグボート

12
...の.NET Frameworkのほとんどを反映して試してみて、より少ない7つのステートメントを持っているどのように多くの方法を見る
デビッドBoike

回答:


195

これは私にとって「標準臭」です。特定の制限のあるコーディング標準を見るたびに、私は心配します。ほとんどの場合、メソッドは標準が許可するよりも大きくする必要がある場合に遭遇します(行の長さ/カウント、変数の数、出口点の数など)。基準はよりガイドラインに近く、適切な判断を下すための十分な余裕を持たせる必要があります。誤解しないでください、標準があることは良いことですが、それらは「プロキシによるマイクロ管理」になるべきではありません。


25
「プロキシによるマイクロ管理」の+1。誰かが「7プラスまたはマイナス2」ルール(en.wikipedia.org/wiki/…)を読んで、コードエディターのような長期ストレージと短期ファクト保持を混同しているのではないかと思います。
ふわふわ

25
賢明に考え抜かれた標準は、コード内のマジックナンバーを禁止していますよね?コーディング標準もその標準に準拠していると思います。数字の7は間違いなく「魔法のような」品質を持っています。
アダムクロスランド

2
ドキュメントのタイトルが「GuidlinesC#3.0および4.0のコーディング」ではない場合、あなたの答えはより理にかなっています。
Andy

+1私の考えでは、コーディング標準に従うべき唯一の理由は、独断的に任意の数に従うことではありませんが、バージョン管理で不必要なマージの問題(チームで作業するときに関連する問題)を起こさないようにすることです。通常、ファイルを短くしてコンポーネントを増やすと、コードの変更をマージするときに問題が発生する可能性が低くなります。
スポイケ

3
このドキュメントをダウンロードし、調べてみました。1.6では、「プロジェクトはこれらのガイドラインに従う必要があるとは述べておらず、どのガイドラインが他のガイドラインよりも重要であるとも述べていません。しかし、どのガイドラインが重要であり、使用、疑問が生じた場合のコンサルタント、およびソースコードに使用するレイアウトの種類。1は「絶対にスキップせず、すべてのソリューションに適用できるガイドライン」を意味しますが、修正することもできます。
-19:

83

通常、ものを小さなメソッドに分割することをお勧めします。しかし、重要なことは、意味のある場所で物事を分割することです。

分割する意味がない場合は、分割しないでください。これは、一部の手順またはGUIコードの場合によくあります。

Steve McConnell氏はCode Completeで、短い方法を使用するときは必ずしも生産性が向上するとは限らないと述べています。意味をなさないときに分割すると、コードに複雑さを追加してもメリットはありません。

常にガイドラインと同様に、なぜ制約が存在するのかを覚えておくとよいので、いつ適用されないかを学習できます。ほとんどのコードではメソッドが短いか、おそらくDRYまたは懸念の分離に問題があります。ただし、そうでない場合は問題ありません。


1
素晴らしい答え。最後の2行は、特に重要なポイントです。
Xonatron

6
重要な経験則は、サブメソッドが直交しているかどうかをチェックすることだと思います。それらが独立している場合、任意の順序で呼び出すことができ、クラス不変式を尊重することができ、それらを分離しておく方が良いです。メソッドが密結合されている場合、クラスの不変式を解除する、および/または特定の順序で呼び出す必要がある場合は、それらをまとめておいた方がよいでしょう。
hugomg

4
完全なコードには、良いものがたくさんあります。すべてのプログラマーは、毎日ランチでその一部を食べ​​る必要があります。
-deadalnix

29

それは経験則としてみなされるべきです。

「80(100,120)列以下のテキスト」、「メソッドごとに1つの出口点」、「2レベル以下のネスト」などは、コードの匂いの指標のしきい値と呼ばれます。時々それらに違反する場合、それは必ずしもコードが悪いことを意味しません。一貫してそれらに違反していることに気付いた場合は、コードに何か臭いがするので、一時停止してアプローチを再考することをお勧めします。

私にとって、最も重要な基準は、「このコードは理解可能ですか?」、「反復的ですか?」、「論理的な場所で分割されていますか?」、「疎結合ですか?」です。さらにいくつかありますが、基本的な考え方は、ドナルドクヌースのアドバイスを思い出すことによって要約できると思います。


7
「80/100/120」列の制限により、コードを読み取ることができます。ほとんどの端末は80カラムで開きます。作成者が80カラムに折り返すのは、すべてのリーダーがコードを読みたいたびに端末のサイズを変更するよりも簡単です。他の制限とは異なり、N列の制限はコードのセマンティクスに影響を与えません。これは純粋に文体的なルールです。「4スペースタブを使用」または「独自の行に関数の開き中括弧を置く」と同じカテゴリ。
ディートリッヒエップ

4
確かに、それはセマンティックな側面よりも美的な側面です。しかし、それは私の最後の文が適用されるところです。行を分割する「いい」場所がない80列のルールを超えるJavaステートメントを見つけることは珍しくありません。これは、コードの可読性と理解に影響します。また、デメテル
12

7
21世紀には、IDEに「動的ワードラップ」と呼ばれるこの機能があります。
ジェルジAndrasek

9
@GyörgyAndrasek:しかし、誰もが常にあなたのIDEを使用していません。私たちが持つ端末では、GitHubでのコードを見lessに、vimそしてemacs、そして、自動ラッピングはせいぜい無計画に思えます。コーディング標準はあなたの利益のためではなく、チームで働く人々の利益のためです。
ディートリッヒエップ

2
@DietrichEpp個人的には、80桁目で常にラップされているコードを読むのに苦労しています。最近、標準のEclipseフォーマッタが使用されているJavaプロジェクトで作業する必要がありました。また、メソッド内では、2行または3行を超える行を追跡することは非常に困難でした(ただし、他のフォーマッタ設定も非難しています)。結論として、80は少し時代遅れだと思います。私は個人的に120の制限を使用し、それを強制するようにエディターを設定し、120カラム幅のコンソールを持ち、Githubは実際に125カラムを表示します。そして、私はそれがそのようにはるかに読みやすいと思います。
突く

18

メソッド内のステートメントの数を実際に数えるのに時間をかけたことはありませんが、明確な目的を1つだけ実行するメソッドを書くよう努めています。コードがクリーンで読みやすく、DRYおよび単一責任の原則に従っていれば、おそらく作業を完了したことになります。7ステートメントの制限を強制するためにメソッドを任意に分割すると、コードが読みにくくなり、保守しにくくなると思います。


1
読みやすくするために+1。メソッドの長さが20、30、または50行であっても問題ではありません。DRYとSRPがあなたの目標である場合、メソッドが少し長めの側面にあるように見えるかどうかは関係ありません...ほとんどの場合、コードを読みやすくしようとすると、メソッドが短くなることがわかります自然になります。
-S.ロビンズ

11

おおよそです

これらの種類の規則は、文字通りに解釈されるべきではありません。彼らは「メソッドは短くあるべきだ」と言ったかもしれません。ただし、一部の人はそれを「1ページ未満」と解釈し、他の人は「最大2行」と解釈したでしょう。

私は彼らがあなたに大まかな考えを与えるために「7つの声明」を言ったと仮定します(私は彼らが「約7」を言ったはずだと思いますが)。時々9が必要な場合は、汗をかかないでください。しかし、20を打っている場合は、このルールの正しい球場にいないことがわかります。


それはそれからそれをかなり明示的な近似にします。「スキップしないで、すべての状況に適用できるガイドライン」の下にマークされています。
ブライアン

1
@brian-ガイドライン作成者が「大体」という言葉を誤って省略したか、独裁的なタイプである可能性があります。私のポイントは、OPがこれを球場番号としてとらなければならないということです。コンパイラーまたはインタープリターが実施しない規則は、単なる提案です。
ネイサンロング

「コンパイラーまたはインタープリターが実施しない規則は単なる提案です」必ずしも真実ではありません。私は彼のカスタムのリシャーパーまたはfxcopルールを見ていないので、実際にこの特定のルールを強制するかどうかはわかりませんが、すべてのスタイルガイドラインに照らして検証するよう強制する企業があります。私は、Microsoftの厳しいコーディングガイドラインに合格できるコードを書くことを会社に強制している人々に会いました。
ブライアン

私はそれが近似値であり、一粒の塩によって取られるべきであることに同意します。コード標準の段落が任意の数を持ち出すことは必然的に混乱を引き起こすでしょう。ほとんどの場合、標準はコンテキストから除外され、「人々」は独断でそのarbitrary意的な近似に従います。
スポイケ

10

7はまったく意味のない完全に任意の数値です。

循環的な複雑さは、ステートメントの数よりも大きな問題です。単一のメソッドに数百のステートメントがあるコードを見ました(これはひどいと思いました)が、循環的な複雑さは1で、実際には1つのことしかしませんでした。たくさんのステップがありました。これをより小さなメソッドに分割することについて説明しましたが、これらのメソッドはこの1つのメソッドによってのみ呼び出されます。

これはかなり極端な場合ですが、ポイントは、コードをDRYに保ち、循環的複雑度を低く保つ必要があることです。メソッドの行数よりも重要です。

たとえば、switch / caseステートメントを考えてみましょう。7つ以上の可能な値がある場合、評価を複数の方法に分割する必要がありますか?もちろん、それはばかげています。

ステートメントの数を7未満に保つためだけに、コードをより多くのメソッドに人工的に分割すると、コードが悪化します。

ガイドラインは、各メソッドが1つのことを行い、コードを乾燥した状態に保つことです。


1
+1:任意の制限は、arbitrarily意的にのみ有用です。メソッドには、単一の抽象化レベルで単一の一貫した操作を含める必要があります。このようなアトミックユニットを壊すと、コードがより複雑になり、コードの理解が難しくなります。
アロングラネネク

DRYは過大評価されています。多くの場合、密結合ではない何かの2つの側面を密結合することを意味します。
ブラッドトーマス

4

まあ、それは少し依存します。データベースにアクセスするコードをたくさん書いています。例外処理のボイラープレートコードは、多くの場合7ステートメント以上です。私の最高のガイドラインは、あなたの機能に一つの目的があることを確認することだと思います


8
定型コードを独自のメソッドに抽象化することはできませんか?
-erjiang

投稿した後、これはJavaではなくC#であることに気付きましたが、この種のことを考えています。stackoverflow.com/questions/321418/…–
ジェイディー

@erjang:できます。Javaでは、各クエリを匿名クラスでラップする必要があるため、非常に見苦しくなりますが、実行する価値はあります。C#ではそれほどugくなく、間違いなくやりがいがあります。
ケビンクライン

個人的には、いくつかの余分な行を読みやすくすることができます。しかし、おそらくそれは私だけです。
ジェイディー

@Jaydeeリンクされた質問は、一般的ではあるが奇妙なプラクティスを示しています。例外をラップしてロギングすることです。次のレベルでは、同じことを行うことができます。この方法では、ログに単一の例外が複数回表示されます。スローするメソッドを宣言し、3行保存した方が良いでしょう。との両方psを閉じるヘルパーメソッドを記述し、rs別のメソッドを保存します。またはList<Row> readDb(String sql, Object... args)、ジョブ全体を実行するメソッドを作成します(メモリに収まる結果セットに対してのみ機能しますが、通常、大量のデータをフェッチすると、DBで作業を行う必要があります)。
maaartinus 14

4

すべてがトレードオフです。提案されたアプローチの問題-各メソッドが短くなるようにいくつかのメソッドとクラスにリファクタリング-は、さまざまな理由で、極端に取られた場合に読み取り不能なコードにつながることです。

foo()7つのことを行うメソッドを想像してください。あなたは7つのことは多すぎると主張するかもしれません。たぶん多くの場合、あなたは正しいです。一方、これらの7つのことは密接に関連している可能性があります。ロジックはスムーズに流れ、散文のように読みます。実際に必要なときに理解するのに問題はないかもしれません。さらに悪いことに、これらの7つのものを大きなソースツリー全体に分散させるとfoo()、7つの異なる場所を見なくても何が起こるかわかりません。

多くの人々が頭の中でこのようなルールを取得し、その結果はOOスパゲッティと私が思うものです。すべてがきちんとしていて、独自の小さなメソッドまたはクラスで囲まれ、各場所でアトミックな小さなマイクロトランザクションが発生しています。しかし、そのようなコードベースに新鮮になり、それが何をしているのかを知ることは不可能です。あなたは迷子になります。


4

それは悪いガイドラインではありません。それらが十分にグループ化され、相互に関係している限り、メソッドとクラスを分割したことを後悔したことはありません(多すぎることはありません)。

トリックは、垂直に分割しないことです(ある時点でメソッドをつまんで、新しいメソッドを開始するだけです)。単体テストの場合と同様に、最初からこのようなルールを念頭に置いて、実際に設計を改善し、メソッドの途中で3つまたは4つのステートメントを別のメソッドに渡すことで、メソッド呼び出しがあなたがより良いことを記述しているため、コードの途中にある3つまたは4つのステートメント。

この種の分割は、それがand意的で一度しか使用されない場合でも、コードの新しい明快さのために、より良いリファクタリングにつながる可能性があります。これは小さなクラスにも当てはまります。

単体テストのように考えてください。事実の後にユニットテストを追加しようとすると、それは難しく、時には不可能に思えますが、最初からデザインする場合、実際にはすべてのコードが改善されます。

概要?「7個未満のステートメントを使用する」というデザインの匂いと「7個を超えるステートメントを使用した」というコードの匂いを比較する場合、むしろコードの匂いをなくしたいと思います。


4

うわー!私は、あなたの方法は非常に小さくすべきだと大雑把に言っている単純なガイドラインで、このような激しい議論を見つけることを決して期待していませんでした。彼らは常にガイドラインを明確にしたい開発者なので、私は7を選択します。

文書の冒頭ですでに免責事項を引用している人もいます。しかし、明確にするために、このドキュメントは、より良いコードを記述し、より良いシステムを設計するのに役立つガイドラインのコレクションを表しています。ガイドラインがレベル1としてマークされている場合でも、何もルールであるべきだとは言いませんでした。これらのレベルは、このドキュメントをしばらく使用している多くの人々の集合的な意見です。

また、専門家であると主張したこともありません。しかし、私はこの職業に15年間携わっており、約4年のC ++の経験と11年のC#の経験があります。もともとはIndustrial Strength C ++に基づいていましたが、それ以来、コミュニティからの意見で改良を続けてきました。

とにかく、私が提起しようとしていたポイントは、あなた自身のために考え続けなければならないということです。7つのステートメントのガイドラインが役に立たないと思われる場合は、単に長くしてください。ちなみに、私は時々このガイドラインに違反しています。私はそれを意識して違反し、結果を受け入れます。


3
良い声でお話しします、そして、私はあなたが合理的な議論をすると思います。そうは言っても、「彼らは常にガイドラインを明確にしたい開発者だ」というあなたの論理的根拠に同意しません。ガイドラインを明示的にすることは、これがそれらを不正確にしない限り、良いことです:今ではガイドラインではなく、それはarbitrary意的なルールです。あなたが目撃したように、任意の数字を導入することは、撃shotされ、正当化される死んだ特定の方法です。
コンラッドルドルフ

3

まず、これはガイドラインであり、ルールではありません。ガイドラインと呼ばれるので、そのように扱ってください。これは、(常に)あなた自身の判断も必要であることを意味します

それとは別に、この制約に従わない優れたコードの例がたくさん考えられます。単なるガイドラインであるにもかかわらず、貧弱なものです。


2

私は上の声明に同意します。これは単なるガイドラインであり、完璧な世界ではすべてがオブジェクトとなり、すべてのプログラムで再利用され、世界は美しい場所になります。それは常に真実であるとは限らず、時にはそれは多くのオーバーヘッドや無駄なリソースにつながるでしょう。それも念頭に置く必要があります。


6
「私の上の声明に同意します」stackexchangeサイトでこの種の文を避けてください。回答が投稿される順序は、必ずしも表示される順序ではないことに
注意してください。– luiscubal

手遅れになるまでは考えませんでした。しかし、私はまだ私のおならを指摘するためにあなたを+1します。
-Falcon165o

2

混合物に例外処理を追加すると、非常にばかげています。

"try、catch、finally"の後、メソッドごとに4つのステートメントが残ります。

また、20個のフィールドフォームのメソッド "validateForm"を検討します。個々の検証をすべて別のメソッドで処理する場合でも、呼び出すフィールド検証メソッドは20個あります。これらのガイドラインによると、「validateTopOfScreen」、「validateMiddleOfScreen」、「validateBottomOfScreen」のような無意味な分割になります。


try/ catch/ finallyはC#のステートメントではないと言うのはかなり安全だと思います。Ecma-334§12.3.3.15およびその周辺のセクションを参照してください。(省略) " 形式ののtry-catch-finally文を:試みる試行ブロックキャッチ(...)キャッチブロック-nがついについに-ブロック "
からCVn

さて、私が前に言ったように、それはあなたが何度も何度もしなければならない決定です。ただし、特定の例は、オブジェクト指向の設計を正しく行わない例です。画面を、検証を行う複数のコントロールに分割することもできます。
デニスドゥーメン

@Dennis-true、HTMLフォームの実行時間が長すぎます!
ジェームズアンダーソン

@Jamesそして、それがこの特定のガイドラインの目的です。代替の、潜在的にはより良いソリューションを考えさせようとしています。
デニスドゥーメン

2

問題は、「ルール」と「ガイドライン」を混同することです。ルールは従うことを意味します-ガイドラインは、あなたが何をしているのか、それが本当にもっと良い方法でできるのかを検討させるためのアドバイスです。

平均して、ほとんどのプログラミングはおそらくガイドラインに従うことで改善されると思いますが、ガイドラインを独断的に守ると、意図したよりも多くの問題が発生する場合が常にあります。それがルールとしてではなくガイドラインとして提示されている理由です。

以前の回答者は、ガイドラインの作成者がそれらを独断的に適用することを決して意図していないことを示しており、その効果に関する記述をドキュメントに含めました。


0

上記のコメントの一部に同意します。私にとって7は任意であり、Rubyのある言語では役立つかもしれませんが、C#、Java、C ++のような言語では、この「7行」の規則を疑います。私の現在のアプリケーションには22のテキストフィールドがあり、サーバー側の検証を行っています。このメソッドはvalidateInput()と呼ばれ、checkEmailFormat()のような複雑なものを検証しない限り、私の好みは1つのメソッド自体のすべてのフィールドを検証します。したがって、基本的に、validateInputメソッドのコードは108行であり、時々複雑な検証を呼び出します。

次に、各フィールドを検証するために25のメソッドを呼び出した場合を想像してください。新しい開発者が入ってきた場合、彼はメインメソッドに出入りして25のメソッドをジャンプする必要があり、これらのメソッドは他のいくつかのメソッドを呼び出している可能性があります。彼は大きなプロジェクトで迷子になります。

コードを明確にするために私が本当にしていることは、基本的にこれらの4行が元々何をしているのかを明確にコメントすることです。

validateInput(UserObj user){

//名の検証....... ......

//姓の検証...... ......

//電子メールの検証..... //電子メールの形式を確認するには複雑すぎる通常の表現checkEmailFormat(); .... .....

等々.. }


1
James Andersonsの質問に対する私の回答も参照してください。あなたの特定のケースでは、その検証方法が同時にいくつかの原則とガイドラインに違反していないのだろうかと思います。
デニスドゥーメン

0

悪いルール。例外処理、データベースフィールドの設定、検証のコードでは、ほとんどのメソッドはどのようにして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());   });

繰り返しになりますが、1つの方法で多くのことを行うという素晴らしい例です。ほとんどすべての反論において、人々は(メソッドの文脈において)単一責任原則に違反しています。
デニスドゥーメン

-1

すべてのジュニアプログラマは、この原則に従うように強制する必要があります。それは彼らに忙しいものの構造を考えるように強制するでしょう、単により多くの行コードを追加するのではなく。

私は現在、たくさんのif elseステートメントと継続し、それに織り込まれたリターンを持つ550行のコードのメソッドを探しています。それはがらくたです。プログラマーが自分がやっていることについて考えることだけを強いられていた...

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