============================================================ Credits: The following tools were used: Tool Version Vendor JDK 1.1.5 Sun JavaCC 0.7 Sun Demeter/Java 0.6.4 Northwestern University PerlTools 1.0.2 Original Reusable Objects, Inc. PerlTools is a set of Java classes implementing Perl style regular expression pattern mathching and substitution facilities. This tool kit allowed me to easily translate my template expansion logic from Perl into Java. My use of PerlTools complies with its License Agreement. More information may be found at: http://www.oroinc.com The necessary object code for PerlTools can be found in 'cycle6/gen/com/*' Thus it should not be necessary to modify CLASSPATH to pick up the PerlTool class files when running 'javac' or 'java' from 'cycle6/gen' (See the 'Mechanics' section for details') ============================================================ Summary: This project re-implemented a code generation tool that I originally developed as a Perl script. At 1500 lines, the Perl script was becoming unmaintainable mostly because of the poor encapsulation of data structures that it employed. The goals of the project were to create a more maintainable implementation, and to improve upon the format of the input files used by the tool. I did all of my development in terms of Demeter/Java and JavaCC input files. I did not directly write or modify any Java source. The class dictionary contains 47 classes. There are about twice that many classes in the generated code. At this point the Demeter/Java implementation provides the basic functionality of the tool, but is missing some significant capabilities that are exploited in practice: o Support for C++ conversion operators o Generation of 'Imake' file to build generated classes o Unimplemented command line options: -v : verbose output -o : create list of generated files -p : specify a header file path prefix Curiously the Demeter/Java implementation is about the same size (2400 lines) as the Perl implementation and still does not provide the same level of functionality. (See below for a detailed break-down of the Demeter/Java implementation.) This observaton still holds when you discount the manually generated JavaCC grammar files used to implement the improved input format. These comparisons are approximate because I simply counted raw lines of text. Nonetheless, there is not the order of magnitude difference that one typically sees between Java and Demeter/Java. Perhaps one reason for the similar sizes, is that there is a subtantial amount of non-traversal logic in this program. For instance template expansion (Expand.beh) is the largest single file. This code deals mostly with file I/O and text transformation, and doesn't entail much object traversal. The logic in this area follows the Perl code fairly closely. Likewise, the second largest file, Load.beh, contains the database loading logic and is concerned mostly with parsing and object building rather than traversal. I still consider the Demeter/Java version more maintainable for several reasons: 1) The underlying data model is more naturally represented by classes than by associative arrays of strings. Furthermore this data model is explicitly documented by the class dictionary. 2) Important collaborations can be captured in a single behavior file. rather than being scattered across multiple files. The Perl version represents about 3 person months of development effort. The Demeter/Java version represents about a single person month of development effort. I would attribute this difference more to the following factors than to any superior expresivity in Demeter/Java. o Problem is already well defined. All of the requirements issues were solved during the development of the Perl version. I simply had to reproduce existing functionality. o Substantially less testing of the Demeter/Java version was performed. =========================================================== Bugs and Improvements Most of my testing was done against templates, configuration and definition data used in our production environment. Since this information is proprietary, I have included contrived data for this delivery. Bugs: o Method definitions cannot use 'void' to indicate no arguments, e.g. method [bar] int foo(void) const; will not parse. o $[Header] can expand to the same value more than once in a template. o $[ExternalClass] can expand to the same value more than once in a template o $[ExternalClass] should not expand to the class being generated. $[Header] should not expand to the header of the class being generated. o Issues bogus 'Generating source' messages when neither -h or -cc option is given on the command line (i.e. no source is requested or generated). Unfinished: o MakeTemplate.expand is unimplemented. o Need to add support for C++ conversion operators. o Many unimplemented command line options. o 'virtual' and 'static' method qualifiers are treated in two different ways. Make the handling of 'virtual' the same as 'static'. o Compare code generated by this version with code generated by Perl version. o Re-implement command line parsing to use pattern matching rather than a JavaCC grammar o Add line numbers to error reports. ============================================================ Observations on using Demeter/Java: 1) There were several cases where I had to maintain dual data structures (e.g. a Hashtable or Vector and a Demeter/Java repetition class) to hold the same information. I needed the repetition class to perform traversals, but for performance reasons I needed an alternate way to look up information in the collection. 2) It takes time to design traversals that are robust against change I have a number of traversals from ExpansionContext that would probably break if I added another collection to that class. 3) Demeter/Java allows methods of a class to be scattered across many behavior files. While this is handy for grouping all of the methods related to a particular collaboration, it makes locating commonly used methods more difficult. (Especially under Windows95 where I found myself 'grep'-less :-) I started organizing my behavior files into two categories (a) files containing methods of a single class, which are shared by several collaborations, and (b) files containing methods from several classes but specific to a single collaboration. 4) The Demeter/Java translator has an annoying habit of regenerating code when it doesn't have to. I ran it twice in a row, and discovered that the second run had overwritten most of the generated files even though none of the input files had changed. Consequently, I wound up nearly always building from scratch whenever I made even a small change to the code. Since a complete build takes about 9 minutes on my PC (a 75MHz Pentium with 40MB of RAM), this represents a big productivity hit (only 2 to 3 rebuilds per hour). It's not only the delay that is painful, but the loss of continuity in your thinking that is so damaging to productivity when when build times start to exceed a minute. The mind wanders and time is lost refocusing on the problem at hand when the build does complete. ============================================================ Implementation Size Analysis: Lines File Contents ----- ---- -------- 128 CmdArgs.beh Methods of class, 'CmdArgs' 73 Display.beh Collaborations to display database 45 EntityAsType.beh Collaboration to register entities as types in the type registry 465 Expand.beh Collaboratons for template expansion 166 GenerateCode.beh Top level collaborations for code generation 309 Load.beh Loads database from files (Config, Definitons) 84 MacroTable.beh Macro Table data structure 67 Main.beh Top level of the progra 50 TypeUseFixup.beh Collaboration to bind each TypeUse object with its corresponding DefinedType object. 74 Util.beh Miscellaneous methods of sundry classes. ---- 1461 Subtotal 98 cmdargs.jj Command line parsing 629 stubgen.jj Database file parsing (Config,Definitions) ---- 727 Subtotal 195 stubgen.cd Class dictionary ==== 2383 Total ============================================================ Mechanics: Here is a summary of the contents of 'cycle6'. Source code: *.beh *.jj *.cd Build scripts: build.bat Execute this Windows95 batch file from 'cycle6' to rebuild entire project. build.sh Unix shell script equivalent to 'build.bat' build.log Expected output from 'build.bat' Test Data used by Sample test/ Config Configuration for handle-bridge-body pattern Definitions Entities & interfaces for Library example *.h Header template files *.cc Impl template files Sample Input/Output: run1.bat Example 1 input (generates 'facade' code) run1.sh Unix shell script equivalent to 'run1.bat' run1.log Output produced by run1.bat code1/* C++ code generated by run1.bat run2.bat Example 2 input (generates 'bridge' code) run2.sh Unix shell script equivalent to 'run2.bat' run2.log Output produced by run2.bat code2/* C++ code generated by run2.bat run3.bat Example 3 input (generates 'User' client code) run3.sh Unix shell script equivalent to 'run3.bat' run3.log Output produced by run3.bat code3/* C++ code generated by run3.bat