Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #42821 > unrolled thread

Meta-C question about header order

Started byJens Schweikhardt <usenet@schweikhardt.net>
First post2014-04-12 19:37 +0000
Last post2014-06-10 09:40 -0700
Articles 20 on this page of 69 — 15 participants

Back to article view | Back to comp.lang.c


Contents

  Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-12 19:37 +0000
    Re: Meta-C question about header order Keith Thompson <kst-u@mib.org> - 2014-04-12 13:51 -0700
      Re: Meta-C question about header order glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-04-13 00:11 +0000
      Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 11:40 +0000
        Re: Meta-C question about header order "BartC" <bc@freeuk.com> - 2014-04-13 13:10 +0100
        Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-13 06:29 -0700
        Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-13 14:41 +0000
      Re: Meta-C question about header order Ken Brody <kenbrody@spamcop.net> - 2014-04-15 10:36 -0400
    Re: Meta-C question about header order Richard Damon <Richard@Damon-Family.org> - 2014-04-12 16:58 -0400
      Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-13 03:40 +0000
        Re: Meta-C question about header order Ian Collins <ian-news@hotmail.com> - 2014-04-13 16:26 +1200
          Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-13 05:02 +0000
            Re: Meta-C question about header order Ian Collins <ian-news@hotmail.com> - 2014-04-13 17:21 +1200
              Re: Meta-C question about header order Ken Brody <kenbrody@spamcop.net> - 2014-04-15 10:59 -0400
              Re: Meta-C question about header order Ken Brody <kenbrody@spamcop.net> - 2014-04-15 11:02 -0400
            Re: Meta-C question about header order Ken Brody <kenbrody@spamcop.net> - 2014-04-15 10:59 -0400
              Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-15 08:26 -0700
              Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-15 15:56 +0000
        Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 11:34 +0000
        Re: Meta-C question about header order Richard Damon <Richard@Damon-Family.org> - 2014-04-13 15:04 -0400
        Re: Meta-C question about header order Ken Brody <kenbrody@spamcop.net> - 2014-04-15 10:52 -0400
    Re: Meta-C question about header order Ian Collins <ian-news@hotmail.com> - 2014-04-13 11:09 +1200
      Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 11:47 +0000
        Re: Meta-C question about header order Ian Collins <ian-news@hotmail.com> - 2014-04-14 08:54 +1200
          Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-13 21:37 +0000
            Re: Meta-C question about header order Ian Collins <ian-news@hotmail.com> - 2014-04-14 09:49 +1200
          Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-14 19:17 +0000
            Re: Meta-C question about header order Ian Collins <ian-news@hotmail.com> - 2014-04-15 10:24 +1200
              Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-16 19:58 +0000
            Re: Meta-C question about header order Richard Damon <Richard@Damon-Family.org> - 2014-04-14 21:45 -0400
    Re: Meta-C question about header order luser- -droog <luser.droog@gmail.com> - 2014-04-12 16:48 -0700
      Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 11:52 +0000
    Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-13 01:04 +0000
    Re: Meta-C question about header order "BartC" <bc@freeuk.com> - 2014-04-13 10:15 +0100
      Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-13 04:06 -0700
      Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 12:01 +0000
        Re: Meta-C question about header order "BartC" <bc@freeuk.com> - 2014-04-13 13:46 +0100
          Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 13:58 +0000
    Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 11:29 +0000
      Re: Meta-C question about header order Martin Shobe <martin.shobe@yahoo.com> - 2014-04-13 08:48 -0500
        Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-13 14:25 +0000
          Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-13 15:02 +0000
          Re: Meta-C question about header order Martin Shobe <martin.shobe@yahoo.com> - 2014-04-13 21:45 -0500
            Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-14 01:16 -0700
              Re: Meta-C question about header order "BartC" <bc@freeuk.com> - 2014-04-14 10:16 +0100
              Re: Meta-C question about header order Richard Damon <Richard@Damon-Family.org> - 2014-04-14 21:33 -0400
            Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-14 16:25 +0000
              Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-14 09:47 -0700
              Re: Meta-C question about header order Martin Shobe <martin.shobe@yahoo.com> - 2014-04-14 13:29 -0500
                Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-14 19:31 +0000
                  Re: Meta-C question about header order Les Cargill <lcargill99@comcast.com> - 2014-04-14 20:03 -0500
                    Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-15 01:04 +0000
                Re: Meta-C question about header order Keith Thompson <kst-u@mib.org> - 2014-04-14 15:15 -0700
              Re: Meta-C question about header order Richard Damon <Richard@Damon-Family.org> - 2014-04-14 22:01 -0400
              Re: Meta-C question about header order "BartC" <bc@freeuk.com> - 2014-04-15 09:51 +0100
                Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-15 06:01 -0700
                  Re: Meta-C question about header order "BartC" <bc@freeuk.com> - 2014-04-15 14:29 +0100
                    Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-15 10:38 -0700
                    Re: Meta-C question about header order Kaz Kylheku <kaz@kylheku.com> - 2014-04-15 18:27 +0000
                      Re: Meta-C question about header order Malcolm McLean <malcolm.mclean5@btinternet.com> - 2014-04-15 12:45 -0700
                        Re: Meta-C question about header order ralph <nt_consulting@yahoo.com> - 2014-04-15 22:02 -0500
            Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-14 17:44 +0000
    Re: Meta-C question about header order Tim Rentsch <txr@alumni.caltech.edu> - 2014-04-19 01:25 -0700
      Re: Meta-C question about header order Richard Damon <Richard@Damon-Family.org> - 2014-04-19 10:30 -0400
        Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-23 19:47 +0000
          Re: Meta-C question about header order James Kuyper <jameskuyper@verizon.net> - 2014-04-23 15:53 -0400
        Re: Meta-C question about header order Tim Rentsch <txr@alumni.caltech.edu> - 2014-06-10 09:25 -0700
      Re: Meta-C question about header order Jens Schweikhardt <usenet@schweikhardt.net> - 2014-04-23 19:27 +0000
        Re: Meta-C question about header order Tim Rentsch <txr@alumni.caltech.edu> - 2014-06-10 09:40 -0700

