#regionsはアンチパターンまたはコードの匂いですか?


265

C#では、#region/ #endregionキーワードを使用して、エディターでコードの領域を折りたたみ可能にすることができます。これを行うたびに、おそらく他のクラスやメソッドにリファクタリングされる可能性のある大きなコードの塊を隠すためにそれを行います。たとえば、管理しやすくするために、3つまたは4つの領域を持つ500行のコードを含むメソッドを見てきました。

地域の賢明な使用は問題の兆候でしょうか?私にはそう思われます。


9
参考までに、CodeMapは地域のニーズをほとんど排除します。visualstudiogallery.msdn.microsoft.com/…-クリックすると、method / attribute / whateverに移動します。私は毎日それを使用していますが、生産性と認知の面でどれだけ利益を得ているかは驚くべきことです。クラスのより明確な「鳥瞰図」が得られます。

7
誰でもこれをwikiにすることはできますか?この質問に対する正しいまたは間違った答えはありません(まあ、理由の範囲内で)、それはほぼ完全に主観的です。
エドS.

6
それが価値があることのために、ジェフ・アトウッドは彼らを嫌っている。彼は彼らが悪いコードを隠すと主張します。
ブライアン

3
コードの匂いは、シャワーを浴びず、消臭剤を使用しない開発者です!
マルコ

5
悪臭を放つコードで丁寧に作成されたリージョンは、Febreezeのいくつかの絞り込みが無愛想なソファで行うことです。あなたがそれを交換するための(時間)お金を見つけるまで、それは耐えられます。
ニュートピア

回答:


285

コードにおいは、潜在的にバグの数を増やす可能性のあるデザインに問題があることを示す症状です。これはリージョンの場合ではありませんが、リージョンは長いメソッドのようにコードの匂いの作成に寄与する可能性があります。

以来:

アンチパターン(またはアンチパターン)とは、一般的に使用される可能性のあるソーシャルまたはビジネスオペレーションまたはソフトウェアエンジニアリングで使用されるパターンですが、実際には非効率的および/または逆効果です

領域アンチパターンです。コードの品質や可読性を向上させたり、バグの数を減らしたりすることなく、コードのリファクタリングをより複雑にするだけの、より多くの作業が必要です。

メソッド内で領域を使用しないでください。代わりにリファクタリング

メソッドは短くなければなりません。メソッドに10行しかない場合、他の5行で作業するときに、5行を非表示にするためにリージョンを使用することはおそらくないでしょう。

また、各メソッドは1つだけのことを行う必要があります。一方、リージョンは異なるもの分離することを目的としています。メソッドがAを実行し、次にBを実行する場合、2つの領域を作成することは論理的ですが、これは間違ったアプローチです。代わりに、メソッドを2つの個別のメソッドにリファクタリングする必要があります。

この場合にリージョンを使用すると、リファクタリングがさらに難しくなる可能性があります。あなたが持っていると想像してください:

private void DoSomething()
{
    var data = LoadData();
    #region Work with database
    var verification = VerifySomething();
    if (!verification)
    {
        throw new DataCorruptedException();
    }

    Do(data);
    DoSomethingElse(data);
    #endregion

    #region Audit
    var auditEngine = InitializeAuditEngine();
    auditEngine.Submit(data);
    #endregion
}

最初の領域を折りたたんで2番目の領域に集中するのは危険であるだけでなく、フローを停止する例外を簡単に忘れることができます(return代わりにガード句があり、それを見つけるのはさらに困難です)。この方法でコードをリファクタリングする必要がある場合:

private void DoSomething()
{
    var data = LoadData();
    #region Work with database
    var verification = VerifySomething();
    var info = DoSomethingElse(data);

    if (verification)
    {
        Do(data);
    }

    #endregion

    #region Audit
    var auditEngine = InitializeAuditEngine(info);
    auditEngine.Submit(
        verification ? new AcceptedDataAudit(data) : new CorruptedDataAudit(data));
    #endregion
}

現在、リージョンは意味をなさないため、最初のリージョンのコードを見なくても、2番目のリージョンのコードを読んで理解することはできません。

私が時々見る別のケースはこれです:

public void DoSomething(string a, int b)
{
    #region Validation of arguments
    if (a == null)
    {
        throw new ArgumentNullException("a");
    }

    if (b <= 0)
    {
        throw new ArgumentOutOfScopeException("b", ...);
    }
    #endregion

    #region Do real work
    ...
    #endregion
}

