diff --git a/content/h.dj b/content/h.dj deleted file mode 100644 index 4b083a9..0000000 --- a/content/h.dj +++ /dev/null @@ -1,167 +0,0 @@ -title = "header files are cool, actually" - -+++ - -You know what. -I actually kinda like header files. - -Yeah, _those_ things. -From C and C++. - -I've heard lots of opinions from fellow programmers, saying it's annoying to have to update your signatures in _two_ places. -However, I believe a lot of the extra repetition comes from _the bad design of C++'s classes_, rather than the idea of header files itself. - -I've mentioned this briefly before in [C++ without Classes][page:programming/cxx-without-classes], but a lot of redundant editing is born out of C++'s poor implementation of class encapsulation. -In C++, your implementation details come out leaking into the header file. - -```cpp -// .h file - -class World -{ -public: - Entity& entity(Entity_Id id); - - void update(const Update_Context& cx); - void draw(const Draw_Context& cx); - -private: - void draw_entities(const Draw_Context& cx); - - Entity entities[256]; - // etc -}; - -// .cpp file - -Entity& World::entity(Entity_Id id) { /* ... */ } - -void World::update(const Update_Context& cx) { /* ... */ } - -void World::draw(const Draw_Context& cx) { /* ... */ } - -void World::draw_entities(const Draw_Context& cx) { /* ... */ } -``` - -Closing yourself in the bubble of C++ might make you think header files are just that. -Annoying nuisances, artifacts of language design of the past. -DRY killers. - -Hacks of the dated C compilation model. - -However, if you observe what header files (or their equivalents) look like in _other_ languages---you start seeing something different.\ -Consider the same example, but written in C. - -```c -typedef struct -{ - Entity entities[256]; - // etc -} World; - -Entity* world_entity(World* w, Entity_Id id); - -void world_update(World* w, const Update_Context* cx); -void world_draw(const World* w, const Update_Context* cx); -``` - -See the difference? `draw_entities` is nowhere to be seen. -Meanwhile, in the corresponding implementation file: - -```c -Entity* world_entity(World* w, Entity_Id id) { /* ... */ } - -void world_update(World* w, const Update_Context* cx) { /* ... */ } - -static void draw_entities(const World* w, const Update_Context* cx) { /* ... */ } - -void world_draw(const World* w, const Update_Context* cx) { /* ... */ } -``` - -The `draw_entities` implementation detail---a _private function_---is still very much there! - -In OCaml, you would do something similar. -Here's `world.mli`: - -```ocaml -type t - -val entity : t -> Entity.id -> Entity.t -val update : t -> Game_loop.update_context -> unit -val draw : t -> Game_loop.draw_context -> unit -``` - -And here's `world.ml`: - -```ocaml -type data = { - entities: Entity.t array; -} -type t = data ref - -let entity w id = (* ... *) - -let update w cx = (* ... *) - -let draw_entities w cx = (* ... *) - -let draw w cx = (* ... *) -``` - -(Disclaimer: my knowledge of OCaml is pretty surface level. This is probably not valid syntax.) - -Our implementation detail `draw_entities` appears again, but only in the module's interface file. - -And that's how I view header files: as _public interface declarations_. -They say, "this is the set of public procedures you can run on these types." - -When viewed this way, header files become extremely useful for tracking changes in a module's public API, semantic versioning-wise. - -But perhaps more importantly, because headers written with the "public interface" philosophy in mind are so laser-focused on exposing the... well, _public interface_, they become your module's _reference documentation._ - -My favourite example of this is [Dear ImGui](https://github.com/ocornut/imgui/blob/v1.92.1/imgui.h), which takes this idea to the extreme. -Dear ImGui needs no documentation generator like Doxygen. -It's all right there in the header file, and all you have to do is open it in your text editor and grep for whatever you need at the moment. - -Here's an excerpt of `imgui.h` (reformatted to fit my blog's column limit better): - -```c -// Windows -// - Begin() = push window to the stack and start appending to it. -// End() = pop window from the stack. -// - Passing 'bool* p_open != NULL' shows a window-closing widget in -// the upper-right corner of the window, which clicking will set -// the boolean to false when clicked. -// - You may append multiple times to the same window during -// the same frame by calling Begin()/End() pairs multiple times. -// Some information such as 'flags' or 'p_open' will only be -// considered by the first call to Begin(). -// - Begin() return false to indicate the window is collapsed or fully -// clipped, so you may early out and omit submitting anything to -// the window. Always call a matching End() for each Begin() call, -// regardless of its return value! -// [Important: due to legacy reason, Begin/End and BeginChild/EndChild -// are inconsistent with all other functions such as BeginMenu/EndMenu, -// BeginPopup/EndPopup, etc. where the EndXXX call should only be -// called if the corresponding BeginXXX function returned true. -// Begin and BeginChild are the only odd ones out. -// Will be fixed in a future update.] -// - Note that the bottom of window stack always contains a window -// called "Debug". -IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); -IMGUI_API void End(); -``` - -Compare this to grepping through an `.rs` file, which usually yields lots of unrelated results. -I pretty much never grep through Rust files to look at APIs, while I do it all the time in C++. - -Perhaps it's a sign that the complexity of JavaScript-heavy online HTML documentation viewers with mediocre search functionality is entirely self-inflicted.\ -(I'll give them though that rich text is pretty cool, and Hackage's global type signature search is _wicked_ cool. Nothing that a sufficiently advanced LSP server shouldn't be capable of doing, though.) - -(...and also, fuck Doxygen. I hate using Doxygen so much. But I'll leave that for another time.) - ---- - -Either way, that does it for The Ramblings I Will Link Whenever Someone Mentions Header Files Are The Bane Of Their Existence. - -Thank you for reading. diff --git a/content/treehouse/new.tree b/content/treehouse/new.tree index ef76a8a..14343c1 100644 --- a/content/treehouse/new.tree +++ b/content/treehouse/new.tree @@ -26,13 +26,6 @@ if you've been wondering what I've been up to, you've come to the right place. if you want to read any of the posts, follow the links. it's like that by design. -% tags = ["programming", "cxx"] - id = "01K1Y3G5N1KGCN1E9B36QTYMSZ" -- ### [header files are cool, actually][page:h.dj] - - % id = "01K1Y3G5N1WTEYF5X4JJHGR5XN" - - in which I ramble about how to write good header files. - % tags = ["meow", "shower"] id = "01K05F3E3DN1PY9ZWN98ZE5HVV" - ### [furry! ---w--- (version 2)][page:furry.dj] @@ -208,7 +201,7 @@ if you've been wondering what I've been up to, you've come to the right place. % id = "01JDJJSEWAVZGJN3PWY94SJMXT" - I recently rebuilt the treehouse to use a virtual file system for its source and target directories. - + % id = "01JDJJSEWA7K5T3Z0Y6NQ8RBGX" - this is an exploration of how I built my abstraction, how it works, and what I learned from it. @@ -239,7 +232,7 @@ if you've been wondering what I've been up to, you've come to the right place. % id = "01JDTBGSJ7KB9GYWQZ8G9D97NY" - I'm an adorable little cat boy. purrow! _snuggle snuggle_ - + % id = "01JDTBGSJ7RVYR0VD693FN10QH" - a lesson in Shock Therapy & Getting Over It {-with Bennett Foddy-} @@ -339,7 +332,7 @@ if you've been wondering what I've been up to, you've come to the right place. % id = "01J293BFEB4G7214N20SZA8V7W" - sometimes people call me crazy for saying that bashing JavaScript is senseless and that it's not as bad of a language as people make it out to be. - + % id = "01J293BFEBYSW4K7YHVN42J3WP" - so I decided to collect my thoughts into a nice little page I can link easily. @@ -416,7 +409,7 @@ if you've been wondering what I've been up to, you've come to the right place. % id = "01HR9ZTS8RY3N4EJM5W7WBTF0G" - sidebars! also known as, _"enjoying the main content? how about I distract you from it so that you can't focus!"_ - + % id = "01HR9ZTS8RQ1EN0THYEVNQRY2A" - seriously though. I don't like them. diff --git a/template/components/_pink_space.hbs b/template/components/_pink_space.hbs index 5ca67b0..0d07bb2 100644 --- a/template/components/_pink_space.hbs +++ b/template/components/_pink_space.hbs @@ -1,5 +1,5 @@