Naked Objects
By Richard Pawson and Robert Matthews

Case study: Travel bookings

User and developer views of the system

What follows is a series of views illustrating different aspects of the system from the perspectives of the user and the developer. This is not a programming tutorial. Rather, it is an attempt to show the close correspondence that exists between the two views of a business system developed with the Naked Objects framework. From these screenshots it is possible to get a sense of just how easily a user-request can be translated into the necessary code changes.

Classes

An 'application' consists of nothing more than a set of business object classes. All user operations take the form of actions invoked upon an instance of one of those classes or upon the class as a whole. Any class that could form the start-point of a user activity is shown in the user's 'Classes' window, shown here on the left of the screen.

1. These are the six business classes that constitute the prototype reservations system.

2. Right-clicking on any class icon pops up a menu of class methods, including one to create a new instance of that class. The generic class methods shown here require no programming since they are automatically provided by the framework.

3. Other generic class methods allow the user to find particular instances or show all instances of that class.

4. This symbol represents a collection of objects: in this case, all seven of the cities in the system.

5. Where there are more instances than can be shown in one window, the collection would provide methods (greyed-out here) to page through the objects.

6. The code for this application is all held in a project folder called ecs.delivery.

7. There is one Java class corresponding to each of the business object classes presented to the user. The label on the user's class icon is (by default) automatically derived from Java class name. Here CreditCard has been converted into Credit Cards. (Irregular plurals must be manually specified.)

8. Each business object class must implement the NakedObject interface in order for the viewing mechanism and/or persistence mechanism to be able to use it. The easiest way to achieve this is to make each business class inherit from the AbstractNakedObject class provided with the framework.

9. The only code in this project that is not a business class is EcsExploration which is needed to run the application. Almost everything that this class needs is provided by the framework's Exploration class. When the application is deployed this EcsExploration will be replaced by a simple configuration file.

Instances

For most business scenarios, the user of the system will be dealing with individual instances of the business classes, and sometimes with collections of instances of the same type. By default, an instance uses the same icon as its class, but has an individual title. It is also possible to vary the icon according to the identity or the status of the object.

1. By default, instances use the icon of their class, but instances have titles to identify them. This instance is shown collapsed to its icon-only view.

2. The menu actions shown here provide different ways to view the object. The viewing options offered will depend upon the type of object. All the viewing options are created automatically by the framework.

3. The default view is the 'form' view shown here.

4. Instances have titles that are usually derived from one or more of their identifying attributes and/or their current state

5. Each class is defined by the set of methods it can fulfil. All these methods deliver specific business value, and result directly from a user requirement. The underlying technical methods needed to manage the objects can all be inherited from the framework and need never be seen by application developers.

6. Each business class needs a title method to generate the title that appears next to the icon. This is normally derived from one or more of its attributes such as a name, status, or reference number.

7. The title method must return a Title. Here the firstName is turned into a Title object (using an inherited method), then the lastName is appended to it. The append method looks after leading and trailing spaces automatically.

8. CreditCard has a more complex title method that masks all but the last five digits of the number.

Fields

Open a view of any object and you will see a set of fields. Some of these fields contain simple values (such as dates, numbers or text strings), which the user may be able to enter or edit. Other fields will contain business objects, shown as icons. Even where an icon appears inside another object view, that icon still represents a fully functional object: you can invoke its behaviours in situ or open up a new view of it.

1. An empty 'value' field.

2. The grey hole indicates that a City can be dropped in here.

3. This field contains another business object - a City.

4. Here the user has typed some text into the value field.

5. If you attempt to drag the right type of object into a field, (here a City) the drop zone will flash green. A red flash indicates that the framework will not let you drop that object there, either because it is the wrong type or due to some other programmer-specified rule.

6. Each field in the user view is determined by the existence of a get method in the Java class definition. The field name is, by default, a formatted version of the method name.

7. A business object field will require a get and a corresponding set method.

8. Because setCustomer requires a Customer as a parameter in the Java file, the framework will automatically provide the ability for the user to drop a Customer onto the corresponding field in the user view, but will disallow objects of other types by flashing the field red.

9. The framework provides a set of generic NakedValue classes including TextString, WholeNumber, Date and Money. Such fields require only a get method because the value object itself provides the methods for changing its contents.

10. NakedValue objects are typically initialised within the constructor method for the business object they are contained in.

11. The resolve method ensures that a referenced object is only retrieved from secondary storage when it is actually needed.

