patternswiftMinor
Portfolio object made of Asset classes and Securities
Viewed 0 times
assetmadeportfoliosecuritiesclassesandobject
Problem
I am learning Swift and object oriented programming. I am new to design patterns and protocol oriented programming.
In my test code I have several related objects:
I want to be the most abstract as I can to avoid tight coupling.
The following code works but I am wondering how it can be improved. Do you see major weak points in my design?
```
import Foundation
protocol SecurityType{
var code : String {get set}
var name : String? {get set}
}
class Security:SecurityType{
var code : String = ""
var name : String?
init(withCode aCode: String, andName aName: String?){
self.code = aCode
if let securityName = aName{
self.name = securityName
}
}
}
protocol SecuritiesBasketType{
var name : String {get set}
var securities : [SecurityType]{get set}
init()
}
extension SecuritiesBasketType{
//Default Initializers
init(withName aName: String){
self.init()
self.name = aName
}
init(withName aName: String, andSecurities securitiesArray:[SecurityType]){
self.init()
self.name = aName
for aSecurity : SecurityType in securitiesArray{
securities.append(aSecurity)
}
}
mutating func addSecurity(security: SecurityType){
securities.append(security)
}
}
class AssetClass : SecuritiesBasketType{
var name : String = ""
var securities = [SecurityType]()
required init(){}
}
class WatchList: SecuritiesBasketType{
var name : String = ""
var securities = [SecurityType]()
required init(){}
}
class Portfolio{
var name : String = ""
var securities = [Se
In my test code I have several related objects:
Security: the most important object that will be contained in the other ones.
AssetClass: ContainsSecurityobjects
Portfolio: ContainsSecurityandAssetClassobjects
Watchlist: ContainsSecurityobjects. Think about it as aPortfolioobject that cannot containAssetClassobjects, onlySecurityobjects.
I want to be the most abstract as I can to avoid tight coupling.
The following code works but I am wondering how it can be improved. Do you see major weak points in my design?
```
import Foundation
protocol SecurityType{
var code : String {get set}
var name : String? {get set}
}
class Security:SecurityType{
var code : String = ""
var name : String?
init(withCode aCode: String, andName aName: String?){
self.code = aCode
if let securityName = aName{
self.name = securityName
}
}
}
protocol SecuritiesBasketType{
var name : String {get set}
var securities : [SecurityType]{get set}
init()
}
extension SecuritiesBasketType{
//Default Initializers
init(withName aName: String){
self.init()
self.name = aName
}
init(withName aName: String, andSecurities securitiesArray:[SecurityType]){
self.init()
self.name = aName
for aSecurity : SecurityType in securitiesArray{
securities.append(aSecurity)
}
}
mutating func addSecurity(security: SecurityType){
securities.append(security)
}
}
class AssetClass : SecuritiesBasketType{
var name : String = ""
var securities = [SecurityType]()
required init(){}
}
class WatchList: SecuritiesBasketType{
var name : String = ""
var securities = [SecurityType]()
required init(){}
}
class Portfolio{
var name : String = ""
var securities = [Se
Solution
I've got a problem with your
There are a couple of problems here. First, why do we need two classes that are identical in every way except name? We don't.
I understand that we will want assets that we actually own as well as assets that we're watching to help us make future decisions, but making different classes like this simply does not make sense. Additionally, this
But we must have the zero argument constructor because of the problem with the protocol. We have conformed to the
In some cases, a
But WHY?
What you have here is a protocol that should be a class. You've done all of the work in the protocol and protocol extension, and it has resulted in very weird things. It doesn't make much sense to subclass anything that conforms to this protocol and it doesn't make much sense to create more than one class that conforms to this protocol. And when those two things are true (and they are here), then it doesn't make much sense to have the protocol at all. We should instead have a class that looks something like this:
Now the
In Swift, we want to adopt a protocol-oriented approach to programming. Protocols allow us to do some powerful things. But with that said, we need to use the right tool for the right job.
We use protocols to allow multiple implementations of the same interface. The most classic example is with
SecuritiesBasketType protocol and its extension. The problem is best highlighted by taking a look at the multiple classes you've implemented to conform to this protocol.class AssetClass : SecuritiesBasketType{
var name : String = ""
var securities = [SecurityType]()
required init(){}
}
class WatchList: SecuritiesBasketType{
var name : String = ""
var securities = [SecurityType]()
required init(){}
}There are a couple of problems here. First, why do we need two classes that are identical in every way except name? We don't.
I understand that we will want assets that we actually own as well as assets that we're watching to help us make future decisions, but making different classes like this simply does not make sense. Additionally, this
name property makes relatively little sense, and having a zero-argument constructor plus var properties is problematic as far as I'm concerned.But we must have the zero argument constructor because of the problem with the protocol. We have conformed to the
SecuritiesBasketType, which has a zero-argument initializer as part of its conformance. This means that everything that conforms to this protocol as well as things that inherit from that must implement this zero-argument constructor with the required keyword.In some cases, a
required initializer makes sense. Like, for example, with the NSCoding protocol (more reading). But here, we've only required this zero argument constructor so that we can add two other constructors in the protocol extension. But WHY?
What you have here is a protocol that should be a class. You've done all of the work in the protocol and protocol extension, and it has resulted in very weird things. It doesn't make much sense to subclass anything that conforms to this protocol and it doesn't make much sense to create more than one class that conforms to this protocol. And when those two things are true (and they are here), then it doesn't make much sense to have the protocol at all. We should instead have a class that looks something like this:
class SecuritiesBasket {
let name: String
var securities: [SecurityType]
init(withName name: String, securities: [SecurityType]) {
self.name = name
self.securities = securities
}
func addSecurity(security: SecurityType) {
securities.append(security)
}
}Now the
SecuritiesBasket class does everything we wanted out of the SecuritiesBasketType protocol, but it does it without forcing any required initializer (which severely dictates a lot of the things you do with subclasses from that point).In Swift, we want to adopt a protocol-oriented approach to programming. Protocols allow us to do some powerful things. But with that said, we need to use the right tool for the right job.
We use protocols to allow multiple implementations of the same interface. The most classic example is with
UITableView and its delegate/datasource properties. All of the UI logic of the table view exists within UIKit, yet with just a handful of methods in the protocols, the table view can adapt to display whatever information you need it to display.Code Snippets
class AssetClass : SecuritiesBasketType{
var name : String = ""
var securities = [SecurityType]()
required init(){}
}
class WatchList: SecuritiesBasketType{
var name : String = ""
var securities = [SecurityType]()
required init(){}
}class SecuritiesBasket {
let name: String
var securities: [SecurityType]
init(withName name: String, securities: [SecurityType]) {
self.name = name
self.securities = securities
}
func addSecurity(security: SecurityType) {
securities.append(security)
}
}Context
StackExchange Code Review Q#119199, answer score: 4
Revisions (0)
No revisions yet.