Tuesday, September 22, 2009

Frameworks -- Explicit and Implicit Wiring

In any new project, there is that moment when you are reflecting whether a group of classes belong to the package "core" or "utils" or "framework", or whether you need all these three altogether.

The difference between utils, framework and core should be simple. Utils are the basic functions needed by everyone, mostly unrelated to this specific project. They are all stateless by definition, simple input and output, with no dependency with the project's structures. Utils can always be easily tested as stand alone. Core is the basic stuff. The stuff you would direct a new developer to learn first. It is project specific. It may include the basic types relevant for this project, interfaces, enums, project's basic exceptions, etc. Make sure to avoid making it a trash can. It's not the address for things without a context.

Framework is the tricky one of all three. As opposed to "utils", the role of "framework" as suggested by its name is more complex. A framework is a piece of behavior interacting with other code to represent a real, concrete, runtime behavior. Usually, even if built specifically for this project, it has some generic characteristics, it is written in a way that could be extended, or used in the future in other ways that we don't see currently. For this we use design patterns like strategy, command, visitor, and in fact almost any that you can think of, to create some kind of "dynamic behavior", or "dynamic wiring". Which means that the framework describes a behavior, but not entirely, only an exact usage can describe an end-to-end scenario. This is why frameworks are best explained with an example (while utils can be explained by what they simply do).


There are good frameworks and bad ones. EJB in its first versions for example was horrible (some don't like it till today, a first bad impression is hard to fix). JDBC is a good framework. Java-Servlets is a good framework. What makes good frameworks good is that people find them easy to use, they save development time compared to other alternatives, and you would usually find over time very few versions of the same good framework (and the new versions would be fully compatible with old code). Of course the question is how to achieve this simplicity, real contribution and long-run future compatibility.


When designing and implementing a framework, occasionally you want to make life easier for the user by doing something automatic for him, let's say pass the value of some field into another field with a relevant name convention -- thus the user doesn't have to write a single line of code! There is this trick in the framework which does it for him. Let's call it "implicit wiring". Alternatively, you may expose to the user a way to acquire the value and require him to pass it explicitly by writing his own code. Let's call it "explicit wiring".


In some cases the difference is not so obvious. Suppose you have a controller which may implement many kinds of behavior, if not implemented then a default behavior is used by the framework. When the number of different behaviors of this controller start to inflate, things become a bit obscure, unreadable, thus maybe "implicit". A better approach would be to break the controller to different interfaces and allow the user to implement the interfaces representing the relevant behavior for him, thus checked by the compiler that no method is accidentally left out, more readable and "explicit".


This discussion came out recently with my team member Effie.
We had a reference between two UI elements: "table" and "toolbar". I suggested that if "table" doesn't declare on its referenced counterpart "toolbar" then we will assume by default that it relates to a toolbar with some predefined name (e.g. "toolbar"). That way, I said, even if the user forgot to give a name for his toolbar, things would work nicely.

Effie's reaction was a bit frightening. (Well, not for someone who knows him). It is common in our work environment that a worker shouts at his boss. Which happened in this case. "I'm not working this way, if you want such a framework leave me out of it", was the part I can quote. Of course when he chilled out came the explanation. Implicit wiring is the base of all framework sins. I like such semi-emotional semi-professional reactions! And he was totally right. Think of someone trying to understand how the framework connects a toolbar to a table. And if he wants to add now another table and toolbar how can he do it? True, there is still the explicit way of referencing by name, but once I entered the implicit way, most cases would be using the implicit format which makes the explicit less known and less documented in examples. Also, implicit wiring tends to break over time, as at some point it may collide with something else and break old code. On the other hand, if you allow only the explicit way, all examples would present the explicit way, code would be always more simple to understand and maintain, and less prone for future incompatibilities. Even with the costs of higher efforts in the first implementation, explicit shall win.


Frameworks in their nature do things behind your back. Try to narrow this behavior as much as you can. Make things explicit as much as possible. Less to explain and document and more for your framework future compatibility.


No comments: