Monday, January 31, 2005

IntelliJ eclipse keymap

I use IntelliJ at work and Eclipse at home. One thing that frustrates me a lot is the different keyboard shortcuts in both the IDEs to achieve the same functionality. I am now comfortable with IntelliJ's settings. Wouldn't it be nice if I get to import all the IntelliJ's keyboard shortcuts in Eclipse. Of course, I can do that manually by changing the mapping in eclipse, but I don't want to do that. Did a google on that, but didn't find any.

Thursday, January 27, 2005

Object BootCamp - day12

Today was a practical intensive session. We implemented the hopCountsTo method first. We also refactored the isConnectedTo method to avoid duplication. We then implemented minHopCountsTo method that returns the minimum hopcounts to a node. That was it for the day.

Wednesday, January 26, 2005

Object BootCamp - day11

Fred started talking about the final form of relation between objects - Collaboration. Collaboration is when two objects know each other and they interact and churn objects. Recursion is a form of churning objects. Basically, there are three parts to Recursion.
1. Original Question
2. Recursive Question and
3. Terminal Question

We did an exercise on Recursion. We chose to design and represent Graphs in objects. So we came up with a design for the same. We had a Node class whose job was to understand its neighbours. We then implemented canTraverseTo method that returns a boolean if we can traverse between two nodes. We used recursion to implement the same.

We then designed and implemented hopCountsTo method that returns the number of hops it takes to reach another node. I wrote the tests for the same and tried re-using the canTraverseTo method. The canTraverseTo method had an arraylist which held the visited nodes. So I refactored the class and ran the tests. I hit the green bar. I was happy and wrote more tests. Green bar again. Though I was a bit sceptical, my partner was very happy. We announced we had completed. When the entire class saw our code, they knew it wouldn't work. So we kept adding more tests and showing the green bar to them. Then we wrote a test that should fail. We hit the green bar again. Only then did we notice that we were running the wrong tests. That was embarassing.

Monday, January 24, 2005

Object BootCamp - day9 & 10

Day 9 was all about the history of Objects thinking. Essentially there are two schools of Object thinking - Rational and Tektronics. Rational suggests the UML way, whereas the Tektronics suggests the Agile way. Fred talked in depth about various people in both camps. It was interesting.

Day 10's topic was Collections. Most people are familiar with this, so am not going to go into the details. But I am listing some interesting observations:

1. There is a ListIterator which has methods to traverse in the reverse direction.
2. LinkedList has addFirst, removeFirst methods which are unique to itself.

Will add more when i get time.

Thursday, January 20, 2005

Object BootCamp - day8

A short discussion, essentially a continuation of yesterday's discussion, on Inheritance marked the beginning of day 8 of the BootCamp. When do we mark methods final? Rarely. But there is an advantage of declaring methods as final - it encourages the "buy" relationship as opposed to inheritance.

We then talked about Cloning in Java. There are two types of cloning - shallow and deep. Why is Cloning necessary? So that you don't give away your data. It is not necessary for immutables. How deep do you need to clone? Till you hit an immutable.

Fred then explained why Cloning is broken in Java. He gave five reasons why cloning is broken in Java:
1. It is Shallow by default.
2. It returns Object, not its own type.
3. The clone method is protected, so when an object buys another, and wants to invoke its clone method, it is not possible to.
4. When we try to call a clone method, the class should have implemented the marker interface Cloneable.
5. The clone method throws a CloneNotSupportedException, a checked exception.

Some alternatives to clone method are:
1. Serialization and deserialization gives a full hierarchy of objects.
2. Copy constructors.
3. We could use reflection and write our own cloning mechanism or
4. Write our own copy method.

But all the above methods also have different drawbacks that makes clone method the best available option.

Fred then started talking about Polymorphism. He chose a very interesting method to explain Polymorphism. He chose four of us and took us outside. He then gave a criteria - height. He then took us inside the class again. He asked the rest of the people to sort us, and that we knew the criteria. So others sorted us by choosing two of us and asking us to decide who was better. After gettingsorted by height, we were given a second criteria and a third. In all these cases, they group sorted the same way without ever knowing about the criteria. This is polymorphism.

We then implemented Polymorphism in our Probability and Rectangle examples. We had an interface Comparable/Orderable which had one method isBetterThan. And then we wrote a max method to find a max from a set of Comparable/Orderable objects.

That was it for the day.

Wednesday, January 19, 2005

Object BootCamp - day7

As usual, we started the day with a discussion about the previous session. I said that the conversion of units was now taking place in both Quantity and Unit classs. The code was getting ugly. Itneeded to be in one place and that should be the Unit Class. Fred readily agreed to that view. Also, if we need to have a method for finding average of Temperatures, where would we put that? There were ways of achieving it. One was subclassing a Collections class writing our own Collection and the other alternative was to have a static method in Quantity class that finds the average of a collection of Quantitites. Fred's opinion was that the second alternative was better because subclassing a Collection class was a bad idea. More on that a bit later. There was a discussion on naming standards, and how important it was in an agile team. Naming a collection of plants as Forest is a bad idea, instead naming it Plants yells out the intention better.

