Part 1: The Case for Naked Objects: Getting Back to the Object-Oriented Ideal
Part 2: Challenging the Dominant Design of the 4-Layer Architecture
Part 3: Write an application in Java and deploy it on .Net
Part 4: Modeling simultaneously in UML, Java, and User Perspectives
Part 5: Fat is the new Thin: Building Rich Internet Applications with Naked Objects
The Naked Objects framework (See Part 1) enables a radical approach to the design and development of business systems in which all business functionality is implemented as methods on the domain objects, and these objects are exposed directly and automatically to the user.
Two of the benefits claimed for using Naked Objects are that it dramatically improves development productivity (because the developer no longer writes a user interface) and that the resulting systems will be more agile (meaning: easier to maintain) because they will be built on cleaner object models.
In this article we describe a controlled experiment designed to test and quantify those two claimed benefits, by comparing an application designed using a conventional 4-layer approach with an application of equivalent functionality developed with Naked Objects.
Comparative implementations are surprisingly rare, despite the obvious demand for them. One reason for this is that they can be very vulnerable to bias, and therefore open to criticism. (See, for example, discussions on TheServerSide concerning the much quoted comparative implementations of the Pet Store application). Although we cannot guarantee that ours is free from any possible bias, we did go to great lengths to avoid the most obvious sources of bias, and generally to conduct the experiment in a scientific manner.
For this reason we decided to start with an application that already existed, and the code for which was publicly documented. CarServ is a Java application designed to support an auto servicing shop: booking-in cars for service, and billing the customer. It was written as a teaching example by Dan and published in his book 'Better Software Faster' in May 2002. The full source code for this implementation is available from http://www.bettersoftwarefaster.com/, along with the definitions of the use-cases that it was designed to fulfill. The application was written and published before Dan had heard of Naked Objects. And though Dan would certainly not claim that his original implementation of CarServ was beyond improvement, it was written expressly to demonstrate good practices in modern business systems design.
Description of CarServ
CarServ adopts a typical multi-layered architecture based on four layers:
- The presentation layer creates the graphical views of the objects, and captures user inputs. The presentation layer was written using Java Swing components. A screenshot from the system is shown below:
- The application layer. The objects in this layer encapsulate the functionality for user commands.
- The domain layer, where the business object entities are defined. The domain objects have some business behaviours, but they are mostly concerned with defining the attributes and relationships. A UML diagram of the core of the domain model from CarServ is shown below. (The diagram uses colour conventions to reflect different archetypes of object, as proposed by Peter Coad in 'Java Modeling in Color').
- The data management layer. Each class from the domain layer has a corresponding data management object which is responsible for mapping the domain objects onto a relational database.
Defining a comparative implementation
In January 2003 we set about writing a new implementation that, as far as possible, would have the same functionality as the original one. The new implementation would be written in the same version of Java (1.3), using the same IDE (Borland's Together Control Center) and the same relational database (Cloudscape) for persistence, but all the Java code would be re-implemented from scratch and make use of the Naked Objects framework. Hereafter we shall refer to the original implementation as FourLayerCarServ and the new one as NakedCarServ.
We took two more important measures to protect against bias:
- All the coding of the new implementation would again be done by Dan, who has been using Java for many years. Thus, any differences between the new applications could not be attributed to different development styles or competence. (This decision was also a big relief for Richard, whose coding skills leave something to be desired!)
- The domain model would remain unchanged (the core of which was shown above). Richard is a very experienced object modeller and saw several potential opportunities to improve on the original model. However, to have done so would have been to invalidate the comparison.
Description of the NakedCarServ implementation
The development of NakedCarServ therefore consisted of taking the domain layer object definitions (i.e. attributes and relationships) from FourLayerCarServ, and re-coding them from scratch, observing the conventions required by the Naked Objects framework, and then adding behaviours (methods) to those domain objects sufficient to allow the use-cases that had been implemented in CarServ to be fulfilled by a user. A screenshot from NakedCarServ is shown below. (This was produced using Naked Objects version 1.0.2, which represented each object in a separate native window. The default viewing mechanism for Naked Objects has since been considerably improved).
The objects were made persistent on the same relational database as FourLayerCarServ. In both cases the tables were defined by means of SQL statements, but since these are largely equivalent, they have been excluded from the metrics below. In fact, the Naked Objects framework does have a capability to auto-generate the tables from the domain objects definitions, using Java reflection. However, this capability was not used in this experiment.
Evaluating the development effort for the two implementations
It took Dan about a day to write NakedCarServ. Unfortunately, we don't have an accurate record of how many hours FourLayerCarServ took to develop, because Dan didn't know that he was conducting the first half of a controlled experiment at the time! His memory is that it took something like two weeks, but this is not hard data.
However, we were able to run a number of hard metrics against the two completed implementations, including the number of classes, the number of methods, and the lines of code written by the application developer. (The same tool was used to assess the metrics on both systems). The results, shown below, provide a first level approximation of the relative development effort.
The results show an improvement of (approximately) 7:1 in the number of classes, 3:1 in the number of methods, and 4:1 in the lines of code. The classes in NakedCarServ have more methods on average - reflecting the greater behavioural richness of the domain objects. Yet the average method length (lines of code divided by number of methods) is slightly lower for NakedCarServ than for CarServ. If the average method length had grown this could have suggested a loss in agility rather than an improvement.
Terser code is not necessarily faster to write. Writing NakedCarServ required the programmer to know the APIs of the Naked Objects framework. A complex framework would not only take time to learn, but would require more mental effort to use, potentially offsetting the advantages of terse code, at least in terms of simple productivity.
One way to assess the complexity of the framework is to count the number of framework classes, and the number of unique methods on those classes, that the application developer has invoked explicitly from within the application code. Although the Naked Objects framework introduces several new classes and methods, it also eliminates the need for the programmer to deal directly with class libraries for user interface (in particular the Swing library). The initial results from this assessment are shown below.
The results show a substantial advantage for the Naked Objects framework. This suggests that the reduction in the code required for the NakedCarServ implementation was not achieved at the expense of having to master a more complex framework. Indeed, using the Naked Objects framework significantly reduces the number of external classes and methods that the application programmer must deal with. Anecdotally, many developers report that the main difficulty of learning and using Java is not the basic constructs of the language, but the complexity of the class libraries such as Swing.
(Note: references to classes within the java.lang and java.util packages were not included in the count. These are constructs that any Java programmer needs to be familiar with to write any application code at all and are therefore common to both implementations. When left in the count the difference between the two implementations is even more in favour of Naked Objects, but probably unrealistic.)
Some caveats need to be added to these results.
First, because Naked Objects auto-generates the user presentation, it was not possible to make the user interfaces the same. In FourLayerCarServ the programmer had full control over the presentation layer and therefore was able to optimize the screen layout and/or graphical design to the task in hand. In certain visual respects NakedCarServ is a poorer presentation - in particular in the presentation of the diary (although we expect to include a purpose-designed diary viewer in a future version of the Naked Objects framework). On the other hand, NakedCarServ makes more use of drag-and-drop and is in certain respects much nicer to use. However, this experiment was not concerned with the relative usability of the two systems, but the development effort. The point here is that because the user interfaces are quite different, the two systems cannot be said to be functionally identical. (In a future article we shall be looking specifically at the usability of Naked Objects, based on a large scale application developed for the Irish Government).
Second, NakedCarServ does not implement 100% of the explicit functionality of CarServ. For example the original implementation includes an Undo capability such that each business action can be undone (although the code to perform the undo must still be written for each method). In NakedCarServ, many of the simpler actions can easily be undone with a single operation, but some of them would require more than one user operation to undo them.
However, FourLayerCarServ code did not itself implement all the use-cases that had originally been intended for it in the Better Software Faster book The application addressed only the needs of the service side of the business, not the sales and administrative aspects. Nor did it implement all of the use-cases that had been identified and documented for the service side. In its published state CarServ could deal only with customers (and other objects) that already existed in the database; it did not implement the use case for adding a new customer, for example.
In NakedCarServ functionality was intentionally written only to support the same sub-set of use-cases as the original. However, the nature of the Naked Objects framework meant that NakedCarServ actually fulfils several of the use-cases not addressed in FourLayerCarServ, simply as a by-product of the framework. For example, for any business object class Naked Objects automatically provides the capability for the user to create a new instance of that class and to retrieve instances of the class matching a given character string. The net effect is that NakedCarServ actually implements many more use-cases than CarServ even though this was not intentional.
Finally, some of the advantages in the Naked Objects implementation can be attributed to the simpler relationship between the domain objects and the underlying persistence. This is not strictly an aspect of the naked objects concept, which is concerned only with the relationship between the domain layer and the user interface. Ideally, we would have factored the effect out of the results. The reason we couldn't do this is that in FourLayerCarServ some business functionality exists in the Database Management layer - so it would not be realistic to take those objects out of the metrics.
In fact one of the most striking qualitative observations from the experiment was that even though the motivation behind the classic 4-layer architecture is the separation of concerns, it is almost inevitable that business logic ends up being scattered across all four layers. In NakedCarServ the business logic is necessarily limited to the domain layer, because that is the only layer the application developer has direct control over.
This distinction alone should render the Naked Objects implementation easier to maintain. In order to test this hypothesis, we wrote down four different business scenarios, each representing an unforeseen future change in requirements . Each of these was defined as a single sentence (in the style of an Extreme Programming 'story') and we were careful to ensure that each was expressed strictly in terms of a business requirement, and not biased towards one style of user interface or the other.
These were the four stories:
- 'I want to be able to record a customer's email address'
- 'I want to be able to see the total value of business that we've done with a customer'
- 'I want to introduce a new type of service that is fixed-priced (such as a Winter Tune-up). instead of parts-and-labour.'
- 'I want to have a pool of cars that customers can borrow during a service (subject to availability), and record which customer has which pool car.'
The two implementations were then modified to accommodate each of these scenarios, and the effort required (measured in minutes) to make the changes to both systems was recorded. On each system the business change scenario was implemented in the form best suited to the design of that system. All the coding was again done by Dan, who authored both systems and was therefore equally familiar with both.
The results are shown below in minutes.
The work actually done on this scenario did not include implementing a new GUI. With appropriate scaffolding in place (none such exists in the original implementation), Dan estimated a further two hours to implement the GUI. This is probably very optimistic!
The summary of these results is that the changes took less time to implement for NakedCarServ than for FourLayerCarServ. More striking, though, was that the modifications to FourLayerCarServ were much more scattered: each modification to a business object typically involved modifications to objects in all four layers of the architecture. In NakedCarServ, all modifications took place in the domain layer and most were limited to one or two object classes. This suggests that had the application been much larger, or if the developer making the modifications was not the original author, the difference in modification effort between the two systems could well be much larger. Testing that hypothesis would require a much larger effort than it was possible to devote to this experiment.
This experiment provides good evidence for the claims that Naked Objects speeds up the development cycle and that the resulting systems are more agile (more easily adaptable to accommodate unforeseen changes). In this experiment we did not attempt to evaluate the other claimed benefits for Naked Objects, including usability and effectiveness for requirements capture because this was not a real system for real users. Those claims will be tested in future articles in the context of real client situations.
After the experiment was complete Robert Matthews (the author of the Naked Objects framework) looked at the NakedCarServ code and saw several opportunities to further reduce the code, given his greater familiarity with the framework. However, we did not incorporate his improvements because it would distort the result, since it would almost certainly be possible to improve the FourLayerCarServ coding given additional effort.) As they stand, the figures we present reflect the efforts of a single developer to do a reasonable job in a reasonable time.
More significantly, though, subsequent analysis of the experiment has prompted Robert Matthews to make some significant improvements to the Naked Objects framework and more are planned. In particular we observed that a significant proportion of the NakedCarServ code is concerned with making functionality unavailable! Dan's summary of this is that conventional business systems development is purely an 'additive' process, whereas in naked object development a significant proportion is 'subtractive' - functionality provided by default through the framework must be rendered unavailable based upon the user's authority or upon, say, the state of an object. Between us we have now started to design a much more efficient way to do this in Naked Objects. When those capabilities are released we shall attempt the CarServ implementation once more - and we aim to reduce the coding effort by half as much again. Our motto (taken from Antoinne De Saint-Exup'ry's 'Wind, Sand and Stars'): 'Perfection is finally attained, not when there is no longer anything to add, but when there is no longer anything to take away, when a body has been stripped down to its nakedness.'