Pages

Saturday, December 28, 2013

Assertive Programming

 If you believe that something can never happen in your code, use assertions to ensure that. Never go with assumptions only.

"This code won't be used 30 years from now, so two-digit dates are fine."
"This application will never be used abroad, so why internationalize it?"

Always avoid this kind of self-deception.

In C and C++, we have assert macros which check a boolean condition. Here is an example:

void writeString(char *string) {
   assert(string != NULL);
   ...
}

This assert statement checks for a null string before executing the code inside the method. The execution stops when it encounters a null string.

While using assertions, make sure that they don’t make any side effects. The conditions passed to assertions may sometimes create side effects. Never put code that has to be executed as a part of the program into an assert statement.

Asserts shouldn’t be used for real error handling. Assertions check for things that should never happen.

Leave Assertions Turned On

Some people have a misunderstanding that assertions will become overhead after testing and deploying to production, and hence they should be turned off in production. The real problems start in production, not while developing or testing. Always leave the assertions turned on.

Turning off assertions when you deliver a program to production is like crossing a high wire without a net because you once made it across in practice. There's dramatic value, but it's hard to get life insurance.



- summary of Assertive Programming, from The Pragmatic Programmer: from Journeyman to Master

Thursday, December 26, 2013

Dead Programs Tell No Lies

Sometimes other people can easily find what’s not right with us, even before we realize it. It is true with other people’s code too. If something goes wrong in our code, sometimes it is a library routine that catches it first. In normal case, it is easy to fall into the "it can't happen" mentality.

But pragmatic programmers always code defensively. We always look for rogue pointers in other parts of the program. We always check that the correct versions of shared libraries were actually loaded.

All errors give you information. You could convince yourself that the error can't happen, and choose to ignore it. Instead, Pragmatic Programmers tell themselves that if there is an error, something very, very bad has happened.

Crash, Don’t Trash

It is always better to crash immediately after finding a problem than going wrong indefinitely. One example for this is Java. It throws an exception when something wrong happens. If that exception is not handled properly, the execution stops. In languages like C, which doesn’t not support exceptions, we can make use of macros.

When our code discovers that something that was supposed to be impossible happened, our program is no longer viable. Terminate it as soon as possible. A dead program normally does a lot less damage than a crippled one.

- summary of Dead Programs Tell No Lies, from The Pragmatic Programmer: from Journeyman to Master

Wednesday, December 18, 2013

Design By Contract (Part 1)

A contract defines the rights and responsibilities of a person, as well as those of the other party. Each party respects their commitments and everyone benefits. We can use the same concept to make software modules interact.

The concept of Design by Contract was developed by Bertrand Meyer, for the language Eiffel.

Every methods in a software system does something. Before doing that, the routine may have some expectations. Meyer describes these expectations and claims as follows:

  • Preconditions - The requirements for the routine. It defines what must be true for the routine to be called.
  • Postconditions - What the routine guaranteed to do. This defines the state of the world when the routine finishes its tasks
  • Class invariants - A class ensures that this condition is always true from the perspective of a caller. By the time the routine exits and control returns to the caller, the invariant must be true.



summary of Design by Contractfrom The Pragmatic Programmer: from Journeyman to Master

Wednesday, December 11, 2013

Pragmatic Paranoia

While driving, everyone personally thinks that they are the only good driver on Earth. We find all other drivers violating the rules. Then we start driving defensively. We look out for trouble before it happens. We always expect the unexpected.

The situation is similar in software world. We constantly encounter code written by other programmers - code that might not live up to our high standards. We check for errors or bad data.

But pragmatic programmers are always a step ahead.

They don't trust themselves, either!

No one writes perfect code. There is nothing called perfect software. We all should accept this fact. Pragmatic programmers code in defenses against their own mistakes.

Here, we’ll discuss about the defensive measures we take while coding.


summary of Pragmatic Paranoia (introduction)from The Pragmatic Programmer: from Journeyman to Master

Tuesday, December 10, 2013

The Art of Simplicity (Part 1)

It was for the first time, that we were visiting Technopark, Trivandrum. That’s one of the main reasons as to why we reached a little late. Dr. Venkat Subramaniam had already started delivering his keynote on The Art of Simplicity. Here, I am extracting some key points from it (I am directly jumping into the topic since I missed the first few minutes of the session!)...

Simplicity.. Being simple is always distraction-free. One example that we see and use in our day to day life is Google. Imagine, we are in the middle of a serious coding session. Suddenly, some confusion strikes our mind and we decide search for a better implementation or syntax. In the World of internet, there are a lot of things that can distract us. They tempt us to navigate away from our real goal, thereby, wasting a good share of our productive time.

This is where Google comes to help us. In the home page of Google, there is nothing to deviate us from our real intention. Just search, get what you want and leave! The real courage lies in developing such simple and elegant systems rather than complicating it with detailed designs or images.

Simple fails less. If at all it fails, it is always easy to find out the problem and cure it. Simple is always easy to understand.

Simple is always mutable. We neither have to change much, nor worry about anything else before changing it.

Here is a famous quote by Richard Feynman, an American theoretical physicist:

If you can't explain something to a first year student, then you haven't really understood it.

(to be continued...)



Thanks to +Vaishnavi M K and +Arun Prakash for your suggestions and proofreading.. :-)

Monday, December 09, 2013

Active Code Generators

Passive generators are used for convenience. But active generators are required if we want to follow the DRY principle. An active generator takes a single piece of information in one format and converts it into different formats. The generated code is disposable. The code is generated as needed by the generator. Whenever we find ourself trying to get two disparate environments to work together, we should consider using active code generators.

Active generators can be used in situations when we have multiple programming languages in a single application. In order to communicate, each code base will need some information in common, like data structures, message formats etc. Sometimes, we can parse the information out of the source files of one language and use it to generate code in a second language.

Code generators need not be complex. Keep the input format simple, and the code generator becomes simple.

Code generators need not generate code.  

