News for hackers. Stuff that matters.
Re:Don't DRY Your Code Prematurely by delichon on Thursday May 30, 2024 @01:47PM (#40526559)
"Read" isn't quite the right word for code. "Decode" is better. We have to read to decode, but decoding is far less linear than reading narrative text. Being DRY usually makes decoding easier, not harder, because it makes the logic more cohesive. If I know you only fromajulate blivers in one place I don't have to decode elsewhere.
Re:Don't DRY Your Code Prematurely by wwfn on Thursday May 30, 2024 @02:07PM (#40526845)
I was just mulling this over today. DRY = easier-to-decode is probably true if you're working on groking the system at large. If you just want to peak in at something specific quickly, DRY code can be painful.

I wanted to see what compile flags were used by guix when compiling emacs. `guix edit emacs-next` brings up a file with nested definitions on top of the base package. I had to trust my working memory to unnest the definitions and track which compile flags are being added or removed. https://git.savannah.gnu.org/cgit/guix.git/tree/gnu/packages...

It'd be more error prone to have each package using redundant base information, but I would have decoded what I was after a lot faster.

Separately, there was a bug in some software aggregating cifti file values into tab separated values. But because any cifti->tsv conversion was generalized, it was too opaque for me to identify and patch myself as a drive-by contributor. https://github.com/PennLINC/xcp_d/issues/1170 to https://github.com/PennLINC/xcp_d/pull/1175/files#diff-76920...

Re:Don't DRY Your Code Prematurely by emidln on Thursday May 30, 2024 @02:35PM (#40527180)
Bazel solves this exact problem (coming from its macrosystem) by allowing you to ask for what I term the "macroexpanded" BUILD definition using `bazel query --output=build //some/pkg/or:target`. When bazel does this, it also comments the file, macro,and line number the expanded content came from for each block.

This gives us reuse without obscuring the real definition.

I automated this in my emacs to be able to "macroexpand" the current buid file in a new buffer. It saves me a lot of time.

Re:Don't DRY Your Code Prematurely by withinboredom on Thursday May 30, 2024 @02:19PM (#40526975)
> Being DRY usually makes decoding easier, not harder

"Usually" being the keyword and what the article is all about IMHO. I work in a codebase so DRY that it takes digging through dozens of files to figure out what one constant string will be composed as. It would have been simpler to simply write it out, ain't nobody going to figure out OCM_CON_PACK + OCM_WK_MAN means at a glance.

Re:Don't DRY Your Code Prematurely by djeastm on Thursday May 30, 2024 @02:30PM (#40527133)
>I work in a codebase so DRY that it takes digging through dozens of files to figure out what one constant string will be composed as.

I don't know the codebase, but to my mind that level of abstraction means it's a system-critical string that justifies the work it takes to find.

Re:Don't DRY Your Code Prematurely by RussianCow on Thursday May 30, 2024 @03:20PM (#40527631)
Sorry, but this doesn't make sense. Why should system critical things be more difficult to understand? Surely you want to reduce room for error, not increase it?
Re:Don't DRY Your Code Prematurely by withinboredom on Thursday May 30, 2024 @04:13PM (#40528076)
I mean, sure, I guess API urls could be system-critical. But generally, I prefer to grep a codebase for a url pattern and find the controller immediately. Instead, you have to dig through layers of strings composed of other strings and figure it out. Then at the end, you’re probably wrong.
Re:Don't DRY Your Code Prematurely by jbverschoor on Thursday May 30, 2024 @04:19PM (#40528139)
Function calls, the essence of DRY, are only readable if it is well known and well understood what it does.

When code is serial, with comment blocks to point out different sections, it is much easier to read, follow, and debug.

This is also a little bit of a tooling problem

Re:Don't DRY Your Code Prematurely by hathawsh on Thursday May 30, 2024 @01:57PM (#40526693)
Well, "read" is still the verb we use most often to describe a human interpreting code. Also, many information-dense books are not intended to be read linearly, yet we still say we're "reading" (or "studying") the book.
Re:Don't DRY Your Code Prematurely by dsego on Thursday May 30, 2024 @03:30PM (#40527716)
Visually parse.
Re:Don't DRY Your Code Prematurely by Nevolihs on Thursday May 30, 2024 @03:54PM (#40527916)
Does it? Every time I see DRY'd code, it usually makes the project it's in more difficult to understand. It's harder to understand where values come from, where values are changed, what parts of the codebase affect what. And that's before trying to figure out where to change something in the right place, because it's often unclear what other parts of the code are coupled to it through all the abstractions.

At a high level, at first glance, the code might look good and it "makes sense". But once you want to understand what's happening and why, you're jumping through five different classes, two dozen methods and you still don't know for sure until you run a test request against the API and see what shows up where in the debugger. And you realize your initial glimpse of understanding was just window dressing and actually nothing makes sense unless you understand every level of the abstractions being used.

It's suddenly a puzzle to understand another software developer instead of software engineering.

Re:Don't DRY Your Code Prematurely by hnick on Thursday May 30, 2024 @07:13PM (#40529803)
An IDE can help a lot. Coming from Perl, everything you said was true. I wanted everything in one file as much as possible, and breaking tasks off into functions just meant I had to jump around to try and rebuild the flow in my head. I spent so much time inside the debugger since reading the code would only go so far.

Now I work in C#, we have a lot of classes with a few functions, a lot of helper functions. Doesn't matter since it's so easy to use the tooling to build a mental picture - let alone refactor it in an instant if that variable name feels a bit off, or we think a function is not used (such things were always a risky exercise in Perl).

We refactored one insurance based project to use generic base classes extensively since all insurance shares some attributes and features - this really helped cut down complexity of changes and overall just reduced code on the screen to sift through. I had a lot of fun doing this, I'm a weirdo who almost likes deleting code more than writing it. Once you hit the lowest level it is a little less intuitive due to being generic but at the higher levels we mostly work at, it's simpler, and rolling out a new product we get a lot of stuff for free. They got a long way copy-pasting the product logic (4 or 5 product lines) but at this point it made sense to revisit, and I sneak a bit more in each time I have a change to do.

Re:Don't DRY Your Code Prematurely by cloverich on Thursday May 30, 2024 @05:30PM (#40528931)
One area I find DRY particularly annoying is when people overly abstract Typescript types. Instead of a plain interface with a few properties, you end up with a bunch of mushed together props like { thing: boolean } & Pick<MyOtherObj, 'bar' | 'baz'} & Omit<BaseObj, 'stuff'> instead of a few duplicated but easily readable interfaces:

interface MyProps { thing: boolean; bar: string; baz: string; stuff: string; }

Re:Don't DRY Your Code Prematurely by jddj on Thursday May 30, 2024 @06:28PM (#40529455)
Am I crazy for almost exclusively just using type and sum types and no generics or interfaces and somehow being able to express everything I need to express?

Kind of wondering what I'm missing now.

Re:Don't DRY Your Code Prematurely by Aeolun on Thursday May 30, 2024 @06:45PM (#40529586)
Hmm, you can do pretty nice things with generics to make some things impossible (or at least fail on compile), but I agree it’s hardly readable. In some cases you need that though.