No-one comes out of the womb caring about code quality. People learn to care about the craft precisely because internal quality -- cohesion, modularity, robustness -- leads to external quality (correctness, speed, evolvability).
People who care about code quality are not artists who want to paint on the company's dime. They are people who care about shipping a product deeply enough to make sure that doing so is a pleasant experience both for themselves and their colleagues, and also have the maturity to do a little bit more thinking today, so that next week they can make better decisions without thinking, so that they don't get called at 4 AM the night after launch for some emergency debugging of an issue that that really should have been impossible if it was properly designed.
> No one has ever made a purchasing decision based on how good your code is.
Usually they don't get to see the internals of the product, but they can make inferences based on its externals. You've heard plenty of products called a "vibe-coded piece of crap" this year, even if they're not open source.
But also, this is just not true. Code quality is a factor in lots of purchasing decisions.
When buying open source products, having your own team check out the repo is incredibly common. If there are glaring signs in the first 5 minutes that it was hacked together, your chances of getting the sale have gone way down. In the largest deals, inspecting the source code
It was for an investment decision rather than for a purchase, but I've been personally hired to do some "emergency API design" so a company can show that it both has the thing being designed, and that their design is good.
> People who care about code quality are not artists who want to paint on the company's dime. They are people who care about shipping a product deeply enough to make sure that doing so is a pleasant experience both for themselves and their colleagues, and also have the maturity to do a little bit more thinking today, so that next week they can make better decisions without thinking, so that they don't get called at 4 AM the night after launch for some emergency debugging of an issue that that really should have been impossible if it was properly designed.
Speak for yourself. This is exactly the GPs point. Some people care more about the craft of code than the output. I personally find writing good code to be what motivates me. Obviously its a spectrum; shipping is good too. But it's not why I get up in the morning.
Okay, I admit I went too hard on that one to fight against the OP. I too get extreme pleasure from condensing a 300-line function into 30 lines of simplicity, even when practical considerations (it has a clean interface and no-one's even needed to open this file in 2 years) would dictate elegance there is not helpful.
Code quality is a side-effect of caring. The most important part of product design is caring at all levels. However it's caring about the external details that is the most important. Coding language is largely a function of the population of good coders in your areas. Code evolvability is almost entirely subjective.
Let's take two code bases. A 40 year old legacy Cobol monstrosity being maintained by a staff of well trained engineers that are engaged. The second an idiomatic Haskell application written simply and to the highest standards, but with a staff of junior engineers that specialize in imperative programming. The Cobol code base is much more evolvable. The staff can effectively make changes because they deeply know the product.
Evolvability is not an intrinsic feature of the software. It is a synthesis of culture, talent, passion, and code style.
Timely! I spent a good chunk of yesterday investigating Bombadil. I'm a huge fan of PBT and a huge fan of temporal logic (though not linear temporal logic) and we're currently trying to level up our QA, so it seemed like a good match.
Unfortunately, I concluded that Bombadil is a toy. Not as in "Does some very nice things, but missing the features for enterprise adoption." I mean that in a very strong sense, as in: I could not figure out how to do anything real with it.
The place where this is most obvious is in its action generator type. You give it a function that generates actions, where each action is drawn from a small menu of choices like "scroll up this many pixel" or "click on this pixel." You cannot add new types of actions. If you want to click on a button, you need it to generate a sequence of actions to first scroll down enough, and then look up a pixel that's on that button.
Except that it selects actions randomly from your list, so you somehow need the action generator, when run the first time, to generate only the scroll action, and then have it, when run the second time, generate only the click action. If you are silly enough as to have an action generator that, you know, actually gives a list of reasonable actions, you'll get a tester that spends all its time going in circles clicking on the nav bar.
(Something in the docs claimed that actions are weighted, but I found nothing about an actual affordance for doing that. Having weights would make this go from basically impossible to somewhat impossible.)
(Edit: Found the weighted thing.)
I am terrified to imagine how to get Bombadil to fill out a form. At least that seems possible -- you can inspect the state of the web page to figure out what's already been filled out. But if you want the state to be based on anything not on the current page, like the action that you took on the previous page, or gasp the state on disk (as for an Electron app), that seems completely impossible. Action generators are based on the current state, and the state must be a pure function of the web page.
Its temporal logic has a cool time-bounded construct, but it's missing the U (until) operator. One of their few examples is "If you show the user a notification, it disappears within 5 seconds." But I want to say "When you click the Generate button, it says 'Generating...' up until it's finished generating." And I can't.
(Note: everything above is according to the docs. Hopefully everything I said is a limitation of the docs, not an actual limitation of the framework.)
I shared my comments with the author yesterday on LinkedIn, but he hasn't responded yet. Maybe I'll hear from him here.
I have a pretty positive opinion of Antithesis as a company and they seem to be investing seriously in it, and generally see it as a strong positive sign when someone knows what temporal logic is, so I have hopes for this framework. I am nonetheless disappointed that I can't use it now, especially because I was supposed to finish an internal GUI testing tool this week and my god I'm behind.
Hey, yeah, so actions are indeed independent and you can't express fixed sequences of them (e.g. fill out thus form by doing X, then Y, then Z). If you want to enforce certain sequentiality you'd need to precondition your generators. This is admittedly limited right now. I do want to add QoL things like `filter` on the generators to make that more ergonomic.
Also, as you note, you can't implement custom actions. And that's just something that I haven't gotten to yet. It'd be quite straightforward to add a plain function (toStringed) as one of the variants of the Action type and send that to the browser for eval. (Btw, we're taking contributions!)
Weighting is also important right now. There's no smart exploration in Bombadil yet, only blind random, so manual weighting becomes pretty crucial to have more effective tests (i.e. unlikely to run in circles). I'd like to both make the Bombadil "fuzzer" better at this, but eventually you might want to run Bombadil inside Antithesis instead to get a much better exploration, even in a single campaign.
The Until operator is also one of those things that I haven't gotten to yet. I actually didn't expect someone to hit this as a major limitation of the tool so quickly, which is why I've focused on other things. Surprising!
To add some more context, Bombadil is an OSS project with one developer (but we're hiring!) and it's 4 months old and marked experimental. I'm sorry you were disappointed by its current state, but it's very early days, so expect a lot of these things to improve. And your feedback will be taken into account. Thanks!
While the title sounds intriguing, I'd really like examples to explain what this is good for. The Github page has more information, but it's not helpful. "XML instead of JSON" -- okay, why? I thought the consensus was generally that JSON is a better data format than XML thanks to its compactness and simplicity.
Reading the page, I'm left very confused what this is. Is it a new query language, or a new data format, or both? I think it's both. Am I expected to redo everything in this format? Like, get both my freeform planning notes about what to build and also my production Postgres DB in the same file? I don't even know how to begin doing that.
It's not in these notes, but you can do some super cool stuff with the linear algebra of polynomials. Using inner products, you can not only rederive linear regression, but also its polynomial generalizations, and even zany things like finding the best fit of the form ax^3+cx (missing x^2 and constant terms).
I think this could work well as a blog post. If you're not willing to read the code yourself, maybe you could at least go through the report yourself and point out issues it highlights, show the relevant code, and explain why that's actually bad.
But I only set out to get the overall vibe of what Yegge is doing. The static analysis [1] and the automaton's take [2] were plenty for doing that.
> …maybe you could at least
> go through the report yourself
> and point out issues it highlights
I suppose. But to be frank, I'm not that interested in the project to do a super deep dive.
It was all I could do to muster up the will to even do as much as I did eventually force myself to do.
I'm not the faniest fan boy of AI-assisted coding. But I appreciate them for what they're good at. To me, it delivered a stellar code review here.
> …show the relevant code,
> and explain why that's
> actually bad
I humbly don't think I could add anything that the LLM and static analysis haven't brilliantly illuminated already.
The Sonar Cloud analysis is super detailed. And the automaton's code review is on the money. Digging into their respective nitty gritty is left as an exercise for the reader.
People tend to read articles because the author is able to share insights that would be much harder -- whether in skill, time, or energy -- to come up with themselves.
But here you're asking to put the reader to put in more work than you did, to find an insight that may or may not be there.
What is your picture of the moment-by-moment thoughts of someone who would click this and upvote?
I can write a similar article that: most people problems are technical problems.
This article hits on a pet peeve of mine.
Many companies and individuals can benefit from better processes, communication skills, and training.
And also people who proclaim "Most technical problems are people problems" and "It's not what you know, it's who you know" are disproportionately those who are attempting to influence others that "My skillset is more valuable than your skillset." The people who believe the opposite are heads-down building.
The truth is that nearly all problems are multifactorial and involve long chains of causality. They can be patched at multiple points.
And so while there are standard stories about "If you do the 5 Why's and trace back causality, the issue becomes a deeper human problem," you can nearly always do something else and find an alternative technical solution.
The standard story goes: "This thing failed because this this other thing crashed, because this thing was misconfigured, because the deployment script was run incorrectly, because no-one trained Bob how to use it." See, the human problem is the deepest one, right?
But you can find an alternate technical fix: why was it possible to run the deployment script incorrectly?
Or you can ping-pong it back into a technical problem: he wasn't trained because everyone is stressed with no time because things keep breaking because of bad architecture and no CI. So actually the technical problem is deepest.
But no, because that only happened because the CEO hired the wrong CTO because he didn't know anyone who could evaluate it properly....
...which only happened because they didn't use <startup that helps you evaluate engineers> (technical problem)
...which only happened because said startup didn't have good enough marketing (human problem)
...which only happened because they were too slow to build from their own tech debt and didn't have the money (technical problem...)
And so on. Ping, pong.
The article says: we had too much tech debt because humans weren't trained enough.
One can also say: we had too much tech debt because we didn't have good enough linters and clone detectors to keep out the common problems, and also we had made some poor technical choices that required hiring a much larger team to begin with.
If you have a pet problem, you can always convince yourself that it's responsible for all woes. That just keeps you from seeing the holistic view and finding the best solution.
reply