C#で「グローバル」変数をカプセル化する方法 /ベストプラクティス


9

C#で、複数のメソッドで使用する必要がある変数をカプセル化するためのベストプラクティスは何ですか?2つのメソッドの上の私のクラスの先頭で単にそれらを宣言することは問題ありませんか?

また、設定ファイルのアプリ設定を使用している場合、ゲッターを使用する必要がありますか?このような...

private string mySetting{ get { return WebConfigurationManager.AppSettings["mySetting"]; } }

ベストプラクティスは何ですか?


インダイレクションの追加の(そしておそらく不要な)レイヤーを追加する以外に、ゲッターの目的は何でしょうか?
ロバートハーベイ

4
ゲッターは、はるかに優れた複数の呼び出しよりにあるWebConfigurationManager.AppSettings、それは後で変更することがずっとeaserだから
ダニエル・リトル

@Lavinski:もちろん、後でデータストアを別のデータストアに交換する可能性がある場合は、実際には、そのようなことはめったに起こらず、AppSettingsで発生する可能性は非常に小さいようです。
ロバートハーベイ

10
「getter」には、インテリセンスを機能させるという利点があり、キー文字列「mySetting」(正しく記述されている場合はコンパイラーによってチェックされません)が1か所にしかありません。
Doc Brown

回答:


5

それだけでは問題ありません。本「クリーンコード」によると、それは実際には非常に良い習慣であり、ボブおじさんは本当にそれを奨励しています。多くのメソッドで使用される変数は、メソッド間で高度のまとまりを示す可能性があります。さらに、高度なオブジェクト変数は、そのクラスを2つに分割する必要があることを示唆している可能性があります。オブジェクト変数としてそれらを宣言すると、隠れたクラスの候補を見つけるのに役立ちます。

オブジェクトレベルの変数はグローバル変数ではないため、さまざまなメソッドで共有する必要がある場合でも、それらを使用することを恐れないでください。


あなたの助けに感謝しますが、結束と言ったとき、あなたは本当にカップリングを意味したと思います。
user1944367 2013

いいえ、まとまりを意味しました。ソフトウェアエンジニアリングのクラスでも、高い結束力への欲求を理解するのに苦労しました。通常、低カップリングと高凝集度を求めます。結合は、私たち自身の方法で見ることができる物理的なものです。クラスが別のクラスを使用する場合、それはそれに結合されます。それが実際にインスタンス化され、そのクラスのオブジェクトである場合、それはそれに非常に関連しています。ただし、結束はより論理的なものです。クラスの凝集度が高いということは、メソッド間で変数を共有していなくても、そのメソッドが非常に類似したドメインに属していることを意味します。
Uri

オブジェクト変数を使用するさまざまなメソッドは、それらが一緒に結合されることを必ずしも意味しません。char []パスワード変数を含むEncrypterクラスを作成し、Encrypt(string text)を作成することもできます。およびDecrypt(string text); その中のメソッド。どちらも同じパスワード変数を使用しますが、両者の間に明らかな結合はありません。ただし、同じドメイン、つまりテキスト暗号化を扱っていることに気付くでしょう。私の知る限り、これらのクラスは非常にまとまりがありますが、このクラスは2つに分割できます。暗号化は復号化のドメインに属していないと主張することができます。
Uri

4

一定の方法で設定をカプセル化することは素晴らしいアイデアです。

私が行うことは、1つの静的グローバル1つまたは複数のインスタンスクラスのいずれかの設定クラスを作成して、依存関係の注入で管理することです。次に、起動時にすべての設定を構成からそのクラスにロードします。

また、リフレクションを利用してこれをさらに簡単にする小さなライブラリも作成しました。

設定が私の設定ファイルにあると

<?xml version="1.0" encoding="utf-8" ?>
<configuration>   
    <appSettings>
        <add key="Domain" value="example.com" />
        <add key="PagingSize" value="30" />
        <add key="Invalid.C#.Identifier" value="test" />
    </appSettings>
</configuration>

必要に応じて、静的クラスまたはインスタンスクラスを作成します。設定が少ない単純なアプリケーションの場合、1つの静的クラスで十分です。

private static class Settings
{
    public string Domain { get; set; }

    public int PagingSize { get; set; }

    [Named("Invalid.C#.Identifier")]
    public string ICID { get; set; }

}

次に、ライブラリ呼び出しを使用するか、Inflate.StaticまたはInflate.Instance任意のキー値ソースを使用できるのがすばらしいです。

using Fire.Configuration;

Inflate.Static( typeof(Settings), x => ConfigurationManager.AppSettings[x] );

このためのすべてのコードは、https://github.com/Enexure/Enexure.Fire.Configurationの GitHubにあります。

nugetパッケージさえあります:

PM>インストールパッケージEnexure.Fire.Configuration

参照用コード:

using System;
using System.Linq;
using System.Reflection;
using Fire.Extensions;

namespace Fire.Configuration
{
    public static class Inflate
    {
        public static void Static( Type type, Func<string, string> dictionary )
        {
            Fill( null, type, dictionary );
        }

        public static void Instance( object instance, Func<string, string> dictionary )
        {
            Fill( instance, instance.GetType(), dictionary );
        }


        private static void Fill( object instance, Type type, Func<string, string> dictionary ) 
        {

            PropertyInfo[] properties;
            if (instance == null) {

                // Static
                properties = type.GetProperties( BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly );
            } else {

                // Instance
                properties = type.GetProperties( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly );
            }

            // Get app settings and convert
            foreach (PropertyInfo property in properties) {
                var attributes = property.GetCustomAttributes( true );
                if (!attributes.Any( x => x is Ignore )) {

                    var named = attributes.FirstOrDefault( x => x is Named ) as Named;

                    var value = dictionary((named != null)? named.Name : property.Name);

                    object result;
                    if (ExtendConversion.ConvertTo(value, property.PropertyType, out result)) {
                        property.SetValue( instance, result, null );
                    }
                }
            }
        }
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.