While at UberConf 2010 I had the opportunity to attend a talk on AntiPatterns put on by Mark Richards. There are many AntiPatterns that exist in the software world, but Mark decided for this talk to focus on seven that he considers to be the most common. The following is a quick summary of Mark’s talk.
What are Patterns?
A pattern is a repeatable process that produces positive results each time. The main reason patterns were developed were to help improve communication between developers. Design patterns allow developers to use a common language to convey complex design ideas in just a few words.
What are AntiPatterns?
AntiPatterns are things we repeatedly do that produce negative results. The example Mark used was Gambling. Even though repeating this process produces negative results, we still do it again and again.
Factors that cause Anti-Patterns
- Haste – When project deadlines are tight, budgets are cut, team sizes are reduced, in these pressure situations we tend to ignore good practices.
- Apathy – Developers who really don’t care about the problem or the solution will almost always produce a poor design.
- Ignorance – When a developer either lacks knowledge of the domain or of the technology being used, that ignorance will result in antipatterns being introduced.
Seven Common AntiPatterns
There are many, many antipatterns in software design, but these are some of the most common.
1. Cargo Cult Programming
Using design patterns, techniques, or new technologies before really understanding them. Often as developers we jump into new technologies because they are interesting and we want to use them so we try to fit it in somehow, whether or not it is necessary for our project. This can lead to introducing a new technology or pattern when it is not needed and add unnecessary complexity.
- Don’t introduce a new technology unless it is absolutely necessary.
- When you see some code you aren’t sure of, take the time to read and understand it.
- Take the time to read and understand a technology you are currently using or considering using.
2. Lava Flow
An old area of the code is never updated or touched because everyone on the project is scared to touch it. Often this occurs because none of the original developers who wrote the code still work at the company. Some signs of lava flow are when you have large blocks of code commented out (“Why was this commented out, was it needed?”) and also when there is dead code still hanging around in the code base.
- Remove the commented out code.
- TDD with meaningful regression tests.
- Use tools to find dead code.
- Use interfaces to isolate the mess and also help locate dead code. If no path through the interface uses it, then it is safe to remove the code.
3. Parallel Protectionism
Code becomes so complicated and fragile that developers start copying the code and making changes to the copy rather than extending the original code out of a fear of breaking some existing functionality. Problems with this antipattern are that not only does it introduce duplicate code to the product, but now if a bug is found we now have two places to apply the fix instead of just one.
- Look for duplicate code at all levels.
- Split up complicated areas of the code into smaller chunks.
- Avoid creating complicated tricky code that developers will be afraid of. Focus on readability over clever tricky code.
4. Accidental Complexity
Introducing unnecessary complexity to a project out of ego by trying to out do other developers by accomplishing the same task in less lines of code (“Wow, look at this amazing piece of code I wrote!”). This can also happen by accident when a system is built one method at a time without any real overall plan.
- Focus on simple designs.
- Write readable code instead of “tricky code”.
- Frequent code reviews, or better yet, pair programming!
5. Object Orgy
An objects private values should never be exposed for modification unnecessarily. This is usually caused by poor encapsulation. For example: generating setters for every property in an object is NOT encapsulation. By always generating setters you are creating an object where it’s state can be invalidated at any time. The state of an object should be initialized by a constructor. Object Oriented programming is about object state, not getters and setters.
- Use proper encapsulation.
6. The Blob
A class or package in your system that does far too much. The catch all for any code where the developer is not sure where to put it, or is just too lazy to create a new class or package. Also what can happen is developers will put code somewhere else simply because it is smaller and easier to work with, even if it is not the correct location. This antipattern is usually caused by a lack of proper object oriented design skills on a team.
- Code reviews or pair programming.
- If you can’t describe a classes functionality with a single sentence, then it has too much responsibility.
7. Golden Hammer (Most Common)
Using the same technology or technique to solve every problem. For example: “I like Perl, Perl is the best language ever, it is perfect for any problem”.
- Be familiar with many programming languages, technologies, tools, and know each of their strengths and weaknesses.
- Set your personal preferences aside and always pick the best tool/technique for each problem you are trying to solve.