It can be used to generate any text that is required in our project.


summary of Code Generatorsfrom The Pragmatic Programmer: from Journeyman to Master

Friday, December 06, 2013

Passive Code Generators

Passive code generators saves typing. They generate a given output from a set of inputs. The generated output is an independant source file. The origin of the file will be forgotten.

Passive code generators can be used for:

Creating new source files: While creating a new source file, some editors automatically add basic code, comments and other auto generated blocks to the file. This is done by using a passive code generator. They can be also used for generating source code control directives or copyright notices.

Performing conversions among programming languages: Passive code generators can be used for performing one time conversion of code from one programming language to another. The conversion need not be 100% accurate. We get to choose how much effort you put into the generator, compared with the energy we spend fixing up its output.

Producing lookup tables and other resources: Many of the earlier graphics systems were using precomputed tables, instead of calculating the trigonometric values, for sine and cosine values. These lookup tables were generated using passive code generators.


summary of Code Generatorsfrom The Pragmatic Programmer: from Journeyman to Master

Thursday, December 05, 2013

Code Generators

A code generator is a set of code that generates another code. This is used when the same code has to be used in different places (where we want to have the same functionality) with different contexts. This helps to avoid repetitive typing and once built, code generators can be used throughout the life of the project at virtually no cost.

There are two main types of code generators:

  1. Passive Code Generators - They run once and produce result. The result is free from the generator used. 
  2. Active Code Generators - They are used each time when a result is required. The result is a throw-away, which can be always reproduced.


- summary of Code Generatorsfrom The Pragmatic Programmer: from Journeyman to Master

Tuesday, December 03, 2013

Debugging (Part 4)

The Elements of Surprise

When something goes wrong, the amount of surprise we feel is directly proportional to the amount of faith we have in our code. This is the main reason that makes us think that there is something wrong with the library or the third party code we use. We must realize that one of our assumptions might have gone wrong. Prove it, if it is not, by checking all the boundary conditions.

Don't Assume It—Prove It

When we come across a surprising bug, take some time to think why it wasn't caught earlier. Merely fixing the code may cause the bug to happen again. Always check whether there are any other areas of code susceptible to the same bug. If yes, find and fix them. If bug fixing takes a longer time, ask ourselves the question: why?  If the bug occurred due to somebody’s wrong assumption, discuss the same with the whole team. If one person assumes incorrectly, there is a greater chance that others may also go wrong.

Do all this, and hopefully you won't be surprised next time.

Debugging Checklist
  • Is the problem being reported a direct result of the underlying bug, or merely a symptom?
  • Is the bug really in the compiler? Is it in the OS? Or is it in your code?
  • If you explained this problem in detail to a coworker, what would you say?
  • If the suspect code passes its unit tests, are the tests complete enough? What happens if you run the unit test with this data?
  • Do the conditions that caused this bug exist anywhere else in the system?

summary of Debugging, from The Pragmatic Programmer: from Journeyman to Master

Monday, December 02, 2013

Agile Kerala 2013: An Awesome Experience

It's only once in a while, we meet people who inspire us. In the last three days, I could meet many of them. We were at Technopark, Trivandrum to attend Agile Kerala 2013. It was the first ever Agile and Lean software development conference in Kerala. Truly speaking, I registered for the conference only because I would be able to visit Kerala and meet some of my friends. Learning was only my second priority.

But after going there, everything changed. It was an unexpected and awesome experience, I must say! Main talks were delivered by Venkat Subramaniam, an Agile Developer and Naresh Jain, Tech Startup Founder & Agile Coach. Both of them, and all other speakers were really good and gave us a memorable experience to cherish. The talks helped all three of us to have a better insight into Agile. 

We were not learning agile, but were experiencing it live!

The best among them was the live pair programming session by Naresh & Venkat. Unlike all other sessions, it was truly unplanned. This helped everybody, even for those who were new to pair programming and Test Driven Development (TDD), to understand the real power and use of these practices. They showed us how TDD helps us to detect and correct problems long before compiling the code...

There are more things to tell than a single post can contain. I'll be posting about the sessions soon.

Thanks to Vinod Purushothaman and Manoj Vadakkan for organizing such a beautiful event. Thanks to all other speakers...

I am quite sure that +Arun Prakash and +Vaishnavi M K experienced the same.. Happy to have you both there...  :-) 

And this is my first personal post other than the summaries. Please do comment and criticize.. I always love to hear feedbacks from you...


All good, all the time,

Yedhu Krishnan

Debugging (Part 3)

Let’s look at some commonly used debugging strategies:

Visualize Your Data

The best way to understand what a code is doing or what a code is going to do, is to look at the data it is operating on. The simplest way is to use ‘variable name = value’ approach. But it will much more helpful if we use some debugging tools which help us to visualize data. There are debuggers that represent our data as 3D diagrams. Even if our debugger has limited capabilities for visualizing data, don’t go panic! We can do it by ourselves by using hand, pen and paper or by using some external tools.

Tracing

Debuggers allow us to check the current state of the program. But sometimes, we need more than that. What if we need to check the state of the program or a data structure for over a period of time? That’s when we use tracing codes.

Tracers are simple, primitive statements that we write into our code or file. It could be messages like ‘reached here’ or ‘value of x = 2’. Even though it looks simpler, it is particularly effective and important at many places.

Tracing statements can be used to "drill down" into the code.

Rubber Ducking

One of the simplest ways to find a cause for the problem is to explain the same to somebody. The other person may not have to do anything. Just listen and nod (like a rubber duck bobbing up and down in a bathtub). While explaining things step by step, we will be able to find the cause by ourself.

Verbalizing some of the assumptions we took always helps us to get new insights about the problem.

Process of Elimination

We might be working on a mixture of application code, written by us, written by others, third party products like database etc and the platform environment like OS and system libraries. It is possible that there exists a bug in OS, compiler or library. But that should not be our first thought when a problem is detected. It could be the code under development. Sometimes it happens because the application code is incorrectly calling the library. Even if the problem does lie with a third party, we'll still have to eliminate our code before submitting the bug report.

