From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-2.9 required=5.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=unavailable autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,38159b1b5557a2e7 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2004-01-26 12:54:27 PST Path: archiver1.google.com!news2.google.com!news.maxwell.syr.edu!news.tele.dk!news.tele.dk!small.news.tele.dk!proxad.net!usenet-fr.net!enst.fr!melchior!cuivre.fr.eu.org!melchior.frmug.org!not-for-mail From: Lionel.DRAGHI@fr.thalesgroup.com Newsgroups: comp.lang.ada Subject: RE: Standard Ada Preprocessor (Was: why ada is so unpopular ?) Date: Mon, 26 Jan 2004 21:03:02 +0100 Organization: Cuivre, Argent, Or Message-ID: NNTP-Posting-Host: lovelace.ada-france.org Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" X-Trace: melchior.cuivre.fr.eu.org 1075147430 28252 80.67.180.195 (26 Jan 2004 20:03:50 GMT) X-Complaints-To: usenet@melchior.cuivre.fr.eu.org NNTP-Posting-Date: Mon, 26 Jan 2004 20:03:50 +0000 (UTC) To: comp.lang.ada@ada-france.org Return-Path: X-Mailer: Internet Mail Service (5.5.2653.19) X-Virus-Scanned: by amavisd-new-20030616-p5 (Debian) at ada-france.org X-BeenThere: comp.lang.ada@ada-france.org X-Mailman-Version: 2.1.3 Precedence: list List-Id: Gateway to the comp.lang.ada Usenet newsgroup List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Xref: archiver1.google.com comp.lang.ada:4837 Date: 2004-01-26T21:03:02+01:00 | -----Message d'origine----- | De: Warren W. Gay VE3WWG [mailto:warren@ve3wwg.tk] ... | >> | >>> C with preprocessor directives is also Maintenance Hell. | I don't see | >>> that it's a better Hell. | >> | >> Given that it should be optional, it would not be your problem ;-) | | I would tend to agree. There is no "pure" way to make non-trivial | code portable. | | If we go back to the "non-normalized database" metaphore, keeping | separate versions of code for purity sake (to avoid conditional | compilation), is like having to update a customer name in a | database in 12 different tables. This potentially leads to | leaving one instance of that name wrong, or left unchanged. A good design allows to separate common and customized code in a pretty sharp way. There is no free lunch, and you need some more code and design. Method template and Strategy patterns are useful here. It is possible (and not so hard) to get a software with no embedded dead code, and with almost no possible source confusion, that is, with the whole configuration defined in one source. Lets consider two OS interfaces (not compiled code) : ---------------------------------------------------------- package OS_Interface is procedure Open_File (Name ... ...); ... -- etc. private type Abstract_Interface is abstract ... procedure Open_File (Abstract_Interface ... Name ... ...) is abstract; ... procedure Register_As_Concrete (Abstract_Interface'class'Access...); -- used by child interfaces to register themself end OS_Interface; ---------------------------------------------------------- package body OS_Interface is Concrete : ... -- pointer to the concrete Interface, -- set by Register_As_Concrete procedure Open_File (Name ... ...) is begin Open_File (Concrete, Name ...); -- let's dispatch to the concrete -- Interface end Open_File; ... end OS_Interface; ---------------------------------------------------------- package OS_Interface.Windows is type Windows_Interface is new Abstract_Interface ... -- define abstract operations -- redefine some of the concrete operations. ... procedure Register; -- register this one as the concrete interface -- by calling Register_As_Concrete with -- a local dummy instance of Windows_Interface end OS_Interface.Windows; For the configuration, you need some separate configuration procedure : ---------------------------------------------------------- separate (Main) procedure Configure is begin OS_Interface.Windows.Register; end Configure; But this is the only compilation unit provided in several versions, the only one that you need to manage carefully in your configuration system. As for conditional compilation systems, some external configuration is pretty unavoidable. Note also that calls to (for example) a specific Linux thin binding will be hidden into the OS_Interface.Linux package : Register is the only operation in OS_Interface child specification, so if you don't "with" it within the Configure operation, this code is not included in the executable. Another advantage is that you don't touch common code when adding or modifying some specific implementation. You don't cause useless recompilations or regression testing. For user code, the whole stuff is hidden : it just call OS_Interface.Open_File (Name, ...); as usual. One drawback of this template respect to conditional compilation is an added indirection and dispatching hidden into OS_Interface body. But if someone care of performance at this point, he is in a desperate situation. Another drawback is the difficulty to compare implementations, but it's not that useful, neither that difficult to do with your favorite environment. -- Lionel Draghi