12. The objectChanged method advises anything using that object, such as the viewing mechanism or persistence mechanism that the object's status has changed.

Associations

We have just seen how a field can contain a reference to another business object. Naked Objects can also handle more complex relationships such as multiple associations, where one object knows multiple instances of another type, and bi-directional associations, where two objects both know about each other.

1. The Customer can have multiple Locations associated with it.

2. A new Location can be associated by dropping it onto the grey hole at the bottom of the collection.

3. Right clicking on any member of this collection offers the option to Remove Reference.

4. This is an example of a bi-directional association. When a Customer is associated with a Booking, a reference to that Booking is automatically added to the customer's list of bookings.

5. A multiple association is managed by an InternalCollection (provided by the framework) which can hold only objects of a specified type.

6. A multiple association needs only a get method to return the InternalCollection, which then provides its own methods for accessing the objects it contains.

7. Bi-directional associations (whether singular or multiple) require the provision of associate and dissociate methods.

8. associateBooking on the Customer first adds the new Booking to the internal collection of bookings, then sets the customer field on that Booking to point to this (customer). In a bi-directional association, one object manages the association and the other one delegates responsibility to it.

9. Adding a fieldOrder method to an object allows us to control the order in which fields are presented to the user.

Behaviour

The two principal mechanisms by which a user can invoke a business behaviour are by selecting an action from a pop-up menu on a business object and by dragging one object onto another. (The latter is not the same as dragging an object into an empty field inside an object.) It is also possible to invoke business behaviours at the class level - through the pop-up menu on that class - or by dragging an instance icon onto the class icon.

1. At the bottom of the pop-up menu for an object are the business methods that can be applied to that object.

2. An ellipsis ... following the menu action indicates that this will return another object as a new window.

3. Dragging Home, Boston directly onto Logan Airport, Boston will trigger the creation of a new Booking that uses those two locations as Pick Up and Drop Off respectively. This shortcut is most useful when both locations show up in a list of frequently-used locations inside a Customer.

4. The method name actionReturnBooking is stripped of its action prefix and reformatted to generate the menu option Return Booking... automatically. For language localization it is possible to over-ride this automatic correspondence. The ellipsis in the menu option reflects the fact that an object will be returned by this method - in this case a Booking.

5. createInstance creates a new instance of the Booking class, called returnBooking. Just using the simple Java new keyword instead of createInstance would not perform all the necessary initialization.

6. This code swaps the pick-up and drop-off locations for the return booking.

7. If an action method requires an input parameter (in this case another Location) then this behaviour will not show up on the pop-up menu. Instead, it will be automatically invoked when the user drops an object of the required type onto this object.

8. This method, invoked when the user drops one location onto on another, creates a new Booking assigning the two locations to the pickUp and drop-off fields respectively.

9. If another object has invoked this method then the newly created Booking will be passed back to it. If the method was invoked by the user from the menu, then the returned object will automatically show up as a new window.

10. actionNewBooking is a static method: it can be invoked from the class icon, not the instance icons. This method takes a Customer as a parameter and returns a Booking. In other words, drop a customer on the Bookings icon and it will generate a new booking for that customer.

Control

Naked objects empower the user but that does not imply an absence of controls. Different users will need access to different objects, different fields within those objects and different behaviours on those objects. It will also be necessary to enforce certain business rules, such as preventing an action from being invoked unless the object is in the right state. In Naked Objects these forms of control are implemented using about methods and About objects.

1. Here, the Confirm option is greyed out, but the user can Check Availability.

2. Check Availability resulted in the booking's status field changing to Available. Because of this the user now has the option to Confirm the booking.

3. The booking now has Confirmed status.

4. The actionConfirm method has a corresponding aboutActionConfirm method that determines whether the former can be accessed. If access is denied then the viewing mechanism will grey out this menu option.

5. about methods return an About object, which contains data about the availability of a method, class or instance it applies to. Generic forms of About are provided with the framework.

6. Availability may be determined by business rules or by user authorisation. The whole determination could be sub-contracted to an authorisation server.

7. Here, aboutActionConfirm checks to see if the Booking object's status field is set to Available. If so, ActionConfirm will be made accessible to the user.

8. Here, a reason is provided for the unavailability of the method. In the current version of the framework, this message shows up in the system log window. In a future release better use will be made of this capability, perhaps in the form of optional balloon help.