tag:blogger.com,1999:blog-372741832024-03-16T03:10:21.585+02:00Java: Developing On The StreetsAnonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.comBlogger75125tag:blogger.com,1999:blog-37274183.post-75838588270518000452012-02-04T20:08:00.000+02:002013-01-15T18:58:06.682+02:00From 0 to Node.Js/Jasmine/CoffeeScript in 10m<b>Context/Background</b><br />
I wanted to get started with <a href="http://nodejs.org/">Node.js</a>, <a href="http://pivotal.github.com/jasmine/">Jasmine</a>, and <a href="http://coffeescript.org/">CoffeeScript</a>. How to go about it in an Ubuntu system? For some reason installing node.js via <code>sudo apt-get install nodejs</code> (<a href="https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager">full instructions</a>) didn't work for me. I overcame this by locally compiling it, but then other issues came up as I moved on to Jasmine. It took some trial-and-error time but eventually I zeroed in on the solution. A key part is the installation of <a href="http://npmjs.org/">npm</a> (a package manager for Node.js).<br />
<br />
<b>Starting Point</b><br />
You have <a href="http://nodejs.org/#download">downloaded Node.js source code</a> (here, <code>node-v0.6.10.tar.gz</code>) into your <code>~/Downloads</code> directory.<br />
<br />
<b>From .tar.gz to Jasmine...</b><br />
<pre><code>mkdir -p /tmp/installation
sudo apt-get install npm
cd /tmp/installation
tar -zxf ~/Downloads/node-v0.6.10.tar.gz
cd node-v0.6.10/
./configure
make
node -e "console.log('Node.js is up')"
curl https://npmjs.org/install.sh | sudo sh
sudo npm install jasmine-node -g
cat <<EOF > app1.spec.js
var app = require('./app1.js');
describe("my app", function() {
it("greets you", function() {
expect(app.helloWorld("Martin")).toEqual("Hello, Martin");
});
})
EOF
cat <<EOF > app1.js
exports.helloWorld = function(s) {
return "Hello, " + s;
}
EOF
jasmine-node app1.spec.js</code></pre>
<br />
<b>... to CoffeeScript</b><br />
<pre><code>sudo npm install -g coffee-script
cat <<"EOF" > app2.spec.coffee
app = require './app2'
describe "my app", ->
it "greets you", ->
(expect app.helloWorld "Martin").toEqual "Hello, Martin"
EOF
cat <<"EOF" > app2.coffee
exports.helloWorld = (s) ->
"Hello, " + s;
EOF
jasmine-node --coffee app2.spec.coffee</code></pre>
<br />
<b>Final thoughts</b><br />
This post's goal is to reduce setup time/learning curve such that others can start using these (great) tools right away. As a Node.js noob, I didn't even know that npm exists. I also found it difficult setting up my first toy programs: a Node.js program, a Jasmine spec, a CoffeeScript program, and a Jasmine/CoffeeScript spec. There are syntactic issues and framework issues (such as: Node's <span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">require()</span> and <span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">exports</span> thingy) which you need to get exactly right in order to make the pieces fit together. An out-of-the-box running sample - which is what this post tries to provide - can mitigate much of this pain.<br />
<br />
I also found it difficult to find good web-pages discussing this process. Thus, for the common good, I will put a few keywords to help future Noobies find it: jasmine node.js coffeescript Ubuntu npm spec installation setup getting started hello world program.<br />
<br />Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com4tag:blogger.com,1999:blog-37274183.post-69706855476655670992010-11-28T18:00:00.003+02:002014-01-24T20:21:25.612+02:00On the similarity of agile development and concurrent programming<div>
This is one these posts that I've been willing to write for ages. The inspiration came from reading <a href="http://twitter.com/KentBeck">Kent Beck</a>'s <a href="http://www.amazon.com/gp/product/0321278658/">Extreme Programming Explained</a> and from a <a href="http://codemonkeyism.com/high-cost-overhead-working-parallel/">post</a> by <a href="http://twitter.com/codemonkeyism">Stephan Schmidt</a>.</div>
<div>
<br /></div>
<div>
<b>Concurrent Programming</b></div>
<div>
<br /></div>
Let's say you need to write a program that crunches a large set of inputs. There are three different calculations that need to be carried out for each input value. Each calculation is relatively complicated and relies on data structures for looking up previously computed values.<br />
<br />
In a single-core settings things are simple. You can either choose to feed each input into all three algorithms or, otherwise, to run the first algorithm on all inputs and then turn to the other two algorithms. Either way, your throughput will be roughly the same (modulo caching issues).<br />
<br />
The story is different in multi-core machines. By and large, there are two design options:<br />
<br />
<ul>
<li>Option 1 - Decomposition by Algorithms<br /><br />Creare three threads, one for each algorithm. Each thread scans the input and feeds the values into its own algorithm.<br /><br />There are almost no data races - the data structure supporting algorithm 1 are only accessed by thread 1, thus obviating the need to guard against other threads. Cache behavior also seem to be quite good: each thread touches only a part of the heap, thus promoting data locality and cache-friendliness.</li>
<li>Option 2 - Decomposition by Inputs<br /><br />Creare N threads (N == #cores). Each thread takes the next value from the input, and feeds it, in turn, into each of the three algorithms.<br /><br />This design puts a greater burden on the programmer. Each thread touches all data structures, thus requiring careful locking. Locality is also not so good: after accessing data structures of algorithm 1, a thread will start executing algorithm 2 (for the same input) thus touching different data structures resulting in more cache misses.</li>
</ul>
It seems that decomposition by algorithms is superior to decomposition by inputs. It is simpler to implement (less locking), and is likely to be more cache friendly. Are there any advantages to using decomposition by inputs? <br />
<div>
<br /></div>
<div>
Yes!</div>
<div>
<br /></div>
<div>
<ul>
<li>Scalability. Option 1 is great if you have three cores on your machine. If your code runs on a machine with (say) 8 core, then you need to redesign your code such that it has five more threads, possibly by decomposing existing algorithm into smaller, concurrently running, sub-algorithms. This incurs a substantial engineering effort.<br /><br />Option 2, on the other hand, is highly scalable. If you're running on more cores, you just need to spawn more threads. You can even let your code figure the optimal number of threads dynamically, thereby allowing it to adjust to unforeseen circumstances (such as: if the O/S starts running a CPU-intensive process that leaves your program with fewer cores).</li>
<li>Reduced starvation. In option 1, if execution times of the various algorithms are not equal, some threads will finish before the others (idle), thereby making overall throughput sub-optimal.<br /><br />In option 2, a thread may go idle only at the very end of the execution: when the number of remaining inputs is less than #cores, which is a fracture of the total iterations.</li>
<li>Less up-front estimations. In option 1, one needs to estimate the execution times of the various algorithms, across all possible target machines, in order to minimize the effect of starvation.<br /><br />In option 2, such estimations are practically redundant due to the reduced starvation.</li>
<li>Progress monitoring. Given that number of inputs is far larger than number of algorithms in a program, prediction of time-to-completion is more accurate in option 2 (c.f. <a href="http://en.wikipedia.org/wiki/Law_of_large_numbers">Law of Large Numbers</a>).</li>
<li>Easy On/Off. In option 2, if you need to stop in the middle, you just need to stop dispatching work items to threads. Pretty soon all threads will stop. In option 1, the programmer needs to build shutdown logic into each thread/algorithm (e.g.: inspect a shared, atomic boolean and bail out if it goes to false)<br /><br />In much the same way, it is also easy to restart later: you know that all inputs (up to a certain point) were fully processed, and all remaining inputs are fully un-processed. Thus, you have perfectly valid (though partial) output<br /><br />An "Abort" in option 1 leaves each thread in a different location, thereby making it difficult to resume later. The outputs, across the algorithms, are non-aligned (in addition to being partial). </li>
</ul>
<div>
Of course, decomposition by inputs is not always better than decomposition by algorithms. Inter-thread locking may be, in certain cases, so costly that option 1 is still faster. Nonetheless, I argue that, in general, option 2 is likely to be more scalable, yield better throughput (due to less starvation) etc. </div>
<div>
<br /></div>
<div>
<b>Agile Development</b></div>
<div>
<br />
Please re-read the above text, after applying the following substitutions:</div>
<div>
<ul>
<li>Threads, Cores -> Programmers</li>
<li>Inputs -> Features </li>
<li>Algorithm -> Module, Subsytem (or any other large piece of a program)</li>
<li>Execution Time -> Development Time</li>
<li>Cache miss -> Developer switching between different parts of the code </li>
</ul>
<div>
<br /></div>
</div>
</div>
<div>
(I believe that this is just another manifestation of the <a href="http://javadots.blogspot.com/2008/12/is-your-program-greener-or-longer.html">super-linearity axiom</a>: in the world of software development, smaller tasks are more cost-effective than larger ones).</div>
<div>
<br />
PS<br />
I am in the process of further expanding this topic in my bliki, <a href="http://collidingobjects.herokuapp.com/">http://collidingobjects.herokuapp.com</a>. Stay tuned.<br />
<br />
<br />
<br /></div>
Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com7tag:blogger.com,1999:blog-37274183.post-36025522668540201662010-09-19T11:41:00.002+02:002010-09-19T13:19:02.267+02:00Making your Swing App Mac/OSX compliantRunning your plain Vanilla Swing on a Mac, for the first time, will be quite surprising. Your app will stand out, in a bad way, among all other Mac apps because Swing's menu bar is not compliant with OS X's menu bar.<br /><br />Main difficulties are as follows:<br /><ul><li>Your JFrame will have its own menu bar - your menu items will not be shown on the (shared) menu bar</li><br /><li>Using the Command key as the standard accelerator</li><br /><li>Application menu is named after the (fully qualified name of the) main class</li><br /><li>Supporting the standard "Preferences..." application menu item</li><br /><li>Not breaking compatibility with the other OSes (Linux/Windows)</li></ul><br /><br />Alvin J. Alexander has written a fairly detailed <a href="http://www.devdaily.com/apple/mac/java-mac-native-look/java-on-mac.shtml">tutorial</a> about this subject but it is somewhat outdated now. When I tried using classes from <a href="http://developer.apple.com/library/mac/documentation/Java/Reference/1.5.0/appledoc/api/com/apple/eawt/package-summary.html">com.apple.eawt</a> (as suggested there) Eclipse complained:<br /><br /><div style="text-align: center;"><i>Access restriction: The type Application is not accessible due to restriction on required library /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Classes/ui.jar</i></div><br />(In addition, any static dependency on such Apple-specific classes will break the program when it is runs on Linux/Windows).<div><br />On the other hand, Eirik Bjørsnøs <a href="http://simplericity.com/2007/10/02/1191336060000.html">Macify</a> library provides a good solution to this difficulty, but it does not address the first three points from above.</div><div><br /></div><div>Here's a short program (<a href="http://github.com/imaman/swing-mac">github</a>, <a href="http://github.com/imaman/swing-mac/zipball/master">zip</a>) that shows how these issues can be completely solved. It was derived from both Alvin's and Eirik's articles. It contains Eirik's Macify library (as a .jar) and these two Java classes:<br /><pre><code><br />// Launcher.java <br />package com.blogspot.javadots.swingmac;<br /><br />import javax.swing.*;<br />import org.simplericity.macify.eawt.*;<br /><br />public class Launcher {<br /><br /> private static void macSetup(String appName) {<br /> String os = System.getProperty("os.name").toLowerCase();<br /> boolean isMac = os.startsWith("mac os x"); <br /><br /> if(!isMac)<br /> return;<br /> <br /> System.setProperty("apple.laf.useScreenMenuBar", "true");<br /> System.setProperty("com.apple.mrj.application.apple.menu.about.name",<br /> appName); <br /> }<br /> <br /> public static void main(String[] args) throws Exception {<br /> macSetup("swing-mac");<br /> UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());<br /> <br /> SwingUtilities.invokeLater(new Runnable() {<br /> <br /> @Override<br /> public void run() {<br /> Application app = new DefaultApplication();<br /> Main main = new Main(); <br /> app.addApplicationListener(main.getApplicationListener());<br /> <br /> app.addPreferencesMenuItem();<br /> app.setEnabledPreferencesMenu(true); <br /> }<br /> });<br /> }<br />}<br /><br />// Main.java<br />package com.blogspot.javadots.swingmac;<br /><br />import java.awt.Toolkit;<br />import java.awt.event.KeyEvent;<br />import javax.swing.*;<br />import org.simplericity.macify.eawt.*;<br /><br />public class Main {<br /><br /> private JFrame f = new JFrame();<br /> private MyApplicationListener listener = new MyApplicationListener();<br /><br /> public Main() {<br /> <br /> JMenuBar mb = new JMenuBar();<br /> f.setJMenuBar(mb);<br /> JMenu m = new JMenu("File");<br /> mb.add(m);<br /><br /> addItem(m, "Open", KeyEvent.VK_O);<br /> addItem(m, "Save", KeyEvent.VK_S);<br /> addItem(m, "Save As", KeyEvent.VK_A);<br /> addItem(m, "Import", KeyEvent.VK_I);<br /> addItem(m, "Export", KeyEvent.VK_E);<br /> <br /> f.setTitle("Main");<br /> f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br /> f.setSize(400, 300);<br /> f.setVisible(true);<br /> }<br /><br /> private void addItem(JMenu m, String name, int accelerator) {<br /> JMenuItem mi = new JMenuItem(name);<br /> mi.setAccelerator(KeyStroke.getKeyStroke(accelerator,<br /> Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));<br /> m.add(mi);<br /> }<br /><br /> public ApplicationListener getApplicationListener() {<br /> return listener;<br /> }<br /><br /> // Must be public!!<br /> public class MyApplicationListener implements ApplicationListener {<br /><br /> private void handle(ApplicationEvent event, String message) {<br /> JOptionPane.showMessageDialog(f, message);<br /> event.setHandled(true);<br /> }<br /><br /> public void handleAbout(ApplicationEvent event) {<br /> handle(event, "aboutAction");<br /> }<br /><br /> public void handleOpenApplication(ApplicationEvent event) {<br /> // Ok, we know our application started<br /> // Not much to do about that..<br /> }<br /><br /> public void handleOpenFile(ApplicationEvent event) {<br /> handle(event, "openFileInEditor: " + event.getFilename());<br /> }<br /><br /> public void handlePreferences(ApplicationEvent event) {<br /> handle(event, "preferencesAction");<br /> }<br /><br /> public void handlePrintFile(ApplicationEvent event) {<br /> handle(event, "Sorry, printing not implemented");<br /> }<br /><br /> public void handleQuit(ApplicationEvent event) {<br /> handle(event, "exitAction");<br /> System.exit(0);<br /> }<br /><br /> public void handleReOpenApplication(ApplicationEvent event) {<br /> event.setHandled(true);<br /> f.setVisible(true);<br /> }<br /> }<br />}<br /><br /></code></pre><br /><br />Here are the key points. The order is <span style="font-style:italic;">highly important</span>.<br /><ol><li>Create a dedicated "Launcher" class to carry out the setup phase. A dedicated class ensures that setup takes place before any other UI interaction.<br /></li><li>Set system property apple.laf.useScreenMenuBar to true.<br /></li><li>Set system property om.apple.mrj.application.apple.menu.about.name to the application's name.<br /></li><li>Use Look&Feel to UIManager.getSystemLookAndFeelClassName()<br /></li><li>Use Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() to obtain an OS-correct accelerator key. <br /></li><li>Register an application listener with Macify's Application object. The listener's implementing class must be <span style="font-style:italic;">declared as public</span>.<br /></li><li>Call addPreferencesMenuItem() and setEnabledPreferencesMenu(true) on that application object.<br /></ol><br /><br />The resulting code will work just fine on either Mac/Linux/Windows. The Macify library uses reflection to dynamically discover OSX's runtime system and to wire your listener to it. The use of reflection allows your code to compile on any operating system and also to run fine on Linux/Windows where OSX runtime is clearly not present.<br /><br /></div>Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com5tag:blogger.com,1999:blog-37274183.post-29473325908628087482010-09-12T08:35:00.019+02:002010-09-12T12:06:17.075+02:00Top Ten Getting-Started-With-Dojo TipsYou heard good things about the <a href="http://docs.dojocampus.org/">Dojo</a> library. What is the absolute minimum you need to know in order to start coding effectively with Dojo?<br /><br /><span style="font-style:italic;">Discalimer: This post does not claim that Dojo is better than <a href="http://jquery.com/">JQuery</a> nor the converse. Each library has its strengths. My personal view is that JQuery offers a well designed programming model (the $("selector") thing is ingenious). On the other hand, Dojo currently offers a more extensive set of standard widgets.</span><br /><br /><br /><span style="font-weight: bold;">#1: Importing Modules</span><br /><br />dojo.xd.js is the basic module. Once you imported it into your page via <script src=".."> you can use dojo.require('fully.qualified.name') to import additional Dojo modules.<br /><pre><code><br /><html><br /> <head><br /> <script type="text/javascript" <br /> <span style="color:red">src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"</span>><br /> </script><br /> <script type="text/javascript"><br /> <span style="color:red">dojo.require("dijit.form.Button");</span><br /> </script><br /> </head><br /> <body/><br /></html><br /></code></pre><br /><br /><span style="font-weight: bold;">#2: addOnLoad()</span><br /><br />addOnLoad() lets you register a function that will be called once page loading is finished. This is Dojo's cross-browser-compatible way to hook the onLoad event.<br /><pre><code><br /><html><br /> <head><br /> <script type="text/javascript" <br /> src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"><br /> </script><br /><br /> <script type="text/javascript"><br /> <span style="color:red">dojo.addOnLoad(function() { alert("hi"); })</span><br /> </script><br /> </head><br /> <body/><br /></html><br /></code></pre><br /><br /><span style="font-weight: bold;">#3: Widget creation -- Programmatic Style</span><br /><br />There are two ways to create widgets: Programmatically (shown here) and declaratively (see tip #5). Either way, <span style="font-style:italic;">you must first import the corresponding module via a require() call</span>.<br /><br />In the programmatic you create a widget by calling its constructors, which typically takes two parameters:<ul><br /><li>options: a plain Javascript object specifying widget-specific options</li><br /><li>id: The ID of a DOM node which will host this new widget</li><br /></ul><br />In the example below, a button widget is created via <code>new dijit.form.Button({}, "click-me-button")</code>, which means: no options; ID of hosting element is "click-me-button".<br /><br /><pre><code><br /><html><br /> <head><br /> <script type="text/javascript" <br /> src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"><br /> </script><br /> <script type="text/javascript"><br /> dojo.require("dijit.form.Button");<br /> dojo.addOnLoad(function() {<br /> var button = <span style="color:red">new dijit.form.Button({}, "click-me-button");</span><br /> button.attr("label", "Click Me");<br /> });<br /> </script><br /> <link rel="stylesheet" type="text/css" <br /> href="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/claro/claro.css"/><br /> </head><br /> <body class="claro"><br /> <div id="click-me-button"/><br /> </body><br /></html><br /></code></pre><br /><br /><span style="font-weight: bold;">#4: Overriding a Widget's Methods</span><br /><br />Any method defined in the constructor's first parameter will be attached to the newly created widget, thereby overriding an existing method with the same name. The code below overrides the onClick method of the Button widget. <br /><br />Initial values for the widget's properties can be specified in a similar manner: <code>{ label: "Click me" }</code><br /><br /><pre><code><br /><html><br /> <head><br /> <script type="text/javascript" <br /> src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"><br /> </script><br /> <script type="text/javascript"><br /> dojo.require("dijit.form.Button");<br /> dojo.addOnLoad(function() {<br /> new dijit.form.Button({<br /> <span style="color:red">onClick: function() { alert("Thank you!"); }</span>,<br /> label: "Click me!"<br /> }, "click-me-button");<br /> });<br /> </script><br /> <link rel="stylesheet" type="text/css" <br /> href="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/claro/claro.css"/><br /> </head><br /> <body class="claro"><br /> <div id="click-me-button"/><br /> </body><br /></html><br /></code></pre><br /><br /><span style="font-weight: bold;">#5: Widget creation -- Declarative Style</span><br /><br />The declarative style lets you define widget by using HTML markup. To enable this you <span style="font-weight:bold;">MUST</span> specify djConfig="parseOnLoad: true" at the <script src="dojo.xd.js"> element.<br /><br />You can then use a dojoType="dijit.form.Button" HTML-attribute to tell the Dojo parser to create a button widget that will be hosted by the enclosing HTML element. <br /><br />A nested <script type="dojo/method" event="onClick" args="evt"> element will define a callback method for the onClick event. A nested <script type="dojo/connect"> element will define code that will be executed when the widget is created.<br /><br /><pre><code><br /><html><br /> <head><br /> <script <span style="color:red">djConfig="parseOnLoad: true"</span> type="text/javascript" <br /> src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"><br /> </script><br /> <script type="text/javascript"><br /> dojo.require("dijit.form.Button");<br /> </script><br /><br /> <link rel="stylesheet" type="text/css" <br /> href="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/claro/claro.css"/><br /><br /> </head><br /> <body class="claro"><br /> <div <span style="color:red">dojoType="dijit.form.Button"</span>><br /> <script <span style="color:red">type="dojo/connect"</span>><br /> this.attr("label", "Click Me!");<br /> </script><br /> <script <span style="color:red">type="dojo/method"</span> event="onClick" args="evt"><br /> alert("Thank you!");<br /> </script> <br /> </div><br /> </body><br /></html><br /></code></pre><br /><br /><span style="font-weight: bold;">#6: Defining widget variables -- Declarative Style</span><br /><br />If you add a jsId="myButton" attribute to an HTML element that defines a Dojo widget (i.e. has a dojoType attribute) the Dojo parser will assign the widget to a global variable named myButton.<br /><br />This allows programmatic access to a declaratively-defined widget.<br /><br /><pre><code><br /><html><br /> <head><br /> <script djConfig="parseOnLoad: true" type="text/javascript" <br /> src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"><br /> </script><br /> <script type="text/javascript"><br /> dojo.require("dijit.form.Button");<br /> dojo.addOnLoad(function() {<br /> alert("Press OK to change style");<br /> <span style="color:red">myButton</span>.attr("style", "color:red; font-weight:bold;");<br /> });<br /> </script><br /><br /> <link rel="stylesheet" type="text/css" <br /> href="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/claro/claro.css"/><br /><br /> </head><br /> <body class="claro"><br /> <div dojoType="dijit.form.Button" <span style="color:red">jsId="myButton"</span>><br /> A simple button<br /> </div> <br /> </body><br /></html><br /></code></pre><br /><br /><span style="font-weight: bold;">#7: Obtaining the associated DOM node</span><br /><br />Widgets and DOM nodes are distinct objects. In order to get the DOM node associated with a widget, use the widget's .domNode property.<br /><br /><pre><code> <br /><html><br /> <head><br /> <script djConfig="parseOnLoad: true" type="text/javascript" <br /> src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"><br /> </script><br /> <script type="text/javascript"><br /> dojo.require("dijit.form.Button");<br /> dojo.addOnLoad(function() {<br /> myButton<span style="color:red">.domNode</span>.innerHTML = myButton<span style="color:red">.domNode</span>.innerHTML.bold();<br /> });<br /> </script><br /><br /> <link rel="stylesheet" type="text/css" <br /> href="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/claro/claro.css"/><br /><br /> </head><br /><br /> <body class="claro"><br /> <div dojoType="dijit.form.Button" jsId="myButton"><br /> A simple button<br /> </div> <br /> </body><br /></html><br /></code></pre><br /><br /><span style="font-weight: bold;">#8: Looking up a DOM node</span><br /><br />dojo.byId("someId") is Dojo's cross-browser-compatible way to obtain a DOM node by its ID.<br /><br /><pre><code><br /><html><br /> <head><br /> <script type="text/javascript" <br /> src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"><br /> </script><br /> <script type="text/javascript"><br /> dojo.addOnLoad(function() {<br /> <span style="color:red">dojo.byId("some.div")</span>.innerHTML = "found it!";<br /> });<br /> </script><br /> </head><br /> <body><br /> <div id="some.div"/><br /> </body><br /></html><br /></code></pre><br /><br /><span style="font-weight: bold;">#9: The Widget -> Model -> Store Pattern</span><br /><br />Sophisticated Dojo Widgets, such as the <a href="http://docs.dojocampus.org/dijit/Tree">Tree</a> or the <a href="http://docs.dojocampus.org/dojox/grid/DataGrid">DataGrid</a> widgets rely on the following structure: <br /><br />The widget <span style="font-style:italic;">observes</span> a model which <span style="font-style:italic;">observes</span> a data store which <span style="font-style:italic;">maintains</span> the actual data.<br /><br />There are several (predefined) models that can work with each widget. The Tree widget, for example, can work with either a <a href="http://docs.dojocampus.org/dijit/tree/TreeStoreModel">TreeStoreModel</a> or a <a href="http://docs.dojocampus.org/dijit/tree/ForestStoreModel">ForestStoreModel</a>. These models can work with stores such as <a href="http://docs.dojocampus.org/dojo/data/ItemFileWriteStore">ItemFileWriteStore</a> or <a href="http://docs.dojocampus.org/dojo/data/ItemFileReadStore">ItemFileReadStore</a>.<br /><br /><pre><code><br /><html><br /> <head><br /> <script type="text/javascript" <br /> src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"><br /> </script><br /> <script type="text/javascript"><br /> dojo.require("dojo.data.ItemFileWriteStore");<br /> dojo.require( "dijit.Tree" );<br /><br /> function initPage() {<br /> <span style="color:red">var store</span> = new dojo.data.ItemFileWriteStore({ data:<br /> {<br /> identifier: 'id',<br /> label: 'name',<br /> items: [<br /> { id: 1, name: 'Star Wars Saga', root: true,<br /> children:[{_reference: 2}, {_reference: 3}, {_reference: 4}] },<br /> { id: 2, name: 'Star Wars' },<br /> { id: 3, name: 'The Empire Strikes Back' },<br /> { id: 4, name: 'Return of the Jedi' },<br /> ]<br /> }<br /> });<br /> <br /> <span style="color:red">var treeModel</span> = new dijit.tree.ForestStoreModel({<br /> <span style="color:red">store: store</span>,<br /> query: { 'root': true }<br /> });<br /><br /> <span style="color:red">var widget</span> = new dijit.Tree({<span style="color:red">model: treeModel</span>, showRoot: false }, "div-tree")<br /> }<br /> <br /> dojo.addOnLoad(initPage);<br /> </script><br /> <link rel="stylesheet" type="text/css" <br /> href="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/claro/claro.css"/><br /> </head><br /><br /> <body class="claro"><br /> <div id="div-tree"></div><br /> </body><br /></html><br /></code></pre><br /><br /><span style="font-weight: bold;">#10: Change the Widget's Content by Mutating its Data Store</span><br /><br />When you're dealing with Widget-Model-Store setup and you want to change the content displayed by the widget, the correct way to do it is to change the data store object. These changes will be propagated along the observation chain and will eventually be reflected at the UI.<br /><br />Obviously, the store object must support mutations. Read-only stores (such as: <a href="http://docs.dojocampus.org/dojo/data/ItemFileReadStore">ItemFileReadStore</a>) will not work for you, here.<br /><br />The code below invokes store.deleteItem() when the "Delete 'Return of the Jedi'" button is clicked. The associated Tree widget is automagically updated.<br /><br /><pre><code><br /><html><br /> <head><br /> <script type="text/javascript" <br /> src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"><br /> </script><br /> <script type="text/javascript"><br /> dojo.require("dijit.form.Button");<br /> dojo.require("dojo.data.ItemFileWriteStore");<br /> dojo.require( "dijit.Tree" );<br /><br /> function initPage() {<br /> var store = new dojo.data.ItemFileWriteStore({ data:<br /> {<br /> identifier: 'id',<br /> label: 'name',<br /> items: [<br /> { id: 1, name: 'Star Wars Saga', root: true,<br /> children:[{_reference: 2}, {_reference: 3}, {_reference: 4}] },<br /> { id: 2, name: 'Star Wars' },<br /> { id: 3, name: 'The Empire Strikes Back' },<br /> { id: 4, name: 'Return of the Jedi' },<br /> ]<br /> }<br /> });<br /> <br /> var treeModel = new dijit.tree.ForestStoreModel({<br /> store: store,<br /> query: { 'root': true }<br /> });<br /><br /> var widget = new dijit.Tree({model: treeModel, showRoot: false }, "div-tree");<br /> <br /> new dijit.form.Button({<br /> label: "Delete 'Return of the Jedi'",<br /> onClick: function() {<br /> store.fetchItemByIdentity({ identity: 4, onItem: function(item) {<br /> <span style="color:red">store.deleteItem(item)</span>;<br /> } });<br /> }<br /> }, "div-button");<br /> }<br /> <br /> dojo.addOnLoad(initPage);<br /> </script><br /> <link rel="stylesheet" type="text/css" <br /> href="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/claro/claro.css"/><br /> </head><br /><br /> <body class="claro"><br /> <div id="div-button"></div><br /> <div id="div-tree"></div><br /> </body><br /></html><br /></code></pre>Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com7tag:blogger.com,1999:blog-37274183.post-39357294906011425972010-08-25T10:23:00.008+03:002010-08-26T17:50:45.146+03:00I thought that a small project does not need testing...<div style="text-align: right; font-style: italic;">(...Or: You can't over-estimate the importance of a testing infrastructure)<br /></div><br />Over the last few weeks I had to write three small (1-2 days of work) applications. They were a command line utility, a Swing application that analyzes the complexity of Java methods, and a web-page--a single .html file--that lets it user extract some information from a REST server (Javascript, JQuery, Ajax).<br /><br />I don't think that LOC is a good code metric, but just to give a feeling on the sizes of these projects, their respective LOC (including blanks, comments, unit tests, HTML) values are: 515, 1383, 664.<br /><br />Reflecting on these three application I see a common theme: While I did unit test (and even TDD-ed) certain parts of the apps, I didn't put much emphasize on making the code testable. After all, these are very small apps which should not take very long to develop, so investing in testability seemed like a waste of time. I believed that the benefits of automatic testing will not outweigh the initial cost of putting the required scaffolding in place.<br /><br />I was wrong. Even in web-page of 664 lines (including plain HTML), I quickly got to a position where the behavior of the app was quite intricate. In order to make sure that new functionality does not tamper with existing one I found myself repeatedly rerunning a lengthy series of manual tests. At the next round, there was even more "existing functionality" to test...<br /><br />The total testing effort is actually similar to the sum of a simple arithmetic series: Sn = 1 + 2 + 3 + ... + n. In such a series the value of Sn grows ~ n^2. This means that the time needed for adding a new piece of functionality will rise as the app grows. Eventually it will reach a point where the time of implementing a feature will not be determined by the complexity of the feature but by the complexity of the app. All features, little or big, will take a lot of time to complete because the dominant cost is the testing, not the implementation.<br /><br />If I decide not to (manually) test every new increment of functionality I am at the risk of not detecting bugs the moment they are introduced. This incurs significantly longer times for fixing these bugs when they are eventually detected.<br /><br />Of course, at the beginning everything looked fine. However, after just a few hours the signs of a technical debt became evident: the code grew messy. I was afraid to refactor. I felt that I am coding in "extreme cautious" mode. I am no longer in control of my code. I could not move it in the direction that I wanted.<br /><br />The amazing thing is the short distance that you have to walk in order for this effect to kick in. It usually took less than half a day for me to realize that manual testing slows me down.<br /><br />Will I do things differently in the future? Yes. I will start with a <span style="font-style: italic;">testable</span> <span style="font-style: italic;">skeleton </span>of the app before adding any substantial behavior to it. The "start-from-a-skeleton" practice is already quite popular. The emphasize here is two fold:<br /><ul><li>It should be a <span style="font-style: italic;">testable</span> skeleton. This will let you build testability into the system from the very start.<br /></li><li>The extra cost of a testable skeleton pays off <span style="font-style: italic;">even in extra-small</span> projects.<br /></li></ul>A thorough treatment of this topic is given in chapter Four of <a href="http://www.growing-object-oriented-software.com/">GOOS</a> (by <a href="http://www.m3p.co.uk/">Steve Freeman</a> and <a href="http://www.natpryce.com/">Nat Pryce</a>) which talks about "Kick-Starting the Test-Driven Cycle". In particular, they argue that the goal of every first iteration should be to "Test a Walking Skeleton". Go read it.Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com3tag:blogger.com,1999:blog-37274183.post-5573378754090614302010-08-17T22:39:00.005+03:002010-08-18T00:29:03.716+03:00I don't want to hear the "we-need-to-separate-tests-from-code" excuseMany programmers tend to place their unit tests in a dedicated source folder. I do it differently. In my projects, the unit-test of class SomeClass is called SomeClass_Tests and it is located in the very same folder as SomeClass.java.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__Z062ijpkY4/TGr4x5tQPaI/AAAAAAAAA7Q/k0hOjKVNtgg/s1600/IDE-2.PNG"><img style="cursor: pointer; width: 293px; height: 395px;" src="http://4.bp.blogspot.com/__Z062ijpkY4/TGr4x5tQPaI/AAAAAAAAA7Q/k0hOjKVNtgg/s400/IDE-2.PNG" alt="" id="BLOGGER_PHOTO_ID_5506487030601760162" border="0" /></a><br /><br /><br />This has all sort of benefits: I can instantly see if a class has a test. I can instantly jump from the test to the testee and vice-versa. I don't have to create two parallel hierarchies of folders. It is very unlikely that I will rename the production class but not its test. Renaming of a package affects both tests and production classes. etc. There is one word that summarizes these benefits: <span style="font-style: italic;">Locality</span>. Things that change together ought to be placed as close as possible.<br /><br />There are IDE plugins out there that provide similar capabilities over a project structure that has separate source folders. However, these plugins will not help you when you access your code not through your IDE (for instance, I often explore my code repository via a browser).<br /><br />But even more importantly, as I got more and more (test) infected I realized that I don't want to have this test-production separation. The tests are not something external that needs to be put away. Tests are a central piece of knowledge about my code. I want them to be near by. Think about it: Would you separate your Javadoc text from the class/method it is describing? Will you find it productive to write code in a language which dictates that fields are defined in one file and methods are defined in another file? (Actually, this is pretty much what happens in C++ ...).<br /><br />Of course not.<br /><br />The main difficulty is the packaging/deployment phase. I often heard the argument that "we need to have two separate folders because otherwise our deliverable (.jar/.war/...) will include both production code and testing code, and this is bad".<br /><br />Is it really bad? First, In many situations (web-apps anyone?) the size of the binary does not matter much. Second, in situations where the deliverable includes the source code, the tests can be quite handy as usage samples.<br /><br />If you're in a situation where these arguments do not hold, and you absolutely cannot place test code in your deliverable, then the remainder of this post is for you. <br /><br />I often said that it is not hard to write a program that will delete .class files of test classes. It requires some knowledge of bytecode inspection techniques which apparently is not very common. So, as a service to the Java community and for the common good, I cleared a few hours and wrote it. The result is <a href="http://github.com/imaman/class-wiper/downloads">class-wiper</a> (<a href="http://github.com/imaman/class-wiper">sources</a>) a command line utility that will recursively scan the given directories and will delete all .class files therein that are related to JUnit. <br /><br />Specifically, it will delete a class if either: (a) it mentions the @Test annotation; or (b) It uses directly or indirectly a class that mentions @Test. Your production code will never meet neither of these conditions. If you don't want test classes to reach your client you just need to invoke it from your build script, as follows:<br /><br /><pre><code> java -jar class-wiper <binary-dir1> <binary-dir2> ...</code></pre><br /><br />This software is provided absolutely for free. Use it anyway you like. Change it. Tweak it. Hack it. Sell it. Whatever. I only ask one simple thing: please stop saying that you need to place your tests in a separate directory because you don't have a way to prevent your tests from reaching the deliverable.Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com12tag:blogger.com,1999:blog-37274183.post-24325352691508705052010-08-06T09:36:00.015+03:002010-08-08T12:58:53.744+03:00Repeat after me: Immutable objects will not slow you downAs noted by <a href="http://codemonkeyism.com/generation-java-programming-style/">Stephan Schmidt</a> the advent of functional programming promotes the use of immutable objects even in non-functional languages. Immutable objects have many positive traits: they are safer, they throw less exception, they are not prone to problems of covariance, they prevent races when used in a multi-threaded settings, etc.<br /><br />The main (only?) down side of immutable object is the fact that they make it difficult to update the data in your program. This should not be a surprise. After all, if they are immutable then it only makes sense that they will not encourage mutations.<br /><br />Here is the general description of the problem: if x is an immutable object and x.f == y, and you want x.f to point at z, then you can't just set x.y to z. You need to create a new object, x', that is identical to x in all aspects except that x'.f == z. You then need to find all references to x and reroute them to x'.<br /><br />In certain cases (such as: many object holding references to x) this rerouting may be quite hard and error prone. Also, if the objects pointing at x are immutable themselves, then further updates need to be carried out across your data structure. These difficulties are the reason why most C/C++/Java/C# folks tend to prefer designs with mutable objects, despite the benefits of immutability.<br /><br />Side note: functional languages usually offer powerful pattern matching mechanisms that simplify the process of updating (immutable) data structures.<br /><br />Anyway, even in cases where correctly rerouting references is not that bigger problem, developers are sometimes reluctant to use immutability due to performance issues. The argument goes as follows: <span style="font-style: italic;">If I make this class immutable, </span><span style="font-style: italic;">I will have to allocate a new object </span><span style="font-style: italic;">every time I update one of the fields. This extra allocation will slow down my program.<br /></span><br />This argument is, by and large, incorrect.<br /><br /><span style="font-weight: bold;">Reason #1</span>. Most of the code you're writing will not affect the performance of your program. There is no point in optimizing your code prematurely.<br /><br /><span style="font-weight: bold;">Reason #2</span>. Mutable objects lead to defensive getters/setters. That is, If a method returns a field pointing at a mutable object it usually needs to create a copy of it to prevent the caller from breaking the invariants of the class. This means that an object will be duplicated even if the caller just wants to read its content. Given that reads are more frequent than writes we actually have that <span style="font-style: italic;">immutable objects yield faster programs</span> simply because they do not imply object copying with every get/set operation.<br /><br />I experienced this effect a few years ago when I had to optimize CPU-intensive code that dealt with queries over in-memory tables. The profiler indicated that most of the time my program was busy duplicating rows of these tables which, usually, were not mutated at all. Switching into an immutable design resulted in a significant performance boost.<br /><br />Still not convinced? Maybe this will help you. When Josh Bloch discusses API design decisions that create performance problems, he gives as an example Java's <a href="http://download-llnw.oracle.com/javase/6/docs/api/java/awt/Dimension.html">Dimension</a> class which is---wait for it---<a href="http://download-llnw.oracle.com/javase/6/docs/api/java/awt/Dimension.html#setSize%28double,%20double%29">mutable</a>. Specifically, each call to <a href="http://download.oracle.com/javase/6/docs/api/java/awt/Component.html#getSize%28%29">Component.getSize()</a> must allocate a new Dimension object which leads to numerous needless allocations. Further details are given in Josh's excellent lecture, <a href="http://www.infoq.com/presentations/effective-api-design"><span>How to Design a Good API & Why it Matters</span></a> (Immutability of class Dimension is discussed ~ 32 min. into the talk).Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com8tag:blogger.com,1999:blog-37274183.post-22250846224204733392010-07-22T14:07:00.002+03:002010-07-22T15:04:07.890+03:00So You Want to Practice your Code Reviewing Skills? - SummaryEarlier this week I published <a href="http://javadots.blogspot.com/2010/07/so-you-want-to-practive-code-reviewing.html"></a><a href="http://javadots.blogspot.com/2010/07/so-you-want-to-practive-code-reviewing.html">So You Want to Practice your Code Reviewing Skills?</a> which challenged the readers to find bugs in ~ 150 LOC.<br /><br /><br />The replies were very interesting. Here's a summary<br /><br /><span style="font-weight: bold;">Concurrency/Distribution/Singleton</span><br /><ul><li>instance() method is not synchronized</li><li>sessionCounter needs to be volatile/guarded by synchronization (in visitorCount())</li><li>(Mutable) Singeltons cannot be distributed. is If there is several instance of the webapp running, not all values will be counted because several counter will exist and not be synchronized from JVM to JVM. </li><li>The singleton implementation is broken. See, for instance, <a href="http://www.oreillynet.com/onjava/blog/2007/01/singletons_and_lazy_loading.html">this article</a>.</li></ul><span style="font-weight: bold;">General</span><br /><ul><li>DataBaseHelperget() method may return the empty string ("") if no rows are in the table, and the singleton only expects a valid number or null, which will cause a NumberFormatException</li><li>the counter may roll over. For a 7 year old web app this is perfectly possible.</li><li>I consider constructs like this catch(Exception e) { sLogger.error("", e); } to be a bug.<br /></li></ul><span style="font-weight: bold;">JDBC</span><br /><ul><li>The DB change isn't being committed so it has to rely on the underlying driver's behavior.</li><li>The insert statement doesn't explicitly defines column names, which is susceptible to failure if the order of rows in the DB table changes.</li><li>The update statement updates the row with param = 'SESSION_COUNT' although the insert inserts 'session_count'. Usually this would not work without special set-up in the db and/or connection.</li><li>generateResult() does not close the ResultSet object. Note that the originating Statement object is hidden inside the DataBase.performSqlQuery() method (whose code is not given) so Statement also remains open. The closing of these two objects is deferred to the GC. <br /></li></ul><span style="font-weight: bold;">Final thoughts</span><br /><ul><li>Do not use singletons. A singleton is a smell that indicates the need for dependency injection.<br /></li><li>In general, service objects in web-apps should not maintain state in (plain-old-Java) fields. If you need to have some state, write it to the DB. That's the only way to share state in a distributed settings.</li><li>The nastiest bug of all: the combination of exceptions being silently absorbed, and DataBaseHelper.get() returning an empty string ("") leads to a situation where sessionCounter stays zero, which will reset the visitor count at the DB to 100, thereby loosing the (correct) visitor count.<br /><br />Here's the scenario: In generateResult() an SqlException if fired (let's say due to a temporary network problem). It is silently caught by generateResult() which then returns an empty list. get() will return an empty string, which will yield a NumberFormatException in reloadParamsFromDB(), which - again - is silently ignored.<br />Therefore, no assignment to sessionCounter is taking place, so it retains its default value, zero. At the 100th call to addSession() sessionCounter current value (100) will be written to the DB.<br /><br />Solution: add to the value at the DB instead of writing to it.</li></ul>Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com0tag:blogger.com,1999:blog-37274183.post-5932798997126072002010-07-17T11:54:00.008+03:002010-07-21T08:49:37.864+03:00So You Want to Practice your Code Reviewing Skills?The code below is taken from a real web-app that has been up and running for > 7 years. This specific fragment is realizing the visitor count functionality: keeping track on the number of visitors hitting the site. Each time a new session is created SiteInfo.instance().addSession() is called. <br /><br />Your task (should you choose to accept it...) is to find bugs in this code. In other words: will the visitor count, (as reported by SiteInfo.visitorCount()) always be correct? If not, what values can be seen there? How can we fix the code?<br /><br />Please ignore design issues (I don't like the singleton anymore than you do), or technological issues, such as: "well you should just rewrite the whole thing with Spring + Hibernate". Just examine the code-as is and try to determine if/where can it fail.<br /><br /><pre><code><br /><br />public class SiteInfo {<br /> <br /> private static SiteInfo inst;<br /> <br /> private SiteInfo() {<br /> //<br /> };<br /> <br /> // This is a singleton (Yak!)<br /> public static SiteInfo instance() {<br /> if(inst == null) <br /> inst = new SiteInfo();<br /> return inst;<br /> }<br /><br /> private int sessionCounter = 0; <br /> private static final String INIT = "100";<br /> <br /> public int visitorCount() {<br /> return sessionCounter;<br /> }<br /> <br /> public synchronized void reloadParamsFromDB() {<br /> Connection con = null;<br /> ConnectionPool pool = null;<br /> try {<br /><br /> pool = ConnectionPoolFactory.getInstance();<br /> con = pool.getConnection();<br /><br /> String countStr = DataBaseHelper.get(con, "config", "value",<br /> "param", "session_count"); <br /> if (countStr == null) {<br /> String q = "INSERT INTO config VALUES ('session_count','" + INIT + "')";<br /> try {<br /> runCommand(q, con);<br /> countStr = INIT;<br /> }<br /> catch (Exception e) {<br /> log.error("", e);<br /> }<br /> }<br /><br /> sessionCounter = Integer.parseInt(countStr);<br /> }<br /> catch (Exception e) {<br /> log.error("", e);<br /> }<br /> finally {<br /> ConnectionPoolFactory.release(pool, con);<br /> }<br /> }<br /> <br /> private void runCommand(String q, Connection con) throws Exception {<br /> Statement stmt = con.createStatement();<br /> try {<br /> stmt.executeUpdate(q); <br /> }<br /> finally {<br /> stmt.close();<br /> }<br /> }<br /> <br /> public synchronized void addSession() {<br /> sessionCounter++;<br /> if(sessionCounter % 100 != 0)<br /> return;<br /><br /> Connection con = ConnectionPoolFactory.getInstance().getConnection();<br /> Statement stmt = null;<br /> try {<br /> stmt = con.createStatement();<br /> String sql = "UPDATE config SET value='" + sessionCounter <br /> + "' WHERE param='SESSION_COUNT'";<br /> stmt.execute(sql);<br /> }<br /> catch (Exception ex) {<br /> log.error("", ex);<br /> }<br /> finally {<br /> try {<br /> if(stmt != null)<br /> stmt.close();<br /> ConnectionPoolFactory.release(con);<br /> }<br /> catch(SQLException e) {<br /> log.error("", e);<br /> }<br /> }<br /> } <br />}<br /><br />public class DataBaseHelper {<br /> public static String get(Connection con, String table, <br /> String columnA, String columnB, String columnAValue) {<br /> String result = "";<br /> String sqlQuery = "SELECT " + columnB + " from " + table<br /> + " WHERE " + columnA + " = '" + columnAValue + "'";<br /><br /> // Run the query. Translate the result set into a list of maps.<br /> // Each map corresponds to a single row in the ResultSet<br /> List<Map<Object,Object>> rows = generateResult(sqlQuery, con);<br /> try {<br /> Iterator<Map<Object,Object>> iter = rows.iterator();<br /> if(iter.hasNext()) {<br /> Map<Object,Object> m = iter.next();<br /> <br /> result = (String) (m.get(columnB));<br /> if (result == null)<br /> return null;<br /> }<br /> } <br /> catch (Exception e) {<br /> return null;<br /> }<br /> return result;<br /> } <br /><br /> public static List<Map<Object,Object>> generateResult(String query, Connection con) {<br /> List<Map<Object,Object>> result = new ArrayList<Map<Object,Object>>();<br /> try {<br /> ResultSet resultSet = DataBase.performSqlQuery(query, con);<br /> if(resultSet == null)<br /> throw new Exception("Impossible"); <br /> <br /> ResultSetMetaData resultSetMetaData = resultSet.getMetaData(); <br /> int columnCount = resultSetMetaData.getColumnCount();<br /> <br /> String[] columnNames = new String[columnCount];<br /> for(int i = 0; i < columnCount; i++)<br /> columnNames[i] = resultSetMetaData.getColumnName(i + 1);<br /> <br /> while(resultSet.next()) {<br /> Map<Object,Object> map = new HashMap<Object,Object>();<br /> for(int i = 0; i < columnCount; i++) {<br /> String col = columnNames[i];<br /> map.put(col, resultSet.getString(i + 1));<br /> }<br /><br /> result.add(map);<br /> }<br /> }<br /> catch(Exception e) {<br /> sLogger.error("", e);<br /> }<br /><br /> return result;<br /> }<br />}<br /></code></pre>Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com7tag:blogger.com,1999:blog-37274183.post-51553180949835728002010-06-21T14:47:00.002+03:002010-06-21T15:54:46.628+03:00JUnit Rules!Rules are a simple, yet amazingly powerful, mechanism introduced in <a href="http://junit.org/">JUnit</a> version 4.7. They allow developers to easily customize JUnit's behavior by exposing meta information regarding the currently executing test. This post provides a straightforward example for writing a custom rule that augments JUnit with some useful functionality.<br /><br />My subject class is IntSet: A set of integers implementing the standard operations of add(), remove(), contains(), clear() in O(1) time. To make this performance guarantee the set needs to know (in advance) the range of the values (min..max) and its size limit (number of elements that it will accommodate).<br /><br />All in all, IntSet looks something like this:<br /><pre><code><br />public class IntSet {<br /> ... // Some private fields<br /> public IntSet(int limit, int min, int max) { ... }<br /> public int size() { ... }<br /> public boolean contains(int n) { ... }<br /> public void add(int n) { ... }<br /> public void remove(int n) { ... }<br />}<br /></code></pre><br /><br />One of my unit tests specifies the behavior of IntSet when its size limit is reached. If I'm only interested in the type of the exception I can specify it via the expected attribute of the @Test annotation:<br /><br /><pre><code><br /> @Test(expected=IllegalStateException.class)<br /> public void shouldNotExceedCapacity() {<br /> IntSet s = new IntSet(2, -10, 100); // Set size limit to 2<br /> s.add(30);<br /> s.add(40);<br /> s.add(50); // Insertion of the 3rd element should fail<br /> }<br /></code></pre><br /><br />There are two drawbacks with this test. First, It only asserts the type of the an exception. It does not check the error message specified for the exception. Second, it does not assert that the exception was triggered by the last add() call. In other words, if we have a bug and the 2nd add() call is failing - with the same type of exception - the test will still pass.<br /><br />To overcome this limitation we want to check the error message of the thrown exception. Specifically, we want to verify that the execution of the method fires an exception whose error message is "Cannot insert '50' - The set is full". Clearly, the chances of such an exception being thrown by the 2nd call are pretty slim.<br /><br />Extending JUnit in such a manner is pretty easy thanks to the rules mechanism:<br /><br /><pre><code><br />public class IntSet_Tests {<br /><br /> @Retention(RetentionPolicy.RUNTIME)<br /> @Target(ElementType.METHOD)<br /> @interface Throwing {<br /> public String value();<br /> }<br /> <br /> @Rule<br /> public MethodRule mr = new MethodRule()<br /> {<br /> @Override<br /> public Statement apply(final Statement base, FrameworkMethod m, Object o) {<br /> Throwing t = m.getAnnotation(Throwing.class);<br /> if(t == null)<br /> return base;<br /> <br /> final String message = t.value();<br /> return new Statement() {<br /> <br /> @Override<br /> public void evaluate() throws Throwable {<br /> try {<br /> base.evaluate();<br /> fail("No exception was thrown");<br /> }<br /> catch(AssertionError e) {<br /> throw e;<br /> }<br /> catch(Exception e) {<br /> assertEquals("Incorrect exception message", message, e.getMessage());<br /> }<br /> }<br /> };<br /> } <br /> };<br /><br /> // All sort of @Test methods ...<br /><br /><br /> // And now, a method that asserts the error message<br /> @Throwing("Cannot insert '50' - The set is full")<br /> @Test<br /> public void shouldNotExceedCapacity() {<br /> IntSet s = new IntSet(2, -10, 100);<br /> s.add(30);<br /> s.add(40);<br /> s.add(50);<br /> }<br />}<br /></code></pre><br /><br />First we define a new annotation, @Throwing. Then we define a field annotated with @Rule to provide the custom handling of this annotation. Finally, we annotate the shouldNotExceedCapacity() method with a <code>@Throwing("Cannot insert '50' - The set is full")</code> annotation.<br /><br />The mechanism works as follows: before each test method is run, JUnit creates a <a href="http://kentbeck.github.com/junit/javadoc/latest/org/junit/runners/model/Statement.html">Statement</a> object which is merely a command object through which the acutal method can be invoked. JUnit passes this object along with a <a href="http://kentbeck.github.com/junit/javadoc/latest/org/junit/runners/model/FrameworkMethod.html">FrameworkMethod</a> object (a wrapper of Java's Method) and the unit test instance to all @Rule fields defined at the test class.<br /><br />A @Rule field must be public and must implement the <a href="http://kentbeck.github.com/junit/javadoc/latest/org/junit/rules/MethodRule.html">MethodRule</a> interface (of course, you can instead extend one of several classes conveniently defined by JUnit). In the apply() method, above, we create a new Statement object that wraps the original one. The new evaluate() method will check that if an exception is thrown its message matches the text specified by the @Throwing annotation attached to the method.<br /><br />Obviously, there are other ways to do that. For instance, one can use the <a href="http://kentbeck.github.com/junit/javadoc/latest/org/junit/rules/ExpectedException.html">ExpectedException</a> class (a predefined JUnit rule) to achieve a similar effect. The purpose of this post is to surface the (mighty) powers of JUnit meta programming.Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com5tag:blogger.com,1999:blog-37274183.post-58653426196495342662010-06-13T14:25:00.005+03:002010-06-13T16:43:17.268+03:00Axiom: InstabilityI had already blogged about the <a href="http://javadots.blogspot.com/2008/08/axioms-of-programming.html">Axioms of programming</a>: the fundamental rules that govern the development of every piece of (substantial) software. In this post I want to focus to on the <font style="font-style: italic;">Instability Axiom</font>:<br /><br /><div style="text-align: center;"><span style="font-style: italic;">The external behavior of a component will need to change over time</span><br /></div><br />Here's a real story. I once was involved with a very a small project, let's call it the PQR project: three people working part time for three weeks, putting together an HTTP server a web client and a GUI client - all are very simple. During these three weeks we were also learning some new technologies so actual coding time (of all developers combined) was about 20-25 days.<br /><br />During these three weeks two important changes were applied to PQR's specification: <ul><li>The technology with which the GUI client was implemented had to be changed. Instead of implementing it over Tech.A we had to switch to Tech.B.<br /><br /></li><li>The initial specs defined the data that should be persisted by the server. As we were playing with the intermediate versions of the project, we came to realize that a descent user experience requires that additional information will be persisted.<br /></li></ul><br />The main point of this post is not if/how we managed to support these changes. The point is that even in small projects <span style="font-style: italic;">specs are not stable</span>. We were not successful in defining the project's goals for a three week period in a project which is as simple as industrial projects get. Of course, If the project were more complicated (more people, wider scope) then the instability was likely to be even higher.<br /><br />This example indicates that a "fire and forget" type of development (AKA: "divide and conquer" ) where one breaks down the desired functionality into a few large pieces, assigns each piece to a programmer, and then lets each programmer work on his task in isolation of his peers (until an "integration" milestone is approaching) is broken.<br /><br />First, external forces will change the specs, thus affecting the assigned tasks. In the PQR project, the change in client technology was due to some external factors (business/marketing constraints). Even though the initial specs were examined and audited by several layers of approvals, no one had predicted this change.<br /><br />Second, feedback from working early versions of the product (even with partial functionality) will change our understanding of the product and its desired capabilities. In PQR, the change regarding which-information-should-be-persisted was driven by experimentation with early versions.<br /><br />If we had taken a Fire-and-Forget approach then our ability to respond to the first change were very limited as every team member was in the middle of his large task. Also, by the time a first working version were available, very little time was left to implement significant changes.<br /><br />Bottom line: Software is unstable. Breaking the effort into tiny tasks with frequent integration points (I am speaking about granularity of hours not weeks) is an excellent way to cope with this inherent instability.Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com2tag:blogger.com,1999:blog-37274183.post-37181388727484781522010-02-25T17:32:00.012+02:002010-03-07T07:48:26.754+02:00Programmers are Decision MakersSo yesterday I bumped into this bug: a listener of a tree object (not Swing's JTree. A tree with nodes and labeled edges, a-la Data Structures 101) was referencing a null object:<br /><pre><code><br />public class Auditor implements TreeListener {<br /><br /> private Map<String,Date> map = new HashMap<String,Date>();<br /><br /> public void nodeAdded(Node n) {<br /> map.put(n.id(), new Date());<br /> }<br /><br /> public void nodeRemoved(Node n) {<br /> Date d = map.get(n.id());<br /> String s = d.toString(); // <-- NPE is here!!<br /> map.removeKey(n.id());<br /><br /> // some other things ...<br /> }<br />}<br /></code></pre>My unit tests told me that the Auditor and Tree class are working fine - the tree fires the correct events and the Auditor reacts correctly. Of course, a Green bar does not guarantee "no bugs" so I double checked the code and it seemed fine.<br /><br />Indeed the problem was elsewhere. Turns out that a bug in my app caused each listener to be registered twice. Auditor was not expecting to be called twice for each event, hence the NPE.<br /><br />So I fixed the bug. Then I went back to the addListener() method of the Tree class. It is a very simple method:<br /><br /><pre><code>public class Tree {<br /><br /> private List<TreeListener> listeners<br /> = new ArrayList<TreeListener>();<br /><br /> public void addListener(TreeListener arg) {<br /> listeners.add(arg);<br /> }<br /><br /> // Additional methods ...<br />}<br /></code></pre><br />Looking at the code I tried to think if this method should be changed in order to prevent future occurrences of this bug. As I was thinking about it I realized that this simple method is an excellent illustration to one software's most fundamental truths:<br /><br /><div style="text-align: center;"><span style="font-style: italic;">Programming is about making (design) decisions.</span><br /></div><br />I am not the first one to say this (see <span class="fn">Joakim Holm's "<a href="http://jockeholm.wordpress.com/2010/01/29/programming-is-all-design/">Programming is all Design</a>" or </span><a href="http://jockeholm.wordpress.com/2010/01/29/programming-is-all-design/"></a><a href="http://alistair.cockburn.us/Foundations+for+Software+Engineering">Alistair Cockburn</a><span class="fn">). Here's the (probably partial) list of decision that a programmer has to make when writing a one-liner method that should simply add a listener to a list.<br /></span><br /><br /><ol><li>Should the listeners field be private? Maybe we want subclasses to manipulate/inspect it in some way, which calls for <code>protected</code> visibility.<br /><br /></li><li>What is the order of notification? Should we use a "first-registered first-notified" policy? or maybe "last-registered first-notified". Is order important at all? If not then maybe we would like to force the application not to depend on the order by random shuffling?<br /><br /></li><li>Can a listener be registered with more than one Tree object? If so, then the listener interface should probably specify the originating tree, not just the node<br /><br /></li><li>Can a listener be registered more than once with a single Tree object? Usually the answer is no, but there are scenarios where multiple registration does make sense.<br /><br /></li><li>Assuming each listener may be registered exactly once, how do we deal with multiple registrations?<br /><ul><li>Throw an exception?</li><li>A standard Java assertion? Could be disabled which may be good or bad depending on context.</li><li>Throw an <code>AssertionError</code>? Has a more dramatic effect than a plain Exception. Also will be reported by JUnit as a failure rather than an error. Again, may be either good or bad.</li><li>Silently ignore. Return from the method without adding the listener. This seems very natural but it has the drawback that it hides the problem. If I choose to silently ignore then I will get no notification about future problems. How about logging?</li><li>Return a Boolean value indicating whether the listener was already registered. Puts the responsibility on the client code to check this value. Will not always happen.<br /><br /></li></ul> </li><li>Do I need to provide some thread protection?<br /><ul><li>Define the method as synchronized?</li><li>Define the listeners field as a ConcurrentLinkedList?</li></ul><br /></li><li>How should this list of listeners interact with the Garbage Collector? Should a listener that is only accessible from this list be collectible (by storing it as a <code>WeakReference</code>)? A "No" answer puts additional burden on client code: must remove listeners from the Tree object when they are no longer needed. If listeners are dynamically added as the app is running this may become a big problem.<br /><br />Note that choosing weak references is not always a good idea. Some listeners are only accessible from the listened-to object. Take for example a listener that inspects the tree and updates the title of the main window. It is created, pushed onto the listeners list and all other traces to it are lost. A weak reference will make such a listener disappear with the very first collection cycle.<br /><br /></li><li>Do I want to refactor the whole "listeners" concern into a dedicated strategy class. This will improve testability and decoupling.</li></ol><br />As I said this is a partial list. Point is simple: a programming task requires much more decision (and mental energy) that what initially seems. In other words: <span style="font-style: italic;">If you want to design everything upfront you'll end up programming upfront</span> but without the assistance of tools such as IDE, Unit tests, Refactoring, and the likes. Good luck.Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com1tag:blogger.com,1999:blog-37274183.post-54629937391687185892010-02-09T16:07:00.002+02:002010-02-09T16:31:08.178+02:00Katacast: String Calculator – GroovyThe original idea behind Code Katas was that of a small programming exercise whose solution often includes some interesting challenge. In katacasts.com<a title="Corey Haines" href="http://www.coreyhaines.com/"> Corey Haines</a> further <a href="http://katas.softwarecraftsmanship.org/?page_id=2">explains</a> that:<br /><br /><blockquote>Over time, the concept of Katas grew from a problem to solve to a solution to practice. Uncle Bob Martin (among others) began talking about the idea of practicing the solution to a kata until the steps and keystrokes became like second nature, and you could do them without thinking.<br /></blockquote><br /><br />In TDD Katas the focus in on doing the TDD cycle, Red-Green-Refactor, right. Corey had recently published a screencast where yours truly solves the <a href="http://osherove.com/tdd-kata-1/">StringCalculator</a> TDD Kata in Groovy. It illustrates some points about TDDing (like "Fake it till you make it" or "triangulation") in a very clear way.<br /><br />So, If you feel like you want to better understand TDD you can <a href="http://katas.softwarecraftsmanship.org/?p=145">watch the Kata</a> on Corey's site. An explanation of the different moves is given in the accompanying text.<br /><br />Another recommendation is to watch <a href="http://blog.extracheese.org/">Gary Bernhardt</a>'s screencast where he <a href="http://blog.extracheese.org/2009/11/refactoring_a_cyclomatic_complexity_script.html">refactors cyclomatic complexity code</a> in Python.<br /><br />Enjoy.Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com0tag:blogger.com,1999:blog-37274183.post-67373087578465060422010-02-04T15:58:00.002+02:002010-02-04T16:03:29.126+02:00Swing - Tabs to SpacesHow do you make a swing text component (JTextEditor, JEditorPane, etc.) to insert spaces whenever the user hits the "Tab" key?<br /><br />The answer is below. It is based on setting a document filter on the component's document object. The (static) install() method can do all the setup for you.<br /><br /><pre><code>package com.blogspot.javadots;<br /><br />import javax.swing.text.AbstractDocument;<br />import javax.swing.text.AttributeSet;<br />import javax.swing.text.BadLocationException;<br />import javax.swing.text.DocumentFilter;<br />import javax.swing.text.JTextComponent;<br /><br />public class TabToSpaceFilter extends DocumentFilter {<br /> <br /> private String spaces = "";<br /> private JTextComponent textComponent;<br /> <br /> public TabToSpaceFilter(int tabSize, JTextComponent tc) {<br /> textComponent = tc;<br /> for(int i = 0; i < tabSize; ++i)<br /> spaces += " "; <br /> }<br /> <br /> @Override<br /> public void insertString(FilterBypass fb, int offset, String text,<br /> AttributeSet attr) throws BadLocationException {<br /> super.insertString(fb, offset, translate(offset, text), attr);<br /> }<br /><br /> @Override<br /> public void replace(FilterBypass fb, int offset, int length,<br /> String text, AttributeSet attr) throws BadLocationException {<br /> super.replace(fb, offset, length, translate(offset, text), attr);<br /> }<br /><br /> private String translate(int offset, String s) {<br /> int col = columnOf(offset);<br /> <br /> StringBuilder sb = new StringBuilder();<br /> int top = s.length();<br /> for(int i = 0; i < top; ++i, ++col) {<br /> char c = s.charAt(i);<br /> if(c == '\t') <br /> sb.append(spaces.substring(col % spaces.length()));<br /> else<br /> sb.append(c);<br /> } <br /> <br /> return sb.toString();<br /> }<br /><br /> private int columnOf(int i) {<br /> String s = textComponent.getText();<br /> if(i == 0)<br /> return 0;<br /> int prev = s.lastIndexOf("\n", i-1);<br /> if(prev < 0)<br /> return i;<br /> <br /> return (i-prev)-1;<br /> }<br /> <br /> public static void install(int tabSize, JTextComponent area) {<br /> AbstractDocument ad = (AbstractDocument) area.getDocument();<br /> ad.setDocumentFilter(new TabToSpaceFilter(tabSize, area));<br /> }<br />}<br /></code></pre>Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com11tag:blogger.com,1999:blog-37274183.post-40486056862196353072010-01-05T12:54:00.002+02:002010-01-05T12:58:22.229+02:00How JUnit's assertArrayEquals() should be implementedI find myself writing this assertion method at (almost) any project where #tests > K where K is typically 10. In other words: Every project.<br /><br /><br /><pre><code><br /> public static void arrays(Object[] actual, Object... expected) {<br /> for(int i = 0; i < Math.min(actual.length, expected.length); ++i)<br /> Assert.assertEquals("Array mismatch at index " + i + ":", expected[i],<br /> actual[i]);<br /> <br /> Assert.assertEquals("Array length mismatch", expected.length,<br /> actual.length);<br /> }<br /></code></pre>Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com2tag:blogger.com,1999:blog-37274183.post-80441531109923761842009-12-18T15:59:00.006+02:002009-12-29T09:30:30.704+02:00Top Five Bugs of My Career - SolvedYes, I know. A long time has passed since the "<a href="http://javadots.blogspot.com/2009/10/top-five-bugs-of-my-career.html">top five bugs</a>" post, leaving these bugs waiting to be resolved (to my defense let me say this is not intentional between my day job and me writing my Ph.D. dissertation I have very little energy left for blogging).<br /><br />Anyway, the long wait is over. It is now solution time.<br /><br /><span style="font-weight: bold;">#5: Only guests are welcome - 2008, Javascript</span><br /><br />The night before I did some refactoring. I had two methods, let's call them f1() and f2(), both taking two parameters and doing almost the same thing. So I consolidated them into one method, f(). I then searched all call sites of f1() and f2() and changed them to call f(). One of the f2() calls passed null as the second parameter, however f() was built mainly on the f1() code so it didn't know how to handle nulls.<br /><br />This was frustrating because there were very few f2() calls and I went over them manually. Actually, at some point the null was just there in front of my eyes. But at that moment I didn't think that f() cannot digest nulls. I didn't bother to write unit tests for the Javascript part of the project, so I had no way to verify my refactoring. #Lazy<br /><br /><span style="font-weight: bold;">#4: The unimaginably slow load - 2005, Java</span><br /><br />When I wrote the code that saves the data structure into a file (last step of the import) I chose the simplest thing that could possibly work: serialization. Later, I added a publish/subscribe functionality to the data structure, thereby allowing GUI objects to respond to changes in the data.<br /><br />Guess what happens when you serialize a data structure that has a reference to a listener that is an inner class of the app's Top-level JFrame object: you serialize every piece of runtime data your program holds. Everything. Instead of the saving a minimalistic storage-oriented data structure you suddenly save caches, in-memory indexing tables, the works.<br /><br />Unfortunately, all these objects were all Serializable so I didn't get any exceptions in the process, just a very slow save/load process.<br /><br /><span style="font-weight: bold;">#3: Modal smiles, Modeless cries - 2001, C</span><br /><br />This is a C-specific issue. The error messages were stored in an array of structs where each struct represents a single error. There was an upper limit on the number of errors so I declared an array of 1,000 structs (which was well beyond the limit) . In order to avoid the hassle of dynamic memory management this array was actually a local, stack stored, variable.<br /><br />After filling the array the code pops-up the Modal window that shows the errors by issuing a DialogBox() call. This call will return only after the window is closed. Thus, as long as the window was open execution was still sitting there at my function, and my array was safe on stack.<br /><br />A Modeless window is different. The call that creates a modeless window, CreateDialog(), returns immediately while the window is still open. Execution then continues, reaches the end of my function and returns to the caller. At this point, the stack is unwound and the array vanishes into thin air. When the user clicks on an error the event handler tries to access the array (via a pointer) but the array is no longer there. It is an <a href="http://www.mtholyoke.edu/%7Eebarnes/python/dead-parrot.htm">ex-array</a>.<br /><br /><span style="font-weight: bold;">#2: The out-of-nowhere crash - 2002, C</span>++<br /><br />Again, we are in the no-garbage collection territory. In C++ you constantly write destructors that take care of releasing the resources that the object acquired. This is a safe way to avoid leaks.<br /><br />What happens when you have a bug in a destructor (e.g.: null pointer error)? Right. the program crashes.<br /><br />When are destructors of local variables called? At the end of the scope. Literally. At the curly brace character closing the scope.<br /><br />So there you have it: the program crashes when it reaches the curly braces after the "b = true". The assignment itself went fine. The destructor was the problem. My IDE back then was not smart enough to treat closing braces as a statement. It treated it as part of the "b = true" assignment thereby misleading me to think the assignment failed.<br /><br /><span style="font-weight: bold;">#1: The memory monster - 2004, C#</span> <span style="font-weight: bold;"><br /></span><br />Actually, this bug is very simple once you see the code. It is my #1 due to the long time it took to track it down. Let's take another look at the code:<br /><br /><pre><code>for(int i = 0; i < rows.Length; ++i)<br />if(rows[i].isOutOfView)<br /> rows.Remove(i);<br /></code></pre><br />If the isOutOfView property is true we remove the current element from the collection. Let's play with i=4. The if() is true, we call rows.Remove(4), we increase i's value to 5 and start the next pass. Alas, the rows.Remove(4) call moved every element one position towards the beginning: the element at position 5 is now in position 4. At the next pass when i=5 we examine the element that used to be at position 6.<br /><br />Net result: we never checked the element at position 5. Thus, some of the elements that were needed to be removed from the collection were not removed. Later, the isOutOfView property of these elements were reset back to false. Overtime they accumulated until the heap collapsed.<br /><br />That's it. Hope you enjoyed this account. Other bug stories will be happily acknowledged.Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com0tag:blogger.com,1999:blog-37274183.post-49630762288949092532009-10-20T12:44:00.003+02:002009-10-20T15:00:00.031+02:00Write only Fields ?!Java's <a href="http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/tree/MutableTreeNode.html">MutableTreeNode</a> offers a <a href="http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/tree/MutableTreeNode.html#setUserObject%28java.lang.Object%29">setUserObject(Object)</a> method. Its natural counterpart, the <a href="http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/tree/DefaultMutableTreeNode.html#getUserObject%28%29">getUserObject()</a> method is defined only by the implementing subclass <a href="http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/tree/DefaultMutableTreeNode.html">DefaultMutableTreeNode</a>.<br /><br />This means that whenever your logic needs to work with the data that is associated with a tree node, it needs to downcast not to the interface, but - wait for it - to the actual implementation. This counters a fundamental engineering principle that Java is often trying to promote: interfaces over implementation.<br /><br />Moreover, offering a setter without a getter suggests that someone in Sun thought that it might be useful to have a variable that can be written-to but not read-from. This makes as much sense as placing 'something' in a safety deposit box and then throwing away all keys. Why would you want to do that? You might just as well throw away that 'something'. Either way, you'll never see it again.<br /><br />Done Ranting.Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com0tag:blogger.com,1999:blog-37274183.post-31678968175203043952009-10-05T00:41:00.022+02:002009-10-13T17:50:11.334+02:00Top Five Bugs of My CareerThis time, I thought to take a different angle. Instead of reasoning about software I'll just write about specific acts of programming in specific programs. More precisely, I want to write about specific bugs that I had the (mis) pleasure to track down.<br /><br />I took my first full-time programming job ten years ago, almost to the day. During this period I introduced and solved many bugs (Hopefully the difference between #introduced and #solved is not very large). My criteria for choosing which bugs will make it into this list is that of <span style="font-style: italic;">memorability</span> - I chose the bugs that I remember most clearly. When discussion bugs, memorability is a key factor. The more painful the bug the greater the impact it will leave in your memory. Thus, in some sense, I am about to list my most painful bugs from the last decade.<br /><br />To make things interesting, this post will disclose (mostly) the descriptions of the bugs. The cause/solution will be disclosed in the next post. This will give you programmer's mind something to chew on for a few days. For the same reason I also (occasionally) omitted pieces of information whenever I felt that their inclusion in the bug description will make the solution too obvious.<br /><br /><span style="font-weight: bold;">#5: Only guests are welcome - 2008, Javascript</span><br /><br />So my partner and myself are about to demo a web app which we quickly prototyped in a couple of weeks. It is an on-line discussion system. Buzzwords used: database, web-server, Ajax, CSS. We also had a decent suite of tests.<br /><br />It is 8:45am. The demo will start in 15 minutes. I am doing one last quick run of the demo. I log in as an anonymous guest. I browse through the pages and everything is fine. I try to log in as a user. Name: "Noga" (that's my dog's name). Password: "hithere". Oops. No response. Not even a "login failed" message.<br /><br />I know that login is doing some Ajax-ing so I quickly try to bypass the Ajax mechanism by manually forming a login URL containing my credentials. It works. So I now know that the defect is Ajax related but I don't have the time to rewrite the login page such that it will not use Ajax, let alone test it.<br /><br />8:55. The Anxiety-meter is screaming. We come up with a cunning solution. We start the demo with an already logged-in user (by secretly entering the login URL before the demo starts). We walk through all the pages. Then we log out and show that everything works for a guest user. Luckily, we are not asked to go back to a non-guest user. We are saved.<br /><br /><span style="font-weight: bold;"><br />#4: The unimaginably slow load - 2005, Java<br /><br /></span>I am working on a Java mass analysis tool. It is a program that digests jar files and classifies the classes therein based on a set of rules. The program is a console app which supports operations such as these:<br /><ul><li>import<jar-file><name>: import a new jar file into the system and give it the specified name<br /></name></jar-file></li><li>load<name>: load a previously imported jar-file into the memory</name></li><li>classify<out-file>: Run the classification rules on all currently loaded jars. Saves the results into the specified file (.csv)</out-file></li></ul>The import command scans the jar file and transforms it into my own data structure which is optimized for the type of analysis I need to do. The data structure is then saved to the file system. The load command reads the saved file back from into memory.<br /><br />For a few days I am working on adding new classification rules. When developing new rules I tend to work with a set of small Jars. This minimizes the classification time, thus shortening the feedback cycle. From time to time I find myself also changing the implementation of the underlying data structure (fixing bugs, adding new operations which are needed by the rules, etc.).<br /><br />At some point I decide that my new rules are complete and I put them to work on several real inputs: large zip files with > 100K classes. I notice that both the import and load commands run much slower than before. In fact, they run so slow that they wipe out all the benefits of having my own optimized data structures.<br /><span style="font-weight: bold;"><br /></span><span style="font-weight: bold;">#3: Modal smiles, Modeless cries - 2001, C<br /><br /></span>A Win32 Content editing app. User can add, edit, search for, browse through, and delete records. There is also a <span style="font-style: italic;">Record Checker</span> mechanism that scans all records and detects all sort of irregularities such as broken cross-record links, duplicate names, etc.<br /><br />The output of the checker is a list of error messages. The messages are displayed on a new window. Clicking on a message opens the corresponding record in the main window.<br /><br />Originally the error window was a <a href="http://www.usabilityfirst.com/glossary/main.cgi?function=display_term&term_id=320">modal</a> window: it disabled the main window. Clicking on an error closed the output window and reactivated the main window. We then decided that it makes much more sense to make this a <a href="http://www.usabilityfirst.com/glossary/main.cgi?function=display_term&term_id=321">modeless</a> one. I implemented this change and was astonished to see that the click functionality stopped working. Clicking on an error (in the modeless window) created an access violation and a total eclipse of the app. Remember, we are speaking about the C programming language, so expecting something as fancy as a stacktrace is out of the question.<br /><br /><br /><span style="font-weight: bold;">#2: The out-of-nowhere crash - 2002, C</span>++<br /><span style="font-weight: bold;"><br /></span>A C++ Win32 app. I am initiating a <a href="http://www.codinghorror.com/blog/archives/000589.html">shotgun surgery</a> that takes a few days to complete. Back then I was unaware of refactoring/unit testing (the whole company relied on manual testing) so instead of taking baby steps, I did a massive cross-code revolution.<br /><br />Having battled numerous compilation and linking errors I am finally in a position where I can run the code. The thing immediately crashes. It does not even show the window. Again, the tools that we used didn't support stacktracing. I had no idea where to start.<br /><span style="font-size:85%;"><br /><br /><span style="font-style: italic;">For those unfamiliar with the Win32 technology, here's some background. In a Win32 app all GUI events of a window arrive at a single callback function which takes four parameters: hwnd - a handle to the originating widget, msg - an int specifying event type, wparam & lparam - two ints providing event specific data.<br /><br />Typically, the body of such callback functions was a long switch (on the msg parameter) with a case for each of the events that the program was interested in. </span></span><br /><br />In this particular program the message-handling switch block was particularly long. The GUI was quite complicated and there were numerous events (~ 200) that had to be listened to. The callback function was more than a thousand lines long.<br /><br />First, I tried to apply reasoning. I made educated guesses regarding which events are likely to be the ones causing the crash. After several hours of unsuccessful guesses I went to a more brutal approach: I commented out the whole switch block. This made the crash disappear but eradicated every functionality that the program had. Then I uncommented half of the cases inside this switch block. The crash didn't appear and some functionality went back on. This meant the the crash was due to the code that was currently commented.<br /><br />I continued the comment/uncomment game using a binary-search strategy. Quite quickly I zeroed in on the problematic message. I placed a breakpoint and started stepping through/into the instruction. This particular switch invoked code on other functions. One of them looked like this:<br /><pre><code><br />bool b = false; <br />if(...) {<br /> // many lines<br /> b = true;<br />}<br /></code></pre><br /><br />I started debugging this code. When I stepped over the <span style=";font-family:courier new;font-size:85%;" >b = true</span> statement the program crashed. This puzzled me. b is a local variable. It is stack allocated. How can an assignment to it fail?<br /><br /><span style="font-weight: bold;">#1: The memory monster - 2004, C#</span> <span style="font-weight: bold;"><br /><br /></span><span>I joined a small team working on a C# GUI app that was due to be released soon. We had a customer already using </span><span>an early access version of the </span><span>product in return for doing beta testing. The #1 item on our todo list was a report from this customer saying that the program becomes non-responsive after running for several hours. This is a serious defect, a real show stopper. As you can imagine, we never managed to reproduce the problem on our machines.<br /><br />The release date got nearer and we still had no clue regarding the cause of this mysterious defect. As we had no better thing to do, we kept working on other items from our todo list, which was quite pathetic as we knew we will not be able to release the software with this defect.<br /><br />At some point I decided to start fresh. I made the assumption that the defect was some sort of a leak.<br /><br /></span><div style="text-align: left;"><span style="font-size:85%;"><span style="font-style: italic;">Side note: Programmers often believe that in a garbage-collected environment memory leaks cannot occur. That's not true. A garbage collector (GC) will find all unreachable objects and will reclaim as many of them as possible. This does not mean that it will reclaim all unreachable objects. Many GC algorithms leave some of the garbage floating around for the next collection cycle. Moreover, a GC will consider something as garbage only if it is no longer reachable from your code. Thus, if your program maintains references to objects that are no longer needed, these objects will be considered, by the GC, as non-garbage. This will turn the program into a memory-consuming monster.<br /><br />Such a leak often happens if you have some (software) cache in your code. The cache will keep references to objects - thereby preventing them from being collected - even if the application code no longer references them. Thus, if you implement a cache you must always implement some cleanup strategy.</span></span><br /></div><span><br />I left the program running on my machine over the weekend hoping it will help me spot the leak. Sadly, when I came back to check on it, it was running smoothly. Disappointed, I sat down with the customer's contact person trying to understand how the program is being used. This conversation made me realize that the #1 thing that they (beta users) are doing much more than us (developers) is - wait for it - scrolling.<br /><br />Ctrl+Alt+Delete -> Task Manager. I fired up the app, opened a data file, grabbed the scrollbar knob and started dragging it up and down. Looking at the Task Manager window I could see the Mem Usage value climbing. Slowly, but steadily. After a few minutes memory usage exceeded the main memory, the operating system started swapping and the program practically halted. This was awesome. I managed to reproduce the bug.<br /><br />I opened the code that handled scrolling events (this was a custom widget with a custom data model that we developed). My eyes zeroed in on this loop:<br /><br /><pre><code><br />for(int i = 0; i < rows.Length; ++i)<br /> if(rows[i].isOutOfView)<br /> rows.Remove(i);<br /></code></pre><br /><br />Got it? Great. <br />Otherwise, wait for the next post...<br /><br />(To be concluded)<br /></span><br /><a href="http://news.ycombinator.com/item?id=877310">Hackernews discussion</a>Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com5tag:blogger.com,1999:blog-37274183.post-32920469981745562432009-09-21T00:20:00.005+03:002009-10-01T07:19:08.155+02:00The #1 Software Development Post for Sep.'09<div style="text-align: right;"><span style="font-style: italic;">Best Dundies Ever - Pam </span>(<a href="http://www.officetally.com/the-office-the-dundies">The Office</a>)<br /></div><br />Actually, I believe that on September 9th I read the best post for the whole year. Since I can't wait till December 31st, I decided to celebrate earlier, by handing out the "Best September Post" award. I am referring to Stephan Schmidt's <a href="http://codemonkeyism.com/high-cost-overhead-working-parallel/">The high cost of overhead when working in parallel</a> piece.<br /><br />Stephan's post argues that working on several projects in parallel is much less efficient than working one project at a time. He shows that by calculating the time spent on status meetings throughout the whole period. Typically, the scheduling of such meetings is based on calendar events (weekly, bi-weekly, monthly, etc.) and not on measured progress (because measuring productivity is <a href="http://martinfowler.com/bliki/CannotMeasureProductivity.html">hard</a>). Thus, when working in parallel you will have more meetings for the same amount of project progress. As a direct result, you end up with a higher meetings/real-work ratio.<br /><br />Stephan's bottom line, that working in parallel is less efficient than working sequentially, may seem quite trivial. Most developers already know that context-switching between projects incurs significant costs in time and mental energy. They know they are more productive when they can concentrate on one goal. They know that working on several projects is not-unlike juggling: you get to touch each one, but for very little time.<br /><br />So, how come a post with a trivial conclusion is my #1 post this month? It's all about the argument. Stephan did a brilliant job taking a well known phenomena and providing a solid explanation for it. This is remarkable because most of the practices in the field of software engineering have only a vague explanation which often leads to endless, pointless, debates.<br /><br />Even unit testing, which is clearly one of the most effective practices, has no real explanation. We do unit testing because it works, but there is no explanation as to how come testing your program against very few inputs dramatically improves its correctness with respect to an infinite space of "real world" inputs.<br /><br />Stephan's post managed to do it. It supplies a rock solid, non disputable, easy-to-digest, explanation to a software development phenomena. This is not a trivial thing. Go <a href="http://codemonkeyism.com/high-cost-overhead-working-parallel/">read</a> it.Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com9tag:blogger.com,1999:blog-37274183.post-63679578879499532532009-09-06T16:37:00.006+03:002009-10-01T10:12:58.330+02:00My #1 Testing Pattern<div style="text-align: right;"><span style="font-style: italic;">Sex... to save the friendship - Jerry Seinfeld</span> (<a href="http://www.seinfeldscripts.com/TheMango.html">The Mango</a>)<br /><br /></div>This pattern is not the one that I most frequently use. Far from it. It is just the one the I like the most because it delivers a sense of reassurance and peace.<br /><br />So, sometimes you lose your confidence. You no longer believe that your test suite is doing its work. Lost faith threatens to bring down the whole development cycle: you cannot refactor/change/add because a Green bar will no longer indicate "no bugs".<br /><br />This problem often happens after a long refactoring session. When you're finally done you run the tests expecting a Red - you're sure you broke something. To your surprise you get Green. You now have doubts. Is the Green really Green?<br /><br />Whatever the reason for this distrust is, this is a very dangerous situation.<br /><br />Luckily, there is a simple solution: <span style="font-style: italic;">Start breaking your code.</span><br /><br />Pick a random point in your code and change it. Return null from a method. Throw an exception. Comment out an assignment to a field. Whatever. Just break the code. Now run the tests again. If your tests are OK you will get a Red bar. This will raise your confidence level: the test suite just showed you that things are under control. You should now undo this bug that you just introduced and repeat this process with a different program-breaking change. The more you repeat it, the more confidence you will gain.<br /><br />On the other hand, if you get Green after breaking the code, then your distrust is justified. You do have a problem. You should write more tests, starting - wait for it - right now.Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com5tag:blogger.com,1999:blog-37274183.post-34275223417560174152009-08-27T21:51:00.006+03:002009-08-28T01:10:04.065+03:004 Reasons Why Plugin Architectures are AwesomeIt seems that we are surrounded by plugin-based programs. Examples? Firefox, Eclipse, JEdit, <a href="http://www.fogcreek.com/FogBugz/blog/post/The-FogBugz-Plugin-Architecture.aspx">ForBugz</a>, the list is long. This post enumerate the reasons why plugins are so great. Only the first point is obvious. The other are subtle but just as important. Personally, I like reason #2 the most.<br /><br /><span style="font-weight: bold;">1. Happier Users<br /><br /></span>With plugins, users are not limited to the functionality built into the base product. They can enhance the product/customize it to their needs by installing third-party plugins. This is the obvious reason. In fact, many people think this is the only reason.<br /><br /><span style="font-weight: bold;">2. Happier Developers(!)</span><br /><br />Plugin-based programs are usually very easy to debug. Let me tell you how a typical debugging cycle works in such programs: You start (as always) by writing a test that captures the bug. Then you gradually remove plugins from the program until you arrive at the minimal program that still produces the bug. If you do it via a binary-search (over the set of plugins) the process will converges quite quickly.<br /><br />Usually, you end up with a very short list of plugins. A few educated guesses will help you spot the bad plugin right away. Even if you're out of guesses, you're still in a very good position: the amount of code that needs to be scanned has been dramatically reduced.<br /><br />Compare that to a program that is not plugin based. Such a program cannot function without any of its parts. Thus, you have no systematic way to reduce the amount of code involved with a bug.<br /><br /><span style="font-weight: bold;">3. Plugins are Agile</span><br /><br />Breaking up a user request (story or even theme/epic) into tasks is usually a breeze in a plugin-based program. One should simply break the story functionality-wise and implement each piece as a separate plugin. This is much easier than breaking a story according to implementation-oriented tasks. Bottom line: less overhead due to iteration planning.<br /><br /><span style="font-weight: bold;">4. Easy Collaboration</span><br /><br />A real story: A few months ago my team was asked to assist another team with their product. That product had plugin support so we simply implemented our additions as plugins. We were not afraid to break things because we had no access to the source code of the core (big plus). Also, the core was written in C++ but the plugin system is in Java (second big plus).<br /><br /><br />That's my top four reasons. As you can see only the first point is user-oriented. The other three points are all developer-oriented. Surprising, isn't it?Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com5tag:blogger.com,1999:blog-37274183.post-23104919582656253582009-08-15T16:09:00.006+03:002009-08-16T21:28:59.022+03:00Why Aircraft Carriers are not AgileIn <a href="http://ia311019.us.archive.org/0/items/OriandRanreversim31_nothing/reversim31_nothing.mp3">Podcast #31</a> of <a href="http://www.reversim.com/">Reversim</a>, one of the podcasters (I think it is <a href="http://twitter.com/orilahav">Ori</a>) mentions this anecdote:<br /><blockquote>I once had the chance to talk with a consultant. When I asked him what he thinks about agile he said: 'Have you ever seen an aircraft carrier that was developed using an agile methodology?'<br /></blockquote><br />(Disclaimer: (1) The anecdote is stated in a somewhat vague manner. I took the liberty of rephrasing it into a concrete statement. Hopefully I got it right. (2) I am not saying that either Ori or Ran are in favor of the statement. They just mentioned it)<br /><br />So, the topic of this post is this simple question:<br /><div style="text-align: center; font-style: italic;">Why aircraft carriers are not built using an agile methodology?<br /></div><br />And my answer is this:<br /><div style="text-align: center;"><span style="font-style: italic;">Because the engineers can know up front that it will float</span><br /><br /><div style="text-align: left;"><br />That's it. That's the answer. That's the point I am making. The remainder of this post is just the rationale.<br /><br />An aircraft carrier is one of the most complicated machines ever built by man. Still, there is one perspective wherein the complexity of an aircraft carrier is a mere fracture of the complexity of almost any computer program. I am speaking about the ability to reason about the machine from its blue prints.<br /><br />If you take the blue prints of an aircraft carrier you can determine whether the thing will float or sink. It is a simple matter of volume vs. weight. Of course, calculating the volume or the weight from the blue prints is not always a trivial task, but it is still doable. In fact, one can use a computer to do this. Bottom line: the blue prints give a precise answer to the most fundamental question related to any vessel: will it float?<br /><br />In computer programs things are different. Even if you take the actual source code you will not be able to get a precise answer to the fundamental question of programs: will it compute the correct output? It is not a <span style="font-style: italic;">difficult</span> question to answer. It is an <span style="font-style: italic;">impossible</span> question to answer. All the computers in the land will not help you answer this question. That is what Church/Turing had proven in the 1930s (I know I mention these guys in almost every post - but that's how I see things: all difficulties in software construction are due to the properties proven by these two).<br /><br />Note that we are speaking about the source code. The blue prints (UML diagrams, design documents, whatever) provide even less information about the program than the source code. Therefore, they cannot provide any better answer.<br /><br />Under these circumstances it is not surprising that agile methodologies which promote a trial-and-error type of process are on the rise. When you don't know how a machine will behave unless you build it and run it, the only viable option is to built it, run it, see what it does and make the necessary adjustments.<br /><br />Going back to the original question, let's play this little experiment: Suppose we live in a universe where there is no practical way to determine whether a thing floats or sinks. There are some vague heuristic for building vessels that float, but every now and then ships sink as soon as they leave the dock. So, in such a universe<br /><br /><div style="text-align: center; font-style: italic;">will you volunteer to go aboard an aircraft carrier that has been carefully planned but never left the dock?<br /><br /><br /></div></div></div>Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com14tag:blogger.com,1999:blog-37274183.post-11572823894215302562009-08-15T10:00:00.006+03:002009-08-15T11:23:46.854+03:00Software Design Comes to Hollywood<div style="text-align: right;"><span style="font-style: italic;">Don't let yourself get attached to anything you are not willing to walk out on in 30 seconds flat if you feel the heat around the corner - <a href="http://www.imdb.com/title/tt0113277/">Heat</a> (1995)<br /><br /></span><div style="text-align: left;"><span style="font-style: italic;"></span><br /></div><div style="text-align: left;"><div style="text-align: left;"><div style="text-align: left;">So <a href="http://www.eaipatterns.com/gregor.html">Gregor Hophe</a> is seeing design patterns in <a href="http://www.eaipatterns.com/ramblings/18_starbucks.html">Starbucks</a>. As for me, I'm seeing software practices (I am not using the term "Principles" because of <a href="http://javadots.blogspot.com/2009/08/there-was-only-one-principle-and-that.html">this</a>) in movies. The quote in the subtitle is probably my favorite. It is taken from <a href="http://www.imdb.com/name/nm0000520/">Michael Mann's</a> <a href="http://www.imdb.com/title/tt0113277/">Heat</a> where Neil McCauley (Robert De Niro) says it twice. Neil uses this line to explain how professional criminals like him should treat the relationships that ties them to the real, honest, life.<br /><br />I think this goes to programmers as well. We should be willing to walk out on any piece of code the minute we understand it becomes a liability. Every line/method/class is a viable candidate to being eradicated as part of a wide scope refactoring. In other words<br /><br /><div style="text-align: center;"><span style="font-style: italic;">Don't let yourself write any code fragment you are not willing to walk out on in 30 seconds flat if you feel the technical debt payment coming around the corner </span><br /><span style="font-style: italic;"></span></div><span style="font-style: italic;"> </span><br />Note that this goes not only to source code. If you are doing too much up front design you are likely to get attached to diagrams/blue prints/specs. <a href="http://twitter.com/neal4d">Neal Ford</a> calls it <a href="http://memeagora.blogspot.com/2008/12/irrational-artifact-attachment.html">irrational artifact attachment</a>.<br /><br />Individuals who do not follow Neil McCauley's discipline get attached to their past work. They think that some piece of code is so well written or so central to the inner workings of the program that they only allow small patches to be applied to it. They never get to see that what is really needed is a substantial refactoring. This often leads to code that is a big mess of hacks piled up on top of something they are not emotionally ready to get rid of.<br /><br /></div></div><span style="font-style: italic;"><span style="font-style: italic;"><span style="font-style: italic;"><span style="font-style: italic;"></span></span></span></span><span style="font-style: italic;"></span></div></div>Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com2tag:blogger.com,1999:blog-37274183.post-82845396442924183822009-08-02T18:08:00.015+03:002009-08-18T11:38:43.868+03:00There was only one principle and that was principle-22I think the title pretty much summarizes my approach towards software design. If I put bluntly, then I'd say that<br /><br /><div style="text-align: center;"><span style="font-style: italic;">the only universal principle in software is the one saying that there are no universal principles in software</span>.<br /></div><br />Hmmm.<br /><br />Maybe this was a bit exaggerated. So let me rephrase:<br /><div style="text-align: center; font-style: italic;">there are very few universal principles in software. The vast majority of principles are not universal.<br /></div><br /><br />A careful examination of of "truths" about software would reveal that many of them are not more than a rule of thumb whose applicability is limited. Let's take the <a href="http://en.wikipedia.org/wiki/Law_of_Demeter">Law of Demeter</a>: a principle that is based on a clear distinction between good and bad. In theory, this well defined order seems like an excellent vehicle for taming the usually chaotic structure of software. In practice, this principle often leads to <a href="http://sensualjava.blogspot.com/2009/03/oh-null-null.html">questionable consequences</a>. It is rear to see it widely used other than in toy examples.<br /><br />[Following Yardena's comment, the OCP example was rewritten as follows]<br /><br />Another example is the <a href="http://en.wikipedia.org/wiki/Open/closed_principle">Open-Closed Principle</a>: A class should be open for extension (i.e: subclassing) but closed for modification (i.e.: manipulation of the source code). Here's how Robert C. Martin <a href="http://www.objectmentor.com/resources/articles/ocp.pdf">summarizes this principle</a>:<br /><blockquote> ... you should design modules that never change. When requirements change, you extend the behavior of such modules by adding new code, not by changing old code that already works<br /></blockquote>Got it? good modules never change. The principle suggests that one can foresee the future to such an extent that one can develop a class up to a point where its source code will never need to change. Ever. I bet that at least 50% of all programmers do not buy this premise. <a href="http://www.refactoring.com/">Refactoring</a>, which has gained immense popularity as a highly effective development technique, is based on a completely opposite premise.<br /><br />How about the <a href="http://www.objectmentor.com/resources/articles/isp.pdf">Interface Segregation</a> principle? This allegedly universal principle has zero relevance in dynamically typed languages which have no notion of interfaces.<br /><br />These are just three examples off the top of my head. Similar loopholes can be found in almost every software principle.<br /><br />The funny thing is that we already know that it is practically impossible to reason about the important aspects of software. Turing and Church had already proven it. Yet, we (hopelessly) keep on trying to formulate "truths" about something that we can hardly reason about.<br /><br />I think it is much more about psychology than anything else. We want to conquer new frontiers. It is in our genes. Our attempts to formulate software principles are all about taming the wild beast called "software" and making it pleasant and manageable. Sorry, it will not work. There are all sort of notions that are beyond our scope of reasoning. Software is one of them. We'd better accept this fact.Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com3tag:blogger.com,1999:blog-37274183.post-91033597611421291112009-03-07T09:01:00.010+02:002009-03-08T08:27:36.777+02:00The Story of WaterfrontI think the last straw for me, WRT to <a href="http://clojure.org">Clojure</a>, was a conversation I had with <a href="http://www.doc.ic.ac.uk/~abuckley/">Alex Buckley</a> during OOPSLA'08. While speaking about JVM support for dynamic languages Alex mentioned Clojure and Rich Hickey's <a href="http://www.lisp50.org/schedule/schedule/hickey.html">talk</a> that was part of <a href="http://www.lisp50.org">Lisp50@OOPSLA</a>. This conversation gave me the motivation for delving into Clojure.<br /><br />In a nutshell Clojure is a Lisp-dialect that runs on the JVM. Being Lispish it offers a flexible and concise notation. Being a JVM language it allows complete and straightforward interoperability with Java. In other words: In order to write serious Clojure programs you only need to learn language constructs. You don't need to get acquainted with new libraries.<br /><br />Clojure comes with a <a href="http://en.wikipedia.org/wiki/REPL">REPL</a> which lets you quickly evaluate Clojure expressions. In order to utilize the benefits of a REPL your programming work-flow should be different. Instead of the write-compile-run (or TDD's test-write-compile) rhythm, you need to switch to a more constructive mode: you write an isolated small expression, you run it, and then you add it into the program. Here's how Steve Yegge <a href="http://steve-yegge.blogspot.com/2008/06/rhinos-and-tigers.html">describes</a> it:<br /><br /><blockquote>You're writing a function, you're building it on the fly. And when it works [for that mock data], you're like, "Oh yeah, it works!" You don't run it through a compiler. You copy it and paste it into your unit test suite. That's one unit test, right? And you copy it into your code, ok, this is your function.<br /><br />So you're actually proving to yourself that the thing works by construction. Proooof by construction.</blockquote> <br /><br />After adopting this work-flow I noticed that I constantly copy code from my text editor into the REPL. It didn't take long for this sequence to start annoying me. I wanted a tighter integration. I wanted an Editor which is also a REPL. I envisioned an editor where I can right click on a piece of text, choose "Eval" and immediately see the results in an "Output" window. <br /><br />This vision was (and still is) the seed of <a href="http://www.sourceforge.net/projects/waterfront">Waterfront</a>. <br /><br />I used Clojure itself as the implementation language (what better way is there to learn a language than to use it something serious?). In fact, once I had the baic functionality working, I used Waterfront for developing Waterfront. These two choices helped me in detecting all sorts of features that are needed for the Clojure developers. Here are a few examples:<br /><br />First, I needed parenthesis matching. It's a must if you have a Lisp-like syntax. I wanted to be able to see the doc of Clojure functions. When manipulating Java objects I needed to see the list of methods/fields/constructors of classes. I also noticed that when I write proxies (using Clojure's proxy function), I constantly switch back and fourth between Waterfront and the Javadoc of the proxied class, copying the names of the methods I want to override.<br /><br />I tried to address these needs as best as I can. Currently, Waterfront supports the following features:<br /><ul><li>CTRL+E: Eval current selection, or the whole file if the selection is empty</li><br /><li>Edit -> Eval as you type: When turned on (default) periodically evaluates your code. Boosts productivity as many errors are detected on the spot.</li><br /><li>Syntax and Evaluation errors are displayed on: (1) The Problems window; (2) The line-number panel, as red markers.</li><br /><li>Source -> Generate -> Proxy: Generates a proxy for the given list of super-types, with stub implementations for all abstract methods.</li><br /><li>F1: Doc or Reflection<br /> Shows the doc (as per Clojure's (doc x) function) of the identifier under the caret.<br /> Shows the synopsis of a Java class if there is a class symbol under the caret (e.g.: java.awt.Color).</li><br /><li>CTRL+Space: Token-based auto completion.</li><br /><li>Full parenthesis matching.</li><br /><li>An extensible plugin architecture.</li><br /><li>Eval-ed code can inspect/mutate Waterfront by accessing the *app* variable. For instance, if you eval this expression, <code>((*app* :change) :font-name "Arial")</code>, you will choose "Arial" as the UI font.</li><br /><li>Eval-ed code can inspect the currently edited Clojure program. For instance, if you eval this expression, <code>((*app* :visit) #(when (= (str (first %1)) "cons") (println %1)))</code>, the output window will show all calls, made by your code, to the cons function.</li><br /><li>Other goodies such as undo/redo, toggle comment, recently opened files, indent/unindent, Tab is *always* two spaces, ...</li><br /></ul><br /><br />In terms of implementation, Waterfront is based on the <a href="http://groups.google.com/group/clojure/browse_thread/thread/cd88c3d948ff6b4a/e10960d88a87350c?#e10960d88a87350c">context pattern</a>. It allows event handlers to communicate in a functional (side-effect free) manner. On top of this there is a plugin-loader mechanism which loads the plugins that are specified in Waterfront's configuration file. This means that functionality can be easily added or removed (extremely useful when debugging!).<br /><br />The overall response was warm. I plan to move Waterfront into clojure-contrib in order to provide Clojure newbies with a lightweight IDE to ease the transition into the language. <br /><br />I am almost done telling the story of Waterfront. The only thing missing is the answer to this question: why Waterfront? <br /><br />Here's the answer: Back in the 90's there was this TV show called: <a href="http://en.wikipedia.org/wiki/HLOTS">Homicide: Life on the Streets</a>, describing a homicide unit in Baltimore's police department. One of the story lines - that runs throughout all seasons - is about a Baltimore bar called "The Waterfront" which is owned and operated by three Baltimore cops: Det. Meldrick Lewis, Det. John Munch, and Det. Tim Bayliss. Needless to say, I like this show very much.Anonymoushttp://www.blogger.com/profile/15900841850889743147noreply@blogger.com6