Sunday 28 December 2014

Creating good interfaces - The Law of Demeter




For the ones who are used to the OOP approach, the term Interface,
may relates to a structure that will determine the behaviour that other structures will assume. However, when talking about Software Engineering concepts they are more than that. They help to define Software abstractions that can be widely used in a software system. Interfaces can also be seen as what structures exposes (i.e make public), to the world. Once you make something public, you're creating a chance to other structures rely on and from this point, you'll need to maintain this relationship.
Such definition help us to understand why some software implementations are so hard o maintain.
Sometimes people don't get it right and make things public when they actually should not. Structures that exposes functionality more than needed, are actually creating a new chance to be coupled to other structures. More coupling means a software that is hard to change . A software that is hard to change is expansive. A software that is expansive... well, you may know what is gonna happen from this point...

The Law of Demeter


It is a Software Design technique that aims  to help create low coupled structures. It's based on the Information Hiding principle where structures know less as possible about each other.  It states that structures should only "talk" with his "close friends" not with strangers. Even when talking with "friends", they should avoid go into "details" about how they internally do things.
As far you manage to create a solution where structures don't know about how internally each other work, you are gonna create a solution that is more susceptible to change. It is certainly a property we look for when creating any software solution.

The problem


To understand the solution, would be better firstly understand the problem. Consider the following:





On the previous example, ClassA has a given responsibility. However, it exposes it's internal details like the ClassB usage. The scenario is even worst once ClassB also exposes the need of use ClassC. This last has actually a functionality that everyone else seems to be interested in. Here everybody knows everybody, this is actually creating a weak dependency chain. As far this system grows, other structures can do the same as ClassA, making the  whole system more coupled and harder to maintain. Here all classes are violating the Demeters's Law. More than that, they don't have good Interfaces.

The Solution


Good interfaces don't reveal its internal implementation details, they expose only what is enough to it's consumers, It provides more flexibility in which regards internal changes once the coupling between structures is well managed. Looking  at the previous solution, it stands out a design flaw once AnotherClass is using ClassC through ClassA and ClassB.
A possible solution would make ClassA manage the calls in a such way that ClassB and ClassC wouldn't need talk to each other. ClassA could also expose the functionality in a such way that AnotherClass wouldn't need to know any other internal structure.




Internal details in all classes are not exposed anymore to AnotherClass. Differently than the previous solution, small internal changes on ClassC are unlikely to break all other classes . The previous chain dependency is now broken into a more composable solution.


Pros

  • Low coupling. A solution that is simpler to maintain 
  • Interfaces that are simpler to use 
  • Improvement on the software testability once internal dependencies are no exposed.

Cons

  • It is common see on the web definitions that the Demeter's Law is a matter of counting the "dots" between method calls (i.e more than two dots violates the law). Look at this direction only can be pointless. Fluent Interfaces is an example that this definition alone can be wrong. The Law should be read as a low coupling principle than other thing. 
  • The Demeter's law issue lives on its own name. It's stated as a law but does not means it never needs to be violated. In cases where the changes on the design aren't worth compared with the benefits, would be ok live with it for a while. A good code/design pratic would help you and your team put a light on this.

Related links: 

Sunday 14 December 2014

Being Explicit

Be explicit on what you mean can sometimes save from headaches and troubles. If you go to a restaurant, and there things you don't like to eat, you need to make it explicit to the Waiter (specially if you are allergic, which is my case), before ordering a dish. If you manage to make it right, your dish will be as you wish. Notice that to be successful here, you needed to be explicit with the Waiter, otherwise he wouldn't get your right,
Ok, lets see now hot  all these is relates with software development. Lets start with a couple of questions:
  • Have you already, debugged an API or any software unit in order to realise what it does? 
  • Have you spend hours using the approach "try and fail" to be sure about the side effects of a design change? 
  • Have you looked to a method/function/procedure that returns nothing, receives no parameters and throws meaningless exception?
If you said yes for any of these questions, then you have already dealt with a design that is not explicit enough about its intentions. On those scenarios, we are not able to be sure about the consequences of changes on the design or even be 100% sure about what expect from there, at least not easily. This is a problem I've seen quite often in some systems, and there are some variables that can make the scenario a bit more complex:
  • New people joining on the team.
  • Lack of tests
  • No "useful" documentation.

What means be Explicit?

