Live data from Hacker News

DRY is an over-rated programming principle?

gordonc.bearblog.dev

181–190 of 501 posts

Re: DRY is an over-rated programming principle?

#181
Tl;dr with the comments but I didn’t see “debugging” or “maintenance” showing up. Collecting things, which I assume is an aspect of DRY, makes it less risky - the change or fix can be applied once rather than hoping all of the instances in the code were addressed (correctly). Developer time is precious no matter how many of them you have. Given a sensible design, you can always tune hotspots. Can’t speed up debugging and brittle or unclear code means you’ll be doing more of it.

And if it’s “just going to be used once” who really care how it’s written other then “quickly and correctly”? And sadly, too many things aren’t just used once.

Re: DRY is an over-rated programming principle?

#182
Pizza Cost Optimization Dark Pattern Programming Example:

Here is the pizza cost optimizer from Pizzatool, written in object oriented NeWS PostScript, which checks all of the pre-defined base pizza styles and selects the "best" combination of style + extra toppings, ostensibly to save the user some money.

It's actually a dark pattern, because it's biased towards selecting higher level pizzas instead of the least expensive pizza. But at least the dark pattern is documented:

"Figure out the cost of the pizza, were we to order it as this style, and remember the style as the best match if it pleases us. The definition of pleasing us is biased towards matching higher level complex pizza styles, rather than economical lower level pizzas with extra toppings. This is the kick-back to Tony&Alba's for all that free beer."

The Story of Sun Microsystems PizzaTool How I accidentally ordered my first pizza over the internet:

https://medium.com/@donhopkins/the-story-of-sun-microsystems...

Tony and Alba's Pizza and Pasta, Mountain View:

https://www.yelp.com/biz/tony-and-albas-pizza-and-pasta-moun...

PizzaTool Source Code:

https://www.donhopkins.com/home/archive/NeWS/pizzatool.txt

    % Calculate the cost of this pizza.
    %
    /updatecost { % - => -
      10 dict begin % localdict
        /TheBest /defaultstyle ClassStyle send def
        /TheStyle null def
        /TheTopping null def
        /TheBestCost 99 def
        /TheBestExtras 0 def

        % For each and every pizza style in the universe:
        /styles ClassStyle send { % forall:               % style
          /TheStyle exch def                              %

          % Ask this style for its list of standard toppings.
          /TheToppings /toppings TheStyle send def

          % Is every topping from this style on our pizza?
          true                                            % true
          TheToppings { % forall:                         % true topping
            Toppings exch arraycontains? not { % if:      % true
              % Oops, this topping's not on the pizza. No dice.
              pop false exit                              % false
            } if                                          % true
          } forall                                        % true|false

          { % if: all the toppings of the style were on our pizza:
                                                          %
            % Make an array of our pizza toppings that aren't in the style.
            /ExtraToppings [
              Toppings {                                  % ... topping
                % Is this topping included in the style? Then toss it.
                TheToppings 1 index arraycontains? {      % ... topping
                  pop                                     % ...
                } if
              } forall
            ] store                                       %

            % Figure out the cost of the pizza,
            % were we to order it as this style,
            % and remember the style as the best match if it pleases us.
            % The definition of pleasing us is biased towards matching
            % higher level complex pizza styles, rather than economical
            % lower level pizzas with extra toppings.
            % This is the kick-back to Tony&Alba's for all that free beer. 
            PizzaSize /pizzasizeindex self send           % sizeindex
            ExtraToppings length                          % sizeindex extras
            /extraprice TheStyle send                     % $
            dup                                           % $ $
            ExtraToppings length                          % $ extras
            /extras TheStyle send sub                     % $ $ extras'
            1 le { .9 mul } if                            % $ biased$
            TheBestCost le { % ifelse:                    % $
              % Hey this is the best match so far, let's not forget it!
              /TheBestCost exch store                     %
              /TheBest TheStyle store
              /TheBestExtras
                ExtraToppings length /extras TheBest send sub
              store
            } { pop } ifelse                              %
          } if                                            %
        } forall                                          %

        % Set the window footers of the pizza topping panel.
        % The left footer displays the name of the pizza style,
        % and the right footer displays a message
        % telling the user to choose more toppings,
        % or the number of extra toppings,
        % or nothing at all.
        TheBestExtras dup 0 lt { % ifelse:                % extras
          neg dup 1 eq { () } { (s) } ifelse              % extras (plural?)
          exch (Choose % more topping%!) sprintf          % (message)
        } { % else:                                       % extras
          dup 0 ne { % ifelse:
            dup 1 eq { () } { (s) } ifelse                % extras (plural?)
            exch (With % extra topping%.) sprintf         % (message)
          } { % else:                                     % extras
            pop nullstring                                % ()
          } ifelse
        } ifelse                                          % (left footer)
        /name TheBest send exch                           % (left) (right)
        /setfooter ToppingWindow send                     %

        % Remember the price of this pizza in dollars rounded to cents,
        % and calculate its string value. 
        TheBestCost                                       % $
        Fraction mul
        100 mul round 100 div
        /Price 1 index store
        dup 100 mul round cvi 100 mod                     % $ cents
        exch floor cvi                                    % cents dollars
        1 index 10 lt { (%.0%) } { (%.%) } ifelse         % cents dollars fmt
        sprintf                                           % (price)

        % Set the value of the costfield and totalfield labels to
        % the price string.
        dup /setvalue costfield send
        /setvalue totalfield send                         %

        % Set the value of the stylevalue label to the name of the best style,
        % and set the stylemenu value to the index of that name in the list of
        % pizza styles. (The stylemenu is an exclusive settings menu.)
        /name TheBest send                                % name
        dup /setvalue stylevalue send
        PizzaStyleNames exch arrayindex {                 % index
            [exch] /setvalue stylemenu send               %
        } if                                              %

        % Remember the best match pizza style.
        /Style TheBest store

      end % localdict
    } def

