How does D improve design practices over C++?

Tony tonytech08 at gmail.com
Thu Nov 6 13:57:33 PST 2008


"Janderson" <ask at me.com> wrote in message 
news:gesi8g$4ii$3 at digitalmars.com...
> Tony wrote:
> > "Janderson" <ask at me.com> wrote in message
> news:gepsn2$21jr$1 at digitalmars.com...
> >> Tony wrote:
> >>> Let me be facetious with Janderson's list plz...
> >>>
> >>> "Janderson" <ask at me.com> wrote in message
> news:ge8tpd$1f6b$1 at digitalmars.com...
> >>>> Hi,
> >>>>
> >>>> I was talking with some collages at work and they asked me how D
> enforces good programming practices.   For course I mentioned a couple of 
> the ones I knew of hand -
> >>>>
> >>>> - Unit checking
> >>> Not sure what is meant by this, but it sounds minor.
> >> Sure C++ can do unit checking, but its not built in.  You have to
> use macros or templates in something that is not really designed to work 
> correctly with the language.  Even if you ignore that there's a barrior to 
> entry by not having something like this in the language.  By having it in 
> the language good coding practices are encouraged.
> >
> > I write unit tests. I don't know why I'd need or want language
> support for that.
>
>
> What api do you use?  All the api's I've used are not as nice as the built 
> in one for D.

In-house/proprietary, but it's hardly anything automated such as I'm sure 
there are commercial offerings for. I'm not close enough to deployment to 
worry about detailed testing: there are still some architectural issues to 
solve for higher level framework components.

>
>
> >
> >>>> - Design by contract
> >>> Overblown concept, but can be done with C++ also to a more than
> adequate degree (heard of assertions?).
> >> Yes this can be done with C++ but D takes it it many steps further.
> >
> > Like I said, I find the techniques more important that some
> implementation of them (mechanism rather than policy?).
>
> D contracts take this one step futher then C++.  They allow one to 
> decouple the contracts from the code itself:
>
> long square_root(long x)
>     in
>     {
>     assert(x >= 0);
>     }
>     out (result)
>     {
>     assert((result * result) <= x && (result+1) * (result+1) >= x);
>     }
>     body
>     {
>     return cast(long)std.math.sqrt(cast(real)x);
>     }

Or if one wanted something like that in C++:

class MyInvariant
{
    MyInvariant(long& x)
    {
        // do a check on entry
    }

    ~MyInvariant()
    {
        // do a check on exit
    }
};


>
> D also has better compile time messages.  It also support static asserts.
>
>
> >
> >>>> - Invariant checks
> >>> Part of DbC concepts. See Koenig and Moo's array example in
> "Accelerated C++". Which, btw, leads me to believe that there are few 
> instances "where the stars line up just right" for invariant checking to 
> be useful.
> >> Invariant checks can be done in C++ but its very unweildly.  It is
> very annoying to have to instruct each function with scope guards.  D 
> encourages good invariant checking by making it easy.
> >
> > But again, I am thinking that the scenarios where invariants can be
> established is a very small subset of classes.
> >
>
> I think the best programmers use invariant checks a whole lot.

If one has a lot of opportunity to use invariants, I'll bet it has to do 
with the domain. Such as numerical programming: that would seem to have a 
lot of those opportunities for use of invariant checking. In other domains 
(mainstream GUI dev?), much less so or even rarely so.

>
> >>
> >>>> - Stronger const
> >>> Insignificant. I still use many #defines just because I know that
> const vars take space and #defines are a pre-compile-time thing (yes, I 
> value the preprocessor for some uses, this being one of them).
> >> Actually any good compiler will inline const variables but I'm not
> talking about those sort of const.  Also you pay 2 costs for using 
> #define:
> >>
> >> 1) its not typesafe
> >> 2) it adds to your compile time because the pre-processor has to do
> more.
> >
> > Coming from the Windows world, one isn't "afraid" of 1 above
> whatsoever. Compile time? CPUs are evolving faster than I'll ever be able 
> to outpace them with the complexity or volume of my software.
>
> I guess for u compilation time isn't a problem.  It is for me.  Every 
> large project I've worked on gets to a point where compile time is a 
> problem.  Partly because of use of code-generation (templates) which yes 
> slow things down but is also generating a load of code I don't have to.