First of all, lets look for a definition of the word explicit:
  • Fully and clearly expressed; leaving nothing implied. Meaningful
  • stated clearly and in detail, leaving no room for confusion or doubt. Fully Understanding.
  •  Fully and clearly defined or formulated: "generalizations that are powerful, precise, and explicit" (Frederick Turner)
Meaning and understanding are the key things here and that is why they are highlighted. A software unit is explicit enough when we make the right assumptions about what it does without go into details about how it does and also having full controls over its side effects. A whole design is explicit enough when we are able to recognise the right concepts/abstraction and be able to predict what is their behaviour when working together.

How to get there?

Here are some tips I use to make my designs more explicit:
  • Look for deep understanding on the domain - This a a pre-requisite to all items that are gonna follow. In order to find out the right abstractions, you need to understand the rules, see the entities, recognise its behaviour, the boundaries, etc. Everything starts from here. If you don't find the right abstractions, something will be missing in your design and the chances to achieve explicit will be smaller. This knowledge usually comes with time but as soon you get there, the explicit we are talking about Will emerge.
  • Minimise the side effects - side effects are hard to make explicit. When trying to make them explicit we usually end up with a complicated and unclear solution (i.e, checked exceptions, sharing state). On the other hand, hide it totally sounds unnatural  couse it will hard to predict them when using the system. If you can't get right of them, try to minimise shared state internally and use other software design techniques to deal with failures on the right place.
  • Create meaningful interfaces - In the end of the day,  we  expose APIs and functionalities through interfaces. Interfaces need to be clear enough about what they are suppose to do when used. It pass through finding the right abstractions giving to it the right names.
Be explicit is a matter of being honest about what are the intentions (Intention reve of your design. It is  It does not mean an implementation should reveal all its internal details but instead,  providing the necessary information to the that are interested use it safely, without misunderstanding.

Saturday 6 December 2014

Paying debts


It is awesome the benefits  that credit cards brought to us. Where ever we go, for almost anything we buy, we can just use our credit cards! We almost don't  need cash on the wallet anymore, cards are enough! The way they work is quite simple. As far you use them, you accumulate debits with bank that needs to be payed later. Anything different than that will put you troubles and it will stop working.
Such example can be perfectly used as a metaphor for Software Development. From the technical side, we make agreements with business people in order to meet the schedule. We  implement short term solutions, we postpone design decisions that has huge impact on the software being delivered, etc. That is fine once all parts  keep in mind that, "there is no free lunch"! As using credit cards, there will be a time we need the pay for our expanses, otherwise we will be in troubles. It means that business and tech side will need to review the debits created along the way and "pay" for them at some point.

As  Software Engineers, I'd say we fail very often in order to show it to business. If we manage to release the product two, three, four times without even touch on the Tech Debt subject, business could argue "why wouldn't the Engineers make it once more"? Then Releases will take more time to be delivered, developers will be under pressure, more and more bugs appearing on production, etc. Suddenly the software that was released just few years ago to production now is being called "legacy... Well, you may have seeing it already, and you also may now what happens from this point....

I've  been approaching this scenarios using some techniques, some of them I'm able to describe:


  • The new Bridge Metaphor: Believe me, nobody from business will easily accept stop everything in order to pay Tech Debts. I'd say it is at least unlikely to happen. Things need to keep moving and that is natural. So if we find a way to conciliate delivery and improvements would be perfect, wouldn't it? So, there is a Software Design technique I've been using during few years that works well on this cases,  the new Bridge Metaphor. The main idea is try to conciliate delivery and improvements all at the same time. Well, this is what business people want to listen when approaching them with problems i described on the beginning of this post, don't you think?
  • We need to show to business clearly the problems on not picking up tech debts. Sure, there several other variables that will weight here that makes it easier or harder, i.e: Organisation Mature, how business trust on tech team, complexity and risks involved, etc. BTW, another thing that I'll  look on such scenarios  prioritise the debts that if payed now, will have immediate effects on the following releases.Following this approach, the task of showing the importance of prioritise debts becomes easier. I'm telling that couse there are times where there are some many debts to pay, that picking try to prioritise them aleatory usually ends in long meetings with frustrations on both sides (business and IT).

As mentioned before, the point sometimes is more complex than that. Even the techniques i mentioned will demand some effort and flexibility from both sides (business and IT people). BTW, i believe these tips can help even in more complex scenarios.