Have you seen code like this and wonder how to make it cleaner?
if (country=="US") { // US specific code } OR if (client == "abc") { // Code for client abc }
I often see a web of if/then or switch statements sprawled out to various parts of an application to provide a country or client specific code paths. Such conditional statements have their counterparts in other layers of the application. These corresponding conditional statements are consistently required to be kept in sync with each other. This not only make the code very fragile, but also adds a lot of cost to a minor change.
Is If/switch are really bad? no definitely not, in fact it is good part as long as used properly and definitely not over used.
Like all other statements of a programming language, If/then/else, for loop, while, switch statement are the main building blocks of the any programming language and they empower us to implement complex logic. Software applications are getting bigger, complex and unfortunately most of the times messier.
Did I say messier? yes UNLESS we conform to the proven patterns and practices. Just by following some basic inheritance (OO) along with extracting some cross cutting concerns (AOP), we can reduce the complexities of the code.
In the following code snippet, a simple “if” condition is used to implement a country specific code in the same method. It is very likely that there would be other methods requiring to make similar distinction in the context and provide a country specific implementation. If there is a change required for one country, we will need to change the method and that will put code for other countries at the risk of accidental change. Hence unnecessary increase in the testing scope. This result in very fragile code.
public class BusinessProccesor { public void ProcessSomething() { if (context.Country == "AU") { // AU specific code } else if (context.Country == "US") { // US specific code } CommonCode(); } }
Just by following some basic inheritance (OO), we can extract all the logic for one country in one class, reducing the reasons to change a class. This will be a step towards implementing SRP (Single Responsibility Principle).
public absract class BaseBusinessProccesor { public abstract void ProcessSomething() { CommonCode(); } } public class AUBusinessProccesor: BaseBusinessProcessor { public void ProcessSomething() { // AU specific code base.ProcessSomething(); } } public class USBusinessProccesor: : BaseBusinessProcessor { public void ProcessSomething() { // US specific code base.ProcessSomething(); } } public class static BusinessProcessorFactory{ public BaseBusinessProcessor GetProcessor(){ if (context.Country == "AU"){ return new AUBusinessProcessor(); } else if (context.Country == "US){ return new USBusinessProcessor(); } } }
So instead of so several if/then/else or switch statements in a class, we have reduced it to only once per class i.e. at the time of creating an instance of the class. In the above code, it is in the static factory method.
I see this as a cross cutting concern and if we leverage the advanced containers (unity, castle windsor etc) available these days we can reduce it to once per application or even once per container extension. I will go into more details into this into my next blog.
[…] to the previous post, object creation based on the current context is a cross cutting concern, so it should be dragged […]
LikeLike
[…] is my third and last post on writing multi-tenant applications. Before this I have discussed how to avoid if/else type structures and how context based dependency injection can help us do it efficiently. In this post I will […]
LikeLike