The requestor pattern: avoid looping twice

Posted in Design Patterns by ary on the March 26th, 2008

In my quest for making every piece of code testable, I run across the requestor pattern. You won't find it doing a Google search. I first saw it in many places in JDT's source code. The idea is separating an extraction of information (a processor) from it's actual processing (a requestor).

For example, JDT has a class named SourceElementParser that parses a source file and notifies it's top-level memebers, like classes, methods and fields. This class only does the parsing job and notifies the result to an ISourceElementRequestor, which has methods like enterType, exitType, acceptField, etc. In this way, the extraction of the top-level members is separated from what is actually done with that information, allowing testabilty of the processor by mocking the requestor.

Also, as the top-level members are discovered, they are notified to the requestor. Another possible implementation could be that the job done by SourceElementParser would return a tree structure representing the top-level members. This tree structure could then be processed by any class wishing to use it. The problem with this approach is that you loop twice: first for building the structure, then for processing it.

A second example is a processing REST requests. Imagine a simple contacts service, where you can retrieve all the contacts, create, edit, or delete one. The URLs could be ".../all", ".../create?id=...&name=...", etc. The requestor pattern solution is the following: a class that parses an URL and notifies interesting, object oriented information to a requestor.

public class RestProcessor {
  public void process(String url, IRestRequestor requestor) {
    if (".../all".equals(url)) {
     requestor.getAllContacts();

    }

    // ...

  }

}

public interface IRestRequestor {

  void getAllContacts();

  void createContact(String name);

  void editContact(int id, String name);

  void deleteContact(int id);

}

Yet another example: treemaps. Given an array of numbers, tell in which rectangle to position them. The class responsible for doing this could return an array of rectangles, but if the numbers to process are a lot, then two loops will happen: one for the calculation of the rectangles, the second for the actual use of them. Using the requestor pattern is straight forward:

public class TreemapProcessor {

  public void doTreemap(double[] numbers,
    double width, double height,
    ITreemapRequestor requestor) {
      // ...
  }

}

public interface ITreemapRequestor {

  void position(int numberIndex,
    double left, double top,
    double width, double height);

}

Java tips learnt from Eclipse

Posted in Design Patterns,Eclipse,Programming by ary on the November 16th, 2007

Here are some Java tips for making your code more beautiful, understandable, reliable and maintable. They are in no particular order.

  1. Suppose your code will be read by somebody else. Even if you are working on a project on your own, it's worth commenting properly your code, using interfaces and trying to make your code understanable. That somebody else might be you: in a couple of months you won't remember all the details of your implementation without good comments.
  2. Comment properly your code: try writing the comment of a function or class before getting into implementation details. That will also give you a better understanding of the problem. Appart from this, there are some very useful comments:
    • This interface is not intended to be implemented by clients. Sometimes interfaces are used to hide implementation details. This kind of comment is used to tell the user about this.
    • This interface may be implemented by clients. It's almost the opposite of the previous point, except that the library may already provide some implementations.
    • This class is not intended to be instantiated by clients. Some classes are used for internal purposes or as results of method invocations. This tells the user they are expected to obtain instances of the class, not to create them.
    • This class is not intended to be subclassed. Even if the class is final, this method tells the user it's not correct to subclass some class, because it may lead to poor performance or incorrect behaviour.
    • You can obtain an instance of this class/interface from Foo. In case of an interface or a class that is not intended to be instantiated, this helps the user get instances of them.
    • See Foo. This tells the user the referenced class is somehow related to the commented class. Even if the referenced class is already mentioned in the general comment, these kind of references are more visible than some word in a big comment.
  3. Provide clean interfaces between different modules of a system. Typical modules are UI and logic (or core). As much as possible, these modules should communicate using interfaces in order to hide implementation details.
  4. Use internal packages. Classes that are not supposed to be used outside of a module should be in a separate package hierarchy. Eclipse usually uses the name "internal" for this purpose. For example, in JDT, there's "org.eclipse.jdt.core", "org.eclipse.jdt.ui", and "org.eclipse.jdt.internal.core" and "org.eclipse.jdt.internal.ui". Note that "internal" is the root of all internal packages; you should not name the internal packages, for example, "org.eclipse.jdt.core.internal" and "org.eclipse.jdt.ui.internal". This makes it easier for users browsing the packages to recognize internal packages.
  5. Use interfaces. Interfaces may have different purposes:
    • Provide different implementations for the same goal. The typical example is a list, which may have different implementations for different performance use cases (LinkedList, ArrayList, etc.).
    • Allow criteria modification. For example, a sort function may accept a Comparable interface in order to provide any kind of sort criteria, based on the same algorithm.
    • Hide implementation details. This also makes it easier for a user to read the comments, since in the body of the interface there are only methods, fields and comments, no long chunks of code to skip.
  6. Use the I prefix for interfaces. This maks it easier for a user to recognize an interface.
  7. Treat interfaces that have one implementation differently. Usually interfaces that are used to hide implementation details have a single implementation in the whole system. In these cases:
    • Don't prefix a name with implementation details. For example, there could be an IUser interface which has an implementation based on a database. Don't name it DatabaseUser if the chances of changing the implementation are very low; User is enough, with a comment saying "implementation of IUser using a databasea". Long names are harder to read. The User class should be in an internal package.
    • Use casts without fear. You interfaces return and accept IUser instances. Since they are interfaces, you might think you need to put in the IUser interface every method needed to accomplish client tasks as well as internal tasks. This is not true. Provide interface methods for things a client might need, and in method implementations cast to the single implementation and use the internally available methods. IUser should be marked with a comment saying a client should not implement it.
  8. Implement toString() as much as possible. Ideally, every class should implement the toString() method. When you are debugging in Eclipse, it's much easier to see important details of a class by seeing it's toString() information instead of manually expanding lots of nodes. You should't worry about performance details in this method.
  9. Prefer packages with lots of classes than lots of packages with two or three classes. Having too many packages makes it difficult for a user to browse the source code.
  10. Write all comments in english. Although in an ideal world I would recommend doing it so in a neutral language, like Esperanto, there's a high chance someone from another country will need to understand your code.
  11. Write tests, even if it seems impossible to do so. For example, if you need to debug a web page, how can you test correct use of the Request and Response classes? Abstract them with an interface that only provides the methods needed by your application, and use mocks in the tests. Also, try to make your tests as short and self-explaining as possible. If you need to write utility classes just for tests, do so, you won't be losing time.