I'll bet it's a design problem rather than a template machinery problem. 
Templates are way overused IMO, and few people know how to or just don't 
bother architecting nice generic classes and functions.

>
> Also #defines really arn't a problem for cpu at compile time, your right 
> there.  I'm trying to point out that using #defines for const is totally 
> rediculus (sorry for being so harsh).  No C++ book or expert would 
> recommend it and it doesn't result in any run-time optimisation what so 
> ever.

Obviously I take language feature "recommendation" with a grain of salt. I 
do #define because I've never had any problem with it (and look at the 
Windows header files sometime!) and #defines don't create a data object in 
memory. It's simply never been a problem. Now if one is "hell bent/anal" 
about "doing away with the preprocessor, power to them, "it ain't me" 
though. I don't want the template machinery taking over the capability of 
the preprocessor: I use it to mutate the language and experiment. I will 
probably implement a preprocessor to replace or add to what I have with C++ 
before I jump into compiler development for my language that is evolving.

>
> >
> >> I'm talking about the const you put in function declarations which
> are very important.
> >>
> >>
> >>>> - Modules
> >>> If that means doing away with header files, I don't think I like
> it. I rely on headers as the engineer's blueprint (of course you have to 
> write very clean code to have that make sense).
> >> I think this means you simply haven't run up against any of the
> problems with header files.
> >
> > That's probably exactly what it means. But maybe I'm tooling up to
> write utility software rather than large scale software.
>
> That could be so.  D does seem targeted at large scale software.  For me 
> that's great.  That's the thing with C verse C++.  I think C is great 
> until you have to write something large that is maintainable.  C++/D has a 
> lot of scaffolding and that only starts to pay dividends when the code 
> gets larger.  At some point a C++ program will be smaller then a C 
> program.
>
> >
> >>>> - Garbage collection
> >>> That's a major deal breaker for me.
> >> Garbage collection can be turned off in D if you don't need it.
> >
> > So I've been told. But I think the default should be to include it
> when you like rather than the other way around. Obviously, I can use a GC 
> library in C++ if I was so inclined.
>
> This is a good debatable point.  I don't agree but that's just because of 
> all the headakes I've had to track down with manual management.
>
>
> >
> >> However for me (even when performance is very important and a game
> programmer) I can deal with it.
> >>
> >>>> - No automatic copy constructor
> >>> Can't comment.
> >> I'd encourage you to read "See C++ Coding Standards: 101 Rules,
> Guidelines, and Best Practices (C++ In-Depth Series)" by Herb Sutter, 
> Andrei Alexandrescu
> >>
> http://www.amazon.com/Coding-Standards-Guidelines-Practices-Depth/dp/0321113586
> >> one of the only books that has Bjarne Stroustrups seal of approval.
> >
> >> Effective C++ is another good read.
> >
> > Been there a number of times. Automatic copy constructor issue didn't
> catch my eye though obviously.
>
> In C++ its standard practice by most programmers to disable the copy 
> constructor for many of the classes they create.  Some companies it 
> mandatory to either disable it or implement one.

