HN user

dkarl

19,618 karma
Posts2
Comments3,965
View on HN

But web applications are not just pipelines of isolated tools. They are full of shared assumptions: request shapes, validation boundaries, session handling, rendering, routing, serialization, deployment targets.

Some of those things are specific to web applications. Others are not. It's fine for web-specific logic to be tied to all of the shared assumptions of a web framework, but application logic should not be. As the architecture evolves, the application logic may need to be run in other architectural contexts: as a message consumer, inside an orchestration framework, etc.

That's one of the most painful things about PHP. Entire businesses get built around business logic in PHP backends, and then when you need to execute that logic in a different architectural context, every line of it has to be rewritten, because it's too much work to extricate it from the context of serving web requests.

If you are designing your framework to contain application logic, then it should look ahead to the possibility of that logic being used in a different architectural context. It should facilitate and encourage writing application logic that is agnostic of the web context. Otherwise you're encouraging people to repeat the mistake of PHP all over again.

The "When touching it is the right call" is the tricky part, because it contains this very subjective exception: "Every new feature costs three times what it should because of the design, and you can show the trend."

I've been in situations where I was sure this was true. I've also been in situations where the person claiming it simply refused to become competent in the language, framework, or persistence technology that the system was built on.

Also subjective: "The business needs a capability the current code was never shaped to grow into." Most of the times I've heard this brought up, it's not that you need a re-write, but you need a re-architecture. Often the existing system can continue to do its job as it always has, but in a new architectural context. Or 90% of the code can stay the same, while the application it runs in is changed, for example from a web service to a Kakfa consumer. (This is why it's so important to avoid languages and frameworks that are tightly bound to an architectural choice.)

I find this far too black and white. There's a lot to gain from conversations where you can't change the other person's mind. If you see making them agree with you as the only positive outcome, I can see why you'd give up arguing with people, but you're losing out on a lot of potential benefit.

I also think it's too adversarial. The author's claim, "If you genuinely believe something others don’t, that’s not a debate to win. That’s an edge," is not very persuasive, because you communicate far more with teammates, bosses, and subordinates than with enemies and competitors. Most of the people you communicate with on a day-to-day basis are people who can be dealt with more profitably through cooperation.

"You Can Only Change Yourself" is another far too absolute conclusion. You change and are changed by everybody you come in contact with. Every conversation is a chance to influence someone. If you can't make them see your point right away, you can sow the seeds for a future insight. Or you can clarify why you disagree. You can change their mind from "this person doesn't understand the problem" to "this person cares about an aspect of the problem that I don't think is primary."

I think the author should broaden their idea of what can be achieved in talking with someone they disagree with. It won't help them win arguments, but it will help them reap more benefit over time.

The problem with "tech debt" is it can mean anything from "this is ugly code that takes 5 minutes longer to read but it works well" to "this in a insecure/unstable pile of horse manure and customers will start to notice". The latter is where time should be spent. The former is a vanity project that doesn't bring the business any value.

You may have worked with people whose meaning of "code quality" encompassed things that you found inconsequential and a waste of effort. They may have even told you that if you didn't care about those things, then you didn't care about code quality. But that's not true. It only meant you disagreed with them about what code quality is and how to recognize it.

You draw a distinction between aspects of code that tend to lead to better outcomes and aspects of code that don't matter. You say you know what tech debt looks like. When you look at a codebase, you have opinions on where time should be spent to improve it. "Code quality" is shorthand for the heuristics underlying those opinions.

Instead of accepting that other, possibly dumber people get to define what code quality is, own your own definition of it and use it when you communicate with other people.

This article repeats what we've long known about how technical interviews aren't great at evaluating technical skills and inadvertently filter for things that aren't important. But it doesn't offer a better way of evaluating technical skills. It talks about how to evaluate other things that do matter but aren't substitutes or proxies for technical skills.

Also, this argument is some grade school smarty pants "I'm too smart to show my work" bullshit:

And because the interviewer can’t distinguish “skipped steps due to incompetence” from “skipped steps due to operating at a higher cognitive level,” they default to the interpretation that protects their ego.

I thought the days of hiring toxic "so smart I can't communicate" superstars was over?

A foreign student who is afraid of returning to her home country sounds like an ideal low-level drug dealer. They are legally vulnerable because they are afraid of being expelled from the country, and they have access to lots of potential buyers in their fellow students. And someone who is new and is looking for friends is more easily approached and recruited.

Some have chosen to link their fate to the technology, dedicating themselves to learning prompt engineering, while others are staging a revolt against it.

I don't understand why these are seen as mutually exclusive choices. I think I would be in both of these camps if I were a student.

Unfortunately, a convincing demonstration to convince a skeptical colleague would require measuring developer productivity.

Among skeptics, I've only seen people won over by using it themselves, because when they use AI for their own work, they invest the time to review the code, understand it, and assess its quality by their own standards. That's how people learn to trust AI coding assistance.

I kind of get what they're thinking in trying to make sure all engineers use AI. For myself, and for the engineers working with me, I saw everyone go through an initial aversion and resistance to AI, and then an instant productivity boost when we started using them. So there's definitely a good reason to get everybody to start using AI. You don't want a good engineer resisting AI indefinitely if you know it will make them more productive.

Incentivizing people who are already using AI to use as many tokens as possible does seem a little crazy, though.

Little tidbit that isn't mentioned in the article: he was a consultant on the film Quest for Fire and developed movement patterns and gestures for the actors.

In the business of apparel, I think this is a natural consequence of high-end buyers turning their noses up at long-lived brands, and working to differentiate themselves from mainstream middle-class buyers. It's a revolt against modernism making more and more goods accessible to people outside the economic and cultural elite.

If you're fancy, what do you do when mass production and the internet make the markers of fanciness accessible to the very people you're trying to be fancier than? For one, you stigmatize mass production and elevate artisanal handmade goods. Those are inherently impossible to democratize. Another thing you can do is replace the appreciation of quality with the act of discovery as proof of elevated taste. Make taste a moving target, so the dirty unwashed masses are always a step behind.

Brands like Brooks Brothers or Eddie Bauer have no place in this system. The best the masses can do to imitate the elites is buy cheap fast fashion from brands that go viral and don't live long enough for anyone to know their quality before they're gone.

Flippant answer: in the U.S., in your twenties, you have no spare space, and visiting friends sleep on your couch. In your forties, you have a guest bedroom, and visiting friends stay at a hotel.

Possibly more accurate answer: it depends on what kind of housing people live in, if they have kids, and if they work at home. Most residential houses were built for couples with children, so if someone owns a house and is single and/or childless, they likely have spare bedrooms that serve as a home offices, hobby spaces, or guest bedrooms. People living in apartments usually don't pay for more space than required for their daily needs.

I don't think that's the way you're supposed to read it? I think you're supposed to read it as, the trendy extremes tell you something about a place, even if the details are silly and ephemeral. People with no filter, no shame, no interest in correctness or consequences, and no pole star except trends are like a cartoon guide to the trends and the mentality driving them.

I think the author would agree with most of what you wrote.

I interpret YAGNI to mean that you shouldn't invest extra work and extra code complexity to create capabilities that you don't need.

In this case, I feel like using the filesystem directly is the opposite: doing much more difficult programming and creating more complex code, in order to do less.

It depends on how you weigh the cost of the additional dependency that lets you write simpler code, of course, but I think in this case adding a SQLite dependency is a lower long-term maintenance burden than writing code to make atomic file writes.

The original post isn't about simplicity, though. It's about performance. They claim they achieved better performance by using the filesystem directly, which could (if they really need the extra performance) justify the extra challenge and code complexity.

Honestly, at this point, if I had a design that required making atomic changes to files, I'd redo the design to use SQLite. The other way around sounds crazy to me.

"Why use spray paint when you can achieve the same effect by ejecting paint from your mouth in a uniform high-velocity mist?" If you happen to have developed that particular weird skill, by all means use it, but if you haven't, don't start now.

That probably sounds soft and lazy. I should learn to use my operating system's filesystem APIs safely. It would make me a better person. But honestly, I think that's a very niche skill these days, and you should consider if you really need it now and if you'll ever benefit from it in the future.

Also, even if you do it right, the people who inherit your code probably won't develop the same skills. They'll tell their boss it's impossibly dangerous to make any changes, and they'll replace it with a database.

Advice like this turns almost everybody's normal state into a disorder.

"Go to sleep only when you are very tired" is a child's approach to sleep, it's what we all want to do, and by adulthood we learn that it's counterproductive. But we still want it so much that we regularly test it and are reminded why we don't operate that way.

It reminds me of the intuitive eating folks who say, "Ignore standard diet advice, just listen to your body and feed it what it knows you need," but then when you overeat, they say, "You aren't listening properly, you aren't in tune with your body." Then if you ask, "How will I know when I'm in tune with my body and listening to it properly?" they say, "When what it asks for matches standard diet advice."

If my Oura ring can be trusted, alcohol doesn't interfere with my total amount of sleep or my REM sleep, but it reduces my deep sleep drastically and can even result in me getting zero deep sleep, which hasn't happened a single time without alcohol.

Honestly, if I could quit my job for six months and work in a codebase like yours, I'm extremely curious what I could accomplish with AI.

We have a codebase at work that was "stuck." We've consistently done minor library upgrades, but no major upgrades in several years, and was recognized as a major piece of technical debt / minor disaster for almost two years, in that we urgently needed to dedicate an engineer to it for a month or more to bring it up to date. We also suspected that framework upgrades would improve performance enough to save us a little bit in operating costs. I got curious, created a branch, and threw Claude at it. Claude knocked it out in a couple of days while I mostly worked on other things. Then we dedicated several engineer days to doing extra manual testing. Done and deployed. Now we're ready to experiment with giving it less resources to see if the performance improvement holds up in practice.

This codebase was only about 200k lines of code, so probably smaller than yours. Really curious how it would go with a larger codebase.

EDIT: Claude may only have taken a couple of days because I was only checking in occasionally to give it further instructions. I don't know how fast it would have been with my complete attention.

You couldn't go far on those early Prius batteries. I had a circa-2009 Prius and semi-intentionally ran out of gas to see what happened. I was able to drive a couple of miles to a gas station, but the battery was depleting extremely quickly, and I doubt it would have lasted ten minutes.

These interactions really don't get the testing they need.

When they aren't designed, how do you know how to test?

Over the weekend, I was directed to file a police report with a chatbot and could not complete it because it was asking for information that did not exist and did not apply to my case.

(I'm sure somebody is going to say that this can be solved by having LLMs role play as victims and have an LLM observe and decide what's a failing test case and what isn't.)

Is it a pint? 4 months ago

This is exactly it. That's why the glasses have the same basic form (stem, bowl, and tapered rim) as wine glasses and snifters. The liquid sits in the bowl, and the aroma is captured in the empty space between the liquid and the rim.

People see lower property taxes as a silver lining for short-term swings in the market, but I don't know anybody who thinks this is a short-term swing that they can ride out.

Nobody is happy about their property values going down long term. It exposes them to the risk of a big loss if they're forced to sell because of events in their life.

I guess what I mean by that is that Rob Pike was obviously aware that his rules were not as catchy and pithy as the aphorisms he credited, and his only reason for writing his rules was to improve on them by making them more explicit and less prone to user error. But presenting his versions alongside the more catchy ones means that every time people read them, the catchy ones distract attention and remain more memorable than the improved versions.

I think it's important to think about architectural and domain bounds on problems and check if the big-O-optimal algorithm ever comes out on top. I remember Bjarne Stroustrup did a lecture where he compared a reasonably-implemented big-O-optimal algorithm on linked lists to a less optimal algorithm using arrays, and he used his laptop to test at what data size the big-O-optimal algorithm started to beat the less optimal algorithm. What he found was that the less optimal algorithm beat the big-O-optimal algorithm for every dataset he could process on the laptop. In that case, architectural bounds meant that the big-O-optimal algorithm was strictly worse. That was an extreme case, but it shows the value of testing.

Domain bounds can be dangerous to rely on, but not always. For example, the number of U.S. states is unlikely to change significantly in the lifetime of your codebase.

Anecdotally, what we found in Austin was a combination of two factors:

First, awareness of the futility and selfishness of "growth elsewhere" as a solution is much higher in younger people — and by younger, I mean currently under fifty. Generational turnover in Austin had been eating away at the NIMBY majority, and conversations about housing in Austin have long been polarized more by age than by left/right political sentiment. There's a caricature, with a strong vein of truth, of the old Austin leftist who has Mao's little red book on their shelves and thinks apartment buildings are an abomination, and Austinites of that generation are experiencing mortality. At the same time, younger people are adopting more and more urbanist mindsets compared to their parents.

However, I think a much much bigger factor was the influx of younger people, especially young people with experience of larger cities, diluting the votes of the older NIMBYs. Austin has been shaped by growth for half a century, but its "discovery" in the 2000s and very brief status as a darling of coastal hipsters (remember that term?) has had a lasting effect on Austin's popularity and its demographics. It's been twenty years since it was the "it" place for Brooklynites to visit, but in that twenty years, it's had a lot of exposure for young urban dwellers, and some of them discovered they liked it and moved here, bringing their comfort with dense living and their appreciation that growth can bring a lot of positives.

Personally, every homeowner I know in Austin has seen their houses depreciate significantly this decade, and I don't think it changed a single person's mind about Austin's housing policy. People who opposed the reforms are bitter about the outcome, and people who supported the reforms say it sucks for us personally, but it's what we set out to accomplish, and we're glad that it worked.

I think it's fine and generous that he credited these rules to the better-known aphorisms that inspired them, but I think his versions are better, they deserve to be presented by themselves, instead of alongside the mental clickbait of the classic aphorisms. They preserve important context that was lost when the better-known versions were ripped out of their original texts.

For example, I've often heard "premature optimization is the root of all evil" invoked to support opposite sides of the same argument. Pike's rules are much clearer and harder to interpret creatively.

Also, it's amusing that you don't hear this anymore:

Rule 5 is often shortened to "write stupid code that uses smart objects".

In context, this clearly means that if you invest enough mental work in designing your data structures, it's easy to write simple code to solve your problem. But interpreted through an OO mindset, this could be seen as encouraging one of the classic noob mistakes of the heyday of OO: believing that your code could be as complex as you wanted, without cost, as long as you hid the complicated bits inside member methods on your objects. I'm guessing that "write stupid code that uses smart objects" was a snappy bit of wisdom in the pre-OO days and was discarded as dangerous when the context of OO created a new and harmful way of interpreting it.