简体   繁体   中英

Better approach for conditional code

I have some code with a large number of constants defined inside #if DEBUG... #else blocks; something like:

public static class C
{
    #if DEBUG
        public const string FIELDAAA = "VeryLongDescriptiveFieldName";
        public const string FIELDBBB = "AnotherLongDescriptiveFieldName";
        public const string FIELDCCC = "YetAnotherLongFieldName";

        // ... many more field definitions
    #else
        public const string FIELDAAA = "F1";
        public const string FIELDBBB = "F2";

        // Notice that FIELDCCC is missing - whoever added it to the
        // DEBUG block, forgot to add it here.
    #endif
}

These fields are used in building textual requests to a 3rd-party server - the server can take field names in either form. Using the short form is a lot more efficient, though, because each message has a size-limit and when a request becomes too big, it has to be broken up into several messages. Each message carries a cost so our software should use the short field names in production and the long names during development (for debugging).

There are a number of source files with this setup and most of them have mismatching constants in the DEBUG-block and in the else-block. Because of these mismatches, parts of this application cannot be built in release mode because of missing constants.

I'm trying to fix this by removing the huge DEBUG blocks but I need to keep both long and short field name definitions while making sure that it's really hard to add a new one incorrectly. I also want to keep the number of changes to a minimum - this is in a big application used by a lot of users and I don't want to introduce a breaking change - these fields are used in a number of places.

Currently this is what I have in mind:

public static class C
{
    public const string FIELDAAA =
        #if DEBUG
        "VeryLongDescriptiveFieldName";
        #else
        "F1";
        #endif

    public const string FIELDBBB = 
        #if DEBUG
        "AnotherLongDescriptiveFieldName";
        #else
        "F2";
        #endif

    public const string FIELDCCC = 
        #if DEBUG
        "YetAnotherLongFieldName";
        #else
        "F3";
        #endif

    // more constants
}

I don't know if I have a mental block but I can't think of anything significantly better. Is there a better approach that would get me what I'm trying to do but with a less messy setup? I don't have a problem using #if DEBUG but this feels dirty and if there's a cleaner solution, I'd prefer that.

Yes there is !!. ( always )

IMHO i think you could use something like Factory Pattern ( http://www.oodesign.com/factory-pattern.html ) or use a DI (Depedency Injection - https://en.wikipedia.org/wiki/Dependency_injection .

This way you should remove the public static C class and you could use a another solution like this below.

This way you don't tie your solution with only #if debug each string, and you use the factory pattern to instantiate the "right" constants so you don't need to worry between each string.

Your code will compile because the Interface demands that each class implement the properly, and the property without a set will not allow the programmer to change the content.

In the class that is using your constant you could do.

public class UsingClass
{
    IConstantClass constants;
    public UsingClass(){
         constants f = new FactoryConstants();
    }
}

public class FactoryConstant
{
   public FactoryConstant()
   {
   }
   public IConstantClass GetConstant()
   {
       #if DEBUG
       return new ConstantsDebugMode();
       #else
       return new ConstantsProduction();
       #endif
   }
}

public interface IConstantClass
{
   public string FIELDAAA {get;set;}
   public string FIELDBBB {get;set;}
} 

public class ConstantsProduction : IConstantClass
{
   public string FIELDAAA
   {
       get { return "ProductionString"; }
       set { }
   }
   public string FIELDBBB
   {
       get { return "ProductionString2"; }
       set { }
   }
}

public class ConstantsDebugMode : IConstantClass
{
   public string FIELDAAA
   {
       get { return "ReallyLongStringDebugMode"; }
       set { }
   }
   public string FIELDBBB
   {
       get { return "ReallyLongStringDebugMode2222"; }
       set { }
   }
}

PS.: I didn't test this code but it should work.

The Depedency injection solution you will configure in a config file how the system should implement the interface class (IConstantClass) so you don't need need to instantiate each time the Factory Class.

You could change my code and pass a Interface to the class in the constructor or a property with the correct solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM