0

I have many repeated parts of service logic which just fetches object if it exists or returns a newly saved one. enter image description here

I want to move it from service because it just clutters up the logic. But I do not know where to put it.

I thought about 2 options:

  1. findOrSave method in repository which accepts new entity and performs find or save logic.
  2. findOrCreate method in repository which accepts entity parameters and creates a new one and then performs find or save with new object.

First options removes fetch or save logic from service, but it forces service to instantiate object (which adds boilerplate code).

Second option will make service cleaner, but it adds entity instantiation responsibility to repository.

In my opinion first option is better, because service would get rid of findOrSave logic and repository responsibility would be unchanged. I think it is a best of both worlds.

1 Answer 1

3

Putting this logic in a different class does not reduce the clutter. The clutter is simply moved to another part of your architecture. The truth is, I don't think there is a perfect place to put this logic where all developers have consensus. Instead, think through the use cases:

  • Would it be surprising that finding a company by TIN using a repository also creates the company? If this would surprise people, don't put the logic in the repository.

  • Is auto-creating a Company a core part of the business domain? If so, it should be represented somehow in an aggregate root in Domain Driven Design.

  • If auto-creating a Company is not a core rule of the domain, where would this logic surprise people the least — when all else fails, defer to the Principal of Least Astonishment.

    • If putting this "get or create" logic in a service class appears to be an idiom for this application, keep the logic in a service class. This flows from the Principal of Least Astonishment.

That being said, I see nothing wrong with it being in a service layer provided the method name or comments clearly indicate that a company is retrieved or auto-created if it doesn't exist. That way callers can judge whether the method is appropriate for their use case. The same could be said about a similar method in a repository. The important bit is to clearly indicate that this "find" operation is not just a "query" but also an "insert" if the query does not return anything.


The question title mentions "get or save" yet the code example shows a new company being created. The word "save" is confusing here. I interpret "save" to be a "create" or an "update". The term is ambiguous. The word "create" matches the intent of the method, so "getOrCreate" makes sense.

1
  • Thanks, you made me to view problem from another perspective! Commented May 22 at 17:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.