Hacker News new | ask | show | jobs
by agentultra 3835 days ago
I think you missed the philosophical justification at the beginning of the series. This is Handmade Hero we're talking about where we build every system of the game with no help from libraries, frameworks, or engines. The whole point is to show people how it all works from soup to nuts.

Using libraries, even the STL in C++, would be cheating.

In the bigger picture of things these abstractions have costs. They're not free despite the C++ propaganda machine telling us otherwise. It's important to know what those costs are in order to make effective decisions about whether to include them in your project.

And finally the golden rule: if it looks right it is right. We're not here to write pretty, elegant code. Your pretty abstractions don't matter to the hardware. The target platform your system runs on is likely a highly-optimized piece of circuitry with real, physical constraints. Casey is the first programmer I've seen teaching people to keep the Intel manual handy and how to implement data-structures for cache-efficiency instead of pretty abstractions and virtual machines and template meta-programming.

It may not be a style of programming that agrees with you but it's one that has a growing number of proponents from Casey to Mike Acton, Jonathan Blow, and others. It's not a new idea either... but it certainly distinguishes itself as a reaction to the normative notion of programming by abstraction. It's a philosophy that proscribes programming by mechanical sympathy; using machines to manipulate data to get the results you desire.

1 comments

I haven't missed it, I know the idea is to do everything by hand, which I think definitely has educational value but does not necessarily lead to better or more efficient code (to the contrary, even). Not using STL or Boost on the one hand, but using many of the available OS frameworks on the other hand, seems a bit arbitrary, I don't see why 'handmade' should mean 'reinventing the wheel' even on basic tools and building blocks like data structures etc.

>> In the bigger picture of things these abstractions have costs. They're not free despite the C++ propaganda machine telling us otherwise. It's important to know what those costs are in order to make effective decisions about whether to include them in your project.

Based on years of writing all kinds of software I can only disagree with this. Even in games there's such a tiny amount of code that would really benefit from going all the way down to the bare metal to avoid some constant-factor overhead of higher-level abstractions, that it rarely makes any sense to even think about these things before you have working code you can run through a profiler. Almost always, spending your time and effort finding and using higher-level abstractions pays off much more than tinkering with your ghetto-hashmap implementation 'to make it faster'.

>> It may not be a style of programming that agrees with you but it's one that has a growing number of proponents from Casey to Mike Acton, Jonathan Blow, and others. It's not a new idea either... but it certainly distinguishes itself as a reaction to the normative notion of programming by abstraction. It's a philosophy that proscribes programming by mechanical sympathy; using machines to manipulate data to get the results you desire.

Philosophically, that's all nice and dandy. Practically speaking, it doesn't make much sense though, except for educational purposes (and even then, only up to the point of showing how things work, then moving on and settling on a proven, battle-tested version of the same thing that you don't need to maintain and debug yourself. At least that's my opinion...

> it rarely makes any sense to even think about these things before you have working code you can run through a profiler. Almost always, spending your time and effort finding and using higher-level abstractions pays off much more than tinkering with your ghetto-hashmap implementation 'to make it faster'.

There is a circularity to this logic that you should address.

On the one hand, you shouldn't write your own abstractions because someone else did a good-enough one already.

On the other hand, you shouldn't try to write more appropriate abstractions because you should have working code first.

Well, which is it? If you intend to write appropriate abstractions(and that's a goal of HH), you have to start off being a bit too crude and slow so that you have a working test case; then you can gradually improve that with better algorithms as you uncover the performance profile.

Jumping to "use someone else's code" introduces a dependency and a guess about average-case behavior. That is okay if we're making "Premade Hero", but it teaches nothing about algorithm design.

And w/r to your own project, there are a lot of guesses about what will be useful or helpful - the specifications boil down to "it would be fun to add more physics and scripting to Thrust" which, as a game design goal, is quite impoverished. HH also lacks for design right now, but everything in it is built on direct experience and isn't going to box in Casey later. It is motions he is going through to show to the crowd how it all works if you were going to do it yourself.

I get that... but Handmade Hero is an educational effort. It is trying to show people how to implement their own data structures. How to read the manuals for your OS and hardware and how to program that hardware.

There is no "battle-tested" single data-structure that is going to fit into every program ever written. Different data, different platform, different problem. The philosophy chosen by STL and Boost, etc, panders to the lowest-common denominator or some idealized use-case. That might be useful for certain applications but making an educated decision on whether to include it takes knowing the cost of memory access and how your cache is being utilized (or not as is often the case with STL bloat-ware). The "zero-cost abstraction" promise is a myth.

Any significant game engine or system will end up considering, carefully, it's memory allocation strategy and access patterns. You will end up writing specialized data structures for your particular data challenges to best use the hardware and operating system running your program.

The more abstractions you add the more difficult it becomes to manage the complexity in your programs and you end up writing more abstractions to solve the problems with your other abstractions. Soon your program takes tens of thousands of cycles access the data it needs in your loop and you end up cutting out all of the abstractions anyway.

And there's nothing wrong with teaching people to think this way. If we want to call ourselves engineers it's time to stop thinking that only a certain elite is allowed to write the data structures we mere mortals are blessed to use. Everything has a cost. You can't add features and incur no cost. Every instruction, memory access, page to disk -- it all takes electricity and time. We should be able to think about our systems holistically and consider each aspect of our system.

I'm not saying we should write every program from scratch every time. However we should be able to if it's required by the problem we're trying to solve. Our job is to solve data problems. We take data in and transform it to perform some task. Everything else from the bottom up introduces a cost to the system. Maybe 90% of the time you do need a garbage collector -- you've considered your access patterns and object life-times and know that the particular algorithm and its costs align with the goals of your system.