简体   繁体   English

条件代码的更好方法

[英]Better approach for conditional code

I have some code with a large number of constants defined inside #if DEBUG... #else blocks; 我在#if DEBUG... #else块中定义了一些带有大量常量的代码; 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. 使用此设置的源文件很多,其中大多数在DEBUG块和else块中具有不匹配的常量。 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. 我正在尝试通过删除巨大的DEBUG块来解决此问题,但是我需要同时保留长字段名和短字段名的定义,同时还要确保添加新的错误名称确实很困难。 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. 我使用#if DEBUG没问题,但是感觉很脏,如果有一个更干净的解决方案,我希望这样做。

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 . 恕我直言,我认为您可以使用类似Factory Pattern(工厂模式)( http://www.oodesign.com/factory-pattern.html )或使用DI(Depedency Injection-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. 这样,您应该删除公共静态C类,并且可以使用下面的其他解决方案。

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. 这样,您就不会只用#if调试每个字符串来绑定解决方案,并且使用工厂模式实例化“正确的”常量,因此您无需担心每个字符串之间的关系。

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. PS .:我没有测试此代码,但它应该可以工作。

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. 您将在配置文件中配置的Depedency注入解决方案,系统应如何实现接口类(IConstantClass),因此您不需要每次都实例化Factory类。

You could change my code and pass a Interface to the class in the constructor or a property with the correct solution. 您可以更改我的代码,并使用正确的解决方案将接口传递给构造函数中的类或属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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