Eliminate the correct parts one by one and narrow down the domain. Finally we will be able to track down the real culprit.


summary of Debugging, from The Pragmatic Programmer: from Journeyman to Master

Thursday, November 28, 2013

Debugging (Part 2)

Where to Start?

Before we start to look at the bug, we have to make sure that the bug happened in a cleanly compiled code. We have to set compiler warnings as high as possible. It is a waste of time to find a problem that the compiler can detect and find for us.

Before starting to fix the problem, gather as much as data as possible. If the bug is reported by a third party, there is greater chance that the accuracy will be less. Always watch the person to get enough details before starting.

Remember two main points:

  1. Interview the user who reported the bug - Gather enough data
  2. Never do artificial tests - Go for brutal and boundary conditions and test everything!


Bug Reproduction

The best way to start fixing a bug is to reproduce it. If we are not able to reproduce it, we’ll never know if it is there or not. Sometimes by forcing yourself to isolate the circumstances that display the bug, you'll even gain an insight on how to fix it.


- summary of Debugging, from The Pragmatic Programmer: from Journeyman to Master

Wednesday, November 27, 2013

Debugging (Part 1)

The word bug is used to represent something which is an object of terror. It was first introduced by Rear Admiral Dr. Grace Hopper, the inventor of COBOL. He was the first person to find out a ‘bug’ (a moth caught in a relay!!) in a computer system.

Bugs are still there in computer systems, even though they are not the flying ones! Software defects happen in many ways, from misunderstood requirements to coding errors. 

Modern computer systems are still limited to doing what you tell them to do, not necessarily what you want them to do.

No one writes perfect software. Here we can discuss about the issues related to debugging and about the strategies used for finding elusive bugs.

Psychology of Debugging

For many developers, debugging is a sensitive and emotional subject. People look for others to blame on bugs. Working on someone else’s bug is not the time to blame them. Consider it as problem solving, which helps us to improve ourselves.

Fix the Problem, Not the Blame

Debugging Mindset

We have to have the right mindset before we start debugging. We should be free from all other pressures and distractions. Be comfortable and remember the first rule of debugging:

Don't Panic

There could be many reasons (like facing a deadline) to get into panic. Be calm and think twice before starting. Don’t try to fix the symptoms you see. The actual cause might be somewhere else and the symptom could only be a result of that. Instead of jumping in to fix the symptoms, try to go deep and find the root cause and fix it.

Find and fix the cause, not symptoms…


- summary of Debugging, from The Pragmatic Programmer: from Journeyman to Master

Tuesday, November 26, 2013

Source Code Control

We all know about the UNDO key, which forgives our mistakes and helps us to start over. Most of the applications allow multiple levels of undo and redo. But what if we want to go back to something that was there 10 days back, even after rebooting the system multiple times?

That’s where Source Code Control Systems (SCSS) come into handy. SCSS can be considered as a project-wide giant UNDO key that allows us to go back to any point of time (in the development history!).

A good source code control system not only allows us to undo things. It helps us to:

  1. Keep track of every change we make in the source code and documentation
  2. Keep track of compiler and OS versions
  3. Answer many questions
    • Who made changes in this line of code? 
    • What's the difference between the current version and last week's? 
    • How many lines of code did we change in this release? 
    • Which files get changed most often?
  4. Identify releases of our software
  5. Create parallel branches and work separately on them
  6. Have multiple people working on the same code base
Source code control systems may keep the files they maintain in a central repository—a great candidate for archiving.

Progress, far from consisting in change, depends on retentiveness. Those who cannot remember the past are condemned to repeat it. 
- George Santayana


- summary of Source Code Control, from The Pragmatic Programmer: from Journeyman to Master

Friday, November 22, 2013

Editors

We know that text is the basic raw material of programming. It makes editors unavoidable while discussing about the tools. 

Editors help us to create and manipulate text. It is always good to be proficient with one editor rather than playing around with many. Learning one editor or its keybinding helps us to work very fast and you’ll find yourself getting better and better with it. 

Use a single editor well

But we have to consider some points while choosing an editor. Choose an editor which is available on multiple platforms. It should be comfortable and useful to us. 

Editor Features

There are are some basic abilities that we think every decent editor should have. An editor should be:
  1. Configurable - Including fonts, colors, window sizes, and keystroke bindings
  2. Extensible - An editor shouldn't be obsolete just because a new programming language comes out. 
  3. Programmable - You should be able to program the editor to perform complex, multistep tasks 

In addition, many editors support features that are specific to a particular programming language, such as: 
  1. Syntax highlighting 
  2. Auto-completion
  3. Auto-indentation
  4. Initial code or document boilerplate 
  5. Tie-in to help systems
  6. IDE-like features (compile, debug, and so on) 

- summary of Power Editing, from The Pragmatic Programmer: From Journeyman to Master

Thursday, November 21, 2013

Shell Prompts

Every craftsman needs a solid, reliable workbench for holding his/her work-piece at a convenient position while working with it. For programmers, the workbench is the command shell. From the shell, we can launch applications, debuggers, browsers, editors, and utilities.

But the programmers raised in GUI interfaces might find this difficult. They might also ask the question:

Can't we do everything equally well by pointing and clicking?

The answer is ‘No’. By using GUI, you are missing many of the capabilities of the environment.

A benefit of GUIs is
WYSIWYG — what you see is what you get. 
The disadvantage is
WYSIAYG — what you see is all you get.

GUI environments are normally limited to the capabilities that their designers intended. Never chain yourself by the restrictions created by the GUI. Gain familiarity with the shell, and you will find yourself improving.


summary of Shell Games, from The Pragmatic Programmer: From Journeyman to Master

Wednesday, November 20, 2013

The Power of Plain Text (Part 2)

Let us see the benefits of using plain text.

