Hypothetical: All code in classes but main()

Discussion in 'C++' started by Juha Kettunen, Apr 10, 2004.

  1. wow, finally I meet somebody who likes (c++) classes like me :). I am "with
    you" ... I never really liked that c-style programming, if you can do the
    same thing with classes, but this just my opinion and taste - I am not
    saying, that I have the truth in this issue. Maybe its like that somebody
    likes tea, but somebody else might hate tea but like coffee :).

    I dont see eny limitations in "normal programming" - I would defenitely
    choose class route if possible . I was jus thinking, that some very critical
    fast code might need pure c-code because of efficiency. For example in chess
    game programming you calculate 2 000 000 moves per second, so classes might
    not be suitable in all programming because they might be a little bit too
    slow ... but to be honest with you, I am not sure of this ... Does somebody
    know if this is true or not?
     
    Juha Kettunen, Apr 10, 2004
    #1
    1. Advertisements

  2. This is a purely *hypothetical* question. That means, it's /pretend/,
    CP. ;-)

    If you were forced at gunpoint to put all your code in classes, rather than
    in namespace scope (obviously classes themselves are an exception to this),
    and 'bootstrap' your program by instantiating a single application object
    in main(), would that place any limitations on what you could accomplish
    with your program? Are there any benefits to doing things that way (other
    than survival)?

    BTW, yes, I /do/ favor this approach.
     
    Steven T. Hatton, Apr 10, 2004
    #2
    1. Advertisements

  3. Juha Kettunen

    Jeff Schwab Guest

    I almost always have a single object to represent the whole application,
    and use main() only as an entry point. That said, forcing _everything_
    into classes seems to disallow use of some of my favorite C++ features
    and programming styles. For example, many operator overloads belong
    outside the class.

    template< typename T >
    int add_one( T const& t )
    {
    return 1 + t; // If T is a UDT, where is operator + defined?
    }
     
    Jeff Schwab, Apr 10, 2004
    #3
  4. I normally don't jump into hypothetical discussions like this, but parts
    of this just rankled me.

    Personally, I can see no practical functional limitations or benefits.

    [snip]
    Where this whole thing starts to spiral out of control is here. "C-code"
    by itself is no slower or faster than the equivalent "C++-code" (ie,
    class-based code). If you wanted to, you could write "slow" or "fast"
    code in either. In fact, writing the theoretical "fastest" program is
    possible in C and C++ - your compiler and your algorithm are what
    determine how "fast" your code will run.

    For the record, I make games, and I need "efficient" code to move big
    chunks of data around very quickly. I use classes with impunity - the
    things I usually watch for are polymorphism and virtual functions, and
    hidden code (destructors and constructors that aren't immediately
    obvious). And even these I use in some cases.

    But being told to put all your code into classes is as illogical to me
    as being told to use only words and phrases from Shakepeaean iambic
    pentameter as variable names. Or, more practically but no less obtuse,
    hungarian notation. Does it help anything? Not really. Does it hurt
    anything? Not really. And if it does either it does them in equal
    measure. So why insist on it?

    I mean, compare the elegance of this:

    int max(int a, int b) { return (a > b) ? a : b; }

    int larger = max(1, 2);

    To this:

    class Math
    {
    public:
    static int max(int a, int b) { return (a > b) ? a : b; }
    };

    int larger = Math::max(1, 2);

    Only Java programmers could find the latter more legible.

    Both can run just as fast (if you inline the former; the latter is
    intrinsically inlined), so it's not a speed issue. Namespace Math::max
    provides (essentially) the same amount of collision protection and
    encapsulation as class Math::max, so it's not a maintennance issue.

    What it is, is a design issue. What you're telling me is that there are
    such things as "Math" objects. In order to find the max of two numbers,
    I have to go get a "Math" and use the "Math"'s "max" operation. Or, in
    the static case, that "Math"'s have a behaviour or mechanism that is not
    specific to any one "Math", but is nonetheless "Math" object-specific
    behaviour.

    On the other hand, the free function tells me that "max" is an operation
    in category (ie, namespace) "Math". In other words, "max" is a "Math"
    operation.

    Doesn't the latter just make more sense?

    So in conclusion, what the hell are the benefits of such arbitrary
    constraints? Write your program so that it makes logical sense and
    models the problem it is trying to solve as closely as possible. If the
    language has the tools, and if they don't lead to bad design and
    maintennance problems, use them.

    If you really feel the need to apply arbitrary constraints, why not
    write your code in morse code ( http://www.ioccc.org/1986/hague.c )?

    mark
     
    Mark A. Gibbs, Apr 10, 2004
    #4
  5. I believe there is actually a technical limitation met when binary operators
    (ones that take two arguments) are forced to be class members. I need to
    review the section, but I believe there are some symmetries that are lost.
    IOW A@B works but B@A doesn't for cases such as '+' and '*'. Another
    problem is the fact that functions which were external to a class now gain
    access to member data and potentially become bound to it. This is the
    argument Stroustrup gives for having helper functions at namespace scope.

    I actually proposed another access specifier in addition to private,
    protected, public and firend. I suggested /associated/ which would allow a
    function to be a member, but it would only have access to public members of
    its own class.
     
    Steven T. Hatton, Apr 10, 2004
    #5
  6. I believe there actually are two. I already mentioned them in another post
    in this thread.
    As you correctly pointed out below, virtual function calls have some
    overhead beyond static calls. A static call to a member should be just as
    fast as a global 'C'-style call, as far as I know.
    One argument would be for the sake of uniformity. But I guess that's just
    the soldier in me talking.
    There are advantages to having the static Math class in Java. It provides
    for an easy point of reference. It's kind of like having a directory
    structure and using it to organize your data. Personally, the following is
    my idea of what a more complete set of mathematical operators looks like in
    a programming language. But MMA is a specialized language:

    http://documents.wolfram.com/v5/TheMathematicaBook/MathematicaReferenceGuide/InputSyntax/A.2.7.html
    Other than the fact that people tend to be sloppy with namespaces.
    No. It's saying there are mathematical operators which can be classified as
    such.
    You don't instantiate Math. It is a utilities class.
    And how does this differ from Java's use of a class where you use a
    namespace?
    It depends how it's managed. Java takes the functional operator approach to
    mathematical syntax, whereas C++ allows for infix notation. I find that
    far more significant in terms of how it 'feels' to use. An interesting
    parallel to this is found in Misner, Thorne and Wheeler's _Gravitation_
    where three notational forms are used in parallel through out the text:

    http://www.reviewcentre.com/review57645.html
    Actually, this was a hypothetical proposition. One reason for putting
    everything in classes is that it usually makes refactoring easier (with the
    possible exception of helper functions), and also makes reuse easier.
     
    Steven T. Hatton, Apr 10, 2004
    #6
  7. Two what? Limitations or benefits? Are you referring to your comments on
    assymetrical binary operations? That is not a design issue, that's an
    implementation issue. If you want an operation a @ b to be valid for
    objects of type A and B in any order you either have to define
    operator@(A) in B and operator@(B) in A (thus coupling the two), or
    define operator@(B) in A and operator@(A,B) globally (still coupling the
    two), or define operator@(A,B) and operator@(B,A) globally (leaving the
    classes uncoupled). To me, this *supports* non-class functions.

    But whatever you decide out of the above options, you are limited by the
    language. you could write add(A,B) and add(B,A) as class members (of
    either class) with no problems. If you are talking about limitations of
    possible implementations due to constraints of the language, count me
    out. I have no intention of discussing alterations to the language. I
    was talking about limitations on possible designs and program structures.

    Your second argument, if I understood it, makes no sense. "Another
    problem is the fact that functions which were external to a class now
    gain access to member data and potentially become bound to it. This is
    the argument Stroustrup gives for having helper functions at namespace
    scope." So does that support your argument or not?

    If a function requires access to member data, then by all means make it
    a member function. But static functions can't access member data, now
    can they? If they require access to static data, well that's different.
    But if you have a function that does not require instance-specific data,
    and does not require a class-global data (such as max()), you can choose
    to use either a static member function or a non-class function without
    concern.
    That is the idea. It is possible for a theoretical implementation to do
    something different, I suppose, but for all practical purposes it is
    safe to assume that the only functional difference between a global
    function and a class static function is that that the class static
    function has access to private and protected class static data and
    functions.

    So in the context of this discussion, there are no performance differences.
    Being a former soldier myself, I should point out that while uniformity
    is generally a good thing, there are many different types of soldiers,
    some specializing in airborne drops, some specializing in beach
    landings, not to mention the wildly varying trades like pilots,
    artillery, armoured, mechanized infantry etc. etc. etc.

    By all means, be uniform, but if the job calls for artillery, don't send
    in the infantry.
    ?

    You could replace "static Math class in Java" with "Math namespace in
    C++" in your statement, and it would still be valid. The *only* reason
    there is a static Math class in Java (as opposed to a Math namespace) is
    that Java does not support free functions.

    Given that C++ has the option, what are the advantages here?
    People can be just as sloppy with anything in C++, and it's usually the
    same people. Is there any emperical evidence that people tend to
    sloppiness when namespaces are introduced?

    But let me give the benefit of the doubt and ask sloppy in what way?
    Yes, but there are many ways of doing this in C++. You could use a
    "Math" class, or you could use a "Math" namespace, or you could prefix
    global functions with "Math_". Each of these methods groups certain
    operations together, and each tell me different things about that
    grouping. The class tells me that "Math"'s are things, ie, objects -
    it's not called object-oriented programming for giggles - just like
    class Student, class smart_ptr_policy or class ifstream. The namespace
    tells me that these functions are conceptually grouped in some way, but
    otherwise gives me no further indications of how - which is fine, all I
    really need to understand is that they are all "Math" functions.

    The last? I guess it just tells me that someone's a rotten programmer,
    unless they have a better excuse.
    Of course I understand that, it was my argument after all. But a class
    describes a (surprise, surprise) class of objects. The ONLY valid
    reasons I can think of for having a non-instantiable (static) class is
    when that body of operations MUST NOT be extended, and/or they all make
    use of some kind of private data/algorithms that MUST NOT be visible to
    the rest of the program. There are plenty of situations that satisfy
    those constraints. I don't believe max() (or sin(), or round() etc.)
    does. Explain to me why you do.
    ? what do you mean "Java's use of a class where you use a namespace"?

    [Taking a guess at what you meant]

    As I mentioned before, Java has no choice but to do max() with static
    class members. You have a choice in C++.

    Let me make this absolutely clear. I believe there is no difference
    between designs that use non-class-functions and those that do in terms
    of functionality, efficiency and maintainability. If anyone disagrees,
    let me know. As far as I'm concerned this discussion is over the
    benefits of Class::function() vs. Namespace::function(), and nothing more.

    So to answer what I think your question was: it doesn't. It's the same
    damn thing. There are no functional benefits either way.

    But to me at least, you are making a statement when you create a class
    vs. a namespace. A class describes a "thing", an object. A namespace
    describes a group. To me, mathematical operations can be grouped. But a
    "Math" doesn't have a "cosh()" capability. This is the basis of my
    argument for putting these functions in namespaces as opposed to classes.

    On the other hand, if I were to create a MemoryManager that was static
    (non-instantiable), that's a different story. A "MemoryManager" is a
    thing, an object. By making it a static class, I am making clear that
    there is only one MemoryManager available, and you are not responsible
    for creating or destroying it. Likewise, you are not to add functions to
    it (make your own damn MemoryManager). It is a single, global interface
    to some hidden memory system that needs managing. The static functions
    in that class provide some operation or functionality of this monolithic
    MemoryManager thing. Things like allocate(), get_free_memory(). That is
    the language of objects.

    Do not try to bend the Math into an object. That is impossible. Instead,
    try to remember the truth.

    There is no Math.
    wha?

    [Attempting to decode]

    If you prefer to use functional notation as opposed to operators, go
    nuts. I think a + b is more understandable than operator+(a, b), but
    hey, that's me.

    But how is any of that relevant to keeping all the code in classes?
    I understand that it was hypothetical, so was my proposed "morse coding
    standard". I am learning here, too. If you can convince me that
    class-only design is better in some way than using global functions, I
    may change my evil ways. But so far, all I have seen are wishy-washy
    pseudo-statements like "the 'fact' that people *tend* to be *sloppy*
    with namespace" or "putting everything in classes is that it *usually*
    makes refactoring *easier*" (emphasis added in all cases), or assertions
    to the tune of "that's how Java does it, so it must be good".

    So tell me what you mean by "easier" refactoring or reuse, and how a
    collection of static class functions makes this possible over a namespace.

    For the record, Java is designed to run in distributed and network
    environments. Because of the constraints of this environment, everything
    *has* to be a class. They didn't make class Math cause it was a good
    idea. They did it cause they needed the functions and had no other way
    to make them.

    But is it a good idea? I don't know, but I don't think so. Explain to me
    why I might be wrong.

    mark
     
    Mark A. Gibbs, Apr 10, 2004
    #7
  8. Juha Kettunen

    Jeff Schwab Guest

    What purpose would that serve?
     
    Jeff Schwab, Apr 11, 2004
    #8
  9. My point exactly. Though I'm not sure there isn't a third approach which
    might actually address the situation better than either of the two shown
    above.
    Yes it supports the point I was making.
    Of course they can.
    A static function has access to all member data. Am I missing something
    here? I only have a couple months of real C++ experience, so I may have
    misunderstood something, but I'm almost certain a static member function
    can access all member data of instances of the class.
    But there are certain attributes every solder shares with all others.
    Ironically, the model I used for notions of inheritance when first learning
    about the concepts of OO was the military organizational structure. There
    were no OO programming languages available to the average user at the time.
    If you have a reasonably good IDE its very easy to type:
    java.[get a listing of available packages and classes]

    select

    java.Math.[get a listing of available members with their type displayed]

    select what you want.

    If you don't like the fully qualified name in the body of your source, just
    type /Math.operation(arguments)/, highlight it (it will be displayed with
    an indication that the IDE doesn't know about /Math/) hit a specific key
    combination to invoke the display of all candidates available in your
    classpath. Select java.lang.Math from the list, and it is #imported in the
    heading of the source file.

    If you don't have an IDE just use bash to hook into the same support
    features the IDE uses to search the classpath, and to display member
    signatures, etc. It's a bit more work, but with a few scripts, it really
    is quite easy.
    One might argue that the real difference is that in Java you have another
    level of encapsulation. I find 'free' functions to be of questionable
    value. Some people seem to think of them as global functions.
    Perhaps. There is the advantage of predictability. That is, since there
    are fewer options, it's easier to determine how something is structured.
    It also enforces certain structural rules that programmers might otherwise
    violate.
    The STL.
    And (some) C++ programmers believe the last is a viable option.
    But when you have disorganized your collection of operators as described
    above, it is more difficult to work with. As far as OO goes, if you really
    understand what Java is doing, you would understand that it is very much OO
    to do things that way. But even if you only look at the surface, there is
    nothing non-OO about using utilities classes. It's just another way of
    using tools effectively.
    So if there is only one instance of a class, does that mean OO has been
    missused? I find that argument against the use of the Math class to be
    silly. Ever wonder why the German cognate for the English /dish/ means
    table? There is a lesson there.
    I tend to believe the onus falls in the other direction as far as the
    visibility of data. But that's just what the standard texts on OO say.
    One might argue that you have the illusion of choice in C++. How many
    main() functions can exist in a C++ program? How do you specify the
    namespace for that function? That sounds like a restraction, not a liberty
    to me.
    That was what I was intending in the immediate discussion. My inclination is
    to view namespaces as fairly unstructured in comparison to classes.
    I could be argued that /a/ math does have a cosine. But I would tend to
    argue that for practical purposes, there is only one (singleton) math.
    Math /is/ actually instantiated implicitly in Java.
    I don't find that to be a compelling argument. The name Math is just a
    shorthand for mathematical utilities. It works reasonably well. I was
    horrified when I first saw Java's vecmath (well actually it took a few days
    for the horror to sink in). There are some things that are simply awkward
    in it. Operator overloading would, perhaps, be a welcome enhancement, but
    when I simply accepted it for what it was, a lot of the superficial
    objections came to appear irrelevant.
    I sure have a lot of math books about nothing then.
    Yup, you understood the intent. There are some advantages to the functional
    operator approach to mathematical symbolism.
    Can you provide an example of a successfull general purpose programming
    language that used such an approach?
    I could rest my case right here.
    If you read my comment about namespaces you may notice I already addressed
    that. But, namespaces do have on additional drawback in that they are can
    easily be concatanated, sometimes in less than obvious ways.
    I'm not sure of all the cause and effect, but, yes, Java pretty much forces
    the creation of Math. There, of course, are a few alternatives, such as
    making a class for each operator, or for some subset of operators. I'll
    grant that Java lacks a lot of the available finesse in C++. But that
    feature of C++ comes at a cost.
     
    Steven T. Hatton, Apr 11, 2004
    #9
  10. Binding a helper function to a class, and still exclude it from protected
    and private access to data members.
     
    Steven T. Hatton, Apr 11, 2004
    #10
  11. Juha Kettunen

    David Harmon Guest

    On Sat, 10 Apr 2004 17:47:46 GMT in comp.lang.c++, "Mark A. Gibbs"
    Yes, obviously should be

    int larger = std::max(1, 2);
     
    David Harmon, Apr 11, 2004
    #11
  12. Yes, AFAIK you cannot put 'extern "C"' in a class, which severely limits
    what you can then accomplish with only standard C++.

    Apart from that there are issues of design (information hiding) and of
    practical stuff like binary operators. Although that doesn't limit what
    your executable code can accomplish it limits the usability of that code
    in client code, and it impacts negatively on maintainance & performance.

    In a real world project much of the grunt work is typically done by less
    experienced programmers, who tend to use static storage and namespace scope
    functions unless forbidden. As an example, in one mainly Java project many
    classes were designed as singletons using static storage for the instances.
    That created problems in performance testing where a large number of logins
    to the system had to be simulated using threads instead of processes.
     
    Alf P. Steinbach, Apr 11, 2004
    #12
  13. Hey! Whose side are you on here?
     
    Steven T. Hatton, Apr 11, 2004
    #13
  14. Juha Kettunen

    Jeff Schwab Guest

    A function doesn't need to be a member of a class to be associated with
    it. Just declare the function in the same namespace as the class, but
    outside the definition.

    class C { /* ... */ };

    void helper_function( C const& );
     
    Jeff Schwab, Apr 11, 2004
    #14
  15. Well, sure. But then we have people running around thinking of namespace
    scope as 'global' and doing unconscionable things such as using::std at
    global scope.

    Your example is exactly the functionality I was trying to preserve while
    more tightly associating the helper function with the specific class. The
    idea of having a bunch of classes at namespace scope and a bunch of helper
    functions which apply to one or some, but not all the classes seems
    unstructured to me.

    Certainly if care is taken in naming and choosing members of the namespace,
    it is workable. But, from what I've seen, programmers often start grouping
    things with category_subcategory_type names. These should more correctly be
    category::subcategory::type.
     
    Steven T. Hatton, Apr 11, 2004
    #15
  16. Juha Kettunen

    Jeff Schwab Guest

    I don't follow your logic. Using namespaces to group related functions
    and classes doesn't cause people to misunderstand namespaces. In fact,
    this is exactly the canonical usage.

    You can't prohibit people from abusing "using" directives. Your
    approach prohibits clients placing them even within a single function;
    isn't that throwing the baby out with the bath water? Anyway, trying to
    prevent your clients from using common coding styles you don't like
    seems a little pedantic. It's important to support clients by providing
    structure, but it's equally important to respect them, and to allow
    flexibility.
    But changing the word "namespace" to "class" would fix the perceived
    problem?
    How would grouping items in classes instead of namespaces change this?
     
    Jeff Schwab, Apr 11, 2004
    #16
  17. First off I meant to write /using namespace std;/ My brain does weird stuff
    like that.

    It's ok if used frugally. I still find it to be a bit too permissive and
    unstructured.
    No. I didn't suggest doing away with them completely. I don't like the way
    they concatonate and did make a few whimsical suggestions in that
    direction,
    I wasn't really thinking in those terms. I was just trying to determine
    what the technical implications, pro and con, of the all objects approach
    are. I'm not even thouroughly convinced there would be that much
    difference if namespaces were completely removed from the language, and in
    their place people used classes. I'm not suggesting that be done, but I am
    suggesting that it is a worthwhile thought experiment.
    What I'm saying is that, for example, ::std is a collection of templates
    (which I intended as well when I wrote 'class' and 'function') with only
    the fact that they are part of the Standard Library as a common
    characteristic. Yes, one purpose for namespaces is simply a mechanism for
    avoiding name collisions. But limiting their use to that goal puts us back
    in the same fix of having a bunch of unrelated entities all laying around
    on a common floor.

    Changing the name would not necessarily fix the problem. Disallowing
    functions at namespace scope, however, would be an interesting exercise.
    It was really a suggestion of how to address my concerns /without/ putting
    everything in namespaces. I do believe having a rule of thumb that
    everything that could be in a class should be in a class would lead to
    tighter designs with cleaner demarkation.
     
    Steven T. Hatton, Apr 11, 2004
    #17
  18. replace namespaces with class. I'm having one of those days! :-/
     
    Steven T. Hatton, Apr 11, 2004
    #18
  19. What point? And supports it how? It still makes no sense to me.

    I mean, this is how I look at it. If I have a class Foo and a function
    bar(), there is no coupling unless there needs to be, and if there needs
    to be a relationship, there needs to be a relationship.
    I did not say class static functions, I said static functions, which is
    equivalent to globabl functions. I was being very careful not to do this
    in order to not muddy the waters, but this one slipped by.

    Globabl functions cannot access member data. So there is no imperative
    to make them members. It is completely optional.
    class Foo
    {
    public:
    static void foo();
    static int foo_and_bar_can_see_me;
    int foo_cannot_see_me1;
    protected:
    static int foo_can_see_me1;
    int foo_cannot_see_me2;
    private:
    static int foo_can_see_me2;
    int foo_cannot_see_me3;
    };

    void bar();

    Given an instance of Foo f in foo or bar:

    void foo()
    {
    foo_and_bar_can_see_me = 1; // ok
    foo_can_see_me1 = 1; // ok
    foo_can_see_me2 = ; // ok

    Foo f;
    f.foo_cannot_see_me1 = 1; // ok
    f.foo_cannot_see_me2 = 1; // ok
    f.foo_cannot_see_me3 = 1; // ok
    }


    void bar()
    {
    foo_and_bar_can_see_me = 1; // ok
    // foo_can_see_me1 = 1; // bad
    // foo_can_see_me2 = ; // bad

    Foo f;
    f.foo_cannot_see_me1 = 1; // ok
    // f.foo_cannot_see_me2 = 1; // bad
    // f.foo_cannot_see_me3 = 1; // bad
    }

    While you are technically right, that a class static function can access
    all data members, if it needs to access private and protected instance
    members, why is it a class static function?

    Actually, that brings up another area that you're way out in left field
    on. Public data members. I was actually shaking my head in disbelief at
    your proposed "associated" extension. I have never heard any recommend
    the use of public data members in good OO design. It violates
    encapsulation. I have heard some Java wags claim that for performance
    reasons the cost of the accessor methods can be too much, but even that
    has been debunked as nonsense. Just declare your accessor methods final
    and most compilers will optimize them away. In C++ you don't even need
    to rely on the compiler's whims and fancies, just make the accessor
    functions inline.

    There are no benefits to public data members except for backwards
    compatability with old C code (and that is not an issue in this discussion).
    Oh my lord. Your justification for a restrictive design constraint to be
    applied to an entire body of work is that it makes it easier to make
    flashy IDE's?

    But I'll tell you what, I'll play along.

    Why is it not possible for a C++ ide to detect a function sin() in a
    namespace math in a namespace top?

    I type "top" then a "::" and the IDE looks for a class or namespace
    called top. It finds the namespace named top and pops up a charming
    little list box of all namespaces, classes and functions in namespace
    top. Then I click on the "math" namespace, and the box refreshes, now
    with a list of all the namespaces, classes and functions in namespace
    top::math. I could scroll down, but I'm too lazy, so I type "s". the
    field is narrowed considerably. There's sec(), sin(), sqrt() and more. I
    could click, but I paid a lot for this snazzy IDE, so I type the "i".
    Now the field is narrowed down to sin(), sinh() and a couple others. So
    I click on the "sin". Now I see a list of all the overloads of "sin".

    Now, none of my IDE's do it, but I've never been impressed by IDE's, so
    my compilers often have none to speak of (or I don't use them often, as
    in the case of CodeWarrior). I suppose I could get a better editor. So
    I'm not an authority on the subject, but there's probably an IDE out
    there right now that does it for C++. If not, there's no practical
    reason why there can't be, once someone is willing to put in the work.

    java.lang.Math perhaps?
    There is no other level of encapsulation, encapsulation happens (as it
    does in Java) at the class level. If you expose the guts of your class,
    that is hardly the fault of an external function.

    An external function that uses a class is just another client of that
    class. It sees the same interface as anyone else. If that interface
    changes, well you broke your program anyway, that's not the function's
    fault.
    I thought the structure was quite clear. All the math functions are in
    the Math namespace.

    What you're telling me is that you think having all the math functions
    in the Math class is more structured than having all the math functions
    in the Math namespace. But they're the same thing.

    The only possible plausible argument in your favour is that having a
    Math class means that all the math functions must be declared in a
    *single translation unit* (or a single header file, in practice). Yeah,
    I suppose there's some merit to that - you know exactly where to look
    for a function. But that comes at a price.

    The price is that I now have to include ALL the math functions in a
    source file, even if I just want sqrt(). Also, if I have 1000+ math
    functions (which is not inconceivable, what with overloads and all), and
    I want to change or add just one, ALL files that use ANY math functions
    will now need to be rechecked by the compiler. So much for predefined
    headers.

    Plus the obvious maintennance headaches trying to maintain one HUGE
    header file instead of a dozen smaller ones.

    You have not decreased coupling, you have increased it.
    Ok, that's not even a complete sentence. The STL what? Sucks? R0x0rs?
    Tastes like candy? What makes the STL empirical evidence that namespaces
    cause sloppyness? And once again, sloppy in what way? What is sloppy?
    Your point? Some Java programmers believe that public data members are a
    viable option. I wouldn't hire from either group.
    How have I disorganized anything? From what I can read it's perfectly
    well organized. The only difference between your organization and mine is:

    // mine
    namespace Math {
    // organization
    }

    // yours
    class Math {
    public:
    static // organization
    };

    I understand perfectly well what Java is doing. And why. And while I
    could argue over whether it may or may not be "the" OO way to do things
    (because OO is not exactly written in stone, you know, there are many
    interpretations of the OO gospel), I will point out instead that OO is
    hardly the last word in software design theory. Just search for object
    oriented critiques, and alternatives.

    As for utilities classes not being "non-OO", that's quite open to
    debate, but I am not going to debate it. Instead I am going to take you
    up on your final statement. "It's just another way of using tools
    effectively."

    The problem with that is that you're not using the tools effectively. In
    fact, you're not using the tools at all. Namespace-scope functions are
    tools, too. They are designed to solve a specific problem: operations
    that are not associated with class data. You're tossing the screwdriver
    aside and using the hammer to drive screws.

    In Java, all you have is the hammer, so what can you do but use it
    everywhere. In C++ (WHICH IS NOT AN "OO" LANGUAGE - it supports multiple
    paradigms), you have a whole array of tools. Why stick to the hammer?
    I am not an OO expert, so I really can't speak on that authoritatively.
    Personally, I don't think singletons violate OO design. But we're back
    again to insisting that you can create a "Math" (although we're now
    insisting there can be only one (from the Matrix to Highlander)). And
    once more I say, there is no Math. But prove me wrong, make one.

    And no, I've never wondered why any german thinker for english crockery
    would mean table, and for what. And I'm sure there is a lesson there,
    there are lessons everywhere. The questions should, is it a good lesson?
    And, is it relevant?
    Wha?

    What onus? What other direction? I mean, if the body of operations CAN
    be extended, and if they do not make use of any private data or
    functions (that cannot be contained within the function of course), why
    do the "standard texts on OO" say that they must be in a class instead
    of a namespace?
    There is no illusion. You can have as many main() functions as you want.
    You specify namespaces for main() functions the same way as for any
    other function. You can only have one *entry point*, but that's true for
    Java too (in the least illogical case). The only "restriction" here is
    that the main() function in the global namespace is the entry point.

    Java's restriction is no less restricting: the entry point must be a
    static function called main in your startup class. You can have static
    functions called main in other classes if you want. You can have free
    main functions in other namespaces if you want. What's the problem?
    It could also be argued that the world is a flat plate resting on the
    back of an infinitely high pile of turtles, and that there are fairies
    whose job it is to catch us when we fall off one side and put us on the
    other and to alter all of our memories and measurements to keep the
    truth from us. That doesn't make it right.

    If you really understood object oriented terminology, you'd be laughing
    at the idea of instantiating math. What's next, inheriting from Humour?
    Extending Peace? Overriding Truth?
    Unless, of course, you're doing math.
    After you provide me with a coherent and compelling argument in favour
    of ditching non-class functions.
    Yes, more complicated compilers and a shortage of IDE's that are smart
    enough to automatically guess the function you intend to use from part
    of the qualified name.

    Frankly, I don't care how hard my compiler vendor has to work to make me
    a working compiler. I mean, props to the dudes at Edison, but I don't
    see how that's relevant to my design process. So Java lacks a lot of the
    finesse of C++, that doesn't explain to me why you would choose to dumb
    down C++ now to make it more like Java.

    And of course, it doesn't answer the cardinal question. If Java is the
    model that C++ should follow, why does Java keep evolving to look more
    like C++?

    mark
     
    Mark A. Gibbs, Apr 11, 2004
    #19
  20. Then don't use it. That doesn't preclude the use of namespaces or
    namespace global functions.
    I can tell you what would happen, the same thing that would happen if
    you removed packages from Java. A mess.
    Except now there are no more name collisions.

    If I'm reading you correctly your concern with namespaces is that people
    don't use them enough. You would have preferred if there were
    std::container and std::algorithm namespaces. Correct?

    In the context of the STL namespace, anything more than std is not
    necessary anyway. After all, you're not supposed to add anything to it.
    And what do I gain by typing std::container::vector over std::vector?
    Interesting in the sense of the old chinese curse, perhaps. I maintain
    that it adds no functionality and takes away design choices. Ergo, it
    has no benefits.

    What I'm still waiting for you to explain to me is how it could possibly
    decrease the possibility of bugs, or increase clarity - SOMETHING,
    ANYTHING - to justify it.
    But just what is a "tighter" design? How do I measure this "tight"ness?
    What are the benefits of "tight" vs. "loose" code? How does
    Class::function() provide cleaner demarcation than Namespace::function()?

    Just answer me this: can you provide me with any HARD arguments or
    PROVABLE facts that support your argument, or is this all just based on
    what you "feel" would be "better"?

    mark
     
    Mark A. Gibbs, Apr 11, 2004
    #20
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.