Maximized Functionality Vs. Maximized Awesomeness

I used to believe that it was my job to get the customer the most functionality as quickly as possible. Rough edges didn’t matter.

If the customer could live with the strange workflow, a quirky UI, or some other abnormality, so could I. It was more important to get the usable code out there. We’ll smooth the edges out later. Which is fine if it actually happens. But, it never really seems to work out that way.

So, nowadays I am not so sure. Even if the customer wants the functionality, I wonder if we do them a disservice by giving it to them. Perhaps it is a matter of who says it is “done-done”, but I am beginning to wonder if it is better to deliver the tiniest bit of functionality (iteratively of course) until it is freaking awesome. No rough edges, no quirks. Just awesomeness. Then, we move on.

This entails finding out what the heart of the functionality is and only doing that. Also, we need a customer that acknowledges the rough edges whether they face the user or are in the code. Hmmmm.

Well, like I said, I am not so sure. But I am beginning to wonder.

Don’t Be Afraid to Manage

A couple of months ago I read What Have You Changed Your Mind About. It was a fast and enjoyable read. One essay in particular, “Political Science” by Leon Lederman stuck with me.

In the essay, which is about the need for a science-literate political system, Lederman states

…I am driven to the ultimately wise advice of my Columbia mentor, I.I. Rabi, who … urged his students to run for public office and get elected. …We need to elect people who can think critically… We need a national movement to seek out scientists and engineers who have demonstrated the required management and communication skills…

While I agree with Lederman about the need for more science-literate representatives in our government, what I am posting about is related to software development. What is that? Well what if we take the above and do a few substitutions?

s/run for public office and get elected/apply for management positions and get them/
s/elect/hire/
s/scientists and engineers/developers and architects/

The point is this: we’ve all had our share of PHB silliness, but we can’t expect things to get better if we aren’t willing to be involved in managing our affairs. We shouldn’t be afraid to manage.

Questions To Ask Potential Employers

As I’ve moved back into contracting/consulting, I’ve been drawing a list of questions to ask potential employers. I won’t discuss the answers I prefer to hear. But, I think if one knows what answers they’d like to hear, they are better prepared to evaluate if the employer is a fit for them.

Does all of the code compile?

Number of automated tests?

What is your code coverage?

What is your branch coverage?

What is your average cyclomatic complexity?

If working with legacy code, how long has it been since it was modified?

If working with legacy code, who wrote it, an employee or contractor?

Are you familiar with the Joel Test (or something like it)? What’s your score?

If you have the basic infrastructure:
What type of source control do you use?
What tool(s) do you use for continuous/daily builds?
What tool(s) you use for bug tracking?
What tool(s) do you use for deployment?

How long does it take to get a user environment set up?

What type of machines (RAM, CPU, monitor(s) size)?

What type of phones? Obvious how to hang up, redial, etc?

How easy is it to get conference area?

Do conference areas have projectors?

Do conference areas have whiteboards?

Do cubes have whiteboards?

How many managers have programming background?

How many managers to a person?

How are people organized? Matrix, hierarchical, team?

Who makes the estimates?

What is the basic unit of measurement for estimates? Hours, days, points, etc?

Type of browser? Are daily tools dependent upon browser?

And, of course,

Is coffee provided?

3+ Techniques: Binding Java Datastructures To JavaScript

Consider the case where we need to bind stuff from the Java (server side) world to the Javascript (client side) world. In particular, we want the values of a data structure on the server side used in client-side Javascript.

Let’s use assume we have a class like this:

We have a set of Map.Entry. Each member of the set is a String key with a List of Strings as the value. A possible use for such a thing would be the basis of a set of dependent drop downs. One drop down has a set of values (the keys), and when the first drop down changes, the second drop changes (the values).

For the techniques described, I am using JSPs and a servlet container. We have a bit of JavaScript to display the contents of our data structure on the client side:

Now, how do we get this into client side land?

Technique One: Duplication

This isn’t a particularly robust way doing things. The biggest issue is that we have duplication, that requires knowledge of both the data structure and the JSP if we are going to make changes.

Technique Two: Constants

Another way of getting stuff to the client side is to extract the values in the Java data structure to constants:

And then we’ll need it in some sort of wrapper:

Then, we’ll use that wrapper in the JSP:

It is important to note that I didn’t want to start mixing JSP actions with JavaScript to create the fully formed text for the JavaScript. Also, I didn’t want to have a bunch of stuff in the wrapper just for the JavaScript. So, I split the difference and use the string output when rendered on the Java (JSP) side, and a little regex on the JavaScript side. That’s what the replace(/[\]\[]/g, “”).split(“, “) is all about.

Technique Three: Constants Part 2

We can achieve the use of constants in a little cleaner fashion by using the unstandard tag library. It allows us to use constants in a more natural way. No wrapper needed.

Technique Four: JSON

What if we serialize the data structure into JSON? We would need a serializer. In this case I used Xstream:

Then, we could serialize the data structure into a string that can be eval’d:

The tricky parts here are making sure we know what the JSON version of the object is going to look like and at what level can we start accessing the properties.

Tying It All Together

To test the code, I used Jetty, Selenium, and JUnit. The test class:

Conclusion

If I had to only a simple value or two that I needed to bind, I’d probably go the the unstandard tag library path. Unfortunately, the library is no longer supported. But, it seems like it is still being used by a lot of people. For something more complex, I think I’d go with JSON serialization. And, if I had a lot of it, I’d start looking at bundling that technique with some JavaScript frameworks to get some AJAXy types of behavior.

The following links were quite helpful in getting the code operational:
Disabling Pretty Print In Xstream
http://jsfiddle.net/ is awesome

Leave It Better Than When You Got There — How To

Are you familiar with the Boy Scout Rule? Hopefully you are. In its simplest form, in any endeavor, we should leave things better than when we got there. In software, how do we do this? I think at a high level, we have some general problems and solutions:

Problem Solution
No Tests Create Tests
Incomplete Tests Record Test Coverage And Add Tests Until All Paths Through The Code Are Covered
Hard To Understand Tests Refactor Tests Into Chunks That Act As Developer Documentation
Hard To Understand Production Code Perform Refactorings In Fowler’s Refactoring

Problems and Solutions Expanded

Let’s expand a little on the table above. First, the problems are in decreasing severity to a the long term success of project. So, not having a set of tests is the biggest (technical) detriment to the project. Without automated and continuously running tests, we essentially have a black box. We can’t easily make changes without being certain that we are not introducing bugs.

Given the choice between some tests and no tests, I’ll take some tests. If we have some tests, we have a lot of the hard stuff out of the way. But, how do we make it better? We add tests until we have all code paths covered. There are number of tools out there for measuring code coverage. Hook the coverage tool up with your tests. Remember, it is not the percentage of code covered in a class that is important. It is the branch coverage. We want to know that we have tested all the paths through the code. If you have good branch coverage, you’ll have good line coverage. Good line coverage does not necessarily mean good branch coverage.

If we have complete tests, the next issue is most likely that the tests are hard to understand. To fix this, we keep in mind that not only prove that the code is working as expected, but also act as documentation. Effective documentation means exposing only what is necessary important for a certain outcome. We want enough context to understand what is going, but not so much information that the essentials are drowned out. Achieving this is a difficult balancing act. Refactoring test code (extracting methods and classes, using proper setup and tear down) and patterns like the test data builder help us achieve this goal.

Now I must come clean: the assumption all along has been that by starting at the tests we have made changes to the production to make it testable. This means that if we have all the other problems licked, we should be at a stage where the public API for the production code is settled. We have all the code tested, and we know what the code is supposed to do. So, if the production code is difficult to understand, it is a matter of refactoring it.

Find The Java Version Of A Class File

Just a quick note on determining the version of a Java class file: if you are on *nix or are using Cygwin, you can use the following:

hex_value=`od -t x1 ExampleDataStructure.class | head -1 | awk ‘{print “0x”$8$9}’` ; printf “%d\n” $hex_value

Replace ‘ExampleDataStructure.class’ with the name of your class.

The number decimal number that is produced will allow you to determine the Java version. For example, 47 means version 1.3, 48 means version 1.4, 49 means version 1.5, and 50 means version 1.6.

For more details, consult the following:
Real’s How To
Joseph D. Darcy’s Oracle Weblog

Don’t Make It Difficult To Do The Right Thing

Don’t make it difficult to do the Right Thing. Don’t make it easy to do the Wrong Thing.

All to often, when dealing with software, we stop after something is working. But, as those in the know know, we ain’t done. We better have tests at this point, and we need to refactor. This is where we go beyond making something work. This is where we reflect on its usage and how to make it better, how we make it easy to do the Right Thing and hard to do the Wrong Thing.

I don’t want this to become yet another “You Need To Have Tests” post. But, our tests make sure the code still does what we want while we are making the code easy to work with. We need to have a safety net if we are going make changes to the code that will allow us to move beyond “something that works”.

Think about code you’ve worked with. Think about the code bases you liked and the ones you didn’t. Strive to get your code like the ones you enjoyed, the ones you could intuit what you needed to do, the ones that guided you in the right direction. Most likely, that code made made it difficult to do the Wrong Thing, but was so easy to work with that doing the Right Thing was effortless.

Don’t fall int the trap of just recreating code in the style that you were subjected to. Rise above that crap and create something makes it easy to do the Right Thing!

3+ Techniques

It has been said that until you have three options, you really don’t have any choices. With that in mind, I want to introduce a semi-regular series to this blog.

Entitled “3+ Techniques: [Topic]“, where [Topic] is (duh) the topic, the series will be about a few ways of handling said topic. By examining 3 or more ways of tackling a problem, we’ll have an outline some of the choices we have along with code examples. In addition to the techniques, we’ll note some of the pros and cons of each. I hope the series will be useful for ideas and code.

Neatness Counts: Beware Of The Nested Inline