Insurance against obsolescence

Human readable data will always last longer than other forms of data. The plain text formats, used in legacy systems, can be parsed to get the required information at any point of time even if you have little knowledge about the original application. As long as the data is alive, you’ll be able to use it.

Consider a legacy system which was used to store the social security numbers of the employees in a particular firm. If the system was using plain text, it is easier to identify the SSNs while seeing this:

<FIELD10>123-45-6789</FIELD10>

It is far more readable than something like this:

AC27123456789B11P

In the first case, it is not at all difficult to write a script to get all the social security numbers if you know the format of SSN.

Leverage

Almost all tools can operate on plain text, from source code management systems to compiler environments to editors and stand-alone filters. This makes it easier keep the history of changes. File comparison tools such as diff and fc allow you to see at a glance what changes have been made.

Easier testing

If you use plain text to create synthetic data to drive system tests, then it is a simple matter to add, update, or modify the test data without having to create any special tools to do so.


summary of The Power of Plain Text, from The Pragmatic Programmer: From Journeyman to Master

Tuesday, November 19, 2013

The Power of Plain Text (Part 1)

As programmers, our base material is knowledge. The best way to represent the knowledge is nothing but Plain Text. Plain text gives us the ability to manipulate knowledge, both manually and programmatically.

Plain text is made up of printable characters which can be read and understood directly by people. Consider the example:

field123=43ebd

This is easy to read, but difficult to understand. A better choice is to make the text understandable to people. The following is a real example of plain text:

DrawingType=UMLActivityDrawing

Plain text is not always unstructured. HTML and XML are some examples for structured plain text formats.

In formats like binary, the data required to extract the data from the text is different (that additional data could be encryption keys, base number etc.). We cannot parse the original content without that additional data. But plain text always represents a self-describing data stream.

Drawbacks

  1. It may take more space to store than a compressed binary format.
  2. It may be computationally more expensive to interpret and process a plain text file
summary of The Power of Plain Text, from The Pragmatic Programmer: From Journeyman to Master

The Basic Tools

Every person starts his journey with a set of tools. Tools are inevitable for performing any task at its best. You may find one tool good for you, which helps you to improve your skills with the same. Tools help you to improve your talents.

The better your tools, and the better you know how to use them, the more productive you can be.

But tools shouldn’t be always the same. Sometimes, we may find some tools can do better than the ones we are using presently. At such situations, we have to take decision to adapt the change. This happens in software development also. Developers may stick to the same tool or IDE as they don’t want to leave its cozy interface. This is completely  wrong. We have to be comfortable beyond the restrictions and limits imposed by the IDE. The only way to do this is to keep the basic tool set sharp and ready to use.

We’ll start with the the basic tools used in software development..

- summary of The Basic Tools - Introduction, from The Pragmatic Programmer: From Journeyman to Master

Monday, November 18, 2013

Estimating (Part 2)

The following points help us to have a better estimate for the system:

  1. Understand what’s being asked - First part of any estimation is understanding what is being asked. Before giving an estimate, think about the scope of the domain. This is an important part in estimating. Often, the scope will form a part of your estimate: "Assuming there are no traffic accidents and there's gas in the car, I should be there in 20 minutes."
  2. Build a model of the system - From our understanding of the system, we should first build a model of the system. This leads to discoveries of underlying patterns and processes that weren't apparent on the surface. For a project, the model could be the steps that our organization uses during development
  3. Break the model into components - After building a model, the next step is to break our model into different components. We'll find that each component will typically have parameters that affect how it contributes to the overall model. At this stage, simply identify each parameter.
  4. Give each parameter a value - After breaking the model into components, give each parameter a value. This helps to figure out which parameters have the most impact on the result, and concentrate on getting them about right.
  5. Calculate the answers - Now, find answers by considering each component, rather than doing the estimation for that system as a whole. This helps to have better and more accurate estimation.
  6. Keep Track of Your Estimating Prowess - It is always a good idea to record our estimates and sub-estimates. Sometimes, we’ll find our estimates are good. But sometimes, it may go wrong. When it goes wrong, instead of simply avoiding it, take some time to identify what went wrong. This will help to avoid the same problem from happening again. 

- summary of Estimating, from The Pragmatic Programmer: From Journeyman to Master

Friday, November 15, 2013

Estimating (Part 1)

How much disk space will you need for a million names and addresses?
How long does a 1,000-byte block take to pass through a router?
How many months will it take to deliver your project?

Even though the questions lack information, all these can be answered. Depending on how good are you at estimating, your accuracy increases.

Learning to estimate is an important skill when comes to software development. Estimation helps to reduce surprises, rather than wondering why this happened as in when we encounter it.

All answers are estimates, but some are more accurate compared to the other one. While somebody ask us to give an estimate, we should think about the context first. Do they need high accuracy or just asking for a ballpark figure?

If your grandmother asks when you will arrive, she's probably wondering whether to make you lunch or dinner. On the other hand, a diver trapped underwater and running out of air is probably interested in an answer down to the second.

What's the value of Pi? If you're wondering how much edging to buy to put around a circular flower bed, then "3" is probably good enough. If you're in school, then maybe "22/7" is a good approximation. If you're in NASA, then maybe 12 decimal places will do.

The units we use for estimating are also important. If we say that something will take 180 days to complete, they will be expecting it to come in pretty close. But if you say six months, it will give a feeling ‘Oh! Six months!!’

The author recommend us to scale time estimate as follows:

Duration
Quote estimate in
1-15 days
days
3-8 weeks
weeks
8-30 weeks
months
30+ weeks
think hard before giving an estimate!

-  summary of Estimating, from The Pragmatic Programmer: From Journeyman to Master


Wednesday, November 13, 2013

Prototypes

Imagine scenarios where we are developing an expensive and complex product. We may actually want to test it or to see how it looks and works before even spending money and developing it. That’s where the idea of prototyping come in.  Car makers develop dummy models (real or 3D) of the cars before building the actual cars, which helps them to measure the aerodynamics, styling, structural characteristics and so on. By doing this we can see and try risky and uncertain elements even before building the real item.

