Consistency vs. "The itch"
I assume everybody has certain rules, regulations, guidelines or conventions at their jobs/open source projects. I like structure and consistency so, as long as they are sensible, these things make me happy. Still, every once in a while, something itches. What wins, itch or convention?
A very practical example: At my job we agreed on writing API's for all functionality of a software-module. These API's aim to avoid queries all over the place and non-transparant use of parts of modules by other modules. These API's do business logic, storage is the responsibility of different object: the repository. Usually this works out just fine and results in (simple) api functions that look like this:
class FooApi { function storeBar(Bar $Bar) { //assure baz is set if (empty($Bar->getBaz())) { throw new Exception("So exceptional!"); } //assure there is still space to store more Baz'es if ($this->getCurrentBaz() >= $this->getMaxBaz()) { throw new Exception("More exceptional!"); } return $this->Repository->storeBar($Bar); } }
But sometimes there just is no business logic, sometimes an API does storing and storing alone. Resulting in API's that do nothing but delegating calls:
class FooApi { function storeBar(Bar $Bar) { return $this->Repository->storeBar($Bar); } }
Obviously this is slightly annoying. What is worse, functions like these tend to grow in sets. If you don't need business logic in one you probably won't need it in others as well. The end result might be five of these delegated calls instead of one. Hence the itch... You might be very, very tempted not to create this API and call the repository directly.
Embrace the itch!
At the end of it all this means that there is a trade-off between the itch and consistency. Personally I chose consistency. I value consistency because not adhering to consistency basically means you're creating instant-legacy code. Secondly, one day, you will have the need for business logic. Your options at that moment are sucky:
- Implement API fully after all, including all search and replace annoyances. And bugs...
- Implement the business rules somewhere near each repository call. Because f--k DRY right :)
The very small amount of times I make an API that only delegates and will only be delegating for the rest of its life I console myself with the alternatives above.
This is just one example, there are many trade-offs like this. I choose consistency every time, what is your choice?
Comments
-
Secondly, one day, you will have the need for business logic.
So very true.
Every time I chose to scratch my itch and skip the logic/model separation, I found myself refactoring within days :).
-
"You might be very, very tempted not to create this API and call the repository directly." - Really? :) That's not what happens to me, that would would be really nasty.
The API is paramount, in my view. What happens within the API is of a lesser concern. If the API really just does storage, I can imagine that you do not write a separate repository. The db calls can be made within the API directly.
I think this is just a simple matter of YAGNI http://c2.com/cgi/wiki?YouArentGonnaNeedIt
If however, there is a reasonable chance that business logic will be added to the API, as Bert says, it is better to split Logic and Model immediately, to separate concerns and make your code more readable and maintainable.