寻找一些面向对象的设计建议


12

我正在开发一个应用程序,该应用程序将用于在工业环境中打开和关闭阀门,并且正在考虑这样的简单操作:-

public static void ValveController
{
    public static void OpenValve(string valveName)
    {
        // Implementation to open the valve
    }

    public static void CloseValve(string valveName)
    {
        // Implementation to close the valve
    }
}

(该实现会将一些字节的数据写入串行端口以控制阀门-从阀门名称派生的“地址”,以及“ 1”或“ 0”来打开或关闭阀门)。

另一个开发人员问我们是否应该为每个物理阀创建一个单独的类,其中有几十个。我同意,最好使用PlasmaValve.Open()而不是编写类似的代码ValveController.OpenValve("plasma"),但这是否太过分了?

另外,我想知道如何最好地考虑到一些假设的未来需求:

  1. 我们被要求支持一种新型的阀门,该阀门需要不同的值来打开和关闭它(不是0和1)。
  2. 我们被要求支持可以设置在0-100之间的任何位置的阀,而不是简单地“打开”或“关闭”。

通常,我会在这种情况下使用继承,但是最近我开始着手解决“继承之上的组合”问题,并想知道使用组合是否有一个更好的解决方案?


2
我将创建一个通用的阀门类,该类具有特定阀门的标识符(不是字符串,可能是枚举)以及OpenValve / CloseValve方法内部控制流所需的任何信息。或者,您可以使valv类抽象化,并为每个类单独实现,其中,如果不同的阀具有不同的打开/关闭机制,则打开/关闭阀仅调用给定阀类内的逻辑。通用机制将在基类中定义。
吉米·霍法

2
不必担心未来的假设要求。亚尼
pdr 2012年

3
@pdr YAGNI是双刃刀片,我认为一般来说都值得遵循,但是极端的话可以说为帮助将来的可维护性或可读性做任何事情都违反了YAGNI,因此,我发现YAGNI的范围过于模糊许多。就是说,许多人认识到在哪里使用YAGNI以及在哪里扔YAGNI,因为考虑到未来会为您节省很多痛苦。我只是认为应该谨慎地建议人们在您不知道YAGNI在该频谱上的位置时,遵循YAGNI。
吉米·霍法

2
伙计们,“对继承的构图”被高估了。我将创建一个Valve抽象类/接口,然后将其子类化为PlasmaValve。然后,我要确保我的ValveController可以与Valve一起使用,而不在乎它们到底是哪个子类。
MrFox 2012年

2
@suslik:绝对。我还看过不懂SOLID原理的人将其称为spaghetti的出色代码。我们可以永远继续下去。我的观点是,比起由于过度坚持而导致的失落,我看到了更多的因废除既有原则(多年经验而产生)而导致的问题。但是我同意这两种极端情况都是危险的。
pdr 2012年

Answers:


12

如果Valve对象的每个实例都将与此ValveController运行相同的代码,那么似乎一个类的多个实例将是正确的方法。在这种情况下,只需在Valve对象的构造函数中配置它控制哪个阀门(以及如何控制)。

但是,如果每个阀门控件都需要运行不同的代码,并且当前的ValveController运行的巨型switch语句根据阀门的类型执行不同的操作,则您实现的多态性很差。在这种情况下,将其重写为具有公共基础的多个类(如果有道理),并让单一责任原则成为您的设计指南。


1
+1表示基于类型的switch语句为代码气味。我经常在开发人员声称他只是跟随KISS的地方看到这些switch语句。设计原理如何变态的完美示例,呵呵
Jimmy Hoffa 2012年

2
多个实例还可以简化按顺序链接阀门的过程,从而使您可以将实际工厂管道建模为代码中的有向图。然后,您还可以向类中添加业务逻辑,以防万一您需要做一些事情,例如在另一个阀门关闭时打开一个阀门以避免积累压力,或者关闭所有下游阀门,以免产生“水锤”效应当阀门再次打开时。
TMN 2012年

1

我的主要抱怨是使用字符串作为用于识别阀门的参数。

至少创建一个Valve具有getAddress基本实现需求形式的类,并将其传递给,ValveController并确保您不能创建不存在的阀门。这样,您就不必在每个open和close方法中处理错误的字符串。

是否创建调用打开和关闭的便捷方法ValveController取决于您,但老实说,我会将与串行端口的所有通信(包括编码)都放在一个类中,其他类将在需要时调用。这意味着当您需要迁移到新控制器时,只需要修改一个类。

如果您喜欢测试,还应该制作ValveController一个单例,以便对其进行模拟(或为操作员创建训练机)。


我以前从未见过有人推荐单身人士进行测试-通常情况会相反。
卡扎尔克2012年

老实说,单身人士更多地是为了避免静电,因此通信可以同步
棘手的怪胎2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.