Live data from Hacker News

Good refactoring vs. bad refactoring

builder.io

61–70 of 154 posts

Re: Good refactoring vs. bad refactoring

#61
post #10

Oh god the ‘object oriented’ refactor. I wish everyone who had OO thrust upon them in the early 2000s received some explicit communication that what they were taught is essentially a hoax and bears no resemblance to Alan Kay’s original intention

To be fair OOP of today is much more similar to Simula then to Small Talk, reading the wikipedia I can see almost 1:1 mapping including the modeling philosophy and all that, people mostly yoinked the name from Alan Kay.

Re: Good refactoring vs. bad refactoring

#62
post #22
post #15

Earlier quoted context omitted.

The dig against FP is weird since the "good refactor" also uses FP, just a built in one in JS. Which I agree is better, but mostly by being built in and idiomatic, it's still exactly as functional.

I think that was the point - the library added nothing, the same thing could be done with pure javascript.

If that was the point, then that paragraph needs to be rewritten badly.

Re: Good refactoring vs. bad refactoring

#63
post #43
post #30

The first example of a good refactor is a meh refactor at best, and possibly a bad refactor. Array methods such as map or filter are not "more conventional" in javascript; they are "as conventional" as for-loops, and arguably less "conventional", given how for-loops have been around since the introduction of the language. They are also inevitably more expensive than for-loops (every cycle creates an anonymous functio…

> every cycle creates an anonymous function No, that's not how it works. The function is evaluated once before the call and passed as an argument, then internally reused. Also, you're microptimizing. Prioritizing supposed performance over readability. And yes, for-loops and mutable structures are more error prone than map-filter-reduce. The original is OK but could be better.

> No, that's not how it works. The function is evaluated once before the call and passed as an argument, then internally reused.

Yes, sorry; you are right of course.

Re: Good refactoring vs. bad refactoring

#64
post #5

The first example complained about the refactor appealing to functional thinkers (implying that it would be difficult to grok by the existing devs), but then the “improved” version is virtually the same save for the (unnecessary?) use of Ramda in the first. And while many devs are resistant to try functional ways, this first example reads so much better than the original code that I find it impossible to believe that…

(Raises hand.) I prefer the for loop. Pushing items to an array is idiomatic Javascript for creating an array. An if statement is an idiomatic way to do it conditionally. It's also easier to debug. The map and filter methods are nice too, but they're for one-liners.

I also prefer the loop, I would negate the condition and use continue, but otherwise leave it unchanged. I don't have a problem with the functional version but it doesn't scan as well to me.

Re: Good refactoring vs. bad refactoring

#65

I got as far as here: > If you need to introduce a new pattern, consider refactoring the entire codebase to use this new pattern, rather than creating one-off inconsistencies. Putting aside the mis-application of "pattern" (which _should_ be used with respect to a specific design problem, per the Gang of Four), this suggestion to "refactor the entire codebase" is impractical and calcifying. Consistency increases legi…

It is not just about legibility. Developers are trying to repeat patterns they see around. If you do not refactor previous places, they will reproduce the outdated pattern. Plus, it makes code reviews frustrating.

Re: Good refactoring vs. bad refactoring

#66
post #16

That OO refactor isn’t actual OO. The tell tale sign is that it is named by what it does rather than what it is (verb vs noun) and the -or ending in the name [0]. It’s just a function masquerading as a class. The better refactor to introduce OO concepts would have been to introduce an isAdult function on the user class and maybe a formatted function. This + the functional refactor probably would have made for the bes…

> u.isAdult()

Being adult is not a property of the user but of the jurisdiction that the user is in. In some places or some purposes it is 18 but it could be, e.g., 21 for other purposes.

If you software is not going to just run on the USA it is not a good idea to implement isAdult in the user but in a separated entity that contains data about purpose and location.

Re: Good refactoring vs. bad refactoring

#67
post #60

Earlier quoted context omitted.

I think it’s widely accepted that refactors should not change behavior. That’s my experience, at least.

Huh, I guess that's true, even on wikipedia. I will have to stop using the word then. Though I'm pretty sure most people use it in day-to-day with much more abandon.

The metaphor, I think, is that your code is a mathematical function, and, to be even more specific and "toy example" about it, let's say it's a polynomial. If the old code was

x^2 + x z + y x + y z

then you notice that you can express the same polynomial as:

(x + y)*(x + z)

It's still the same polynomial, but you "separated concerns", turning it into a product of two simpler factors.

Similar ideas apply to sets of tuples. Perhaps you were given

{(1, 1), (1, 4), (2, 1), (2, 4), (3, 1), (3, 4)}

and you notice that this can be expressed more simply as the Cartesian product:

{1, 2, 3} x {1, 4}

Again, a literal factoring. You can imagine how variations of this idea would apply to database tables and data structures.

That's where I think the word "refactor" comes from.

Re: Good refactoring vs. bad refactoring

#68
post #60

Earlier quoted context omitted.

Huh, I guess that's true, even on wikipedia. I will have to stop using the word then. Though I'm pretty sure most people use it in day-to-day with much more abandon.

The metaphor, I think, is that your code is a mathematical function, and, to be even more specific and "toy example" about it, let's say it's a polynomial. If the old code was x^2 + x z + y x + y z then you notice that you can express the same polynomial as: (x + y)*(x + z) It's still the same polynomial, but you "separated concerns", turning it into a product of two simpler factors. Similar ideas apply to sets of tu…

My man, thanks for the explanation but I understand the concept I just didn't agree on definition.

Re: Good refactoring vs. bad refactoring

#69
post #68

Earlier quoted context omitted.

The metaphor, I think, is that your code is a mathematical function, and, to be even more specific and "toy example" about it, let's say it's a polynomial. If the old code was x^2 + x z + y x + y z then you notice that you can express the same polynomial as: (x + y)*(x + z) It's still the same polynomial, but you "separated concerns", turning it into a product of two simpler factors. Similar ideas apply to sets of tu…

My man, thanks for the explanation but I understand the concept I just didn't agree on definition.

Sure. Whenever you post on a forum it's half for anybody else reading, right? I just thought it was interesting to consider the underlying metaphor; maybe people don't think about it. Metaphors, connotations, etymologies -- I find these interesting.

Re: Good refactoring vs. bad refactoring

#70
post #66
post #16

That OO refactor isn’t actual OO. The tell tale sign is that it is named by what it does rather than what it is (verb vs noun) and the -or ending in the name [0]. It’s just a function masquerading as a class. The better refactor to introduce OO concepts would have been to introduce an isAdult function on the user class and maybe a formatted function. This + the functional refactor probably would have made for the bes…

> u.isAdult() Being adult is not a property of the user but of the jurisdiction that the user is in. In some places or some purposes it is 18 but it could be, e.g., 21 for other purposes. If you software is not going to just run on the USA it is not a good idea to implement isAdult in the user but in a separated entity that contains data about purpose and location.

With proper OO you could still implement that on the user object.

    boolean isAdult() {
        return this.age >= this.location.ageOfAdulthood();

        // or this.location.isAdult(this.age);  pick your poison!
    }

…anyway it’s just an example of how to introduce OO concepts. As everything in programming it depends
Post reply on HN