Saturday, September 11, 2010

The problem-solving process in dynamic vs. static languages

This post is about why not to used static languages. It will outline the creative process used when starting to attack a problem and implementing its solution in code, and why that very process is hindered greatly by static languages.

You know what I mean, when I say static languages (Java, Scala, C++, et.c.).

I know that I've read about similar ponderings to these on the web earlier but a) I can't find them right now and b) It struck me anew on a personal level when I tried to understand why I work so much quicker when developing code in a dynamic language (especially JavaScript).

The dynamic development process

When I start to formulate a solution to a problem in JavaScript, I focus on the algorithm, on the classes that operate on the data and their methods - on the flow of function calls between different parts of the system I build.

Most often I forget some details about the data being passed or of what kind of state I need to include in the arguments in calls between different classes. This is no big deal as I just create new objects on the fly as arguments or return values, sometimes currying them up as part of a filtering process.

This lets me stay 'in the zone' and focus on the problem I'm trying to solve. The data structures are pliable and can be changed in the same place as the code. I never need to bothered with what kind of data I'm juggling. I might do something like this;

foo.barMethod({size: x, noses: 17, frotz: {a:'b', c:'d'}}, this.somethingImportantAtTheMoment);

The first barMethod argument is an object. Just an object, could be anything. When I need to put more stuff in there, I do so. The object is so lightweight that it doesn't warrant its own class, it is really just a simple wrapper around some data I'm passing, pliable as my code for using it are right now in my problem-solving process.

The static development process

This might differ significantly in Scala which I must confess I haven't studied enough. Please let me know in the comments if so. But when working with Java, I very quickly run into the creation of (often hierarchical) the definition of data classes and interfaces.

Their properties are often complex, themselves objects, a couple of layers deep. Even though each data class is trivial, creating them takes me out of my creative zone, forcing me to make decisions around data that I'm not ready for yet. So naturally I put in the bare minimum of information.

Then when using and passing around these objects, I often find myself constricted by the fairly arbitrary member/property types I've chosen, whose management tend to bleed out into the code, in the form of casts, et.c (This should be an area where Scala does help, though).

When I change my strategies for my problem-solving logic, it impacts heavily on the contents and types of the data classes, even if the data and logic classes are the same. I need continually to pop out of problem-solving mode into yak-shaving mode to arrange the data to fit my new logic.

I have now realized why static people so often tout the importance of having refactoring zombie-dust-powers in their extensive IDEs. From my vantage point it seems like fixing a language deficiency.

But wait!  What about all that evil terror that happens if you just create anonymous objects and functions mid-stride without any type enforcement?  Well, for one thing - testing is key, and another thing - it has actually happened once or twice that I've had to hunt about in somebody else's code for what on earth they have put in an argument object.

Compared to the extreme pain of always having a static retriever biting my private parts, the problem of finding the dynamic bottle of beer in the living rooms has in my experience been an extremely fair trade-off.

YMMV, of course.