Bagaimana cara merangkum variabel 'global' dalam C #? /praktek terbaik

9

Dalam C # apa praktik terbaik untuk merangkum variabel yang perlu saya gunakan dalam beberapa metode? Apakah saya tetap bisa mendeklarasikan mereka di bagian atas kelas saya di atas dua metode?

Juga jika saya menggunakan pengaturan aplikasi dari file konfigurasi saya, haruskah saya menggunakan pengambil? seperti ini...

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

Apa praktik terbaik itu?

pengguna1944367
sumber
Apa yang akan menjadi tujuan pengambil, selain menambahkan lapisan tipuan tambahan (dan mungkin tidak perlu)?
Robert Harvey
4
Seorang rajin rajin jauh lebih baik daripada beberapa panggilan ke WebConfigurationManager.AppSettingskarena lebih mudah untuk mengubah nanti
Daniel Little
@ Lavinski: Tentu, jika Anda berpikir Anda mungkin menukar data store dengan yang lain nanti. Dalam praktiknya, itu jarang terjadi, dan kemungkinan itu mungkin terjadi untuk AppSettings tampak semakin kecil.
Robert Harvey
10
Sebuah "pengambil" memiliki keuntungan yang membuat intellisense berfungsi - dan Anda memiliki string "mySetting" (yang tidak diperiksa oleh kompiler jika ditulis dengan benar) hanya di satu tempat.
Doc Brown

Jawaban:

5

Itu tidak hanya baik-baik saja. Menurut buku Clean Code itu sebenarnya praktik yang sangat bagus, dan Paman Bob benar-benar mendorongnya. Variabel yang digunakan oleh banyak metode dapat menunjukkan tingkat kohesi yang tinggi di antara metode-metode tersebut. Selain itu, variabel objek tingkat tinggi juga bisa mengisyaratkan bahwa kelas tersebut harus dibagi menjadi dua sehingga mendeklarasikannya sebagai variabel objek dapat membantu Anda mengetahui kandidat kelas tersembunyi.

Variabel level objek bukan variabel global, jadi jangan takut untuk menggunakannya jika mereka harus dibagi dengan berbagai metode.

Uri
sumber
terima kasih atas bantuan Anda, meskipun saya pikir ketika Anda mengatakan kohesi Anda benar-benar bermaksud berpasangan.
user1944367
Tidak, maksud saya kohesi. Di kelas Rekayasa Perangkat Lunak juga saya kesulitan memahami keinginan untuk kohesi yang tinggi. Biasanya kita bernafsu dengan kopling rendah dan kohesi tinggi. Coupling adalah hal fisik yang dapat kita lihat dengan metode kita sendiri. Jika suatu kelas menggunakan kelas lain, maka digabungkan dengannya. Jika itu benar-benar instantiate dan objek dari kelas tersebut, maka itu sangat pasangan untuk itu. Namun, kohesi lebih merupakan hal yang logis. Kohesi tinggi dalam suatu kelas berarti bahwa metodenya termasuk dalam domain yang sangat mirip, bahkan jika mereka tidak berbagi variabel apa pun di antara mereka.
Uri
Berbagai metode menggunakan variabel objek tidak harus berarti bahwa mereka digabungkan bersama. Saya dapat memiliki kelas Encrypter dengan variabel kata sandi char [], dan memiliki Enkripsi (teks string); dan Dekripsi (teks string); metode di dalamnya. Keduanya menggunakan variabel kata sandi yang sama, tetapi tidak ada sambungan yang jelas di antara mereka. Anda mungkin memperhatikan, bagaimanapun, bahwa mereka berurusan dengan domain yang sama, dan itu adalah, enkripsi teks. Sejauh yang saya tahu, mereka memiliki tingkat kohesi yang tinggi, meskipun kelas tersebut dapat dibagi menjadi dua. Orang dapat berargumentasi bahwa enkripsi bukan milik domain dekripsi.
Uri
4

Meringkas pengaturan Anda secara konstan adalah ide bagus.

Apa yang saya lakukan adalah membuat kelas pengaturan baik global statis satu atau beberapa kelas instan yang kemudian akan saya kelola dengan injeksi ketergantungan. Lalu saya memuat semua pengaturan dari konfigurasi ke kelas itu saat start up.

Saya juga menulis perpustakaan kecil yang menggunakan refleksi untuk membuatnya lebih mudah.

Setelah pengaturan saya di file konfigurasi saya

<?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>

Saya membuat kelas statis atau instance tergantung pada kebutuhan saya. Untuk aplikasi sederhana dengan hanya beberapa pengaturan, satu kelas statis baik-baik saja.

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

    public int PagingSize { get; set; }

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

}

Kemudian menggunakan panggilan perpustakaan saya baik Inflate.Staticatau Inflate.Instancedan yang keren adalah saya dapat menggunakan sumber nilai kunci apa pun.

using Fire.Configuration;

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

Semua kode untuk ini ada di GitHub di https://github.com/Enexure/Enexure.Fire.Configuration

Bahkan ada paket nuget:

PM> Instal-Paket Enexure.Fire.Configuration

Kode untuk referensi:

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 );
                    }
                }
            }
        }
    }
}
Daniel Little
sumber