Live data from Hacker News

Prefer duplication over the wrong abstraction (2016)

sandimetz.com

351–360 of 375 posts

Re: Prefer duplication over the wrong abstraction (2016)

#351
post #55

I believe that "single source of truth" is a principle that should always be followed. If there's duplicated code where it'd be a bug if they diverge, then you should refactor. It creates a long-distance coupling in your code that may be invisible to future developers until a bug emerges. But with that in mind, I mostly agree with the article: if it's not a violation of "single source of truth", then abstractions are…

> I believe that "single source of truth" is a principle that should always be followed Theoretically and conceptually I agree. But in practice there are a lot of programming languages aren’t as expressive. People prefer codebases with duplications rather than visitor patterns everywhere. In essence, visitor pattern is a tool to solve multi-dimensional abstraction problems, just like type classes in Haskell or CLOS i…

Visitor pattern is there due to a very simply reason. You have n datatypes with m functions. FP languages makes adding a new row to this nm table easy, OOP languages makes adding a new column easy (that is, without changing every* use site as well).

Visitor pattern makes the row addition case possible for OOP languages, that's it.

Re: Prefer duplication over the wrong abstraction (2016)

#352

Two talks come to mind here: Mike Acton's Data-Oriented Design and C++ [1] and Brian Cantrill's The Complexity of Simplicity [2]. Mike's talk argues that code solutions need not be modelled on the real world, and that different data creates different problems, which need different solutions. I can't do the talk justice, but it's had a big impact on me. Brian's talk is about abstraction generally, and how it's difficu…

See also: Data-Oriented Programming: Reduce software complexity by Yehonathan Sharvit https://www.manning.com/books/data-oriented-programming and from SICP : 2.4.3 Data-Directed Programming and Additivity https://sarabander.github.io/sicp/html/2_002e4.xhtml#g_t2_00...

There's a reason why "naming things" is one of the two hard problems in Computer Science. Data-Oriented Design (DOD) and Data-Oriented Programming (DOP) are two different things which has caused a fair amount of confusion on HN before. Data-Directed Programming (DDP) appears to be a third, different thing.

In searching those threads, I came across a post from the author of the DOP book describing the difference between DOD, DOP, and DDP (a different DDP! Data Driven Programing; a fourth thing!) [2], and I see he also made the "naming things" joke in the first paragraph, so I guess my humour isn't that unique!

There's been quite a bit of discussion about DOD and some about DOP (and much conflation between the two) on HN, it can be interesting to read [3].

1. https://martinfowler.com/bliki/TwoHardThings.html

2. https://blog.klipse.tech/visualization/2021/02/16/data-relat...

3. https://hn.algolia.com/?q=Data+Oriented

Re: Prefer duplication over the wrong abstraction (2016)

#353
post #38

I used to struggle with abstractions back in my OOP days but since moving pretty much to a purely functional approach I find that code duplication is rare. Just have a function and call it in two parts. The main abstraction issue is then data structures but with TypeScript interfaces being duck typing essentially I run into few problems there as well. So code duplication because of abstraction issues is rare. Code du…

what exactly is 'calling a function in two parts'

I read it as if your function contains a lot and you'd like to reuse part of this functionality in another place you don't have to figure it out how to abstract this. It's easy to just split your function in two parts and call the part you are interested in far away as is.

But I'm probably overthinking it.

Re: Prefer duplication over the wrong abstraction (2016)

#354
post #267
post #225

Similarly, I've seen some developers who seem to think that any inline string or numeric constant is evil. In one PR, I saw: HTTPS_SCHEME = 'https' DOMAIN = 'www.example.com' url = HTTPS_SCHEME + '://' + DOMAIN I don't understand what they think this is buying, other than just cargo culting "don't embed constants." And of course, the constant definitions were at the top of the file and the url building code was hundr…

Having the constants at the top is more easily customizable, especially should this file get duplicated. If devs need to switch to http instead of https for testing or staging, it makes sense to separate the scheme from the domain and put the constants up top or even in another file. It also matters whether ‘url’ was constructed in multiple places or a single place. Having named constants at the top of the file is a…

