Live data from Hacker News

Code Smells: Iteration

blog.jetbrains.com

41–50 of 95 posts

Re: Code Smells: Iteration

#41
post #4

Earlier quoted context omitted.

It's obvious to some of us, but not all of us. I see things way worse than this on a fairly regular basis.

Sets have a very specific use case: they only contain unique values and (unless using a specific implementation) they don't have any defined order. Switching from arrays to sets just to get rid of an iteration doesn't sound like fixing a smell to me. Also, insertion, iteration and memory usage are less efficient for a set.

Importantly Sets have different semantics than Lists. Creating a set is an information losing process. A list converted to set cannot be recovered, but a set converted to a list is easily recovered.

I don't think this is handled well in TFA. Because of some dubious iteration at the call site, the author changes the semantics of getLoadNames(), blithely assuming that duplicates should not be allowed and order is not important.

The author mentions that the function is called at two other places. For all we know the original author was aware of Sets but chose List because it more correctly matched the use of the structure.

Re: Code Smells: Iteration

#42
post #13
post #2

At the risk of sounding arrogant, isn't this a bit obvious? To me, code smells are more about spotting when someone's been forced to do something a bit weird and convoluted. It's possibly the cleanest solution available given the immediate context, but this is actually a symptom (or "smell") that something is wrong with the wider design of the system. This article seems more about detecting choices around data struct…

It's worse than that. We have met the Enemy and the Enemy is us. Java, as introduced, claimed that nearly everything was an Object. What we got instead was nearly everything is a String. The Real WTF in this code is that all of the important information is passed around as Strings. The iterator and its source hint at this but she fixes the wrong problem. Ever has this been the way with Java. Despite having a statical…

One reason for this is the tight coupling in developers' minds between what I'd call "types" and "representations" (these terms are very overloaded, so others may use them in different ways).

Just because, say, a function name and a string are represented in memory the same way, that doesn't mean they are the same type; in particular there are many strings which aren't function names, and there are many operations (e.g. append) which make sense for strings but not for function names.

I can think of two things to blame for this:

- Languages which make it complicated, verbose and/or inefficient to introduce new, incompatible names for existing representations (i.e. nominal typing). For example, having to declare a new class in a new file with a private field, a constructor method and a getter method; that's a lot of boilerplate, and those method calls will incur a runtime cost. Haskell's `newtype` is pretty good in comparison, e.g. saying `newtype FunctionName = FN String` lets me use `FunctionName` in type signatures, I'll get a type error if I try to use a `String` as a `FunctionName` or vice versa, and I can construct and destruct a `FunctionName` using `FN` (e.g. `let x = FN "foo"`)

- Developers only coding for the happy path. When writing a test suite, it's important to test that bad outcomes are prevented, as well as just testing known-safe inputs. The same should apply to types: types should be used such that meaningless expressions are ill-typed, as well as just allowing known-good expressions to be well-typed.

Unfortunately these sorts of considerations tend to get derailed by similar-but-unrelated issues, e.g. 'YAGN a `FunctionName` interface because there's only one implementation'.

