Thursday, March 17, 2011

Theory of Constraints: Agile Programming

I am on an agile project surrounded by a team of smart developers. Recently, we started mentioning “refactoring” in our stand-ups. The business who participated in our stand-up interpreted “refactoring” as not producing new code for new features. As a result, the business cringes every time we mention the word.

After we learned that the business had concern with our refactoring effort, we tried to come up with some good explanations to convince them that it is a good idea to continuously improve our code. The following is a list of reasons we initially came up with:
  • Reduce code duplication
  • Improve code maintainability
  • Improve code testability
  • Improve code re-usability
  • Improve code quality
The above is a list of agile programming best practices. They make sense to agile developers. To the business, the agile programming best practices are just busy work that prevent them from getting their new features sooner. The business understands the importance of having a good quality software. However, they think it is a long term investment that don’t yield ROI in the near future.

I need a way to layout my thoughts so that I can identify the conflict and common goal. This is where Evaporating Cloud comes in handy. It is one of the six Thinking Processes in Eliyahu Goldratt’s Theory of Constraints. After several tries, I managed to construct the following evaporating cloud:


I will start with the common goal. In order to deliver features faster, I should write new code. I agree. On the other hand, in order to deliver features faster, I should write less code. That makes more sense to me since I am a developer. Code re-usability is a big part of what I do everyday. Next, to the conflict (indicated by lightning bolt). In order to write new code, I should not refactor code. However, in order to write less code, I should refactor code. The conflict is obvious. I cannot refactor code and not refactor code at the same time.

After giving the conflict some thought, it becomes clear to me that it is possible to come up with a compromise. I don’t have to stop refactoring code in order to write new code. In fact, I can do better. If I refactor the existing code, I can write less new code for the new feature. Consequently, I can deliver the new feature faster. What I should have told the business at the stand-up is: Refactor code in feature X to help with new feature Y development. During the next stand-up, I started using the above statement to report my status and the business seemed receptive. The business really sees their ROI when our team starts delivering features faster.

The end result is that the business does not care if we refactor our code or not as long as it helps to deliver new features faster. In return, we promise not to refactor code that does not provide business value. For example, we will not refactor code based on the assumption that it will be re-used in the future. Premature refactoring not only violates YAGNI agile programming principle but also fails to deliver business value. Evaporating cloud is helpful to find a resolution to conflict faced by two parties. It produces win-win solution.

Saturday, October 30, 2010

Functional Programming: Currying vs Partial Application

As functional programming becomes popular, many developers, including me, are curious to find out what is the fuss about Scala and Clojure. After playing with functional programming for a while, I came across concepts called currying and partial application. Unfortunately, these two concepts are not properly explained in either books or on-line resources 2-4. The concepts are very simple once we understand them. Let's start with the formal definition of Curry 1:

Given a function f of type f:(A x B) -> C , then currying it makes a function curry(f): A -> (B -> C) . That is, curry(f) takes an argument of type A and returns a function of type B -> C .


I will be using Scheme to demonstrate this concept. A simple non-curry subtract function will look like this:

(define (subtract a b)
(- a b))

(subtract 10 2)
;Value: 8

Going back to the first part of the definition, i.e. f:(A x B) -> C, the subtract function takes two arguments and produces value 8.

After we curry the subtract function, we have the following:

(define (subtract a)
(lambda (b)
(- a b)))

((subtract 10) 2) ;; extra parenthesis is used to invoke the returned function
;Value: 8

From the second part of the definition, i.e. curry(f): A -> (B -> C), the subtract function takes one argument, a, and returns a function, lambda, which takes another argument, b. The lambda function will be evaluated and returns 8.

Partial Application is just an application of curry function. Instead of returning a function with only one argument, a function with multiple arguments is returned. Consider a simple calculator below:

(define (make-calculator a)
(lambda (operation b)
(cond ((eq? operation 'add) (+ a b))
((eq? operation 'subtract) (- a b))
(else (error "Unknown operation"
operation)))))

(define cal (make-calculator 10)) ;; returns a function with two arguments

(cal 'add 5)
;Value: 15

After sifting through the on-line resources 1-4, I found wikipedia has the best explanation of curry and partial application. In practice, people use the terms curry and partial application interchangeably because partial application is just an application of curry. But, it is important to know the distinction.

Resources:
  1. Wikipedia
  2. What is currying
  3. Currying vs. Partial Application
  4. Partial Application != Currying

Monday, January 18, 2010

Amazon's biased coin toss problem

I was at CodeMash conference last week. Amazon.com was one of the vendors at the conference. They were recruiting people at the conference. They posted all kinds of brain teaser problems for the attendees to solve. One of the problems drew my attention and I have been obsessed with it for a few days. Here is the problem:

You are given a randomFlip() that returns true 50% of the time. Implements a biasedFlip() that returns true 31.416% of the time using randomFlip().

I have taken probability courses in high school and college. All the probability problems I came across involved calculating probabilities for certain number of coins or dices. The above problem is new to me. I applied all my probability knowledge but got nowhere. So, I turned to google and found this solution. The solution is a bit confusing because it is used to break a three or more way tie, or create a probability distribution other than 50-50. We need to create a probability distribution other than 50-50 for our problem. I was stuck again because I don't understand some of the steps. Again, I turned to Internet. This time, I turned to Dr. Math for help. It is a great site to search for Math solution or ask a question. After getting some clarifications from Dr. Math, I managed to construct the following steps for our problem:

Step 1: The probability for each outcome is 31.416%.

Step 2: The intervals are [0, 0.31416) and [0.31416, 1).

Step 3: Convert 0.31416 to binary decimal.

0.31416 * 2 = 0.62832
0.62832 * 2 = 1.25664
0.25664 * 2 = 0.51328
0.51328 * 2 = 1.02656
0.02656 * 2 = 0.05312
0.05312 * 2 = 0.10624
0.10624 * 2 = 0.21248
0.21248 * 2 = 0.42496
0.42496 * 2 = 0.84992
0.84992 * 2 = 1.69984
0.69984 * 2 = 1.39968
0.39968 * 2 = 0.79936
0.79936 * 2 = 1.59872
0.59872 * 2 = 1.19744
0.19744 * 2 = 0.39488
0.39488 * 2 = 0.78976
0.78976 * 2 = 1.57952

From the above, the binary decimal for 0.31416 is 0.01010000011011001.

Step 4: true = 1; false = 0

Step 5: Call randomFlip() and record each result.

Step 6: Convert the sequence of true and false to a binary decimal according to step 4.

Step 7: Will be illustrated by below code.

The following code illustrates how to create a biased flip program:

public boolean biasedFlip() {
String binaryProbabilityInString = "01010000011011001"; // binary decimal for 0.31416

for (int i=0; i<binaryProbabilityInString.length(); i++) {
boolean isTrue = randomFlip();
if (isTrue && binaryProbabilityInString.charAt(i) == '1') {
continue;
} else if (!isTrue && binaryProbabilityInString.charAt(i) == '0') {
continue;
} else if (!isTrue && binaryProbabilityInString.charAt(i) == '1') {
return true; // when the probability of the toss is < 0.31416
} else if (isTrue && binaryProbabilityInString.charAt(i) == '0') {
return false; // when the probability of the toss is > 0.0.31416
}
}
return true;
}


randomFlip() is trivial and we will skip that. It returns true 50% of the time. Let's assume that true = 1 and false = 0. In biasedFlip(), we loop through each bit of 0.31416. If the randomFlip() returns true (1) and the bit is “1” or randomFlip() returns false (0) and the bit is “0”, we call randomFlip() again. If randomFlip() returns false (0) and the bit is 1, it means the probability of next and future coin flip will be less than 0.31416. For example, if the first two flips return 00 (represents 0.00 in binary decimal form), the decimal value will be less than 0.01 (first two bits of 0.31416). We are sure that the probability of next and future flip will be in [0, 0.31416) interval. So, there is no need for us to flip the coin any further and we are done. On the other hand, if randomFlip() returns true (1) and the bit is 0, it means the probability of next and future coin flip will be greater than 0.31416. For example, if the first flip returns 1 (represents 0.1 in binary decimal form), 0.1 will be greater than 0.01 (first two bits of 0.31416). We are sure that the probability of next and future flip will be in [0.31416, 1) interval. As a result, there is no need for us to flip the coin any further and we are done.

The probability problem is interesting and challenging. I learned a lot by working through the problem. It is a popular interview question asked by companies like Amazon and Facebook but there are not many solutions on the Web. In my opinion, this is a lousy interview question. People who do not work with probability a lot won't come across this kind of problem. However, it is a good programming exercise and I enjoyed it.

Update: I sent an email to the author of "How to Simulate a Biased Coin Toss With a Fair Coin" to get some clarifications on the steps and he updated the article with some examples.

Sunday, November 1, 2009

Too much OO as a result of TDD?

I was directed to this interesting article about Object-oriented (OO) creates complexity. The author is building a snakes and ladders game with someone who is new to Test-Driven Development (TDD). The author and his developer came up with 6 objects i.e. Game, Board, Player, Dice, Snake, Ladder. Another developer happened to pass by them and thought they were wasting time on creating those objects. After 15 minutes of discussion, they came up with the following approach (quoted directly from the article):
  • one class called Game (place holder, the class is not really required) with one method called move(int number_on_the_dice)
  • a list to hold the current position of each player on the board (there can be more than 2 players)
  • a hashmap with starting and ending points on the board (represents both the snakes and ladders, how does it matter whether its a snake or a ladder, they are just starting and ending points on the board)
  • a counter to calculate player’s turn
  • and … and what? …that’s it
I could not help wondering what went wrong. Then it strikes me that I may end up with the similar approach if I chose to use TDD. For example, I will use ladder and snake objects to keep track of the starting and ending point for ladder and snake, respectively. There will be more than one snake and ladder on a board. So, I will end up shoveling them into a container, too. What is interesting about the snake and ladder objects is they both have the same attributes i.e. starting and ending point. If I am using the TDD approach, this will be revealed to me right away and I need to question my approach.

TDD is not only about testing and design. TDD suppose to help us to uncover the unexpected so that we can make the necessary trade-off in our design. We should not just focus on creating objects or tests during TDD. We should pay attention to the signs in our code, which we call code smell. For example, if our ladder and snake objects have the same attributes (starting and ending point), we should pause and think a little bit. It seems like we have code duplication in different objects. It is no different than having similar code in two different methods. We should strive to eliminate code duplication. But, before we do that, we need to ask ourselves a few questions:
  1. Will the additional object help to communicate the domain concept better to the next developer?
  2. Will the additional object help to communicate the domain concept better to the business user?
  3. Is the domain concept complex enough to warrant a separate domain object?
  4. Is there a hidden domain concept that can represent both snake and ladder domain concepts?
After we understand the trade-offs, then we refactor our code. So, it is not TDD that introduces object complexity. It is us who often miss the forest for the trees.

Thursday, October 15, 2009

Test-Driven Design

Venkat wrote a nice article on when to use mock. He made a point that by gaining deeper realization on domain problem, we can make our design simpler. As a result, we will not need a mock object. I feel that the role of Test-Driven Development (TDD) as a design tool deserves more attention. This is the most misunderstood part of TDD. Many people think that TDD is about writing test. But, it s more than just testing. We are also designing our application at the same time. I prefer the term Test-Driven Design over Test-Driven Development.

Test After

We will look at a simple example to illustrate the difference between test first and test after approaches. Let's say we we are building a billing system for a clinic. One of the functionalities is to collect payment from a patient for the services tendered. We will use Test After approach. As an exercise, I created a Patient.java and a getPayment() method. It came to me naturally that in order to calculate amount owed by a patient, I would need a list of services that are provided to the patient. So, I added a parameter to my getPayment method. The implementation looks like the following:
public class Patient {

// ...

public double getPayment(List servicesTendered) {

double payment;
if (servicesTendered.size() > 0) {
payment = calculateAmountOwed(servicesTendered);
makePayment(payment);
} else {
payment = 0d;
}

return payment;
}

// ...
}

The test I produced based on the above implementation is as follow:
public void testGetPayment() {
Patient patient = new Patient();

assertEquals(patient.getPayment(new ArrayList()), 0d);
}

We can easily implement similar test to test for non-zero service list. The above test is good enough for our discussion. So far, everything looks good. I am happy with this implementation.

Test-Driven Design (Test First)

In Test After, I implement getPayment method by thinking of what do I need in order to implement the method. In test first, I have to change my mind set. I need to think of how to create some test code to test the getPayment method. In other words, I need to think of how to use my code in the test. Below is the test code I produced by using test first approach:

public void testGetPayment() {
Patient patient = new Patient();

patient.addService(new Service(LAB_WORK));

assertEquals(patient.getPayment(), 15d);

}

The above test method is different from the previous one. The difference is I don't pass in a list anymore. When I write test first, I am thinking from a patient perspective. When a service is tendered, it should be added to the patient. It is just like an on-line shopping cart. A customer can add any items in store to his/her basket. Similarly, a patient should be able to add services tendered to him/her. Below is the new getPayment implementation.
public double getPayment() {

double payment;
if (servicesTendered.size() > 0) {
payment = calculateAmountOwed();
makePayment(payment);
} else {
payment = 0d;
}

return payment;
}

The calculateAmountOwed method does not need a list of services anymore. The service list is available in the Patient class.

Since we design and write test at the same time, no time is wasted. The test we wrote serves two purposes:
  1. Artifact. The test tells other developers how to use our code.
  2. Safety net. The test allows other developers to modify our code confidently.
Another benefit of writing test first is we can change our code easily since no actual code is written yet. If we do test after, we tend to avoid making changes to our implementation even if our design is wrong. We will try to tweak our test to comply with our implementation. As a result, our test may still pass even though our implementation does not work correctly.

Further readings:

Neal Ford wrote a nice two parts article on Test-Driven Design with more advance examples:
  1. Test-driven design, Part 1
  2. Test-driven design, Part 2

Sunday, October 11, 2009

Code better than yesterday

Code maintenance is a big part of a developer's job. After we write our first method and then go back to fix it, it is a maintenance job 1. This is true for developing a new application from scratch or making enhancement to an existing application. But, developers often don't see it that way. When we inherit a poor written application, we lose a lot of freedom and creativity in creating our own solution.

I happen to inherit a poorly written application from time to time. When I inherit such application, I am not very motivated to work on the application. Everyday is a torture for me to just look at the legacy code. The code is poorly written, application architecture is accidental, no test cases or some of the test cases don't have assert statements. I complete the tasks I am asked to do by putting down the solution that first comes to my mind without refining it so that I can finish the project as soon as possible and move on to the next project. But, what if the next project is worse than the project I had before? So, the evil cycle continues.

I didn't resolve to hacking my solution overnight. At the beginning of the project, I was determined to make the project better by recommending some of the pragmatic approaches to be adopted in the project. I had a long discussion with the team and everyone thought those were good ideas. But, everyone had higher priority on their plates and none of the good ideas were realized. I tried to put in some tests, refactored some of the code that I was working on so that it is testable. But, no matter what I did, it didn't seem to have an impact to the overall application. So, I gave up and went down to the code hacking path. I fell into the trap of Broken Window Theory.

The truth is, I lost focus. I care too much about the end result. I should focus on completing today's tasks to the best I can by refactoring the legacy code into testable code and refactoring long method into smaller methods using composed method pattern. I should fix one broken window at a time and not attempting to fix all the broken windows overnight. If I have done something to make today's code better than yesterday, I have achieved something and I should be happy about it1. I may not see a big difference as a whole but incremental improvement is the first step to improving the whole application. If I stay on this path, the developers around me may see the benefit of the good practices I am adopting and start following.

1. The Passionate Programmer

Sunday, August 16, 2009

Prototype Programming

I have been playing with dynamic languages such as Ruby and Groovy. I like what I see so far. Also, I have been relearning JavaScript as a true dynamic language. I came across this concept called prototypical inheritance in JavaScript and it is fascinating. The idea of prototypical inheritance is to create a new object from an old object and then add "stuff" to it. Here is a simple JavaScript example:

// convenient method extracted from Douglas Crockford's
// website -
// http://javascript.crockford.com/prototypal.html
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}

var animal = {
name : "",
get_name: function () {
return this.name
}
};

var cat = Object.create(animal);
cat.name = "Mr. Black";
cat.says = "meow";

document.writeln(cat.name + " " + cat.says);

// Mr. Black meow


Instead of doing classical inheritance in static language such as Java, we simply add "says" method to the newly created cat object.

Interesting enough, there is way to achieve the same thing in Ruby:

animal = Object.new

def animal.name=(name)
@name=name
end

def animal.name
@name
end

cat = animal.clone
cat.name = "Mr. Black"

def cat.says
"meow"
end

puts cat.name + " " + cat.says # Mr. Black meow


Now, the "says" method is added to the cat object.

"class" does not exist in both JavaScript and Ruby. Everything is Object in JavaScript and Ruby.

It is possible to achieve the same thing in Java using AOP through Spring or AspectJ. But, we have to learn Spring or AspectJ first before integrating either of them into our application. Productive language like Ruby has this capability built in and developer can just use it without incurring huge upfront cost. I hope this is the first step to convincing some of my colleagues why using a productive language like Ruby or Groovy is important.

The usage of prototypical inheritance is unclear at the moment. But, reusing a chunk of code across objects is important. Usually, this is done through inheritance even though there is no "is-a" relationship. Deep inheritance can cause unnecessary complexity in our application. In Ruby, this problem can be solved using Module and Mixin.