In my opinion (and it's just that - an opinion, and mine - yours may differ), it's better to make the code as stupid simple as possible. When you build it, don't assume future change in that spot, because you could be terribly wrong about exactly what would change, so you're adding complexity for no benefit. The first time you need to change the scheme from `https` to `http`, just change it inline in the URL building code. The second time you need to do it, make a constant or an env var.

Over time, everyone develops their own intuition and opinions on what sorts of change and refactors are likely, and which sorts will never come. It's not perfect - it's part of the art of software, not the science. I'm not going to claim I've never written an interface that had a useless cut-point - I definitely have written many.

In my opinion, it's better to err on the side of simplicity, understandability, and closeness than to prematurely factor out those constants.

It's a judgement call - every situation and every practitioner will have a different response. In this case, knowing this product, and as the code reviewer for this patch made by a newer engineer (senior but new to the team), I was very confident that we would never need to change the scheme, and that the extra line and extra cognitive load of groking `HTTPS_SCHEME + "://"` over just `"https://"` or `BASE_URL + blah` was not worth it.

I suggested that the engineer either rewrite it with an inline constant, or refactor the whole base URL out without separating the scheme.

Re: Prefer duplication over the wrong abstraction (2016)

#355
post #225

Similarly, I've seen some developers who seem to think that any inline string or numeric constant is evil. In one PR, I saw: HTTPS_SCHEME = 'https' DOMAIN = 'www.example.com' url = HTTPS_SCHEME + '://' + DOMAIN I don't understand what they think this is buying, other than just cargo culting "don't embed constants." And of course, the constant definitions were at the top of the file and the url building code was hundr…

That particular example doesn't quite fit, but I've certainly seen cases where otherwise perfectly ordinary fixed strings needed to be broken up to meet linting rules.

Ah yeah those are bad linting rules then. That's one of my pet peeves. Inconsistent style is better than style forced into jankiness. Also... linters should auto-format whenever possible. I'll make a few exceptions, but broadly I like to set the enforcement of linting rules to only those cases that are honestly confusing or misleading.

Re: Prefer duplication over the wrong abstraction (2016)

#356
post #244
post #225

Similarly, I've seen some developers who seem to think that any inline string or numeric constant is evil. In one PR, I saw: HTTPS_SCHEME = 'https' DOMAIN = 'www.example.com' url = HTTPS_SCHEME + '://' + DOMAIN I don't understand what they think this is buying, other than just cargo culting "don't embed constants." And of course, the constant definitions were at the top of the file and the url building code was hundr…

I ran into this as well. If an Event has a name, you can instantly grep across a giant monolith (or a big folder of microservice repos) and find every file that is concerned with that event. If you pull it out into a constant, you're back to opening up projects one-by-one to 'find usages'

grepability is underrated. This is one of the reasons I dislike passing functions into interfaces - it makes it harder to follow the call chain when the functions are constantly renamed.

Luckily there are often solutions that just come down to which arbitrary labels that you assign. e.g. compare these two blocks

    do_thing = do_thing_one_way if condition else do_thing_other_way
    process(data, do_thing=do_thing)
versus

    thing_processor = do_thing_one_way if condition else do_thing_other_way
    process(data, thing_processor=thing_processor)
The first is much more greppable - search for "\bdo_thing" all over the code base. The second requires realizing that the processor function renames the internal function to "thing_processor".

Re: Prefer duplication over the wrong abstraction (2016)

#358
post #333
post #42

Nobody wants to listen. Nobody. In 90% of the companies there are some so called senior devs that get ecstatic when they create a new abstraction. Overengineering, abstractions and premature optimisation are the 3 worst plagues of engineering. At the same time I’m happy they exist because it means we’ll always have a job.

There are codebases out there with enormous amounts of duplication, filled with implicit dependencies. You just haven't encountered them to appreciate good abstraction.

I think that all this people defending this post have no idea that this rationale can cause. I'm sitting at a codebase that has the same code for iterating copied around 20 times.

As a senior I will tell you to dedup whether I can to avoid this shit.

Re: Prefer duplication over the wrong abstraction (2016)

#359
post #309

Earlier quoted context omitted.

I was probably that guy! It was all the rage 20 years ago, including worrying about the diamond inheritance problem. What is the equivalent in the current generation? ORM that no one can maintain? Unnecessary dev ops complexity? Anything "web scale"?

Are ORMs still a thing? I've been away from OOP for some years now, but just when I was leaving it, there was a trend firmly against ORMs... my guess was that they were on their way out, replaced by more lightweight libs and frameworks? Or did they make a comeback? Regarding OOP itself, I also remember when "favor composition over inheritance" became a thing. Was this reversed too?

    > Are ORMs still a thing?
In enterprise CRUD software: Absolutely.

    > favor composition over inheritance
I was very late to arrive to Java around 2015. This expression was wide-spread at the time. For those involved with "OOP" enterprise languages like .NET/C# or Java, when did "favor composition over inheritance" become dominant?

Re: Prefer duplication over the wrong abstraction (2016)

#360
post #309

Earlier quoted context omitted.

Are ORMs still a thing? I've been away from OOP for some years now, but just when I was leaving it, there was a trend firmly against ORMs... my guess was that they were on their way out, replaced by more lightweight libs and frameworks? Or did they make a comeback? Regarding OOP itself, I also remember when "favor composition over inheritance" became a thing. Was this reversed too?

I love an ORM. I think much of the problems people experience with ORM, OOP, Restful routes, is because they get the domain model wrong. When you model the data correctly you don’t need to have complex queries that push ORM beyond their breaking point.

    > I love an ORM.
No trolling: What langauge and what framework? One thing I can say from experience: I have seen some teams where they have deep knowledge of an ORM framework, and they are crazy productive when writing enterprise CRUD software.
Post reply on HN