Decoupling to Win

Hey guys how you doing?

Let’s talk about cool thing and let Node.JS posts to next week!

Coupling and Decoupling, a long, long discussion and some developers simply ignore it! How many times have you heard: “it’ll be a tough job to change this thing”.

The changes must to be only at your back-end but your devs insists that the front-end must to be changed too…

Well, if you already heard this statements, sorry, there’s a tight coupling between your back-end and front-end.

This couplig breaks some software engineering principles (please, see https://courses.cs.washington.edu/courses/cse403/96sp/coupling-cohesion.html for more information!) and prevents that the teams works independently, decreasing the overall efficiency.

In this hypothetical case, the front-end guys must to await the back-end guys to finish their work to evaluate the necessary changes, and then, fix the front-end.

Sometimes, even if you access you data through an API, you can create a tight and undesirable coupling.

In this post, I’ll show you a complicated case that I have faced in a real life and how I fixed.

Of course, I’ll ommit the real data and I’ll simplify the layers to be more simple to show the problem and the fix.

Let’s code!

The Plan

It will be a website that consumes its data through an API. For some reason, the company must to change the API and, the return of the new API is somewhat different.

I’ll use .Net Core 2 for API and Website and a Azure SQL Database. Why? Well… Because I am a C# Developer!

The website will consume the API and list some names that are stored at database.

The APIs

The 1st

Class Person with its property Name.2017-09-10

The database StudiesII, hosted at Azure, with its table Persons, initialized with some names…2017-09-10 (1)

The API Controller Names, that will returns a names list.
2017-09-10 (8)

And… the result!2017-09-10 (3).png

The 2nd

Class Pessoa with its property Nome.2017-09-10 (4)

The database StudiesIII, hosted at Azure, with its table Pessoas, initialized with some names…
2017-09-10 (5)

The API Controller Nomes, that also will returns a names list.
2017-09-10 (9)

The result!2017-09-10 (7)

Note that, the result ‘doesn’t change’, it continues an IEnumerable<T>, both objects returns an Integer for the ID, and a String for the name, but, the JSON property name changed and it will be enough to break any app that consumes its data.

Consuming…

So, I started the three projects and at the names page, I filled an unordered list with the names provided by the API:2017-09-10 (10)

“The Boss” says…

“It works! Go, go go! Let’s finish the website!”

A few months later, the company that provides the API was shut down and… “The Boss” finds a small Brazilian Company that provides the same services and “The Boss”, that knows a little bit of websites, APIs, etc., think:

“Hummmm… the same data, it’ll be an easy job! just change the API’s enpoints!”

But, there is several “time bombs” coded at the website! You probably already know the history…

The tight coupling

At the page or even at its ViewModel, there are functions like this:theproblem

Did you noticed the problem? The front-end developer must to search the entire application to change the endpoints and fix the property names, that is probably different! And they are…

Capturar

Instead of change in a single point, there are now several points to check and the application is at risk and you can get this kind of error:

The endpoint was canged, not the property name. The app doesn’t throw an error, but, the name wasn’t printed because the new property name is “nome”…theProblem2

It can be very difficult to stabilize the application after the changes, because every place that this api is called must be fixed.

Decoupling

The application must rely in a middleware that will deal with the APIs and provide the class that makes sense to the application.

The middleware should get the APIs data and translate to internal types using the respository pattern.

For example, “name” or “nome” can be translated into “artistName” and so on! It makes sense for the application (do you know DDD – Domain Driven Design?).

Read more about the respository pattern: https://msdn.microsoft.com/en-us/library/ff649690.aspx

1st step: creating the Application Class

This is the website class that the app will rely for for print the artists’ names!
2017-09-10 (11)

2nd step: install a JSON Framework

Install Newtonsoft.Json! It’s a high-performance JSON framework for .NET (https://www.newtonsoft.com/json) and, if you use .Net, believe-me: you’ll need it!2017-09-10 (12)

3rd step: write agnostics classes to made the requests

We’ll need two classes:

ApiRequester

As the name says: this class will fire requests against an API!

It has a BaseServiceUrl, wich is a constant that holds a ‘Base Uri’. We’ll use it to create the Uri that’ll be used in the requests.

It has a constructor which expects two parameters: a string with a ‘path’ and a boolean who says whether the connection should be secure or not.

The constructor also instantiates the HTTP Client.2017-09-10 (15)

 

The method Get() will simply perform a GET at a “mounted” uri.

The logic is, as most of APIs follow this pattern “http (or https)” + “//www.yourwebsite.com/api/” + “a path, for example, names, user (passing an id), etc.”, the GetRequestUrl method uses these information to build the uri.

As my example doesn’t have a post, I only had a Get method. Remember: it’s a very simplified version!2017-09-10 (16)

ApiRequest

This is an Abstract Class and it also has virtual methods.

An Abstract class as Microsoft explains:

Use the abstract modifier in a class declaration to indicate that a class is intended only to be a base class of other classes.

Please see: https://docs.microsoft.com/en-ca/dotnet/csharp/language-reference/keywords/abstract.

For the keyword virtual, please see https://docs.microsoft.com/en-ca/dotnet/csharp/language-reference/keywords/virtual.

2017-09-10 (17)

Note the generic methods! Please see: https://docs.microsoft.com/en-ca/dotnet/csharp/programming-guide/generics/generic-methods.

The post is getting longer… 😦

These generic classes will be used on the concrete implementation of the repository pattern.

4th step: implementing the simple Repository Pattern

The API controller will get only one method: GetArtistNames(), so, this is the Interface IArtistNames.

And, this is the concrete implementation! I created the ArtistNamesRespository class!2017-09-10 (18)

It uses the ApiRequest as Base Class and also implements the IArtistNames interface.

The constructor

It passes to the base class the path and the boolean secureConnection.

The IArtistNames implementation

The method GetArtistNames calls the Base Class’ Request<T>() method, passing what it should returns, and I also overwritten the DeserializeResponse, to convert the JSON to an IEnumerable<Artist>.

5th step: the Api Controller

Here the first decoupled thing!

Note that I don’t instantiate the class ArtistNamesRespository!

The Api doesn’t know the repository! A class that implements the Interface IArtistNames is injected on its constructor.2017-09-10 (19)

The benefit with this approach is, I can code other class, test it and change at the Dependency Injection configuration and it’ll be changed at all classes that uses it.

Changing the line 23, all the application will be updated.2017-09-10 (20)

6th step: javascript fix!

The get URI now points to the middleware and the JSON property also refers to a middleware property!2017-09-10 (21)

Debugging

F5, manually go to “names” page!2017-09-10 (22)

The page is loaded and, when “document is ready”, the API is called!2017-09-10 (23)

1st break: the Dependency Injection instantiates the repository and will inject to the Api Class2017-09-10 (24)

2nd break: the repository is injected!2017-09-10 (25)

3rd break: the get is called!2017-09-10 (26)

4th break: the GetArtistNames is called! Important: it’ll call the generic method Request defining the return type!2017-09-10 (27)

5th break: the RequestWithoutParse() is called…2017-09-10 (28)

6th break: the Requester’s Get melhod is called…2017-09-10 (29)

7th break: note at the “Autos” panel the mounted URI…2017-09-10 (30)

And the response…2017-09-10 (31)

8th break: the JToken is parsed (RequestWithoutParse stands for “without parse to the middleware type”)…2017-09-10 (32)

9th break: now, the DeserializeResponse will be called. Do you remember? We have overwritten this method!2017-09-10 (33)

10th break: cool! The correct method was called!2017-09-10 (34)

11th break: now the recieved JSON will be converted to a middleware type – IEnumerable<Artist>…2017-09-10 (35)

The result! Success!!!2017-09-10 (36)

Refactoring: changing the API, the path and the Converter

Remember? “The Boss” changed the things… We have coded the right way and, if we’re right, with few steps we’ll change all the application to a New API!

1. We code a single class which is responsible for all API requests and we have a constant with a Base Uri. Let’s change it!2017-09-10 (37)

2. We have set the path of the calls… Let’s change it too!2017-09-10 (38)

3. Finally, we must to convert the new returned JSON to our type…2017-09-10 (39)

Done.

— Hey??? Only this?
— Yes! Run!

The result2017-09-10 (40)

Conclusion

It’s worth do the right thing!

Of course, in a real life the things are not so simple, but, no matter how complex is your application, you’ll only need to change 3 points, all of them at the repository layer!

Your business logic and the front-end will be preserved.

The “concrete case” that I’m inspired to write this post was funny.

As a technical leader, I tried to explain all this things to my manager, department director and vice-president, that it would be too expensive and risky change for the company and I suggested to mantain the middleware under our responsabilittie, because, if the change failed, we would keep the amount invested in the front-end.

They didn’t hear me, the change failed and the company perceive a huge loss in this operation.

Sad but true. Hope you hear me and do the right thing at the first time!

See you at next post! Do you want the post code? Ask me and I’ll put it on Github!!!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s