Reusable code and reasons to implement a "personal code library"
eusable code is the bomb. Every programmer that has been programming for any length of time has reusable code somewhere. In a perfect world that code would be easily accessible and generic enough to simply drop into an existing work in progress. Sadly, all too often, developers find themselves sorting through previously written source files to refer to some algorithm or implementation coded years ago but again needed. Once found, "cut and paste" is usually followed by lengthy modifications that are required to get the old code to work in the new program.
At the most basic level, this "copy and modify" method still qualifies as reusing code. Still, while virtually every developer at one time or another has used this technique, it leaves something to be desired.
A far better way of reusing code is to implement a personal code library. Done correctly, it allows for several advantages over non-library techniques:
1) Code naturally tends to be more organized and programs become modular in nature. 2) Reusing existing code speeds up development. 3) Fewer bugs can be introduced if less coding is done so new projects are naturally more stable. 4) When bug fixes are found and fixed in the library, they are automatically fixed in all other works that share the library. 5) Shared code gives a common feel across all of your works giving them a sort of "signature."It should be noted that there are several different ways of reusing code. The techniques shown in this article have worked best for me, but the reader may prefer different techniques. Keep an open mind, because my way is not the only way.
Three steps to a personal code library
By just a few simple steps, a developer can build a library of customized code that can be drawn upon with a few simple keystrokes. The first step, we've already touched upon....
Step one, template code, is really the basis for any serious library. The practice of making code templates consists simply of identifying code that you use more than once (or are likely to use again) and saving it in a special file so that it can be found more easily. A blank game is a prime example of a code template (see "A Starting Point.")
Additionally, patches to the standard Inform Library, generic methods (like the Center routine), and common classes from which specialized objects are inherited are all good candidates for your library. Anytime a developer begins to search through old code to copy into a new project, a flag should go up. This is an indication that the code being tracked down is a good candidate for a template. Once isolated, and the code is placed in its own file, it can be more easily found and copied into a new project. Taking the time to identify what code is really reusable is half the battle and will pay for itself in both organization and rapid development.
There are con's associated with using this approach alone, however. While cutting and pasting organized template code into a new project may speed up development, it lends itself to an unorganized project. This method alone has a tendency to begat spaghetti-code and special care needs to be taken to organize the destination source file. Additionally, when a bug has been identified in a template, it must be fixed in all projects in which the template was pasted. Luckily, Inform hosts a directive that minimizes our need to "cut and paste."
Step two, the practice of including modules has several distinct advantages that augment the power of template coding and address the irritations associated with "cut and paste." The most notable advantage is shared code. Implemented via Inform's #include directive, the same template can be referenced in multiple works. Modifications to the shared file affect all referencing projects. A bug fixed in one, is fixed in the others. This includes programs in which the bug has yet to be identified. This leads to more stable and robust code throughout all of your works.
Again, there are some annoyances with this technique. Because of the nature of the Inform compiler and the standard library, most template code cannot simply be added to a game file in one large block (which is essentially all the #include directive does.) Hidden in the back of "The Inform Designer's Manual" Appendix 11, are directions concerning what goes where in an Inform Program. From this, you can derive four sections (surrounding the standard library's #include's) where library code needs to be placed:
1) The REPLACE section - appears prior to the inclusion of Parser. REPLACE directives, used when modifying system routines, go here. 2) The MESSAGE section - appears between the Parser and Verblib includes. Definitions of the LibraryMessages object, SACK_OBJECT, and the task_scores array goes here. 3) The CODE section - appears between the Verblib and Grammar includes. Attribute, Property, Classes, and Object implementation goes here. Most implementation code is placed in this section. 4) The GRAMMER section - appears following the Grammar include. All new Verb and Extend directives go here.One possible, though not recommend, way of addressing this is by implementing separate files for each section needed by a library entry and including them at the appropriate location. Obviously this file juggling can be managed in a better way. Again, Inform offers a better solution.
Step three, using conditional compilation, is the final technique needed to bring everything talked about thus far together. Inform implements conditional compilation with various #If... directives. While the #include directive adds code to a file where none actually exists, these directives give the ability to ignore code in a file that does exists. Using these directives, the compiler can selectively dismiss sections of code and a large, diversified library can still produce a tight specific program.
Creative use of these directives can cause a file to be interpreted differently each time it is compiled. This allows us to address the hassles identified above but coding a module to be interpreted differently depending on where in the program it is included. As an added bonus, we can wrap all library includes into a "single point of entry" include file and choose which library packages we include by declaring constants. This makes for even cleaner code. Not bad.
The Framework and the Implementation
To the experienced developer, all of this coding with conditional directives means one thing: a framework. Obviously the content of your personal library will vary from developer to developer, but the implementation framework has already been coded and is available to all. It contains everything you need to begin developing and using a personal library. That is, a sample blank game template (implementing the library), a library entry template, and a "single point of entry" file. Additional library entries are also available for individual downloads, or a complete package of every thing is also available. All of this for the great low price of a download click from http://www.onyxring.com/orlibrary.aspx.
As always, the best way to learn is to look at the code. There are several comments inside each of the files that describe how to use it.