我有一些实现了ICommand { Execute }接口的命令类。几个命令都有重复的代码段。我有几个选项来实现DRY(Don't Repeat Yourself):
- 创建静态帮助类并将重复代码移动到那里
- 创建命令继承,使用受保护的辅助方法
你会选择哪一个?为什么?
添加:感谢所有回复的人,许多答案都很相似且有用!
我有一些实现了ICommand { Execute }接口的命令类。几个命令都有重复的代码段。我有几个选项来实现DRY(Don't Repeat Yourself):
你会选择哪一个?为什么?
添加:感谢所有回复的人,许多答案都很相似且有用!
除了静态类之外,另一个选项是将公共代码放入一个新类中,并使用依赖注入将助手类注入到命令中。这也符合组合优于继承的概念。
在你自己的代码中使用帮助程序是一种源于懒惰的不良实践。
唯一可能需要帮助程序的情况是扩展第三方库(如selenium等)中封闭类的行为。
什么是帮助程序?它是一个静态方法,位于类本身之外的某个地方。
我们会遇到哪些问题呢?
何时使用帮助程序?当您需要扩展第三方库而无法继承它时。否则,只需继承库即可。
何时不使用帮助程序?为了减少重复代码。您需要将此代码移动到另一个服务中。阅读有关DDD的内容以提高重构技能,并了解如何以最佳方式组织服务。
这里可能没有一个正确/错误的答案,尽管我想你肯定可以实现得很糟糕。这很大程度上取决于您的实际要求以及您的命令之间的关系。一般来说,我可能会选择基类实现和继承层次结构,假设命令相关且代码直接与命令本身相关,而不是与某个外部实体相关,该实体应该是其自己的类。当然,它们通过它们是命令这一事实相关联,并且基类可以反映出来。
如果您有仅适用于无关命令子集的公共代码,并且创建继承层次结构将强制存在不存在的关系,则添加“helper”类(如果可能,则为非静态,以提高可测试性)将是解决问题的完全自然的方法。您可能会发现,您可以自然地将“helper”方法分组到它们自己的类中。例如,如果几个方法需要与您的身份验证子系统交互,则可以为这些方法设置AuthenticationMediator。我也认为两者都可以做一些。
public IRandom
{
byte NextByte ();
}
public static class IRandomExtensions
{
// logic that acts against public interface IRandom
// may be applied to all implementations
public static int GetNextUnbiasedInteger (this IRandom random) { }
public static IEnumerable<T> Shuffle<T> (
this IRandom random,
IEnumerable<T> items) { }
}
如果业务逻辑针对实现成员进行操作,
public class SomeCommand : ICommand
{
// an implementation-specific member, NOT a member
// of ICommand
public int SomeControlCount { get; set; }
}
// a method that references implementation-speciic
// details. where should this go?
public void DoSomething ()
{
SomeCommand command;
int count = command.SomeControlCount;
}
那么我们应该将其与实现类更紧密地绑定。如果这是一个足够常见的情况,则可能需要一个基类。
个人认为,复杂的继承结构会带来比它们所值得的更多麻烦,请根据可维护性、可读性和可重用性自行判断,你应该没问题!
希望这可以帮到你!:)
无状态代码使用辅助程序。
具有多个方法的状态相关代码使用继承。例如,当多个方法使用共享成员变量并因此维护共享状态时。
目标是减少重复代码的数量,这取决于代码的类型。然而,我真的很讨厌人们过度使用这种方法,并制作超级抽象的类或帮助函数,这些类或函数跳转到其他奇怪的抽象代码,例如“Executor”、“Invoker”、“DataConveyer”、“DataManager”、“SharedCode”。最终,它们确实完成了它们应该完成的工作,但它们之间相互关联,以至于您不确定在哪里进行新更改以添加此新功能。我应该在DataConveyer中还是在DataManager中进行呢?
因此,黄金目标应该是保持简单。