DEV Community

Cover image for Simplify Business Logic with Reactive Architecture
Danny Kim
Danny Kim

Posted on

Simplify Business Logic with Reactive Architecture

Expressing a complex business logic as a readable code is not an easy task. Also, refactoring can feel like shifting the complexity around rather than making it simpler. I'd like to show you a technique that can simplify your code: using Reactive Architecture.

Please take a look at this example:

class Feedback {
  create(user, message) {
    // Save the feedback on db.
    dbService.create("Feedback", message);
    if (user.isVip) {
      // Send notification on slack on VIP feedback.
      slackService.notify(message);
    } else {
      // Non-VIP feedbacks get deleted later.
      taskQueue.enqueue(
        "/tasks/delete-feedback",
        {id: message.id},
      );
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

As you can see, it is really common for a business logic to include side-effects like logging, messaging, analytics, and scheduling. The example code wraps the ugly part behind services methods (like slackService.notify), but you can see the function is clearly doing more than one thing. Basic extraction like below won't really improve anything here.

function enqueueDeleteTask(messageId) {
  taskQueue.enqueue(
    "/tasks/delete-feedback",
    {id: messageId},
  );
}
Enter fullscreen mode Exit fullscreen mode

But we can simplify the code by splitting them into cause & effect. Also known as Reactive Architecture or event handlers.

class Feedback {
  constructor(options) {
    this.onVipFeedback = options.onVipFeedback;
    this.onNonVipFeedback = options.onNonVipFeedback;
  }
  create(user, message) {
    dbService.create("Feedback", message);
    if (user.isVip) {
      onVipFeedback();
    } else {
      onNonVipFeedback();
    }
  }
}

// usage
const feedbackService = new Feedback({
  onVipFeedback: (message) => {
    slackService.notify(message);
  },
  onNonVipFeedback: (message) => {
    taskQueue.enqueue(
      "/tasks/delete-feedback",
      {id: message.id},
    );
  },
});
Enter fullscreen mode Exit fullscreen mode

This structure is much better than the original code because

  1. Feedback.create method will not change when business logic changes for VIP feedback handling. It will stay short and readable.

  2. Feedback.create method doesn’t depend on “slackService” or “taskQueue” anymore. This makes testing much easier.

The benefits of Reactive Architecture get amplified as your business logic gets more complicated. Try this technique next time you’re writing a complex code. The technique is pretty versatile so you can use it as easily in backend controllers as in React component functions.

Top comments (0)