AkkaStream. Proper flow decomposition


(Sergii) #1

Hi,

I have a huge akka flow that contains multiple shapes with custom logic. Most of these shapes are being reused frequently. Having all of them inside one logical unit (Class, Actor, whatever) is not an option as it becomes really huge. I tried to decompose it in a very doubt-able way. I created set of static classes which contain static methods that returns some shapes, for example:

public class MyCustomShapeProvider extends AbstractShapeProvider {

    public static Graph<UniformFanOutShape<DataContainer,DataContainer>, NotUsed> getMyCustomShape() {
        return Partition.create(DataContainer.class, 2, MyCustomShapeProvider::getPartitionLogic, false);
    }

    public static int getPartitionLogic(DataContainer elem) {
           //Perform some logic and call other class static funtions
    }

   // Other functions that implement business logic are here.
}

Usage of this code looks like following:

final UniformFanOutShape<DataContainer, DataContainer> myCustomShape = builder.add(MyCustomShapeProvider.getMyCustomShape());

Could you please help me to come up with better ideas how to decompose such code properly without such a heavy usage of static methods? Maybe there are some best practices?

Thank you very much!

Regards,
Sergii


(Gergő Törcsvári) #2

Hy!

I’m coding mostly in scala in the past 2 years. We often do this. We create an object (this is a pure singleton static thing; like a class with only static parameters and methods), and write our (flow) staff to it. It’s totally ok in the programming perspective as far as you don’t use mutable states. If you browse the akka-streams or alpakka sources, there are a lot of scala-objects. I think the heavy usage of static methods in this use-case is good. (Just hide the inner logics behind privates and show as little interface to the fellow users as you can.)


(Sergii) #3

Hi Gergő,

Thank you very much for the feedback! The problem with statics is testing. The only one tool that can properly mock static calls in Java is PowerMock, however, it has problems with Java 10 compatibility. It is a good idea to use singletons, I will try it. Thanks.

Regards,
Sergii


(Gergő Törcsvári) #4

Testing is always an interesting part in streams! When I’m not using cycles I usually not test the whole flow. The reason behind this is simple: The parts are tested, and the connections are tested by the framework.

What is the reason of mocking one component? You want to mock the side-effects only. So if you use a mapAsync inside a flowShape, you can factor the inner function out as function parameter. If you have something like a StuffDAO with Future<Stuff> find(String id) you can use the whole StuffDAO as an input parameter too. I think the Flows should be pure from side-effects, so you can test them easily and can compose them as static functions.


(Sergii) #5

I want to test the logic of a custom shape, I mean that “other functions” from the static class. The problem is they have some inter-dependencies, when static calls another static and I want to mock this invocation. It is usual java testing, not Akka one.