Monday, September 30, 2013

Girl Develop It: Code & Coffee

Girl Develop It (GDI) must be really popular, because when I signed up there were at least 10 people on the wait list. I'm still not sure how I managed to pass those and snatched a spot to go to the meetup.

The event was hosted by Table XI, which was right around the corner from 8th Light. The event organizer, Jen Mozen, must have been a psychic because she knew I would get lost, thus she posted signs in front of the building and the elevator to direct us to the place. Although Meetup said 39 people will attend, I think ~15 showed up, which was really nice. It felt a little more intimate. We were able to introduce ourselves and talk about our background. I found a lot of people there are new, which is great. I wish my sisters were here so they can attend. It's a great learning environment.

Jen was nice enough to be extra prepare and things people could work on.
Although IFFF sounds really interesting, I opted for working on my own application. It's a code review app which allow users to submit their code and for others to review. Chris was nice enough to work with me on it. He showed me a really cool gem called table print which he develops. It prints out your SQL stuffs in a table format.

So instead of it looking like this:

The gem makes it looks like this:

The time Chris spent with me was really useful. I got the basic of take request down. It also reminded me how useful pairing it. It helped me focus on the problem at hand. And when I try to explain the application to Chris and what I wanted to do, I realize I was having a lot of problem because of the way I name things. So I went back home and rename my request to review request and review to review reply. It makes it easier for me to refer to things. Ideally I probably want to do one or two hours of pairing in the morning because that's when my mind easily distracted.

Overall, it was a really nice meetup. I would definitely go again :)

Wednesday, September 11, 2013

SOLID: Liskov's Substitution Principle

In 1988, Barbara Liskov wrote:
If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.

Uncle Bob's interpretation:
Subtypes must be substitutable for their base types.

Head First Object-Oriented Analysis and Design's interpretation:
"When you inherit from a base class, you must be able to substitute your subclass for that base class without things going terribly wrong. Otherwise, you've used inheritance incorrectly!" 

If none of those interpretation makes sense, read on.

I will try to explain this using Java. But before I explain what the principle means, let's define what subtype is. A is a subtype of B if it implements or extends B. For example, ArrayList is a subtype of List because ArrayList implements List. List is a subtype Collection because it List extends Collection. Because this relationship is transitive, ArrayList is also a subtype of Collection.



Now we know what I mean when I say subtype, let's try to understand the principle.  Let's say we have the following code is Java:
What the principle is saying is that I can rewrite the code to this:
Or this:
Even though I changed Collection to List and Set, the behavior is unchanged because List and Set are subtypes of Collection, so you can substitute the subtype with its base class. What this translate to is that I can pass a List or a Set into removeAll because the method takes a Collection.

Be careful because this is a one way street. List can be substituted Collection but Collection may not be substitutable for List because List is a child of collection.

Photo by Derick Bailey

There are two ways you can violate the Liskov Substitution Principle:

  1. When the subtype Class removes functionality from the base class.
  2. When methods that reference the base class knows about its subtype.
Both of these violations translates to wrong abstraction. For example, look at this code:
Looks good right? In most cases, it is good. However, when I run this test, it will fail. I get an UnsupportedOperationException.
Why did it fail? Because Arrays.asList() returns an AbstractList, which is an unmodifiable list. It doesn't support List.add() or List.remove(). This is a violation of the Liskov Substitution Principle because AbstractList removes functionality from List. I can't substitute AbstractList (the subtype) for List (the base class). We can fix this by making the List interface have all the unmodifable methods. Then have another interface for ModifableList.


(Note: For the sake of simplicity, I ignored that the List interface implements Collection. But you get the idea.)

This way, our method can be changed to:
This makes a lot more sense because you can only remove items in list that are modifiable.

The second way to violate this principle is having your method knowing details about the subclass.
The calculateArea violates the Liskov Substitution Principle because it knows about the subtype of Shape. This makes it hard for the method to close for modification. What happens when you add a circle, now you have to add another if statement to check if it's a circle. To fix this, we can move the calculateArea() to the Shape class. Then each Shape can implements its calculateArea() so we don't have to check to see what type it is.

This is another way you can violate the principle: This method knows the subtype of the base class. It casts the list to LinkedList, but not all lists are LinkedList. Therefore we cannot substitute the subtype ArrayList in this method even though List is ArrayList base class.

