Collections Hell anti-pattern

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
Quizatzhaderac
Posts: 1827
Joined: Sun Oct 19, 2008 5:28 pm UTC
Location: Space Florida

Collections Hell anti-pattern

Postby Quizatzhaderac » Tue Oct 29, 2013 9:38 pm UTC

I was looking for this in lists of anti-patterns and I couldn't find anything, so I've decided to name it "Collections Hell". I was wondering if anybody had named this? If not, is it rare? If rare, is it just people at my company that did it?

The principles of the collections hell anti-pattern are as follows:

1) Minimize defining classes; they create social discord among the pixies that produce the magic smoke. All classes can be represented as a Map<String,Object>, with the keys taking place of the member names and the values the members' contents.
1.1) If possible, avoid actually specifying the map is of the type <String,Object>; that's the only kind of map one should have anyway.
1.2) This works recursively; see how many layers of maps you can have in maps.
1.3) Just as this frees your members from being bound to classes, you are now free to put the semantics in wide and disparate places.
1.4) If you need an actual map, it can be represented as a list of maps where each map has the keys "key" and ""value"
1.5) When used widely, this has the benefit of producing consistent method signatures (everything takes and returns maps)
2) It's always appropriate to alter objects by passing them as the first object to a method.
2.1) Language is irrelevant to this.
2.2) The actual object the method is associated to need not have any bearing on the subject your method operates on.
3) Specifying types clutters up the code and makes compile time errors more likely.
3.1) This also frees you to add different types to the collection in the future.
3.2) If you must specify type on a nested collection, specify only the first level and use wildcards for the lower levels. Do not stop to learn how wildcards work.
4) The best way to specify type is with an unchecked cast when getting something out of a collection.
5) Avoid using comments, good code should be self documenting.
The thing about recursion problems is that they tend to contain other recursion problems.

heatsink
Posts: 86
Joined: Fri Jun 30, 2006 8:58 am UTC

Re: Collections Hell anti-pattern

Postby heatsink » Tue Oct 29, 2013 10:48 pm UTC

Points 1 and 3 sound like Python classes. A Python class instance is a Map<String, Object> with some syntactic sugar layered on top. (That's true in the common case, I'm leaving out some details.) Lisp is similar, except instead of a Map they use Tuple<Object, Object>.

Of course I'm being facetious, but it's a fairly common perception that programming languages are for telling computers what to do. Ergo, a language is more powerful if it gives you more ways of telling a computer what to do. So, the reasoning goes, use the most general data type possible and revel in your power! Why in the world would you want to restrict what you can do with your data?

korona
Posts: 495
Joined: Sun Jul 04, 2010 8:40 pm UTC

Re: Collections Hell anti-pattern

Postby korona » Tue Oct 29, 2013 11:47 pm UTC

Point 5 is actually not that wrong. Comment about ideas (WHY the code does something) and not technique (HOW the code does something).
A comment like "a zero in the id field marks the entry as deleted" or "note that xxx must be called before running this function otherwise yyy breaks" are useful. Comments like "/* this function computes the shortest path in a graph */ vector<Vertex> computeShortedPath(Graph g, Vertex src, Vertex dest)" or "the following block computes 5^n mod 17" are not.

User avatar
skeptical scientist
closed-minded spiritualist
Posts: 6142
Joined: Tue Nov 28, 2006 6:09 am UTC
Location: San Francisco

Re: Collections Hell anti-pattern

Postby skeptical scientist » Wed Oct 30, 2013 2:29 am UTC

korona wrote:Point 5 is actually not that wrong. Comment about ideas (WHY the code does something) and not technique (HOW the code does something).
A comment like "a zero in the id field marks the entry as deleted" or "note that xxx must be called before running this function otherwise yyy breaks" are useful. Comments like "/* this function computes the shortest path in a graph */ vector<Vertex> computeShortedPath(Graph g, Vertex src, Vertex dest)" or "the following block computes 5^n mod 17" are not.

I agree that why comments are often useful, whereas how comments are often not useful. But one thing you left out is that it is also often useful to comment about WHAT the code does, especially for function and class declarations. (Incidentally, both of your examples of "bad comments" are about what the code does, not about how the code does it.) For example, example, your comment "this function computes the shortest path in a graph" is not helpful because that is obvious from the function and variable names, but what *would* be helpful is knowing things like what happens if there are multiple shortest paths, what happens if there is no path from src to dest, whether I can pass in a network (which is a subclass of graph) and get the cheapest path, and so on. These sorts of things would be too unweildy to put into the function name, but would be extremely helpful things to put into comments at the functio declaration.

