mardi 31 mai 2016

Can an Abstract Factory be responsible for "creating or finding an existing" item?

My Ruby code has a Concrete Factory, which builds some complex objects:

author = Author::Factory.build(email: "john@example.com")

class Author
  class Factory < BaseFactory
    def self.build(email: nil)
      # ... Some data preparation and defaults
      Author.new(
        email: email
        # Map and assign more attributes
      )
    end
  end
end

Now, I've run into a situation where I either need to build a new one, or assign one from an existing collection. In database-terms: an UPSERT, or in ActiveRecord: find_or_create_by.

And I am not sure if this:

  1. Is a proper task for an Abstract Factory and
  2. If the proper way to implement this is by passing the collection, or to make the Factory itself responsible for fetching it.

Passing it in:

author = Author::Factory.build(email: "john@example.com", existing: authors)

class Author
  class Factory < BaseFactory
    def self.build(email: nil)
      author = existing.find {|author| author.email == email }
      # If not found, prepare and build a new one, like above.
    end
  end
end

Letting the Factory find it:

author = Author::Factory.build(email: "john@example.com")

class Author
  class Factory < BaseFactory
    def self.build(email: nil)
      author = Author.find_in_existing_with(email: email)
      # If not found, prepare and build a new one, like above.
    end
  end
end

So: Should a Factory every be responsible for finding-or-building?

And if so, must the Factory be responsible for fetching the items that it must match against, or should the caller pass them along?

Aucun commentaire:

Enregistrer un commentaire