引数の検証が数十のLOCにまたがり始めたときに領域を使用するのは魅力的ですが、この問題を解決するためのより良い方法があります。

public void DoSomething(string a, int b)
{
    if (a == null)
    {
        throw new ArgumentNullException("a");
    }

    if (b <= 0)
    {
        throw new ArgumentOutOfScopeException("b", ...);
    }

    InternalDoSomething(a, b);
}

private void InternalDoSomething(string a, int b)
{
    ...
}

メソッド以外の領域をグループ化しないでください

  • 一部の人々はそれらを使用してフィールド、プロパティなどグループ化します。このアプローチは間違っています。コードがStyleCopに準拠している場合、フィールド、プロパティ、プライベートメソッド、コンストラクタなどはすでにグループ化されており、簡単に見つけることができます。そうでない場合は、コードベース全体で均一性を確保するルールを適用することを検討してください。

  • 他の人々は地域を使用して多くの同様の実体隠します。たとえば、100個のフィールド(コメントと空白を数えると少なくとも500行のコードが作成される)を持つクラスがある場合、それらのフィールドを領域内に配置し、折りたたんで、忘れてしまいがちです。繰り返しますが、あなたはそれを間違っています:クラスに非常に多くのフィールドがあるので、継承を使用するか、オブジェクトをいくつかのオブジェクトにスライスすることを考える必要があります。

  • 最後に、一部の人々は、関連するものグループ化するために領域を使用するように誘惑されます:デリゲートを伴うイベント、またはIOに関連する他のメソッドを伴うIOに関連するメソッドなど。 、読んで理解する。2番目のケースでは、おそらく複数のクラスを作成する方が適切です。

地域に適した用途はありますか?

いいえ。従来の使用法:生成されたコードがありました。それでも、コード生成ツールは、代わりに部分クラスを使用する必要があります。C#にリージョンサポートがある場合、これは主にこのレガシー使用であり、コードでリージョンを使用する人が多すぎるため、既存のコードベースを壊さずにそれらを削除することは不可能だからです。

について考えてみてくださいgoto。言語またはIDEが機能をサポートしているという事実は、その機能を毎日使用する必要があるという意味ではありません。StyleCop SA1124ルールは明確です。リージョンを使用しないでください。決して。

現在、同僚のコードのコードレビューを行っています。コードベースには多くのリージョンが含まれており、実際には、リージョンを使用しない方法と、リージョンが悪いコードにつながる理由の両方の完璧な例です。ここではいくつかの例を示します。

4000 LOCモンスター:

私は最近、usingPrograms.SEのどこかで、ファイルに含まれるsの数が多すぎる場合(「Unused Usingsを削除」コマンドを実行した後)、このファイル内のクラスが多すぎることを示しています。同じことがファイル自体のサイズにも当てはまります。

コードを確認しているときに、4000 LOCファイルに出会いました。このコードの作成者は、同じ15行のメソッドを何百回もコピーアンドペーストし、変数の名前と呼び出されたメソッドをわずかに変更したように見えました。単純な正規表現では、ジェネリックをいくつか追加するだけで、ファイルを4000 LOCから500 LOCにトリミングできました。より巧妙なリファクタリングにより、このクラスは数十行に削減される可能性があると確信しています。

リージョンを使用することにより、著者は、コードを維持することが不可能であり、記述が不十分であるという事実を無視し、コードをリファクタリングするのではなく複製することを奨励しました。

地域「Do A」、地域「Do B」:

別の優れた例は、単純にタスク1、タスク2、タスク3などを実行するモンスター初期化メソッドです。完全に独立した5〜6つのタスクがあり、それぞれがコンテナクラスの何かを初期化します。これらのタスクはすべて1つのメソッドにグループ化され、リージョンにグループ化されました。

これには1つの利点がありました。

  • この方法は、地域名を見ると理解しやすいものでした。これは、リファクタリングされた同じメソッドが元のメソッドと同じくらい明確になると言われています。

一方、問題は複数ありました。

  • リージョン間に依存関係があるかどうかは明らかではありませんでした。うまくいけば、変数の再利用はありませんでした。そうしないと、メンテナンスがさらに悪夢になる可能性があります。

  • メソッドをテストすることはほぼ不可能でした。一度に20のことを行うメソッドがそれらを正しく行う場合、どのように簡単にわかりますか?

フィールド領域、プロパティ領域、コンストラクター領域:

