My Adventures in Coding

July 3, 2010

Refactoring Principles

Filed under: Refactoring,UberConf 2010 — Brian @ 9:07 am

While at UberConf I had the great opportunity to attend a talk by Venkat Subramaniam titled “How to Approach Refactoring”. The following is a quick summary of his talk and what I took from it.

Refactoring Principles

  1. Reduce code
  2. Avoid clever code – keep it simple!
  3. Make it small and cohesive – single responsibility
  4. Eliminate duplication – DRY
  5. Eliminate dependencies – rather than striving to reduce dependencies, strive to remove them
  6. Write self documenting code – make comments unnecessary
  7. Code should be understandable in seconds – it is not just about reducing the amount of code, but also about clearly expressing meaning.
  8. Avoid primitive obsession – focus on creating higher level abstractions
  9. Checkin frequently, take small steps – every commit should be only one change.
    • Shorter feedback cycle
    • Other developers are kept in the loop
    • Avoid large painful merges
  10. Keep code at one level of abstraction – each method should do one thing, and delegate to other methods that each do one thing.

When not to Refactor

  • Never refactor while making any other code change. Take a note of the refactoring and complete it after the bug fix or functionality change has been committed. Never commit a refactoring at the same time as any other code change. If you do break a build, having small, single change commits, will make spotting the problem that much easier.

    1. When you spot a code smell – take a note of it
    2. Finish your change
    3. Commit
    4. Refactor
  • Never refactor alone. You should always have a second set of eyes on the problem. Pair programming is essential while refactoring. The second person will be their to help ensure we are making the code easier to understand, using good names, and helping to ensure we are not breaking any existing logic.

When to Refactor

  • You can refactor before or after a bug fix or a functionality change
  • If you think the change will improve the design of the code
  • If you think the change will improve the readability of the code for other developers

June 23, 2010

Coding is still writing

Filed under: Refactoring,UberConf 2010 — Brian @ 10:15 pm

While at UberConf I had the great opportunity to attend a talk by Venkat Subramaniam titled “How to Approach Refactoring”. Many times I have attended talks and read articles focusing on refactoring techniques, but rarely do these other sources discuss the behaviours that allow refactoring to work. Knowing all of the refactoring techniques without understanding the fundamentals that make refactoring beneficial, can result in making code worse!

There are many great refactoring books out there such as

However, during Venkat’s talk he recommended a book that is not about programming, but instead about non-fiction writing in general: On Writing Well by William Zinsser. Whether you are writing a newspaper article, a book, or writing code, many of the same principles for better writing still apply.

  • Simplicity – Writing is a about communication. Often as developers we make code unnecessarily complex. We do this because for some developers it feels good and impresses others. A developer should never be proud of complexity in code, but instead focus on simplicity.
  • Clarity – Make it clear. Don’t use cryptic naming, instead make it clear and easy to understand.
  • Brevity – Make it short, but be careful not to take it too far. Reading a very long piece of text can make it take time to understand a piece of code, but it is also easy to make it too short. Use only as many words as it takes to make the code understandable and no more.
  • Humanity – Write it for people. Remember that code is going to be read by other developers, so consider how others will interpret what you have written and keep that in mind when writing code to make it simple, clear, and concise.

June 20, 2010

Tail Recursion in Scala: A Simple Example

Filed under: Scala,UberConf 2010 — Brian @ 8:39 pm
Tags: , , ,

While at UberConf I had the great opportunity to attend a talk titled “Scala for Java Programmers” put on by Venkat Subramaniam, the author of the book “Scala Programming“. In my previous post I gave examples of using XML in Scala. In this post I will walk you through the examples Venkat used to show how to properly do tail recursion in Scala.

Recursion
def factorial(number:Int) : Int = {
    if (number == 1)
       return 1
    number * factorial (number - 1)
}
println(factorial(5))

In order for a recursive call to be tail recursive, the call back to the function must be the last action performed in the function. In the example above, because the total returned from the recursive call is being multiplied by number, the recursive call is NOT the last action performed in the function, so the recursive call is NOT tail recursive. The method calls itself until the parameter passed in equals 1. In this recursive method call, the sequence of calls looks like:

5 * total (5 – 1)
4 * total (4 – 1) = 20
3 * total (3 – 1) = 60
2 * total (2 – 1) = 120

Tail Recursion

To take this example and make it tail recursive, we must make sure that the last action performed in the function is the recursive call. To do this we update the factorial function to have two parameters. The new accumulator parameter stores the intermediate value, so we are no longer doing a calculation against the value returned from the function like we were before.

