Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In C# what is the best practice for encapsulating variables I need to use in multiple methods? Is it OK to simply declare them at the top of my class above the two methods?

Also if I am using app settings from my config file should I use a getter? like this...

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

What best practice is?

share|improve this question

We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations. Answers that don't include explanations may be removed.

    
What would be the purpose of a getter, other than adding an additional (and probably unnecessary) layer of indirection? –  Robert Harvey Apr 18 '13 at 23:41
3  
A getter is much better than multiple calls to WebConfigurationManager.AppSettings because it's much easer to change later –  Daniel Little Apr 19 '13 at 1:01
    
@Lavinski: Sure, if you think you might swap out the data store for a different one later. In practice, that seldom happens, and the likelihood that it might happen for AppSettings seems vanishingly small. –  Robert Harvey Apr 19 '13 at 19:30
9  
A "getter" has the advantage that it makes intellisense work - and you have the key string "mySetting" (which is not checked by the compiler if its written correctly) only in one place. –  Doc Brown Apr 19 '13 at 20:51
add comment

3 Answers

up vote 4 down vote accepted

It's not just OK. According to the book Clean Code it's actually a very good practice, and Uncle Bob really encourages it. A variable used by many methods could show a high degree of cohesion between the methods . Moreover, a high degree of object variables could also hint that said class should be split in two so declaring them as object variables could help you find out hidden class candidates.

Object level variables aren't global variables, so don't be afraid to use them if they should be shared by various methods.

share|improve this answer
    
thanks for your help, though I think when you said cohesion you really meant coupling. –  user1944367 Apr 24 '13 at 19:37
    
No, I meant cohesion. On Software Engineering class also I had a hard time understanding the desire for high cohesion. Usually we lust after low coupling and high cohesion. Coupling is a physical thing that we can see on our own methods. If a class uses another class, then it's coupled to it. If it actually instantiates and object of said class, then it's very couple to it. However, cohesion is more of a logical thing. High cohesion in a class means that its methods belong to a very similar domain, even if they don't share any variable between them. –  Uri Apr 25 '13 at 2:31
    
Various methods using an object variable don't necessarily mean that they are coupled together. I could have a Encrypter class with a char[] password variable, and have Encrypt(string text); and Decrypt(string text); methods inside it. Both of them use the same password variable, but there's no apparent coupling between them. You may notice, however, that they deal with the same domain, and that is, text encryption. As far as I know, they have a high degree of cohesion, although said class could be split in two. One could argue that encryption doesn't belong to the domain of decryption. –  Uri Apr 25 '13 at 2:37
add comment

Encapsulating your settings in a constant manner is a great idea.

What I do is create a settings class either one static global one or multiple instance classes which I'll then manage with dependency injection. Then I load all the settings from configuration into that class on start up.

I've also written a little library that makes use of reflection to make this even easier.

Once my settings are in my config file

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

I make a static or instance class depending on my needs. For simple applications with only a few settings one static class is fine.

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

    public int PagingSize { get; set; }

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

}

Then using my library call either Inflate.Static or Inflate.Instance and the cool thing is I can use any key value source.

using Fire.Configuration;

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

All the code for this is in bitbucket at https://bitbucket.org/Lavinski/fire

There is even a nuget package http://nuget.org/packages/Fire/

Install-Package Fire

Code for reference:

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 );
                    }
                }
            }
        }
    }
}
share|improve this answer
add comment

I like to do extension methods off of the app settings, this makes it clear where the value comes from and provides type safety and only one place where I have to get the raw string right (none if you can use VS.2012, C#5 and the new caller info attributes).

I do the same thing for session variables. The less magic strings the better.

As for your first question - they can technically go anywhere, but in general should be declared as close to the usage as reasonably possible. For class variables that are used by just one function, then just above the function (one of the places VB has C# beat imo).

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.