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.





Monday 24 November 2014

An important Software Design Property - Context Independence

We could start by asking what Context really means in terms of Software Design and why having Context Independence is good? Firstly, lets define Context:

Context -  it is  everything that needs to be set in order to use a given data structure (i.e a Class). This is mostly about its relationships and their dependencies.

Basically the Context of a given structure is what it needs to be functional, so without Context you can't use It. In other words, this is something that you can't avoid, you need to deal with it when designing your software. BTW, there are some very known design issues that follow  Data Structures with Heavy Context. Some of them are:
  • Make them hard to test;
  • Make them hard to use/reuse and extend;
  • Deal with this kind of structures is always hard, so it'll naturally make the them hard to change and maintain
Lets look to an example, Consider the following classes relationship:


Here are them exchanging messages:


AS far we can see, Class B, Class C and Class D have their own Context. This something they need in order to make their job. Class A is using them, and also it dealing with their contexts, as soon it needs to initialize them.  Here is where problems get started. What about the effort needed to test Class A? Avoid dealing with each individual Context  would be something desirable by any  Class which needs to the those classes. The property we are looking forward here is Context Independence.

A technique that can be used on this case is Dependency Injection. DI can make Class A free from the Context Initialization. By consequence it will also be flexible and make the design more susceptible to changes. This is how  it could looks like:



Now Class A is Context Free once it does not deal with all details with Context from other classes. Implementation on Class A will be more clear, testable and easier to extend and change.

Another technique that can be used in order to be sure if a given Structure is Context Free is checking how it is communicating  with other Structures. If it is asking other Structures How to things instead of What,  it means you are on the wrong. You probably have a Structure that knows too much about others  and it is probably dealing Contexts you should avoid.

Context Independence is a technique that can help you to keep the healthiness  of your design. It works pretty well with SOLID principles. I am actually not able to see them work separately  in a more complex solution.




Monday 10 November 2014

Building Changeable Software - The new Bridge Metaphor

In a Software Engineer daily job, there are several situations where a complete redesign needs to take place in order to make things work as they ideally need. The reasons to that happen (sometimes often than we'd like to see) can be many. I'll try to list some of them, but i can be missing some:

  • As developers we make mistakes - this one is obvious, knowledge about the domain  will come with time, the same is also valid for engineering techniques and principles. Until there we are gonna make mistakes and lack of  Code Review and design sessions  can just potentialize it.
  • Pressure to deliver - there are scenarios where we just need make things as faster as we can. Issues in Production that affecting the user experience can be damaging to business. So on this scenarios there is few space to huge refactorings  and redesigns and that is reasonable. The problem start when people start use this excuse to put pressure on anything we do, even it is not Production specific.
  • Fear to touch on production code - lack of test coverage can make it worst.
  • A mix between all them.
Understand the reasons why it happens and learn how deal with them is important for a Software Engineer also. Given the frequency it is scenario is presented to us, know how to deal it sometimes is the key in order to start introduce changes.

The new Bridge Metaphor

Let's say there is a bridge over a river. It lets people go here and there with their cars, but it is becoming too old. It's maintenance is becoming expansive and it is no long supporting the traffic volume. A new solutions needs to take place, otherwise users will suffer on the next years with the problems the current bridge is gonna present.
Ok, what about rebuild the current bridge in order to attend the new demands? The idea looks promising in terms of costs, but in the end of the day, it'll represent the bridge unusable during days or even weeks, which is unacceptable. Does not matter what happens, people needs to be able to keep using it.
Well, what could be done then? An alternative is keep the old bridge working and build a new one. At some point, when the new bridge is ready, the whole traffic can be switched to the new and fresh bridge disabling the old one.
Even more expansive, this is the most feasible thing that can be done once the other approach would bring several headaches to the users

Ok, but what it is the relationship with software development? I'd say it is all.
Business needs to keep moving, most part of the time there isn't much space to stop deliver functionality to make big redesigns. Try to sell this approach to business usually does not work. Moving things little by little is much easier to sell once it can be conciliated with functionality being delivered to production. This is like keep the old bridge working while new one is being  built, as far you can see on the picture.

As a Software  Engineer, I usually spend most part of my time maintaining software rather than working on green field projects  On such scenarios i have been following this approach in order to delivery good software and keep things moving. It also fits pretty well when dealing with legacy software.
The downside when following this metaphor is that at some point you will need to accept some code replication and some "ifs" on the code being delivered while the new bridge isn't done.