The Artima Developer Community
Sponsored Link

Angle Brackets and Curly Braces
Static Versus Dynamic Attitude
by Bill Venners
February 9, 2005
Summary
To what extent does the mindset encouraged by a language and its surrounding culture influence people's perceived productivity when they use that language? In this weblog post, I take a look at this question in the context of the static versus dynamic typing debate.

Advertisement

There has been much debate concerning the relative merits of static and dynamic languages. Dynamic language enthusiasts feel they are far more productive when using languages such as Smalltalk, Python, and Ruby compared to static languages like Java or C++. Static language enthusiasts feel that although dynamic languages are great for quickly building a small prototype, languages such as Java and C++ are better suited to the job of building large, robust systems. I recently noticed that in my own day-to-day programming with Java and Python, I approach programming with a different mindset depending upon the language I'm using. I began to wonder to what extent the mindset encouraged by a language and its surrounding culture influences people's perceived productivity when they use that language.

Refactoring JSPs to Poor Man's Struts

A year ago at Artima I had a large number of JSPs that weren't organized in an model-view-controller (MVC) architecture. In these JSPs, the business logic was mixed with logic responsible for generating the HTML view. I wanted to start making incremental improvements to these JSPs by refactoring each JSP into an MVC architecture whenever I needed to make a change to that JSP. I didn't want to change any existing URLs, and wasn't pleased with the frameworks I investigated such as Struts and WebWork, so I adopted an interim approach I called "poor man's struts."

For each JSP I refactored to the poor man's struts architecture, I created a Page class (the controller) with a static process method. I moved the business logic from the JSP into the process method, and called the process method from the top of the JSP, like this:

// Imagine this is the top of a JSP,...
ExamplePage.Context context = ExamplePage.process(request, response, session);

After executing the business logic, the process method returned a context object filled with objects that the remainder of the JSP needed to render the page. Because the business logic often included explicit redirects, I decided to let the context object indicate whether or not the process method had already redirected the client. If the so, the JSP simply returned:

// Imagine this is the top of a JSP,...
ExamplePage.Context context = ExamplePage.process(request, response, session);

if (context.isRedirected()) {
    return;
}
The remainder of the JSP, the view portion, usually depended on variables that were declared in the business logic portion. Now that the business logic had been moved to the process method, I needed to redeclare those variables. Therefore, I declared the missing variables next and initialized them with values and objects extracted from the context object, like this:
// Imagine this is the top of a JSP,...
ExamplePage.Context context = ExamplePage.process(request, response, session);

if (context.isRedirected()) {
    return;
}

long forumID = context.getForumID();
boolean reply = context.isReply();
String subject = context.getSubject();
String body = context.getBody();

The Context Classes

My insight into the different mindsets I adopt when using Java and Python became apparent to me when I was deciding how to return the information and objects from the process method to the JSP. In many web MVC frameworks, this information is moved by placing the information in a context object, whose sole purpose in life is to move the information from the controller to whatever entity is rendering the view. Similarly, in the case of poor man's struts, the process method populates a context object and returns it to the JSP. Because all poor man's struts context objects would need to indicate to the JSP whether or not the process method had performed a redirect, I created ControllerContext, a superclass extended by all context classes:
public class ControllerContext {

    private boolean redirected;

    public ControllerContext(boolean redirected) {
        this.redirected = redirected;
    }

    public boolean isRedirected() {
        return redirected;
    }
}

For each Page class, I created a nested class called Context. The constructor of this class accepted a boolean redirected flag and a parameter for each value or object needed by the JSP. Here's an example:

// Declared inside the ExamplePage controller class

public static class Context extends ControllerContext {

    private long forumID;
    private boolean reply;
    private String subject;
    private String body;

    public Context(boolean redirected, long forumID, boolean reply,
                    String subject, String body) {

        super(redirected);

        if (forumID < 0) {
            throw new IllegalArgumentException();
        }
        if (subject == null || body == null) {
            throw new NullPointerException();
        }

        this.forumID = forumID;
        this.reply = reply;
        this.subject = subject;
        this.body = body;
    }

    public long getForumID() {
        return forumID;
    }