Page 3 of 4 — ← Prev page 1 2 [3] 4  Next page →


#42876

FromJens Schweikhardt <usenet@schweikhardt.net>
Date2014-04-13 14:25 +0000
Message-ID<bqvl3kFhg97U8@mid.individual.net>
In reply to#42874
Martin Shobe <martin.shobe@yahoo.com> wrote
	in <lie4jc$2r1$1@dont-email.me>:
...
# The problem is the dependencies are still that big, messy, uglier than 
# hell graph doxygen generated.

No, they aren't. The dependencies are directed *acyclic* graphs. Before,
they contained cycles since with the include guards, a.h can include b.h
and b.h can include a.h without an actual cycle emerging. But both
directions must appear as edges in the graph for each header might be
included in isolation. Cycles are impossible by design under the
"headers don't include headers" rule.

# That graph now has to be kept in the heads 
# of each and every developer. Really, really, really, ..., ugly!

Why in the heads? If you forget one, the compiler tells you
"foo_t undeclared" and you include the header with typedef foo_t
above it. Repeat if necessary. This Turing machine can be proven to halt. :-)

FlexeLint is even smart enough to tell us about "Header file frob.h not
used in file bar.c", so we can cut down the headers to what's minimally
needed.

Can you imagine how much code is out there containing tons of unneeded
#include statements? Who goes to the trouble of analyzing whether some
header is actually needed? The common pattern is that include directives
grow in number, never decrease, like entropy. Who would dare to remove
an include directive from a *header* file? After all, it might be
required somewhere up the include chain in one of those myriads of
files. With the "headers don't include headers" this is dead simple to
answer, even without FlexeLint: remove it and check if it compiles to
the same object file as before. All you need to worry about is *one* C
file. If you want to remove an include from a header, you repeat this
check for *all the others including it directly or indirectly*. Nobody
but the most determined developers dare doing this. THAT is ugly.

Regards,

	Jens
-- 
Jens Schweikhardt http://www.schweikhardt.net/
SIGSIG -- signature too long (core dumped)

[toc] | [prev] | [next] | [standalone]


#42878

FromKaz Kylheku <kaz@kylheku.com>
Date2014-04-13 15:02 +0000
Message-ID<20140413075816.671@kylheku.com>
In reply to#42876
On 2014-04-13, Jens Schweikhardt <usenet@schweikhardt.net> wrote:
> Martin Shobe <martin.shobe@yahoo.com> wrote
> 	in <lie4jc$2r1$1@dont-email.me>:
> ...
> # The problem is the dependencies are still that big, messy, uglier than 
> # hell graph doxygen generated.
>
> No, they aren't. The dependencies are directed *acyclic* graphs. Before,
> they contained cycles since with the include guards, a.h can include b.h
> and b.h can include a.h without an actual cycle emerging. But both
> directions must appear as edges in the graph for each header might be
> included in isolation. Cycles are impossible by design under the
> "headers don't include headers" rule.

Also, they are *simple* directed graphs: a simple graph has no multiple
paths between the same two nodes.

This is the case when the dependencies are flattened and included in order.
No cycles, no redundancy.

> above it. Repeat if necessary. This Turing machine can be proven to halt. :-)

Well lookie who said he is not a computer scientist! Phwt!

[toc] | [prev] | [next] | [standalone]


#42892

FromMartin Shobe <martin.shobe@yahoo.com>
Date2014-04-13 21:45 -0500
Message-ID<lifi4h$3fe$1@dont-email.me>
In reply to#42876
On 4/13/2014 9:25 AM, Jens Schweikhardt wrote:
> Martin Shobe <martin.shobe@yahoo.com> wrote
> 	in <lie4jc$2r1$1@dont-email.me>:
> ...
> # The problem is the dependencies are still that big, messy, uglier than
> # hell graph doxygen generated.
>
> No, they aren't. The dependencies are directed *acyclic* graphs. Before,
> they contained cycles since with the include guards, a.h can include b.h
> and b.h can include a.h without an actual cycle emerging. But both
> directions must appear as edges in the graph for each header might be
> included in isolation. Cycles are impossible by design under the
> "headers don't include headers" rule.

There is such a thing as a circular dependency. Your rule won't change 
that fact at all. Neither does it change anything about what information 
any part of the code needs to be compiled correctly. All you are 
changing the one responsible for providing that information.

> # That graph now has to be kept in the heads
> # of each and every developer. Really, really, really, ..., ugly!
>
> Why in the heads? If you forget one, the compiler tells you
> "foo_t undeclared" and you include the header with typedef foo_t
> above it. Repeat if necessary. This Turing machine can be proven to halt. :-)

Yes, and the developers need to remember where foo_t is declared. 
They'll have to know this even when they don't care about foo_t because 
it's only an implementation detail five levels deep on the dependency 
graph. By requiring each header to include all the information it needs, 
the developer doesn't even have to know foo_t exists, let alone where to 
find it. (Or, even worse, which one to use.)

