Long parameter lists
For example’s sake, let’s say we have a UIButton
subclass that we want to be customizable at call site, so we add two parameter’s to its init
method:
final class Button: UIButton {
init(textColor: UIColor, borderColor: UIColor)
}
// ...
let button = Button(textColor: .darkText,
borderColor: .darkText)
Looks pretty OK.
Some time passes and the need to customize its background color appears, at which point we’d need another param:
final class Button: UIButton {
init(textColor: UIColor, borderColor: UIColor, backgroundColor: UIColor)
}
// ...
let button = Button(textColor: .white,
borderColor: .white,
backgroundColor: .darkText)
Still not that bad, although I'd start to argue.
Some more time passes and we now need to have it big or small, have rounded corners or not and animate on touch sometimes. Adding three more params would suffocate both the implementation site and call sites.
We could add default params, as to make call sites prettier, but it’s still not the best we can do. What if we wrapped all these params in a Config
object and used that for the init
?
final class Button: UIButton {
init(config: Config)
}
extension Button {
struct Config {
var textColor: UIColor = .darkText
var borderColor: UIColor = .darkText
var backgroundColor: UIColor? = nil
var animatesOnTouch = false
var cornerRadius: CGFloat? = nil
}
}
// ...
let button1 = Button(config: Button.Config())
var config = Button.Config()
config.textColor = .white
config.borderColor = .white
config.backgroundColor = .darkText
config.animatesOnTouch = true
config.cornerRadius = 8
let button2 = Button(config: config)
The init
is clean, the call site is clean and we create a custom Config
object only when needed and set only the properties we need.
Looks a lot better, doesn’t it?
As a bonus tip, I like to nest related objects, like Config
in our case. I prefer Button.Config
to ButtonConfig
; while they’re basically the same, both from the number of characters to the way you’d pronounce it, nested objects feel more semantically correct, more organized.