![]() |
|
![]() |
| But comments go out of date, and the compiler doesn’t check them against the implementation. To document + enforce the intended functionality, use tests. |
![]() |
| Sure, people find different things complex.
For example, I can't make heads or tails of rxjs, and honestly have zero motivation to do so. Other people see it and find it intuitive. Shrug. |
![]() |
| Japans cultivate this through their entire culture - starting from young children. We, the Westerns, are already at least 2 decades behind, sometimes even 4-5 decades ... |
![]() |
| That is wrong in general. With enough tests you absolutely can show the absence of bugs for certain programs. It is for example easy to test „hello world“ exhaustively. |
![]() |
| The system it runs on is part of the specification. A program is correct if fulfills all specified requirements. You're saying a car is defective because it breaks when you put sugar in the tank. |
![]() |
| And then we find a new category of bug, consider how we ran millions of different programs for many billions of CPU hours on all of our x86 CPUs before we learned about Spectre and meltdown. |
![]() |
| It would be interesting to see the NASA approach compared to how SpaceX does things. Considering that they have done manned missions they seem to have very similar requirements. |
![]() |
| What so bad about old technology? Siemens is still selling point mechanisms based on designs that are almost as old as electric motors themselves. They work just fine. |
![]() |
| But in neither case was it due to a code failure that put the shuttle into an unrecoverable state, but rather one the falls into materials and/or mechanical engineering. |
![]() |
| Space Shuttle was part of "Star Wars" project to bring down the Soviet Union. It met its goals by being super expensive.
Space flights were just side project... |
![]() |
| There's quite an interesting discussion from Richard Hipp on converting sqlite code to aviation standards https://corecursive.com/066-sqlite-with-richard-hipp/#testin...
>DO-178B. It’s a quality standard for safety-critical aviation products... Your tests have to cause each branch operation in the resulting binary code to be taken and to fall through at least once... took a year of 60 hour weeks... It made a huge, huge difference. We just didn’t really have any bugs for the next eight or nine years. |
![]() |
| Beautiful.
---------------------------- This controller is intentionally written in a very verbose style. You will notice: 1. Every 'if' statement has a matching 'else' (exception: simple error checks for a client API call) 2. Things that may seem obvious are commented explicitly We call this style 'space shuttle style'. Space shuttle style is meant to ensure that every branch and condition is considered and accounted for - the same way code is written at NASA for applications like the space shuttle. ---------------------------- ^^^^ This bit reminds me of exhaustive checks in typescript code. I try to use them all the time. https://www.typescriptlang.org/docs/handbook/2/narrowing.htm... |
![]() |
| If you think these things are considered harmful, I'd encourage you to read "John Carmack on Inlined Code"
http://number-none.com/blow/john_carmack_on_inlined_code.htm...
"The flight control code for the Armadillo rockets is only a few thousand lines of code, so I took the main tic function and started inlining all the subroutines. While I can't say that I found a hidden bug that could have caused a crash (literally...), I did find several variables that were set multiple times, a couple control flow things that looked a bit dodgy, and the final code got smaller and cleaner." If Carmack finds value in the approach, perhaps we shouldn't dismiss it out of hand. Also worth noting his follow-up comment: "In the years since I wrote this, I have gotten much more bullish about pure functional programming, even in C/C++ where reasonable... When it gets to be too much to take, figure out how to factor blocks out into pure functions" |
![]() |
| Thanks. This is the first instance of a respected software engineer arguing in favor of this style that I have read (contrast with Dave Thomas, Kent Beck, Bob Martin, etc.)! |
![]() |
| > Are these loops in Kubernetes so hot that extra microseconds for some program stack manipulation will affect performance?
Actually, looking at the code itself, pv_controller doesn't look overly hot, but extremely high value. In this case the long methods are intended to keep the logic confined, so one can read end to end and understand what is going on. The code even doesn't use automatic type inference in Go (the := syntax), in some cases to make code more readable. From what I understand, this code needs to be "kernel level robust", so they kept the overly verbose formatting and collected all three files to a single, overly verbose file. I don't think this is a bad thing. This is an important piece of a scale-out system which needs to work without fault (debate of this is another comment's subject), and more importantly it's developed by a horde of people. So this style makes sense to put every person touching the code on the same page quick. > I feel Space shuttle programming's job in many ways is in fact to try and remove ambiguity from code. But not by explaining the language, but the variables and their units. I sure wouldn't mind spamming "units in cm" everywhere or explaining every branch logic if it's mission critical. A code comment needs to explain both the logic, and how the programming language implement this logic the best way possible. In some cases, an optimized statement doesn't look like what it's doing in the comment above it (e.g. the infamous WTF? comment from id Games which does fast_sqrt with a magic number). In these cases I open a "Magic Alert" comment block to explain what I'm doing and how it translates to the code. This becomes more evident in hardware programming and while working around quirks of the hardware you interface with ("why this weird wait?", or "why are you pushing these bytes which has no meaning?"), but it also happens with scientific software which you do some calculation which looks like something else (e.g.: Numerical integration, esp. in near-singular cases). > Not so much this inconsistent doxygen/javadoc style documentation on every variable/class. If you're going to go full entrprise programming, commit to it. This is not inconsistent. It's just stream-of-consciousness commenting. If you read the code from top to bottom, you can say that "aha, they thought this first, then remembered that they have to check this too, etc." which is also I do on my codebases [0]. Plus inline comments are shown as help blobs by gopls, so it's a win-win. I personally prefer to do "full on compileable documentation" on bigger codebases because the entry point is not so visible in these. > "a proper linter configuraion would have really helped enforce these rules". gopls and gofmt do great job of formatting the codebase and enforcing good practices, but they don't touch documentation unfortunately. [0]: https://git.sr.ht/~bayindirh/nudge/tree/master/item/nudge.go |
![]() |
| Yes, if it's your first day on the job and you don't know that CSI is a driver. Yes, if GetCSINameFromInTreeName ever gets renamed to something less obvious. |
![]() |
| It's a lot easier to glance through a single 2k line file than it would be to go through 200 separate 100 line files (+ extra overhead for imports in each file) |
![]() |
| I would consider this a code smell:
And I overall dislike the level of nesting in some of these functions but that might just be the nature of Go code. |
![]() |
| The Go ideology is basically to just write down all the code, in a more or less straightforward translation of what you would have written in C, and not to try to abstract anything. |
![]() |
| This kind of thing should be enforced with linting rules and an automated action that rejects any pull request which violates the rules, not with a comment. |
![]() |
| Is this code unit tested? If it's so critical that every branch has to be accounted for, I would assume that time would be well-spent combinatorically testing its inputs, right? |
![]() |
| Some of this looks real bad though, like `if !found … else …`. Why the double negative, when you're going to have both branches anyway? |
![]() |
| But do they have tests that achieve 100% condition/decision branch coverage?
If they do, changes that disrupt handling some cases ought to be detected by the tests. |
![]() |
| Yes, I agree though the issue there is that changes which aren't believed to change the behavior might, as there isn't a way to tell except by being a very careful programmer and reviewer. |
![]() |
| More to the point, the comment in the code mentions the “combinatorial” explosion of conditions that have to be carefully maintained by fallible meat brains.
In most modern languages something like this could be implemented using composition with interfaces or traits. Especially in Rust it’s possible to write very robust code that has identical performance to the if-else spaghetti, but is proven correct by the compiler. I’m on mobile, so it’s hard to read through the code, but I noticed one section that tries to find an existing volume to use, and if it can’t, then it will provision one instead. This could be three classes that implement the same interface:
The last class takes a list of IVolumeAllocator abstract types as its input during construction and will try them in sequence. It could find and then allocate, or find in many different places before giving up and allocating, or allocating from different pools trying them in order.Far more flexible and robust than carefully commented if-else statements! Similarly, there's a number of "feature gate" if-else statements adding to the complexity. Let's say the CreateVolume class has two variants, the original 'v1' and an experimental 'v2' version. Then you could construct a SeqVolumeAllocator thus:
And then you never have to worry about the feature flag breaking control flow or error handling somewhere in a bizarre way.See the legendary Andrei Alexandrescu demonstrating about a similar design in his CppCon talk “std::allocator is to allocation what std::vector is to vexation”: https://youtu.be/LIb3L4vKZ7U |
![]() |
| You appear to have misread "expression" as "exception"; this is completely unrelated. An expression-based language is one that lets you do `let blah = if foo then bar else baz`, for example. |
![]() |
| "Else" is for when the if condition is false.
A resumable exception initiated in the "then" part of an if will not go to "else" when control resumes; it will go to the next statement after the if. |
![]() |
| I've been experimenting with k8s and/or running it on prod basically since the initial release, and I've so far only had one workload-affecting bug.
The bug caused the scheduler to get stuck meaning pods assigned to nodes kept running, but no new pods would be scheduled. https://github.com/kubernetes/kubernetes/issues/124930 That's a pretty good track record, and indicates a level of fail-safe design (everything continued working, even though a critical components kept crashinglooping). |
Maybe the disconnect here is that most of my experience is in enterprise software rather than systems software. Perhaps many of the comments in this file seem unnecessary to regular contributors within the k8s project? Whereas if I were writing this same code in an enterprise (and thus expect it to be read by people far in the future lacking context on all the technical details) I would have put -more- comments in this file, given the sheer complexity of all it's doing.