Best Practices

Externalize Strings: Always externalize all strings as if creating a fully localized application, even for applications that will never be localized. The benefit here is that Strings are kept out of Java code. The practice enables quick review of all text displayed by an application, including the capability to conveniently spell-check text.

JavaDoc Everything: All classes and methods of an application should have JavaDoc comments in the interest of maintainability. This applies regardless of whether more than one developer will ever work on a given source file of an application. When a particular class or method proves difficult to explain in the JavaDocs, it can be an indicator that the code would benefit from review and refactoring.

Derive Components: Echo Components are built with the intention that they be extended. You may find it beneficial to extend the high-level container Components such as ContentPane, Column and Row for application-specific purposes.

Create Event-driven Components: When deriving your own Components, you can further decouple them from your application by implementing your own event notifications. If necessary, you can even create your own event and event listener implementations. By providing all notification via events, your Components can be made to be standalone entities, eliminating coupling to a specific application.

Avoid Using Grids: Do not use the Grid component unless you absolutely need to. The Row and Column components will render more quickly and they have substantially more capability to perform fine-grained client-server updates when cells are added and removed. Grids do not have this capability. Also, don't use the Grid component to render tabular data; the Table component is designed specifically for this purpose.

Mind the UpdateManager: Don't perform unnecessary component add/remove operations. The Echo2 UpdateManager is watching your application for component hierarchy and property changes in order to determine the simplest course of action to update its state on the client web browser. If you remove and re-add a Component, for example, the UpdateManager won't know that in fact nothing has changed, and the re-added Component will thus be re-rendered on the client, consuming more bandwidth than necessary.

Use StyleSheets: Use StyleSheets wherever practical. They clean up your code and result in less memory being used on the application server. When you use StyleSheets, a single instance of the defined style properties can be shared across every user instance of a deployed application, which can result in a substantial reduction in memory usage. StyleSheets can also make it quite easy to change the theme of an application, and/or allow an application to have multiple user-selectable themes. To take advantage of the memory savings you must of course share StyleSheet instances amongst all users, e.g., by declaring them static in the ApplicationInstance.

Use AbstractTableModels: Many developers who are new to using the Table component are tempted to use the DefaultTableModel due to its apparent simplicity when compared to AbstractTableModel. In practice, rolling your own model based on AbstractTableModel can be a substantially cleaner and quicker method of creating a Table.

Pitfalls

getDefaultWindow(): The ApplicationInstance.getDefaultWindow() method will return null until the ApplicationInstance.init() method has finished executing.

getApplicationInstance(): The Component.getApplicationInstance() method will return null if a Component has not been registered, i.e., if it has not been added to a hierarchy whose root Window is bound to an ApplicationInstance. The most common circumstance where this presents a problem is within its constructor, at which time a Component cannot possibly have been added as a child of a hierarchy. Similar problems can occur shortly after a Component has been removed from a hierarchy. If you need to access the relevant ApplicationInstance and cannot guarantee that a Component will be registered, you should instead use the static ApplicationInstance.getActive() method.

LayoutData Property Changes: If you update a property on a LayoutData object, it will not be detected by the UpdateManager, and thus the change might not be rendered on the client. The correct practice in this case is to instead create a new LayoutData object and then invoke setLayoutData() on the Component to reconfigure it. Never update a LayoutData (or any property object) once it has been put into service.

Mutable Properties: Most property objects in Echo, such as Color, Font, and Border are immutable. Some of the more complex property objects however are mutable, largely due to the fact that making them immutable would require obnoxiously complex constructors. An example of such a mutable property object can be found in the FillImageBorder. Even if a property object is mutable, it should never be reconfigured under any circumstances once it has been put into use.

Extent Units: Some properties of various Components that are expressed using Extents will only allow certain types of units. The API documentation of a Component will specify such requirements if they are applicable. If such requirements are ignored, a Component may throw an exception when the illegal property is set.