Fred then started talking about Inheritance. Inheritance is bad, but still important(around 10% on the PIE chart). So when do we go for inheritance? Answer is, there is a two question test:

1. Almost all of the code is reused.
2. The two objects exhibit "kind of" relationship. Also called the Grandmother test. Which means that it should be simple enough to say that they are of same kind. It should not require a programmer to say that such a relation exists.

Two level inheritances are absolutely bad. It means something is wrong with the design. Inheritances are normally not designed for. They are normally discovered.

Fred then asked us to design a Square class. I went ahead and implemented a square, which inherited from Rectangle class. I also overrided the equals method in Rectangle class so that a Square ofside 10 equals a Rectangle with length and breadth equalling 10. All the tests ran and I was happy. Fred saw the Square class and said that it does nothing, so there is no need for such a class. We were as usual surprised at that remark, but it made a lot of sense.

That was the day 7 session.

Tuesday, January 18, 2005

Object BootCamp - day6

Today was a non-productive day. We started talking about the design for Temperature comparisons and then went ahead to implement it. We spent more than an hour to get the green bar for implementing the equals method. Most of us introduced a new class for Temperature which extends Unit class. We made the add method throw an UnsupportedException. Since the add operation should not be permitted on the Temperature class(because we cannot "add" two temperatures), we were not quite sure if that was a good idea. The alternative would be to have an addable quantity and then a factory to create Quantities. That way there would be no add method when we instantiate temperatures. We took the first route, though i didnt quite like that.

We then were stuck in deducing the relation between Celsius, Fahrenheit and Kelvin scales as a linear equation. I couldn't quite get it right and we spent an hour trying to figure out what was going wrong. Lessons learnt from today's session:

1. It should not take more than 15 minutes to get the green bar. Else, we probably are biting too much.
2. Had we taken smaller steps in representing the Temperature class, we probably would have made it.
3. We didn't spend time in designing at all. We had to pay for it by spending too much time on broken unit tests.
4. There are 4 features of OOP, encapsulation, inheritance, polymorphism and Identity.

Fred also suggested having a constant called Temperature in Unit class instead of a sub-class. He suggested using identity in place of inheritance. The identity is a very powerful concept. It is something which cannot be represented in RDBMS. We need to find either a string or a number to represent the identity.
That was what happened during a day of highly practical session.

Monday, January 17, 2005

Object BootCamp - day5

It was another day of lots of practical work and less of theory. We started the class with each one of us taking turns and giving a brief description of the various concepts that we had covered so far. We then continued with the Quantity/Unit exercise. We were asked to represent addition of two Quantities in terms of objects. For example, it should be possible to say 2 Quarts and 1 Quart equals 12 Cups.