Re: DRY is an over-rated programming principle?

#183
post #95

Wtf. If your use-case is that the user can select the crust, sauce, cheese and toppings for a pizza, just pass that shit to the make_pizza function with the help of enums and arrays. If you want to have predefined pizzas, you'd simply make a dictionary of pizza templates with all the options that the make_pizza function needs and/or if you wanna be fancy, you'd make a separate make_pizza_from_template function, but d…

> It's not your fault if nobody cared to mention that the user should be able to arbitrarily subdivide the pizza and select options sepatately for each subdivision - that's a feature update and it's OK if the original program hadn't though of that.

I would argue it’s part of your job most of the time to challenge whatever needs are presented and ask questions about the long-term vision to find a good middle ground of future proofing vs over-engineering. That is of course one of the hardest things to get right.

Re: DRY is an over-rated programming principle?

#184

Earlier quoted context omitted.

I don't read coding opinion articles like OP but I like to check out comments. > DRY does NOT lead to over-complicating things. That is not true. I dive around foreign code bases a lot and dry-ness is actually a significant complicating factor in understanding code, because you're jumping around a lot (as in physically to different files or just a few screens away in the same file). As in, inherently every time it's…

I can't disagree more. DRY forces you to create pure reusable code, and split your code into small pieces. When I read such code I need to understand just a few pieces.

You need multiple cases of duplication (repeating yourself) before you can infer a reusable piece of code.

If you make everything as generic and reusable as possible from the beginning, you'll end up with messy code that has way too much options to set for every simple operation.

Re: DRY is an over-rated programming principle?

#185
post #141
post #74

Earlier quoted context omitted.

If you have the same code copied to several places it makes it much harder to maintain. If there you find a bug in that code block then you have to fix it in several other places, and if you forget some, a bug that you thought you had already fixed might arise again.