I do that too: I "disable" (declare private and don't supply an 
implementation") the compiler-called class functions by default when 
designing a class and putting them back if they are needed.

>
> >
> >>
> >>>> - More restrictive operators
> >>> I'm not really concerned about that. I'd avoid them unless doing
> numerical programming.
> >> The point here is that in C++ operators where used for all sorts of
> things that they where not designed for.  This makes code hard to follow.
> >
> > I whole heartedly agree!
> >
> >> D restricts operators making them more difficult to use for
> something they are not really designed for, ie encouraging better design.
> >
> > Minor. I know when not to use operators (read: hardly ever!).
>
> For you this might not be a useful feature however for many others it is, 
> and that is who I was address when I wrote this document.  With small apps 
> with short development cycles you have intimate knowledge about everything 
> that makes it tick.  With large apps you have to communicate though code. 
> A language that enforces some sort of standards and documentation (ie even 
> key words as simple as interface) will ultimately help others with that 
> communication.  Also when I go back to the code in 6months I will have a 
> better understanding of it because the compiler prevented me from writting 
> something that was nonsensical.
>
> >>>> - Specific constructs such as Interfaces
> >>> C++ has interfaces. Should it be a keyword? Maybe. How are D's
> interfaces different from C++'s?
> >> C++ has interfaces which can easily become abstractions.  This is
> not good.  By saying something is an interface, your documenting -> this 
> is an interface don't change me.  Its much better when the code can 
> enforce rules rather then by just comments.  You look at an interface in D 
> and you know its an interface, C++ you have to read though the code or 
> hope someone has documented it.  I'm not the best explainer in the world 
> so maybe someone else can explain this better.

I guess for D it is a bigger issue because header files are frowned upon? 
The header file in C++ is the first level of documentation, and if you code 
cleanly, maybe all that is required. Combine that with some 
design/architecture description and most of the documentation chore is done.

> >
> > I use naming standards for interfaces: iSomeClass, for example. I'm
> not sure what problem D's interfaces solve. I find no problem with C++'s 
> interface techniques.
> >
>
> Compiler checked documentation.  This is an interface and that's what it 
> is.  Don't make it abstract.  It a built in naming and enforced 
> convention.  Also I know there's lots of heat around styles however having 
> things like "i" in front of classes means that you can't change what that 
> thing is (well you can in you have access to the user-code and what to do 
> a find-replace).
>
> >>>> - More restrictive casting
> >>> Ouch!! I prefer to slice bread with a knife rather than having a
> machine do it. (Bad analogy, but y'all get the point).
> >> I'd rather the machine catch something at compile time rather then
> runtime.
> >
> > As long as I'm not prevented from doing casting I know is safe, it's
> fine.
>
> That's the point of casts right :)   You can always cast to what you want 
> in D however the more dangerous ones can be slightly harder to do.
>
> >
> >>>> - No C style Macros
> >>> Implementing a template or template system with a good preprocessor
> is something completely different than macros. I value the preprocessor 
> for such uses (I wish it was more powerful than in C++ though).
> >> Macros in C++, powerful yes but I think they are over used.
> >
> > Macros and using the preprocessor as a template machine are apples
> and oranges. Every use of the the C++ preprocessor does not fit the 
> definition of "macro", thought everyone pounces on the obvious as you do 
> below:
> >
> >> D has a replacement for the macro system which is more powerful.
> Most of which is not done in the preprocess.  I've seen more horrible C++ 
> macros then I can count.  They are definably not a good practice. Any good 
> C++ books will talk about "Macro side effects".  They arn't typesafe, 
> there's a possibility of having an operation performed in a place you 
> don't expect.  They don't work will on multilines (i hate \ because its 
> not maintainable and error prone).  Doing things like string operations 
> are just non-intuitive.
> >>
> >> The other bad thing about macros is they are extremely difficult to
> debug.
> >>
> >> D provides many of the functionalities of macros in a nicer form:
> >> - Better Templates
> >> - Mixins
> >> - Version
> >>
> >> Site note: About ~80% of macros I've seen in C++ could have been
> done with templates in C++ and they would have been much better in so many 
> ways.


Again though, "macros" and "preprocessor-implemented templates" are not the 
same thing, but I'd rather not go round and round on this.

Tony 





More information about the Digitalmars-d mailing list