这是非常基本的东西,但这是可行的。我发现自己永远无法同意将大型类拆分为较小的类的方式是使事情更易于维护还是难以维护。我虽然不详细介绍设计模式,但也熟悉面向对象设计的概念。除了所有花哨的规则和准则,我希望通过一个非常简单的示例场景来就我所缺少的内容动动你的大脑。基本上遵循以下思路:“...这种设计将使其变得更难”,等等...由于缺乏经验,我无法预料的所有事情。
假设您需要编写一个基本的“文件读取器/文件写入器”样式类来处理某种类型的文件。我们将该文件称为 YadaKungFoo文件。 YadaKungFoo文件的内容本质上与INI文件类似,但有细微的差别。
有以下部分和值:
[Sections]
Kung,Foo
Panda, Kongo
[AnotherSection]
Yada,Yada,Yada
Subtle,Difference,Here,Yes
[Dependencies]
PreProcess,SomeStuffToPreDo
PreProcess,MoreStuff
PostProcess,AfterEight
PostProcess,TheEndIsNear
PostProcess,TheEnd
好的,这样可以产生3个基本类:
public class YadaKungFooFile
public class YadaKungFooFileSection
public class YadaKungFooFileSectionValue
后两个类实际上仅是具有ToString()重写的数据结构,以吐出使用几个通用列表存储的值的字符串列表。这足以实现YadaKungFooFile保存功能。
因此,随着时间的流逝,YadaYadaFile开始增长。几种重载以不同格式保存,包括XML等,文件开始向800行左右移动。 现在是真正的问题:我们想添加一个功能来验证YadaKungFoo文件的内容。首先想到的是添加:
var yada = new YadaKungFooFile("C:\Path");
var res = yada .Validate()
至此我们已经完成了(我们甚至可以从构造函数中调用该方法)。麻烦的是验证非常复杂,并使类很大,因此我们决定创建一个新的类,如下所示:
var yada = new YadaKungFooFile("C:\Path");
var validator = new YadaKungFooFileValidator(yada);
var result = validator.Validate();
现在,此示例显然是,非常简单,琐碎且无关紧要的。上面的两种方式中的任何一种都可能不会造成太大的变化,但是我不喜欢的是:
总的来说,我觉得我没有经验来理解为什么一个设计不好的所有方面,在什么情况下它并不重要,哪个问题更重要:较小的类或更紧密的类。它们似乎是矛盾的要求,但也许我错了。也许验证者类应该是一个复合对象?
本质上,我是在征求有关上述设计可能带来的好处/问题的意见。有什么不同的方法可以做? (基本FileValidator类,FileValidator接口(interface)等。您将其命名)。可以将YadaKungFooFile功能视为随时间增长的功能。
最佳答案
鲍勃·马丁(Bob Martin)写了一系列有关类设计的文章,他将其称为SOLID原则:
http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
原则是:
因此,鉴于这些,让我们看一些语句:
这是第一个大红旗:YadaYadaFile首先担负两个职责:1)维护节/键/值数据结构,以及2)知道如何读写类似INI的文件。所以这是第一个问题。添加更多文件格式使问题更加复杂:当1)数据结构更改,或2)文件格式更改,或3)添加新文件格式时,YadaYadaFile更改。
同样,为所有这三个职责都配备一个验证器会使该单个类承担太多责任。
大类是一种“代码气味”:它本身并不坏,但是它通常是由某些真正不好的东西导致的—在这种情况下,这是一个尝试太多东西的类。