Wednesday, September 19, 2018

The distributed monolith antipattern

The words distributed and monolith are usually adversaries in software architecture, contrary to the monolith model,  a distributed approach will allow you to have isolated services as building blocks of functionality for your system. Let's assume you reached that architecture already, either from scratch or by decomposing an existing monolith. At this point you have a set of services. 

Some people go and just say - "it's microservices!". Well..., that's not enough yet, but now you have all the pieces into individual services and the whole system working together.  This is a step into the right direction for scalability, but we can do more in other areas. 

So, let's check: how do you deploy them?

If you deploy all services at once, you still have a lot to improve, for now you have a "distributed monolith" (Open to a better name for this), which I consider to be an antipattern, and this is more of a common practice than expected, this is basically a problem inherited from Service Oriented Architecture but there are a few reasons it happens.

Common reasons

1. Services share the same database.
This is old as time, it's OK for this to happen during transition from monolith or classic SOA to microservices, but you need to move away from it. Sometimes organizations just don't pour resources to continue moving forward with the evolution of a system.

2. Deployment constraints tying them together
Some DevOps limitation, rule or result of laziness (e.g. somebody liked how things looked in one docker compose file and left it like that).  

3. Shared library with business logic
Another bad practice from SOA, a developer encapsulated business logic into a library, then new business updates require all apps and services to be updated and deployed almost simultaneously.  Reusability is important in software but doing it through libraries when using services is a Pandora's box. If you have a service-based architecture, expose business logic only through services.  

You can find almost any reason to justify what could be seen as a bad practice, it's up to you, the developer, to decide how to proceed. For example, sometimes you *have* to share a database because consistency is more important than speed or scalability for a specific application. If a requirement like that exists, then you are already building the correct system and there is no need to modify it just to fit with an architectural schema.  

Monday, January 22, 2018

Playing with strings and performance in C#

A few weeks ago, I was solving a problem at HackerRank and after completing a solution that ran  under 100 milliseconds, the program would still timeout during execution. HackerRank limit is usually 1 second, so something was taking more than 900ms.

It was the strings!

Yes, we know handling strings is costly, but this time there was no way around it.  At the final stage of the problem I had to construct a string over 200k chars long from an array of Boolean values that represented the bits of the number.  

Disclaimer: Strings are slow, mainly because they are immutable. Concatenating two strings, creates a third one and possibly 2 for the garbage collector to pickup.

Looking through the code I noticed I was simply using "+=" instead of StringBuilder.Append method. After using StringBuilder the solution was faster and the submission was approved. It was  fast now, but it got me thinking "how much faster indeed?" which ended with me measuring the performance of concatenating strings, because we always knew StringBuilder was faster than regular operation with strings but I still wanted to see the numbers.

I used C# and tested the same set of examples in NetCore and full .Net Framework. I did not notice any performance differences between the two of them.

What was measured?

I measured 3 ways to concatenate strings, and each of them in reverse mode. Here are the 6 variants:
  • Using the + operator. (str += "1";)
  • Using + operator to insert in front (str = "1"+str)
  • Using string.Concat (str = string.Concat(str,"1"))
  • Using string.Concat to insert in front (str = string.Concat("1",str))
  • Using StringBuilder.Append to add at the end
  • Using StringBuilder.Insert to place in front
Every operation was ran against data sets of multiple lengths, for 10, 20, 30, 40 and 50k characters. The chart below shows the results in milliseconds. 

It was a surprise to see that StringBuilder.Append is not only faster, but appears to be in constant time O(1). Also, to see that the Insert method is for certain sizes slower than other operations, so StringBuilder is not always faster.  

Now if we run the tests for a data set with 100k characters, we get a new surprise: the insert method starts being faster at a bit over 50k chars in length, with the other operations degenerating in performance. 

If you like competitive programming or have an interesting in high performance solutions, make sure to always measure. Do experiments a lot in code and test different scenarios. In my case, I had an array reversed so I walked the array backwards and used the Append method instead of Insert. That was the difference between failing or passing a problem.   

Check the code for StringBuilder at GitHub. The implementation uses string.wstrcpy, while is blazing fast, this is still O(n). 

Sunday, January 14, 2018

New programming book published on Amazon

After a relatively long hiatus as a writer I finally completed a new milestone. I coauthored a programming book and published it on Amazon. I must say I am glad that we finally completed it; while it was a fun and rewarding journey, it was a long one and it took a lot of time, effort and coordination. 

The book is in Spanish, and it's 500+ pages long.

Title: "Empiece a Programar. Un enfoque multiparadigma con C#"
Format: Paperback

The title translates to "Begin programming. A multi-paradigm approach with C#". The book is written in Spanish, not only because all the authors are Cubans, but also because we believe that the Spanish-speaking community deserves a fresh new book; instead of a translated one.

We used C# throughout the book in order to teach programming, and we travel from the simple "Hello World" snippet to arrays, data structures, dynamic programming, recursion, inheritance, SOLID principles, functional programming and concurrency - among other subjects - across 17 chapters.  

Every chapter is loaded with code examples, detailed explanations and images to help the learning process. It's aimed to engineering and/or programming students, and even though the material is tailored for beginners, it can also be useful by more senior developers wanting to deepen their knowledge of programming.  

Here are the links to buy the book: