I like how the first three or so anti-patterns are in the exact opposite direction as the last three or so. The art of being a programmer is literally "don't waste time over-thinking things, but also don't ship under-thought trash". For all our fixation on simplistic and ease of use, programming is actually incredibly difficult and way more art than science.<p>And it's exactly this requirement of masterful manipulation of balance that makes me love this field so much and long to get better at it. Getting a handle on the artsy spirit of programming is really what separates the wheat from the chaff in terms of programmer skill. There is no formal programmer guild in real life, but if there was, and there was some sort of test a journey-man programmer must undergo in order to become a master programmer, it would be the test of being given a large project and then deciding correctly exactly how much technical debt to take on to be able to ship a product within a reasonable time-frame and yet have its internals not be complete unmanageable spaghetti.
> Fear of Adding Classes<p>I've seen this a lot, and is often made worse by attaching a load of unnecessary baggage/repurposing to classes.<p>For example, I've worked on PHP projects which, over time, have gained coding standards like:<p>- All classes should be in separate files, named to match the class name<p>- All classes should be built from a PHPSpec specification<p>- All classes should have their own test class<p>- No class can instantiate another, unless it's a "Manager" class which does only that. Everything else is dependency injected.<p>- Test classes can only instantiate their associated class; everything else must be mocked<p>And so on.<p>Now, each of these has its merits, but as each new practice was added, it increased the 'fear of adding classes', even if just subconsciously. Refactoring to break up classes became less and less common, since a simple code change would require:<p>- Whole new test classes (OK)<p>- New files (seems a bit like Java-envy, but OK)<p>- Injecting new instances wherever the old class was used (seems a bit overkill...)<p>- Mocking the behaviour of the first class in tests for the second, and vice versa (this is getting a bit silly...)<p>- Creating 'Manager' classes to instantiate the new classes (hmm...)<p>- Creating new test classes for these managers (erm...)<p>- Mocking the dependencies of the managers...<p>In the end, it was just far easier to just throw all new logic into existing classes, which grew and grew.
I always get a bit nervous when I see Knuth's quote about premature optimisation. While the points the author makes are valid, the fact that it gets bandied about as an out-of-context sound bite results in a lot of code getting written with a complete disregard for any optimisation whatsoever.<p>Another far more common antipattern that isn't mentioned here is premature abstraction. You see a lot of this in enterprise .NET codebases -- such as the widespread "best practice" to build ineffective and obstructive abstraction layers "just in case you might want to swap out Entity Framework for a web service."
If you're a dev and have never read these two wikipedia links, I highly recommend it.<p><a href="http://en.wikipedia.org/wiki/Code_smell#Common_code_smells" rel="nofollow">http://en.wikipedia.org/wiki/Code_smell#Common_code_smells</a><p><a href="http://en.wikipedia.org/wiki/Anti-pattern#Examples" rel="nofollow">http://en.wikipedia.org/wiki/Anti-pattern#Examples</a>
You forgot the most important anti-pattern of all:<p>"Not Invented Here".<p>The urge to rewrite things that you encounter is strong in software engineers, and you should always be suspicious when you find yourself thinking "I could do this so much better." Especially when it's true!
I think example 9. (the stack that wraps a linked list) is not a necessarily an antipattern. Removing degrees of freedom and adding obvious constraints make systems simpler and easier to comprehend.
Surely the purpose of the LabStack example is to restrict the interface of a LinkedList to that of a Stack? Defining a new type to present a more restricted interface is not useless... it helps one reason about what has or hasn't been done to an object.
I'm a little confused. I'd say that an anti-pattern is something one can avoid. Sure, I can think about every optimization I'm doing, and if I already know well enough that I'll need it and doing it right. But I can't really avoid discussing about something that is unimportant in my eyes, because the person who will discuss about it usually thinks it's important. I'd say that in the "bike shedding" regard my anti-pattern would be that I ignore some complaint as unimportant because I still don't understand it well enough.<p>Other things are also hard to avoid by myself, like<p>- God Classes (I could refactor here, but then the anti-pattern is fear of refactoring)<p>- Management by Numbers (I'm not a manager, what can I do about it? Actually I'm happy if my management is already that good that they have numbers. Nothing is more horrible than management who doesn't tell you explicitly what they want and then complains about details for half a year, then starts with the next project without declaring the last one to be finished or anything. I'd say numbers are good, finding the right ones is tricky, though.)<p>- Useless classes are avoided by simply not writing them? No, they develop when code gets refactored and nobody had looked at the responsibility of that specific class for some time. Nobody writes classes without having a goal for them in mind. Mostly calling methods of another class is fine. It happens in design patterns like Observer, Delegator, or Compositor.
I read this many years ago. Let me find the source.<p>Edit: I can't find it. Anyone else remember reading this? The mysql job queue reference was from a popular article that went out about it at the time<p>Edit 2: the job queue article is from 2011.<p>Edit 3: still can't find it. But I know every part of this article before seeing it ... I tested myself and remembered all the details... Where is this thing from?<p>Still can't find it. My confidence in the permanence of the web is pretty destroyed right now. I can't even find references to it existing.
> God Class<p>I don't understand how to avoid this even if you break it up in smaller classes. You still need a point of entry where the logic begins and where it is decided which components to use. ThIs always means some kind of Manager or Main class for me. How do I fix it?
Enjoyed this list. Over the years I've become better and better at spotting these issues, but even still sometimes it's hard to see them creeping up on you.<p>The worst for me these days is analysis paralysis. I'm currently working on my own so I don't have anyone around to bounce ideas off. For smaller tasks it's not a problem, but there are bigger design decisions that have ended up taking longer than probably should. When you're left to figure them out on your own it takes a lot longer to convince yourself of the "better" way of doing something.
"It seems that perfection is attained, not when there is nothing more to add, but when there is nothing more to take away."<p>Great quote - It reminds me of the story of when Michelangelo unveiled the statue of David, someone asked him how he managed to create such a masterpiece and Michelangelo answered "It was simple, I just chipped away all the rock that wasn't David".
Is <a href="https://en.wikipedia.org/wiki/Facade_pattern" rel="nofollow">https://en.wikipedia.org/wiki/Facade_pattern</a> a God class? I like the idea if it only delegates to other classes. Its downside is the dependencies to many classes.
#5 is a classic example of the Expression Problem[1]. Are you trying to add more shapes or more functions that operate on shapes?<p><a href="http://c2.com/cgi/wiki?ExpressionProblem" rel="nofollow">http://c2.com/cgi/wiki?ExpressionProblem</a>
Having worked for big corporations in Europe, I'd like to see manager types spend 10% of time technical people spend on self-optimising themselves, their working environment, post-mortems, understanding antipatterns, productivity etc.
It's nice to notice that top three actually does not have anything to do with programming. Those are absolutely general issues when ever doing anything at all.
> "Magic Numbers and Strings"<p>I don't know about this one...we need something have a chuckle (or cry) about over beer after work, and to make sure software archaeologists in 100 years time have an interesting job (not to mention plenty of opportunities to write blog-spam)!