So we started by writing the assert statement:
assertEquals(new Quantity(12, Unit.CUP), new Quantity(1, Unit.QUART).add(new Quantity(2, Unit.Quart));

We then easily implemented the add method in Quantity by putting the following code:

public Quantity add( Quantity other ) {
return new Quantity(this.value+ other.unit.convertTo(other.this)*other.value, this.unit);
}


Fred suggested to move the complex statement out there to a method in itself. So we ended up like this:
return new Quantity(this.value+convertedValue(other), this.unit);

When we did this, we found yet another usage of the above statement in equals method and changed that too. We found the code to be clean at the end of this. Fred noted that it is important to listen to code, as Kent calls it. The complex statement was yelling at us to refactor it. Had we listened to the code, we would have ended up with a neat code.

The class ended with an interesting problem waiting to be solved tomorrow. How do we represent Temperature conversions through the same sets of classes? How do we represent additions of two temperatures? 0 deg Celcius + 0 deg Celcius = 0 deg Celcius? Whereas, 32 deg F + 32 deg F = 64 deg F? We spent some time analyzing the problem, but could not come to a design. Try out for yourselves if you can come up with a design. Good Luck. Will probably provide solution in tomorrow's notes.

Thursday, January 13, 2005

Object BootCamp - day4

Yesterday i had written about how to refactor the "or" method in Probability class to use existing methods. The day started with a question on that. What if we had started with the "or" method? Fred suggested that either we could have written down the "and" and "not" methods as private, or could have very well settled for the first version. At a later time, when the "not" and "and" methods are written, we could refactor the "or" method to reuse the other methods.

Fred then observed that there was a difference between object thinking and traditional thinking. Object thinking tries to find groups of behaviours to find objects, traditional thinking tries to group data together. He also gave an interesting anology of churning of objects. He said we should churn objects and they in turn communicate and churn out objects.

What followed next was a discussion on equals method. Fred gave us a template for writing equals method. The first step should be to check if both instances are same. The second step should be a check for null. Then the type of the objects should be compared. Note that we should use the getClass to compare the type instead of the instanceof operator. Reason is that instanceof operator returns true even for subclasses, which is not desirable for equals method. Finally the actual comparison for equality of two instances of the same type should be done, probably in a private/protected method.

In summary, the steps to write an effective equals method are:
1. if( this == other ) return true;
2. if( other == null ) return false;
3. if( this.getClass() != other.getClass() ) return false; // can use instanceof when class is final.
4. return equals( (Probability) other ); // a private/protected method to do the actual check.

We then had a discussion about the various relations that two objects can have. Essentially, there are four types of relations: a "buy" relation( composition relation ), aggregation, inheritance and collaboration. A buy relation seems to be the favorite with Fred and he would like to see a cascading chain of such relation. There should be no cycles of relations and backward pointer. Both of these are code smells.

Fred then gave us a more real world problem to design. He wanted us to represent relations like 1 quart = 4 cups.
Take a moment and think about a solution, its really interesting.

I came up with a design as below:

// understands the quantity of anything in terms of a standard unit of measurement
class Measure {
private final double quantity;
private final UOM unitOfMeasure;
}

I was not quite sure about how UOM class should look like and what its job would be. At the end of the session, the below representation seemed to be the best that we were able to come up with. I still believe the factor could also be represented in terms of objects. Let me think...


// understands a standard measurement unit
class UOM{
public static final UOM QUART = new UOM("Quart", 1);
public static final UOM CUPS = new UOM("Cups", 2);

private final String name;
private final double factor;
private UOM(String name, double factor) {
...
}
}

Wednesday, January 12, 2005

XP Game

Today couple of my colleagues conducted XP Game for those of us who had joined ThoughtWorks recently. It was fun. Visit this link for more on the game. We were divided into small teams of 5-6 people and played the role of developers and customers in turns. We estimated the tasks as developers and prioritized the same as customers. We played a couple of iterations and believe me, it was fun. Some observations from this exercise:
1. We were aggressive in our estimates in the first iteration.
2. The second iteration was drastically different and better in estimates as well as implementation due to the lessons learnt in the first iteration.
3. Tasks in the later iterations which were similar to the earlier ones were done almost exactly on time.

Overall, it was fun way of learning XP concepts like velocity, estimation etc.

Object BootCamp - day3

We started the day with a question to Fred asking him why he chose Probability to design. In the sense that why not something more equivalent to real world. Fred replied that Probability is a very good example, because when anyone is asked to represent Probability in a code, most people eventually end up with a float or a double to represent it. Also, in yesterday's class most of us had spent a great deal of time in checking for nulls and boundary conditions. Fred suggested that this is a waste of time and that we should listen to users. Only when the user requests for boundary conditions should we actually put that in code.
Also, Fred suggested that there need be no null checks in code. If someone passed in null, he/she deserves a NullPointerException.

Bottomline was, as engineers we tend to overengineer rather simple situations. Do not write extra code than necessary.

Then we had a very interesting discussion about designing for change. Designing for change does not mean we need to design for reusability. Why bother about tomorrow? If a code can be changed today, and if it takes the same time later, we better postpone it. That itself is a gain. For a code to be easy to change, XP advocates four principles:
1. It Works
2. It Communicates
3. There is no duplication in it and
4. Fewest possible classes are present.

We had switched partners in the middle of the session yesterday as well as today. An observation from that was it is important that all members within the same team use almost the same set of tools and IDEs. It is better to have environments that are identical.

We continued with the Probability class and implemented "and" and "or" methods. Most of us implemented the or method as

Probability or(Probability other) {
return this.value + other.value - and(other).value;
}


Fred suggested using the DeMorgan's theorem. So we ended up with a code like this:

// DeMorgans theorem states A || B = not( not(A) and not(B) )
Probability or(Probability other) {
return this.not().and(other.not()).not();
}


The above code, though a bit confusing has another big advantage. It re-uses the existing code, therefore better tested.

Tuesday, January 11, 2005

Object BootCamp - day2

The day started with Fred asking us what was the wierdest thing that we heard yesterday. I said i was surprised to find that the names of the methods should not have get/set(forget about having getters/setters, the name should not even have the string get/set as in getArea in Rectangle class). He said that well designed do not have getters/setters. For example, the JDK APIs hardly have getters/setters. Objects should not be modified through setters after they are constructed. For changeability of an app, objects should do what they are supposed to do.

He said having multiple levels of calls like a.b().c().d() was a code smell. This is a tight coupling. Instead the behavior c()/d() should be moved to a. I asked that this might increase the size of the classes, so how to keep it small. Fred suggested refactoring to find embedded objects as a key to keeping small classes.

Fred then asked us to design a class for Probability. The goal was to represent Probability in objects. We had a fairly long discussion as to what would the class Probability would look like. We ended up designing a class called Probability which would be treated as its mathematical equivalent. It would have behaviours like and, not, etc.

We followed TDD and wrote tests for equality. Fred suggests writing the assert statement first in a test method. When we are not able to come up with an assert statement, it means that we have to design. Fred suggested designing and "conversation"(as covered in yesterday's post) to overcome this. This way we can arrive at better design. We started with an assertion as below:
assertEquals(0.5, new Probability(1,2).chance());

Fred did not like it. He said what is 0.5? Its a number. What are the operations possible on it. Addition, subtraction, multiplication etc? Why should a probability have those opertations? Probability is not a number. So we modified it to
assertEquals(new Probability(0.5), new Probability(1,2));

Other things that were covered in today's session was how to override equals method effectively. equals method cannot throw exceptions, so all condional checks should be made explicitly. Also, instead of using the instanceof operator to check the class, Fred suggested using getClass method as that will allow sub-classing without breaking equals. Also, when equals method is overridden, hashcode method should also be overridden.

Object Bootcamp - day1

Fred started the session by asking the class to draw a pie chart based on the importance of the concepts of Polymorphism, Inheritance and Encapsulation to OOP. I came up with a figure of 45%Encapsulation, 30% Polymorphism and 25% Inheritance. Most of us were around the same percentages. Fred's opinion was 60% Encapsulation, 30% Polymorphism and 10% Inheritance. He also noted that in the early days, when OOP was introduced, high importance was placed on Inheritance.

He then gave a brief history of how OOP evolved. Initially, finding the right data structure was considered the most important thing to do. It was assumed that once the data structure is correctly identified, then writing a set of behaviors around it is essentially what OOP was all about.

Later Data hiding evolved to be the most important thing. Since changing a datastructure affected several behaviors in the above said method, this turned out to be the challenge. So it was important to hide the data and provide behaviors around it, this is also known as Encapsulation.

We then started to design a Rectangle Class. Fred says it is important to conceptualize for a good OO design. "Jobs" of a class needs to identified first. Every class must have one and only one job, and this should be understood to identify an object. Example of a good job for class Rectangle is: undertands a geometrical object with 4 sides with right angles at all the ends. Examples of bad jobs are ones that have circular reference, jobs that describes the data and jobs that go into implementation details.

When we design objects, we should think of them as having a conversation. Suppose a user of Rectangle class asks the rectangle for the length, the question that we should ask is why? what are you going to do with that. Probably calculate area. In that case, that behavior has to be present in the Rectangle class itself. This is the conversation.

According to Fred, any class whose name ends with "er" or "or" is a bad object and hence bad encapsulation. Also, Manager classes are like real world Manager, they take credit for what they dont do. ;)

Fred likes to see all classes begin with a comment that starts with "understands". Example:
// understands four sided geometrical figure with right angles at all the corners
class Rectangle {
...
}


For tests, usuall "ensures" seems to fit it.

// ensures that Rectangle works fine
class RectangleTest extends TestCase{
...
}


In OOP, the cycle that someone should usually follow is as below:

Task followed by Design, followed by cycles of Test and Code and then finally integrate before proceeding to another task. This cylce should be done as quickly as possible. Fred says this cycle should be over as early as 15 minutes. At the end of 15 minutes, he likes to see the Green bar. The design aspect of this cycle is falsely ignored as not agile/xp but actually is very much part of this cycle. Yes, there is no upfront design as in a traditional waterfall model, but still is an important step where objects are identified, although for a very negligible time period.

Object Bootcamp series...

I started attending Object BootCamp by Fred George, a very senior consultant/coach here at ThoughtWorks. He is currently in India and is running these sessions. Through these sessions, he mentors/teaches Object programming and thinking. The sessions are generally lab intensive, so I will try my best to write as much theory on these as possible.

Tuesday, January 04, 2005

Is TDD an engineering way?

Recently I had a discussion with a couple of my colleagues here at TW about TDD. One of them was of the view that TDD is not an engineering way of coding, because it takes away the element of thinking from you when you do TDD and that the designs unfold before you. That itself partly being a credit to TDD, I tend to disagree that TDD is not an engineering way. In engineering, lots of importance is given to specification, and TDD is a way of writing the specs before writing the code, a perfect engineering way. You write tests before you write the code that is tested. Tim Bray seems to be of the same opinion here.

And as far as the element of thinking goes, I disagree again. Though TDD is simple, it takes a lot of thinking to recognize the emerging patterns and code smells. It is not easy to notice the designs unfold before you, especially for a beginner. Also, code smells if it takes you time to write a simple test. It is high time you start refactoring before going ahead. You need to realize all these and much more as you do TDD. It is simple, not easy.