How often do you really write the same piece of business logic code in multiple places? I think discussion is that mostly it really is different code that only superficially looks the same. I don't like pizza example. But I have seen more issues because people were trying to cram code that looks the same in one function than some bug needed to be fixed multiple times because code was duplicated. You also have layers…

> How often do you really write the same piece of business logic code in multiple places?

well, depends if you avoid DRY or not. If you apply DRY, zero times.

Re: DRY is an over-rated programming principle?

#186
post #41

Earlier quoted context omitted.

> Mistake 1: Switch from DRY to premature optimization. "Premature optimization" is largely a bogus concept, because the meaning of "optimization" has shifted a lot since the concept was first created. People now use optimization to mean "sensible design that does not needlessly waste resources". In this meaning of optimization, "premature optimization" is a bogus concept. You should absolutely ALWAYS write non-pessi…

> You should absolutely ALWAYS write non-pessimized code by default. Some days I come here just for the typos. :) Today I've seen two good ones, number zero was "Costco had to stop returns on TVs because people were “renting” them for free for the superb owl."

Where is the typo? And the usefulness of your comment?

Re: DRY is an over-rated programming principle?

#187
post #175

Earlier quoted context omitted.

> What does `make_pizza()` do? It could be a lot or it could be a little. It could have side-effects or not. Now I have to read another function to understand it, rather than easily skimming the ~four lines of code that I would have to repeat. This is not a problem of DRY. This is a problem of wrong abstraction and naming. If the function is just four lines, it could easily be named `make_and_cook_pizza`. In the alte…

Exactly this. I fixed a problem like this a week ago. I found some duplicated code, factored it out into one place by introducing an abstract base class (Python) and in the process discovered one of the duplicated methods had a logic error leading to returning a slightly smaller integer result. The code had test coverage, but the test confirmed that it produced the wrong result. I had to fix the test too.

So your refactor broke the tests, so you assumed the tests must be wrong.

Re: DRY is an over-rated programming principle?

#188
A better formulation of DRY is SPOT (Single Point Of Truth). Definitions (code, data) that represent the same “truth”, i.e. when one changes all have to change to represent a consistent truth, should be reduced to a single definition. For example, if there is a rule that pizzas need at least one topping, there should only be a single place where that condition is expressed, so that when the rule changes, it isn’t just changed in one place but not the others. Another example is when fixing a bug, you don’t want to have to fix it in multiple places (or, more likely, neglect to fix it in the other places).

Re: DRY is an over-rated programming principle?

#189

Especially if there is a very common refactoring bug and you get a pepperoni pizza instead of a pizza with one of the most natural toppings like pineapple. But I tend to agree with the author. Sometimes verbosity is the lesser evil. No suggestion should become a dogma and whoever played some games of code golf knows that short code doesn't mean code that is easy to read. Extreme example of course. But I believe many…

> ...Especially if there is a very common refactoring bug and you get a pepperoni pizza instead of a pizza with one of the most natural toppings like pineapple.

Exactly! The DRY'ed example in the first section should read rather:

  def make_hawaiian_pizza():
    make_pizza(["ham","pineapple"])
This demonstrates the omnipresent dangers of untested copy-paste.

"Copy-paste, copy-paste, Will Robinson!!"

Re: DRY is an over-rated programming principle?

#190
Every time I read an article like this, "why is overrated", I think, yeah you are right in theory. But most places I have worked, these best practices were not overused, but underused. If you have the problem that your coworkers create unneccessary abstractions, I envy you, because I have so often had the opposite problem. Maybe this is not the case if you work in a great software development team. But if you work somewhere where they do software development on the side (science, hardware, etc..) it is the main issue.

People not able to factor out functions or structure their code in a readable way. Variables are called v1, v2, v3. Unit testing seen as a waste of time. CI seen as a fun toy. They lack the experience to even notice the difference.

Maybe I'm becoming a curmudgeon, but I think many people would be well served by just googling " best practices", learning the acronyms like DRY, and just following them. And when you have gained some experience, sure, then you should question the wisdom and not follow it blindly.

Post reply on HN