Naked Objects
By Richard Pawson and Robert Matthews

The anatomy of a naked object

Behaviours

Any method within a naked object that is prefixed with 'action', and that returns either a NakedObject type or void, is made available to the user. Methods defined this way that take no arguments are displayed on the object's pop-up menu, as shown in the example below. The name used on the menu defaults to the method name stripped of its prefix and with spaces added where uppercase characters are found.

Methods that take a single parameter (which must be of the type NakedObject) are made available through drag and drop gestures.

When one of these action methods returns a non-null value, the framework will attempt to show that returned object to the user - typically in a new window. This is indicated on the pop-up menu by an ellipsis (...) being added to the menu name, e.g. the Return Booking... option shown above will display a new object, whereas Check Availability won't.

Instance methods

A typical action method (taken from the City class) is shown below. It creates a new Location object and sets its city field so it refers to the city object that the method was called on. This newly created and persisted object is then returned to the user. This method shows itself as New Location... on the city's pop-up menu and is invoked when that menu item is selected.

public Location actionNewLocation() {
	Location loc = (Location) createInstance(Location.class);
	loc.setCity(this);
	return loc;
}

The next method (taken from the Location class) creates a new booking object. This method requires another location object to be provided as an argument, so that it can set up both the new booking's pick up and drop off fields. This method is invoked by dropping one location object onto another.

public Booking actionNewBooking(Location location) {
        Booking booking = (Booking) createInstance(Booking.class);
        Customer customer = location.getCustomer();
        booking.setPickUp(location);
        booking.setDropOff(this);
        if (customer != null) {
            booking.setCustomer(customer);
            booking.setPaymentMethod(customer.getPreferredPaymentMethod());
        }
        booking.setCity(location.getCity());
        return booking;
    }

On the screenshot below you can see the dragged object, whose title and labels have changed to purple; the object it was dropped on, whose title and labels flash green to indicate a valid drop; and the resulting new booking with its Customer, Pick Up, Drop Off and City fields set up using the information from the two objects involved in the invoked method.

Most often, action methods are used to change the state of an object. This example from the Booking class changes the status value object and then associates the pickUp and dropOff locations, and the paymentMethod used in the newly-confirmed booking directly with the existing customer object that the booking was made for - so that they can easily be re-used in a future booking for that customer. Note that this method does not return anything; it only changes the state of the two objects:

public void actionConfirm() {
	getStatus().setValue("Confirmed");

	getCustomer().associateLocations(getPickUp());
	getCustomer().associateLocations(getDropOff());
	if (getCustomer().getPreferredPaymentMethod() == null) {
		getCustomer().setPreferredPaymentMethod(getPaymentMethod());
	}
}
Disabling methods

Action methods may be rendered unavailable because a user lacks appropriate authority, or the object is not in an appropriate state, or because of some other business rule. The availability of an action... method can be controlled by adding a corresponding about... method. This method must return an About object, have the same method name with 'about' prefixed, and have exactly the same parameter list. The following code shows two action... methods and their about... methods. The first makes the NewLocation method available if the city field contains something. The second disables the NewBooking method if the location that will be used to invoke the action method is the same location as the one the method will be invoked on, i.e. if the user attempts to drop the location object onto itself.

public Location actionNewLocation() {}

public About aboutActionNewLocation() {
    if(city.isEmpty()) {
        return ActionAbout.DISABLE;
    } else {
        return ActionAbout.ENABLE;
    }
}

public Booking actionNewBooking(Location location) {}

public About aboutActionNewBooking(Location location) {
    return ActionAbout.disable(location.equals(this));
}

When an about... method disables a zero-parameter action method, that method is greyed out on the object's menu.

When it disables a one-parameter method, the framework will flash the target object red as the user tries to drag an object (even of the right type) over it.

Method ordering

The ordering of listed methods, particularly for menu items displayed on an object's pop-up menu, is based on the array of action methods that is produced by Java's reflection mechanism. The ordering, therefore, is dependent on how the JVM you are running collects the data about your class, and you have no direct control over this. You may, however, specify an order within your class definition, which the viewing mechanism can then interpret. This is done by adding a static method called actionOrder that returns a String listing the names derived from the methods separated by commas. These need to be the reflected names and not the method identifiers. For example the string 'Call Back' would be used to refer to the actionCallBack method. (Case is ignored.)

The following example from the Booking class specifies a suitable order for its action methods:

public static String actionOrder() {
	return "Check Availability, Confirm, Copy Booking, Return Booking";
}

Any listed name that does not match a method is simply ignored, and methods that are not listed will be placed after all the specified methods.

Class methods

It is also possible to write methods that are invoked on a class rather than on a specific instance. These can be used to find instances that match given criteria - for example, to find bookings that use a specific location; or to create one object based on another, such as a city being used to create a new location in that city.

The same principles apply when defining such a method, but the method is declared as static. The following shows a typical class method (within the Booking class) that creates a new booking for a customer. This would be invoked by dropping a customer object onto the Bookings class and would result in a new booking being returned in a new window:

public static Booking actionNewBooking(Customer customer) {
    Booking newBooking = (Booking) createInstance(Booking.class);
    newBooking.setCustomer(customer);
    newBooking.setPaymentMethod(customer.getPreferredPaymentMethod());
    return newBooking;
}
Class method ordering

You can order class methods in the same manner as instance methods, but using the static method called classActionOrder.