def factorial(accumulator: Int, number: Int) : Int = {
  if(number == 1)
    return accumulator
  factorial(number * accumulator, number - 1)
}
println(factorial(1,5))

However, we can still do better! Scala allows a function to be declared inside another function. So here we take the code inside the function and wrap it in a new inner function called factorialWithAccumulator. By making this change we avoid changing the parameters of the factorial method so no one calling it needs to do anything different.

def factorial(number: Int) : Int = {
   def factorialWithAccumulator(accumulator: Int, number: Int) : Int = {
       if (number == 1) 
           return accumulator
       else
           factorialWithAccumulator(accumulator * number, number - 1)
   }
   factorialWithAccumulator(1, number)
}
println(factorial(5))
Why Tail Recursion?

In the recursion example, notice how the result of each call must be remembered, to do this each recursive call requires an entry on the stack until all recursive calls have been made. This makes the recursive call more expensive in terms of memory. While in the tail recursive example, there are no intermediate values that need to be stored on the stack, the intermediate value is always passed back as a parameter.

June 17, 2010

UberConf 2010

Filed under: Conferences,UberConf 2010 — Brian @ 1:11 pm

Attending UberConf

Attending UberConf

This week I had the great opportunity to attend UberConf 2010 in Denver Colorado. This is primarily a JVM platform focused conference, but still has a variety of topics outside of the JVM such as iPad development, Agile, and Design Patterns. Also the conference has a good focus on alternative languages on the JVM such as Scala, Clojure, JRuby, and Jython.

The keynote speaker at the conference was Cliff Click, the chief JVM architect. He gave a great opening speech on concurrency in the JVM. I also really enjoyed attending several other talks presented by Cliff at UberConf.

I was very excited this week to have the opportunity to attend a Scala Workshop put on by Venkat Subramaniam whole wrote the book “Scala Programming“. I also had the opportunity to attend his “How to Approach Refactoring” talk which was also excellent.

I finished off the week by attending a talk put on by Stuart Halloway on the programming language Clojure. Stuart also authored the book “Programming Clojure“. It was a fun three hour introduction to a very interesting programming language. Stuart left us with a number of exercises and examples to work from to continue learning the language on our own. The language is a strange mental shift to make which is a good thing.

June 16, 2010

Working with XML in Scala: A Simple Example

Filed under: Conferences,Scala,UberConf 2010 — Brian @ 7:20 am
Tags: , , , ,

While at UberConf I had the great opportunity to attend a talk titled “Scala for Java Programmers” put on by Venkat Subramaniam, the author of the book “Scala Programming” . During the talk we went into a number of examples of where Scala excels over Java, in that it makes life for the developer significantly easier. One of those areas is in working with XML. In Scala, XML is a first class citizen (Woohoo!).

So for those of you who have never used Scala before, here are a few simple examples of working with XML:

Create XML
In this example all we do here is take some xml and assign it to a val. Okay, so does not seem like anything special, but wait, notice the lack of quotes around the XML tags.

val xml = <car make="Ford">Galaxy</car>
println(xml)

prints the XML:

<car make="Ford">Galaxy</car>

Generate XML
In this example we take a Map and generate XML based on the values in that Map.

val cars = Map("Galaxy" -> "Ford", "Chevelle" -> "Chevrolet")

def createCar() = {
   cars.map { entry =>
       val (key, value) = entry
       <car make={key}>{value}</car>
    }
}

val xml = <cars>{createCar()}</cars>
println(xml)

prints the XML:

<cars>
    <car make="Ford">Galaxy</car>
    <car make="Chevrolet">Chevelle</car>
</cars>

Parse XML with Xpath

val xml = <car make="Ford">Galaxy</car>
val make = xml \\ "@make"
println(make)

prints out the Result: Ford

Parsing XML From A Service
Alright, now let’s actually do something useful. The following is a simple example used by Venkat during his scala session. In this example we access Yahoo’s weather feed and return the City, State, and current temperature for Denver, CO.

import scala.xml._
import java.net._
import scala.io.Source

val theUrl = "http://weather.yahooapis.com/forecastrss?w=2391279&u=f"

val xmlString = Source.fromURL(new URL(theUrl)).mkString
val xml = XML.loadString(xmlString)

val city = xml \\ "location" \\ "@city"
val state = xml \\ "location" \\ "@region"
val temperature = xml \\ "condition" \\ "@temp"
 
