Using the Builder Design Pattern to output HTML on Servlets

I am fortunate, in a way, to be working on a website where the technology is dated and the code was not shown any “love and care” for a number of years. So why would anybody feel fortunate to be working on a website like this, well it is just so easy to make improvements and to feel the sense of achievement when you improve something.

I recently had an example where I was refactoring some of our servlets. As I was going through and tidying I noticed a number of similar pieces of code and html. To eliminate the duplication I moved the duplicated code into methods. Once I was complete with the refactoring, I was still not happy. A page needs to be built in a certain order and all our servlet pages should be built in the same manner.

As a result, this ended up being a neat example to utilise the Builder Design Pattern. I am not going to go into any detail about the pattern itself because there are a number of posts, for example this tutorial on the Builder Design Pattern and books, such as Design Patterns: Elements of Reusable Object-Oriented Software by the GOF. I simply want to provide an example of how this has simplified our building of servlets into a standard manner.

So essentially we would have required nearly 80 lines of code to generate the very simple example page below.

An example of the outputted html screen

An example of the outputted html screen

The code to create this page using our traditional coding style for servlets would have looked as per below.

package com.servlet.presentation;

import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.PrintWriter;

public class ServletWithHTML extends HttpServlet {

public void doGet(HttpServletRequest request,
 HttpServletResponse response)
 throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

out.println("<html> ");
 out.println("<head>");
 out.println("<title>An example using a builder pattern to make the servlet code prettier</title>");
 out.println("<link rel=\"stylesheet\" href=\"css\\reset.css\">");
 out.println("<link rel=\"stylesheet\" href=\"css\\style.css\">");
 out.println("</head> ");

out.println("<body>");

out.println("<form>");

out.println("<div class=\"title\">Builder pattern to make servlet html creation easier to read</div> ");

out.println("<div class=\"paragraph\">An example using a builder pattern to make the servlet code prettier</div>");

out.println("<dl>");

out.println("<dt class=\"twocolumn\"><label>");
 out.println("Label text 1");
 out.println("</label></dt>");
 out.println("<dd class=\"twocolumn\"><p>");
 out.println("Value text 1");
 out.println("</p></dd>");

out.println("<dt class=\"twocolumn\"><label>");
 out.println("Label text 2");
 out.println("</label></dt>");
 out.println("<dd class=\"twocolumn\"><p>");
 out.println("Value text 2");
 out.println("</p></dd>");

out.println("<dt class=\"twocolumn\"><label>");
 out.println("Label text 3");
 out.println("</label></dt>");
 out.println("<dd class=\"twocolumn\"><p>");
 out.println("Value text 3");
 out.println("</p></dd>");

out.println("<dt class=\"twocolumn\"><label>");
 out.println("Label text 4");
 out.println("</label></dt>");
 out.println("<dd class=\"twocolumn\"><p>");
 out.println("Value text 4");
 out.println("</p></dd>");

out.println("</dl>");

out.println("<div class=\"paragraph\">This is really hard to read</div>");

out.println("</form>");

out.println("</body>");
 out.println("</html>");
 }
 }

Even though this is a very simple example, reading the page is very difficult with all the html references and quotes. It is also not very descriptive in describing what the developer is trying to do.

So first off a FormBuilder was created to build the page and generate the associated html.

package com.servlet.builder;

import java.io.PrintWriter;

public class FormBuilder {

private StringBuilder stringBuilder = new StringBuilder();

public FormBuilder() {
 stringBuilder.append("<form>");
 }

public FormBuilder title(String text) {
 div("title",text);
 return this;
 }

public FormBuilder paragraph(String text) {
 div("paragraph",text);
 return this;
 }

public FormBuilder twoColumnTable(TwoColumnTable twoColumnTable) {
 stringBuilder.append(twoColumnTable.toString());
 return this;
 }

public void toString(PrintWriter printWriter) {
 endForm();
 printWriter.println(stringBuilder.toString());
 }

public String toString() {
 endForm();
 return stringBuilder.toString();
 }

private void endForm() {
 stringBuilder.append("</form>");
 }

private void div(String style,String text){
 stringBuilder.append("<div class=\"").append(style).append("\">");
 stringBuilder.append(text);
 stringBuilder.append("</div>");
 }
}

To create the two column table in the example page a TwoColumnTable builder was created.

package com.servlet.builder;

