Introduction to Software Engineering/Architecture/Anti-Patterns

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Anti-Patterns and Code Smells[edit | edit source]

If design patterns are the good guys, then the anti-patterns are the bad guys. And sometimes a good guy can turn into a bad guy. This happens in Hollywood movies, but it also happens in software engineering.

The "golden hammer" is a favorite notion of this problem: you learned to use a tool in one context (the golden hammer), and now because you are so proud having learned how to use this complicated tool, all of a sudden you see golden nails everywhere.

A good example is the Singleton pattern: it is so easy that it is the first pattern most beginning software engineers understand and henceforth, since presumably it is a good guy, they will use it at every possible occasion. However, the problem with the Singleton is that it violates information hiding. Now information hiding is one of the sacred cows of modern software engineering, and it should be violated only when there is a really good reason for it. And just having learned about the Singleton pattern is not!

In software engineering, an anti-pattern is a pattern that may be commonly used but is ineffective and/or counterproductive in practice.[1][2] The term was coined in 1995 by Andrew Koenig,[3] inspired by Gang of Four's book Design Patterns, which developed the concept of design patterns in the software field. The term was widely popularized three years later by the book AntiPatterns,[4] which extended the use of the term beyond the field of software design and into general social interaction. According to the authors of the latter, there must be at least two key elements present to formally distinguish an actual anti-pattern from a simple bad habit, bad practice, or bad idea:

  • Some repeated pattern of action, process or structure that initially appears to be beneficial, but ultimately produces more bad consequences than beneficial results, and
  • A refactored solution exists that is clearly documented, proven in actual practice and repeatable.

By formally describing repeated mistakes, one can recognize the forces that lead to their repetition and learn how others have refactored themselves out of these broken patterns.

Examples of Anti-Patterns[edit | edit source]

To understand anti-patterns a little better, let us take a look at a few examples. By studying them you may recognize some violation against software engineering principles you may have committed yourself at one point in time. Some of these anti-patterns have very funny names.

Singleton Overuse[edit | edit source]

We have talked about this one: the first pattern you understood immediately, and you used it heavily. But beware it violates information hiding. Therefore the simple rule: when in doubt don't use it. My experience is that the larger the project, the more Singletons show up.

How do you detect Singletons? Look at the class diagram. All classes that have references to themselves (or their base class) are potential Singletons. If you want to get rid of them, Kerievsky shows you the medicine that cures this disease. [5]

Functional Decomposition[edit | edit source]

Although very popular once, in a modern object-oriented language there is no more space for functional decomposition. It is a remanent of procedural languages such as C or Pascal. Usually it indicates old software that was integrated into a new project or migrated.

This anti-pattern reveals itself in three ways: The names of classes sound like function names (e.g. CalculateInterest). Or the classes only have one action, i.e., they only do one thing. Or all class attributes are private (which is fine) but they are only used within the class. To detect this anti-pattern you can use a tool such as SourceMonitor.[6] It lists all class names, and also lists the functions.

Poltergeist[edit | edit source]

People like this anti-pattern because of its name. What it is, are classes that briefly appear to only disappear into oblivion. Either nobody knows what they really do, or they have very limited functionality. Usually they are not needed or can be absorbed in other classes.

Usually one recognizes this anti-pattern by class names that end in ’*controller’ or ’*manager’. Again a tool such as SourceMonitor can help to find this anti-pattern.

Often a consequence of "agile" approaches where cogitating is preferred to Design.

Spaghetti[edit | edit source]

Spaghetti code is like the noodles: it is very long. Although the noodles are delicious, code the longer it gets is not.

SourceMonitor can help you find this pattern, you simply look for methods with many lines of code. Refactoring usually is the cure here.

Blob[edit | edit source]

A blob is a class with a lot of attributes and methods. Quite often these are not even related. You can detect this smell with your favorite code analysis tool, by listing classes with lots of attributes and methods or many lines of code. Usually splitting this class into several smaller classes will help here.

Copy and Paste[edit | edit source]

As the name implies, somebody copied some code from some place to another place. It is the simplest way to duplicate functionality, but it should be avoided for many reasons. The simplest solution is to turn the code into a method instead, or use inheritance.

To detect almost identical code you can use a tool like PMD’s Tool Copy/Paste Detector.[7][8]

Lava Flow[edit | edit source]

What is lava flow? "A lava flow is a moving outpouring of lava, which is created during a non-explosive effusive eruption. When it has stopped moving, lava solidifies to form igneous rock."[9] In software engineering it means that the code is ancient, nobody has touched it for eons, and nobody has the guts to touch it (never touch a working class...).

You can find these classes by using your source control system. Simply list those classes that have not been checked out and modified for a long time.

Code Smells[edit | edit source]

Code smells are similar to anti-patterns, but not quite as formal. If code smells, then that smell can be o.k. (like some cheese) or it can be bad, possibly indicating a deeper problem. Kent Beck introduced the idea in the late 1990s and Martin Fowler made it popular in his book Refactoring. Improving the Design of Existing Code.[10] You can use tools, such as FindBugs, Checkstyle or PMD to find bad smells. Usually refactoring is used to remove the offending odor. Martin Fowler and Joshua Kerievsky, among others, provide the appropriate refactorings.

Duplicate Code[edit | edit source]

This smell is very similar to the Copy and Paste anti-pattern. You can use the PMD Tool Copy/Paste Detector [7] to find the problematic areas.

Long Method[edit | edit source]

Related to the Spaghetti anti-pattern, you can find it using SourceMonitor when sorting classes according to ’Avg Stmts/Meth’. Methods that have more then 50 lines are definitely suspicious.

Indecent Exposure[edit | edit source]

In the current Victorian age of information hiding, naturally indecent exposure is a bad thing. If a class has too many methods, or, god forbid, any public attributes then we talk about indecent exposure. You find this smell by checking for public methods of classes. If a class has more than 50% public methods, this may not conform to the information hiding policy.

Lazy Class[edit | edit source]

Reminds me of the Poltergeist anti-pattern: this is a class that does so little that it has no reason for existence. Try to absorb it into another class. To detect this smell use SourceMonitor: Sort 'Methods/Class' and look for classes that have fewer than two methods or look for classes with very few lines of code. They are suspect of being lazy.

Large Class[edit | edit source]

A large class is the opposite of a lazy class. You find it similarily, look for classes with too many methods, or too many statements. Usually a class should not have more than 30 methods or more than 400 statements. Also class with too many attributes could be large classes. Kerievsky shows several possible ways of reducing this smell.[5]

Really means not coding to code conventions. Look up Meyer, MISRA etc.

Known Anti-Patterns[edit | edit source]

There are many known anti-patterns. A list and brief description of some is provided for your entertainment.

Organizational anti-patterns[edit | edit source]

  • Analysis paralysis: Devoting disproportionate effort to the analysis phase of a project
  • Cash cow: A profitable legacy product that often leads to complacency about new products
  • Design by committee: The result of having many contributors to a design, but no unifying vision
  • Escalation of commitment: Failing to revoke a decision when it proves wrong
  • Management by perkele: Authoritarian style of management with no tolerance of dissent
  • Matrix Management: Unfocused organizational structure that results in divided loyalties and lack of direction
  • Moral hazard: Insulating a decision-maker from the consequences of his or her decision
  • Mushroom management: Keeping employees uninformed and misinformed (kept in the dark and fed manure)
  • Stovepipe or Silos: A structure that supports mostly up-down flow of data but inhibits cross organizational communication
  • Vendor lock-in: Making a system excessively dependent on an externally supplied component[11]

Project management anti-patterns[edit | edit source]

  • Death march: Everyone knows that the project is going to be a disaster – except the CEO. However, the truth remains hidden and the project is artificially kept alive until the Day Zero finally comes ("Big Bang"). Alternative definition: Employees are pressured to work late nights and weekends on a project with an unreasonable deadline.
  • Groupthink: During groupthink, members of the group avoid promoting viewpoints outside the comfort zone of consensus thinking
  • Smoke and mirrors: Demonstrating how unimplemented functions will appear
  • Software bloat: Allowing successive versions of a system to demand ever more resources
  • Waterfall model: An older method of software development that inadequately deals with unanticipated change