また、レビューされたコードには、すべてのフィールド、すべてのプロパティなどをグループ化した多くの領域が含まれていました。これには、ソースコードの増加という明らかな問題がありました。

ファイルを開いてフィールドの膨大なリストを見ると、最初にクラスをリファクタリングしてからコードを操作する傾向が強くなります。地域では、物を折りたたんでそれを忘れる習慣があります。

別の問題は、どこでもそれを行うと、1ブロックの領域を作成することに気付くということです。これは意味がありません。これは、実際に私がレビューしたコードの場合で、#region Constructor1つのコンストラクターがたくさん含まれています。

最後に、フィールド、プロパティ、コンストラクターなどはすでに順番に並んでいるはずです。それらが慣例(大文字で始まる定数など)に一致する場合、要素のタイプがどこで停止し、他の要素が始まるかはすでに明らかなので、そのための領域を明示的に作成する必要はありません。


13
#regionsには少なくともいくつかの防御可能な用途があると思います。たとえば、ガード句の折りたたみ(入力パラメーターのチェック)は、そのままにしておくと、メソッドの要点または「肉」を損なうことになります。別の例は、API境界での例外処理です。他のメソッドを呼び出して例外をラップすることでスタックトレースに影響を与えたくない場合が多いので、ラップして再スローするコードの行がいくつかあります。多くの場合、これは無関係なコードであり、安全に折りたたむことができます。
ダニエルB

9
リアリティチェック。役に立つメソッド間#regionをたくさん見ました。数十行から数百行のネストされた制御ロジックを備えた数百行のメソッドを使用する場合は、少なくとも領域に配置されたバカに感謝します。
レーダーボブ

37
@radarbob:要するに、リージョンは、そもそも存在してはならないくだらないコードで役立ちます。
アルセニムルゼンコ

41
-1(評判があった場合)。タイプメンバが適切に編成され、分離されている場合でも、多くのメンバが存在する可能性があります。リージョンを使用すると、操作したいメソッドにたどり着くために、10個または12個のプロパティと関連するgetterおよびsetterをスクロールする必要がなくなります。唯一の選択肢は、すべてのプロパティを個別に折りたたむことです。これは私が好きではありません。リージョンが提供する大規模な表示/非表示機能は非常に便利です。ただし、メソッド内リージョンについては同意します。
アサドSaeeduddin

14
私はこの答えに厳密に同意しません。コードの悪臭と地域は互いに関係がありません。コードが悪臭を放つ場合、リージョンの有無にかかわらず悪臭を放ちます。リージョンを使用する方法は、クラスをリージョンに分離することです。一般に、私は同じパターンに固執します:パブリックプロパティ、パブリックメソッド、プライベートフィールド、プライベートメソッド。それが私がリージョンを持っている唯一の用途です。それ以外の場合は、おそらくコード内のSRPプリンシパルが壊れています。
アレクサス

113

多くの人が地域をそれほど情熱的に憎んでいるのは信じられないことです!

私は彼らの多くの異議に完全に同意します:コードをa #regionに押し込んでビューから隠すことは悪いことです。クラスを#regions個別のクラスにリファクタリングする必要がある場合に分割することは明らかに間違いです。を使用し#regionて冗長なセマンティック情報を埋め込むことは、冗長です。

しかし、これらのことは、コードで領域を使用することに本質的に問題があることを意味するものではありません!ほとんどの人々の反対は、他の人がこのようなIDE機能を誤って使用する傾向があるチームで働いたことに起因すると推測できます。プライマリーを自分で作業する贅沢があり、地域が私のワークフローを整理するのに役立っていることに感謝しています。強迫神経症のせいかもしれませんが、どれほどきちんとエレガントに書かれていても、一度にたくさんのコードを画面に表示するのは好きではありません。物事を論理的な領域に分けることで、自分がやろうとしているコードで作業することに関心のないコードを折りたたむことができます気にします。私は不適切に記述されたコードを無視しているわけではありません。それ以上リファクタリングする意味はありません。

C ++での作業により多くの時間を費やし、Windows APIに直接プログラミングするようになったので、地域のサポートがC#のサポートと同じくらい良いことを望んでいます。別のGUIライブラリを使用すると、コードがより簡単または明確になり、無関係なコードノイズを画面から取り除く必要がなくなると主張できますが、そうしないことには別の理由があります。キーボードとIDEに十分習熟しているため、リージョンに細分化されたコードの展開/折りたたみに要する時間は1秒未満です。私が意識的に集中しているのは、現在取り組んでいるコードだけに制限しようとする、頭の力で節約する時間です。すべてが単一のクラス/ファイルに属しますが、すべてが同時に画面に属しているわけではありません。