The end result of all this is Web applications concatenating together a bunch of "strings" which are actually HTML, plaintext, SQL, user input and URL parameters :(

Re: Code Smells: Iteration

#43
post #8

Earlier quoted context omitted.

That was my take as well. It's like seeing code with the same constant inlined in multiple places rather than centralized: // Use some inlined string as a magic code value: doStuff("Some Magic Code"); ... // Later on same inlined string: doOtherStuff("Some Magic Code"); versus: // Define it once: const GOOD_NAME_FOR_MAGIC_CODE = "Some Magic Code"; // Use it: doStuff(GOOD_NAME_FOR_MAGIC_CODE); ... // Use it somewhere…

Decreasing code duplication is good of course. But you need to be careful that the two pieces of code are inherently equal and not just by accident. Because once you consolidate the code, for example like you suggest, and somebody comes along and changes `GOOD_NAME_FOR_MAGIC_CODE` to something else, without being aware that it is used in multiple places, he might inadvertently make a change he did not mean to do. Tes…

Wouldn't this name change be immediately caught by the compiler?

Re: Code Smells: Iteration

#44
post #13

Earlier quoted context omitted.

It's worse than that. We have met the Enemy and the Enemy is us. Java, as introduced, claimed that nearly everything was an Object. What we got instead was nearly everything is a String. The Real WTF in this code is that all of the important information is passed around as Strings. The iterator and its source hint at this but she fixes the wrong problem. Ever has this been the way with Java. Despite having a statical…

Agree. I think we're all Stringly-typed developers. We use strings everywhere. We throw strings across system boundaries at will.

"We use strings everywhere."

That's bad.

"We throw strings across system boundaries at will."

That's neither good nor bad, it's just inevitable. The point of not using "strings" is that strings generally do not have the semantics of whatever it is you are really dealing with, because strings are just raw sequences of bytes and are generally too permissive for the specific type. For instance, if you have a URI, that comes with a list of restrictions for validity such as "can't start with a colon". Programming-language strings aren't URLs because they permit starting with invalid scheme declarations, or being empty.

However, when crossing system boundaries, you are exposed in some sense to the raw truth of the hardware, which is "raw sequences of bytes" is the only thing that really exists. When someone sends you something claimed to be a "URI", you really can't blindly count on that, if you want robust code you are going to have to validate that. Even if you work very hard and use higher-level abstractions to try to map things to higher-level types, you still have the problem that the semantics have to be an exact match for this to work; in one program the URI type only permits http and https, in another it permits arbitrary (valid) schemes, and there you go, there's a difference sufficient that you must validate.

To match semantics between two programs sufficiently that you can claim with a straight face that you really, truly aren't throwing "strings" across system boundaries requires incredibly tight coupling between all participating programs.

Re: Code Smells: Iteration

#45

Does anybody here really have to be told this? This is literally CS 101 (your first month of 61B at Cal). Why is this posted here?

I wasn't taught this in my class, I was always dealing with very small lists so iterating did not make much of a difference.

Re: Code Smells: Iteration

#46

Earlier quoted context omitted.

Decreasing code duplication is good of course. But you need to be careful that the two pieces of code are inherently equal and not just by accident. Because once you consolidate the code, for example like you suggest, and somebody comes along and changes `GOOD_NAME_FOR_MAGIC_CODE` to something else, without being aware that it is used in multiple places, he might inadvertently make a change he did not mean to do. Tes…

Wouldn't this name change be immediately caught by the compiler?

I assume wereHamster is referring to the value of the constant being changed, rather than the name.

Re: Code Smells: Iteration

#47

Does anybody here really have to be told this? This is literally CS 101 (your first month of 61B at Cal). Why is this posted here?

Are you the guy in that same class that points out how "obvious" everything is, in an attempt to prove how much smarter you are to the professor?

Re: Code Smells: Iteration

#48

Earlier quoted context omitted.

Decreasing code duplication is good of course. But you need to be careful that the two pieces of code are inherently equal and not just by accident. Because once you consolidate the code, for example like you suggest, and somebody comes along and changes `GOOD_NAME_FOR_MAGIC_CODE` to something else, without being aware that it is used in multiple places, he might inadvertently make a change he did not mean to do. Tes…

Wouldn't this name change be immediately caught by the compiler?

If you have one, yes.

But I meant when you change the definition of that binding (the right-hand side of the equal sign).

Re: Code Smells: Iteration

#49

Earlier quoted context omitted.

Agree. I think we're all Stringly-typed developers. We use strings everywhere. We throw strings across system boundaries at will.

If you're just using objects to represent groupings of strings and encapsulate behavior around converting them back to strings for output at some point, why not just operate on the strings instead of all the serialization / deserialization? Maybe enough of the quick stuff I do isn't enough to warrant more complex data structures, but I get pretty far into a problem with just dicts (in Python) and generally get annoye…

cat your_comment.txt | fold -w 80 -s | grep that | head -n 1 | sed "s/ have/'d be/" | sed 's/n/to/' | cut -d's' -f1-2

Re: Code Smells: Iteration

#50
post #46

Earlier quoted context omitted.

Wouldn't this name change be immediately caught by the compiler?

I assume wereHamster is referring to the value of the constant being changed, rather than the name.

I'd bet dollars to donuts the situations where you want it to change outnumber the ones where you don't by more than 10:1.
Post reply on HN