Friday, November 14, 2014

So what is "decoupling"?

One favorite argument when arguing for new technology or when people is arguing over what design principles you should use is the term "decoupling". My personal belief about this word is that it's extremely abused and more than often just used to boost the credibility of your own idea. It's also used as something to give the technology some "magic" properties as in "if we use this everything will be a lot easier". This is especially true for the arguments for using technologies like REST or Microservices. These two definitely have their uses but too often they are used as some sort of silver bullet which solves everything you throw at them. And with these two technologies are very often accompanied with the term "decoupling" or more correctly loose coupling. Well how intriguing, so how do they do this?
Consider following code
public void process(String[] array){
   for(int i = 0 ; i < 3; i++) {
       // Do something with array[i]
   }
}

So we loop through an array which is 3 elements long. So what happens if we do
public void process(String[] array){
   for(int i = 0 ; i < 5; i++) {
       // Do something with array[i]
   }
}

We have now changed the loop to 5 iterations. We haven't changed the method's signature so we don't need to change the type or anything, in a REST service the URL haven't changed. It still looks like the method as in the previous example. However it will fail if the client only has provided an array which only contains three elements. So how does this relate with REST or Microservices? Well if this would be a REST method, the technique REST wouldn't do shit about it. It would fail miserably like any other protocol able to invoke a method. This change will require a change with the client, so its not particularly "decoupled". The same would be true for a Microservice, all of its clients has to change. So where's the decoupled stuff with it? In REST is it the idea of you could add parameters without changing an API with a JSON map? Whats the point of that, send in data the service doesn't use or receive data which is not used? Have a endpoint which swallows data which you then try to make sense of it? Yay now you just created a ball of mud service by bypassing all of the abstraction mechanics you have available because you are lazy and being unprofessional.

With a Microservice the argument is that just because you can deploy stuff separately will make them decoupled. How does that apply to the above change?

 There's no such thing as a free lunch when coding. The above code is extremely simple but the length of the array is extremely important for the overall functionality of that piece of code. Actually there loads of information you have to deal with just with dealing with a string array of 3 elements. Cutting corners here will create a code which is bound to be misunderstood (yes with or without test), its just a matter of time. The above code has no description or information on what type of strings which is allowed as parameters. String's per se is an abstraction of information. A standalone string doesn't mean anything, it has to be put in a context which is meaningful for that particular data type. Just because it's a string and it's "understood" by the java runtime as an typed object doesn't mean its something which is relevant.

In today's http world, where we don't have to deal with the underlaying binary behaviors because it's abstracted away from us by standards like UTF-8 and such its really easy to not understand that most of the things we are dealing with are just some sort of representation of something, but because we can read it, and interpret it (as humans) we forget that whenever we're sending stuff (changing context) the information has to checked again to actually make sure that the context hasn't changed. This is what we see in the above example. The context has changed. It's still the same type of data but the requirements has changed.

Yes the example is a simple one, but imagine when a system contains millions lines of code, and try to follow data through a system where the code is not describing it's expectations of data makes it extremely hard to reason about the outcome of that code. So think twice when using your damn maps, and just because you can give abstract properties to the relations of an object doesn't mean that will create better code. In fact it will create a lot worse code since the intentions of the data is not described. It's like you would convert everything into an the type object and typecast it just whenever you want the information.

No comments:

Post a Comment