ポイントは#regions、コードを分離して論理的に分割することは、どんな犠牲を払っても避けるべき悪いことではないということです。エドが指摘するように、それは「コード臭」ではありません。コードの匂いがする場合、それはその地域からではなく、その地域に埋めようとしたコードからであると確信できます。機能がより整理されたり、より良いコードを書くのに役立つなら、私はそれを使うと言います。それが邪魔になったり、間違って使用していることに気付いた場合は、使用を中止してください。最悪の事態が発生し、それを使用する人々とチームで作業することを余儀なくされた場合、キーボードショートカットを記憶して、コードのアウトラインをオフにします:Ctrl+ MCtrl+P。文句を言うのを止めてください。これが、「真の」「ハードコア」プログラマーとして見られたいと思う人たちが自分自身を証明しようとする別の方法だと感じることがあります。構文の色付けを避けるよりも、領域を避けるほうがましです。それはあなたをよりマッチョな開発者にするわけではありません。

そうは言っても、メソッドの領域はまったくナンセンスです。それをやりたいと思うときはいつでも、別のメソッドにリファクタリングする必要があります。言い訳しない。


9
よく言った。組織でのリージョンの使用は、IDEの「空白の表示」オプションを切り替えることほど有害ではありません。それは個人的な好みです。
ジョシュ

24
モデルにプロパティを単純にラップする10個または20個のプロパティを持つViewModelでWPFを操作している場合、リージョンが大好きです-それらのプロパティをリージョンに押し込めるだけで(触れる必要はありません)、関連するコードに注意を払うことができます。
カークブロードハースト

4
完全に同意する。.NET 2.0では、プロパティの長さは約8〜10行です。クラスに20を超えるプロパティがある場合、それらは多くのスペースを占有します。リージョンは、それらを折りたたむのに最適です。
クリストフクレス

6
@Kristof:.NET 4.0のプロパティは、単純な入力検証を行います。自動プロパティは、私の目的にとってそれほど魔法ではありませんでした。
コーディグレイ

8
地域を嫌う人々がWPFアプリケーションを開発したことがないか、データバインディングやコマンドバインディングなどのWPFの定義機能を実際に使用したことがないという左のボールを喜んで賭けます。これらの作業を行うようにコードを設定するだけで多くのスペースが必要になり、通常はそれらを再度確認する必要はありません。
l46kok

70

まず、「コードのにおい」という言葉にもう耐えられません。それはあまりにも頻繁に使用され、噛み付くと良いコードを認識できなかった人々によって投げられます。いずれかの方法...

私は個人的に多くの地域を使うのが好きではありません。コードを取得するのが難しくなり、コードは私が興味を持っているものです。私は、頻繁に変更する必要のないコードの大部分があるとき、リージョンが好きです。それを除けば、彼らは私の邪魔をしているように見え、「プライベートメソッド」、「パブリックメソッド」などの地域は私を夢中にさせます。彼らはさまざまなコメントに似ていますi++ //increment i

また、リージョンの使用は、テキストエディタのレイアウトではなく、プログラムロジック/デザインパターンを記述するために一般的に使用されるため、実際には「アンチパターン」にはなり得ないことを付け加えます。これは主観的です。あなたのために働くものを使用してください。アンチパターンがすべての目的である領域の過剰使用のために、保守不能なプログラムになることは決してありません。:)


2
通常、コードの匂いコメントについてはあなたに投票しますが、この場合は正確です。非コードはコードの匂いではありません。+2!

7
ハハ、まあ、「コードの匂い」という用語を正確に使用できないと言っているわけではありません。それはできますが、最近はあまりにも多くのことを投げかけられているので、私の即時の反応は、特にそれを理解したり批判的に考えたりせずに聞いていることを本当に繰り返している人々から来る場合、単に迷惑です。「関数内の5つ以上のローカル変数はコードのにおいです」などのステートメントは、その人が実際に経験したことがどれほど少ないかを示しています。
エドS.

13
コードのにおいについてのあなたのコメントを理解しているかどうかはわかりません。コードのにおいは問題があることを示すものではなく、問題がある可能性があります。
クレイグ

