High Level Language use for "Handmade" projects

Hello everyone,

As a follower of the Handmade philosophy for a long time, pretty much since I learned about Handmade Hero when it came out, I've been building projects (whether commercial or personal) using this philosophy in mind.

Most of my programming expertise is self-taught, but also some is inspired by people like Casey and Jon Blow, and adapting what I've learned into high level languages like C# and Haxe.

Of course, both these languages are OOP languages and would inherently be, in theory, adversaries of the Handmade philosophy.

To give a better perspective on what feedback/opinions I'm looking for, my choice of tools include:

  • C#/WinForms - I use WinForms effectively as my go-to for fast application development, purely on the basis that it was the toolset I first learned and continue to use for personal use. This probably doesn't fall under the category of "Handmade" as I'm using a large framework with many third-party libraries written by other people.
  • Haxe/Kha - A little more "Handmade" friendly than the point above, but of course means a lot more work is required to build something that is reminiscent of a piece of software that people can use, without needing to resort extensively to using third-party libraries.

My question is this: At what point would a piece of software, even if this "Handmade" philosophy is followed as closely as possible in terms of programming quality and effort optimising the code in the language and toolset you are using, not in fact be "Handmade" because the language and toolset you are using is mostly not you and instead a trunk full of third-party libraries mashed together to create a result?

"Handmade" is more about how you approach things that the tools you use. If you're using a library that seems "too big", you would search for an alternative, or create one, which might take times (during which you can continue to use the big one). Depending on what you goal is you can do different choice: not worry about performance/reliability/quality for one time things because the tradeoff between time investment and improvement is good. It's also useful to start with a know tool/lib to get usage code informing design decision when you want to upgrade.

Languages doesn't matter. You can write in a handmade style in C#, it's just that you won't have control over some things, but the language also might provide advantages in other area over other languages.

From the Handmade Manifesto:

Some of us aren't satisfied with the current state of software. We think that wheels need to be reinvented. We like looking under the hood, understanding what others take for granted. We remember how software used to be, and know how much potential there is to make it better. We fight against the status quo, because we know how things could be.

This is what Handmade means. It's not a technique or a language or a management strategy. It's not a library or a framework or a paradigm. It's an idea. The idea that we can build software that works with the computer, not against it. The idea that the user matters more than the programmer. The idea that sometimes a small group can do more than an army of software engineers, and do it better.

You don't need a degree, a dissertation, or a decade of experience. You don't need an expensive computer or a certificate. All you need is an open mind and a sense of curiosity. We'll help you with the rest.

At what point would a piece of software ... not in fact be "Handmade" because the language and toolset you are using is mostly not you and instead a trunk full of third-party libraries mashed together to create a result?

I think you pretty much identified it :)

The sections mrmixer picked from the manifesto are indeed a good guide. It's not so much about the specific tech you use as the blind, lazy, self-serving application of it. Do you have reasons for the tech you're using? Are those reasons well-founded, or just "somebody on Medium told me to"? How do those choices affect your users?

OOP in particular is a frequent subject of discussion here and on the Discord, for obvious reasons. But it's a term that means something different to everyone, which makes discussion difficult. There are many negative aspects of popular "object-oriented design", which are different from the aesthetic quirks of "object-oriented languages", which are different from concepts like modularity, which are different from plain old spaghetti. We're actually planning to have one of our Fishbowl discussions on this topic quite soon, within the next couple weeks - you can join the Discord to catch the announcement, and help us plan the discussion here: https://github.com/HandmadeNetwork/hmn_fishbowl/discussions/37

As long as you understand the libraries you are using on a mathematical level regarding what is promised in post-conditions and side-effects, so that any behavior of the program can be modified the way you want, it doesn't matter which library and language you use, because it might already be identical to how you would build the compiler and library yourself. Some libraries and languages however, make it a lot harder to follow quality principles for programming.

Web languages that transpile to JavaScript and only run on the latest browsers, have a lot higher threshold for what one needs to understand to be used safely with determinism. If it's done using whack-a-mole trial and error on each new browser version, then it's not handmade, for how can you claim to have made something from scratch if you don't even understand why it crashes.