Prototypes are used to try out something before actually developing it. This is entirely different from Tracer Bullets, which is a fully functional implementation. Prototypes may represent only a part of the whole system, with a fewer details. We build prototypes for the softwares to analyze and expose risk. A prototype may not always code-based. It could be as a drawing on a whiteboard, as a non functional mock-up drawn with a paint program, or with an interface builder.

Prototypes are designed to answer just a few questions, so they are much cheaper and faster to develop than applications that go into production. The code can ignore unimportant details

But if you are in a condition where you cannot avoid any details, you must ask yourself twice why you are developing a prototype. At such situations, more apt solutions might be Tracer Bullets or something else.

Things to Prototype

We can prototype:

  • Architecture
  • New functionality in an existing system
  • Structure or contents of external data
  • Third-party tools or components
  • Performance issues
  • User interface design

Prototyping is a learning experience. Its value lies not in the code produced, but in the lessons learned.

How to Use Prototypes

We can ignore some details while developing prototypes. They are:

  • Correctness - Use dummy data where it is appropriate
  • Completeness - The prototype may represent only a part of the real item, in a very limited sense
  • Robustness - Error checking is less likely to happen in prototypes. You have to use it by following the predefined path. Otherwise it may fail or cause errors
  • Style - Prototype code probably may not have any comments or documentation. You may produce reams of documentation as a result of your experience with the prototype, but comparatively very little on the prototype system itself.

Since prototypes use less details and represent a small part of the product,  they can be implemented using high level languages.

How Not To Use Prototypes

While developing prototypes, we must make it clear that they are disposable and incomplete version. Sometimes, prototypes may attract others as real implementations. At such situations, care should be taken. If you feel there is a strong possibility in your environment or culture that the purpose of prototype code may be misinterpreted, you must go for other approaches.

-  summary of Prototypes, from The Pragmatic Programmer: From Journeyman to Master

Tracer Bullets

How to fire a bullet in the dark?

One way is to locate your target, calculate different conditions and specifications and then fire. If everything works fine, bullet may hit the target.

There is another way: use tracer bullets.

When tracer bullets are fired, their phosphorus ignites and it leaves a trail to whatever they hit. The entire path of the bullet and the target can be identified. Tracer bullets are prefered more than calculations, why? Because the feedback is immediate.

The same method can be used in projects also. Like firing in the dark, if you are building something that hasn't been built before, the requirements might be vague. You might be using some algorithms, languages or technologies that aren't familiar. You may face a large number of unknowns. The project takes longer time and the environment may change in between.

Pragmatic Programmers, however, tend to prefer using tracer bullets. Tracer code can be used while developing.  It contains all the error checking, structuring, documentation, and self-checking that any piece of production code has. It has many advantages:

  1. Users get to see something working early - If we are communicating what we are doing during each step of development, the users can see something even before finishing the development. This keeps them from not being disappointed and helps to gain more trust.
  2. Developers build a structure to work in - It helps anybody the team to understand what is going on. They don't have to deduce anything from thin air
  3. You have an integration platform - Instead of integrating everything at the end, this helps to build a platform, to which modules can be integrated and tested while they are finished.
  4. You have something to demonstrate - You have always something to demonstrate to your customer.
  5. You have a better feel for progress - Makes easier to measure performance and to demonstrate progress to your user

Tracer bullets show what you're hitting. This may not always be the target. You then adjust your aim until they're on target. That's the point.

-  summary of Tracer Bullets, from The Pragmatic Programmer: From Journeyman to Master



Monday, November 11, 2013

Version Control Systems

Version Control Systems allow users to manage changes in programs stored in a computer system. Changes are usually identified by an incrementing number or letter code also known as revision number or revision.

One of the main features of version control system is branching. When you’re working on a feature which you are not sure is going to be in the next release, you can spawn a new branch and start working on it. After completing the feature, you can decide whether to merge it to the main line or to avoid it altogether. 


( image courtesy: FeatureBranch, by Martin Fowler )

Consider a scenario when 2 persons, Professor Plum and Reverend Green, work on their own feature branches as shown above. Both of them periodically pull from the main branch so as to avoid losing any updates. When Professor Plum finishes his feature, he’ll push it to the main line. After that, when Reverend Green pulls from the main line, he’ll get an entirely different version of the code. This results in a merge ambush when he tries to push it to the main line.


( image courtesy: FeatureBranch, by Martin Fowler )

The best practice to avoid this is to push the code to the main line regularly. This helps to achieve Continuous Integration. The longer you wait, the more painful it becomes.


( image courtesy: FeatureBranch, by Martin Fowler )

There are mainly two kinds of merges: textual merge and semantic merge. Textual merge refers to merging text from one source file to another. Semantic merge is tougher compared to textual merge, where we need to ensure that the feature that we’re going to merge should work with all other existing features. 

An alternative to using branches for making new features is a technique called Branch by Abstraction. This allows to make structural changes to the code-base incrementally without spawning another branch.

Another argument in favor of branching is Feature Toggle. Feature toggle helps to develop and test a feature on trunk. Imagine we are releasing into production every two weeks, but need to build a feature that's going to take several months to complete. Here we can create a configuration file to define a toggle for the unfinished feature. The feature will not be shown when the toggle is turned OFF. After completion, we can turn the toggle of that particular feature ON.

Distributed Version Control System

The distributed version control system uses a centralized repository, which allows a user to check in and check out. Here, the programmers are not aware of other people working in parallel, since they are isolated from one another. But there are some situations where it is handy to be aware of people around you. That’s why decentralized version control systems were introduced.

Decentralized Version Control System

A decentralised version control system, like distributed VCS, allows users to push and pull from a central repository. But here, every version of the repository that exists is a complete version of the repository. Each person has his own personal repository. A user can pull, not only from the central repository, but also from other users’ local repositories. In addition to that, commit and push can be performed within the local repository as well as on the central repository.

