采取简化的情况:我有一个类,它的工作是在给定路径上创建某些文件(让我们称之为FileCreator)。但是,只有在所述路径中尚不存在文件时才需要创建文件。
FileCreator检查文件是否存在于路径中然后创建它们是否更好,或者创建第二个负责检查的类(FileChecker)并让FileCreator完全进行创建(没有是否确实存在与否?)
情境1 :决策逻辑依赖于决策
class FileCreator
def initialize(path)
@path = path
end
def create_files
unless files_exists?(path)
#create files at path
end
end
def files_exists?(path)
#check if files exist at path
end
end
file_creator = FileCreator.new('/foo')
file_creator.create_files
情境2 :决策逻辑位于自己的班级
class FileChecker
def initialize(path)
@path = path
end
def files_exists?(path)
#check if files exist at path
end
end
class FileCreator
def initialize(path)
@path = path
end
def create_files
#create files at path
end
end
file_checker = FileChecker.new('/foo')
file_creator = FileCreator.new('/foo')
file_creator.create_files unless file_checker.files_exists?
第一个场景更方便,但我想第二个场景更灵活(从某种意义上说,我现在确切地知道哪个类究竟是什么,所以我可以很容易地将它们放在一起)。
我对编程很陌生,所以对这个特定问题的想法或模式的任何外部引用都会受到赞赏(同样,不确定这个问题是否被正确标记)。
答案 0 :(得分:3)
我会保持尽可能简单(但不简单; - )
在你刻意简化的例子中我会有一个单独的类,Check功能与Create功能密切相关,所以有一定程度的凝聚力,所以我们可以争辩说这段代码属于一个。 / p>
我有动力在某些条件下将代码重构为单独的类。在解释一些这样的条件之前,请注意思考过程:我知道我可以重构我是否需要,实际上我可以这样做而不会扰乱任何创建功能的用户;设计有一些内在的灵活性,我们只是考虑重新安排Create实现的内部。
将重构分为两类的一些可能原因:
答案 1 :(得分:1)
我更倾向于将两种功能放在同一个类中。 OOP是关于将数据与单个对象中的行为相结合。在这种情况下,您的数据是您的路径和文件名,并且您有两个与该数据相关联的行为:检查存在和创建。
考虑到这一点,我认为将这个对象称为File而不是File + some verb会更像OOP。毕竟,OOP是关于对象的建模,该对象的动词是它的方法。
我的实现可能类似于:
public class File
{
private readonly string path;
public File(string path)
{
this.path = path;
}
public void Create()
{
if (!DoesFileExist())
{
// create file.
}
}
private bool DoesFileExist()
{
// check if file exists.
}
}
答案 2 :(得分:1)
答案是它可能并不重要;但是,单一责任类通常更具可重用性,特别是如果您有多重继承。除非有特定的理由将它们联系在一起,否则你可以将它们分开。
如果没有其他考虑,我可能会把这个例子写成一个类。然而,一旦它成为一个需要考虑的东西,你可能只是让它们分开。
答案 3 :(得分:0)
在这样一个简单的场景可能是最好的选择是第一,记住,软件设计的最终目标是生产系统简单易懂/修改/延伸,第一类是很容易理解的。
来自djna的答案非常好,重构时有明显的好处。当重构的日子到来时,考虑另一种选择,你有两个责任:
你可以这样:
class FileCreator
def initialize(path, fileCreationCriteria)
@path = path
@fileCreationCriteria = fileCreationCriteria
end
def create_files
unless fileCreationCriteria.meetCriteria?(path)
#create files at path
end
end
end
然后你可以有不同的标准,例如文件已经退出,另一个例子可以是空间限制o。创建对象时,您可以:
file_creator = FileCreator.new('path', CreateIfNotExists.new)
file_creator = FileCreator.new('path', CreateAllwaysAndOverride.new)
file_creator = FileCreator.new('path', CreateUntilSpaceLimitIsReached.new('1GB'))
可能有一个默认标准可能是一个好主意,想想你的班级/ api的来电者可以轻松搞定。
显然,这是不是过度设计更加像最初的一个问题,你存在,它只是作为一个例子SRP和启闭(现在你的文件创建者的接近的修改和对扩展开放和只有一个责任)
请记住,模式和原则只是指南,总是取决于背景和设计师的良好判断。