Filter pattern: kobiri’s parser pipeline

Souleymane Sidibe
3 min readDec 28, 2021
Photo by Quinten de Graaf on Unsplash

If you have never heard about Kobiri, it’s ok. A quick explanation will be: Kobiri is a mobile money client that relies on one of the most used mobile technology and on your carrier sms notifications. To learn more about it please visit kobiri.app/home.

Kobiri needs your sms to work properly. To be more precise, Kobiri needs to extract your transaction data from every sms notification coming from a specific set of senders. We have here two main use cases. The first time you open the app, Kobiri will fetch all your previous transactions(that are still available as raw data). It’s not rare to have to analyse thousands of transactions. And the second use case is every time you make a transaction you receive one or more sms that represent a given transaction.

This post will not cover how we deal with changes. I mean when the carrier changes a sms or the sender name or things like that.

So the problem I needed to fix here is, ​on the right hand side we have a set of parsers that can handle, each one, a specific kind of transactions. We have parsers for transfer transactions, parsers for a given bill payment. And on the left hand side we have tonnes of sms waiting to be parsed.
The constraints:

  • A transaction can have its meaningful data located in one or more sms
  • Once a transaction is retrieved you do not need to pass it to the next parser
  • We should be able to chain the parsers
  • A parser can use a sub-set of parsers while processing a given transaction. We will not talk about why we need this for the sake of simplicity
  • Testing!

Below the way we were handling the transaction

It was an infinite try catch blocks inside try catch blocks. I​t​ was horrible to read or change. The code above looks simple but it was way longer and complex than that.

Filter pattern or Criteria pattern is a design pattern that enables developers to filter a set of objects using different criteria and chaining them in a decoupled way through logical operations.

The criteria pattern to the rescue! if you want to learn more about it and how to implement it, the link below is a good start

I desperately needed something better that could scale. Because I knew that I would need more and more parsers. And having to deal with try catch blocks was not sustainable.

The criteria pattern was a good fit because it checked all the boxes(you remember the constraints above?) in a decoupled way. I could have a separate criteria and most importantly a separate class for a given transaction type. And even better, the getTransactions() function would barely change! Just chaining a new criteria. If I need to update the logic of a criteria the getTransactions() function would not care about it!
Testing is so much easier. You can unit test every criteria. You just need to verify if the output list is correct. That’s it.

Above, the new version of the getTransactions function. This function will change only when a new criteria needs to be added. You can clearly see the what. The how (implementation details) is hidden inside criteria’s implementations. The chaining aspect is also very cool because there is no if else. The code is short and easy to understand. You can see what kind of transaction type the app supports.

This is what I wanted to share today. The approach is not perfect. I will be happy to learn a much better solution. Feel free to comment or mention me on twitter.

This is probably my last post of 2021. I wish you all a happy new year.
Let’s make 2022 better! 😊

--

--