- a summary of the video, Version Control Systems, from Agile Engineering Practices, by Neal Ford

Reversibility

It starts with a quote:

“Nothing is more dangerous than an idea if it's the only one you have.”

Change, it may be required at any point of time. Nothing is forever. Relying only on one solution leads to greater problems.

If we go with the assumption that this is the only way to do something, unpleasant surprises may arise. There is always more than a single way to implement anything. Look for alternate solutions, be prepared for change at any moment.

But changes don’t have to be that strict or that immediate. But as the time goes on, you may get stuck at one point of time, due to lack of reversibility. Sometimes, small small problems will pile up into a bigger problem that is difficult to solve.

Our aim is to produce flexible, adaptable and maintainable code. By sticking to practices like DRY (Don’t Repeat Yourself), decoupling and the use of metadata, we don’t have to make critical irreversible decisions.

“The mistake lies in assuming that any decision is cast in stone—and in not preparing for the contingencies that might arise. Instead of carving decisions in stone, think of them more as being written in the sand at the beach. A big wave can come along and wipe them out at any time.”

Flexible Architecture

Along with code flexibility, we also need flexibility in the areas of architecture, deployment, and vendor integration. Technologies like CORBA etc, helps to isolate the parts of the project from being dependant on platforms. Our code shouldn’t depend on third party products, for which the changes are always unpredictable. Abstract out everything, from everything else.

“Whatever mechanism you use, make it reversible. If something is added automatically, it can be taken out automatically as well.”

-  summary of Reversibility, from The Pragmatic Programmer: From Journeyman to Master

Friday, November 08, 2013

The Singleton Pattern

The Singleton Pattern got its name because it restricts instantiation of a class to a single object. This can be implemented by creating a method which creates an instance of the class if one doesn't exist, but returns the reference to the existing object, if already exists. Singletons are different from static classes as we can delay their initialization to a later point of time.

In JavaScript, Singletons serve as a shared resource namespace which isolate implementation code from the global namespace so as to provide a single point of access for functions.

The applicability of the Singleton pattern is described as follows:
  • There must be exactly one instance of a class, and it must be accessible to clients from a well-known access point.
  • When the sole instance should be extensible by sub-classing, and clients should be able to use an extended instance without modifying their code.
Singletons are useful but they shouldn't be overused. The Singleton pattern is useful when exactly one object is needed to coordinate others across a system.

They're often an indication that modules in a system are either tightly coupled or that logic is overly spread across multiple parts of a code base. Singletons can be more difficult to test due to issues ranging from hidden dependencies, the difficulty in creating multiple instances, difficulty in stubbing dependencies and so on.

Read more about Singleton Patterns ...

The Evils of Duplication

Duplication is generally considered a bad practice. It should be avoided in production code as much as possible. Programmers are the people responsible for collecting, maintaining and organizing knowledge. Knowledge, as we all know, is never constant. It changes from time to time. Our knowledge about the requirements may change while communicating with the customer. The technologies and tools change rapidly with time. These changes create instabilities which always make programmers remain in the maintenance mode.

Most of the people do have a misconception that maintenance starts only when the product is released. That’s not at all right! With the arrival of new requirements and changes in the environment, maintenance needs to be a regularly followed activity.

Duplication is easy to create but ends up creating a maintenance nightmare. The only way to develop maintainable and reliable code is to apply the DRY (Don’t Repeat Yourself) principle.

DRY, as it sounds, is not so dry!

Imagine that we have the same information represented at two or more places. If we change data at one place, we should remember to change it in other places as well. Otherwise, two of these may contradict each other, resulting in serious problems.

“It isn't a question of whether you'll remember: it's a question of when you'll forget.”

That’s where the DRY principle comes in.

How Does Duplication Arise?

Duplication can be classified mainly into four categories:

Imposed Duplication: This happens when the developers are left with no other choice than to impose duplication. There are situations where duplication is unavoidable or the environment seems to require duplication. But with a bit of ingenuity you can normally remove the need for duplication.

Inadvertent Duplication: In this scenario, the developers don’t realise that they are duplicating information, and generally it happens by accident.

Impatient Duplication: This is the most easily avoidable duplication. There might be situations where duplication makes things easy. In such cases, developers go lazy and accept duplication. There could be many reasons for that. In times like these, developers shouldn’t forget the fact that:

"Shortcuts make for long delays."

Investing time now saves time later.

Interdependent duplication: This is the hardest type of duplication. Here, different people in a team (or different teams) duplicate the same piece of information. This happens often due to lack of communication (obviously, something that stands against agile practices!). This can be also avoided with a clean design, a strong project leader and a well understood division of responsibilities.

Whatever you develop, make it easy to reuse. Failure to develop reusable code leads to duplication.

summary of The Evils of Duplication, from The Pragmatic Programmer: From Journeyman to Master

The Revealing Module Pattern

The Revealing Module Pattern, proposed by Christian Heilmann, is a slightly improved version of Module Pattern.  This makes coding easier as we don’t have to repeat the name of the main object when we wanted to call one public method from another or access public variables. Also, in the previous case (Module Pattern), we have to change the name of the private method also, if we need to make it public.

In this pattern, we would simply define all of our functions and variables in the private scope and return an anonymous object with pointers to the private functionality we wished to reveal as public.

Advantages
  • More consistent syntax
  • Eases readability
Disadvantages
  • If a private function refers to a public function, that public function can't be overridden if a patch is necessary
  • Modules are more fragile
Read more about Revealing Module Patterns ...

Orthogonality

In computing, the term orthogonality refers to the degree of interdependence or decoupling between the modules. Two modules are orthogonal if changes in one does not affect another. This makes it easier to modify one without affecting any other components of the system. Non-orthogonal systems, on the other hand, are difficult to change and control.

Orthogonality adds up the value of overall system with two main benefits:

Increased Productivity

In orthogonal systems, changes are localized within the module itself. This helps to reduce the development and testing time. Also, the effort required to write self-contained blocks is less. Smaller components are easier to reconfigure and re-engineer, which also makes them reusable.

Orthogonality adds more functionality per unit. Assume we have one component which does M  distinct things and another component which does N things. In orthogonal systems, we get M×N different things. But in non-orthogonal systems, some things may overlap thereby reducing the total number.

Reduced Risk

Diseased sections of code are isolated in orthogonal systems and they are less likely to spread symptoms to other modules. Orthogonality also helps to slice and transplant them to healthy ones. The resulting system is less fragile since the changes affect only a small area.

- summary of Orthogonality, from The Pragmatic Programmer: From Journeyman to Master

The Module Pattern

Modules are an integral piece of any robust application's architecture and typically help in keeping the units of code for a project both cleanly separated and organized.

Different options for implementing modules in JavaScripts are:
  1. The Module pattern
  2. Object literal notation
  3. AMD modules
  4. CommonJS modules
  5. ECMAScript Harmony modules
Advantages of Module Patterns
  • Clean
  • Supports private data
Disadvantages of Module Patterns
  • As we access both public and private members differently, when we wish to change visibility, we actually have to make changes to each place the member was used.
  • Cannot access private members in methods that are added to the object at a later point.
  • Inability to create automated unit tests for private members.
  • Additional complexity when bugs require hotfixes.

Pair Programming

A summary of Pair Programming video, by Neal Ford (Agile Engineering Practices)

Pair programming is a controversial agile development practice. It involves two programmers working on a pairing station. A pairing station consists of two monitors, two mice, two keyboards and a single processing unit. So, technically, it is a shared computer system. The pairing system has all the tools required for development.

The two programmers have distinct roles. One of them is the driver, who types the code and the other is the navigator, who goes through what the driver is doing. The latter analyses the code in a holistic fashion and decides whether the driver is moving in the right direction. The navigator may thus interject the driver for suggestions and/or corrections. The two switch roles frequently.

The navigator and driver may have different ideas and due to collaboration, the resulting software tends to be much more efficient. If the same project has more than one pair of programmers, pair rotation can be done, which allows all the programmers to pair with each other. Pair programming and pair rotation helps to spread knowledge within the team rapidly. If one programmer discovers something really cool, within no time, everybody else learns it.


The human brain is divided into two: the left part and the right part. When coding alone, we use only the left part, which deals with linear (step-by-step) thoughts. During pair programming, the navigator uses the right part of the brain, which deals with non-linear and holistic thoughts while the driver uses the left part of the brain. Since the programmers always switch, they effectively end up using both parts of their brains and the code thus developed is of much higher quality.

In Flow, The Psychology of Optimal Experience, the author, Mihaly Csikszentmihalyi, explains about a psychological state called flow ( that’s what the book is all about! ). When a person is in his state of flow, time completely disappears. He dedicates full attention to what he is doing and may also experience tunnel vision. In this state, people are highly productive. However, the flow state is highly fragile and once broken, it can take up to 20 minutes to get restored.

The state can be compared to sleep. We fall asleep unconsciously. But when somebody wakes us up, it will take time to get back to sleep again. Similarly, the train of thought, once broken, will take time to get loaded back into the brain again.

During pair programming, it is possible for two people to be in the flow state at the same time! That is a really powerful source of productivity. Moreover, when we work in pairs, people are less likely to interrupt us presuming we are busy, as opposed to when we work alone. This helps retain the flow state for a longer period of time. A person also ends up wasting less time after breaks since he knows that the other programmer in the pair is waiting.

Pairing is tightly feedback-driven. Coding is the most complicated part in the development cycle and getting correct feedback at the right time helps increase productivity and decrease error rate.

The driver narrates his actions, which helps him understand better what he is doing. It is proven that when we recite something, we’ll be able to comprehend it in a much better manner. Pairing helps in knowledge-sharing and communication. It also makes programmers experts at explaining complex technical concepts.

Furthermore, it is fun too..!!

What pair programming is not
  1. Two people crowded over one computer
  2. Mentoring - Mentoring is when one person is learning and the other is coaching. This is a little hard for both parties, because the coach has to slow down for the learner to understand and the learner needs to push himself beyond his comfort zone to understand things better.
  3. Keyboard domination - This happens when one person loves to type. One idea to avoid this situation is to combine it with Test Driven Development. One person writes a failing test and the other writes code to make the test pass then writes another failing test. The former now writes code for that second test to pass, and this process continues.
  4. Pair marriages - This happens when pair switching does not happen.
  5. Less productivity - The decrease in productivity is not significant when compared with the decrease in error rate. In fact, errors take more time to get fixed during later stages.
Isn’t it awkward if I pair with someone who is much better than me? Of course not!

- “When you play with a better player, your game gets better.”



Thanks to +Jerry John Jacob for the proofreading and edits.. :-)

The Three Bucket Model

The features while developing a product can be categorized into three buckets:
  1. Gamechanger - People will want to buy your product because of this feature.
  2. Showstopper - People won’t buy your product if you’re missing this feature, but adding it won’t generate demand.
  3. Distraction - This feature will make no measurable impact on adoption.
This can be explained as follows. If you are building a phone, it has to be able to call others. Otherwise people will never buy your product (since it wouldn’t be much of a phone). But having voice call feature won’t make everybody buy your phone, because other phones already have that. Here voice call feature is a showstopper.

But suppose if your phone can project videos on to a surface, a feature which is not there in many other phones, it could be a gamechanger, which excites many people. But some people will not even care about that (and they won’t buy your phone!).

Empirically, successful products have one to three game changing features, dozens of features that neutralize showstoppers, and very few features that are distractions.

Constructor Pattern

In object oriented languages, constructor is a special method used for initializing an object once it is created and allocated memory for that. In JavaScript, as almost everything is an object, we're most often interested in object constructors.