    public boolean isReply() {
        return reply;
    }

    public String getSubject() {
        return subject;
    }

    public String getBody() {
        return body;
    }
}

Attitudes on Multi-Valued Returns

The context object is a vehicle that enables the process method to return multiple values to the JSP. In several Java MVC frameworks, the context object is essentially a Map. The controller places objects into the context Map identified by named keys. Had I taken this approach in poor man's struts, for example, the process method of ExamplePage could have placed the subject string "A Tale of Two Cities" into the Map with the key "subject". I rejected this approach primarily because I felt creating a specific Context class for each controller would allow me to employ the type system to enforce constraints. The ControllerContext superclass, for example, enforces that all context objects supply a boolean redirected value. The ExamplePage.Context subclass enforces that ExamplePage.process always provides a non-negative forumID. My theory was that such constraint checking would help me achieve robust code.

In practice, however, I found I was always in a hurry when I refactored a JSP to poor man's struts, because I only performed this kind of refactoring when I otherwise had some enhancement or bug fix to make to the JSP. I also found that this approach to the context object required a lot of code. To speed up the process, I wrote a Python script that, given a simple list of types and variable names, generated much of the needed Java code. The Python script did not generate any validation of input parameters in the Context constructor. I needed to write those by hand, and I discovered that I rarely felt it worth the time to do so.

Given this experience, I ultimately decided that the added type safety wasn't really worth the extra effort it required in this situation. In our new MVC architecture, the controllers return essentially a Map context, and we enforce constraints with unit tests. The wierd thing is that I realized that if I had been designing poor man's struts in Python, I probably wouldn't have thought twice about just returning all that information in a tuple, as in:

(redirected, forumID, reply, subject, body) = ExamplePage.process(req, resp, session)

From a safety perspective, a tuple seems even more error prone than a Map, because I have to get the order correct on both sides, not just the names. If the thirteenth element in the tuple is a message ID, then I have to make sure the thirteenth element in both the return and assignment tuples is messageID. While order is generally random, names of keys and variables are usually similar, such as:

String subject = context.get("subject");
In Java, the multi-valued approach equivalent to Python's tuple would be toss everything into an array of Object and pull it out by index on the other side. I would never do that in Java, but I don't hesitate to do it in Python. Why?

One reason is that Python supports this multi-valued return technique better in its syntax than Java, but I realized that the availability of syntax isn't the main reason I do it in Python. The main reason is that's the way it's usually done in Python. By contrast, that's not the way it's usually done in Java. The cultures are different. The culture that guided the design of a language influences my attitudes and mindset when I use the language. The Java culture encourages me to build solid bricks that can be combined to build large, dependable systems. The Python culture encourages me to glide smoothly and quickly to a solution.

This realization got me wondering, to what extent is this perceived increase in productivity with languages such as Python, Ruby, and Smalltalk due to the culture of those communities, and the mindset that the culture engenders in programmers, versus the actual languages themselves? Do you find yourself performing acts with reckless abandon in one language that would make you feel guilty to do in another? How easily can you switch mindsets when you switch languages? Do you find yourself fighting the mindset in one language, and feeling at home in another? What is the real source of the differences in the static versus dynamic language debate?

Talk Back!

Have an opinion? Readers have already posted 22 comments about this weblog entry. Why not add yours?

RSS Feed

If you'd like to be notified whenever Bill Venners adds a new entry to his weblog, subscribe to his RSS feed.

About the Blogger

Bill Venners is president of Artima, Inc., publisher of Artima Developer (www.artima.com). He is author of the book, Inside the Java Virtual Machine, a programmer-oriented survey of the Java platform's architecture and internals. His popular columns in JavaWorld magazine covered Java internals, object-oriented design, and Jini. Active in the Jini Community since its inception, Bill led the Jini Community's ServiceUI project, whose ServiceUI API became the de facto standard way to associate user interfaces to Jini services. Bill is also the lead developer and designer of ScalaTest, an open source testing tool for Scala and Java developers, and coauthor with Martin Odersky and Lex Spoon of the book, Programming in Scala.

This weblog entry is Copyright © 2005 Bill Venners. All rights reserved.

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use