Tuesday, October 9, 2007

Applying scala to solving real world problems

Scala is no doubt an excellent language. However, problems like 8-queen or quick sort in the scala doc just aren't  convincing to software professionals in the industry. So I'd like to show how to apply it to solving real world problems in Java. Here let's consider the logging problem in Java. Usually people write code like:

        if (log.isDebugEnabled())
        {
            log.debug("Foo is: " + foo);
        }

Why check isDebugEnabled() if the log object will not log the message if debug is not enabled? This is for performance. If we didn't have this check, the toString() would always be called on foo and the result would always be appended to "Foo is:" to form a new string, even when debug was not enabled.

Scala can easily solve this problem using called-by-name parameters:

class Log {
  var isDebugEnabled: Boolean = false;
 
  def debug(msg: => String) {  //msg is a string expression that is unevaluated
    if (isDebugEnabled) {
      System.out.println(msg); //evaluate msg as if it is a function
    }
  }
}

Now you call this method and provide an expression and it won't be evaluated unless debug is enabled:

    val log: Log = new Log();
    var foo: Int = 123;
    log.debug("Foo is:"+foo); //won't be evaluated
    log.isDebugEnabled = true;
    log.debug("Foo is:"+foo); //will be evaluated inside the debug() method

Tuesday, September 25, 2007

My thoughts on the differences between Tapestry and Wicket

After working with both Tapestry (3.x, 4.x and some alpha versions of T5 and as a committer) and Wicket (1.2x and 1.3 betas), below is the differences that I found:

Genius vs developer community

In Tapestry, it is Howard who writes most of the code and makes the final decision. There are a few committers but they are either working on T4 which is going to be superseded by T5 or just fixing bugs or writing documentation. I believe this is because Howard is such a genius in programming that few committer is up to a level to technically challenge him. In addition, as he wrote most of the code, naturally he gets the final say. But most importantly, I think it is because star programmers normally aren't good project managers. When I was a committer in Tapestry, I always wanted Howard to take more on a role of articulating and sharing his vision of T5, inviting active code committers and reviewing their code instead of writing his own (like Linus does with Linux). It seemed that I didn't succeed. Maybe he believes it takes less time to write code than relying on others to implement his vision, after all not many people are smart enough to understand his vision, not to mention to write high qualify code as he.

In Wicket, decisions are always made by technical discussions among the many active committers (8 or so) and then a vote. Those committers are active in the sense that they wrote and maintain significant parts of Wicket (e.g., core, unit testing framework, portlet, ajax). The creator of Wicket is no longer the most active code contributor. In fact I once saw him asking others on the mailing list how a part of Wicket worked!

Performance vs ease of use

A major design goal of Tapestry is high performance. In fact, Howard reserves T5 and Java for situations when high performance is required, while dynamic languages should be used for the rest. This design goal leads to the decision that 1) page objects should be pooled and are stateless as the state is maintained separately. 2) a component can generate multiple element in the output and therefore the component tree is vastly different from the element tree generated.

In Wicket, performance is not a design goal. Instead, it is the ease of use. This leads to the decision that 1) page objects are stateful and 2) there is a direct one-to-one mapping between the component tree and the element tree generated. These differences make it very easy to learn Wicket, to create Wicket pages and to understand how a Wicket application works, at the cost of heavier use of the session. In addition, this also supports the Back button transparently in Wicket as each page in the browser corresponds to a unique page object in the session. In Tapestry, one could use client persistence to store the state to achieve a similar effect. However, client side state is insecure by nature.

Expressive power vs conceptual familiarity

Just like other world class programmers, Howard favors the ultimate power of expression. That is, he hates any kind of duplication or any boileterplate code. Therefore, one can find a lot of domain specific languages in Tapestry and a lot of automatic magic running to free the programmer from any chore.

In Wicket, everything except the HTML code is done in Java. Plain old Java, not a domain specific language built on topic of Java annotations. There is more boilerplate code, but the programmer will get first class tool support (content assist), compile time checking, refactoring, API doc generation and access and etc. More importantly, it is a lot easier to learn because there is no new concept/language to learn (e.g., a listener in Tapestry is just a plain Java abstract method in Wicket, a validator in Tapestry is just a Java object in Wicket). The use of domain specific language also creates a barrier for functional enhancements. One has to build the function itself and then enhance the parser.

Code quality vs functionality

I've never seen any code that is as good quality as the Tapestry code. The Wicket code just won't compare! One can easily find duplicate code, untestable code due to the extensive use of concrete classes instead of interface, classes having specific logic to handle some specific arguments if they along to a certain classes (fragile) and etc.

Is this a bad thing for Wicket? Yes in a sense. However, this is the result of having a lot of code contributors, including those who are not genius but have a strong itch and the ability to code a solution. So the other side of the story is that Wicket tend to have more working functions than Tapestry (tree component, more ajax functions, modal dialog, dynamic images, wizard. role based authorization, captcha, breadcrumb, ...).

Technology driven vs user driven

Howard strives to create a framework that is technically excellent so to attract users. However, users can seldom persuade Howard on what is good for them. The Wicket team seems to listen to the users on what they want.

Technical advances vs version compatibility

I felt Howard, as a technical genius, has an unstoppable urge and unlimited energy to improve the Tapstry code. Therefore, whenever he sees a technical advance that can improve the code quality, he can't wait to adopt it (T3=>T4 using IoC; T4=>T5 using annotations replacing for XML and convention over configuration), hoping to deliver an excellent shiny new framework for users to enjoy, while leaving the old incompatible version behind.

The Wicket team on the other hand favors version compatibility more than technical advances.

Final words

So, which is better for you? It's up to you to decide. I've written a book on Wicket and another one Tapestry 4.1. The first several chapters in both books are free, so you can check them out yourself.