Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 我需要帮助重构代码以符合单一责任原则_Swift_Oop_Design Patterns_Solid Principles - Fatal编程技术网

Swift 我需要帮助重构代码以符合单一责任原则

Swift 我需要帮助重构代码以符合单一责任原则,swift,oop,design-patterns,solid-principles,Swift,Oop,Design Patterns,Solid Principles,我目前正在阅读一本名为《Ruby中的实用面向对象设计》(Practical Object Oriented Design in Ruby)的书,试图理解这些坚实的原则。第一个原则是单一责任,我理解这个概念的方式是一个类/方法应该只有一个责任或改变的理由 在下面的代码中,我有一个计算类,负责(4)四种不同的操作,加,减,乘和除,这在我看来不符合单一责任理论 有人能如此友善地重构下面的类,使其遵守单一责任吗 我知道这可能是一个非常固执己见的话题,但我真的需要更好地理解这个概念 仅供参考-为了简单起见

我目前正在阅读一本名为《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
”原则S
O
LID,对吗?一切都开始变得有意义了。你的第二种方法和第一种方法一样符合OCP。你可以这样看,但我认为这不是OCP实现的最佳示例。添加其他方法不会违反OCP。