[erlang-questions] Extracting pure functions
Andy Till
atill@REDACTED
Sat Feb 21 12:30:57 CET 2015
I suggest caution before applying this technique liberally to production
apps. We had a couple of projects with a lot of code like this and it
is very difficult to work with.
It differs slightly from your example, it didn't return MFAs, just
tuples which would be matched in a "process_side_effects" function which
applied all the side effects. That meant you had to zip up and down the
module to find the whole implementation for a function of logic plus
side effects.
Where I found issues is in the inflexibility in handling errors. Not
crash bug errors but stuff like econnrefused from a socket, so you have
to handle it in the side effect function. Then there is logic in two
places. It also defies all editor navigation and static analysis tools
like ctags and xref. I created a behaviour for this pattern (gen_io on
github) but decided not to use it so treat it as highly experimental.
On 20/02/2015 20:35, Gordon Guthrie wrote:
> Judson
>
> That mechanism is perfect for building highly testable services.
>
> Effectively you are transforming the testing domain from:
> * if I receive these inputs then I emit these side effects
>
> to:
> * if I were to receive these inputs then I would have emitted these side effects
>
> To test the former you have two choices:
> * build a full system test
> * meck the living bejesus out of your system
>
> This mechanism is particularly useful if the serve contains a large data structure that needs to be manipulated in memory.
>
> Gordon
>
>> Le 20 févr. 2015 à 19:46, Judson Lester <nyarly@REDACTED> a écrit :
>>
>> I'm thinking about how to separate pure functions from those that cause side effects, and one of the places I'm trying to find a decent pattern for is message passing.
>>
>> I'm primarily concerned with being able to easily test the functional components as units, and then use integration testing for the parts that involve a side effect.
>>
>> For instance, I have a gen_server that handles a message and emits an event sometimes.
>>
>> handle_event_message(Arg, State=#state{collected_args=Args,event_server=Ev}) ->
>> gen_event:notify(Ev, {some_event, Arg}),
>> State#state{collected_args[Arg |Args]}.
>>
>> (obviously, I'm simplifying a lot here)
>>
>> What I'm wondering about is extracting something like:
>>
>> handle_event_message(Arg, State=#state{collected_args=Args,event_server=Ev}) ->
>> {Effects, State} = pure_handle(Arg, State),
>> [ apply(Mod, Fun, Args) || {Mod, Fun, Args} <- Effects],
>> State.
>>
>> pure_handle(Arg, State) ->
>> { [{gen_event, notify, [Ev, {some_event, Arg}]}],
>> State#state{collected_args[Arg |Args]} }.
>>
>> Which would mean I could test the effects that pure_handle/2 intends in a unit test.
>>
>> Is this a pattern others use? A terrible delusion? Not interesting?
>>
>> Judson
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
More information about the erlang-questions
mailing list