OK so the the title is a little click baity but seriously I’ve been on a tell, don’t ask kick for awhile. I like how it encourages methods be used as messages in true object oriented fashion. But this has a nagging problem that has been rattling about in my head.
I have come to suspect that well written code can follow OO principles and functional principles at the same time. I’m trying to reconcile these ideas and the big sticking point that I’ve landed on is return
.
A pure function has two qualities:
-
Calling it repeatedly with the same inputs always gives the same result. This implies that it is immutable. It’s state is set only once.
-
It produces no side effects. The only change caused by calling it is producing the result.
So, how does one go about being purely functional if you’ve sworn off using return
as your way of communicating results?
The tell, don’t ask idea works by using what some would consider a side effect. When I deal with an object I don’t ask it about it’s internal state. I tell it what I need done and it uses its internal state to figure out what to do about what I’ve told it to do. Once I tell it I don’t ask what it did. I just expect it to have done something about what it was told to do.
Way back in the day, when disk drives actually had disks in them and a thumb drive was what you did in the car when the wheel was to cold to touch with your fingers, I was taught how annoying people consider functions that have out parameters. void swap(int *first, int *second)
seemed so handy but we were encouraged to write functions that returned the results. So I took this to heart on faith and started following it.
But now I see people building architectures where objects let how they were constructed control where they send their results. It seems a bit like the out parameter idea all over again. But that’s how tell, don’t ask objects tell other objects what they’ve done.
When I first learned about side effects I thought of it like the output parameter where we’re being told not to surprise people by having some of the work happen in a surprising way by not following the return result
convention. Now sure, I know there’s a pile of parallel asynchronous threading issues that side effects muck about with.
What I’m really trying to ask:
Is return
the only way to avoid all that side effect misery. Or can I follow tell, don’t ask in a purely functional way?