4 ms·
That is a major usability setback. It gets worse when headers A and B both require header C. Let's say your source already includes A and C and you want to add
by john_moscow 6y ago
That is a major usability setback. It gets worse when headers A and B both require header C. Let's say your source already includes A and C and you want to add B. Now you need to manually read through the comments to understand where exactly in the include list you need to plug it.
This will become completely unmanageable once your include count surpasses 20-something, which is normal for large projects.
- sergeykish 6y agoUsability is easy to fix. Replace comment with #pragma or better list dependencies in a separate file (like gemspec). Add #require keyword which resolves order automatically. That's advice from February 21, 1989. They've implemented OS and some GUI applications, for example acme text editor [1]. Maybe it is not that hard. [1] https://github.com/brho/plan9/blob/master/sys/src/cmd/acme/acme.c https://github.com/brho/plan9/blob/master/sys/src/cmd/acme/a...
- kqr 6y agoThis sounds like something that can be solved by a separate tool (similar to rcorder that determines the order in which to execute rc files in BSD systems based on their dependency specifications) one can plug into the build process.
- alxlaz 6y agoAs with much of Pike's advice, it's worth remembering where it comes from: Unix, specifically AT&T-style Unix (and later Plan 9), where a fairly disciplined (programming-wise, at least :P) team of very good, and oftentimes very experienced developers wrote a lot of small, interconnecting utilities. If your whole source code is written in that manner, and written by people who write code in that manner, this advice is easy to follow. On the other hand there aren't many files in the Plan 9 source tree that are longer than, what, 3,000 lines? 4,000? Attempting to shoehorn that, and many other well-intended nuggets of wisdom from the Unix 'heritage", into your average commercial codebase, with dozens of third-party libraries and whatnot, is unworkable (I know, I tried). Some programming advice pearls translate well into any project. "Avoid gratuitous comments like "increment i", use comments to explain the reasoning behind functionality, not describe what the source code already adequately describes" can be applied on any source tree, starting at any point. But some of them -- such as this one -- only work if you write and organize your code in a particular way. FWIW, I think that this bit of advice was useful back when Pike wrote it, in the age of slow, buggy C compilers (although some would argue we're still in that era!) munching code off of network-mounted drives. Nowadays, not so much -- I think it has readability advantages but I doubt the performance gain (if any is left) is worth the extra programmers' effort. I like to follow it when I'm writing small utilities but I don't really fuss about it for larger projects, and I've never been curious to see how fast it is. I believe (but never measured it, so take it with a grain of salt!) that it's one of those things that 30+ years of computer systems evolution (in the biological sense -- "advancement" is probably too strong a word) has made obsolete.
- flohofwoe 6y agoI think that's (a big part) of the whole point: splitting a project into too many small headers which depend on each other is bad. Including headers into headers just hides the problem, but it's still there under the hood and grows worse the bigger the project becomes until it's too late to do anything about it. That how you get hours-long compile times in large C++ projects. Instead use few big headers, for instance one public-interface header per system/module which only contains declarations (no inline or template code), and at most one private header for each module (or better none at all). Then keep the dependency tree between modules/systems as flat as possible. This is especially important for large projects.
- guenthert 6y agoThe preprocessor can be expected to read files and scan to the corresponding #endif very fast. Reading from cache is also very fast. C++ compilation bogs down when templates are involved. You want to split those (in a way which makes sense to the human reader), so that only the ones needed for a given compilation unit are instantiated. Further the link stage, which is difficult to parallize, is a bottleneck.
- flohofwoe 6y agoIt's not just about compile speed, but also about staying sane while working on the project ;)
- cxr 6y ago> Now you need to manually read through C already has similar problems that are worse. For any given function used in a program, you have no guarantee that you can locate where that function is implemented in a straightforward way. In the worst cases, you have to resort to using dumb hacks like ctags or a project-wide recursive grep. It makes it hard to read any given program in the Knuthian way—laid up in bed with a printout to study how it works. (Go has the same problem. When I started seriously looking at Go, I was surprised that it copied C here, given the strong influence from Oberon.)