类的结构设计方法
The way to design structure of classes
我的 classes 结构非常简单。 Class B和C继承自A。在某些功能和属性的情况下,功能相似。 Class B 和 C 对数据的处理不同,但 classes 具有相同的输出(创建输出的函数在 A class 内部)。结构示例:
现在我需要扩展功能。我需要添加选项以在处理和数据输出方面存在一些差异 (class X)。此选项由配置文件管理,因此我想保留下载、处理和输出数据的旧方式,例如:
- 选项 1 - 使用 旧方法处理和输出 在没有 线程 的情况下下载数据
- 选项 2 - 使用新的处理和输出方式下载没有线程的数据
- 选项 3 - 使用 threads 下载数据,使用 old 方式处理和输出
- 选项 4 - 使用新方式处理和输出无需线程下载数据
我不确定如何实现新处理和输出数据的组合。我需要 Class B 和 X (BX) 以及 Class C 和 X (CX) 的组合。我考虑了这些选项:
- 最简单但最糟糕的方法 - 在 class B 和 class A 中复制一些函数。
- 保留 classes A 和 B 并添加 BX 和 AX classes 的组合。
- 重写classes A和B只为下载数据。然后添加classes用于处理数据,然后添加classes用于输出数据。所有 classes 将共享对象。看起来是最好的选择,但需要做的工作最多。
有没有更好的选择(例如设计模式或类似的东西)如何以最干净的方式扩展 classes?
在我看来你有一个Dataflow。
你拥有的是获取(下载)数据 -> 处理数据 -> 输出数据.这基本上是一个具有三个阶段的管道。
如果您使用对象来为您建模,则有两种类型的对象:执行操作的对象和一种或多种管理数据流和操作顺序的对象。
让我们使用三个接口(您可以使用抽象 classes 来定义它们并不重要)来定义管道的步骤:IDataDownloader, IDataProcessor 和 IDataOutputer.
让我们添加另一个对象来表示和管理管道:
(注意:我没有python的经验,所以我会用C#写它抱歉..)
public class Pipeline {
private IDataDownloader mDataDownloader;
private IDataProcessor mDataProcessor;
private IDataOutputer mDataOutputer;
public void Setup() {
// use a config file to select between the two ways
if (Config.UseOldWayDownloader) {
mDataDownloader = new OldWayDownloader();
}
else {
mDataDownloader = new NewWayDownloader();
}
// ....
// or you can use service locator or dependecy injection that will get
// a specific downloader based on configuration/setup
mDataDownloader = Services.Get<IDataDownloader>();
// ....
}
public void Execute() {
var data = mDownloader.Download();
var processedData = mDataProcessor.Process(data);
mDataOutputer.Output(processedData);
}
}
这样你会变得很好 separation of concerns 并且你会得到一个可以扩展的模块化系统。该系统也是可组合的。您可以用不同的方式组合它的各个部分。
看起来工作量更大,但事实并非如此。干净的设计通常更容易编写和扩展。
的确,您可能会多写一些代码,但是由于设计简洁,您可以更快地编写此代码,并且可以节省调试时间。调试是我们编写软件的大部分时间,但它经常被程序员忽视,认为他们只能通过编写和代码行来衡量。
松散类型语言就是一个例子。很多时候你写的代码越少越胖,但是很容易因为错误而出错。万一出错,你会得到更多(有时更难)调试,这样你就浪费了时间。
如果您从一个简单的概念验证应用开始,它们将显着加快开发速度。一旦您达到了拥有经过测试的强大软件的地步,就会有不同的力量介入。
为了确保您的软件健壮,您必须编写更多测试和更多 checks/assertions 以确保一切 运行 顺利进行。所以最后你可能会有相同数量的代码,因为强类型会为你做一些检查,你可以写更少的测试。
那什么更好呢?嗯...这取决于。
有几个因素会影响开发速度。这
程序员对一门语言的品味和经验。该应用程序也会对此产生影响。有些应用程序更容易用松散类型的语言编写,而另一些则更容易用强类型语言编写。
速度可以不同,但并不总是这样,有时只是一样。
我认为,在您的情况下,您会浪费更多时间来尝试获得正确的层次结构并对其进行调试,即使最后您的代码少了几行。在较长的 运行 中,如果您需要扩展它,拥有一个更难理解的设计会大大降低您的速度。
在管道方法中添加新的下载、处理或输出数据的方法就是添加单个 class。
好吧,为了让它成为 UML 答案,我添加了 class 图:
Pipeline
提到了这三个处理 classes。它们都是抽象的,因此您需要以不同的方式实现它们。 configuration
将根据配置(文件)的内容分配它们。
我的 classes 结构非常简单。 Class B和C继承自A。在某些功能和属性的情况下,功能相似。 Class B 和 C 对数据的处理不同,但 classes 具有相同的输出(创建输出的函数在 A class 内部)。结构示例:
现在我需要扩展功能。我需要添加选项以在处理和数据输出方面存在一些差异 (class X)。此选项由配置文件管理,因此我想保留下载、处理和输出数据的旧方式,例如:
- 选项 1 - 使用 旧方法处理和输出 在没有 线程 的情况下下载数据
- 选项 2 - 使用新的处理和输出方式下载没有线程的数据
- 选项 3 - 使用 threads 下载数据,使用 old 方式处理和输出
- 选项 4 - 使用新方式处理和输出无需线程下载数据
我不确定如何实现新处理和输出数据的组合。我需要 Class B 和 X (BX) 以及 Class C 和 X (CX) 的组合。我考虑了这些选项:
- 最简单但最糟糕的方法 - 在 class B 和 class A 中复制一些函数。
- 保留 classes A 和 B 并添加 BX 和 AX classes 的组合。
- 重写classes A和B只为下载数据。然后添加classes用于处理数据,然后添加classes用于输出数据。所有 classes 将共享对象。看起来是最好的选择,但需要做的工作最多。
有没有更好的选择(例如设计模式或类似的东西)如何以最干净的方式扩展 classes?
在我看来你有一个Dataflow。
你拥有的是获取(下载)数据 -> 处理数据 -> 输出数据.这基本上是一个具有三个阶段的管道。
如果您使用对象来为您建模,则有两种类型的对象:执行操作的对象和一种或多种管理数据流和操作顺序的对象。
让我们使用三个接口(您可以使用抽象 classes 来定义它们并不重要)来定义管道的步骤:IDataDownloader, IDataProcessor 和 IDataOutputer.
让我们添加另一个对象来表示和管理管道:
(注意:我没有python的经验,所以我会用C#写它抱歉..)
public class Pipeline {
private IDataDownloader mDataDownloader;
private IDataProcessor mDataProcessor;
private IDataOutputer mDataOutputer;
public void Setup() {
// use a config file to select between the two ways
if (Config.UseOldWayDownloader) {
mDataDownloader = new OldWayDownloader();
}
else {
mDataDownloader = new NewWayDownloader();
}
// ....
// or you can use service locator or dependecy injection that will get
// a specific downloader based on configuration/setup
mDataDownloader = Services.Get<IDataDownloader>();
// ....
}
public void Execute() {
var data = mDownloader.Download();
var processedData = mDataProcessor.Process(data);
mDataOutputer.Output(processedData);
}
}
这样你会变得很好 separation of concerns 并且你会得到一个可以扩展的模块化系统。该系统也是可组合的。您可以用不同的方式组合它的各个部分。
看起来工作量更大,但事实并非如此。干净的设计通常更容易编写和扩展。
的确,您可能会多写一些代码,但是由于设计简洁,您可以更快地编写此代码,并且可以节省调试时间。调试是我们编写软件的大部分时间,但它经常被程序员忽视,认为他们只能通过编写和代码行来衡量。
松散类型语言就是一个例子。很多时候你写的代码越少越胖,但是很容易因为错误而出错。万一出错,你会得到更多(有时更难)调试,这样你就浪费了时间。
如果您从一个简单的概念验证应用开始,它们将显着加快开发速度。一旦您达到了拥有经过测试的强大软件的地步,就会有不同的力量介入。
为了确保您的软件健壮,您必须编写更多测试和更多 checks/assertions 以确保一切 运行 顺利进行。所以最后你可能会有相同数量的代码,因为强类型会为你做一些检查,你可以写更少的测试。
那什么更好呢?嗯...这取决于。
有几个因素会影响开发速度。这 程序员对一门语言的品味和经验。该应用程序也会对此产生影响。有些应用程序更容易用松散类型的语言编写,而另一些则更容易用强类型语言编写。
速度可以不同,但并不总是这样,有时只是一样。
我认为,在您的情况下,您会浪费更多时间来尝试获得正确的层次结构并对其进行调试,即使最后您的代码少了几行。在较长的 运行 中,如果您需要扩展它,拥有一个更难理解的设计会大大降低您的速度。
在管道方法中添加新的下载、处理或输出数据的方法就是添加单个 class。
好吧,为了让它成为 UML 答案,我添加了 class 图:
Pipeline
提到了这三个处理 classes。它们都是抽象的,因此您需要以不同的方式实现它们。 configuration
将根据配置(文件)的内容分配它们。