Live data from Hacker News

Code doesn’t have to be a mess

danielsieger.com

171–180 of 190 posts

Re: Code doesn’t have to be a mess

#171

Something that shocked me was working with junior programmers for the first time. For decades , I had either worked solo or with other experienced developers. It was an eye-opening experience. My style is influenced by Haskell and Rust, even when I program in, say, C# or PowerShell. A simple example: I will extract the read-only logic into a pure function and minimise the size of the mutable procedure. This makes it…

> In every case they said they were in a hurry and that they would “fix it later”.

This. We need to stop using time pressure as an excuse to do a bad job. Moving things out to a separate function might add 10 min but save 100x when everything comes crashing down.

Of course you shouldn’t overengineer but so much can be gained from spending a little time just thinking about how this should work.

Re: Code doesn’t have to be a mess

#172

In my experience people refactor code to their own understanding of the problem and not all refactorings improve the code. People abstract before an abstraction is necessary. I find single file dense leetcode style code easier to understand and follow the flow. Algorithmic code I can reason around. A large mature codebase is far harder to get to know. One of the first things I do when I study a new codebase is find a…

> People abstract before an abstraction is necessary. Sometimes an abstraction cuts to the core of the reason why. See for example https://algebradriven.design/ Good abstractions can communicate intent better than mounds of concrete code because they speak at a higher level. However, mounds of okay concrete code is way easier to deal with then poorly thought out abstractions. This means pragmatists get little practic…

I started designing an algebraic language by writing code.

https://GitHub.com/samsquire/algebralang

It's designed to be expressive and powerful and practical.

The core insight to a problem is rarely what we spend most of our programming time doing.

Re: Code doesn’t have to be a mess

#173
post #26

> Say No Getting junior devs to do this is like pulling teeth. Trying to get a feature stopped after they've built it is soul crushing for them. It's a problem. At this point I've all but given up beyond minimizing the blast radius in code review.

It’s especially difficult when they came up with it themselves.

We’re amidst a rewrite and we have an off-shore team involved. They same team that built the original starting 4yrs ago.

One of their team members decides “we should validate the TLD for email addresses entered by the user.” Code is added, a TLD file is added, and in code review I reject the whole concept. Show me the ticket or feature docs, and I’ll argue with the author of those instead.

“We did this in the last app…” Maybe, but we didn’t spec that for this app.

He got his local project lead (non-tech) to write a Jira story for us to “discuss the technical implementation.” Dude, srsly.

Our app is web-first and is used on congested mobile networks (like, hundreds of people all using the same cellular site simultaneously.) A TLD file does not need to be delivered to each of them for validation that’s pointless.

The idea is off the table, code rejected, but the guy spent time doing something no one asked for and had his local team onboard with it.

Re: Code doesn’t have to be a mess

#174
post #2

Would be curious to know what strategies other people apply in order to keep complexity down over time!

