3

由于需求来回变化,我们的代码中有一些使用 const 的 if/else 块,例如:

const bool DisplayAverageValues = true;
if(DisplayAverageValue)
{
  // Do this
}
else
{
  // Do that
}

由于需求可能会再次发生变化,我们不想删除当前未使用的代码 - 下周可能需要它。我们也不想注释掉未使用的代码,因为我们希望它成为任何重构的一部分。只需更改布尔值,它就可以随时进行编译。

问题是我们收到了无法访问代码的警告,所以我正在考虑用预处理器#if/#else 替换标准的 if/else 块。

#define DisplayAverageValues
#if DisplayAverageValue
  // Do this
#else
  // Do that
#endif

我现在面临的问题是预处理器符号不能设置为false,它只能定义或未定义。从以下位置更改会更加明显:

#define DisplayAverageValues true

#define DisplayAverageValues false

代替

#undef DisplayAverageValues

或者

//#define DisplayAverageValues

(如果在其他地方使用了相同的符号名称,这可能会导致麻烦)。

有没有更好的办法?

4

3 回答 3

2

当您的代码架构中有精确切片时,如果一个代码必须是可编译的并且不与其他代码相交,那么预处理器指令非常有用。在您的情况下,您似乎面临不同的选项,这些选项也可能在代码执行流程中与需求相交。

在我看来,管理它的最佳方法是定义一个Options,RuntimeConfigurations或其他任何类,它包含所有会影响您的应用程序运行时行为的属性,并沿着您的部分传递该类的实例(可能也是一个)Singletone必须考虑不同执行选项的应用程序。

正如 Daniel 所说,另一个选择是将代码提取到不同的模块、插件中,如果你愿意的话,然后动态加载它们。但是它可能实现也可能不实现,顺便说一下,如果之前在您的架构中没有考虑到它,您通常需要花费不相关的时间来实现这种级别的灵活性。

于 2013-05-06T10:21:51.017 回答
1

处理器指令似乎不是为这种情况设计的。从 SOLID 的角度来看,您应该执行以下操作:

1)创建一些界面:

public interface IDoingSomething {
  void Do();
}

2)创建此接口的2个实现:

public class DoingThis : IDoingSomething {
  public void Do() {
    // Do this
  }
} 

public class DoingThat : IDoingSomething {
  public void Do() {
    // Do that
  }
} 

3)在应用程序起点的某个地方读取配置并决定使用哪个实现:

IDoingSomething doerSomething;

if(DisplayAverageValue) {
  doerSomething = new DoingThis();
} else {
  doerSomething = new DoingThat();
}

4)现在在代码中使用你的接口对象来做一些事情:

doerSomething.Do();

这是一种策略模式,它允许您拥有多个实现,只在一个地方在它们之间切换,并且不需要任何代码更改,除了具有具体接口实现的类。这有利于代码维护、可扩展性等。

于 2015-12-30T08:22:55.520 回答
0

评论和 Tigran 的回答中有一些很好的建议,但现在我将继续使用一个仍然易于理解的简单解决方案。通过删除符号名称,毫无疑问如何在需要时更改代码:

#if true
  // Display average values
  ...
#else
  // Do not display average values
  ...
#endif
于 2013-05-07T13:49:35.443 回答