Як інкапсулювати "глобальні" змінні в C #? /найкраща практика


9

У C #, яка найкраща практика для інкапсуляції змінних, яку мені потрібно використовувати в декількох методах? Чи добре просто оголосити їх у верхній частині мого класу над двома методами?

Крім того, якщо я використовую налаштування програми зі свого конфігураційного файлу, чи повинен я використовувати геттер? подобається це...

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

Яка найкраща практика?


Яка була б мета гетеру, крім додавання додаткового (і, мабуть, непотрібного) шару непрямості?
Роберт Харві

4
Геттер набагато краще, ніж багаторазові дзвінки, WebConfigurationManager.AppSettingsтому що згодом змінити набагато легше
Даніель Літтл

@Lavinski: Звичайно, якщо ви думаєте, що пізніше ви можете замінити сховище даних на інший. На практиці це трапляється рідко, і ймовірність того, що це може статися для AppSettings, видається суттєво малою.
Роберт Харві

10
Перевага "getter" має те, що він робить інтелігенційну роботу - і у вас є ключовий рядок "mySetting" (який не перевіряється компілятором, якщо його написано правильно) лише в одному місці.
Док Браун

Відповіді:


5

Це не просто гаразд. Згідно з книгою «Чистий кодекс» це насправді дуже хороша практика, і дядько Боб справді це заохочує. Змінна, використовувана багатьма методами, може виявити високий ступінь згуртованості між методами. Більше того, високий ступінь змінних об'єктів також може натякати, що зазначений клас слід розділити на два, так що оголошення їх як об’єктних змінних може допомогти вам знайти прихованих кандидатів у клас.

Змінні рівня об'єкта не є глобальними змінними, тому не бійтеся їх використовувати, якщо їм слід ділитися різними методами.


дякую за вашу допомогу, хоча я думаю, що коли ви сказали згуртованість, ви дійсно мали на увазі зв'язок.
користувач1944367

Ні, я мав на увазі згуртованість. На уроці програмного забезпечення також було важко зрозуміти прагнення до високої згуртованості. Зазвичай ми прагнемо після низької сполученості та високої згуртованості. З'єднання - це фізична річ, яку ми можемо побачити на власних методах. Якщо клас використовує інший клас, то він пов'язаний з ним. Якщо він фактично створює об'єкт і об'єкт згаданого класу, то це дуже пара до нього. Однак згуртованість - це більше логічна річ. Висока згуртованість у класі означає, що його методи належать до дуже схожої області, навіть якщо вони не поділяють між собою жодної змінної.
Uri

Різні методи, що використовують змінну об'єкта, не обов'язково означають, що вони з'єднані між собою. Я міг би мати клас Encrypter зі змінною паролем char [] та мати Encrypt (текст рядка); і Розшифрувати (рядовий текст); методи всередині нього. Вони обидва використовують одну і ту ж змінну пароля, але між ними немає явної зв'язку. Ви можете помітити, що вони мають справу з одним і тим же доменом, і це - шифрування тексту. Наскільки мені відомо, вони мають високий ступінь згуртованості, хоча зазначений клас можна розділити на два. Можна стверджувати, що шифрування не належить до області дешифрування.
Урі

4

Постійне інкапсулювання налаштувань - чудова ідея.

Що я роблю, це створити клас налаштувань або одного статичного глобального одного або декількох класів екземплярів, якими я потім керуватиму за допомогою введення залежності. Потім я завантажую всі налаштування від конфігурації до цього класу при запуску.

Я також написав невелику бібліотеку, яка використовує роздуми, щоб зробити це ще простіше.

Після моїх налаштувань у моєму конфігураційному файлі

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

Я роблю статичний або екземплярний клас залежно від моїх потреб. Для простих програм із лише кількома налаштуваннями один статичний клас чудово.

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] );

Весь код для цього є у GitHub за адресою https://github.com/Enexure/Enexure.Fire.Configuration

Навіть є цілий пакет:

PM> Install-Package 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 );
                    }
                }
            }
        }
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.