The clean code people are losing their collective minds reading that. lol
Why's that? Uncle Bob seems pretty clear that most of your code should be free of side effects, and that necessary state mutation should be isolated to one place. Carmack is saying the same thing.
John Carmack on inlined code (2014)
361–370 of 402 posts
Re: John Carmack on inlined code (2014)
#362Earlier quoted context omitted.
The important bit is figuring out if those times where "the right way" would have helped outweigh the time saved by defaulting to "good enough". There are always exceptions, but there's typically order of magnitude differences between globally doing "the right thing" vs "good enough" and going back to fix the few cases where "good enough" wasn't actually good enough.
Only long experience can help you figure this out. All projects should have at least 20% of the developers who have been there for more than 10 years so they have background context to figure out what you will really need. You then need at least 30% of your developers to be intended to be long term employees but they have less than 10 years. In turn that means never more than 50% of your project should be short term…
It’s very difficult to get opportunities for growth. Most of the challenging work is given to the seniors, because it needs to be done as fast as possible, and it’s faster in the short term for them to do it than it would be for you to do with with their help.
It’s very difficult for anyone else to build credibility with stakeholders. The stakeholders always want a second opinion from the veterans, and don’t trust you to have already sought that opinion before proceeding, if you thought it was necessary to do so (no matter how many times you demonstrate that you do this). Even if the senior agrees with you, the stakeholder’s perception isn’t that you are competent, it’s that you were able to come to the right conclusion only because the senior has helped you.
Re: John Carmack on inlined code (2014)
#363It's clear that Carmack's article is addressing a particular sort of C++ codebase that might be familiar to game developers, but isn't familiar to a lot of us here who work on web applications and backend distributed systems. His "functions" aren't really what we think of as functions: they're clearly mutating huge amounts of global state. They sound more like highly undisciplined methods on large namespaces. You can see that from the following quotes:
> There might be a FullUpdate() function that calls PartialUpdateA(), and PartialUpdateB(), but in some particular case you may realize (or think) that you only need to do PartialUpdateB(), and you are being efficient by avoiding the other work. Lots and lots of bugs stem from this. Most bugs are a result of the execution state not being exactly what you think it is.
> if a function only references a piece or two of global state, it is probably wise to consider passing it in as a variable.
In the world of many people here, i.e. away from Carmack's C++ game dev codebases of the 2000s with huge amounts of global mutable state, the standard common sense still applies: we invented structured programming with functions for profoundly important reasons: modularity and abstraction. Those reasons haven't gone away; use functions.
- In a large codebase you do not need or want to read the full tree of implementation in one go. Use functions: they have return types; you know what they do. A substantial piece of implementation should be written as a sequence of calls to subfunctions with very carefully chosen names that serve as documentation in themselves.
- Make your functions as pure as possible subject to performance considerations etc.
- This brings a huge advantage to helper functions over inlining: it is now easy to see which variables in the top-level function are being mutated.
- The implementation is much harder to understand in a single function with 10 mutable variables, than in two functions with 5 mutable variables. I think ultimately that's just a fact of combinatorics; not something we can hold opinions about.
- But sure, if the 10 mutable variables cannot be decomposed into two independent modules then don't create spurious functions.
- A separate function is testable; a block inside a function is not. It wasn't really clear that the sort of test suites that many of us here work with were part of Carmack's codebases at all!
- It is absolutely fine to use a function if it improves modularity / readability even if it only called once.
Re: John Carmack on inlined code (2014)
#364Earlier quoted context omitted.
The mistake with focusing on reaction time is that humans can anticipate actions and can perform complex sequences of actions pretty quickly (we have two hands and 10 fingers). So someone playing one of those "test your reaction time" games might only score like 30ms. But someone playing a musical instrument can still play a 64th note at 120BPM. Imagine playing a drum that took between 0 and 5 extra frames at 60FPS b…
Another example is music (and relatedly, rythm games). With memorized music you have maximal anticipation of actions. The regular rithm only amplifies that anticipation. Musicians can be very consistent at timing (especially rithm section), and very little latency or jitter can throw that off.
So for the second problem, you just ignore input and play "open loop". For the first problem, you may have to play notes on the slow rank slightly early, although this is only practical if you separate them off on a different keyboard. Otherwise, you can only use that rank for slow music, and make use of the note increasing in volume and changing in tone as that rank comes in.
Re: John Carmack on inlined code (2014)
#365Earlier quoted context omitted.
> maxim suggests that no matter what your moral framework looks like, you should accept that under some circumstances it's OK to have child marriages You seem to have either misread the maxim, or misunderstood it. The maxim is not that an intelligent person -must- hold two contradictory thoughts in their head at once - rather, that they should be able to. Being "able to" do something, does not mean one does it in all…
In this context, it doesn't matter if they "must" or "should be able to". No, I didn't misunderstand the maxim. No, I didn't mean that it has to happen in all cases. You are reading something into what I wrote that I didn't. The maxim is not used by religious people to its intended effect. Please read again, if you didn't see it the first time. The maxim is used as a challenge that can be rephrased as: "if you are as…
Your comment literally says "the maxim suggests".
If that wasn't what you were saying, then your comment is misphrased.
If that -was- what you were saying, then I reiterate that, no, the maxim does not suggest that. You (or whatever hypothetical person you're referring to) are the one suggesting it, not the maxim.
It doesn't matter how you rephrase it - "should be able to" is not the same as "must". "Able-bodied people should be able to jump off the top of a building." That's a perfectly valid and true statement - jumping off of things is within the physical capabilities of the able-bodied. But that statement, however true, does not suggest that one must jump off the top of a building to prove that one is able-bodied.
> No, I didn't mean that it has to happen in all cases.
If it doesn't have to happen in all cases, then an intelligent person can simply say "no, even though I am -able to- accept contradictory ideas, in this case I still reject child marriage in all contexts". Clearly you would agree that this is perfectly compatible with the maxim. So, in what way is the maxim being harmful here?
In reality, your comment has almost nothing to do with the maxim itself, and is mostly just about people using religion and rhetoric to manipulate others. Such people would use whatever tool they have available - with or without the existence of the maxim.
Re: John Carmack on inlined code (2014)
#366Earlier quoted context omitted.
There are multiple reasons that contributing to various projects may be difficult. But, I was replying to a specific comment about writing code in a way that is easy to understand, and the comment author's acknowledgement that this idea/practice is hard to scale to a large number of developers (presumably because everyone's skills are different and because we each have different ideas about what is "clear", etc). So,…
> Yet, even a very competent C++ dev is going to have a ton of trouble figuring out the Chromium code base. I don't think this is true, or at least it wasn't circa 2018 when I was writing C++ professionally and semi-competently. I sometimes had to read, understand and change parts of the Chromium code base since I was working on a component which integrated CEF. Over time I began to think of Chromium as a good refere…
Re: John Carmack on inlined code (2014)
#367Earlier quoted context omitted.
For-loops do exist, they just need to not have side effects, which in practice means the likes of map/filter/reduce (ideally promoted to a first class language feature like sequence comprehensions). You could argue that those are still desugared to recursion, but I think at that point it's kinda moot - the construct is still readily recognizable as a loop, and it's most likely also implemented under the hood as an im…
>For-loops do exist, they just need to not have side effects, No they don't. For loops and loops in general are procedural actions. You are jumping from directive to directive, command to command. Loops are NOT functional at all. loops are an artifact of the computational machine, jumping to different instructions. Functional programs like functions in mathematics DO not contain for loops. > which in practice means t…
def range_mul(n, mul):
for i in range(n):
yield i*mul
x = list(range_mul(10, 20))
range_mul is a pure function, yet it is implemented with a for loop. Once you have first class continuations or the equivalent, the differences between imperative and pure blur (cf. Haskell do-notation, is it imperative?).In any case I think you are missing int_19h point, the it doesn't matter if a function is implemented using imperative constructs, if you can't tell from the outside it is still pure. And an FP compiler will convert pure code to imperative anyway.
Re: John Carmack on inlined code (2014)
#368I thought that at least his crash was a result of bad constants in flight software: https://www.youtube.com/watch?v=SWZLmVqNaQc
The first comment appears to agree with me.
Re: John Carmack on inlined code (2014)
#369Earlier quoted context omitted.
There are multiple reasons that contributing to various projects may be difficult. But, I was replying to a specific comment about writing code in a way that is easy to understand, and the comment author's acknowledgement that this idea/practice is hard to scale to a large number of developers (presumably because everyone's skills are different and because we each have different ideas about what is "clear", etc). So,…
I guess I just don't really get your point then, it's not like the Linux Kernel or Chromium or Firefox are giant buggy messes that don't work at all. They certainly have bugs but by-and-large they work very well with minimal issues for most people. I also think their codebases are pretty approachable, IMO A competent C or C++ developer can definitely read the code from either one with a little effort - It's not the e…
That's kind of my point, though. I'm trying to zoom out and "think outside the box" for a minute. It's hard to compose smaller pieces into larger systems if the smaller pieces have behavior that's not very well defined. And our programming languages and tools don't always make it easy for the author of a piece of code to always understand that they introduced some unintended behavior.
To your first point: I'm not shitting on Chromium or Firefox or any other software projects, but they're honestly ALL "buggy messes" in a sense. I'm a middling software dev and the software I write for my day job is definitely more buggy, overall, than these projects. So, I'm not saying that other developers are stupid (quite the opposite!). But, the fact that there are plenty of bugs at any given point in any of these projects is saying something important, IMO. If I use our current programming tools to write a Base64 encode/decode library, I can do a pretty good job and there's a good chance that it'll have zero bugs in a fairly short amount of time. But, using the same tools, there's absolutely no hope that I (we, you, whoever) could write a web browser that doesn't have any bugs. That's actually a problem! We've come to accept it because that's all we've got today, but my point is that this isn't actually an ideal place to settle.
I don't know what the answer is, but I think a lot of people don't even seem to realize there's a problem. My claim is that there is a problem and that our current paradigms and tools simply don't scale well. I'm not creative enough to be the one who has the eureka moment that will bring us to the next stage of our evolution, but I suspect that it's what we'll need to actually be able to achieve complex software that actually works as we intend it to.
Re: John Carmack on inlined code (2014)
#370Clean architecture can be summarized thusly:
1. Bubble up mutation and I/O code.
2. Push business logic down.
This is how it's stated in [1]:
> The concentric circles represent different areas of software. In general, the further in you go, the higher level the software becomes. The outer circles are mechanisms. The inner circles are policies.
Inlining as a practice is in service of #1, while factoring logic into pure functions addresses #2, noted in the foreword:
> The real enemy addressed by inlining is unexpected dependency and mutation of state, which functional programming solves more directly and completely. However, if you are going to make a lot of state changes, having them all happen inline does have advantages; you should be made constantly aware of the full horror of what you are doing. When it gets to be too much to take, figure out how to factor blocks out into pure functions (and don.t let them slide back into impurity!).
1: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-a...