Object constructors are used to create specific types of objects - both preparing the object for use and accepting arguments which a constructor can use to set the values of member properties and methods when the object is first created.

Object Creation

Three common ways to create JavaScript objects are:
  1. var newObject = {};
  2. var newObject = Object.create(null);
  3. var newObject = new Object();
Where the "Object" constructor in the final example creates an object wrapper for a specific value, or where no value is passed, it will create an empty object and return it.var newObject = new Object();

JavaScript (implementation of) Design Patterns

Here, we’ll explore the JavaScript implementation of some of the patterns.

Categories Of Design Pattern

Design patterns can be broken down into a number of different categories. Three of these categories are:
  1. Creational Design Patterns - focuses on handling object creation mechanisms. Examples are Constructor, Factory, Abstract, Prototype, Singleton and Builder.
  2. Structural Design Patterns - concerned with object composition and typically identify simple ways to realize relationships between different objects. Examples are Decorator, Facade, Flyweight, Adapter and Proxy.
  3. Behavioral Design Patterns - focuses on improving or streamlining the communication between disparate objects in a system. Examples are Iterator, Mediator, Observer and Visitor.

Anti-Patterns

While a pattern represents a best practice, an anti-pattern represents a lesson that has been learned. There are two notions of anti-patterns that are presented. Anti-Patterns:
  1. Describe a bad solution to a particular problem which resulted in a bad situation occurring
  2. Describe how to get out of said situation and how to go from there to a good solution
An anti-pattern could be a bad design that is worthy of documenting.

Writing Design Patterns

It would be good to consider these tips while designing new patterns:
  1. How practical is the pattern? - Patterns should provide proven solutions, not speculative ones.
  2. Keep best practices in mind - Design decisions should be based on the best practices.
  3. Our design patterns should be transparent to the user - Design patterns should be entirely transparent to any type of user-experience.
  4. Remember that originality is not key in pattern design - While writing design patterns, we do not need to be the original discoverer of the solutions. If the approach is strong enough to have broad useful applicability, it has a chance of being recognized as a valid pattern.
  5. Patterns need a strong set of examples - A patterns should have examples that demonstrates its successful application.

The Structure of a Design Pattern

A pattern is presented in the form of a rule that establishes the relationship between a context, a system of forces that arises in the context and a configuration that allows these forces to resolve themselves in the context.

Component Elements of a Design Pattern

A design pattern should have a:
  • Pattern name and a description
  • Context outline - the contexts in which the pattern is effective in responding to the users needs.
  • Problem statement - a statement of the problem being addressed.
  • Solution - a description of how the problem is solved.
  • Design - a description of pattern's design and the user's behavior in interacting with it.
  • Implementation - a guide to how the pattern is implemented
  • Illustrations - a visual representation of classes in the pattern
  • Examples - an implementation of the pattern in the minimal form.
  • Co-requisites - supporting patterns needed.
  • Relations - other patterns that resemble this pattern.
  • Known usage - where and how the pattern is used.
  • Discussions - thoughts on the benefits of the pattern.
Though the initial cost for creating a pattern is really high, the value return from that can be quite worth it.

What can be considered as a Pattern?

Not every algorithm, best practice or solution might not be considered as a complete pattern. Even if something appears to meet the criteria for a pattern, it cannot be considered as one until  it has gone through suitable testing by others for a period of time. A Pattern should be both a process and a thing.

Proto-patterns
: A pattern that has not yet been known to pass the "pattern"-ity tests.

Also, the individuals sharing the pattern may not have the time or interest of going through the "pattern"-ity process and might release a short description of their proto-pattern instead. Brief descriptions or snippets of this type of pattern are known as patlets.

The work involved in fully documenting a qualified pattern can be quite challenging. A pattern may be considered "good" if it does the following:
  1. Solves a particular problem: Patterns are not supposed to just capture principles or strategies. They need to capture solutions.
  2. The solution to this problem cannot be obvious: The best design patterns usually provide solutions to problems indirectly.
  3. The concept described must have been proven: If a pattern is highly speculative in nature, only the brave may attempt to use it.
  4. It must describe a relationship: The pattern must describe much deeper system structures and mechanisms that explain its relationship to code.

Advantages of Patterns

Why do we use Patterns? Here are some advantages:
  1. Patterns help in identifying minor issues that can cause serious issues during the software development process
  2. Patterns provide generalized solution, not specific to one problem
  3. Patterns help to make the code more DRY
  4. Patterns add to a developers vocabulary, which makes communication faster
  5. Patterns that are commonly used can be improved over time, making it more efficient
We use patterns every day. To understand how helpful patterns can be, lets review a simple element selection problem that jQuery solves for us.

Suppose we need to get the count of all the elements in the DOM with class 'foo', we can use a number of methods:
  1. Select all of the elements in the page and then store references to them. Next, filter this collection and use regular expressions (or another means) to only store those with the class "foo".
  2. Use a modern native browser feature such as querySelectorAll()
  3. Use native features such as getElementsByClassName()
But in jQuery, we can simply use $("selector"). This is significantly more easy to use for selecting HTML elements on a page versus having to manually handle opt for. This provides the most optimized way for accessing all the elements having a particular class or characteristics.

JavaScript Design Patterns - Introduction

What is a Design Pattern?

A pattern is a reusable solution or a template that can be applied to commonly occurring problems in software design.

Why patterns are important?

Design patterns have three main benefits:
  1.     Patterns are proven solutions
  2.     Patterns can be easily reused
  3.     Patterns can be expressive
Patterns provide a solution scheme, not exact solution for the problem. Patterns don’t solve all design problems nor do they replace good software designers, however, they do support them.

Learning JavaScript Design Patterns

This series is a summary of the book Learning JavaScript Design Patterns, by Addy Osmani, which I am currently reading. It is available for purchase via O'Reilly Media, but also available as a free eBook online. I'm looking forward to your feedback...