55 karma · joined February 1, 2018
Output: At 18, I had a career-defining epiphany.
I encountered a three-panel framework that fundamentally disrupted my perspective and shaped the leader I am today. It wasn't just a comic strip; it was a masterclass in clarity and human dynamics.
The "Garfield" model presents a powerful dichotomy: Jon Arbuckle (the visionary/operator) and Garfield (the disruptor). It’s a perfect metaphor for today’s global landscape—from satellite tech to grassroots politics. It’s about two stakeholders in a constant state of harmony and friction.
I’ve spent years analyzing this specific interaction. Jon is in deep-work mode, absorbing the "market data" of his newspaper. He reaches for a key resource—his pipe—only to find a gap in his supply chain.
His query, "Now where could my pipe be?" is the ultimate professional question. We are all searching for our "pipe"—that missing piece of the puzzle.
Then comes the pivot. The "aha!" moment. Divine intervention meets radical disruption: The cat is smoking the pipe.
It’s a bold take on asset misappropriation and unexpected results. When Jon shouts "Garfield!", he isn't just calling a pet; he's identifying the disruptor in his ecosystem.
Lesson learned: Always know who is holding your "pipe" in the marketplace. #Leadership #Disruption #Clarity #GrowthMindset #GarfieldStrategy
Many of those things you list really don't take too much time to do, like writing systemd units or using an ORM. But they really help when anyone needs to take a look at things in the future or someone else wants to contribute as well later on. Besides, they're easier to do when things are still fresh in the mind, and these kinds of chores rarely get done later on when a project has grown.
This being a hobby project may also be a reason why the other programmers want to do things right; they may get satisfaction and learn new things by doing it this way!
As far as LOC goes, I know well enough that it's a meaningless statistic that has very little practical use. I've written 34 lines of JavaScript that were as meaningful as 25k lines of C, but those lines of JS were obviously interpreted on an engine that's millions of LOC.
I'm not really sure what fewer dependencies you are used to other than a compiler, make, a scripting environment to orchestrate things (bash) and some (other) scripting environment to cook assets (Python3). I suppose that that last bit is something you're not used to in a more embedded world, but in the world of user-facing tools with UIs, it's really not uncommon at all to have a dependency on some font library or internationalization library so that you can generate an image or display some text. The latter of which is presumably fairly important, given that the users and hardware manufacturers that this project supports aren't based out of locations where English is the native language. I'm not sure localization can be pulled out of scope, because of that.
> > Besides, you can always treat a built Docker image as a stable toolchain archive if that's a concern; there's little reason to assume that it won't work 12 years into the future as
> I heavily disagree with this assumption and the rest of the assumptions related to the stability of the dependencies.
Docker images quite literally contain an entire (userspace) root filesystem. As long as you have an existing Linux installation on an x86 processor, a Linux kernel that didn't cause any breaking changes compared with the one that was used when the image was built, and some way of extracting a gzipped tarball, you can take the image that you previously built 12 years ago, extract its contents, and run all of the tools (gcc, Python3, make, bash) embedded within outside of Docker, without any dependency issues because all of the dependent libraries can be found within the image already (if they weren't in there, the project's CI builds would not work at all!).
You can verify this quite easily: install Docker, then run `docker pull ubuntu:latest; docker save --output test.tar.gz ubuntu:latest`.
I'll agree with you that if you are a user that stumbles upon this project 12 years from now (assuming they ceased development today) there are likely some challenges as you'll have to source the dependencies from somewhere and the repository URLs used today may no longer be available by then (most projects probably suffer from this). But if today someone builds the IronOS development image from the Dockerfile and saves it, I really don't know what'll have to happen for it to be impossible to get the compiler and other tools contained within to run on supported hardware in 12 years.
EDIT: Imagine what the project owners would have to do to do the same things they're doing now (building documentation, cooking required assets) but without relying on third party tools or programming languages other than C. They'd have to spend time writing font parsers, documentation generators, build scripting tooling, and much more! In a sibling comment you mentioned that "it seems to me that at some point this industry stopped trying to solve real issues", but I'd argue that the project pulling in the scope of building those tools to avoid dependency issues is exactly that: them solving issues that is not within their scope or merit to solve.
Besides, you can always treat a built Docker image as a stable toolchain archive if that's a concern; there's little reason to assume that it won't work 12 years into the future as - as far as I can tell - none of the software relies on it being run inside a Docker container.
[1] https://github.com/Ralim/IronOS/blob/80c4b58976268849b6d1c8d...
"Type '{ foo: number; }' is not assignable to type 'B'.
Property 'baz' is missing in type '{ foo: number; }' but required in type '{ foo: number; baz: number; }'."
I've had the compiler emit errors much like the following for way more complicated types that combined several of these kinds of structures together to form much more bespoke type checks (reproduced from memory, so I'm not 100% certain on the error or use case): const e = form.email
^
ERROR: "email" is not in '"name" | "firstname" | "lastname" | "e-mail" | "birthdate" | "password"'
The thing to note here is that it often doesn't expose the details of the implementing type and underlying (admittedly complicated) type system primitives at all to users. That said, I'll have to be honest and say that I have seen it throw much more difficult to understand nested errors referring to the underlying type implementation when I was working on the type system itself to create stricter type checks for functionality that was previously unchecked (i.e. treated as "any" by the compiler).The other thing to note is that these things are really only doing type checking. If it becomes troublesome and it does start to spit out type errors incorrectly, throw unreadable errors, or otherwise become a maintenance burden, these types are not particularly difficult to remove, and by removing them you won't break your code. Consider that to be the equivalent of removing a linting rule or no longer requesting a review from a colleague. Though it's probably a good idea to document how to remove these advanced checks for when people find them annoying when someone leaves ;)
Incorrect type checking implementation is probably the biggest problem with these things getting complex, though. If your type check is incorrectly throwing errors for implementations that don't contain any errors at all, that's going to set you back a lot!
I've used types like this in a pretty advanced TypeScript UI project consuming lots of services to enforce compile time errors. We were using generated TS clients for all of the APIs we consumed, and the compiler would automatically throw readable errors wherever we were missing form fields or types became incompatible. I committed the advanced type once, documented its usage, and I don't think anyone has had to deal with it since, whilst the types have steadily prevented errors.
And even then: it's just type definitions. If it really becomes a maintenance burden or someone has no clue what it does, you can simply replace the type with "any" or something similar and all of your problems are gone and typescript won't complain anymore (at the expense of less type error checking).
EDIT: improved wording
In practice you'd have someone that understands this set it up once, and then document its usage for others, maybe document the implementation to make it easier to modify later.
The TS compiler is surprisingly good at giving you good readable error messages as well when your code violates these advanced types; the errors tell you what you specified and what is supported, it doesn't display the low level type logic as part of the error users see. This means that there's very little need for anyone to really how these type definitions work.
EDIT: clarifications and spelling.
Besides that, the context matters here. This post is riding off of the attention that another Skyrim WTF bug got recently, which was posted on Twitter. Continuing the conversation there seems like the lowest barrier to entry to me, considering that the author already has a Twitter account and a following there, especially if you actually want to reach people that might find it interesting.
I do greatly enjoy no-buildstep projects for the same reasons as you've mentioned, but when working with others I've also seen them fail because of knowledge gaps in more junior engineers. Provisioning a server and CI/CD pipeline to build your projects is a lot easier than ensuring that everyone working on a project has all of the required knowledge to keep it nice and performant at runtime.
Looks a lot cleaner, and the .html itself is a valid diagram as the script tag that bootstraps the renderer is prefixed with a comment hash.
EDIT: I used to have this in a gist that I'd load via rawgit.com, but since that's no longer active, I figured I'd update my script and make it publicly available through unpkg :)
I don't think JavaScript was really the point of it.
(EDIT: but JavaScript having functions as a first-class citizen, and closures, makes it a very good candidate for something that leverages event loops for this kind of thing)
If anything, TypeScript sometimes feels like a nice middle-ground between C# and JavaScript (and Java?), and though it's not perfect, I do feel that it's pleasurable once you get the hang of it and the quirks of the ecosystem.
Ryan's original criticisms regarding Node were totally valid, but most of them weren't really easily addressable without significant breakage or a long migration strategy, which potentially could've caused a _lot_ of issues and unclarity for many years.
I looked through the codebase, and noticed that this uses a custom data format to persist HTTP requests and responses in local storage. I'm not sure if it's technically possible in all circumstances, but I think it might be valuable to have requests and responses be stored as HAR 1.2 [1] when possible, so that the trace can be used by other tools [2] to aid in debugging, verifying and analyzing behaviour as well as perhaps automated creation of load/performance tests.
[1] - http://www.softwareishard.com/blog/har-12-spec/
[2] - e.g. https://toolbox.googleapps.com/apps/har_analyzer/