【发布时间】:2013-11-30 00:40:23
【问题描述】:
1) 简介
我已经开始在 Python 中实施一个工具,该工具收集多个系统指标(例如 cpu 利用率、cpu 饱和度、内存错误等)并将它们呈现给最终用户。此工具应理想地支持尽可能多的平台(Linux、FreeBSD、Windows 等)。
我已经针对一些我认为重要的指标为 Linux 系统完成了此工具的实现,并且我刚刚开始为 FreeBSD 系统实现相同的指标。此工具的设计方式必须允许支持更多系统指标和未来更多的平台。此外,很快将添加一个网络界面,并将接收来自我的工具的数据。
2) 到目前为止我的设计决策
由于上述原因,我决定在 Python 中实现该工具(方便在许多系统上从不同来源读取数据,而且,我对它有点熟悉 :))和我为每个系统指标遵循一个类结构(继承很重要,因为某些系统共享功能,因此无需重写代码)。此外,我已经确定我有一个使用工厂方法的有效用例。
2.1) 类结构
这是 CPU Metrics 的示例类图(为了问题而进行了简化):
CpuMetrics (Abstract Base Class)
/ | \
/ | \
/ | \
/ | \
/ | \
/ | \
LinuxCpuMetrics FreeBSDCpuMetrics WindowsCPUMetrics (per OS)
/ \
/ \
/ \
/ \
/ \
/ \
/ \
ArchLinuxCpuMetrics DebianLinuxCpuMetrics (sometimes important per Distro or Version)
2.2) 工厂方法
在名为CpuMetrics的抽象基类中定义了一些抽象方法,应通过继承类和一个名为get_impl()的工厂方法来实现。我对何时应该使用工厂方法进行了一些研究(例如,this 之类的答案),我认为在我的情况下使用它是有效的。
例如,我希望客户端(例如我的 Web 界面)调用我的工具来获取 CPU 利用率指标,如下所示:
cpu_metrics = CpuMetrics.get_impl() # factory method as an alternative constructor
cpu_metrics.get_cpu_util() # It is completely transparent for the client which get_cpu_util() is returned.
3) 我的担忧和我的问题(最后)
按照上面分析的设计,我的工厂方法知道我们现在在哪个系统上是非常重要的(“这是Linux,Windows?我现在应该带哪个实现?”)。因此,我必须高度依赖诸如platform.system() 之类的函数或其替代品。所以我的工厂方法所做的是(大致再次):
def get_impl():
"""Factory method returning the appropriate implementation depending on system."""
try:
system = platform.system() # This returns: { Linux, Windows, FreeBSD, ... }
system_class = getattr("cpu", system + "CpuMetrics" )
except AttributeError, attr_err:
print ("Error: No class named " + system + "CpuMetrics in module cpu. ")
raise attr_err
return system_class()
我对此感到非常不舒服,原因有两个:
1) 我强迫未来的程序员(甚至我自己)遵循他的类的命名约定。例如,如果有人决定扩展我的系统,比如说,对于 Solaris,他绝对必须将他的类命名为 SolarisCpuMetrics。
2) 如果在 Python 的未来版本中修改了 platform.system() 的值(或我将选择使用的其他替代方法),那么我必须更改我的命名约定并大量修改我的工厂方法。
所以我的问题:是否有解决我问题的方法?我的代码会变得不可读或我的担忧无效吗?如果您认为有一种解决方法,我需要多少修改/重构我的代码和更改我的设计?
我没有从头开始设计项目的经验,所以我可以参考任何建议。另外,我在 Java 方面有更多经验。在编写 Python 时,我尝试以尽可能多的 Python 方式思考,但有时无法在两者之间进行适当的分离。您的建设性批评非常可取。
【问题讨论】:
标签: python