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:
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?
Factory is a creational pattern, so clients will expect fresh new instances out of it.
Sure, what the Factory does internally is of no concern to consuming code. But if Author
is a domain entity, I fail to see how an Author
-building object could be used by consumers for anything else than the "real world" addition of a new author in the system.
Unless you want be semantically unfair and trick callers by reusing existing authors instead of instantiating new ones. But that doesn't look like something you would typically do in production.