And that's Liskov Substitution Principle. If you are removing functionality, then you want to ask, does this subtype belong to this base class? Or if you find yourself downcasting like I did with the LinkedList, then you want to replace the base type with the subtype. Or if you find yourself checking for case type, then you should ask, does this method belongs in the subtype class? Doing any of these things is an indication that you may be violating the Liskov Substitution Principle.


 Resource:
  1. Software Development Principles Patterns Practices
  2. Head First Object-Oriented Analysis and Design
  3. Object Mentor - Liskov's Substitution Principle
  4. OODesign - Liskov's Substitution Principle

Tuesday, September 10, 2013

Sweeping the floor

When I told people I was leaving my old job for an apprenticeship at 8th Light, my family and friends were worried (and they have good reasons to be). How long will it be? Will they pay you? What are you doing to do if they don't? Where are you going to live? What are you going to eat? You don't even know how to cook! So many questions and no concrete answer.

Thus when Eric sent me the offer letter which states I will get pay during my apprenticeship, I was thrilled! I couldn't believe 8th Light would take this chance on me. Six months of pure learning. That's a lot of money and time spent on me, and they don't know if they want to hire me for real!

On the first day of my apprenticeship, Eric and I talked about the high level "curriculum" of the apprenticeship. One of my duties as an apprentice is to help keep the office clean. Eric spoke about this duty quickly and told me to read more about it in the Apprenticeship Pattern book.

In the book, Dave Hoover and Adewale Oshieye called these unsexy tasks "Sweeping the Floor". (Yes, they used the word unsexy.) They recommends apprentices, like me, volunteer for unglamorous job in the beginning to contribute to the team, build trust, and learn humility. I look at it a little differently. I am thankful to have this opportunity, even if they didn't pay me, I would still do all the unsexy task. To me, it's like buying the craftsmen time. If I take out the garbage, the craftsmen don't have to. Since I free up some of their time, I don't feel as shy about asking them questions. Or when I keep the office clean, it makes the craftsmen happier, so they are more likely to answer questions when I ask. That is not to say the craftsmen here are unapproachable. It is the opposite. They are always friendly and nice. I've never had a craftsman who gives the don't-bother-me-attitude when I approach them.

By doing these unsexy tasks, it makes me feel a little useful. I feel like I am part of a team. I am providing values. It also create a bond knowing that most, if not all, of the craftsmen have "swept the floor," even our CEO.

Although the apprentices are probably the most expensive "custodian" around, the craftsmen still thank us for the little things like keeping the fridge stocks with cold soda. I think it's going to be hard to find a better company than 8th Light. Thank you Paul and Micah for creating such an awesome company. (I was not paid...well not paid specifically to write this blog.)

Wednesday, September 4, 2013

Coding by intention, not accident

There is still something that doesn't sit well with me when I write kata. You're supposed to write the simplest code to make the test pass, but I feel sometimes this lead to coding by accident instead of intention.

For example, for the coin changer kata, when the user enters anything less than 0, I want to return an empty array indicating I have no change for the user.

So my test looks like this:
it "returns nothing when amount is less than the smallest coin value" do
  CoinChanger.get_change(0).should == []
end

For a simplest case, the code looks like this:
get_change(amount)
  []
end
If you read the code, do you think it expresses my intention well?

What happen when the amount is 1 cent? The program changes to this:

def get_change(amount)
  if (amount == 0)
    []
  else
    get_change(amount - 1) << 1
  end
end

But that's not what I mean. I really mean, if amount is 0, -1, or anything smaller than 0, I want it to return the empty array. So the code should really look like this:
def get_change(amount)
  if (amount <= 0)
    []
  else
    get_change(amount - 1) << 1
  end
end

When I write the simplest test case, sometimes, I forget the other condition. In this case, maybe I need to add another test case to test what happen when amount is less than 0. In general, I should be more careful and understand why my test is passing.

Note: This is not the best way to write coin changer. I just want to demonstrate what I was thinking.

Tips for Cob Spec

Things that I found useful in trying to pass Cob Spec
  1. Understand what HTTP Request and Response looks like
    1. The only requirement you need for response is the first line (HTTP/1.1 200 OK)
    2. There is a line break between the header and the body
  2. You can debug your server with Cob Spec
    1. Run your server in Debugger (Right click in your IDE, select Debug)
    2. Put on your breakpoint
    3. Run your cobspec test. It should stop where your breakpoint is.
    4. You can use this method to print out the request Cobspec is sending
  3. Reading client request
    1. I use BufferReader to read my request
      1. To check the end of a header, I check to see if the line is null or empty string ("")