Developing with Sencha Ext GWT - Don't do it!

Impedence Mismatch for Client Side Views

The view technology for the web is to use HTML for the view, CSS for the styling of the view, and Javascript/JSON for client side functionality, objects and data.This stuff is easy and even 14 year olds at school can create resonable web pages using this technology.

Ext GWT uses Java classes, Layout Managers, Layout Containers and Hashmaps. Ah? you may ask. Well, you're damb right. If you've ever used Java Swing you'll know what I'm talking about. There is a reason why Java Swing never took off for creating web application. And that is because it is far eaier to create great looking web applications using Html, CSS and Javascript, than it is using LayoutManagers, RPC, and all that sort of crap.

Devloping sites using HTML, CSS, and Javascript frameworks is easy peasy.

However if you're using Ext GWT and you want do do anyting funky then it is almost impossible.

Also because of the structure of using Java code on the client and the server, you have to make sure that your Java classes can be serialiszed over the wire to the generated cleint side javascript application. There are just loads of classes which are 'black-listed' because they GWT compiler will not compile them to javascript (e.g. java.util.Calendar).

This means you have to convert any entity classes to some intermediatry class then can then be used in the serialization RPC mechansim. So on the server side you're working with say JPA entity objects, then you have to convert these to gxt ModelData objects, then send these over the wire, and convert them back to Enity objects when they come back to the server.

In otherwords what is generally a simple job, becomes time consuming, error prone, and just plain crap.

Conversion from ModelData (Hashmap) to Server-side Entities to Database Entities

This is one of the biggest pain-in-the-arse areas that gxt has. ModelData is just a Hashmap where you set values against keys. The reason why you have to use ModelData is because the RPC mechanism probably wont be able to deal with your normal domain object, particulary if they use runtime annotations such as JPA does. And this is because Ext GWT does not know how to serialise almost anything that is useful, because the serialization mechanism converts  Java source into Javascript, which means that it can not convert any client side specific stuff (such as persistance annotations).

So rather then use the world's standard client side model framework (known and JSON), Gxt/GWT have decided in their wizdom to create a whole new data architecture based on Hashmaps. So for every object you want to send over the wire you have to convert it into a wire friendly format (but not JSON because your Sencha classes do not work with JSON).

So the real big pain in the arse about all this is that if you get quite a complicated object graph from the database that you want to pass streight back to the client, you can't! You've got to write a load of code to convert it into 'view' objects. And that my friends, take a lot of time.

How crap is that, you may ask. Totally says I.

Also keep in mind that because some classes will not automatically be converted to the Ext-GWT RPC friendly format you'll have lots of fun spending many hours working out why you're getting serialization excpetions, and why your code does not work.

In fact, you should probably add 45% more time to your estimates if you working with Ext-GWT. Don't believe me? Then try this test:

Starting from a blank install of Eclipse the task is to create a "hello world" application. First page presents the user with a text field and a button. When the user clicks the button the contents of the text box is sent to the server via AJAX and on callback a dialog box pops up saying "Hello ContentsOfTextBox". First try that using normal HTML, Javascript (maybe JQuery), and server side Java. Then try it using Gxt.

I'll put money on it that the JQuery way of doing this will be completed before the Gxt framework is even installed.