println(city + " " + state + " " + temperature)

Now, for fun, try writing this example in Java (Hmm, okay, that won’t be much fun at all).

To Run the examples

Common AntiPatterns

While at UberConf 2010 I had the opportunity to attend a talk on AntiPatterns put on by Mark Richards. There are many AntiPatterns that exist in the software world, but Mark decided for this talk to focus on seven that he considers to be the most common. The following is a quick summary of Mark’s talk.

What are Patterns?

A pattern is a repeatable process that produces positive results each time. The main reason patterns were developed were to help improve communication between developers. Design patterns allow developers to use a common language to convey complex design ideas in just a few words.

What are AntiPatterns?

AntiPatterns are things we repeatedly do that produce negative results. The example Mark used was Gambling. Even though repeating this process produces negative results, we still do it again and again.

Factors that cause Anti-Patterns
  1. Haste – When project deadlines are tight, budgets are cut, team sizes are reduced, in these pressure situations we tend to ignore good practices.
  2. Apathy – Developers who really don’t care about the problem or the solution will almost always produce a poor design.
  3. Ignorance – When a developer either lacks knowledge of the domain or of the technology being used, that ignorance will result in antipatterns being introduced.

Seven Common AntiPatterns

There are many, many antipatterns in software design, but these are some of the most common.

1. Cargo Cult Programming

Using design patterns, techniques, or new technologies before really understanding them. Often as developers we jump into new technologies because they are interesting and we want to use them so we try to fit it in somehow, whether or not it is necessary for our project. This can lead to introducing a new technology or pattern when it is not needed and add unnecessary complexity.
Avoid it:

  • Don’t introduce a new technology unless it is absolutely necessary.
  • When you see some code you aren’t sure of, take the time to read and understand it.
  • Take the time to read and understand a technology you are currently using or considering using.
2. Lava Flow

An old area of the code is never updated or touched because everyone on the project is scared to touch it. Often this occurs because none of the original developers who wrote the code still work at the company. Some signs of lava flow are when you have large blocks of code commented out (“Why was this commented out, was it needed?”) and also when there is dead code still hanging around in the code base.
Avoid it:

  • Remove the commented out code.
  • TDD with meaningful regression tests.
  • Use tools to find dead code.
  • Use interfaces to isolate the mess and also help locate dead code. If no path through the interface uses it, then it is safe to remove the code.
3. Parallel Protectionism

Code becomes so complicated and fragile that developers start copying the code and making changes to the copy rather than extending the original code out of a fear of breaking some existing functionality. Problems with this antipattern are that not only does it introduce duplicate code to the product, but now if a bug is found we now have two places to apply the fix instead of just one.
Avoid it:

  • Look for duplicate code at all levels.
  • Split up complicated areas of the code into smaller chunks.
  • Avoid creating complicated tricky code that developers will be afraid of. Focus on readability over clever tricky code.
4. Accidental Complexity

Introducing unnecessary complexity to a project out of ego by trying to out do other developers by accomplishing the same task in less lines of code (“Wow, look at this amazing piece of code I wrote!”). This can also happen by accident when a system is built one method at a time without any real overall plan.
Avoid it:

  • Focus on simple designs.
  • Write readable code instead of “tricky code”.
  • Frequent code reviews, or better yet, pair programming!
5. Object Orgy

An objects private values should never be exposed for modification unnecessarily. This is usually caused by poor encapsulation. For example: generating setters for every property in an object is NOT encapsulation. By always generating setters you are creating an object where it’s state can be invalidated at any time. The state of an object should be initialized by a constructor. Object Oriented programming is about object state, not getters and setters.
Avoid it:

  • Use proper encapsulation.
6. The Blob

A class or package in your system that does far too much. The catch all for any code where the developer is not sure where to put it, or is just too lazy to create a new class or package. Also what can happen is developers will put code somewhere else simply because it is smaller and easier to work with, even if it is not the correct location. This antipattern is usually caused by a lack of proper object oriented design skills on a team.
Avoid it:

  • Code reviews or pair programming.
  • If you can’t describe a classes functionality with a single sentence, then it has too much responsibility.
7. Golden Hammer (Most Common)

Using the same technology or technique to solve every problem. For example: “I like Perl, Perl is the best language ever, it is perfect for any problem”.
Avoid it:

  • Be familiar with many programming languages, technologies, tools, and know each of their strengths and weaknesses.
  • Set your personal preferences aside and always pick the best tool/technique for each problem you are trying to solve.

Blog at WordPress.com.