7
用語コードの匂いに立ち向かうための+1。プライベートメソッドがコードの匂いだと主張する投稿を見て、うんざりしました。しかし、全体的に私は地域に対するあなたの嫌悪に反対します。私は簡単に気を取られます。実際、VSにVB4モードがあり、一度に1つのメソッドのみを表示できる場合、それが気に入っています。
ジョシュ

7
完璧に良い隠phorを悪用しても隠phorを軽んじてはならないと言いたいだけです。「コードのにおい」は、すぐに理解され、覚えやすく、簡単に使用できる優れた隠metaです。「コードのにおい」のメタファーを適用することが依然としてポイントを得るための最良の方法である場所はまだたくさんあります。
エリックキング

23

はい、地域はコードの匂いです!

コンパイラからリージョンが完全に削除されるのを見てうれしいです。すべての開発者は、他のプログラマーにとって決して価値のない独自の無意味なグルーミングスキームを考え出します。本当の価値とは関係なく、自分の赤ちゃんを飾り付けて美しくしたいプログラマと関係があります。

あなたが「そうだ、私の同僚がここでいくつかの地域を使っていたらいいのに!」

すべてのリージョンを自動的に拡張するようにIDEを構成することはできますが、それでも目障りであり、実際のコードの読み取りを妨げます。

すべての公開メソッドがまとめられているかどうかは、あまり気になりません。おめでとうございます。変数宣言と初期化の違いを知っています。コードで表示する必要はありません!

価値のないグルーミング!

さらに、リージョンの使用によってファイルに「情報アーキテクチャ」が必要な場合は、コアの問題に対処することができます。クラスが大きすぎます!それを小さな部分に分割することははるかに有益であり、適切に行われると真の意味論/読みやすさが追加されます。


#regionsはコンパイラの一部ですか?それらはIDEに対する単なる指令であり、無視できるものだと思いました。
スティーブルクッツ

2
コンパイラは、C#コードを解析するときにそれらを無視する必要があります。それらを無視しない場合、それらをスローします。そういう意味です。
ジョッペ

1
「あなたが「そうだ、私の同僚がここでいくつかの地域を使用したい!」はい、とてもそうです。プライベートメソッドとパブリックメソッドを持つクラスがある場合、パブリックメソッドをリファクタリングするときにプライベートコードに触れる必要は必ずしもなく、またその逆も必要ないため、それらをリージョンに分割します。
アンシュル

あなたは明らかにアウトソースされたコードを見たことがない。アウトソーシングされたコードで見れば、地域は何度も素晴らしいものになっていたでしょう。たとえコードがひどいものであっても、少なくとも論理的な意味でグループ化されていれば、少なくとも理解しやすいでしょう。ただし、コードが論理的なチャンスでない場合、リージョンもそうではないため、おそらくそれを悪化させていただろう。ただし、適切に使用するとリージョンは素晴らしいです。
-Nickmccomb

15

個人的には、さまざまなタイプのメソッドやコードの一部をグループ化する方法としてリージョンを使用しています。

したがって、コードファイルは、開くと次のようになります。

  • パブリックプロパティ
  • コンストラクター
  • メソッドを保存する
  • メソッドの編集
  • プライベートヘルパーメソッド

メソッド内に領域を配置しません。私見はコード臭のサインです。私はかつて1200行以上の長さで、5つの異なる領域を持つメソッドに出会いました。怖い光景でした!

他の開発者がより速く物を見つけられるようにコードを整理する方法としてそれを使用している場合、私はそれが問題の兆候だとは思わない。メソッド内のコード行を隠すためにそれを使用している場合、そのメソッドを再考する時が来たと思います。


14
あー 私はこれが主観的なトピックであることを知っていますが、男、私は本当にこのスキームに耐えられません。私の経験では、追加された「組織」はまったく役に立たず、コードを閲覧するのが苦痛になります。また、アクセス修飾子だけでなく論理的責任によってメソッドをグループ化することも好みます。パブリックインターフェイスの場合、通常、各メソッド/プロパティをグループ化しますが、多くの場合、保護されたメソッドはプライベートヘルパー関数を呼び出すことがあります。それを呼び出すメソッド。
エドS.

3
@Ed S.-それが私が「のように見えるかもしれない」と言った理由です。それは非常に主観的です。すべてのファイルがそのように見えるべきだと言っているわけではありません。彼らがそうするならば、私は驚くでしょう。複雑なトピックのほんの一例です。:)
ティアナ

