The curious case of coordinators and workers

Michael Angelov
INLOOPX

--

From the industry standard of MVC or MVVM, to the more novel architectures like Clean or VIPER, mobile developers have been continuously looking for an ideal architecture for years. The goal has been, amongst others, to decouple dependencies, extract business logic, improve testability, and avoid bugs.

Having dealt with mobile cross-platform development for some time now, I’ve begun to notice an underlying pattern which I call the “coordinator-worker principle”.

How does it work?

If you ask your client, or a user, about the functionality of an existing application, they will be able to give you an accurate description without going into technical details. In other words, they will describe what the system does without knowing how it is implemented on a device.

Applied to the coordinator-worker principle, this is what coordinators do — they run the application from a non-tech perspective. Their sole purpose is to coordinate the flow of the application — to intercept events, and behave accordingly. According to their role, you might call them presenters, routers, interactors, managers, etc.

You might ask: how does a “presenter coordinator” differ from a presenter within VIPER or Clean architecture? The simple answer is that coordinators are stripped of any technological information (and are therefore, platform independent), since they only communicate with other coordinators or workers via interfaces that they also happen to create.

Of course, coordinators themselves are not sufficient to make an application run on a device. They are only a brain and therefore cannot act without a body. But the behavior alone can be programmed by simply covering it with tests.

Workers, on the other hand, implement what coordinators demand through interfaces on a specific platform. They might get some data from network, insert data into database (and notify the coordinator about the result), or simply transition to another scene, or turn a label to a different color — whatever that means on a given platform.

When it comes to implementation, this kind of separation encourages usage of TDD, making it the standard development method. But again, there is some complementarity in it — as coordinators act globally, their development is driven rather by acceptance test scenarios (you can read about it in my previous article). For workers, on the other hand, it is more suitable to use unit tests.

When it comes to the external testing phase, wherever a bug is reported, it can be easily transformed into a failing acceptance or unit test. With this approach bug fixing becomes less tedious, and as the number acceptance and unit tests grows, it becomes more difficult to to break anything.

In real life application, if you are targeting iOS and Android platforms, you might consider implementing coordinators using Java (with all the great testing frameworks like JUnit or Mockito) and then translating them via j2objc translation tool into Objective-C and implement the corresponding workers on platform. The main thing is not committing yourself to a specific framework and keeping all the good stuff from your favorite platform.

Returning to where I started, you’ll also get decoupled dependencies, extracted business logic, improved testability and fewer bugs.

--

--