Skip to content

Instantly share code, notes, and snippets.

@serodriguez68
Last active April 18, 2020 10:51
Show Gist options
  • Save serodriguez68/2a1ce454d094bdf70d75ecdabf219f52 to your computer and use it in GitHub Desktop.
Save serodriguez68/2a1ce454d094bdf70d75ecdabf219f52 to your computer and use it in GitHub Desktop.
What parameters should go in the initialisation method? Objects that "be" VS Objects that "do"

What parameters should go in the initialisation method? Objects that "be" VS Objects that "do"

Tim Riley has a great rule of thumb for classifying objects and deciding what parameters should be part of the class' attributes (state) VS which should be provided as arguments to the methods of that class.

There are 2 types of Objects: Objects that "be" and Objects that "do".

Objects that "be"

If you say "this object IS a dog", then you are dealing with an object that "be".

The job of these objects are to represent data in our application. They hold data in their state and therefore we must provide that data as initialization arguments.

Objects that "do"

If you say "this object sends notifications" you are dealing with an object that DOES something.

They are typically initialized with configuration arguments only (including injected dependencies) and act on data that is given to them as arguments to their public instance methods.

class CurrencyConverter
  attr_reader :from, :to, :external_conversion_service

  # If you are confused by this way of doing defaults on dependency injection
  # see https://gist.github.com/serodriguez68/29f6be8d51aceff3d1fd202ee4355bf2
  def self.new(**args)
    args[:external_conversion_service] ||= SomeExternalService.new
    super(args)
  end

  def initialize(from:, to:, external_conversion_service:)
    @from = from
    @to = to
    @external_conversion_service = external_conversion_service
  end
  
  # Amount is considered as "data" that is acted upon
  def convert(amount)
    external_conversion_service.process(from: from, to: to, amount)
  end
end

# We configure the converter just one time
usd_to_euro_converter = CurrencyConverter.new(from: :usd, to: :euro)

# We can use this converter multiple times with different data
usd_to_euro_converter.convert(100)
usd_to_euro_converter.convert(1000)

Objects that "do": are intialized with stuff that should never need to change during the "lifecycle" of the object. In web-applications the "lifecycle" can be the web-response cycle or the booting of the program. In other words, if we have to throw away the object after calling it one time, we have probably intialized it the wrong way and we should be providing some stuff as function arguments instead of state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment