Friday, May 22, 2009

Software Engineering, Furniture Making, and Craftmanship

Put up your hand if you were a bit of a geek back in highschool. You didn't take many, or any, shop courses (woodworking, metalworking), you focused your academic attentions on the maths and sciences and you belonged to the chess club. Oops. Looks like I'm the only one in the room with my hand up. Well, anyhow, let's move on.

I've been learning a new hobby, perhaps in order to fill a void from my misspent youth ... furniture making. Or perhaps I've been learning it to fill a craving for some 'artistry' or 'craftmanshp' since if feels like it has been missing from my software engineering. I've come to think that the craving isn't from what I've been making, but rather from how I've been making it. Watching and learning the methods of furniture making has been satisfying that craving in a strange way.

It might not be everybody's cup-of-tea, but if you want to get a glimpse of what I mean you can watch some of the video tutorials on 'www.finewoodworking.com'. For example, there is a a series on making a small cabinet: http://www.taunton.com/finewoodworking/small-cabinet-video/index.asp.

What really impresses me is how confident and capable the instructor is in his practices and even the vocabulary he uses to describe what he is doing. When you watch him work it is clear he is capable of repeatably building and assembly high-quality wooden structures. He's a master craftsman.

What I find very interesting to watch are the techniques/tricks the furniture makers use to make sure the reality of what they build matches up with their intended results. The woodworkers seem very aware of how easy it is to make a wrong cut. A big part of the craft of woodworking seems to be about using methods that reduce the chances of those wrong cuts from happening. In order to do that woodworkers use jigs, fixtures, clamps, fences, and various other techniques to hold the wood product, guide the tools, or place boundaries on the cutting. They put these things in place before they start shaping the product. It is almost as if the woodworker is trying to create an environment, before they start their cutting, where the only thing that can possibly emerge from the wood shaping processses is their desired end product. It leaves the impression that there is as much a skill in creating that environment as there is in actually operating the tools.

I suspect it is not a coincidence that the word 'fixture' appears both in software engineering and woodworking. In woodworking a fixture is something used to hold a wood product in place in a way that makes it easier for the woodworker to shape it. For example if you wanted to cut a board at a particular angle then you might use a fixture to hold the board at the correct angle so that a table saw can be used to produce an angled cut in the board. In software engineering a 'test fixture' plays a similar role; it 'clamps down' the unfinished software product and guides the engineer in the shaping of the product. In theory it makes it harder for the engineer to make the wrong 'cuts'.

If you watch the woodworking videos I mentioned above then you will see another recurring theme. The master cabinet-maker in those videos is well aware that no matter how carefully he measures things the end products do not come out exactly as specified. He often talks about techniques for transferrring information from reality to a yet to be shaped product. For example, imagine a board has already been cut to a certain thickness and a grove must be shaped into which the board is to be fitted. Perhaps the board was supposed to be 1/2 an inch thick but for whatever reason it did not come out that way. What he must be able to do is to transfer the information of the real thickness of board to the grove that is about to be shaped. Although he plans all his cuts he also has techniques that ensure his wood products will match with the reality with which they must interact.

Do I have any great insight into how to apply these woodworking techniques to software engineering. No, not in any earth-shattering way. But from watching the woodworkers do beautiful work I am starting to form an appreciation for what is beautiful about the way they work. I believe, or hope, that with that appreciation I might start to develop a skill for recognizing and nurturing those traites when, or if, they begin to appear in my own work.

Overall it makes me think about what it is I find pretty about woodworking methods and what it is about software engineering that makes the methods less pleasing. I'm starting to form some theories. Perhaps some of you guys have some too.

cheers
Tony

Friday, September 05, 2008

Dojo - x-browser problem with xhrPost().

I ran into a problem the other day with IE7 not behaving the same as FireFox with dojo.xhrPost(). Below is a simple example of the page I was working on that gives you a view into how I was using xhrPost(). This code works perfectly with FireFox but on IE7 not a single form parameter was making it to the server as part of the request.

<form id="myForm" name="myForm" dojotype="dijit.form.Form">
<label>UserName :</label>
<div id="userName" name="userName" dojotype="dijit.form.TextBox"/>

<div id="saveButton" dojotype="dijit.form.Button">Save
<script type="dojo/method" event="onClick">
dojo.xhrPost( {
handleAs: 'json-commented-filtered',
form: 'myForm',
url: 'saveUser.json',
load: function(data) {
// display a message to user here.
}
});
</script>
</div>
</form>

I hacked around a bit and finally found that xhrPost() doesn't seem to play well with the dijit.form.Form widget. I could replace the use of the widget with a standard <form> block without the dojoType and everything seemed to work. However I was using the Form widget in the first place because it has a nice getDescendants() method which i was using for form validation and testing if the form is in a dirty state.

So i decided to try a few more things and finally found that the issue was the use of the "form" attribute of the xhrPost(). For some reason IE7 wasn't properly picking up the form elements when using this attribute. I took a different tact and ended up replacing the "form" attribute with the "content" attribute. Here is what the xhrPost() looks like after the change.

dojo.xhrPost( {
handleAs: 'json-commented-filtered',
content: dojo.formToObject(dojo.byId("myForm")),
url: 'saveUser.json',
load: function(data) {
// display a message to user here.
}
});

Saturday, November 11, 2006

Hello HTML Scraper

Here is a little java application example that shows one way to scrape data from an HTML page. I wrote a little utility class that I can use to scrape various HTML elements from any web page.

I used the nekohtml project (which is an incubated apache project) to parse the html page. The library is pretty simple to use. You give the library the URL to an HTML page, it parses it, and turns it into a XML DOM (Document Object Model) object. Each of the elements in the html page are represented as a node in the DOM.

Whenever I encounter some new technology I try to make a habit of creating an example in the 'hello' project on sourceforge. I start my project by using maven and then work on it using the Eclipse IDE. Exactly how I do that is described in this README.txt file in the project.

The CVS repository information for checking out the example into your Eclipse IDE is:

host = hello.cvs.sourceforge.net
repository path = /cvsroot/hello
user = anonymous
module = /development/examples/hello-html

A unit test, which scrapes all the hyperlinks from the google home page, is here. It tests a little utility class, HTMLPage, that I wrote using the nekohtml library.

My utility class can be used for scraping anything from a page. The code for the utility class implementation is here.

This example shows the basics of how to do HTML scraping.

I am thinking that perhaps it is better as an example of how not to write a teaching example. As a teaching example I do not think it is very good for the following reasons:

  • It trys to be too general when instead it should have just shown how to use the nekohtml API.
  • It unnecessarily introduces a complicated language feature, java generics, that it not important to the teaching example.
  • And if you were looking carefully you will notice I mistakenly called my test a unit test when it is really a system test.

I would write the example over again, except I think you guys probably still got the basics from it.

That's it for this week.

Catch you later,
Tony


That's all for today.
Tony

Thursday, August 03, 2006

Introduction to Echo2 with Maven, Eclipse, and Jetty

I've been dragging my feet about entering the AJAX fray. Thetechnology landscape surrounding AJAX feels very fragmented to me. Where does one begin? Which toolkits will merge to form the standard? Which will be dropped? Not to mention the fact that I'm not an expertWeb developer and would rather leave HTML, CSS, and JavaScript todesigners than be mucking with it myself. As a result, I've chosenmore conventional programmatic GUI toolkits like Swing or Eclipse's SWTfor writing rich client applications. The truth is though, that peopleoften cringe when they hear the word "Applet", and installing a "fat"client on users' desktops is not always an option. And so the searchfor the holy grail begins, a UI technology that does a reasonable jobof meeting these criteria:
  1. Natural Programming Model-- The developer should be able to interact with the UI controls thatmake up the toolkit in a natural OO way. Preferrably, in a language wealready know.
  2. Modern Tool Support-- Developers should be able to easily debug and unit test code writtenwith the toolkit and make use of modern IDE features like refactoring
  3. Ubiquitous Deployment-- Applications written with the toolkit should be easily deployable toa large audience. This means no non-standard plugin installations,browser compatibility hassles, and no "large" downloads
  4. Rich Client Features-- Developers should be able to easily implement Rich Client Featureslike controls that update in real-time, drag-n-drop, resizing panes,popups, dialogs, etc.

The rest of this post will focus on a toolkit that meets the above criteria, Echo2,an open source AJAX-based framework. Developers write their UI code inJava, interacting with the UI controls much like they would if theywere writing a Swing application, but the control itself is splitbetween the web browser and server. For a given user, the state of theUI controls is maintained in the user's session, while the "view"portion of the controls is rendered in the user's web browser.

Hello World Application

I'llstart with a really simple application, simply putting a button on thescreen. The purpose of this example application will be simply to geta development environment setup and a simple application working.

To complete this tutorial, you'll need the following tools:
  • Eclipse IDE -- Available for download here
  • Maven 2 -- Available for download here
  • Echo2 -- Available for download here
We'll use Eclipse to write some Java code and Maven 2 to ease some of the build and deployment stuff.

Creating the Web Project

We'lluse maven to create the boilerplate web app project. Echo2 apps can bedeployed as a war file in any java servlet container. If we usemaven's archetype plugin to create our web app project, then we canalso use maven to do the rest of our build tasks without any additionalconfiguration including compiling our source code, creating and anddeploying our war file, etc.

In a temp directory, create a new project using the following maven 2 command
mvn archetype:create -DgroupId=org.softsoup.echo2 -DartifactId=echo2-hello -DarchetypeArtifactId=maven-archetype-webapp

Thiscommand creates a new directory, "echo2-hello" that contains your newweb app project with some standard directories and files precreated sothat the other maven plugins will know where to look for things when weask it to build the war file, etc. This command also creates thepom.xml document for this project and puts it in the root folder of theproject ("echo2-hello"). This pom.xml document is read by maven tofind out things about your project like your project's dependencies andwhat type of artifact (jar, war, etc) to build from your project.

Adding Echo2 Dependencies

We're going to be writing some classes that will use the Echo2 jars, so we need to add them to our project as dependencies.

Installing the Echo2 jars into Local Maven Repository

Assuming you've downloaded and unzipped the Echo2 distribution in <echo2-home>, run the following commands to copy the Echo2 jars into your local Maven repository:

mvn install:install-file
-Dfile=<echo2-home>/BinaryLibraries/Echo2_App.jar
-DgroupId=echo2 -DartifactId=Echo2_App -Dversion=2.0 -Dpackaging=jar
mvn install:install-file
-Dfile=<echo2-home>/BinaryLibraries/Echo2_WebContainer.jar -DgroupId=echo2 -DartifactId=Echo2_WebContainer -Dversion=2.0 -Dpackaging=jar
mvn install:install-file
-Dfile=<echo2-home>/BinaryLibraries/Echo2_WebRender.jar
-DgroupId=echo2 -DartifactId=Echo2_WebRender -Dversion=2.0 -Dpackaging=jar
There should now be a folder "echo2" under <your-home-dir>/.m2/repository. This folder will contain a folder for version 2.0 which should contain the jars.

Declaring the Dependencies In pom.xml

Now,add the following tags to the dependencies section of the pom.xmldocument located at the root of your echo2-hello project:
<dependency>
<groupId>echo2</groupId>
<artifactId>Echo2_App</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>echo2</groupId>
<artifactId>Echo2_WebContainer</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>echo2</groupId>
<artifactId>Echo2_WebRender</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
</dependency>

Thistells maven to look for these jars when doing builds, packaging etc. NOTE: while our code will not directly depend on the servlet-api, theEcho2 libraries do, so we include the servlet-api as a dependency.

Before moving on to the next step, cd to the echo2-hello directory and run:

mvn compile

Wedon't have any source yet, so it won't really compile anything, butthis will force maven to download all of our declared dependencies thathaven't already been installed into our local repository. In thiscase, we manually installed the echo2 libraries, so it should onlydownload the java servlet api jar.

