Saturday, April 4, 2009

The lost control flow

When I started learning programming languages, in Pascal, the emphasis was on the block structure. The advantages for the developer are obvious, like divide and conquer design, visible scope of variables, linear flow of control, etc.

It seems to me that things were getting too easy, and today the block structure is falling apart. The success of scripting languages, multi-tier architectures, and multiple layers makes it more difficult to follow the data along an application. Now the control flow is being attacked, too.

The multi-threading is obviously the first fighter which multiplies the control flows. But now there is an insidious one coming from event-driven applications. GUI toolkits widely use the listener pattern, because nothing is more natural than adding an event listener on a button so when the user clicks on it, a callback is invoked.

Unfortunately, the listener pattern is being overused, and events are more and more integrated to application logic, even where it is not really mandatory. The excuse behind is for example a cleaner separation between different modules, but triggering a callback disrupts the control flow and the external context is lost (which makes debug more complicated as the origin of event is less known and accessible). This wasn't an issue with the button, because the user click represents really a separate event that initiates a new processing.

Another cause for listener pattern abuse is the complexity of component life cycle. For instance, in Flex, the graphic component is build in several steps (creation, addition to container, measure, update to display with correct location). Flex 4 introduces extra steps for managing skins (skin parts are loaded, according if there are deferred, dynamic, or static). Eventually, the pre or post initialization of components are done through a mechanism like events, at one of the life cycle steps. Not only the control flow is lost, but the life cycle is far from being clear, giving the callback running some code although the state is not really the one the developer expected. For example, when a skin part is loaded, the size and location of the component is not set yet.

The control flow is indeed a cornerstone of programming. It's very sad the modern programming languages don't pay much attention to it and let it falling apart...