If you want another test (because you're so dumb you think that once the setup cost have been concidered then gxt will be much more efficent), then try this test:

Get your best developer to create a Ext-GWT effect that looks like any of these JQuery effects. Then take a look at how long it took them to do it, and how much code they had to write. Personally, I would be supprised if they could do it at all. 

Setting the Width of Form Fields

Setting different width for form fields is fairly easy in HTML. The following form is...

First Name:
Age:

...is made up from the following styled HTML snippet. The important bits are hightlighted in bold.

<div style="border: solid 1px black;
           width:300px;
           padding:5px;
           font:15px tahoma,arial,helvetica,sans-serif;">

    <div style="padding-top:5px;">
       <span style="width:100px;float:left;">
            First Name:
      </span>
      <input type="text"/>
    </div>

    <div style="padding-top:5px;">
      <span style="width:100px;float:left;">
            Age:
      </span>
      <input type="text" size="5"/>
    </div>
</div>

In GXT, things are a little bit more complicated. To get the same effect you'll have to use the FormData object when adding the field to the FormPanel:

private LayoutContainer getNameAndAgeForm()
{
  final TextField<String> firstName = new TextField<String>();
  final TextField<Number> age = new TextField<Number>();
 
  firstName.setFieldLabel("First Name");
  age.setFieldLabel("Age");
 
  final FormPanel formPanel = new FormPanel();
  formPanel.setFrame(false);
  formPanel.setHeaderVisible(false);
  formPanel.setBodyBorder(false);
  formPanel.setLabelWidth(100);
 
  formPanel.add(firstName);
  formPanel.add(age, new FormData(100,-1));
 
  return formPanel;
}

Note the size in the <input> tag relates to the width in number of charactors, whereas in GXT the width relates to pixcels.

Button Colors

You might think that that the following GXT code would set the color of the buttong to yellow:

Button btn = new Button("Hello World");
btn.setStyleAttribute("backgroundColor", "yellow");

And would produce HTML like this:

<button style="background-color:yellow">Hello World</button>

But you would be wrong. It results in no differance to the button color. The HTML produced is:

<table cellspacing="0"
           role="presentation" id="x-auto-250"
           class=" x-btn x-component x-btn-noicon x-unselectable "
           style="background-color: yellow;" unselectable="on">
   <tbody class="x-btn-small x-btn-icon-small-left">
       <tr>
            <td class="x-btn-tl"><i>&nbsp;</i></td>
            <td class="x-btn-tc"></td>
            <td class="x-btn-tr"><i>&nbsp;</i></td>
      </tr>
      <tr>
         <td class="x-btn-ml"><i>&nbsp;</i></td>
         <td class="x-btn-mc">
            <em unselectable="on" class="">
              <button style="position: relative; width: 60px;" type="button" class="x-btn-text " tabindex="0">Hello World</button>
            </em>
         </td>
         <td class="x-btn-mr"><i>&nbsp;</i></td>
     </tr>
     <tr>
          <td class="x-btn-bl"><i>&nbsp;</i></td>
          <td class="x-btn-bc"></td>
          <td class="x-btn-br"><i>&nbsp;</i></td>
      </tr>
   </tbody>
</table>

In other words, you've just styled a <table> element, and your code has no effect on the Button.  You can't change the color of a Button in GXT.

Form Layouts

Here is a common and simple form layout (shows in Firefox - not bothered to optimise for IE, Chrome, etc. But I hope you get the point). Updating the HTML and CSS for working with all browsers will probably take about another hour.

Field 1:
Field 2:
Field 3:
Field 4:
Another:

Time taken using HTML and CSS: 20 minutes. . Here is the HTML:

 <div style="height: 160px; width: 580px;">
    <div style="height: 65px; width: 565px;">

        <div class="formBox">
            <div class="pad5">
                <div class="label">Field 1:</div>
                <input type="text" />
           
</div>
            <div class="pad5">
                <div class="label">Field 2:</div>
                <input type="text" />
           
</div>
        </div>

        <div class="formBox" style="float: right;">
            <div class="pad5">
                <div class="label">Field 3:</div>
                <input type="text" />
           
</div>
            <div class="pad5">
                <div class="label">Field 4:</div>
                <input type="text" />
            </
div>
        </div>

    </div>


    <div class="formBox" style="width: 95%;">
        <div class="pad5">
            <div class="label" style="vertical-align: top;">Another:</div>
            <textarea cols="41"></textarea>
       
</div>

    </div>
</div>

Here is the CSS:

<style>
input
{
  border:solid 1px #99BBE8;
}

div.formBox
{
  float:left;
  widht:10em;
  margin:5px;
  border:solid 1px #99BBE8;
  background-color:#DFE8F6;
}

div.label
{
  font: 12px tahoma,arial,helvetica,sans-serif;
  width:100px;
  display:inline-block;
}

div.pad5
{
  padding:5px;
}
</style>

Here is the code to produce the same form layout in GXT:

final TextField<String> field1 = new TextField<String>();
field1.setFieldLabel("Field 1");

final TextField<String> field2 = new TextField<String>();
field2.setFieldLabel("Field 2");

final TextField<String> field3 = new TextField<String>();
field3.setFieldLabel("Field 3");

final TextField<String> field4 = new TextField<String>();
field4.setFieldLabel("Field 4");

final TextArea textArea = new TextArea();
textArea.setFieldLabel("Another");

final FormPanel leftPanel = new FormPanel();
leftPanel.setStyleAttribute("margin", "5px");
leftPanel.setHeaderVisible(false);
leftPanel.add(field1);
leftPanel.add(field2);

final FormPanel rightPanel = new FormPanel();
rightPanel.setHeaderVisible(false);
rightPanel.setStyleAttribute("margin", "5px");
rightPanel.add(field3);
rightPanel.add(field4);

final LayoutContainer textFieldColumnContainer = new LayoutContainer();
textFieldColumnContainer.setLayout(new ColumnLayout());

textFieldColumnContainer.add(leftPanel, new ColumnData(.5));
textFieldColumnContainer.add(rightPanel, new ColumnData(.5));

final FormPanel textAreaPanel = new FormPanel();
textAreaPanel.setStyleAttribute("margin", "5px");
textAreaPanel.setHeaderVisible(false);
textAreaPanel.add(textArea, new FormData(550,-1));

final LayoutContainer page = new LayoutContainer();
page.add(textFieldColumnContainer);
page.add(textAreaPanel);

add(page); // Add the content page to whatever your using...

Time taken to do this? 30 minutes. So time is not really an issue. You also still have the issues of it looking OK in some browsers but not in others. OK in Firefox, not so good in Chrome.

For me the benifit of not using GXT is that you can optimise for different browsers much easier than if you use GXT. For example you can change the sizing CSS values to 'em's or percentages. With GXT your stuck with Sencha's implementation of the ridged use of either pixel width or percentages.

The other great thing about not using GXT is that anybody can understand the HTML version (i.e. millions of people), while only someone familiar with GXT will understand the GXT version (i.e. a few thousand people).

The other advantage is that the HTML version needs no special setup while the GXT version needs a development environment, compiler and applicaiton server. With the HTML version you can just cut and past the code into an HTML page and view it streight away.

GXT Radio Buttons

So how do you get the value from a GXT radio button. In normal HTML you may have a collection of radio buttons such as:

<input type="radio" name="color" value="RED" />Red</br>
<input type="radio" name="color" value="YELLOW" />Yellow</br>
<input type="radio" name="color" value="GREEN" />Green</br>

Then you can use a bit of javascript to show the value of the clicked button:

<script type = "text/javascript">
 $(document).ready(function()
 {
    $('input[name="color"]').click(function(event)
    {
      var valueOfClickedButton = event.target.value;
      alert(valueOfClickedButton);
    });
 });

</script>

Easy.

How do you do this in GXT? The problem is with GXT's Radio class. You would expect the getValue() method to return the value set (i.e. RED, YELLOW or GREEN from the HTML example above). But the getValue() and setValue() methods are booleans and used to set whether the Radio is checked or not.

You may think that using the getName()method could be used. But you would be wrong - this method will return something like "gxt.RadioGroup.n" no matter what you did in setName(String). So you how about using getFieldLabel()? Well, again, no matter what you did in setFieldLabel(String) it will always return an empty String. 

To get the value of a clicked radio button in GXT you must use the setValueAttribute(String) method. May be obvious once you know, but getting to know is the difficult bit. Check out the following code snippet:

 

final Radio red = new Radio();
red.setBoxLabel("Red");
red.setValueAttribute("RED");

final Radio yellow = new Radio();
yellow.setBoxLabel("Yellow");
yellow.setValueAttribute("YELLOW");

final Radio green = new Radio();
green.setBoxLabel("Green");
green.setValueAttribute("GREEN");

final RadioGroup colorsGroup = new RadioGroup();
colorsGroup.setFieldLabel("Colors");
colorsGroup.add(red);
colorsGroup.add(yellow);
colorsGroup.add(green);

colorsGroup.addListener(Events.Change, new Listener<BaseEvent>() {
  @Override
  public void handleEvent(BaseEvent be)
  {
    final RadioGroup radioGroup = (RadioGroup)be.getSource();
    
    final Radio clickedRadioBtn = radioGroup.getValue();

    // 'name' will equal "gxt.RadioGroup.n"
    final String name = clickedRadioBtn.getName();

    // 'fieldLabel' will equal "" - empty string
    final String fieldLabel = clickedRadioBtn.getFieldLabel();

    // 'value' will always be true
    final boolean value = clickedRadioBtn.getValue();

    // Correct !!! 'valueAttribute' will equal the color set via setValueAttribute(String)
    final String valueAttribute = clickedRadioBtn.getValueAttribute();
  }
});

 

Inconsistances - FormBinding

If you have a form full of lots of fields, you can use a FormBinding object to bind a ModelData object to those fields. So long as the names of the fields and the property keys of the model data match then the binding will be automatic and data will be transfered from the field to the model and visa versa. Neat. 

But FormBinding only works with a FormPanel. If you're using a FieldSet, then you're back to the long handed method of reading and writting values.

 

  1.  FormBinding binding = new FormBinding(panel);  
  2.  binding.autoBind();  
  3.  binding.bind(stock);

 

Here is a short list of sites that could not be developed using Ext-GWT:

  1. Twitter
  2. Facebook
  3. BBC
  4. <Any other cool looking website>

But if you still wanting to use Gxt then here is a list of places where it would be a good option:

  1. Boring back-office systems
  2. Sites for which you don't want users
  3. Consultancies looking to make loads-o-money from Change Requests

Difficult to run Cleint side Tests Against (e.g. Selinum)

Debugging and Maintenance

Debugging and Maintenance

Firstly, lets answer the question; What is code is for? Code is for humans to read, debug, maintain, and understand. This is the key measure of good code - is it easy to understand what is going on and to maintain.

This is one of the most important measurements of great code verses crap code, and generally under this heading, crap code comes from old C++ developers.

Let me give you two examples of code that does the same thing, and see if you an work out which one is easier to debug:

LatLog location = LocationUtil.getLatLong(db.getCustomer("ABC")
                           .getAddress()
                           .getGetPostcode());

LatLog mapCenter = LocationUtil.getLatLong(postcode);
int mapZoomLevel = 0;

int zoom = 0;
if(location == null)
{
   location = UK_LAT_LONG;
   zoom = 15;
}


 

final Customer customer = db.getCustomer("ABC");
final Address homeAddress = customer.getAddress();
final Postcode postcode = homeAddress.getPostcode();

LatLog mapCenter = LocationUtil.getLatLong(postcode);
int mapZoomLevel = 0;

if(location == null)
{
    mapCenter = UK_LAT_LONG;
    mapZoomLevel = 15;
}

So egnoring all the obvious bug errors lets look at the major signes of bad coding practice.

Inline Code

The most obvious and most anoying thing about the first code snippet is that the entire getting of the customer's location is done in a single line. If there are any faults with this line (such as a NullPointerException), the debugger or stack trace will only identify the line and not the partcular method. However on the second snippet, because the stacktrace will tell you the line number you will know at which point the problem occured.

Untidy Code

Secondly the second snippit is easier to read simply because it's layed out more neat and tidy. The '{' line up which makes it easy to see where blocks start and end, and the indentation makes it easy to see what sections of code belong together.

Nameing of Variables

Code such as:

   Address address = ...

Does not give the reader any indication of what the address vaiable is or used for. A better way is:

    Address homeAddress = ....

 An even better way is:

    final Address homeAddress = ...

Which further indicates that the homeAddress value will not be re-assigned latter on in the code.

Probably the worst example of variable declaration is:

    Address a = ...

Which, once the reader has read past this line, does not even give any idea of the type of values that can be assigned to 'a'

Here is the worst way of writing out the code section above:

String pc = LocationUtil.getLatLong(db.getCustomer("ABC")
                       .getAddress()
                       .getGetPostcode());

LatLog l = LocationUtil.getLatLong(pc);
int z = 0;

if(l == null){
    l = DEFAULT;
    z = 15;
}

99% of code written like this comes from people who first learned to write code in C. Those people really do find it hard to write good clear and understandable code.

GWT, Gxt and Selenium Testing

If there is one thing I've learned about using Selenium to test gxt applications, is that there's a lot of pain and blood involved.

I've spend the best part of 5 days working out how to use Selenium Java WebDriver, to test a very complicated application. An application that included Dialog windows, ToolBars, Wizard Dialogs, and the usual array of Ajax, forms, grids and tables.

The journey started by having to understand how GXT renders JavaScript into HTML pages. When you are want to set element IDs in your code against most objects (like Button) - guess what, they don't appear on the <button> tag at all.

The next step is getting the Firefox WebDriver to work with the GWT Development Mode plugin for Firefox to work seemlessly.

In this artical I will divaluge all these secretes and provide you with a downloadable Maven project so you can see extactly what I've done.

But, firstly, to give a bit of context, I want to breafly mension the structure of the Selenium tests.

The tests use the java WebDriver and JUnit to simulate user interaction. The structure of the Seleiumn code uses the Page Object Model which means that each part of of the web application to be tested will have a corrisponding Selenium Page Object. So for example the ToolBar of the Gxt application will have a ToolBarPageObject which has methods for interacting with the toolbar (clicking buttons etc).

Buy combining these Page Objects together you can test your application much more effectivly and maintainably than using the Selenium UI to record scripts. This is because if you change something on your web app (say the toolbar for example), then, using Selenium UI your entire script will be busted. Whereas if you used Page Objects you only need to update the page object representing your toolbar - ToolBarPageObject.

This is just a bit of usefull background info for when you look at the source code downloadable at the bottom of this page.

So to start:

How Gxt Renders IDs on HTML <Form> Elements

OK, so the first and possibly the most supprising thing you need to know, is that when you try and put an ID on a form element such as with :

TextField<String> nameField = new TextField<String>();
nameField.setId("MY_ID");

The ID does not, contrary to what you might expect, get put on the corrsponding <input> HTML tag, but gets assigned to a <div> tag which encloses the <input> tag.

Here is the output from gxt:

<div role="presentation" class="x-form-item" tabindex="-1">

    <label style="width:75px;" class="x-form-item-label">First Name:</label>

    <div role="presentation" class="x-form-el-MY_ID" id="x-form-el-MY_ID">

        <div role="presentation" class="...." id="MY_ID" style="...">
            <input type="text" class="..." id="MY_ID-input" style="...">
        </div>

    </div>
    <div class="x-form-clear-left" role="presentation"></div>
</div>

So this is tip No. 1:

  • Just because you specify a ID on a object in gxt does not mean that the ID will render to the most oviouse corrisponding element in the output HTML

However, there is more. As you may have noticed from the highlighted sections above, the ID that does get put on the input tag gets appended with "-input".

Now, I'm not sure why this is but I would guess its probably because the guys at Sencha are not the brightest cookies in the tin, and didn't realise that some people may want to identify certain obvious elements with the ID tag they specified in their code. But there again, I suppose you could argue that people who want to develop web pages via a Java Swing type of framework (e.g. using LayoutManagers), arn't the brightest lights either.

But to be a little bit fair, they do render the TextField object into a nicely formatted label and input field combination. So maybe they just got confused because they were a bit drunk and pulling a late one on Friday night.

So Tip No. 2:

  • Just because you specified your ID as ID_ABC does not mean that it will render in HTML (or the DOM if you're being picky), as ID_ABC.

Bonus Tip:

  • If you are going to use GXT then add 40% to your estimates.

So where does your ID go? Well if you specify an ID on a Button object:

Button button = new Button("Click Me!");
button.setId("BUTTON_ID");

It gets put on the enclosing table object! Weird hu?

Here, with the intresting bits in blue, is how GXT renders the Button class to HTML:

<table cellspacing="0" role="presentation" id="BUTTON_ID" class=" x-btn x-component x-btn-noicon ">
    <tbody class="x-btn-small x-btn-icon-small-left">
    <tr>
        <td class="x-btn-tl"><i>&nbsp;</i></td>
        <td class="x-btn-tc"></td>
        <td class="x-btn-tr"><i>&nbsp;</i></td>
    </tr>
    <tr>
        <td class="x-btn-ml"><i>&nbsp;</i></td>
        <td class="x-btn-mc">
          <em class="" unselectable="on">
            <button class="x-btn-text " type="button"
                   style="position: relative; width: 60px; " tabindex="0">
               Click Me!
            </button>

          </em>
        </td>
        <td class="x-btn-mr"><i>&nbsp;</i></td>
    </tr>
    <tr>
        <td class="x-btn-bl"><i>&nbsp;</i></td>
        <td class="x-btn-bc"></td><td class="x-btn-br"><i>&nbsp;</i></td>
    </tr>
    </tbody>
</table>

How to Use the Firefox WebDriver

Firefox is the best browser for running Selenium tests. This seems to be because it's open source so gets the best support.

When GWT runs in development mode, the browser you use to view the app needs the GWT plugin. However, if use just use the FirefoxDriver with Selenium, you will find it starts a copy of vanilla Firefox that does not contain the plugin.

So to get Selenium to work with Firefox must first make sure you have the plugin installed in your Firefox browser and then you must create a Firefox profile. The way to create a Firefox Profile is explaned here. But the short answer is to run:

    firefox.exe -p

from the command line. Then use the dialog box to create a profile. Save the profile to a convenient directory for your tests. The profile will contain all the plugins your copy of Firefox has, and some settings info, so before doing this you should disable or remove any plugins that are not relevent (e.g. Adobe), and disable the automatic updates (otherwise every time you run your tests the browser will tell you it needs to be updated).

So now you can start using the FirefoxDriver to drive your tests:

final File profileDir = new File(FIREFOX_PROFILE_DIR);
final FirefoxProfile firefoxProfile = new FirefoxProfile(profileDir);
final WebDriver driver = new FirefoxDriver(fp)
...

So now you should be able to start runing your tests...

If only it was that easy!

The Gxt Selenium Tests

So as you are probably aware if you have tried to run Selenium tests against Gxt, things are not as easy as they may seem. So here are some tips to get you started.

  • Make sure you use the Page Objects pattern.
  • Whenever you've defined a LayoutContainer that you want to run some tests against, make sure you give it a unique ID.
  • Make sure you give every form, form field, button, menu option etc, a unique ID.
  • Try to avoid using EditorGrid whenever you can. This is because its very hard to get working reliably, but I will show you what I did just incase you are crazy enough to try.

Accessing Form Fields

Buttons:

Gxt Code:

final Button button = new Button("Click Me");

button.setId("click-me-button");

Selenium Code:

@FindBy(id = "click-me-button")
private WebElement clickMeButton;

...

@Test
public void testButton()
{
    clickMeButton.click();
}


TextField, NumberField, etc:

Gxt Code:

final TextField<String> nameField = new TextField<String>();
nameField.setId("name-field");
nameField.setFieldLabel("Name");
...

Selenium Code:

// Note the addition of "-input" which is added by gxt.
@FindBy(id = "name-field-input")
private WebElement nameField;

...

@Test
public void testField()
{
    nameField.click(); // See note below
    nameField.sendKeys("Adam Davies");
}

Note: the click() call is not strictly required, but the user will either click or tab to the text field so its best to do that in your tests just to ensure that any corrisponding javascript events are fired.


ComboBox:

Gxt Code:

// CountryCombo is a subclass of SimpleComboBox<String>
final CountryCombo countryCombo = new CountryCombo();
countryCombo.setId("country-combo"); 
...

Selenium Code:

@FindBy(id = "XXXX")
private WebElement countryCombo;

...

@Test
public void testCountryCombo()
{

}

 

EditorGrid Cells:

For EditorGrid cells is a bit more difficult, but generally you have to get the DIV that the cell relates to, click it, which results in gxt generating a edit field (e.g. a TextField), and then you can get the active Field by the class name x-form-focus. It seems that gxt in all it's wizdom put that class against the <INPUT> element when generating an edit field.

The following code demonstates this techique:

 

Note: The generall format that gxt uses to identify cells in a grid is something like this:

x-grid3-col-name row1-col2 row1-col3
row2-col1 row2-col2 row2-col3
row3-col1 row3-col2 row3-col3

Downloads

 

Abstraction and Modulization

Abstraction and Modulization

Here we are talking about how our code is stuctured within each tier and within each class.

It is key charactoristic of great code that the code's abstractions are strcutrued at the same level of functionality. Lets clear this up with an example. Far to many people write methods that do more than a single thing. So they will write a method that says creates a  Customer, and that method will first check that the data is OK, then go on to log the timestamp of when and which user created the customer object, then it may send of an email to inform some manager that a customer has been added and then write the data to the database and log a sucessful insert to the system log.

So I wont bore you by writing out a complete example because you could find lots of them all over the place.

How such a method should look is like this:

public class CreateCustomerService
{
  public createCustomer(final Customer customer, final User user)
  {
    validate(customer);
    validate(user);

    createAttempLogEntry(customer, user);

    addCustomerToDatabase(customer);

    createSuccessLogEntry(customer, user);

    postEmail(customer);
  }

... implementation of methods above...
}

The important thing to take home form this example is that all the methods operate on the same level of abstraction. Even if the validateUser(user) method is only a couple of lines of code it should still be brought out into it's own method because this maintain sinergy with the level of abstraction we are looking for.

This make the code more readable and more modular because we can obviously reuse many of the method in different circumstances.

To Pass Parameters or to use Object State.

One of the questions the always come up from time to time is, is it better to pass parameters around method-to-method within an class or should you use object state/instance variables and invoke the methods without parameters (such that they operate on the object state).

The most meaningful answer I can give you for this is that if you pass them around then there is no need to rely on state, and thus it is easier to make these methods final static methods which lean themselve better to optimisation. Also passing parameters around clearly shows when reading the code what data the method is working with. This, to my mind, is a good enought reason in itself. The easier code is to read and understand, then the better the code is. It is as simple a test as that.

If however, you are using templating or overriding methods from a parent class, then you may need to use instance variables to data communication.

In general I would say the rule would be to only use object state as a second option. Programes are far more extendable and flexible if code does not rely on state.

 

Debugging and Maintenance

Firstly, lets answer the question; What is code is for? Code is for humans to read, debug, maintain, and understand. This is the key mesure of good code - is it easy to understand what is going on and to maintain.

This is one of the most important measurements of great code verses crap code, and generally under this heading, crap code comes from old C++ developers.

Let me give you two examples of code that does the same thing, and see if you an work out which one is easier to debug:

  LatLog location = LocationUtil.getLatLong(db.getCustomer("ABC")
                           .getAddress()
                           .getGetPostcode());

  LatLog mapCenter = LocationUtil.getLatLong(postcode);
  int mapZoomLevel = 0;

  int zoom = 0;
  if(location == null)
  {
    location = UK_LAT_LONG;
    zoom = 15;
  }

 

final Customer customer = db.getCustomer("ABC");
final Address homeAddress = customer.getAddress();
final Postcode postcode = homeAddress.getPostcode();

LatLog mapCenter = LocationUtil.getLatLong(postcode);
int mapZoomLevel = 0;

if(location == null)
{
    mapCenter = UK_LAT_LONG;
    mapZoomLevel = 15;
}

So egnoring all the obvious bug errors lets look at the major signes of bad coding practice.

Inline Code

The most obvious and most anoying thing about the first code snippet is that the entire getting of the customer's location is done in a single line. If there are any faults with this line (such as a NullPointerException), the debugger or stack trace will only identify the line and not the partcular method. However on the second snippet, because the stacktrace will tell you the line number you will know at which point the problem occured.

Untidy Code

Secondly the second snippit is easier to read simply because it's layed out neat and tidy. The layout of the second snippet gives us the oppertunity to give our variables proper names which indicate what they are for. E.g.:

     Address homeAddress;

Use Features of the Language

Most Java programmer underuse the final keyword. This is used to indicate that the variable will not change its value. So by looking at the second snippet you can instantly see that the only modafiable variables are mapCenter and mapZoomLevel. This is great for debugging because once you are satified that the final variables have been assined correctly you do not have to worry about them getting reassined to some erroneous value latter on. This becomes more obvious and important when you are working with large code bases that someone else wrote. At a minimum, if the coder used the finally keyword consistantly you know that they know what they're doing. When you meet coders who refuse to use the final keyword even after you've explained what the benefits are you can pritty much mark them down as bozos.

Another good use of the final keyword is when it's used to indicate that a class or method can't be extended. This shows that the original developer put some thorough into how his code should be maintained and/or extended over time.

Additionally, there are other benefits to using the final keyword which code optimizers will pickup on and use to optimise the code (for example final methods can be repeated and in-lined everywhere by the optimiser during profiling and compile time because they can't be polymorphic).

Test Artical

Hello

 

Custom <p/> Elements

class is code-block

class is cmd-block