Open Closed Principle in Python - Designing Modules Part - 4 | HashedIn

Open Closed Principle in Python - Designing Modules Part - 4

Technology - 03 Jan 2017
Harish Thyagarajan

This is the fourth post in a multi-part series where we will design a reusable python module. Earlier, we created the interface of our module and then worked on the implementation. Our module is already being used by several client developers to send messages.


New Requirements – Retry Failed SMS’es

We now have a feature request from the product managers:

Customers are complaining that they don’t receive SMS’es at times. Watertel recommends resending the SMS if the status code is 5xx. Hence we need to extend the sms module to support retries with exponential backoff. The first retry should be immediate, the next retry within 2s, and the third retry within 4s. If it still continues to fail, give up and don’t try further.

Of course, our product manager assumed we would take care of a few things, viz

  1. We will implement this in all of the 50 modules that are sending SMS’es.
  2. There would be no regression bugs due to this change.

Don’t modify code that’s already working

Let’s start planning our change. There are two seemingly opposing views here. We don’t want client developers to change their code, not even a single character. At the same time, the SmsClient class we wrote in part IIworks great – and we don’t want to change code that is already working either.

A little aside – let’s look at the open/closed principle. The open/closed principle tells us that we should not modify existing source code just to add new functionality. Instead, we should find ways to extend it without modifying the source code. It is a part of the SOLID Programming Principles. In fact, it stands for the ‘O’ in the SOLID principles. In our case, the open/closed principle implies that we don’t want to touch the source code for SmsClient.

Using Inheritance

This is tricky situation, but as with everything else in software, this problem can be solved with a little bit of indirection. We need something sitting in between our clients and our SmsClient class. That something can be a derived class of SmsClient.


If you notice, using inheritance, we got ourselves a way to add retry logic without modifying the existing code that is already known to work. This is the crux of the open/closed principle. See Footnotes for a caveat on using inheritance.

Adding Retry Logic

With that done, we can now work on adding the retry logic. We don’t want to retry if our client gave us an invalid phone number or a bad message – because it is a waste of resources. Even if we retried 100 times, it won’t succeed. We also don’t want to retry if there is a logic problem in our module’s code – because our code cannot fix itself magically, and hence, retry is unlikely to help.

In other words, we only want to retry if Watertel has a problem and we believe retrying may end up delivering the message.

If you revisit our original SmsClient implementation, you will now appreciate the way we designed our exceptions. We only want to retry when we get an SmsException. We simply let the client developers deal with all the other exception types.

How do we go about writing the retry loop? The best way to write the retry logic is via a decorator. It’s been done so many times in the past, that it’s best I point you out to some libraries.

In summary

The open/closed principle tells us not to modify our already working code just to add new features. It’s okay to change code for bug fixes, but other than that, we should look at functional / object oriented practices to extend the existing code when we want to add new functionalities.

Thus, in this post, we saw how the application of the SOLID programming principle and the open/closed priciple in specific helped us to manage retries in our system.

In the next post, we will see how we can handle an additional requirement of A/B testing without modifying existing code.

Footnotes:

In general, we should prefer composition over inheritance. In the next post, we will see the limitations of inheritance and why composition is better.

Free tag for commerce

E-book on Digital Business Transformation