What is an anti-pattern?
Asked Answered
M

15

273

I am studying patterns and anti-patterns. I have a clear idea about patterns, but I don't get anti-patterns. Definitions from the web and Wikipedia confuse me a lot.

Can anybody explain to me in simple words what an anti-pattern is? What is the purpose? What do they do? Is it a bad thing or good thing?

Metaphrase answered 11/6, 2009 at 11:33 Comment(3)
sourcemaking.com/antipatternsDurian
martinfowler.com/bliki/AntiPattern.htmlDurian
The C2 wiki - the original wiki site, by Ward Cunningham - has a lot of material about programming patterns, and a page about AntiPatterns. (Probably visit the start page first if you are unfamiliar with the site's conceptual design. It is far removed from what people think "wiki" means these days, though it obviously inspired the architecture for platforms like Wikipedia and Wikia.)Venture
C
340

Anti-patterns are certain patterns in software development that are considered bad programming practices.

As opposed to design patterns which are common approaches to common problems which have been formalized and are generally considered a good development practice, anti-patterns are the opposite and are undesirable.

For example, in object-oriented programming, the idea is to separate the software into small pieces called objects. An anti-pattern in object-oriented programming is a God object which performs a lot of functions which would be better separated into different objects.

For example:

class GodObject {
    function PerformInitialization() {}
    function ReadFromFile() {}
    function WriteToFile() {}
    function DisplayToScreen() {}
    function PerformCalculation() {}
    function ValidateInput() {}
    // and so on... //
}

The example above has an object that does everything. In object-oriented programming, it would be preferable to have well-defined responsibilities for different objects to keep the code less coupled and ultimately more maintainable:

class FileInputOutput {
    function ReadFromFile() {}
    function WriteToFile() {}
}

class UserInputOutput {
    function DisplayToScreen() {}
    function ValidateInput() {}
}

class Logic {
    function PerformInitialization() {}
    function PerformCalculation() {}
}

The bottom line is there are good ways to develop software with commonly used patterns (design patterns), but there are also ways software is developed and implemented which can lead to problems. Patterns that are considered bad software development practices are anti-patterns.

Costanzo answered 11/6, 2009 at 11:36 Comment(7)
any other examples of Anti-Patterns beside GodObject?Tearing
@Tomasz Programming Pasta serves is one such example. It's best generalized as poor encapsulation between many small objects. Consider it the opposite of the God object en.wikipedia.org/wiki/Spaghetti_codeScarrow
@Tomasz anything that is bad, but is done by some people, is an antipattern. E.g., try: <do something>; except: pass may be the Cardinal Sin antipattern in Python. See this: realpython.com/blog/python/…Beecher
Can a Singleton be considered an anti-pattern because it makes it harder to mock and run tests in parallel (since all tests use and mutate the same singleton, resulting in inconsistencies)?Fite
@Fite it depends if the final purpose of your program is its ability to be tested in parallel... (And in the particular case you mention: that's a reentrant problem that should either be corrected or documented). Singleton is a pattern that should be used for what it's good at.Document
great example, thanks, this is very clarifying. Now I must go and rewrite all of my code...Sindee
@Fite in addition to bad coding, antipattern is also considered any pattern used in the wrong place to solve a problem. Singleton is a good pattern but if you use it for a DB connection it might become anti-pattern. Strategy is an excellent pattern but also in the wrong place it is considered anti-pattern, and so...Barbitone
J
85

Whenever I hear about Anti-patterns, I recollect another term viz. Design smell.

"Design smells are certain structures in the design that indicate violation of fundamental design principles and negatively impact design quality”. (From "Refactoring for Software Design Smells: Managing technical debt")

There are many design smells classified based on violating design principles:

Abstraction smells

Missing Abstraction: This smell arises when clumps of data or encoded strings are used instead of creating a class or an interface.

Imperative Abstraction: This smell arises when an operation is turned into a class.

Incomplete Abstraction: This smell arises when an abstraction does not support complementary or interrelated methods completely.

Multifaceted Abstraction: This smell arises when an abstraction has more than one responsibility assigned to it.

Unnecessary Abstraction: This smell occurs when an abstraction that is actually not needed (and thus could have been avoided) gets introduced in a software design.

Unutilized Abstraction: This smell arises when an abstraction is left unused (either not directly used or not reachable).

Duplicate Abstraction: This smell arises when two or more abstractions have identical names or identical implementation or both.

Encapsulation smells

Deficient Encapsulation: This smell occurs when the declared accessibility of one or more members of an abstraction is more permissive than actually required.

Leaky Encapsulation: This smell arises when an abstraction “exposes” or “leaks” implementation details through its public interface.

Missing Encapsulation: This smell occurs when implementation variations are not encapsulated within an abstraction or hierarchy.

Unexploited Encapsulation: This smell arises when client code uses explicit type checks (using chained if-else or switch statements that check for the type of the object) instead of exploiting the variation in types already encapsulated within a hierarchy.

Modularization smells

Broken Modularization: This smell arises when data and/or methods that ideally should have been localized into a single abstraction are separated and spread across multiple abstractions.

Insufficient Modularization: This smell arises when an abstraction exists that has not been completely decomposed, and a further decomposition could reduce its size, implementation complexity, or both.

Cyclically-Dependent Modularization: This smell arises when two or more abstractions depend on each other directly or indirectly (creating a tight coupling between the abstractions).

Hub-Like Modularization: This smell arises when an abstraction has dependencies (both incoming and outgoing) with a large number of other abstractions.

Hierarchy smells

Missing Hierarchy: This smell arises when a code segment uses conditional logic (typically in conjunction with “tagged types”) to explicitly manage variation in behavior where a hierarchy could have been created and used to encapsulate those variations.

Unnecessary Hierarchy: This smell arises when the whole inheritance hierarchy is unnecessary, indicating that inheritance has been applied needlessly for the particular design context.

Unfactored Hierarchy: This smell arises when there is unnecessary duplication among types in a hierarchy.

Wide Hierarchy: This smell arises when an inheritance hierarchy is “too” wide indicating that intermediate types may be missing.

Speculative Hierarchy: This smell arises when one or more types in a hierarchy are provided speculatively (i.e., based on imagined needs rather than real requirements).

Deep Hierarchy: This smell arises when an inheritance hierarchy is “excessively” deep.

Rebellious Hierarchy: This smell arises when a subtype rejects the methods provided by its supertype(s).

Broken Hierarchy: This smell arises when a supertype and its subtype conceptually do not share an “IS- A” relationship resulting in broken substitutability.

Multipath Hierarchy: This smell arises when a subtype inherits both directly as well as indirectly from a supertype leading to unnecessary inheritance paths in the hierarchy.

Cyclic Hierarchy: This smell arises when a supertype in a hierarchy depends on any of its subtypes.


The above definition and classification is described in "Refactoring for software design smells: Managing technical debt". Some more relevant resources could be found here.

Jacktar answered 19/12, 2014 at 14:23 Comment(0)
S
55

A pattern is an idea of how to solve a problem of some class. An anti-pattern is an idea of how not to solve it because implementing that idea would result in bad design.

An example: a "pattern" would be to use a function for code reuse, an "anti-pattern" would be to use copy-paste for the same. Both solve the same problem, but using a function usually leads to more readable and maintainable code than copy-paste.

Spiritless answered 11/6, 2009 at 11:35 Comment(0)
H
20

An anti-pattern is a way of not solving a problem. But there is more to it: it is also a way that can frequently be seen in attempts to solve the problem.

Herbivore answered 11/6, 2009 at 11:38 Comment(0)
P
17

If you really wish to study AntiPatterns, get the book AntiPatterns (ISBN-13: 978-0471197133).

In it, they define "An AntiPattern is a literary form that describes a commonly occurring solution to a problem that generates decidedly negative consequences."

So, if it's a bad programming practice but not a common one— very limited in frequency of occurrence, it does not meet the "Pattern" part of the AntiPattern definition.

Protuberant answered 11/6, 2009 at 12:26 Comment(2)
I disagree with your interpretation of "common". You can still find common solutions, or patterns, among a company's an individual's or an application's. A progblem might be unique to that company, but that doesn't mean its bad, recurrrent solutions aren't anti-patterns.Rambling
@Rambling I get your point, one prolific programmer can make a pattern common, if only locally. I'll amend the answer.Protuberant
M
12

Just like with a design pattern, an anti-pattern is also a template and a repeatable way of solving a certain problem, but in a non-optimal and ineffective way.

Meritorious answered 11/6, 2009 at 11:40 Comment(0)
L
8

Interestingly a given way of solving a problem can be both a pattern and an anti-pattern. Singleton is the prime example of this. It will appear in both sets of literature.

Laissezfaire answered 11/6, 2009 at 12:32 Comment(1)
Patterns don't kill people, people kill people ;) an anti-pattern is also considered a good pattern used for the wrong purpose, in that case it becomes an anti-pattern. Singleton is an excellent pattern but if you use it to have a single DB instance, then it becomes anti-pattern.Barbitone
B
7

A common way to make a mess. Like the god/kitchensink class (does everything), for example.

Brownedoff answered 11/6, 2009 at 11:37 Comment(0)
O
7

An anti-pattern is the complement of a design pattern. An anti-pattern is a template solution you should not use in a certain situation.

Outpoint answered 29/8, 2015 at 13:24 Comment(0)
H
6

Today, software engineering researchers and practitioners often use the terms “anti-pattern” and “smell” interchangeably. However, they are conceptually not the same. The Wikipedia entry of anti-pattern states that an anti-pattern is different from a bad practice or a bad idea by at least two factors. An anti-pattern is

"A commonly used process, structure or pattern of action that despite initially appearing to be an appropriate and effective response to a problem, typically has more bad consequences than beneficial results.”

It clearly indicates that an anti-pattern is chosen in the belief that it is a good solution (as a pattern) to the presented problem; however, it brings more liabilities than benefits. On the other hand, a smell is simply a bad practice that negatively affects the quality of a software system. For example, Singleton is an anti-pattern and God class (or Insufficient Modularization) is a design smell.

Hoopla answered 2/5, 2016 at 15:25 Comment(1)
I'd say the God class is more of an anti-pattern than a smell. Also, "singleton" isn't a very good example of an anti-pattern. If it can even be considered an anti-pattern, at all.Rambling
E
4

Because patterns are discovered not being created Allen Holub and this discovery happens through repetition; if we have discovered a pattern that solves a particular problem but not in the right way according to domain experts knowledge and experience - we tend to call it anti-pattern

pattern: the right way of solving a common, reoccurring problem.
anit-pattern: not the right way of solving a common, reoccurring problem.
both of these based on latest and up to date knowledge

And ... Yesterday's pest practice is tomorrow's anti-pattern Neal Ford, Engineering-Practices-for-Continuous-Delivery

DevOps worlds examples

It used to be a best practice (Architecting Shared Resources)

enter image description here

But in cloud world it introduces coupling when we manage our resources in cloud.

So nowadays we tend to architect our design based on decoupling or uncouple it Uncoupling • Michael Nygard • GOTO 2018

Thus for a specific domain e.g. DevOps:

Past:
Shared Resources == pattern == good thing
Present:
Shared Resources == anti-pattern == bad thing
Decoupling == pattern == good thing

in a word

Prefer pattern over anti-pattern


Image source: Neal Ford, Engineering-Practices-for-Continuous-Delivery

Exam answered 9/6, 2022 at 8:47 Comment(0)
C
2

Anti-patterns are common ways people tend to program the wrong way, or at least the not so good way.

Cher answered 9/2, 2010 at 8:20 Comment(0)
C
1

Any design pattern that is doing more harm than good to the given software development environment would be considered as anti-pattern.

Some anti-pattern are obvious but some are not. For example Singleton, even though many consider it good old design pattern but there are others who don't.

You can check question What is so bad about singletons? to better understand the different opinions on it.

Chook answered 13/3, 2018 at 11:32 Comment(1)
Actually, anti-patterns generally are not obvious. Obviously bad design patterns are simply bad design patterns. A genuine anti-pattern looks tenable on the surface, but manifests problems later on. In fact, not being obviously bad is the distinction that makes them an anti-pattern in the first place.Daradarach
V
1

It is sometimes used when you misuse design patterns in an illegal way, or you don't know the actual usage of it. For example, having builder pattern for simple classes, or obsessively defining one singleton instance for each Active class you use in your code.

Also it might be beyond design patterns. For example, defining local variables in Java as final, or using try / catch for NullPointerException when you could simply check input against being null, or nulling objects after they are used (like what you do in some other languages) that you don't notice about garbage collection mechanism, or calling system.gc() to make memory empty, and many other misunderstandings, which are quite likely to be considered as Cargo-Cult phenomena.

Variety answered 29/7, 2020 at 10:44 Comment(0)
B
0

In Microservices based area:

Everything is micro except for data is an anti-pattern. It means that if every thing is decomposed reasonable and fully based on DevOps and CI/CD. Maybe some distributed design patterns are in place and even fully replicated, but there is one giant data store behind all of the services, so it is still a monolithic data structure.

Other example of Microservices anti-pattern

Bruton answered 7/12, 2020 at 15:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.