Importing Into Eclipse

If you're using Eclipse, you'll want tocreate an Eclipse project for our new project and then import it intoEclipse. Maven provides a plugin for creating the Eclipse projectfiles from a maven project. from your new echo2-hello directory, runthe following command:

mvn eclipse:eclipse

Notice thatthis command created the .project and .classpath files in yourecho2-hello directory. Now you can import the project into the Eclipseworkspace. Launch Eclipse and choose File->Import->ExternalProjects into Workspace. Select the echo2-hello project. It shouldnow appear as a project in Eclipse's package explorer.

Now, to the Coding!

Adda folder for our project's Java source tree at...echo2-hello/src/main/java. Create a package within that sourcetree, org.softsoup.echo2.hello.

To get our web app up andrunning, Echo2 requires that we create only the following two classeswhich we'll put in our new package.

The application UI class itself, an instance of one of these will be created for each user:
public class HelloWorldApp extends ApplicationInstance {

public Window init() {

// create the root window, content pane,
// window pane, and a button
Window window = new Window();
ContentPane contentPane = new ContentPane();
final WindowPane windowPane = new WindowPane("hello world", null, null);
Button button = new Button("click me");

// add an action listener to the button that changes
// the window pane's title when clicked
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
windowPane.setTitle("hello world " + new Date());
}
});

//add the controls to the screen
windowPane.add(button);
contentPane.add(windowPane);
window.setContent(contentPane);
window.setTitle("hello, world!");

return window;
}
}


OurHelloWorldApp will have a window pane on the screen and a button whichwhen clicked will update the title of the window pane. Notice howhandling the button click is as simple as registering an ActionListenerwith the button. NOTE: the ActionListener here is an interfacedefined as part of the Echo2 API's, not thejava.awt.event..ActionListener.

and a servlet to create the app instances, one instance of these will be created per deployment:
public class HelloWorldServlet extends WebContainerServlet { public ApplicationInstance newApplicationInstance() { return new HelloWorldApp(); } }

Configuring the web.xml

Sinceour Echo2 apps is deployed as a servlet, we need to register ourHelloWorldServlet with the servlet container by editing the boilerplateweb.xml file that maven created atecho2-hello/src/main/webapp/WEB-INF/web.xml. Edit it to look likethis:
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<display-name>Hello SoftSoup!</display-name>
<description>
"Hello, SoftSoup!" Application
</description>

<servlet>
<servlet-name>HelloWorldServlet</servlet-name>
<servlet-class>org.softsoup.echo2.hello.HelloWorldServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>HelloWorldServlet</servlet-name>
<url-pattern>/app</url-pattern>
</servlet-mapping>

</web-app>


This tells the web container that any url's matching "/app" will be dispatched to our HelloWorld echo2 application.

Configuring the Jetty Plugin for Maven

TheJetty plugin for maven will help us to quickly test our app. Basically, the jetty plugin will take a standard Maven web app project(which we have!), and run it within the jetty servlet container withoutassembling the project into a war file. Also, we can configure it toperiodically scan our project for changes, redeploying any changes itfinds automatically. This means that we could sit down in the morningto work on our echo2 app, launch the jetty plugin using, Then let itrun all day while we make changes to our project and test them using aweb browser.

First though, we need to declare our use of this special plugin in our pom.xml file as follows:

...
</dependencies>
<build>
<finalName>echo2-hello</finalName>
<plugins> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> </configuration> </plugin> </plugins>
</build>
</project>


Running the App

Now, run the Jetty plugin using:

mvn jetty:run

This launches our app in the Jetty servlet container on port 8080.

Load the Hello World app using http://localhost:8080/echo2-hello/app

What's Next

I'lltry to make a follow up post that demonstrates some of the moresophisticated features of Echo2 including their "push" stuff which is abig part of the "richness" of RIA's.

Wednesday, July 19, 2006

Inaugural Post

Welcome to Soft Soup. We will periodically be posting articles having to do with Software Engineering. These will include tutorials, reviews, techniques, and general discussions having to do with software.