All dependencies should be injected (and possibly wrapped with custom interfaces, if they're libraries).

All globals should be configurable (most codebases I've seen have a ton of hidden globals).

All side effects should be isolated.

"Break any of these rules sooner than say anything outright barbarous."

Re: Code doesn’t have to be a mess

#175

Earlier quoted context omitted.

> People abstract before an abstraction is necessary. Sometimes an abstraction cuts to the core of the reason why. See for example https://algebradriven.design/ Good abstractions can communicate intent better than mounds of concrete code because they speak at a higher level. However, mounds of okay concrete code is way easier to deal with then poorly thought out abstractions. This means pragmatists get little practic…

I started designing an algebraic language by writing code. https://GitHub.com/samsquire/algebralang It's designed to be expressive and powerful and practical. The core insight to a problem is rarely what we spend most of our programming time doing.

Are those code samples formatted correctly? (they are difficult to read as is)

Re: Code doesn’t have to be a mess

#176

In my experience people refactor code to their own understanding of the problem and not all refactorings improve the code. People abstract before an abstraction is necessary. I find single file dense leetcode style code easier to understand and follow the flow. Algorithmic code I can reason around. A large mature codebase is far harder to get to know. One of the first things I do when I study a new codebase is find a…

> I find single file dense leetcode style code easier to understand and follow the flow. Algorithmic code I can reason around. A large mature codebase is far harder to get to know. I genuinely can't tell if you're being serious or not. If you are, do you also like to read books written as one giant chapter? Or entire chapters as one giant paragraph?

Reading enterprise code is like reading a book where 99% of the pages don't contain any meaningful information.

Re: Code doesn’t have to be a mess

#177
post #117

Earlier quoted context omitted.

The book analogy you use isn't very accurate. Even if you merge chapters and paragraphs like that, you still read it sequentially. Just in a less comfortable way. Which is not at all like a modern codebase that is modular, abstracted, etc. If you're new to a codebase, and want to understand one particular feature, you'd likely need to jump back and forth across 10 files. It's not far-fetched to say that makes it diff…

The thing is that if you just need to understand a specific part of something you will need to jump as well even if everything you needed for that one thing is written sequentially in one file. You will want to skip over implentation details of certain things to get the general picture first on a more abstract level. Let's say you have a simple endpoint that takes a list of comma separated inputs, parses them as numb…

This would be the “simple” code. The “abstract” code would be more like this:

  public class EndpointManager {
    private EndpointInputManager eim;
    private StringSplitter splitter;
    private NumberParser parser;
    private Sorter sorter;
    public EndpointManager(EndpointInput input) {
      eim = new EndpointInputManagerFactory().setInput(input).build();
      splitter = new StringSplitterFactory().setDelimiter(new Delimiter(",")).build();
      parser = new NumberParserFactory().setFormat(NumberParserFormat.INTEGER).setMode(NumberParserMode.LIST).build();
      sorter = new SorterFactory().setSortOrder(SortOrder.ASCENDING).setAlgorithm(SortingAlgorithm.QUICK_SORT).build();
    }
    public EndpointOutput endpoint() throws ParseException {
      splitter.split(eim.getInput());
      parser.parse(splitter.getList());
      sorter.sort(parser.getOutput());
      return new EndpointOutputFactory().setOutput(sorter.getSortedList()).build();
    }
  }

Re: Code doesn’t have to be a mess

#178
post #51
post #41

Earlier quoted context omitted.

Being married to your code/output is just another flaw typical for juniors. Put them on features that aren't critical or ensure they are made aware up front that their work may be rejected if it doesn't meet design expectations.

I'm not a junior dev and I still get peeved when my time is wasted. I guess I would only not care if I didn't care about what I was working on, but that's a different kind of existential torment haha. Beyond opportunity cost, you can think of it as deleterious to your performance. If 10% of your work never gets merged because of shifting priorities, compared with someone else who has miraculously dodged these problem…

No code changes should be merged purely because the author got less code merged than someone else on their team. This sounds harsh maybe, but by your reasoning, your feelings could end up being the cause for bugs, poor quality code and/or bad design ending up in a release.

Of course, you and your team should work together to _avoid_ having to reject work! But it can and will happen, it's perfectly normal for mistakes to be made, it's how all humans learn.

Trying to deny that people sometimes fail is foolish. Punishing yourself for making a mistake is on you.

The only unfair thing here is taking others in the team hostage with the idea that you are entitled to getting your work merged regardless of its quality, purely because it would make you peeved, cranky, annoyed! That constitutes toxic behavior. If this is a pattern for you, people will avoid working with you.

Instead: embrace the opportunity to learn. Get feedback, reflect with the team, do better next time. Maybe pair up to refactor your work. Take the positive approach!

Re: Code doesn’t have to be a mess

#179
post #178
post #51

Earlier quoted context omitted.

I'm not a junior dev and I still get peeved when my time is wasted. I guess I would only not care if I didn't care about what I was working on, but that's a different kind of existential torment haha. Beyond opportunity cost, you can think of it as deleterious to your performance. If 10% of your work never gets merged because of shifting priorities, compared with someone else who has miraculously dodged these problem…

No code changes should be merged purely because the author got less code merged than someone else on their team. This sounds harsh maybe, but by your reasoning, your feelings could end up being the cause for bugs, poor quality code and/or bad design ending up in a release. Of course, you and your team should work together to _avoid_ having to reject work! But it can and will happen, it's perfectly normal for mistakes…

I feel like my little comment here became something of a Rorschach test. I'm definitely not saying we should merge bad code to keep merge rates even. All I'm saying is:

- Someone says "build this thing"

- I build "this thing"

- That someone says "just kidding, we're not gonna use it"

- I'm peeved

Someone else in this thread is arguing this is an entitled position, and here you're arguing that... well, I think you're arguing that I think all my code is always amazing and should always be merged.

I'm not! Like I wrote elsewhere I've written some pretty shit code, I've built the wrong thing, and I've built broken things. I'm sure this is true for most SWEs. This isn't the scenario I'm describing.

But I think this discussion has some merit in terms of how we navigate code review. For example, conversely, I've been on the other end of some pretty... bad feedback. The first example that comes to mind is that we had a portal where you could search by text or category, but once you selected a result we wouldn't save your search anywhere (query params, session storage, etc.). Consequently, when you clicked our "back" link, your search would be gone. We YAGNI'd it for a long time, but we accepted a very tight deadline project (COVID/government related) that required a category that needed to be sticky.

I built this using query params, like pretty much every search out there (for good reason). This ended up changing a lot of templates, a couple of front-end React components, and required extra logic in a couple Django controllers. It was a big-ish change, maybe (to my recollection) 300-400 lines across a few stacked PRs--meticulously, for ease of review. All previous tests passed, all the new tests I wrote (typically >= 50% of my PRs were new tests) passed, I even built a punch list of UI tests I ran through (this was going to be a big user-facing feature and I wanted it to be bulletproof). This took I think... 2 days of constant work, so something like ~30 hours.

This wasn't our typical process; we skipped our usual engineering meetings about implementation strategy and what-not. Our team was small--4 people including our CTO--but even so we had a wide diversity of opinion when it came to implementation, architecture, and style, so it kind of ended up being the case that if we wanted anything to get through PR we had to hash it out beforehand. But we literally had 7 days or something to do this, so we just didn't have time.

But, predictably, despite all my tests and punch list, my PRs were rejected as "too much code", and we missed our deadline. We launched without the feature. Our CTO reviewed the vast majority of our PRs, he reviewed these and he was pretty furious about the scope of the changes, blaming me for missing the deadline.

Afterwards, he tried reimplementing it using query params in less code, but failed. He then tried reimplementing it using local storage, which was less code, but had multiple problems: local storage works across tabs which is deeply weird, but even if he switched to session storage, it didn't work in lots of versions of mobile Safari if you're in private browsing mode. I rejected that PR for those reasons, which we disagreed vehemently about. Eventually, a couple months later, we paired on it, and basically reimplemented my work together.

There are obviously a lot of flags in this little story, but I don't think they're wildly out of the ordinary for a startup (if anything, it's way too much process for a 10 person company). My point is that, while I'm sure there are a lot of cases of "I'm God's gift to this company merge all my work never question me" out there, there are also a lot of cases of "no PR is fit to merge the first time" and "I'm a great programmer, you didn't do this the way I would, therefore this isn't good enough" as well.

Re: Code doesn’t have to be a mess

#180
post #93

Earlier quoted context omitted.

I agree. As a dev in a pretty large organization, I have seen the knowledge of business logic dissapate as the org grew, with some churn. To the point now where very few people actually know how the current system works, let alone how it is supposed to work. This means the only concrete definition of "this is what the system is supposed to do" is only in the code. The organization is disorganized, and the code is onl…

Oh god you just brought back a memory from when I was brought in to manage a team at a dysfunctional organization and I was trying to figure out how a complex service was supposed to work. I asked: "Do you have any documentation or requirements", I was told "The code is the requirements", to which I responded "Wonderful that means there can't ever be bugs because there will never be a discrepancy between the code and…

I'm going to steal your quote. I love it!

To add, how could they do any QA when testing needs to map to those unwritten requirements

Post reply on HN