9

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?

gnat
20.5k29 gold badges117 silver badges308 bronze badges
asked Apr 18, 2013 at 23:15
4
  • What would be the purpose of a getter, other than adding an additional (and probably unnecessary) layer of indirection? Commented Apr 18, 2013 at 23:41
  • 4
    A getter is much better than multiple calls to WebConfigurationManager.AppSettings because it's much easer to change later Commented Apr 19, 2013 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. Commented Apr 19, 2013 at 19:30
  • 10
    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. Commented Apr 19, 2013 at 20:51

2 Answers 2

5

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.

answered Apr 19, 2013 at 3:25
3
  • thanks for your help, though I think when you said cohesion you really meant coupling. Commented Apr 24, 2013 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. Commented Apr 25, 2013 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. Commented Apr 25, 2013 at 2:37
4

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 GitHub at https://github.com/Enexure/Enexure.Fire.Configuration

There is even a nuget package:

PM> Install-Package Enexure.Fire.Configuration

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 );
 }
 }
 }
 }
 }
}
answered Apr 20, 2013 at 2:47

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.