Swift 我需要帮助重构代码以符合单一责任原则
我目前正在阅读一本名为《Ruby中的实用面向对象设计》(Practical Object Oriented Design in Ruby)的书,试图理解这些坚实的原则。第一个原则是单一责任,我理解这个概念的方式是一个类/方法应该只有一个责任或改变的理由 在下面的代码中,我有一个计算类,负责(4)四种不同的操作,Swift 我需要帮助重构代码以符合单一责任原则,swift,oop,design-patterns,solid-principles,Swift,Oop,Design Patterns,Solid Principles,我目前正在阅读一本名为《Ruby中的实用面向对象设计》(Practical Object Oriented Design in Ruby)的书,试图理解这些坚实的原则。第一个原则是单一责任,我理解这个概念的方式是一个类/方法应该只有一个责任或改变的理由 在下面的代码中,我有一个计算类,负责(4)四种不同的操作,加,减,乘和除,这在我看来不符合单一责任理论 有人能如此友善地重构下面的类,使其遵守单一责任吗 我知道这可能是一个非常固执己见的话题,但我真的需要更好地理解这个概念 仅供参考-为了简单起见
加
,减
,乘
和除
,这在我看来不符合单一责任理论
有人能如此友善地重构下面的类,使其遵守单一责任吗
我知道这可能是一个非常固执己见的话题,但我真的需要更好地理解这个概念
仅供参考-为了简单起见,我只使用整数,我知道它对于除法和减法并不理想
class Calculate{
let num1:Int
let num2:Int
init(firstNum:Int, secondNum:Int){
num1 = firstNum
num2 = secondNum
}
func add()->Int{
let total = num1 + num2
return total
}
func subtract()->Int{
let total = num1 - num2
return total
}
func multiply()->Int{
let total = num1 + num2
return total
}
func divide()->Int{
let total = num1 / num2
return total
}
}
let operation = Calculate(firstNum:5 , secondNum:5)
print(operation.divide())
单一责任意味着类应该只有一个逻辑功能
因此,如果你有计算器,它是完全可以的,它可以计算。“单一”并不意味着“单一方法”。计算器可以和、除等,对吗?所以是的,这正是计算器类方法应该做的
例如,如果您想要连接两个计算器类,那么添加方法“connectToAnotherCalculator”是不符合SRP的。正确的方法是创建连接器类,它应该处理计算器之间的通信。我想建议更好的设计。假设您必须添加许多其他操作:百分比、平方根,甚至正弦。您的计算器将以数千行的速度增长。测试呢?假设,我们已经测试了计算器。现在我们需要在每次操作后再次测试它。所以,增加新的操作将花费我们改变计算器,改变所有使用它的地方,以及许多涉及它的测试
但我们可以制作具有单一职责的计算器-计算(操作):
1) 现在我们可以使用everywhere calculator->Calculation(操作),用测试覆盖它并使其通过。
2) 对于每个新操作,我们只需添加新的操作类并对其进行测试。我们可以轻松地更改任何操作,甚至不必触摸计算器和使用它的对象 @Denis Efimov这是我根据你的建议提出的代码。这对我帮助很大,它是用PHP编写的,但很容易翻译成Swift
我只展示了两个运算(加法
和乘法
),但我可以轻松地添加任意数量的运算。请注意,为了简单起见,我只使用Int
s
protocol Operation{
func equation()->Int
}
class Calculator{
func calculate(operation:Operation)->Int{
return operation.equation()
}
}
class Addition:Operation{
var addendOne:Int
var addendTwo:Int
init(addendOne:Int, addendTwo:Int){
self.addendOne = addendOne
self.addendTwo = addendTwo
}
func equation()->Int{
return self.addendOne + self.addendTwo
}
}
class Multiplication:Operation{
var multiplicand:Int
var multiplier:Int
init(multiplicand:Int, multiplier:Int){
self.multiplicand = multiplicand
self.multiplier = multiplier
}
func equation()->Int{
return self.multiplicand * self.multiplier
}
}
let addition = Addition(addendOne:5, addendTwo:5)
let multiplication = Multiplication(multiplicand:5, multiplier:5)
let calculator = Calculator()
print(calculator.calculate(addition))
print(calculator.calculate(multiplication))
你们对这段代码怎么看,这看起来是更好的方法吗?这是否更符合SOLID
原则(SO
)
谢谢这当然符合SRP<代码>计算
由一系列用于执行其计算功能的相关算法组成。我不会重构它。@Epic先生-哦,这样这个类就可以有它所需要的任意多个操作(方法),只要这些操作与该类所做的事情相关,在这种情况下,因为加法、减法等都被认为是计算的一部分,所以在计算类中是可以的,对吗?我之所以感到困惑,是因为这四个方法都返回一个值并暴露于外部世界,但理论上它们使用相同的数据(参数)进行操作。这听起来很有趣,有点像使用协议(接口)?我听说过“编程到接口而不是类”这句话,这就是你的建议吗?我将尝试改进我的原始代码并在这里发布。是的,接口比具体的类有更多的好处。您可以使用接口,然后只在一个地方更改具体的实现。如果你用单元测试来覆盖你的代码,它也允许你注入模拟作为你的接口的实现是的,这是可行的,但是你走错了方向。您问题中的设计确实符合SRP。对于要添加到类中的每个方法,引入新的scublass是没有意义的。我明白你的意思了,我的代码现在更符合“open-close
”原则SO
LID,对吗?一切都开始变得有意义了。你的第二种方法和第一种方法一样符合OCP。你可以这样看,但我认为这不是OCP实现的最佳示例。添加其他方法不会违反OCP。