Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #42821 > unrolled thread
| Started by | Jens Schweikhardt <usenet@schweikhardt.net> |
|---|---|
| First post | 2014-04-12 19:37 +0000 |
| Last post | 2014-06-10 09:40 -0700 |
| Articles | 20 on this page of 69 — 15 participants |
Back to article view | Back to comp.lang.c
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 →
| From | Jens Schweikhardt <usenet@schweikhardt.net> |
|---|---|
| Date | 2014-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]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2014-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]
| From | Martin Shobe <martin.shobe@yahoo.com> |
|---|---|
| Date | 2014-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]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2014-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]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-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]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2014-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]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2014-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]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2014-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]
| From | Martin Shobe <martin.shobe@yahoo.com> |
|---|---|
| Date | 2014-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]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2014-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]
| From | Les Cargill <lcargill99@comcast.com> |
|---|---|
| Date | 2014-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]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2014-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2014-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]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2014-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]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-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]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2014-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]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-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]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2014-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]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2014-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]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2014-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