
Hello all, <Thomas.Klimpel@synopsys.com> wrote:
Lorenzo Caminiti wrote:
*** To me, this is a key question for Boost programmers: IS THIS C++ SYNTAX TOO FOREIGN LOOKING OR DIFFICULT TO USE TO BE ACCEPTABLE? ***
Doesn't Boost.Parameter also uses a foreign looking syntax? But I admit that "DBC_MEM_FUN" is a bit cryptic. How about BOOST_DBC_MEMBER_FUNCTION?
Yes, as Thomas indicated, Boost.Parameter already uses a foreign looking syntax. That essentially answers my question: While the necessity to introduce a macro-based foreign looking syntax like the one of this library should be carefully considered, I do not think Boosters will reject it in principle. SYNTAX 1) I knew of the existence of Boost.Parameter but I never used it so I did not know its API. After Thomas' comment, I have studied Boost.Parameter API and its documentation. The Boost.Parameter macro-based foreign looking syntax is actually very similar to one of this library: Boost.Preprocessor sequences are used to allow the macros to generate function signatures with parameter names/types, return types, etc; There is a BOOST_PARAMETER_MEMBER_FUNCTION, BOOST_PARAMETER_CONSTRUCTOR, etc similarly to DBC_MEM_FUN, DBC_CONSTRUCTOR, etc. 2) In addition, other Boost libraries like Boost.Test (great library which I use every day) and Boost.TypeOf rely heavily on macros (even if in a contexts different from the one of this library and Boost.Parameter). Therefore, I think the use of macros (while always best avoided), it is accepted by Boosters when necessary. "The first rule about macros is: Don't use them unless you have to. Almost every macro demonstrates a flow in the programming language, in the program, or in the programmer.", The C++ Programming Language, B. Stroustrup, 1997. This library uses macros to overcome a programming language limitation extending C++ with DBC features. Languages like Eiffel have built-in language support for DBC; Other programming languages like Java and Ada use external pre-processing tools to support DBC (but that's cheating...). Gottlob Frege wrote:
they are **domain-specific** This, for me at least, makes a big difference. I don't mind seeing some strangeness within a certain domain or to solve a particular problem. But when the augmented language is NOT domain-specific, and instead is used all over your code, then I start thinking that maybe we should just be using a different language.
3) I also understand the concern expressed by Tony that the "DSEL" syntax of this library has a domain that extends to all your class *declarations* (or at least to all the ones for which you need to write contracts) -- that is a pretty large domain... I think, at the end designers/programmers will have to judge if the complexity added by the macro syntax is worth the benefits of DBC for their specific application -- but using Eiffel instead of C++ might not be a realistic option for some (most?) applications. In addition, I would like to stress out that the foreign looking macro syntax only applies to the class declarations and NOT to their definitions -- therefore, only your .hpp files will contain the foreign looking macros, while your .cpp files will essentially remain unchanged. NAMING While my question above was not directly concerned with this library current naming conventions, quite a few comments were made on naming. I think that means that properly chosen names could help making the macros less cryptic (even if they will still retain the foreign looking preprocessor-sequence syntax). In general, I will be more than happy to change the library names to fully comply with Boost guidelines and to be as clear as possible to Boosters. 1) Yes, if this library were to become a Boost library, all macro names will have to start with "BOOST_" (and all library code will have to be included in the "boost::" namespace). 2) Yes, Boost usually fully spells all symbols so MEM_FUN should be MEMBER_FUNCTION, and same story for any other symbol of this library that is not fully spelled. (I try to only use abbreviations already used by the STL, like MEM_FUN similar to the std::mem_fun binder but I am also happy to fully spell all symbols.) 3) The "DBC_BASE(type)" and "DBC_COPYABLE(type)" macros could be replaced by "(inherit)(type)" and "(copyable)(type)" if that made the macro syntax more clear (this will then be similar to the keywords "optional" and "required" introduced by the Boost.Parameter macro syntax). With a bit more work in the library implementation, I think it might be possible to remove the need for DBC_INHERIT_OBJECT and DBC_MULTI_INHERIT_OBJECT (I will have to look at the details of this...). On Mon, Oct 19, 2009 at 7:59 AM, Paul A. Bristow <pbristow@hetp.u-net.com> wrote:
Acronymitis is a serious problem for me ;-( DBC_ everywhere just looks very nasty.
4) DBC (actually "DbC"(TM) to be precise, as indicated by Neil) is a well recognize industry acronym for "Design by Contract"(TM). However, there might be trademark concerns in using this acronym (see http://en.wikipedia.org/wiki/Design_by_contract) and programmers have been using Programming by Contracts (PbC) or Contract Programming (CP) instead. The use of these other, much less know, acronyms will only increase Paul's concern above... In my opinion, if DBC is not to be used than "Contract" will be the best alternative. NAMING OPTIONS a) Use "DBC" (similar to Boost.MPL, Boost.CRC, etc) Library: Boost.DBC Namespace: boost::dbc Macros: BOOST_DBC_CONSTRUCTOR, BOOST_DBC_DESTRUCTOR, BOOST_DBC_MEMBER_FUNCTION, etc b) Use "Contract" (similar to Boost.Parameter, Boost.Test, etc) Library: Boost.Contract Namespace: boost::contract Macros: BOOST_CONTRACT_CONSTRUCTOR, BOOST_CONTRACT_DESTRUCTOR, BOOST_CONTRACT_MEMBER_FUNCTION, etc I am equally happy with either option a) or b). EXAMPLE OF b) This the NameList example I presented in a previous email reworked to use naming convention b). It also shows that the foreign looking macro syntax does NOT affect your .cpp files when function definitions are separated from their declarations. // File: RelaxedNameList.hpp (declarations with foreign looking macros). #include <boost/contract.hpp> // This library, if added to Boost as in option b). class RelaxedNameList: public NameList // Maybe the "..._INHERIT_OBJECT()" macros can be removed... not sure yet. BOOST_CONTRACT_MULTI_INHERIT_OBJECT(RelaxedNameList) { public: void put(const std::string& name) BOOST_CONTRACT_MEMBER_FUNCTION( (public) (void) // Using "copyable" and "inherit" instead of "..._COPYABLE()" and "..._BASE()" macros. (copyable)(RelaxedNameList) (inherit)(NameList) // Subcontracting (inherit) from NameList::put. (put)( (const std::string&)(name) ), { // This preconditions (in OR with the base preconditions allowing for duplicated names in the list). BOOST_CONTRACT_ASSERT_STREAM(self.has(name), "in list", err << "name '" << name << "' not in list"); }, { // This postconditions (in AND with base postconditions). if (self.old.has(name.now)) BOOST_CONTRACT_ASSERT(self.now.count() == self.old.count(), "if in list, count unchanged"); }, ; /* Body: ";" to separate definition from declaration. */ ) ... private: BOOST_CONTRACT_INVARIANT(RelaxedNameList, { // Invariants (in AND with base invariants, no additional invariant here). }) }; // EOF // File: RelaxedNameList.cpp (definitions, with NO foreign looking macro a part from BOOST_CONTRACT_BODY). #include "RelaxedNameList.hpp" void RelaxedNameList::BOOST_CONTRACT_BODY(put)(const std::string& name) { ... // This function implementation. } ... // EOF Thank you all for your comments so far. I will follow up with a couple of more technical emails illustrating some of the library internal mechanisms and comparing this library with DBC support from other languages, libraries, and proposals. Cheers, Lorenzo