Codementor Events

Long parameter lists

Published Jul 11, 2019

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.

Discover and read more posts from Roland Leth
get started
post commentsBe the first to share your opinion
Show more replies