ああ、私が言ったように知っています。主観的です。あなた/あなたのチームのために働くものは何でも。私にとってはうまくいかないので、このスキームのためにそれを手に入れましたが、これを行うプロジェクトを維持しなければなりませんでした。それは私を夢中にさせました。
エドS.

3
@EdS。そのため、vsでオプションを選択し、リージョンをオフにします。問題が解決しました。
アンディ

オブジェクトにsaveメソッドがあるのはなぜですか?:(
TheCatWhisperer

10

#regionブロックを使用して非常に大きなクラスを読みやすくすることは、通常、単一責任原則に違反する兆候です。グループ行動に使用されている場合、クラスがあまりにも多くのことを実行している可能性もあります(もう一度SRPに違反しています)。

「コードの匂い」の考え方に固執すると、#regionブロックはそれ自体ではコードの匂いではありませんが、匂いを隠そうとするという点で、より「コードのFebreze」です。私は過去にそれらを大量に使用していましたが、リファクタリングを開始すると、隠れていないため、表示が少なくなります。


5

ここでのキーワードは「賢明」です。メソッド内に領域を置くことが賢明な場合を想像するのは困難です。それはコード隠蔽と怠inessである可能性が高いです。ただし、コードのあちこちにいくつかの領域があることには、十分な理由があります。

たくさんの地域がある場合、それはコードのにおいだと思います。リージョンは、多くの場合、将来のリファクタリングの可能な場所のヒントです。多くの地域は、誰かが実際にヒントを得ていないことを意味します。

賢明に使用すると、多くのメソッドを持つ単一のクラスの構造と、それぞれに少数のメソッドがあるだけの多くのクラスの構造の間の良い中間点を提供します。これらは、クラスが複数のクラスにリファクタリングされるべきポイントに近づき始めたときに最も便利ですが、まだそこにはありません。関連するメソッドをグループ化することで、数が増え続けている場合に、関連するメソッドのセットを独自のクラスに後で簡単に抽出できるようにします。たとえば、500行のコードに近づいているクラスがある場合、ある領域で収集された合計200行のコードを使用するメソッドのセットは、おそらく何らかの形でリファクタリングするのに適しています。メソッドも良いターゲットかもしれません。

私が領域を使用するもう1つの方法は、大規模なメソッドをリファクタリングすることのマイナスの影響の1つを減らすことです。多くの小さく、簡潔で、簡単に再利用できるメソッドです。リージョンは、メソッドとそのヘルパーを読者にメタカプセル化する良い方法です。そのため、クラスの異なる側面で作業している人は、それらを折りたたんで、コードのその部分をすぐに却下できます。もちろん、これは、リージョンが非常によく整理されていて、コードをドキュメント化する別の方法として基本的に使用されている場合にのみ機能します。

一般的に、リージョンを使用すると、リージョンを使用しない場合よりもはるかに早く、自分自身を整理し、コードを「文書化」し、リファクタリングする場所を見つけるのに役立ちます。


4

主にCRUDサーバークラスの領域を使用して、さまざまな種類の操作を整理します。それでも、私は喜んで彼らなしで行くことができました。

広範囲に使用すると、レッドフラグが発生します。私は、あまりにも多くの責任を負うクラスに目を光らせています。

私の経験では、コードに数百行あるメソッドは間違いなく臭いです。


4

私の経験則では、ファイルに5つ以上の領域がある場合、コードのにおいです

すなわち、フィールド、メソッド、プロパティ、およびコンストラクターを記述することは問題ないかもしれませんが、それ自体の領域で他のすべてのメソッドをラップし始めている場合、何かが深刻に間違っています

..はい、多くの場合、コーディング標準、コード生成、またはその両方が不十分であるため、そのような場合に多くのプロジェクトに参加しています。コードの概要を把握するために、Visual Studioのすべてのアウトラインを切り替える必要があります。


4

地域に利用がある

Windowsフォームアプリの前に、「ハンドコーディング」インターフェイスイベントに個人的に使用しました。

ただし、私の作業では、SQLの処理にコードジェネレーターを使用し、自動的に領域を使用して、選択、更新、削除などのタイプのメソッドを整理します。

したがって、私は頻繁に使用しませんが、大きなコードの塊を削除するのにはまったく問題ありません。


1
同様のコードジェネレーターを使用しましたが、生成されたコードを削除するには部分クラスを使用することを好みます。
クレイグ

必要に応じて、リージョンは生成されたコード内にあり、読みやすく、デバッグしやすくなっています。
ケン

4

あなたは地域をお持ちの場合はINコードあなたは確かに(生成されたコードの場合を除けば。)問題を抱えているコード内の領域を置くことは基本的に「これをリファクタリング。」と言っています

ただし、他の場合もあります。しばらく前に思いついたのは、事前に計算されたアイテムが数千あるテーブルです。これはジオメトリの説明であり、テーブルにエラーがなければ、それを見る機会は決してありません。もちろん、リソースなどからデータを取得することもできますが、コンパイラーを使用して読みやすくすることはできません。


1
これは、別のファイルに保存された部分クラスの場合、またはHardcodedDataSource実装で挿入されたIMyDataSourceの場合のより良い使用例です。
ブライアンベッチャー

3

最近のプロジェクトでは、いくつかの領域が埋め込まれた1700行メソッドがありました。興味深いのは、メソッド内で実行されていた明確なアクションを領域が区別したことです。コードの機能に影響を与えることなく、各領域でリファクタリング->抽出メソッドを実行できました。

一般に、ボイラープレートコードを隠すために使用される領域は便利です。プロパティやフィールドなどを非表示にするためにリージョンを使用することはお勧めしません。クラス内で作業するときに見づらい場合は、クラスをさらに分解する必要がある兆候だからです。しかし、ハードルールとして、メソッド内に領域を配置する場合、そのブロックを領域にラップするよりも、何が起こっているのかを説明する別のメソッドを抽出した方がよいでしょう。


3

リージョンは、高品質のコードで使用できますか?恐らく。多くの場合、彼らはそうだと思います。しかし、私の個人的な経験から私は非常に疑わしいままです-私はほとんど排他的に誤用された地域を見てきました。私はうんざりしていますが、それでも楽観的です。

これまで見てきた地域を使用したコードを、3つのカテゴリに大まかに分けることができます。

  • 因数分解が不十分なコード:私が見たコードのほとんどは、貧しい人々の因数分解ツールとしてリージョンを使用しています。たとえば、さまざまな目的に特化することが理にかなっているクラスに成長したクラスは、代わりに、目的ごとに1つの別々の領域に分割される場合があります。

  • 問題ドメイン用に間違ったライブラリ、時には間違った言語を使用して記述されたコード多くの場合、プログラマーが問題ドメインに適切なライブラリのセットを使用していないと、コードが信じられないほど冗長になります-多くの小さなヘルパー関数実際には属していない(おそらく独自のライブラリに属しています)。

  • 学生または最近の卒業生によって書かれたコード。一部のプログラムとコースでは、あらゆる種類の奇妙な目的のために地域を使用して生徒に教えようとしています。リージョンタグとコードの行の比率が1:5以下の範囲になるまで、ソースコードを散らかすリージョンが表示されます。


3

「コードのにおい」だと思います。

アンチパターンは一般的にソフトウェアの基本的な構造上の問題ですが、リージョン自体はエディターで不快な動作を引き起こすだけです。リージョンを使用することは、本質的に悪いことではありませんが、特にコードのチャンクを隠すために頻繁に使用することは、他の独立した、より大きな問題が他の場所で起こっていることを示します。


@Andrew Grimm:ええ
-whatsisname

3

領域を使用するのは1つのことだけです(少なくとも、使用する他の場所は考えられません)。メソッドの単体テストをグループ化するためです。

通常、クラスごとに1つのテストクラスがあり、メソッドの名前を持つ領域を使用して、各メソッドの単体テストをグループ化します。それがコードの匂いなのか何かわからないが、基本的な考え方は、コード内の何かが変わったために壊れない限りユニットテストを変更する必要がないということなので、特定のメソッドのすべてのテストを見つけやすくするかなり早く。

過去にコードを整理するためにリージョンを使用したことがありますが、前回やったことを思い出せません。ただし、ユニットテストクラスでは地域にこだわっています。


1
複数のメソッドをテストするテストはありますか?
マーシー

私は質問やあなたが何を目指しているのか本当に理解していません。答えは、いいえ、ユニットテストは常に1つのメソッドのみ、または1つのメソッドの特定の側面を対象としています。
アンシュースラー

2

私はそれがアンチパターンであると信じており、率直に言ってそれらは排除されるべきだと思います。ただし、標準の場所で作業するという不幸な状況にある場合、Visual Studioは、地域見るたびに吐き出したい量を最小限に抑える素晴らしいツールを提供します。

このプラグインは、本当に小さい領域のフォントサイズを最大にします。また、すべてのリージョンを開くためにctr + m + lを押す必要がないように拡張されます。この形式のコードガンは修正されませんが、耐えられるようになります。


0

領域を使用して、可視性とメンバータイプの各組み合わせを含めます。したがって、すべてのプライベート関数は領域などに移動します。

これを行う理由は、コードを折りたたむことができるからではありません。これは、プロキシへの参照を挿入できるようにエディターをスクリプト化したためです。

#region "private_static_members"
 /// <summary>
 /// cache for LauncherProxy
 /// </summary>
private static LauncherProxy _launcherProxy;
#endregion

#region "protected_const_properties"
protected LauncherProxy LauncherProxy{
  get{
    if(_launcherProxy==null) {
      if (!God.Iam.HasProxy(LauncherProxy.NAME)) {
        God.Iam.RegisterProxy(new LauncherProxy());
      }
      _launcherProxy=God.Iam.Proxy(LauncherProxy.NAME) as LauncherProxy;
    }
    return _launcherProxy;
  }
}
#endregion

コードに入れ、各部分を適切な領域にきちんとはめ込みます。

この場合、マクロはプロジェクトを分析し、プロキシのリストボックスを提供して、必要なコードを挿入します。カーソルが動かない。

C#の学習の初めに、共通性を維持するためにリージョンを使用することを検討していましたが、それは常に1対1の関係ではないため、ヒットとミスの命題です。2つの地域で使用されているメンバーを心配したい人、またはそれらの条件で物事を分割し始めたい人。

他のタイプの分離はメソッドのみです。メソッドをコマンド、関数、ハンドラーに分割します。そのため、パブリック、プライベートなどのコマンド用の領域があります。

これにより粒度が決まりますが、一貫性があり明確な粒度で信頼できます。


-1が下り投票に125ポイントを獲得するとすぐに。不要なコード行を追加しています。なぜなぜあなたは財産周囲の領域を置くなぜ...(God.Iam.AbusingRegions()==真)がmyName =「マーク」場合
DeadlyChambers

1
@DeadlyChambers理由は2番目の段落に記載されています-エディターマクロを使用して一般的なコードパターンをファイルに挿入しています。リージョンはファイルを構造化して、類似のアイテムをグループ化するのに役立ちます。単一のプロパティの周りに領域を配置していませんが、すべてのプロパティは、属性「protected_const_properties」に応じて指定された領域に分類されます。投稿を読みましたか??
マーク14

1
おそらくそれを次のようにリファクタリングできます。protected LauncherProxy LauncherProxy => God.Iam.GetOrAddProxy <LauncherProxy>(ref _launcherProxy); したがって、地域は必要ありません。また、_launcherProxyは_launcherProxyCacheに名前変更できるため、リージョンやコメントは不要です。
エアロソン

0

領域はプリプロセッサ式です。つまり、コメントのように扱われ、コンパイラによって基本的に無視されます。これらは、Visual Studioで使用される純粋なビジュアルツールです。したがって、#regionは実際にはコード臭ではありません。コードではないからです。コードのにおいはむしろ800などのメソッドであり、さまざまな責任が組み込まれています。したがって、1つのメソッドに10の領域がある場合、おそらくコードのにおいを隠すために使用されています。非常に効果的に使用されているクラスを見たことがありますが、非常に効果的に使用されているクラスは、目を楽しませてナビゲートしやすくしています。


0

地域は気の利いた組織的なアイデアでしたが、すべてを過度に分類したい開発者の傾向を考慮に入れておらず、ほとんどの現代のOOPプラクティスでは一般的に不要です...あなたのクラス/メソッドがあまりにも大きく、あなたはおそらくSOLID原則の「S」に違反している...しかし、いずれの匂いのように、それはしないよう、リファクタリングすべきことは、必ずしも何かが悪い起こっている意味。

リージョンは、オブジェクト指向コードであるIMOよりも機能的なコードでより多くの目的に役立ちます。IMOでは、分割するのが理にかなっているシーケンシャルデータの長い関数を持っていますが、私はc#で個人的に使用したことがあり、ほとんど常に必要のない/見たくないコードに集中してください。私にとって、これらは通常NPocoまたはそのバリアントに使用されるコードベースの生のSQL文字列定数でした。ORMを介してデータがPOCOオブジェクトにどのように入力されるかを実際に気にしない限り、これらは完全に無意味でした...そして気にするなら、ちょっと地域とBAMを拡張するだけです!150行以上の複雑なSQLクエリが表示されます。

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