20 maja 2012

Code sandwich

Ruby koans is a great way to learn basics of Ruby. For me it was also a chance to meet for the first time a 'Code Sandwich' term. This is not a very popular term but I want to write about it. In my humble opinion it is a very common problem and a name 'code sandwich' fits just accurately. I'm going to show how we can solve it in Java and Ruby.

Ruby koans  define 'Sandwich Code' as follows.
Sandwich code is code that comes in three parts:
(1) the top slice of bread,
(2) the meat, and
(3) the bottom slice of bread.
The bread part of the sandwich almost always goes together, but the meat part changes all the time.
I think that the idea is pretty clear and obvious. So let's define a problem. Our 'Code Sandwich' will be reading a file and processing its content. As processing I will implement a method for counting lines number in a file. So let's start !

Ruby

In Ruby to solve defined above problem I will use blocks (more about blocks in ruby you will have a chance to read on my blog soon). First let's define a method for reading file and passing file object to block as a parameter :

def file_sandwich(file_name)
   file = open(file_name)
   yield(file)
ensure
   file.close if file
end
Quite simple. Now we will use this method to implement counting lines number method:

def count_lines(file_name)
   file_sandwich(file_name) do |file|
      count = 0
      while line = file.gets
        count += 1
      end
      count
   end
end

This code is short and very beautiful. I sure that every programmer (even not the Ruby's) can understand it and appreciate how simple it is.

Java

With Java we need to write a little bit more code because Java doesn't have closures or blocks. Instead it has a rigorous compiler that force us to wrap everything into classes and will shout if we mess up with a type system. So we will start with defining a interface for objects that will be able to process a file content.

public interface FileProcessor<T> {
   public T process(BufferedReader reader) throws IOException;
}

When we have it we can implement our 'fileSandwich' and 'countLines' methods. To make this code similar as much as possible to Ruby approach I will use anonymous class and static methods mechanism.

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class FileUtil {

   public static <T> T fileSandwich(File file, 
      FileProcessor<T> processor) throws IOException {

      FileReader fileReader = null;
      BufferedReader reader = null;

      try {

         fileReader = new FileReader(file);

         try {

            reader = new BufferedReader(fileReader);
            return processor.processFile(reader);

         } finally {
    
            if (reader != null) {
               reader.close();
            }
         }
      } finally {
   
         if (fileReader != null) {
            fileReader.close();
         }
      }
   }

   public static int countLines(File file) throws IOException{
  
      return readFile(file, new FileProcessor<Integer>() {

         @Override
         public Integer processFile(BufferedReader reader) 
            throws IOException {
    
            int count = 0;
            while(reader.readLine() != null) {
               count++;
            }
    
            return count;
         }
      });
   }
}

As we can see a Java solution is more complex and need a more code to solve the 'Code Sandwich' problem. Nonetheless it is working and for people familiar with Java this code is pretty readable.

Summary

As we saw 'Code Sandwich' is not a very hard problem and in every language there is a way to solve it. Only difference is how many code you must write. In Ruby language solution is straight. Ruby has blocks that help us keep code clean and follow "Don't repeat yourself" principle. In Java to solve 'Code Sandwich' we need to do more work in order to satisfy compiler. It's just nature in Java. However it doesn't mean that Java is bad. It's just Ruby being awesome :)

Brak komentarzy:

Prześlij komentarz

Prześlij komentarz