Bitwise Config Flags

Çağatay Çalı
Trendyol Tech
Published in
5 min readJul 19, 2020

We as Trendyol, we are a technology team open to innovation looking for solutions from different angles.

In this episode of a coding story, we’re going to touch confusing/complex business requirements and isolate them into one big state of a business graph using magical bits. Then we will solve the problem in an esoteric way.

First in first, background music.

Think about we have to re-code the order detail page in one of the biggest e-commerce sites of the country. The order detail page should be created millions of times a day for different types of order status. As with the background song, rendering time has to be used as efficiently as possible for our customers’ experience.

The Problem 🤯

The order can be in 15 different states, the order has been received, the order is shipping, awaiting order returns, etc. There are 5…10 different pieces to be rendered on the screen in each case!

An example graph of status versus components

Each scenario we have to render the correct combinations of components.

Before we proceed to solve the problem with an esoteric way, let’s solve the problem with different approaches.

Approach #1

Someone new to coding first thinks that they can solve the problem by writing if statements. Let’s see what it will look like in the end.

N x M combination must be coded as hardcoded.

In our case of business, the requirement needs to be covered 15 x 8 = 120 combinations of state of order. Must be tested tightly. The testing effort is gonna be too much to handle. Let’s think about how we can render this and how we going to test this two-component tightly.

Each state of order’s components must be tested tightly as well. x2 coding.

We strictly test the codes we write, this approach brings us x3 effort while writing unit, integration, and e2e tests.

This testing approach also will be used when Approach #2 in case. Also valid for Approach #3 which is bitwise config flag but we’re not gonna use this in #3. We will use jest snapshot testing when the bitwise come in the scene.

The developer who comes after us will not know in which case which component will be rendered. All components carry their business logic.

Approach #2

Like as the first Approach #1 but slightly better for reading & testing.

Using array operations for if conditions like as

.includes — Which is using SameValueZero algorithm

.indexOf — Which is using Strict Equality Comparison algorithm

The includes method intentionally differs from the similar indexOf method in two ways. First, it uses the SameValueZero algorithm, instead of Strict Equality Comparison, allowing it to detect NaN array elements. Second, it does not skip missing array elements, instead of treating them as undefined.

We’re not going to using regex for the search string. We have to choose .indexOf for better micro-optimized results.

Here are the JSPerf results. (Spoiler: V8 uses a Boyer-Moore-Horspool string search wins a.k.a. .indexOf 😅)

Test results of .includes vs .indexOf

When rendering millions of times, this %2 is $.$

But the code is more readable, robust. Better than #1. Let’s see what it will look like in the end.

Two approaches in one image

The previous testing approach can be applied as well.

The first two-approach are %100 valid for daily jobs. Let’s move further approach to build better code readability, long term maintainability, easier testability.

Approach #3

We had to code so many conditions. We solved it in a more isolated way with a low-level solution. In this problem, we have additional problems which other devs do not face or not gonna be faced in the future.

The components must be;

  • isolated with business requirements
  • render localized as well ( N status * M various component * localization )
  • render as fast as possible ( O(n) not gonna fast as O(1) 😈 )
  • responsible for business changes ( We‘ll not gonna have extra effort for change business in future )

I asked myself, 🤔

If I was a component ( Human ) of the scene ( World ), would I know why I was here?

My answer is obviously no, IDK why I’m here. But wait. Why our components know why they are rendered. 😒

Here are the magically rendered components:

Isn’t that looks more clear and more readable?

There’s a method called shouldRender, the function decide who will render. Let’s dive into the function.

👽

The previous approaches solving 2 components & 1 status of an order. This approach is already solving 3 status * 5 component combinations with less line of code. 🤫

  • GRAPH variable holding which status of an order should render which variants/combinations of components so on.
  • STATUSES variable is holding which component is valued ( Order is random, no matter which is first or value is bigger/lower )

GRAPH using “|” operator which is a bitwise operator doing bitwise “OR”.

StatusBar | Cancel means:

0001 | 0100 = 0101 (5)

GRAPH’s CREATED property is calculated as 0101 in just in time compiler in V8 when compiling code for the first time. Never calculated after it. JS memoize till code cold-restart.

.shouldRender method doing bitwise “AND” operation on two variables. If the result is truthy, returns as boolean.

GRAPH[STATE] & COMPONENT doing this basic bitwise operation.

GRAPH[CREATED] & 0001(`which is StatusBar`)

0101 & 0001 -> 0001 (Truthy value)

.shouldRender wraps this basic bitwise calculation with Boolean(…), thus return boolean.

For further reading (If the bitwise operators do not similar for you)

You can change business logic over config-map.js
You can play with GRAPH, try new business :)

The testing approach is snapshot testing.

This approach gave us;

  • More flexible component reordering/moving
  • Reusable components with non-breaking business logic
  • More readable codebase
  • O(1) complexity for rendering decisions (Fast & Consist)
  • Easygoing/long term maintaining ability
  • Easy to test
  • Beginner-friendly code architecture

As a result, we switch our O(n) complexity to O(1) and better control over business logic needs.

Think about you are serving the same components in more than 40 countries, you can duplicate the bitwise config flag for each country then globalization problem has been fixed from day 1.

Bon appetit!

Cagatay.

--

--

Çağatay Çalı
Trendyol Tech

Hack the ( things || ideas ) with code, equipped with NodeJS and coding skills which gained in early age.