public class TwoColumnTable {
 StringBuilder stringBuilder = new StringBuilder();

public TwoColumnTable() {
 stringBuilder.append("<dl>");
 }

public TwoColumnTable row(String label, String text) {
 stringBuilder.append("<dt class=\"twocolumn\"><label>");
 stringBuilder.append(label);
 stringBuilder.append("</label></dt>");
 stringBuilder.append("<dd class=\"twocolumn\"><p>");
 stringBuilder.append(text);
 stringBuilder.append("</p></dd>");

return this;
 }

public String toString() {
 stringBuilder.append("</dl>");
 return stringBuilder.toString();
 }
}

The nice thing with this is that some relationship is maintained between the html elements. In this example only a form can have a TwoColumnTable and row can only be contained in the TwoColumnTable.

Now with the FormBuilder and TwoColumnTableBuilder in place, our java code for the servlet would look like below.


package com.servlet.presentation;

import com.servlet.builder.FormBuilder;
import com.servlet.builder.TwoColumnTable;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class ServletUsingBuilder extends HttpServlet {

public void doGet(HttpServletRequest request,
 HttpServletResponse response)
 throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

out.println("<html> ");
 out.println("<head>");
 out.println("<title>An example using a builder pattern to make the servlet code prettier</title>");
 out.println("<link rel=\"stylesheet\" href=\"css\\reset.css\">");
 out.println("<link rel=\"stylesheet\" href=\"css\\style.css\">");
 out.println("</head> ");

out.println("<body>");

new FormBuilder()
 .title("Builder pattern to make servlet html creation easier to read")
 .paragraph("An example using a builder pattern to make the servlet code prettier")
 .twoColumnTable(new TwoColumnTable()
    .row("Label text 1", "Value text 1")
    .row("Label text 2", "Value text 2")
    .row("Label text 3", "Value text 3")
    .row("Label text 4", "Value text 4"))
 .paragraph("This is really much easier to read")
 .toString(out);

 out.println("</body>");
 out.println("</html>");
 }
}

So 26 fewer lines of code to output exactly the same html. That is nearly a 40% line count improvement on a very simple example.

Writing code to output standard html that is repeated throughout the site in this fashion provides the following benefits:

  • Firstly, the code is a lot cleaner and easier to read.
  • The code is more descriptive.
  • A lot less code needs to be written.
  • The html is generated consistently. We don’t have to remember all the html and css tags.
  • The code becomes testable – for example we can write tests for the builder and if we make any changes to the html we can validate it is correct.
  • Changes to the html we want to generate are made in a single location.
  • The compiler provides support in ensuring tags are contained only within allowed elements.

The full source for this example is available at https://github.com/craigew/HtmlBuilder. In the near future I will add tests to the project to illustrate how this can aid with testability.

Posted in Design Patterns, Software development | Tagged , , , , , , , , , | 2 Comments

The beauty of feature toggles and developing off trunk

In our journey to rejuvenate our development practices and eliminate waste from our development cycle one of the areas of concern was the way we were managing our code. We typically had half a dozen branches of code running at the same time all depending on the time to go-live and the long running projects we had in progress. Long running projects are a problem in their own right, but that is another post on its own. So quite often our branches would look like the following:

  • Current production branch
  • Development branch for current release
  • Development branch for next release
  • Long running project one
  • Long running project two
  • Trunk

This type of branching strategy caused us to be very rigid in our release cycle with very little flexibility in when we moved into production. A lot of risk and waste is also introduced into the cycle.

For example, merging the current release branch back into Trunk is a wasteful exercise, in that someone has to resolve all the merge conflicts. They have to find the developer or developers to determine how to correctly resolve the conflicts, do the merge, and then test to make sure nothing is broken.

This merging process itself adds risk in that the developer doing the merge does get it wrong sometimes. When people are involved in the merge it is inevitable that you will have incorrect decisions being made. We had a number of production incidents resulting from a small oversight by the developer doing the merge. So you really want to merge as little as possible.

Your go-live is also an all or nothing approach. Short of rolling back code, all developed features go into production or the release is delayed. With our release cycle this was not possible, so those features went into production come hell or high water. This meant many long nights and weekends to get features “complete”, incomplete testing and dealing with the fall out in production.

With the all or nothing approach, we started doing more documentation up front, release cycles got longer and features took longer to get to clients. Even though we were doing “Agile” our poor development practices where making us anything but agile in delivering to our clients.

One of the things we did to start eliminating the wastage was to reduce the number of branches we had. We initially went with a single development branch, a short lived release branch and trunk. This ended up being a short interim step to where we are now, with only trunk and the short lived release branch. With developing off trunk we quickly realised the urgency to introduce feature toggles and in a single Friday afternoon we wrote a very simple toggle framework, which I describe below.

First off we need to have a externalised definition of our toggles, which we represented in xml.


<FeatureToggle>
 <feature name="Hello world" value="on"/>
</FeatureToggle>

We also represented this in our code, because we want the compiler to assist us with removing the toggles when the feature is embedded in production.


public enum ProductionFeature {
 HELLO_WORLD("Hello world");

private String featureDescription;

ProductionFeature(String featureDescription){
 this.featureDescription=featureDescription;
 }

public String getFeatureDescription() {
 return featureDescription;
 }
}

The java enum maps to the xml config file allowing us to switch the toggle on and off without having to recompile the code.

We then have a simple class to check if the feature toggle is on or off.

public class Toggle {

public static boolean isOn(ProductionFeature productionFeature) {
 try {
 Map features = xmlParser.getInstance().parse();
 return "on".equalsIgnoreCase(features.get(productionFeature.getFeatureDescription()).toString());
 } catch (Exception ex) {
 return false;
 }

}
}

And this is simply referenced in a jsp or servlet.


<%@ page import="com.toggle.ProductionFeature" %>
<%@ page import="com.toggle.Toggle" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
 <title></title>
</head>
<body>
<%
 if (Toggle.isOn(ProductionFeature.HELLO_WORLD)) {
%>
Hello world
<%}%>
</body>
</html>

Although this is a brutally simple method of toggling features it has allowed us to confidently speed up our delivery with long and short running pieces of work happening in the same branch, namely trunk.

We are now able to go live with complete features that are not completely tested, but switched off in live.  We are then able to switch the feature on in production once testing is complete, or continue developing the feature to completion with the code still being deployed to production.

The possibilities for toggles are endless, you can use them for split testing, or only directing changes to staff before switching it on to our clients. So not only does this way of thinking empower us as developers, but it also empowers the business to push change when and to whom they want.

The complete source for this example is available at https://github.com/craigew/Toggles.

Posted in Software development | Tagged , , , , , , , , | 1 Comment

Apple vs Windows for Developers

I was recently asked to motivate why I would prefer to work with an Apple as apposed to a Windows machine. My experience with the Mac is rather limited, having only come into the Mac pc stable a few months ago. However I thought this would be an easy task as I have been using it at home for development for a few months and I simply love using it. Until I sat down to actually write the motivation.

If I look at it objectively this is what I come up with.

Apple’s Magic mouse – So I really, really enjoy using my magic mouse. The gestures on the magic mouse aid in my efficiency in hand movements and keystrokes.

*nix based – I enjoy the fact that it is unix based, so using the terminal is much better than using the windows cmd window. I also just prefer the Linux type interaction. Considering our targeted deployment platform is Linux this helps me practice my linux commands more often. One could use cygwin for this on the windows machine.

Thunderbolt display – It can drive a thunderbolt, but I could get away with two Dell 27inch IPS monitors that also have a 2560×1440 resolution for the same price. Not as cool as a thunderbolt, but better value for money I think. Whether it is a thunderbolt or any other monitor the higher resolution helps my productivity due to more screen real estate.

Windows VM’s – You can run windows in VM’s on OSx, which the converse is not true (legally anyway). So this helps me as a developer doing local testing. I have multiple virtual box VM’s running on my Mac mini so I don’t clutter my base OS.

So for me it basically comes down to the following:

  • It aids in my efficiency due to the above.
  • Mac being my tool of choice at home, and I would like to get consistency to become as efficient as possible through practice. I spend hours on my Mac Mini over weekends and in the evenings, and then get to work and spend the first few minutes of my day adjusting my brain to the different shortcuts. This is particularly true of developers who are efficient in their IDE’s and navigate using shortcut keys.
  • It just works, straight out of the box everything is easy to setup and configure.
  • It is really a beautiful piece of hardware, and as a craftsman I appreciate this. I want to use tools that have been created with the same attention to detail as what I put into my software development.
Posted in Software development | Tagged , , , , , , , , , , , | 2 Comments

Something to think about when offshoring your software development

With over 6 years of experience in environments predominated by the offshoring of the software development this post is about some observations around how not to offshore your software development.

My first experience with offshoring was as a developer whose projects were being off-shored to India due to cost and the corporate strategy. This brief engagement of only a view months gave insight into the promises being made to the client during the handover phase, and then the subsequent failure to deliver on these promises in the months thereafter.

A year later and in a new job I was to become the client in the offshoring world. This led to a roller coaster 5 years. During these 5 years I was fortunate to make many trips to India and formed many friendships.

We have started to bring our Software Development back in house due to a number of reasons, and so here are my observations on how NOT to offshore your software development.

 People

Don’t offshore if you simply want a managed service offshore to replace local developers. And if you think that you don’t need to take an interest in who is working in your ODC, then definitely do not offshore.

You still need to value your local technical resources. Just because you are offshoring your development it does not mean your technical head count can be reduced to zero. You should never abdicate responsibility for your software and intellectual property. Hands on architects are still important to steer the ship and a small team of developers should work hand in hand with the offshore team using continuous integration tools.

You will most likely be replacing your experienced “expensive” local resource with a “cheap” graduate. You might think you can still get 5 of these grads for your one local resource before it becomes more expensive. That is until your resource count is through the roof and changes are taking longer than ever. And quality is not where it should be.

The offshore team are the people that are going to become custodians of your software and intellectual property. You will be spending many hours with them in telephone calls, Skype calls or instant messaging sessions. Not only, must you be able to communicate with them effectively, culture and language are a barrier, but they must have the same perspective as you when it comes to quality.

Waterfall

Don’t offshore if you are going to manage the projects using a waterfall methodology. You might think one of the draw cards for going offshore is the level to which the vendor complies with CCMI. Unless you and your offshore vendor are going to collaborate on the outputs from the CMMI process it is essentially a waste of time and only gets done for the sake of being done. You essentially end up with lots of process adding very little value.

You as the client need to aggressively investigate how to break down barriers and have rapid feedback cycles. The confusion caused by language and culture cannot be eliminated by writing wordy documents with pretty UML diagrams and throwing them over a wall. And then thinking because you are having status updates every other day and you’re tracking all your tasks in a big project plan, that your project will be a success. Quite the contrary, it will be a failure. Rapid feedback, constant communication and actively participating in the development are the only ways to ensure that you are truly getting what you want.

Agile and Scrum should be used to break down these barriers but it takes considerable effort, on both sides, to get it right.

Continuous Integration and code quality

If you cannot deploy continuously into, at least, a test environment, and you have no view of the quality of the code, then do not offshore.

You have to utilise techniques such as continuous integration to minimise feedback loops. You must be deploying working code into your testing environment at least once a day. You must have some form of code coverage to quantify the quality of your code. And you, as a client, must show interest in these reports and understand them.

Your code is an asset, not in the number of lines but rather the business value or intellectual property it represents. It is much easier, quicker and “less risky” to copy and duplicate a piece of code, than appropriately refactor the code for reuse, because the short term testing impact is minimised.

Keep track of your code coverage reports. Is the number of unit tests increasing, are the violations decreasing, is the number of lines of code decreasing? But this does not replace you being hands on when developing your software.

Tooling

Would a surgeon work on a patient with blunt knives, I think not. So why should developers work with blunt tools, below spec pc’s, outdated IDE’s or poor connectivity. If you as the client are not going to make sure that the developers are as efficient as possible then do not offshore.

Make sure appropriate infrastructure is available for development and communication purposes. The offshore developers should be part of your network; they must be able to develop using any local resource as if they were on your network. And make sure the lines between you and your offshore partner are robust and fast.

On my first trip to India, I could not believe the archaic pc’s and IDE’s the ODC was using to develop Java code. Couple this with poor link between them and us it was not wonder these guys were working ridiculous hours to get projects finished. They were just so inefficient and it was never raised as an issue.

Culture

If you are not going to make an effort to understand and bridge the cultural gap, then do not offshore.

One of the obvious differences can be represented using Hofstede’s Power Distance. Using India as an example, which has a high cultural Power Distance and South Africa, which has a lower Power Distance indicator, developers expect managers to make decisions and are uncomfortable when making discretionary decisions. Comparing this to a South African where developers are typically expected to be self-reliant and make decisions.

You have to constantly work on tactics to bridge this gap and to confirm that you are indeed bridging the gap. Tactics include always getting the offshore team to repeat their understanding to you. Having rotating members of the offshore team onsite also allows for the teams to get to know each other and make sure you make regular trips to your ODC. Experiencing each other’s cultures first hand is the best way I found to bridge the gap, and to create friendships.

Conclusion

So in closing, if you still have to worry about the people, the development methodologies, continuous integration and code quality, the tooling and the cultural issues, do you still want to offshore your software development? Offshoring does work, but do not underestimate the effort required by all parties involved.

Posted in Offshoring, Software development | Tagged , , , , , , , , , | Leave a comment