Program by Coincidence

We should avoid programming by coincidence—relying on luck and accidental successes— in favor of programming deliberately. Don’t Program by Coincidence

How to Program Deliberately

Algorithm Speed

Pragmatic Programmers estimate the resources that algorithms use—time, processor, memory, and so on.

Use: Big O Notation

	bool IsFirstElementNull(IList<string> elements)
	{
    	return elements[0] == null;
	}

	Int BinarySearch(list, target)
	{
	   lo = 1, hi = size(list)
	   while (lo <= hi){
	      mid = lo + (hi-lo)/2
	      if (list[mid] == target) return mid
	      else if (list[mid] < target) lo = mid+1
	      else hi = mid-1
	   }
	}


	bool ContainsValue(IList<string> elements, string value)
	{
	    foreach (var element in elements)
	    {
	        if (element == value) return true;
	    }

	    return false;
	}


	bool ContainsDuplicates(IList<string> elements)
	{
	    for (var outer = 0; outer < elements.Count; outer++)
	    {
	        for (var inner = 0; inner < elements.Count; inner++)
	        {
	            // Don't compare with self
	            if (outer == inner) continue;

	            if (elements[outer] == elements[inner]) return true;
	        }
	    }

	    return false;
	}


	int Fibonacci(int number)
	{
	    if (number <= 1) return number;

	    return Fibonacci(number - 2) + Fibonacci(number - 1);
	}

Common Sense Estimation

Estimate the Order of Your Algorithms

Test Your Estimates

Best Isn’t Always Best

Be pragmatic about choosing appropriate algorithms—the fastest one is not always the best for the job.

Be wary of premature optimization. Make sure an algorithm really is a bottleneck before investing time improving it.

Refactoring

Code needs to evolve; it’s not a static thing.

When Should You Refactor?

Refactor Early, Refactor Often

How Do You Refactor?

Code That’s Easy to Test

Build testability into the software from the very beginning, and test each piece thoroughly before trying to wire them together.

Unit Testing

Testing done on each module, in isolation, to verify its behavior. A software unit test is code that exercises a module.

Testing Against Contract

This will tell us two things:

  1. Whether the code meet the contract
  2. Whether the contract means what we think it means.

Design to Test

There’s no better way to fix errors than by avoiding them in the first place. Build the tests before you implement the code.

Writing Unit Tests

By making the test code readily accessible, you are providing developers who may use your code with two invaluable resources:

  1. Examples of how to use all the functionality of your module
  2. A means to build regression tests to validate any future changes to the code

You must run them, and run them often.

Using Test Harnesses

Test harnesses should include the following capabilities:

Build a Test Window

A Culture of Testing

Test Your Software, or Your Users Will

Evil Wizards

If you do use a wizard, and you don’t understand all the code that it produces, you won’t be in control of your own application.

Don’t Use Wizard Code You Don’t Understand

Based on The Pragmatic Programmer Book by Andy Hunt and Dave Thomas