> FlexeLint is even smart enough to tell us about "Header file frob.h not
> used in file bar.c", so we can cut down the headers to what's minimally
> needed.
>
> Can you imagine how much code is out there containing tons of unneeded
> #include statements? Who goes to the trouble of analyzing whether some
> header is actually needed? The common pattern is that include directives
> grow in number, never decrease, like entropy. Who would dare to remove
> an include directive from a *header* file? After all, it might be
> required somewhere up the include chain in one of those myriads of
> files. With the "headers don't include headers" this is dead simple to
> answer, even without FlexeLint: remove it and check if it compiles to
> the same object file as before. All you need to worry about is *one* C
> file. If you want to remove an include from a header, you repeat this
> check for *all the others including it directly or indirectly*. Nobody
> but the most determined developers dare doing this. THAT is ugly.

As for removing include directives from header files, I do it whenever I 
modify a header file in such a way that the include directive is no 
longer needed. Furthermore, it's not a question of who might need that 
header file up the food chain, it's only a question of is that header 
needed to provide what this header is supposed to provide. If something 
downstream no longer compiles, then I fix that there. It's also how most 
of the people I've worked with do it.

Martin Shobe

[toc] | [prev] | [next] | [standalone]


#42895

FromMalcolm McLean <malcolm.mclean5@btinternet.com>
Date2014-04-14 01:16 -0700
Message-ID<0032a0e5-2d90-4ee3-b773-d50a2a6b684b@googlegroups.com>
In reply to#42892
On Monday, April 14, 2014 3:45:32 AM UTC+1, Martin Shobe wrote:
>
> There is such a thing as a circular dependency. 
>
Not common for headers. Either a or b must be first in the pre-processed
result, unless you're doing something really weird with conditional 
statements and including multiply, you can't generate a circular
dependency.

But not uncommon for source. a can call a function in b and b a function in
a. Generally a sign of poor design, but not always easy to eliminate.

[toc] | [prev] | [next] | [standalone]


#42896

From"BartC" <bc@freeuk.com>
Date2014-04-14 10:16 +0100
Message-ID<AJN2v.131382$oI.105942@fx18.am4>
In reply to#42895

"Malcolm McLean" <malcolm.mclean5@btinternet.com> wrote in message 
news:0032a0e5-2d90-4ee3-b773-d50a2a6b684b@googlegroups.com...
> On Monday, April 14, 2014 3:45:32 AM UTC+1, Martin Shobe wrote:
>>
>> There is such a thing as a circular dependency.
>>
> Not common for headers. Either a or b must be first in the pre-processed
> result, unless you're doing something really weird with conditional
> statements and including multiply, you can't generate a circular
> dependency.

You still need to decide which to declare first, if it can be either. So if 
there is an automatic tool to decide these things, if might get stuck.

But also, if you want to use some automatic tools to derive all or part of 
the headers from their associated modules, then a circular dependency can 
render this impossible, if the processing of one module requires access to 
the header of the other, which doesn't yet exist.

> But not uncommon for source. a can call a function in b and b a function 
> in
> a. Generally a sign of poor design, but not always easy to eliminate.

It can be tricky. Project modules A, B, C all use an interface module I 
which in turn calls some external (to the project) library. You want I to be 
independent from A, B and C.

But 'I' makes use of a very handy function f() residing in C for example, 
which might also make use of some typedef, macro, named constant** etc which 
is also common to A, B and C. It's going to be a lot of work to separate out 
f(), and the result is going to be untidy.

(** However the named const is implemented.)

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#42936

FromRichard Damon <Richard@Damon-Family.org>
Date2014-04-14 21:33 -0400
Message-ID<a003v.89436$86.87785@en-nntp-16.dc1.easynews.com>
In reply to#42895
On 4/14/14, 4:16 AM, Malcolm McLean wrote:
> On Monday, April 14, 2014 3:45:32 AM UTC+1, Martin Shobe wrote:
>>
>> There is such a thing as a circular dependency. 
>>
> Not common for headers. Either a or b must be first in the pre-processed
> result, unless you're doing something really weird with conditional 
> statements and including multiply, you can't generate a circular
> dependency.
> 
> But not uncommon for source. a can call a function in b and b a function in
> a. Generally a sign of poor design, but not always easy to eliminate.
> 

You can get a circular dependency with headers, a header a.h my need a
definition from b.h, and b.h may need a definition from a.h. Now you
can't do this, so something needs to be refactored.

It may be that b.h only needs a forward definition for a struct in a.h,
so maybe it could be changed to just forward declare as an incomplete
definition. It could also be that perhaps a.h needs to be broken into
two pieces, an a1.h that depends on b.h, and an a2.h that doesn't depend
on b, but provides the definitions that b.h needs. If this pops up, it
likely indicates that enough thought wasn't given to partitioning the
pieces (or something was refactored awkwardly).

[toc] | [prev] | [next] | [standalone]


#42898

FromKaz Kylheku <kaz@kylheku.com>
Date2014-04-14 16:25 +0000
Message-ID<20140414090455.107@kylheku.com>
In reply to#42892
On 2014-04-14, Martin Shobe <martin.shobe@yahoo.com> wrote:
>> Why in the heads? If you forget one, the compiler tells you
>> "foo_t undeclared" and you include the header with typedef foo_t
>> above it. Repeat if necessary. This Turing machine can be proven to halt. :-)
>
> Yes, and the developers need to remember where foo_t is declared. 
> They'll have to know this even when they don't care about foo_t because 
> it's only an implementation detail five levels deep on the dependency 
> graph. By requiring each header to include all the information it needs, 
> the developer doesn't even have to know foo_t exists, let alone where to 
> find it. (Or, even worse, which one to use.)

The theme we are seeing from the naysayers is developers shouldn't have to know
this, or shouldn't care about that, and in general should be able to focus on a
small part of the program through a narrow peep-hole in order to make an
intended change while learning as little as possible about the program.

That may be very well and fine in most of the industry, but in certain programs
that are developed to be polished gems of engineerng by people who take pride,
this idea of "know as little as possible" is poor ideological fit.

> As for removing include directives from header files, I do it whenever I 
> modify a header file in such a way that the include directive is no 
> longer needed. Furthermore, it's not a question of who might need that 
> header file up the food chain, it's only a question of is that header 
> needed to provide what this header is supposed to provide. If something 
> downstream no longer compiles, then I fix that there. It's also how most 
> of the people I've worked with do it.

"Something downstream" could be every single source file. Suppose "b.h" does
not actually need "a.h" itself, but everything implicitly depends on "a.h"
bringing in "b.h". For instance, everything has printf in it, and "b.h" is what
brings in <stdio.h>, though b.h doesn't actually use it. (Or just something
like size_t, which could have been obtained minimally from <stddef.h>).

These kinds of problems in the nested include system tend not to get fixed:
nobody wants to.

[toc] | [prev] | [next] | [standalone]


#42899

FromMalcolm McLean <malcolm.mclean5@btinternet.com>
Date2014-04-14 09:47 -0700
Message-ID<d25f303c-c19b-4999-a271-9befe0ac5fba@googlegroups.com>
In reply to#42898
On Monday, April 14, 2014 5:25:40 PM UTC+1, Kaz Kylheku wrote:
>
> The theme we are seeing from the naysayers is developers shouldn't have to know 
> this, or shouldn't care about that, and in general should be able to focus on a
> small part of the program through a narrow peep-hole in order to make an
> intended change while learning as little as possible about the program.
> 
The idea is that we have a set interface

y = square_root(x);

and we can play with the square_root() code to our heart's content. As long as we don't change the
interface, we won't break anything.

However that only works to a limited extent. if we're not changing the behaviour of square_root(),
why are we editing the code at all? In the bad old days, delays were sometimes implemented by
loops calling square_root functions (so that compilers wouldn't optimise them to nothing). So
even increasing the efficiency could break things. In fact we might want to tweak our handling of
negative x. So then we've got to go through all the calling code carefully to make sure that 
nothing depends on the previous handling of negatives. Quite likely we've specified the behaviour 
is undefined / reserved for future expansion, so if callers have done their job correctly, we won't
break anything. But you can't rely on that.
 

[toc] | [prev] | [next] | [standalone]


#42902

FromMartin Shobe <martin.shobe@yahoo.com>
Date2014-04-14 13:29 -0500
Message-ID<lih9ec$fuo$1@dont-email.me>
In reply to#42898
On 4/14/2014 11:25 AM, Kaz Kylheku wrote:
> On 2014-04-14, Martin Shobe <martin.shobe@yahoo.com> wrote:
>>> Why in the heads? If you forget one, the compiler tells you
>>> "foo_t undeclared" and you include the header with typedef foo_t
>>> above it. Repeat if necessary. This Turing machine can be proven to halt. :-)
>>
>> Yes, and the developers need to remember where foo_t is declared.
>> They'll have to know this even when they don't care about foo_t because
>> it's only an implementation detail five levels deep on the dependency
>> graph. By requiring each header to include all the information it needs,
>> the developer doesn't even have to know foo_t exists, let alone where to
>> find it. (Or, even worse, which one to use.)
>
> The theme we are seeing from the naysayers is developers shouldn't have to know
> this, or shouldn't care about that, and in general should be able to focus on a
> small part of the program through a narrow peep-hole in order to make an
> intended change while learning as little as possible about the program.
>
> That may be very well and fine in most of the industry, but in certain programs
> that are developed to be polished gems of engineerng by people who take pride,
> this idea of "know as little as possible" is poor ideological fit.

Allowing people to focus their limited resources on the important issues 
instead of distracting them with irrelevant detail results, in my 
opinion, in a greater chance of those "polished gems of engineering by 
people who take pride" being produced.

>> As for removing include directives from header files, I do it whenever I
>> modify a header file in such a way that the include directive is no
>> longer needed. Furthermore, it's not a question of who might need that
>> header file up the food chain, it's only a question of is that header
>> needed to provide what this header is supposed to provide. If something
>> downstream no longer compiles, then I fix that there. It's also how most
>> of the people I've worked with do it.
>
> "Something downstream" could be every single source file. Suppose "b.h" does
> not actually need "a.h" itself, but everything implicitly depends on "a.h"
> bringing in "b.h". For instance, everything has printf in it, and "b.h" is what
> brings in <stdio.h>, though b.h doesn't actually use it. (Or just something
> like size_t, which could have been obtained minimally from <stddef.h>).
>
> These kinds of problems in the nested include system tend not to get fixed:
> nobody wants to.

I suppose that could happen. In my opinion, those files downstream were 
already broken since they relied on an implementation detail of "b.h". 
Personally, I would remove "a.h" from "b.h" and add "a.h" to all those 
files downstream.