I always tell my teams that neatness counts. Consider having to read a novel that is handwritten. The messier the handwriting, the harder it will be to read. That, in turn, can affect the time it takes to read the novel, enjoyment of the novel, and even understanding of what the novel is about! Thank goodness we don’t have to read handwritten books.

The same can be said for code. Messy (poorly formatted code) can increase the difficulty of understanding the intent and/or modifying the code.

Look at the code I recently came across. The code has been changed to protect the innocent and not-so-innocent. I had to make the font size really tiny to get everything on one line like it was originally. But, the spirit remains intact.

String string = (CyberProvince.findByCountryId((CountryParameters.findCountry()).getCountryId())).getProvinceNumber().toString()

So, image we have some objects that represent part of a hierarchy. In this case, we have provinces which are part of a country. And, to make things more interesting, we have the notion of a virtual province (CyberProvince). Anyway, from the code above it is a really difficult to see what is going on and who the actors are.

So, let’s make this readable. First, the parenthesis:

String string = (CyberProvince.findByCountryId( ( CountryParameters.findCountry() ).getCountryId() )).getProvinceNumber().toString()

In the very least, if you are using a buttload of parenthesis, then use some space to expose the “pieces”. Next, let’s extract a variable:

CountryParameters countryParameters = CountryParameters.findCountry();
String string = (CyberProvince.findByCountryId( ( countryParameters ).getCountryId() )).getProvinceNumber().toString()

A little better. Now, lets clean up some of the parenthesis, and extract a variable.

CountryParameters countryParameters = CountryParameters.findCountry();
Integer countryId = countryParameters.getCountryId()
String string = (CyberProvince.findByCountryId( countryId )).getProvinceNumber().toString()

Let’s extract another variable.

CountryParameters countryParameters = CountryParameters.findCountry();
Integer countryId = countryParameters.getCountryId();
CyberProvince cyberProvince = CyberProvince.findByCountryId( countryId );
String string = (cyberProvince).getProvinceNumber().toString()

Ok. Let’s do another round of parenthesis fixing.

CountryParameters countryParameters = CountryParameters.findCountry();
Integer countryId = countryParameters.getCountryId();
CyberProvince cyberProvince = CyberProvince.findByCountryId( countryId );
String string = cyberProvince.getProvinceNumber().toString()

Before the changes, understanding the code and considering modifications was much more difficult. Now, we can actually understand the intent. We can begin to analyze the code, to weigh the pros and cons of further refactoring of said code. Plus, we have the added benefit of being able to more easily debug the code if needed.

Once again: neatness counts!

Playing With Jetty And Selenium

Now that we’ve seen how to get Jetty up and running, let’s integrate it with Selenium. We’ll be using Selenium 2 to check a simple JSP.

So, in addition to the Jetty-related jars mentioned in the earlier post, we will need the following Selenium jars:

selenium-java-[version].jar
selenium-server-standalone-[version].jar

They are available here.

We have a JSP:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h1>From The JSP</h1>

<h2>h2 text</h2>

</body>
</html>

This page is served when one tries to go to http://localhost:8080.

And, we also have a simple test class:

package com.bitmotif.example;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.server.SeleniumServer;

import static org.junit.Assert.assertEquals;

/**
 * User: pjberry
 * Date: 3/22/11
 * Time: 6:29 PM
 */
public class ExampleTest {

    private SeleniumServer seleniumServer;
    private Server applicationServer;
    private WebDriver driver;

    @Before
    public void setUp() throws Exception {
        startApplicationServer();
        startSeleniumServer();
        driver = new FirefoxDriver();
    }

    @After
    public void tearDown() throws Exception {
        driver.quit();
        seleniumServer.stop();
        applicationServer.stop();
    }

    @Test
    public void testPageContents() {
        driver.get("http://localhost:8080");

        WebElement element = driver.findElement(By.tagName("h2"));

        assertEquals("h2 text", element.getText());
    }

    private void startSeleniumServer() throws Exception {
        seleniumServer = new SeleniumServer();
        seleniumServer.start();
    }

    private void startApplicationServer() throws Exception {
        applicationServer = buildServer( buildWebAppContext() );
        applicationServer.start();
    }

    private Server buildServer(WebAppContext webApp) {
        Server server = new Server(8080);
        server.setHandler(webApp);
        return server;
    }

    private WebAppContext buildWebAppContext() {
        WebAppContext webApp = new WebAppContext();
        webApp.setContextPath("/");
        webApp.setResourceBase("./src/main/webapp");
        return webApp;
    }

}

So, what do we have here? Simply, we fire up Jetty, then fire up the Selenium server, and lastly, we fire up the WebDriver (client). With our server running and proxy running, we use our client to load a page. Next, we load a page and get the h2 tag. Then we check the text in the h2 tag.

This is freaking awesome. Basically, we have a way to test against a container without having to do a deployment! Extending this idea, we can then do things like create tests for Javascript without leaving the IDE or automate acceptance tests for continuous integration without a bunch of tedious configuration. That’s pretty powerful stuff.