The purpose of a header file is to define part of the contract for a function's invocation. If you leave out the names of function's parameters, in most cases there will not be enough information for the average developer to use a function. Consider the following function signature:
void draw_Foobar_widget(
int,
int,
char *
);
Now consider the following:
void draw_Foobar_widget(
int width,
int height,
char *title
);
Which is clearer?
I suppose Mr.Cuddleyourbraces is trying to optimize the DRY principle at the detriment of the information hiding principle. The DRY principle encourages maintainable code. The information hiding principle encourages usable code. The developer who sees the first function definition is compelled to investigate the source code for the initializeFoobarWidget- and thus must confront all the complexity thereof. It is therefore a well-accepted convention to document the external view of a function in the header file. That means providing a function signature that is understandable without consulting the source code. And named function parameters.
Using named function parameters in two places does violate the DRY principle, which is probably why some programming languages don't require a prior function signature (Java, perl, python, php, etc.) But you lose a lot more than you gain by observing the DRY principle to the extreme of not naming function parameters in your header files. The compiler cannot enforce good documentation via a man-page or something of that nature. The compiler can enforce the existence of function signature. A well-disciplined programmer knows how to use them.
Choose your poison:
- Slightly more maintainable code that is never used.
- Usable, well-designed software that takes an extra dash of discipline to maintain.
6 comments:
Naming variables in function declarations is NOT information hiding. If anything it would be contrary to that principle.
Nor are declarations meant to define a contract (and the same goes for everything else that usually goes in a header file). That is what the the formal parameter list in the function definition does. Header files exist so that the compiler has the proper definitions to do its work.
A final note: a well-disciplined programmer knows what does and what does not belong in header files. A header file helps organize a program by keeping all the "prerequisites" out of the way from the real "meat and potatoes" of a the code.
Maybe I wasn't clear- when I referred to "information hiding" I was demonstrating how a principle can be taken too far- when you hide the information of the parameter names, the developer is compelled to investigate- thus losing all the benefits of information hiding in the first place.
When you provide a code library to a customer, where is the "function definition" provided? In the compiled library? Should we force the customer to reverse compile our code to find the function definition?
The header files are a deliverable, along with the .lib, .so, .a or whatever you make for someone's use. If you're especially conscientious, you can publish an additional spec with your delivered code. But I always find the header file (if done correctly) to be the first source for understanding a code library.
The header file can also serve the use of providing an area where shared data or definitions are contained in a common place. This might be considered an "implementation header file" rather than a deliverable header file. These types of header files are recognizable because they are not referenced by other header files- they only appear in the implementation portion of source code. Maybe that's what your babbling about when you refer to the "prerequisites" (that rings of implementation details- something best excluded from deliverable header files).
Just like the deliverable .a and .so files are not intended for the customer to read and understand, header files are similarly incomprehensible with their tangle of conditional compilation and inclusion lines to ensure the product will work on a variety of platforms. Nobody looks to .h files to understand how to use a library other than masochists and wannabe hackers.
Even in cases where function prototypes in headers provide some hints to the user as to how the parameters are used, it is better to add comments on how that is done rather than use the names the developer happened to have used--which may or may not be "self-documenting" and always more awkward than what can be expressed in plain English.
It's pretty clear now that the header files you have been referring to are the ones of your own creation. If you try to deliver the same binary to multiple platforms, I could imagine requiring the aforementioned "incomprehensible" header files. In the real world, most binaries are compiled on the target platform before delivery. This means that the delivered binary has no need of platform-specific hacks.
Ideally a header file would contain a single abstract data type spec (a struct in C) and relevant function prototypes (with named parameters).
"Nobody looks to .h files to understand how to use a library other than masochists and wannabe hackers."
I'd like to see what the rest of the world thinks of that statement.
The header files I am referring to are real world examples. And you set up yet another straw man (perhaps you should considering your handle to that): I said nothing about delivering compiled binaries to the customers, just that the same source files (including the headers) are used.
Your notion of an "ideal" header file is a strange one. You seem to be thinking of Java (which does not have header files) rather than C, given that Java requires exactly one public class per source file (the ADT spec) and within that class you have your methods.
Post a Comment