Return-Path: Delivered-To: apmail-new-httpd-archive@apache.org Received: (qmail 41461 invoked by uid 500); 21 Mar 2000 00:29:25 -0000 Mailing-List: contact new-httpd-help@apache.org; run by ezmlm Precedence: bulk X-No-Archive: yes Reply-To: new-httpd@apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list new-httpd@apache.org Received: (qmail 41450 invoked from network); 21 Mar 2000 00:29:24 -0000 To: new-httpd@apache.org From: Tony Finch Subject: Re: A couple of important features for 2.0 In-Reply-To: <07d701bf92b0$1957d830$064b2509@raleigh.ibm.com> References: Message-Id: Date: Tue, 21 Mar 2000 00:29:21 +0000 X-Spam-Rating: locus.apache.org 1.6.2 0/1000/N "Bill Stoddard" wrote: >> >> 2) Freeze the current API. When a new feature is required, add a new >> function instead of modifying the old one. > >This with 1) helps even more. Bloats the code, stifles creativity and just >doesn't fit in with open source development philosophy. If an API is just >not right, it should be changed. Maintaining deprecated APIs is common >practice in commercial software development but there is a price to pay in >complexity. And complexity is an open source project killer, IMHO; it raises >the project entry barrier and bugs increase non-linearly with complexity. These are the issues I was trying to address with the API jump table but I really don't like that idea for a number of reasons (mostly variations on the theme of run-time complexity). I came up with an alternative this evening which avoids the performance problems of using a jump table by using pre-processor magic instead. To #include the Apache API a module says something like #define AP_API_VERSION 20000320 #include "ap_api.h" and then proceeds to program to the API without worrying about changing versions -- source compatibility and binary compatibility. The core is programmed in a similar way, except it always uses the most recent API version, e.g. all core code says #include "ap_api_latest.h" #include "ap_api.h" before doing anything else. However, when an API change is made, the old version of the function that has been changed is retained (probably as a wrapper calling the new version). Any old versions are distinguished from the new one by mangling their names with different date strings, e.g. ap_foo_19991207 ap_foo_20000319 ap_foo and the latest version of the function has an unmangled name. All unmangled names are really mangled names in disguise: the "ap_api.h" header expands them to whatever is appropriate, according to the value of AP_API_VERSION. "ap_api.h" knows when each API function was changed, and when #included does #define ap_foo ap_foo_XXXXXXXX for the largest XXXXXX not greater than AP_API_VERSION (so if I say #define AP_API_VERSION 20000202 #include "ap_api.h" then when I use ap_foo I'll actually be using ap_foo_19991207). A little tool will be required to maintain "ap_api_latest.h" and "ap_api.h", using a source file with content similar to what is in "ap_mmn.h" right now (i.e. I don't expect the maintenance burden to be a great deal worse). This doesn't solve the problem of changing data structures; I think that will have to be dealt with by adding accessor functions to the API and making third party modules use them. Tony. -- f.a.n.finch fanf@demon.net dot@dotat.at 369 the barnacle-encrusted bilge pump on your sunken dreams