Comments of the form "the following block computes foo" may also be useful, assuming
  1. it is clear or explained why it is useful to compute foo,
  2. it is not clear from looking at the block that it is computing foo, and
  3. it does not make sense to write a function to compute foo.
Here's an example of a helpful comment of this form:

Code: Select all

float fastInvSqrt(float x) {
  long i;
  float y;

  // The following block computes a good starting approximation to 1 / sqrt(x)
  i = *(long*)&x;
  i = 0x5f3759df - (i >> 1);
  y = *(float*)&i;

  // Compute a single iteration of Newton's method
  y = y * (1.5F - .5F * x * y * y);   
 
  return y;
}

Here it is clear from context that we want to approximate 1/sqrt(y) to use as a starting guess for Newton's method, and someone looking at the block would have no idea that the result is an approximation of 1/sqrt(y) without the comment. One could argue that this block should be replaced by a call to a suitably named inlined function, but it doesn't seem unreasonable to leave it as a block.

Of course, it would also be useful and appropriate to have a comment explaining the why behind the line "i = 0x5f3759df - ( i >> 1 );" (or more likely a comment with a link to said explanation), but simply knowing what those three lines do is extremely helpful for understanding how the function works.

* * *


To the OP: I would guess that pattern is rare, as OOP seems to be generally accepted as a good coding practice, and OOP says that classes are good.
I'm looking forward to the day when the SNES emulator on my computer works by emulating the elementary particles in an actual, physical box with Nintendo stamped on the side.

"With math, all things are possible." —Rebecca Watson

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Collections Hell anti-pattern

Postby Jplus » Wed Oct 30, 2013 9:29 am UTC

I suspect that "collections hell" anti-pattern was started by someone who was used to the possibility to treat objects as dictionaries (like in Javascript, Lua...) and who was disappointed not to find the same possibility in Java or C# (either of which I suspect is the language your company works with). Or it might have been somebody coming from pre-class PHP, who was used to using arrays as dictionaries for all datastructure purposes. I suspect this anti-pattern is actually quite common in old PHP code, especially among the less skilled programmers.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

User avatar
Quizatzhaderac
Posts: 1827
Joined: Sun Oct 19, 2008 5:28 pm UTC
Location: Space Florida

Re: Collections Hell anti-pattern

Postby Quizatzhaderac » Wed Oct 30, 2013 3:51 pm UTC

korona wrote:Point 5 is actually not that wrong.
I wouldn't say point 5 is categorically wrong, but it's a terrible philosophy in the context of the rest of the points, where over half of the self documentation has been taken out. For example in java

Code: Select all

//good example
public class ProperContext {
....
   public Bar someMethod(Foo arg){
   ....

//bad example
public class CallingContext {
....
//zero members that are used in someMethod
....
   public Map someMethod(Map properContext, Map arg) {
   //code that requires maps with specific keys and value types
   ....
In the bad example,we know someMethod takes a map, and a map, and returns a map.

Now that I think about this more, it's really more of a collection of anti-patterns I've seen from a small group of developers.
The thing about recursion problems is that they tend to contain other recursion problems.

D-503
Posts: 84
Joined: Sun Apr 15, 2012 11:35 pm UTC

Re: Collections Hell anti-pattern

Postby D-503 » Thu Oct 31, 2013 10:07 am UTC

What kind work does your company do? I can see benefits to pattern 1 for dealing with distributed systems and bridging between programming languages. A problem with classes is that they act as a grate if you have a large system with data from lots of different places flowing through it. A change in one place needs to be reflected in every environment where the data is used. However, if everything is generalized to use maps, you can send augmented objects down the pipes and they'll get to the other end in tact.

User avatar
Quizatzhaderac
Posts: 1827
Joined: Sun Oct 19, 2008 5:28 pm UTC
Location: Space Florida

Re: Collections Hell anti-pattern

Postby Quizatzhaderac » Thu Oct 31, 2013 3:47 pm UTC

A bank, mostly java and C#. Our legacy code pretty much passes xmls. In general these maps should-be-objects aren't sent through pipes as is.
The thing about recursion problems is that they tend to contain other recursion problems.

Story
Posts: 78
Joined: Wed Aug 26, 2009 9:03 pm UTC

Re: Collections Hell anti-pattern

Postby Story » Fri Nov 08, 2013 5:04 pm UTC

I'd say the only 2.2 and 5 are unambiguously bad. The rest is more of a convention issue.

The style you described is actually built into the language in Python, Javascript, etc. The problem comes when people try to use it in languages that weren't designed for it, like Java. But I can understand why they'd want to do it. Heck, I'd say that it is useful sometimes in Java, just not all the time.


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 5 guests