Live data from Hacker News

Code Smells: Iteration

blog.jetbrains.com

61–70 of 95 posts

Re: Code Smells: Iteration

#61
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…

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…

You can go further with the type/representation dichotomy.

An obvious example is printing: All of a sudden, you need to convert an object of that type to a representation that can be read. Read by what? Humans? Other code? Both to some extent? The representation is dependent upon both the original type and the intended recipient.

(In Lisp, "readable" means "acceptable to the read function, which parses Lisp expressions"; some objects, such as compiled functions, inherently cannot become "readable" in this sense, so they get printed in an unreadable form. Should that be a type error?)

You can even have layers of representation: Length is a type of value, whether it's expressed in inches or centimeters or light-seconds is a representation, and whether it's in ints or floats or strings is another layer to the representation. You can add inches to centimeters with the right conversion, much like you can add numerical values represented ints and strings with the right conversions. The conversions just have to be at the right layer of representation.

Your ideas sound a lot like the original Hungarian notation, BTW: If your language-level types are representations (as in, your type system says int and float, as opposed to semantic notions like pixels-from-edge or alpha-percentage) you can encode the real type information in variable names. People mutilated this to encoding language-level type information in variable names, which is utterly pointless and potentially harmful.

Re: Code Smells: Iteration

#62
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…

It's not just Java! I see this all the time in C and C++ as well. Developers seem to be afraid to use types as they were intended. For example, look up any OpenGL question on StackOverflow and you'll see things like what should be an array of 3D vertices with separate x, y, and z components passed as a 1D array of floats. In C++ we see quite a bit of abuse of std::pair instead of just making a fucking struct to hold…

It's an educational problem, Chandler Caruth of LLVM gave a really good talk on POD type slicing and how useful it can be. More to the point that for PODs it's supported in the standard. I do agree on the abuse of pair... pair is there for implementers primarily and shouldn't be used outside of deliberately templated code. Ditto tuple.

That said... with C++17 destructuring... it's a lot less painful since you can do the equivalent to a std::tie in a single line.

Re: Code Smells: Iteration

#63

Earlier quoted context omitted.

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

If you're going to be snarky, fix the useless use of cat.

Re: Code Smells: Iteration

#64
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.

This whole potential problem is one of the reasons the particular example isn't that great. It's overhyped in Java-land where some people treat naked strings like lepers but in places like Clojure-land you'd get a lot of people saying "Just use a keyword" for both places. The keyword's name is its value. It's immutable. An IDE should be able to find all uses of it, or there's always 'ag'. If you really want that coupling behavior, change the interface of the thing you're calling to require conformance to a schema. The simplest way in Java is probably just by taking an enum instead of a string, but there are richer ways (especially outside of Java) worth looking into if you're needing a string value eventually in the implementation since you'll run into the other Java-ism of making a complicated enum class instead of just using enums like keywords with their string value being their actual name value.

Re: Code Smells: Iteration

#65
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…

I think the blog post is not so much about advanced code smell mitigation strategies, but rather about highlighting the features of IntelliJ.

Re: Code Smells: Iteration

#66
post #14

Hashing is indexing and there is no faster and memory efficient index than an array (not vector) of sorted items. Iteration is the best if you can organize your data for it

Not sure what you're trying to get at. Indexing by surrogate index, yes. Indexing by value? That doesn't help. The best you can do is binary search -- O(log n). Hash-based structures are average amortized constant time -- O(1). This works because the key is a function of the value, rather than a surrogate key which is unrelated to the value.

Straight from Wikipedia:

"In many situations, hash tables turn out to be more efficient than search trees or any other table lookup structure. For this reason, they are widely used in many kinds of computer software, particularly for associative arrays, database indexing, caches, and sets."

https://en.wikipedia.org/wiki/Hash_table

Re: Code Smells: Iteration

#67
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…

It's not just Java! I see this all the time in C and C++ as well. Developers seem to be afraid to use types as they were intended. For example, look up any OpenGL question on StackOverflow and you'll see things like what should be an array of 3D vertices with separate x, y, and z components passed as a 1D array of floats. In C++ we see quite a bit of abuse of std::pair instead of just making a fucking struct to hold…

One problem in C++ is if you define a struct then you have to define a bunch of operators yourself (operator<, etc.) which gets annoying after you've realized you've needed them a bunch of times.

Re: Code Smells: Iteration

#68
post #55

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…

The mess of duplicated code is much harder to untangle than de-consolidating code. Especially because subtle differences WILL leak into duplicated code and you won't know if it's on purpose or not. If a dev can't be bothered to figure out where different pieces of code use a variable and whether the change is appropriate for them, do you think they will have the foresight to search for the duplicated code when they n…

If they would need to search for the duplicated code and change it in more than one place, there's something shared to factor out. If the two pieces of code are actually only accidentally the same, changing them independently should be the right thing.

Re: Code Smells: Iteration

#69
post #60

boolean hasName(String storedName) { return getLoadNames().\ contains(storedName); } > That’s it. No more looping, just a simple check. And how is set.contains implemented? https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/... wraps https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/... public boolean contains(Object o) { return map.containsKey(o); // map is HashMap } public boolean containsKey(Obj…

But the loop your pointing out is only over the hash bucket, not the entire set. Ideally it will only have a single element.

Re: Code Smells: Iteration

#70
post #60

boolean hasName(String storedName) { return getLoadNames().\ contains(storedName); } > That’s it. No more looping, just a simple check. And how is set.contains implemented? https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/... wraps https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/... public boolean contains(Object o) { return map.containsKey(o); // map is HashMap } public boolean containsKey(Obj…

But the loop your pointing out is only over the hash bucket, not the entire set. Ideally it will only have a single element.

Good point :)
Post reply on HN