One of the analogies (I beg pardon from “analogy police”) I
have for development is borrowed from the traffic. I believe that it is easy to
learn how to drive a car, however to drive a car safely and in high traffic one
must be aware of traffic rules. We don’t ride car to bump it to the people,
rather we do it to reach our destination in a safe and agile manner. There are
rules, practices and conventions to follow, without them traffic would be a
chaos and commutation will be more painful rather than pleasant.
Software development is basically a translator job. This endeavor
of development might span from couple of weeks to month, to years. The basic facts
remain the same that everyone is doing his job of translation. Business analyst is translating stakeholders
thoughts in to user stories, developers are translating user stories in to
working code, SQA is translating it into test cases. A functional bug is
generally a miss in translation. As close as we are to the production date, our
bug fixing cost is that much high. These translations are again validated using
the unit tests, integration tests and UAT (User Acceptance Testing).
In this article I would like to share my experience and learning’s
which I have gained during my journey, I have not reached the destination yet.
I would like to exchange thoughts with fellows so that we can learn from each other.
This article is focused at anyone who is learning to developing software.
Find out various components involved
I remember when I started my career and I was a just a
college pass out, I was very much passionate about coding a piece of
functionality. My passion kept me awake for so many nights until I realized
that a good focus and change in my development habit can make me more
As soon as someone approaches me and asks me to do a
particular task, all my listening skills were at their least. I was translating
requirement in my brain. I was mapping the things on the fly. I was good,
however the problem was as soon as I found that one particular point in
requirement is new to me, I am not aware of pattern/model to solve it; I would
stop listening to requirement and start doing a dry code in my brain. I would
not listen to requirement any more, rather will listen to the fictitious schema
and API calls running at the back of my mind. I am not sure how many people had
done the same thing. This resulted in a very poor development cycle, because I
need to go to the person again and again and find out more answers. These
visits were often too late during the development phase. This yielded in high
cost of software.
After doing it couple of times, I started introspecting my behavior.
I was curious what am I doing wrong
which seems so much right to me, after all if I am not producing good results consistently
with in time and budget (Each time every time), I must be missing on something.
That was the ‘Aha’ moment of my life when I found that
instead of focusing on how, I should be focusing on what first. I need to note
down what needs to be done, I can always find out better ways around how to do
it. So equipped with this new thought process. I started focusing on “What
needs to be done” first. I started focusing on the components as a block, which
might be required for my design. I
started appreciating the Lego blocks.
Find out a higher level flow among components
Once I have the components blocks, I started finding out the
flow or communication among them. I was very much sure that blocks cannot live
in isolation; they must be able to talk to each other. The communication among
them needs to be crisp and clear. There has to be a PR (Public Relationship
officer) for each block. This is actually used by other blocks as a liasoning officer.
Components talk to each other using these PR officers (more accurately the
public methods). As it is true with public figures that we need to follow
certain protocols to meet them. They will be happy to fulfill our request or
may be giving us an honorable denial as long as we are following the protocol. We
should not be asking them about their personal life. We should not be tweaking
the public relation officer by using our less known private connection inside
the block (after all it will be unprofessional). In same way our components
communication should only be based on the public methods, without any intrinsic
and intimate knowledge about its private members.
This brings us to an interesting programming paradigm of low
coupling and high cohesion. A coupling
is good; however it is good when it is low. I thought about it for a while and
tried to figure out why something bad in high quantity is good when it is low. I
turned out to the best engineering excellence of the world i.e. human body. I
found that in our body we have so many chemicals which are good, but only when
they are in limited quantity or with in the limit. Cholesterol for example (I
may be completely wrong here, I am not a doctor) is required by our body to do
various other functions.
Coming back to our point, without coupling between the
components, components will become like isolated islands, and there will be no means
of talking to them. This will defeat the original purpose of components being
there to help each other and provide services.
What is cohesion? Cohesion is the virtue by which all parts
of a component fits together to serve a single purpose. Assigning more than one
purpose may bring down the component. Cohesion starts from the component and
goes deep till the function level. Where every function tries to do only
specific task. Actually it is a bottom
up and inside out thing. As long as computer is concerned, it can run any kind
of code, however we write code for other human being, who is going to sustain
and maintain the system once we are gone. Code should be easily understandable,
it should not be a murder mystery to resolve where a debug- Holmes carries a call
stack and watch (read as binoculars and spy glass) to find out clues. Code is the best living
documentation but it rarely is the best documentation.
Bottom line is every component should have a responsibility
to fulfill and all communication to it should happen through the well-defined
public functions. The communication among them should have low coupling. My
favorite way to achieve it using Entities (will talk about it in some other
Measure twice cut once
I learned that while we are doing software development, the
only raw material which we put in is some coffee and snacks and our fingers
dancing over the keyboard. This might cause issues; a thoughtful harmony is
melodies while a playing of instrument becomes noise. If I adopt the way, I
used to develop the software and try to build a door. I will find that I am
reordering the wood logs and doing the same tasks repetitively. I might not be measuring
the dimensions for the door, but cutting the wood with estimates. I am not looking
at the requirements like where door will be used, what is the opening direction,
what is the closing direction and what is the top border embroidery design and
what is the bottom design. I just cut it, embezzle the decoration, and then
only to find that the wall slot is bigger and my entire effort will be in vain,
unless I add some kind of supporting wood log, however with that the artistic
decoration will be wasted, which was a requirement.
When we often do coding without paying much attention, we do
the same thing. As we write code, we get emotionally attached to it. We try to
defend it, pretend that there is no bug, assume that it is working and will
support future extensions. This attachment often causes the ego clash in team,
SQA and code reviewer are looked as devils incarnated to haunt us. We do not realize
how ugly it is unless we get a call to fix it or a change request to extend it.
There might be the case that we developed a good code
without measuring it twice. However the problem creeps in while we figure out
that the we don’t know what to do in a particular “else” condition of code. By doing
a white board session, paper work, mocks and discussion, we can find out such
hidden details in much advance.
The solid learning or measuring twice is to use
paper/pencil, white board and discussions in the team to figure out what will
be required. Mock the objects use them to create early prototypes. Jot down
your flows on piece of paper, prepare your table schemas on paper, and find out
what kind of data is expected from the persistent store. Use blocks, use low
coupling and high cohesion to communicate between various modules.
Design Principles to adhere to
Here is the list of
principles which we might want to look in to; this is more like common sense.
If we start building on this foundation, our software will be safe when hit
with the storm of changes, extension and support. I will bring them up in a
different post soon.
- Program to the interfaces not to
- Encapsulate whatever varies
- Favor objects composition over inheritance.