You all know it. When you want something very, very much, it eventually comes true. No? Never happened to you? So, it's only me then. Grab a cup of preferred beverage, sit down comfortably, and listen to my story.
It all began a lot of years ago. I was a developer and later technical lead in Kentico's E-commerce division. Back in those days, we struggled with new functionality and unfortunate decisions from the past. Those ancient choices haunted us every single day. Either in the form of a bug report or an obstacle between us and a new shiny feature.
The E-commerce module was mature enough to challenge the market. Our partners started to build online shops and commerce solutions with it to satisfy the everlasting need for digitalization. You can still see it out there – the last dinosaurs on their way to conquer the Internet. Even after so much time, the world is not entirely digital.
It was very convenient to have a commerce solution right in your CMS, and I'm sure it still is. Needless to say, the market got excited very fast, and the number of e-shops based on Kentico was piling up. It all worked well under lab conditions, but the real world hit us hard very soon.
When looking back, it's arduous to come up with a proper answer to why the hell we did this or that. It wasn't crystal clear a few years ago – the perks of jump-starting a new module. You want to have it quickly and with few resources. Just like playing Counter Strike. The first spawn of the first round, you don't have enough money, and your team has no experience yet. If you are eager to fight, you will instantly buy a Desert Eagle and, while screaming "rush B", you're running towards the enemy guns blazing. You just don't stop.
If you're an experienced player, you know it might work, but most probably, you're going to die. Yes, we rushed B and made a few mistakes. Mistakes in architecture and on a database level. It wasn't entirely on purpose. We had to use what was already there. A perfect example is the use of doubles. The one thing they teach you during your studies, never use a floating point to store numbers you want to use in a precise calculation. Can you imagine a better example than product price? Me neither. However, we did it. We used a double for the majority of numbers we had in the E-commerce module. You'll be surprised, but we didn't shoot ourselves in the foot because we are masochists. The reason was very simple. Kentico didn’t have decimal support. Of course, we had doubles at our disposal. Rush B!
The floating point precision may sound devilish, but honestly, it wasn't that bad after all. It was a mistake, that's for sure, but you need a fairly rare constellation to make it blow up in your face. Or you need another issue that will help. The calculation itself.
You don't encounter the actual hell of cart calculation if your experience ends at the cashier in a supermarket. Simple mathematical operations will become challenging with the taxing and discounting. Especially if you have multiple types of discounts, a taxing system that differs by country, and a cart full of items, gifts, and already discounted variations of all of the above.
We did our best and hardcoded the calculation to fit the current market. You can imagine we hit a wall with the expansion. A setup suitable for one region will not work for the rest. Once the order of the calculation step isn't correct, the double precision might start causing issues. The calculation core was not built to be massively customized. A lot of our partners managed to do it anyway, but with more and more features, it was getting harder. The solution was to rewrite the majority of the original codes. Unfortunately, we were beyond the point of return. The clock was ticking. The battle plan was to patch issues and find workarounds for unsupported scenarios.
We were in the Medieval Period of our E-commerce solution. The dark ages.
"99 little bugs in the code
99 little bugs in the code
Take one down, patch it around
117 little bugs in the code"
You can try to avoid the inevitable. Solve the core issues with workarounds and fixes, but the day will come that you have to face the horrible truth. Judgment day.
We had this epiphany two years ago. The current model wasn't sustainable, and the market was demanding e-commerce capabilities even more than ever.
The first step was to conduct extensive research about the pain points of the architecture and define the right solution. It was a long run. We reached out to a lot of partners, asking a lot of questions. Partners from the United States, Australia, and different parts of Europe. Maybe you were one of them. If that's the case, let me thank you. The time spent on this project was worth it.
The outcome of the research defined the patterns of calculation. We used the acquired information to create a prototype of the brand new architecture. Luckily for us, it was perceived very well by the partners and other users. There was a question or issue here and there, but we managed to polish it to their and our overall satisfaction.
Rising from the Ashes
I remember one thing from my history class. The Renaissance was a period in history, and the word "Renaissance" literally means "rebirth" in French. With the new architecture and all the changes, we introduced during prototyping, our e-commerce module was about to get reborn. This e-commerce renaissance meant a massive refactoring under the hood, including a database structure change.
I'm proud to say we did it. It was the biggest project in the history of the E-commerce division in Kentico, and we nailed it.
The primary advantage is, without a doubt, the new modular architecture. This is information that should ring every developers' bell. Without being too technical, I will say we have a very well documented map for the dev teams. You can visualize the new calculation core as a structure from Lego blocks. Every part of the calculation is one block. Some blocks are bigger, and some of them are smaller or consist of other blocks. But the tremendous part is that you can customize the blocks or switch each block for your custom one. You can easily create a brand new block and chain it to the calculation pipeline or change the order of blocks in the pipeline. Customization was always a virtue of the Kentico system, but this upgrade pushes it even further. With the extensive documentation and the treasure map, you or your developers will always know what to do and where. We believe it will make the changes error proof and very fast to implement. And not only the changes. All kinds of integrations should be straightforward from now on.
I left the boogieman for last. We no longer store price or other calculation related numbers as doubles. We have learned the lesson and introduced decimals into the system. The cart calculation uses decimals, and with the new architecture, we've mitigated rounding issues entirely.
Dropping the Hammer
The cart calculation engine was completely revamped with Kentico 11, but that was only the beginning. We are done with small steps. We want to push commerce with Kentico far and beyond. With this bold plan, we needed to go big. The module's core solved the crucial parts, but we still saw opportunities. Opportunities such as a different pricing strategy in regions or a flexible discount engine, vouchers, delayed payment, and so on. I could continue, and I will in the second part of this blog post.
If you like what you've just read, or if there are aspects you don't grasp entirely, please drop me a line in the comments section below. I always appreciate direct feedback. Especially for a project like this one.
Ask the Experts: Refresh 1, design patterns, and why you should move to MVC
Mar 16, 2021 • 3 minute read