Martin Shobe

[toc] | [prev] | [next] | [standalone]


#42906

FromKaz Kylheku <kaz@kylheku.com>
Date2014-04-14 19:31 +0000
Message-ID<20140414122000.964@kylheku.com>
In reply to#42902
On 2014-04-14, Martin Shobe <martin.shobe@yahoo.com> wrote:
> On 4/14/2014 11:25 AM, Kaz Kylheku wrote:
>> On 2014-04-14, Martin Shobe <martin.shobe@yahoo.com> wrote:
>>>> Why in the heads? If you forget one, the compiler tells you
>>>> "foo_t undeclared" and you include the header with typedef foo_t
>>>> above it. Repeat if necessary. This Turing machine can be proven to halt. :-)
>>>
>>> Yes, and the developers need to remember where foo_t is declared.
>>> They'll have to know this even when they don't care about foo_t because
>>> it's only an implementation detail five levels deep on the dependency
>>> graph. By requiring each header to include all the information it needs,
>>> the developer doesn't even have to know foo_t exists, let alone where to
>>> find it. (Or, even worse, which one to use.)
>>
>> The theme we are seeing from the naysayers is developers shouldn't have to know
>> this, or shouldn't care about that, and in general should be able to focus on a
>> small part of the program through a narrow peep-hole in order to make an
>> intended change while learning as little as possible about the program.
>>
>> That may be very well and fine in most of the industry, but in certain programs
>> that are developed to be polished gems of engineerng by people who take pride,
>> this idea of "know as little as possible" is poor ideological fit.
>
> Allowing people to focus their limited resources on the important issues 
> instead of distracting them with irrelevant detail results, in my 
> opinion, in a greater chance of those "polished gems of engineering by 
> people who take pride" being produced.

Which is why I'm not arguing that this is the (or that there is a) One True Way
to structure C sources.

However, I have found this old-school approach to be very nice and workable
on a recent project of mine; none of the FUD against it is proving to be
a generalization. (FWIF, I have much more experience with the "every header
is guarded, and includes what it needs" approach.)

Anyway, in real engineering, there is more global awareness of changes
to a design. Maybe software is the way it is because everyone expects not
to be distracted with irrelevant details such as "how the hell does this
thing actually work as a coherent whole".

In electronics, you would never get away with bullshit like "I'm just going to
throw a little sub-circuit into this schematic and not care about anything
else, since the impedances obviously are such that it has no impact". (Let
someone else worry about board area and layout, noise and crosstalk issues,
emission, added power consumption and heat dissipation, etc).

It's not easy enough for some people that we can just type our product
from a keyboard and have a toolchain convert it into the final running
image. It additionally has to be possible to make changes without knowing
a whole lot of pesky context. Because our time is so expensive, and all.

Maybe this is why companies sometimes spend hundreds of thousands developing
some beautifully functioning working for a device, and then it goes to hell
because the task of making drivers was given to some yahoos as an afterthought,
and the end product is a flop that blue-screens everyone's PC.

[toc] | [prev] | [next] | [standalone]


#42930

FromLes Cargill <lcargill99@comcast.com>
Date2014-04-14 20:03 -0500
Message-ID<lii087$ccu$1@dont-email.me>
In reply to#42906
Kaz Kylheku wrote:
> On 2014-04-14, Martin Shobe <martin.shobe@yahoo.com> wrote:
>> On 4/14/2014 11:25 AM, Kaz Kylheku wrote:
>>> On 2014-04-14, Martin Shobe <martin.shobe@yahoo.com> wrote:
>>>>> Why in the heads? If you forget one, the compiler tells you
>>>>> "foo_t undeclared" and you include the header with typedef foo_t
>>>>> above it. Repeat if necessary. This Turing machine can be proven to halt. :-)
>>>>
>>>> Yes, and the developers need to remember where foo_t is declared.
>>>> They'll have to know this even when they don't care about foo_t because
>>>> it's only an implementation detail five levels deep on the dependency
>>>> graph. By requiring each header to include all the information it needs,
>>>> the developer doesn't even have to know foo_t exists, let alone where to
>>>> find it. (Or, even worse, which one to use.)
>>>
>>> The theme we are seeing from the naysayers is developers shouldn't have to know
>>> this, or shouldn't care about that, and in general should be able to focus on a
>>> small part of the program through a narrow peep-hole in order to make an
>>> intended change while learning as little as possible about the program.
>>>
>>> That may be very well and fine in most of the industry, but in certain programs
>>> that are developed to be polished gems of engineerng by people who take pride,
>>> this idea of "know as little as possible" is poor ideological fit.
>>
>> Allowing people to focus their limited resources on the important issues
>> instead of distracting them with irrelevant detail results, in my
>> opinion, in a greater chance of those "polished gems of engineering by
>> people who take pride" being produced.
>
> Which is why I'm not arguing that this is the (or that there is a) One True Way
> to structure C sources.
>
> However, I have found this old-school approach to be very nice and workable
> on a recent project of mine; none of the FUD against it is proving to be
> a generalization. (FWIF, I have much more experience with the "every header
> is guarded, and includes what it needs" approach.)
>
> Anyway, in real engineering, there is more global awareness of changes
> to a design. Maybe software is the way it is because everyone expects not
> to be distracted with irrelevant details such as "how the hell does this
> thing actually work as a coherent whole".
>
> In electronics, you would never get away with bullshit like "I'm just going to
> throw a little sub-circuit into this schematic and not care about anything
> else, since the impedances obviously are such that it has no impact". (Let
> someone else worry about board area and layout, noise and crosstalk issues,
> emission, added power consumption and heat dissipation, etc).
>

Yep, yep and YUP!

> It's not easy enough for some people that we can just type our product
> from a keyboard and have a toolchain convert it into the final running
> image. It additionally has to be possible to make changes without knowing
> a whole lot of pesky context. Because our time is so expensive, and all.
>


There are other, more complex reasons for this. Time spent acutally 
coding is, what 5% of total cost?

I am software much more than hardware, but I've never understood this 
drive in these industries. It's verification that's hard; why pretend it
doesn't exist?

> Maybe this is why companies sometimes spend hundreds of thousands developing
> some beautifully functioning working for a device, and then it goes to hell
> because the task of making drivers was given to some yahoos as an afterthought,
> and the end product is a flop that blue-screens everyone's PC.
>


Yep. Although some of that is that drivers come later,
and later is always on the short end of the stick.

-- 
Les Cargill

[toc] | [prev] | [next] | [standalone]


#42931

FromKaz Kylheku <kaz@kylheku.com>
Date2014-04-15 01:04 +0000
Message-ID<20140414180304.67@kylheku.com>
In reply to#42930
On 2014-04-15, Les Cargill <lcargill99@comcast.com> wrote:
> Kaz Kylheku wrote:
>> Maybe this is why companies sometimes spend hundreds of thousands developing
>> some beautifully functioning working for a device, and then it goes to hell
>> because the task of making drivers was given to some yahoos as an afterthought,
>> and the end product is a flop that blue-screens everyone's PC.
>>
>
> Yep. Although some of that is that drivers come later,
> and later is always on the short end of the stick.

Yes; if only one phase of multi-stage development process blows past some
deadline, it is necessarily the chronologically last one.

[toc] | [prev] | [next] | [standalone]


#42919

FromKeith Thompson <kst-u@mib.org>
Date2014-04-14 15:15 -0700
Message-ID<lnr44z8smf.fsf@nuthaus.mib.org>
In reply to#42902
ram@zedat.fu-berlin.de (Stefan Ram) writes:
> Martin Shobe <martin.shobe@yahoo.com> writes:
>>Allowing people to focus their limited resources on the important issues 
>>instead of distracting them with irrelevant detail results, in my 
>>opinion, in a greater chance of those "polished gems of engineering by 
>>people who take pride" being produced.
>
>   Sometimes, people go out of their way to please their lint.
>   When they have a lint that warns on multiple includes of the
>   same file, they deem that to be »dirty«. Would they use a
>   lint that would warn on the lack of include guards, they
>   would instead deem this to be »dirty«.

Is there a version of lint that warns about multiple includes of the
same file?

>   To please their lint, some - otherwise perfectly sane -
>   people write
>
> if(( buf = malloc( bufsiz )))
>
>   instead of
>
> if( buf = malloc( bufsiz ))
>
>   and then call this »good style«.

And I'd tend to agree with those perfectly sane people.  The extra
parentheses make it more obvious that the "=" was meant to be an
assignment, not an "==" comparison.

Though I'd write:

    if ((buf = malloc(bufsize)) != NULL)

myself.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#42940

FromRichard Damon <Richard@Damon-Family.org>
Date2014-04-14 22:01 -0400
Message-ID<Gp03v.37572$S85.2300@en-nntp-16.dc1.easynews.com>
In reply to#42898
On 4/14/14, 12:25 PM, Kaz Kylheku wrote:
> On 2014-04-14, Martin Shobe <martin.shobe@yahoo.com> wrote:
>>> Why in the heads? If you forget one, the compiler tells you
>>> "foo_t undeclared" and you include the header with typedef foo_t
>>> above it. Repeat if necessary. This Turing machine can be proven to halt. :-)
>>
>> Yes, and the developers need to remember where foo_t is declared. 
>> They'll have to know this even when they don't care about foo_t because 
>> it's only an implementation detail five levels deep on the dependency 
>> graph. By requiring each header to include all the information it needs, 
>> the developer doesn't even have to know foo_t exists, let alone where to 
>> find it. (Or, even worse, which one to use.)
> 
> The theme we are seeing from the naysayers is developers shouldn't have to know
> this, or shouldn't care about that, and in general should be able to focus on a
> small part of the program through a narrow peep-hole in order to make an
> intended change while learning as little as possible about the program.
> 
> That may be very well and fine in most of the industry, but in certain programs
> that are developed to be polished gems of engineerng by people who take pride,
> this idea of "know as little as possible" is poor ideological fit.
> 

The issue isn't to know as little as possible, but allow you to focus as
much as needed on the given task, and not get overloaded by details that
are not really needed at this point.

If you don't understand this, then perhaps you have never worked on a
piece of code that was truly large.

>> As for removing include directives from header files, I do it whenever I 
>> modify a header file in such a way that the include directive is no 
>> longer needed. Furthermore, it's not a question of who might need that 
>> header file up the food chain, it's only a question of is that header 
>> needed to provide what this header is supposed to provide. If something 
>> downstream no longer compiles, then I fix that there. It's also how most 
>> of the people I've worked with do it.
> 
> "Something downstream" could be every single source file. Suppose "b.h" does
> not actually need "a.h" itself, but everything implicitly depends on "a.h"
> bringing in "b.h". For instance, everything has printf in it, and "b.h" is what
> brings in <stdio.h>, though b.h doesn't actually use it. (Or just something
> like size_t, which could have been obtained minimally from <stddef.h>).
> 
> These kinds of problems in the nested include system tend not to get fixed:
> nobody wants to.
> 

A file that depends on a.h but doesn't include it directly, but only
indirectly via b.h has violated the basic concept of including what you
need (unless of course b's api promises that it will include a.h), so
the breakage was in the top level c file, not b.h, and that "breakage"
was actually pointing out a problem. These soft of problems are hard to
catch automatically, but you actually get used to checking for most of
this at code review.

[toc] | [prev] | [next] | [standalone]


#42955

From"BartC" <bc@freeuk.com>
Date2014-04-15 09:51 +0100
Message-ID<Jq63v.128045$y41.103520@fx03.am4>
In reply to#42898

"Kaz Kylheku" <kaz@kylheku.com> wrote in message
news:20140414090455.107@kylheku.com...
> On 2014-04-14, Martin Shobe <martin.shobe@yahoo.com> wrote:
>>> Why in the heads? If you forget one, the compiler tells you
>>> "foo_t undeclared" and you include the header with typedef foo_t
>>> above it. Repeat if necessary. This Turing machine can be proven to
>>> halt. :-)
>>
>> Yes, and the developers need to remember where foo_t is declared.
>> They'll have to know this even when they don't care about foo_t because
>> it's only an implementation detail five levels deep on the dependency
>> graph. By requiring each header to include all the information it needs,
>> the developer doesn't even have to know foo_t exists, let alone where to
>> find it. (Or, even worse, which one to use.)
>
> The theme we are seeing from the naysayers is developers shouldn't have to
> know
> this, or shouldn't care about that, and in general should be able to focus
> on a
> small part of the program through a narrow peep-hole in order to make an
> intended change while learning as little as possible about the program.
>
> That may be very well and fine in most of the industry, but in certain
> programs
> that are developed to be polished gems of engineerng by people who take
> pride,
> this idea of "know as little as possible" is poor ideological fit.

You take that thinking a bit further, then it is better to have larger
numbers of much smaller include files that each define only one thing.
Because after all you can't have a single include file providing a
'peephole' into the 10 or 100 functions it might define.

Take it one step further, then perhaps you can dispense with include files
altogether; just discretely define each constant, variable, macro, typedef
and function that is referenced not only directly by the this module, but
also indirectly.

Which means any program along these lines:

#include <windows.h>

int main(void) {
 MessageBox(0,"Hello World","",0);
}

would need to have at least 25,000 lines of preamble before you even get to
your own code.

Actually, that's not quite true. Maybe the programmer can use his/her
knowledge of the inner workings of windows.h to pick up only the 5,091 
scattered lines that are actually necessary in any specific module. Of 
course, a few edits later, it might need to be 6,620 lines, and the next 
day, only 4,378 lines. With luck he/she might have a few minutes spare each 
day to actually work on their code!

Or maybe one can choose the sensible approach and just use these headers as
they were intended.

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#42959

FromMalcolm McLean <malcolm.mclean5@btinternet.com>
Date2014-04-15 06:01 -0700
Message-ID<4a9be194-7060-4caa-bf1f-c4d75865db36@googlegroups.com>
In reply to#42955
On Tuesday, April 15, 2014 9:51:42 AM UTC+1, Bart wrote:
> "Kaz Kylheku" <kaz@kylheku.com> wrote in message
> 
> > That may be very well and fine in most of the industry, but in certain
> > programs that are developed to be polished gems of engineerng by people who take
> > pride,  this idea of "know as little as possible" is poor ideological fit.
> 
> You take that thinking a bit further, then it is better to have larger
> numbers of much smaller include files that each define only one thing.
> Because after all you can't have a single include file providing a
> 'peephole' into the 10 or 100 functions it might define.
> 
> Take it one step further, then perhaps you can dispense with include files
> altogether; just discretely define each constant, variable, macro, typedef
> and function that is referenced not only directly by the this module, but
> also indirectly.
> 
> Which means any program along these lines:
> 
> #include <windows.h>
> 
> int main(void) {
> 
>  MessageBox(0,"Hello World","",0);
> 
> }
> 
> would need to have at least 25,000 lines of preamble before you even get to
> your own code.
> 
I had exactly that issue with Baby X.

There's a message box function. But all it actually needs to expose in its public interface is the
connection to the opaque BabyX system, and the message box function itself, plus a few flags
for options.
So it's a choice whether to wrap everything up into one big include, or require users to #include
headers for each component separately. The internally of course message box makes a lot of calls 
to the Baby X system, it needs buttons and labels and modal access. So should there be private
components?
In fact I went for putting everything into one big header which is included by all files.

[toc] | [prev] | [next] | [standalone]


#42961

From"BartC" <bc@freeuk.com>
Date2014-04-15 14:29 +0100
Message-ID<yva3v.1$Qm2.0@fx16.am4>
In reply to#42959
"Malcolm McLean" <malcolm.mclean5@btinternet.com> wrote in message 
news:4a9be194-7060-4caa-bf1f-c4d75865db36@googlegroups.com...
> On Tuesday, April 15, 2014 9:51:42 AM UTC+1, Bart wrote:


>> Which means any program along these lines:
>>
>> #include <windows.h>
>>
>> int main(void) {
>>
>>  MessageBox(0,"Hello World","",0);
>>
>> }
>>
>> would need to have at least 25,000 lines of preamble before you even get 
>> to
>> your own code.
>>
> I had exactly that issue with Baby X.
>
> There's a message box function. But all it actually needs to expose in its 
> public interface is the
> connection to the opaque BabyX system, and the message box function 
> itself, plus a few flags
> for options.
> So it's a choice whether to wrap everything up into one big include, or 
> require users to #include
> headers for each component separately. The internally of course message 
> box makes a lot of calls
> to the Baby X system, it needs buttons and labels and modal access. So 
> should there be private
> components?
> In fact I went for putting everything into one big header which is 
> included by all files.

Which is the sensible approach I suggested. And I understand with Baby X, 
then it might work on top of X Windows, or on top of Win32, or perhaps 
something else altogether.

Those dependencies /do not belong/ in the user's code. The OP's entire 
approach seems to be along the wrong lines. Maybe there are issues with too 
many include files and too many poorly constructed ones, but I think the 
solutions lie elsewhere.

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#42984

FromMalcolm McLean <malcolm.mclean5@btinternet.com>
Date2014-04-15 10:38 -0700
Message-ID<699eaa03-2d5e-4831-a6ac-d620b6f8d517@googlegroups.com>
In reply to#42961
On Tuesday, April 15, 2014 2:29:20 PM UTC+1, Bart wrote:
> "Malcolm McLean" <malcolm.mclean5@btinternet.com> wrote in message 
> 
> 
> > In fact I went for putting everything into one big header which is 
> > included by all files.
> 
> Which is the sensible approach I suggested. And I understand with Baby X, 
> then it might work on top of X Windows, or on top of Win32, or perhaps 
> something else altogether.
> 
> Those dependencies /do not belong/ in the user's code. The OP's entire 
> approach seems to be along the wrong lines. Maybe there are issues with too 
> many include files and too many poorly constructed ones, but I think the 
> solutions lie elsewhere.
> 
Qt adopts the "include the class you need" approach. Of course it's a lot bigger than Baby X, and
it's C++ rather than C.
I can't remember offhand if Qt exposes header dependencies to the user.

[toc] | [prev] | [next] | [standalone]


#42985

FromKaz Kylheku <kaz@kylheku.com>
Date2014-04-15 18:27 +0000
Message-ID<20140415112328.331@kylheku.com>
In reply to#42961
On 2014-04-15, BartC <bc@freeuk.com> wrote:
> "Malcolm McLean" <malcolm.mclean5@btinternet.com> wrote in message 
> news:4a9be194-7060-4caa-bf1f-c4d75865db36@googlegroups.com...
>> On Tuesday, April 15, 2014 9:51:42 AM UTC+1, Bart wrote:
>
>
>>> Which means any program along these lines:
>>>
>>> #include <windows.h>
>>>
>>> int main(void) {
>>>
>>>  MessageBox(0,"Hello World","",0);
>>>
>>> }
>>>
>>> would need to have at least 25,000 lines of preamble before you even get 
>>> to
>>> your own code.
>>>
>> I had exactly that issue with Baby X.
>>
>> There's a message box function. But all it actually needs to expose in its 
>> public interface is the
>> connection to the opaque BabyX system, and the message box function 
>> itself, plus a few flags
>> for options.
>> So it's a choice whether to wrap everything up into one big include, or 
>> require users to #include
>> headers for each component separately. The internally of course message 
>> box makes a lot of calls
>> to the Baby X system, it needs buttons and labels and modal access. So 
>> should there be private
>> components?
>> In fact I went for putting everything into one big header which is 
>> included by all files.
>
> Which is the sensible approach I suggested. And I understand with Baby X, 
> then it might work on top of X Windows, or on top of Win32, or perhaps 
> something else altogether.

That approach also supports "precompiled headers": a feature that some
compilers have. The included parts of a translation unit can be saved in a
"compiled" form for faster inclusion. If all translation units share the same
material (they all include the same common header) then it just has to be
lexically analyzed once; the binary form is then used by all source files.

The downside of the approach is that it doesn't express dependencies correctly.
Everything depends on every header file. Touch any header and you have to
recompile everything.

The gains obtained from a faster full rebuild will be erased by poor
incremental rebuild times, with interest.

In this regard, it is not sensible, except for very small programs.
Exact dependencies are superior (regardless of the specific approach).

[toc] | [prev] | [next] | [standalone]


#42991

FromMalcolm McLean <malcolm.mclean5@btinternet.com>
Date2014-04-15 12:45 -0700
Message-ID<5e62dc31-b904-4e4b-a4ef-456cb1f1859b@googlegroups.com>
In reply to#42985
On Tuesday, April 15, 2014 7:27:49 PM UTC+1, Kaz Kylheku wrote:
> On 2014-04-15, BartC <bc@freeuk.com> wrote:
> 
> That approach also supports "precompiled headers": a feature that some
> compilers have. The included parts of a translation unit can be saved in a
> "compiled" form for faster inclusion. If all translation units share the same
> material (they all include the same common header) then it just has to be
> lexically analyzed once; the binary form is then used by all source files.
> 
Unfortunately MS Visual Studio creates massive precompiled header files.
It's a real nuisance if you want to separate out your valuable work from
megabytes of binary junk that all computer systems generate. Then it
insists on adding stdafx.h to everything. So portable ansi C source files
won't compile. And it doesnt save any meaningful time for a smallish
project.

[toc] | [prev] | [next] | [standalone]


Page 3 of 4 — ← Prev page 1 2 [3] 4  Next page →

Back to top | Article view | comp.lang.c


csiph-web