Analysis anti-patterns[edit | edit source]

  • Bystander apathy: When a requirement or design decision is wrong, but the people who notice this do nothing because it affects a larger number of people

Software design anti-patterns[edit | edit source]

  • Abstraction inversion: Not exposing implemented functionality required by users, so that they re-implement it using higher level functions
  • Ambiguous viewpoint: Presenting a model (usually Object-oriented analysis and design (OOAD)) without specifying its viewpoint
  • Big ball of mud: A system with no recognizable structure
  • Database-as-IPC: Using a database as the message queue for routine interprocess communication where a much more lightweight mechanism would be suitable
  • Gold plating: Continuing to work on a task or project well past the point at which extra effort is adding value
  • Inner-platform effect: A system so customizable as to become a poor replica of the software development platform
  • Input kludge: Failing to specify and implement the handling of possibly invalid input
  • Interface bloat: Making an interface so powerful that it is extremely difficult to implement
  • Magic pushbutton: Coding implementation logic directly within interface code, without using abstraction
  • Race hazard: Failing to see the consequence of different orders of events
  • Stovepipe system: A barely maintainable assemblage of ill-related components
Object-oriented design anti-patterns[edit | edit source]
  • Anemic Domain Model: The use of domain model without any business logic. The domain model's objects cannot guarantee their correctness at any moment, because their validation and mutation logic is placed somewhere outside (most likely in multiple places).
  • BaseBean: Inheriting functionality from a utility class rather than delegating to it
  • Call super: Requiring subclasses to call a superclass's overridden method
  • Circle-ellipse problem: Subtyping variable-types on the basis of value-subtypes
  • Circular dependency: Introducing unnecessary direct or indirect mutual dependencies between objects or software modules
  • Constant interface: Using interfaces to define constants
  • God object: Concentrating too many functions in a single part of the design (class)
  • Object cesspool: Reusing objects whose state does not conform to the (possibly implicit) contract for re-use
  • Object orgy: Failing to properly encapsulate objects permitting unrestricted access to their internals
  • Poltergeists: Objects whose sole purpose is to pass information to another object
  • Sequential coupling: A class that requires its methods to be called in a particular order
  • Yo-yo problem: A structure (e.g., of inheritance) that is hard to understand due to excessive fragmentation
  • Hurry up and wait: One or more asynchronous events triggered in the constructor of an object

Programming anti-patterns[edit | edit source]

  • Accidental complexity: Introducing unnecessary complexity into a solution
  • Action at a distance: Unexpected interaction between widely separated parts of a system
  • Blind faith: Lack of checking of (a) the correctness of a bug fix or (b) the result of a subroutine
  • Boat anchor: Retaining a part of a system that no longer has any use
  • Busy spin: Consuming CPU while waiting for something to happen, usually by repeated checking instead of messaging
  • Caching failure: Forgetting to reset an error flag when an error has been corrected
  • Cargo cult programming: Using patterns and methods without understanding why
  • Coding by exception: Adding new code to handle each special case as it is recognized
  • Error hiding: Catching an error message before it can be shown to the user and either showing nothing or showing a meaningless message
  • Hard code: Embedding assumptions about the environment of a system in its implementation
  • Lava flow: Retaining undesirable (redundant or low-quality) code because removing it is too expensive or has unpredictable consequences[12][13]
  • Loop-switch sequence: Encoding a set of sequential steps using a switch within a loop statement
  • Magic numbers: Including unexplained numbers in algorithms
  • Magic strings: Including literal strings in code, for comparisons, as event types etc.
  • Soft code: Storing business logic in configuration files rather than source code[14]
  • Spaghetti code: Programs whose structure is barely comprehensible, especially because of misuse of code structures