If using a game-maker where the source code is closed and documentation is vague, it can't be handmade, because it can't be understood mathematically unless you reverse engineer the binary, in which case you should really question the use of a game-maker to begin with. If you cannot add or remove a feature, it's not handmade. There are open-source game-makers with good documentation, in which you can write source code instead of using the pre-made features, but then you might as well use a full programming language to allow changing libraries.

In C/C++, one just have to keep the style simple enough to really understand what is going on and then build upon it as a stable foundation. When considering the total size and maintenance cost of a program, one must include the complexity of any library who's undefined behavior may affect how the program works, for that is code that must also be debugged when things crash. Writing more code on your own and including minimal libraries (without overlapping functionality) can reduce the total amount of code one depends on from a billion lines breaking down to only a few thousand lines that just work every time.

Web languages that transpile to JavaScript and only run on the latest browsers, have a lot higher threshold for what one needs to understand to be used safely with determinism. If it's done using whack-a-mole trial and error on each new browser version, then it's not handmade, for how can you claim to have made something from scratch if you don't even understand why it crashes.

It's ironic you mention that. I've been spending the last few weeks working on my own sort of, "library", if you will, called Twinspire, in Haxe which transpiles to JavaScript.

Despite the work I've put in and having made the decision to use this OOP language in a procedural way and writing multiline multi-formatted text rendering completely myself (which I would consider handmade), it would be interesting to see it's performance when generated in C/C++.

However, I could instead use ODIN, but perhaps I don't want to go too low level.

One of the reasons I don't particularly like C/C++ is its order dependency and forward-declaration requirements. But most importantly, I have to go to great lengths to find third-party libraries like "dear imgui" or "better string library" because the standard C/C++ library lacks in almost every department. While I like the idea of pointers and managing my own memory, I have still yet to use a language which offers that while also offering high level APIs which perform equally as fast as their low level counterparts.

However, my goals do not require the use of low level languages.

For me, I'm looking for a way to build websites that doesn't require me to use HTML5/CSS3/JavaScript etc., hence using a transpiler like Haxe, and building some "handmade" library that just makes programming on the Web actually fun, is something I strongly strive for.

Forgive my language, but I despise current Web technology. One of the reasons I wanted to ask about "handmade", as someone previously emphasised, how is something "handmade" if most of the tools you use is already done for you (like the Web)? That's not really handmade in the grand scheme of things, because the Web does a pretty poor job of telling you why your elements aren't positioned correctly, or why your transforms are clunky.

In the past, I've always used just HTML5/CSS3, no JavaScript libraries whatsoever (apart from maybe jQuery). Everything else I do myself. But Web programming to me is a very lengthy process, and every library that offers solutions to "make web programming better" or "faster" is mostly false. Don't even get me started on templates.

With my solution, it's all about writing a library that fits exactly everything that I need to build a website without needing to touch HTML5/CSS3/JavaScript or even server side languages directly, since Haxe also transpiles to PHP.

There are still roughly 3 abstraction layers (not including actual Web-based abstractions), but it's still better than working with HTML5/CSS3 by a long shot.


Replying to Dawoodoz (#26341)

If using lots of third party libraries as a dependency for a standard library, you will have a lot of problems when those libraries change how they work. You will also bleed through all bugs and pitfalls from the other standard library's string type, which will be exposed in your language when having to use the same text encoding in algorithms. If you plan to make it interoperable with existing libraries, then just make a thin code generator following the same principles and producing human readable code. If you plan to make it stand on its own, make your own standard library so big that you don't need to include anything else.

A standard library is 90% of what defines a language, so begin by making your own C library with hardware abstraction. Then implement any garbage collection in the code generation and let the higher standard library be implemented in your new language, so that developers can copy and paste the code to make their own libraries. Maybe String should be an alias for a List of Character using a template system (can create custom collections) or intrinsic collection type (can use core language syntax and specific compiler optimizations) in your language. Then you just let the standard string implement an interface for converting streams to and from different encodings for accessing operating systems in low level wrappers.


Replying to tienery (#26409)