7 ms·
> Header files are one of the things I miss the most about languages that aren't C. Having a very clear distinction between public and private, and interface an
by kouteiheika 2y ago
> Header files are one of the things I miss the most about languages that aren't C. Having a very clear distinction between public and private, and interface and implementation is one of my favourite things about C code (at least the way I write it).
I always found this argument baffling, because the way some other language solve this problem is with tooling, which is a much better way to do it in my opinion.
Take Rust for example. You want to see the interface of a given library and see how to use it? Easy. Type in `cargo doc --open` and you're done. You get a nice interface with fully searchable API interface with the whole public API, and it's all automatic, and you don't have to manually maintain it nor have to duplicate code between your header and your source file.
- panic 2y agoAs someone who likes C header files, I enjoy manually maintaining them. Designing the interface separately from the implementation feels good to me, and a well-structured .h file is nicer to read than any auto-generated docs I've encountered.
- chii 2y ago> Designing the interface separately from the implementation feels good to me would you make the same argument for java then?
- otteromkram 2y agoAbsolutely not.
- tpoacher 2y agoyou don't like java interfaces?
- marginalia_nu 2y agoEven as a java programmer, I think this is a bad take. Java doesn't force separation of implementation and interface, and java interfaces also have a lot of weird stuff going on with them. Java also has too many tools for this. You both have class/interface, but also public/private. I honestly think C does it better than Java.
- chii 2y ago> java interfaces also have a lot of weird stuff going on with them. really? I know java pretty well, and there aint nothing weird there. C uses conventions to produce an "interface" (ala a header file with declarations). Java uses compilers to produce an interface, which i do really like. You can ship that interface without an implementation, and only at runtime load an implementation for example. > You both have class/interface, but also public/private. And these are all othorgonal concerns. A private interface is for the internal organization of code, as opposed to a public one (for external consumption). That's why you might have a private interface.
- marginalia_nu 2y ago> C uses conventions to produce an "interface" (ala a header file with declarations). Java uses compilers to produce an interface, which i do really like. You can ship that interface without an implementation, and only at runtime load an implementation for example. You can do this in C as well, since it has separate code declarations and definitions. You conventionally put the declarations in the header and definitions in the source file. A C program can link against declarations alone, and the implementations can be loaded later using dynamic linking. > And these are all othorgonal concerns. A private interface is for the internal organization of code, as opposed to a public one (for external consumption). That's why you might have a private interface. But these are profoundly overlapping concerns. Interfaces also hide the internal organization of the code, and on top of this, you also have project jigzaw's modules (that absolutely nobody uses), but which also caters toward separating private implementations from public interfaces.
- layer8 2y agoIt’s important to not conflate Java’s interface keyword with the more general notion of “interface” as in “API”. In Java, you generally don’t and can’t have a source-level representation of the API without it being interspersed with its implementation. (You could imagine such a representation, i.e. remove all method bodies and (package-)private elements, but the result wouldn’t be valid Java. IDEs arguably could and should provide such a source-level view, e.g. via code folding, but I don’t know any that do.)
- xigoi 2y agoThe problem is that you have to write the interface not only separately grom the implementation, but together with the implementation as well, which leads to duplication of information;
- bluGill 2y agoSo? Yes you need some duplicatin but it forces you to put information useful to api users where they won't have to wade through pages of information not of interest to them. eventually they may need to read the source but a lot of common questions are answered by the header and so the small cost to make them is worth it. of course javadoc can answer the same questions but then you have to run it.
- TheNewAndy 2y agoThis is probably something where it comes down to preference and familiarity. I would much prefer a simple text file for documentation that I can grep, open in my text editor, modify easily without switching context (oh, I should have been more explicit in the documentation I wrote - let me just fix that now), etc. All the features you mentioned "nice interface, fully searchable API interface, whole public API" are exactly what you get if you open a well written header file in any old text editor. I used to be a big fan of doxygen etc, but for the stuff I've worked on, I've found that "pretty" documentation is way less important than "useful" documentation, and that the reformatting done by these tools tends to lead towards worse documentation with the people I have worked with ("Oh, I need to make sure every function argument has documentation, so I will just reword the name of the argument"). Since moving away from doxygen I have stopped seeing this behaviour from people - I haven't tried to get a really good explanation as to why, but the quality of documentation has definitely improved, and my (unproven) theory is that keeping the presentation as plain as possible means that the focus turns to the content. I don't know if rust doc suffers the same issues, but the tooling you are mentioning just seems to add an extra step (depending on how you count steps I suppose, you could perhaps say it is the same number of steps...) and provide no obvious benefit to me (and it does provide the obvious downside that it is harder to edit documentation when you are reading it in the form you are suggesting). But with all these things, different projects and teams and problem domains will probably tend towards having things that work better or worse.
- metadat 2y ago> well written text file The problem with this is no one agrees on the definition of "well-written", so consistency is a constant battle and struggle. Language tooling is a better answer for quality of life.
- TheNewAndy 2y agoThat's an interesting assertion, but not one that matches the experience I've had. It is one of those things that sounds "obviously true", but in practice I've found that it doesn't really live up to the promise. As a concrete example of this, having a plain text header file as documentation tends to mean that when people are reading it, if they spot a mistake or see that something isn't documented that should be documented, they are much more likely to fix it than if the documentation is displayed in a "prettier" form like HTML. The problem with header files that aren't "well-written" tends to be that the actual content you are looking for isn't in there, and no amount of language tooling can actually fix that (and can be an impediment towards fixing it).
- salgernon 2y agoI’m with parent - what if you don’t have the tool? What if there’s a syntax error in some implementation or dependency such that the tool chokes early? Human readable headers are accessible out of context if the implementation. They also help provide a clear abstraction - this is the contract. This is what I support as of this version. (And hopefully with appropriate annotations across versions)
- kouteiheika 2y ago> I’m with parent - what if you don’t have the tool? The "what if you don't have the tool" situation never happens in case of Rust. If you have the compiler you have the tool, because it's always included with the compiler. This isn't some third party tool that you install manually; it's arguably part of the language. > What if there’s a syntax error in some implementation or dependency such that the tool chokes early? In C I can see how this can happen with its mess of a build systems; in Rust this doesn't happen (in my 10+ years of Rust I've never seen it), because people don't publish libraries with syntax errors (duh!).
- TheNewAndy 2y ago"Never" is a big call. In this specific case, your tool requires a web browser (though I'm assuming that there is a non-web browser form of what is being sold here). Maybe you are in a situation where you only have terminal access to the machine. Maybe you are on your phone just browsing github looking for a library to use I'm sure people can continue to imagine more examples. It is entirely possible that we have different experiences of projects and teams.
- nindalf 2y ago> I’m sure people can continue to imagine more examples Hopefully they’ll imagine more compelling examples. If the hypothetical person’s phone is capable of browsing GitHub, I don’t see why they can’t also browse docs.rs. It renders well on small screens. That’s not a hypothetical, I’ve actually read the docs for libraries on my phone.
- 2y ago
- nox101 2y agoSounds like COM/DCOM from ~1995. Every API had a public interface including a description. You could open the DCOM Inspector, browse all the APIs, and see the type signature of every function and its docs.
- pjmlp 2y agoStill is COM from 2025, given its relevance on Windows, even more since Vista, as all Longhorn ideas were remade in COM. However the tooling experience is pretty much ~1995, with the difference IDL is at version 3.0.
- Brian_K_White 2y agoheaders perform the same job for all code, not just code that's in some library. Frankly your description of what you just called easy sounds terrible and pointlessly extra, indirection that doesn't pay for itself in the form of some overwhelming huge win somewhere else. It's easy only if the alternative was getting it by fax or something.
- saghm 2y agoHaving to make an entire separate file to mark something as public rather than just having a keyword in the language sounds to me "terrible and pointlessly extra". It's not like you can't just put all your public stuff in it's own file in Rust rather than putting private stuff in it as well; empirically though, people don't do this because it's just not worth the effort.
- nine_k 2y agoThink about closed-source software that has to export a low-level programmatic interface. You may not believe it, but it's still widespread.
- nine_k 2y agoThe include file mechanism is a hack that was acceptable at the time when machines were extremely underpowered, so only the simplest solutions had a chance to be implemented within a reasonable time frame. By now, of course, precompiled headers exist, but their interplay with #define allows for fun inconsistencies. And, of course, they leak implementation as much as the author wants, all the way to .h-only single-file libraries. If you want an example of a sane approach to separate interface and implementation files from last century, take a look e.g. at Modula-2 with its .int and .mod files.
- alextingle 2y agoPrecompiled headers are a terrible misfeature. I ban them in any code base I am responsible for. They encourage the use of large header files that group unrelated concerns. In turn that makes small changes in header files produce massive, unnecessary rebuilds of zillions of object files. The clean practice is to push down #includes into .c files, and to ruthlessly eliminate them if at all possible. That speeds up partial rebuilds enormously. And once you adopt that clean practice, pre-compiled headers yield no benefit anyway.
- pjmlp 2y agoModules already existed in programming languages outside Bell Labs in the same decade, like the Modula-2 you quote.