[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