Adept Software Development

Adept: (A)pplication (D)evelopment (E)nterprise to (P)ersonal (T)ransition. It is a system I am developing to leverage Enterprise developer skills to produce stand-alone software for other market segments. This is a general software development blog discussing issues about project, architecture, design and development. The emphasis will be in Java, but many of the issues will be more general. Almost all will be technical.

http://marringtons.com

Tuesday, January 25, 2005

Using Scope

I recently read an article proposing that where possible a countdown for(;;) loop would improve efficiency without introducing variables that have a scope more large than needed. The proposal was that:
for (i = list.size() - 1; i >= 0; i--)

 

is more efficient than:
for (int i = 0; i < list.size(); i++)

 

It is more efficient, but at the cost of being more obscure, easier to misinterpret. One reader suggested using the extended for initialiser:
for (int i = 0, end=list.size(); i < end; i++)

 

This certainly returns the loop to a more understandable structure, but it is still complex and hence rather difficult to read. All this is because of a fear of cluttering the local scope with variables:
int end = list.size();
for (int i = 0; i < end; i++)

 

It's not something I'd worried about before now. I guess that is because I started with C where all local variables had to be at the top of the function before the first code. A method should be short enough that variable name confusion should not happen - if it does, your IDE should tell you. If scope concerns you, just place the whole in a scope-limiting block. That is what they are there for, after all:
  {
    int end = list.size();
    for (int i = 0; i < end; i++)
  }

 

On an interesting side note, did you know that i, j, k are still often used as temporary variables for loops because FORTRAN allowed variables starting with i, j or k to be used as integers without being defined?

Wednesday, January 19, 2005

For now or While away?

The venerable for(;;) loop construct was invented for C in the 70's and has survived unchanged through C++ to Java. It was originally designed to be more flexible than the counter loop constructs for earlier languages such as BASIC or FORTRAN, which typically only allowed integer counters between a range with an optional step.
FOR i between 1 and 20 step 3

 

was the same as
for (i = 1; i &lt; 20; i += 3)

 

Where the for(;;) loop shines is in other boolean loops.

But consider:

for (o = first(); o != null; o = next())

 

Here we are rapidly losing readability. In truth the for(;;) loop was never very logical. Generations of IT teachers have had to explain that part one occurs above the loop, part two as the first statement of the loop and part 3 at the end. In an industry where logic rules, we have to take the for(;;)loop on faith. The above loop is easier and quicker to read as:

MyObject o = first();
while (o != null)
  {
    ...
    o = next();
  }

 

By all means use for(;;)for simple iterations, but as soon as the logic becomes complicated, consider changing it to a while() loop.

Monday, January 10, 2005

Don't Assume a Getter is Benign

As a development manager, team leader and active developer I get to see a lot of code written by others. One of the most common flaws, as I see it, is the repetitive overuse of getters.
If (myBean.getDate() != null && ! myBean.getDate().equals( today))
    showDate( myBean.getDate());

 

I have seen methods where the same getter has been called more than twenty times as it was needed in complex business logic. There is more than one problem with this:
  1. Even if the getter is benign now - meaning that all it does is retrieve package private data, you can't be sure it will remain so. If the call later causes database access or an RMI call it can cause significant response times.
  2. It makes the code appear far more complex than it actually is, so.
  3. General readability is lowered.
So save yourself a headache – not to mention support staff and possible class clients – and use a local variable. Not only do local variables address the above points, but they also encourage for code self-documentation since the variable name can be more descriptive than a more generic getter.
Date initiationDate = myBean.getDate();

If (initiationDate != null && ! initiationDate.equals( today))
    showDate( initiationDate);

 

Tuesday, January 04, 2005

To Bean, Will Bean, Has Bean - JavaBean

One of the 'patterns' Sun introduced for Java was the JavaBean. To be a bean, an object must have:
  1. All data private
  2. Data accessed by getters and setters only.
  3. The get pattern is the data name, capitalised and preceded by 'get'.
  4. The set pattern is the data name, capitalised and preceded by 'set'.

Example:

class MyBean
  {
    private String stringData;
    public String getStringData() { return stringData; }
    public String setStringData( String to) { stringData = to; }
  }

 

Waking Up and Smelling the JavaBean JavaBeans are useful in their place, but embracing the pattern as a blanket-fix undermines their usefulness and restricts your options. So weigh up the pros and cons for any given situation, and don't use a JavaBean unless the infrastructure calls for one.
Pro Con
Data Cop: Java's policy is to act as a police force for your library. Java assumes that all users of your library are criminals who will cheat and abuse the internals and interfaces if they are allowed. By using getters and setters you have more access control over the data than if it were public. ...The Lazy Cop: At best, Java is a terse policeman – at worst, ineffective. Given that Java does not have a concept of friends (except package private), most setters are public. Why put up with the Gestapo marching through your neighborhood, if they don't notice all the theft going on under their noses? Oh, and using the constructor to load rather than having setters is the same as using final for the resulting data.
Choice Without Consequence: When you use getters and setters, you give the library user more freedom to change the internals without being directly affected – data from a database, for example, can be lazy loaded inside the getter or retrieved each time it is called - all without callers of the interface being aware. ...But Don't Get Lazy: While it is poor practice, I have seen many, many developers call a getter repeatedly rather than save it as a local variable. If the class owner changes a getter from retrieving local class instance data to reading a database, the overheads of bad usage practice change from minor to enormous. If you are publishing beans to be used as black boxes (as ActiveX is used for Windows programs), by all means use getters and setters. In all other cases their use is questionable. Sure, the user of a class will need to change their code if they upgrade to a newer version, but this gives them an excellent opportunity to review the code that needs to be changed. If an instance field becomes private they will know to change to an accessory method. Reviewing the related JavaDoc will tell them what is happening so that they can adjust their usage code accordingly. If the process were transparent they would plug in the new class and not even look at the usage.
The Square Peg Fits: Finally, the reason for the bean design is to provide a clear standard for factory methods and non-Java components (such as XML) to be able to access or modify Java internals. Ah, the rich aroma of plug-and-play. ...But Not Always As Well As The Round: When the infrastructure requires a bean, use the bean pattern with setters and getters. When it is not, use other data storage and retrieval patterns. A discussion of these patterns will keep for another day. There are times when you should access the data directly, times it should be copied into a DTO (data transfer object) and times you should use retrieval methods not using the getXXX() pattern.