Methodological anti-patterns[edit | edit source]

  • Copy and paste programming: Copying (and modifying) existing code rather than creating generic solutions
  • Golden hammer: Assuming that a favorite solution is universally applicable (See: Silver Bullet)
  • Improbability factor: Assuming that it is improbable that a known error will occur
  • Not Invented Here (NIH) syndrome: The tendency towards reinventing the wheel (Failing to adopt an existing, adequate solution)
  • Premature optimization: Coding early-on for perceived efficiency, sacrificing good design, maintainability, and sometimes even real-world efficiency
  • Programming by permutation (or "programming by accident"): Trying to approach a solution by successively modifying the code to see if it works
  • Reinventing the wheel: Failing to adopt an existing, adequate solution
  • Reinventing the square wheel: Failing to adopt an existing solution and instead adopting a custom solution which performs much worse than the existing one
  • Silver bullet: Assuming that a favorite technical solution can solve a larger process or problem
  • Tester Driven Development: Software projects in which new requirements are specified in bug reports

Configuration management anti-patterns[edit | edit source]

  • Dependency hell: Problems with versions of required products
  • DLL hell: Inadequate management of dynamic-link libraries (DLLs), specifically on Microsoft Windows
  • Extension conflict: Problems with different extensions to pre-Mac OS X versions of the Mac OS attempting to patch the same parts of the operating system
  • JAR hell: Overutilization of the multiple JAR files, usually causing versioning and location problems because of misunderstanding of the Java class loading model

References[edit | edit source]

  1. Budgen, D. (2003). Software design. Harlow, Eng.: Addison-Wesley. p. 225. ISBN 0-201-72219-4.  "As described in Long (2001), design anti-patterns are 'obvious, but wrong, solutions to recurring problems'."
  2. Scott W. Ambler (1998). Process patterns: building large-scale systems using object technology. Cambridge, UK: Cambridge University Press. p. 4. ISBN 0-521-64568-9.  "...common approaches to solving recurring problems that prove to be ineffective. These approaches are called antipatterns."
  3. Koenig, Andrew (March/April 1995). "Patterns and Antipatterns". Journal of Object-Oriented Programming 8, (1): 46–48. ; was later re-printed in the: Rising, Linda (1998). The patterns handbook: techniques, strategies, and applications. Cambridge, U.K.: Cambridge University Press. p. 387. ISBN 0-521-64818-1.  "Anti-pattern is just like pattern, except that instead of solution it gives something thats looks superficially like a solution, but isn't one."
  4. Brown, William J.; Raphael C. Malveau, Hays W. "Skip" McCormick, Thomas J. Mowbray (1998). AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis. John Wiley & Sons, ltd. ISBN 0471197130. 
  5. a b Kerievsky, Joshua (2004). Refactoring to Patterns. Addison-Wesley Professional. ISBN 0321213351. 
  6. SourceMonitor
  7. a b PMD
  8. Detecting Duplicate Code with PMD’s CPD
  9. Lava
  10. Fowler, Martin (1999). Refactoring. Improving the Design of Existing Code. Addison-Wesley. ISBN 0-201-48567-2. 
  11. Vendor Lock-In at
  12. Lava Flow at
  13. "Undocumented 'lava flow' antipatterns complicate process". 2002-01-14. Retrieved 2010-05-03. 
  14. Papadimoulis, Alex (2007-04-10). "Soft Coding". Retrieved 2010-05-03. 

Further Reading[edit | edit source]

  • Laplante, Phillip A.; Colin J. Neill (2005). Antipatterns: Identification, Refactoring and Management. Auerbach Publications. ISBN 0-8493-2994-9. 
  • Brown, William J.; Raphael C. Malveau, Hays W. "Skip" McCormick, Scott W. Thomas, Theresa Hudson (ed). (2000). Anti-Patterns in Project Management. John Wiley & Sons, ltd. ISBN 0-471-36366-9. 
  • Brown, William J.; Raphael C. Malveau, Hays W. "Skip" McCormick, Thomas J. Mowbray (1998). AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis. John Wiley & Sons, ltd. ISBN 0471197130. 
  • Kerievsky, Joshua (2004). Refactoring to Patterns. Addison-Wesley Professional. ISBN 0321213351. 
  • Feathers, Michael (2004). Working Effectively with Legacy Code. Prentice Hall. ISBN 0131177052. 
Web sites

External Links[edit | edit source]