ConstructiCat Logo
CodeBust.
Browse section ▾

Poltergeist.

A poltergeist is a short-lived, stateless class that exists only to call methods of another class, adding indirection without adding behavior.

In computer programming, a poltergeist is a short-lived, typically stateless object used to perform initialization or to invoke methods in another, more permanent class. It is considered an anti-pattern. The term was introduced by Michael Akroyd at the 1996 Object World West Conference: like a poltergeist, such an object appears and disappears mysteriously. As a consequence the code is more difficult to maintain and resources are wasted for no benefit. The typical cause of this anti-pattern is poor object design.

A poltergeist can often be identified by its name; they often include words such as "Manager", "Controller", "Supervisor", "StartProcess", etc. in the name.

Sometimes, poltergeist classes are created because the programmer anticipated the need for a more complex architecture. For example, a poltergeist arises if the same method acts as both the client and invoker in a command pattern, and the programmer anticipates separating the two phases. However, this more complex architecture may actually never materialize.

Poltergeists should not be confused with long-lived, state-bearing objects of a pattern such as model–view–controller, or tier-separating patterns such as business delegate pattern.

To remove a poltergeist, delete the class and insert its functionality in the invoked class, possibly by inheritance or as a mixin.

There have been proposed methods in detecting poltergeists in code for refactoring.

In refactoring terms the cure is Inline Class. A poltergeist is closely related to the Lazy Class and Middle Man code smells.

Example

In this C++ example, UserCreator is a poltergeist: it is instantiated only to create a UserManager, call one of its methods and vanish.

import std;

using String = std::string;

class UserManager {
public:
    void createUser(const String& name) {
        std::println("User created: {}", name);
    }
};

// The poltergeist class
class UserCreator {
public:
    explicit UserCreator(const String& name) {
        UserManager manager;
        manager.createUser(name);
    }
};

int main() {
    // Creating a poltergeist just to call createUser()
    UserCreator("Alice");
    UserCreator("Bob");
}

Without the poltergeist, the caller uses UserManager directly and one class less has to be read and maintained:

import std;

using String = std::string;

class UserManager {
public:
    void createUser(const String& name) {
        std::println("User created: {}", name);
    }
};

// No UserCreator: the caller talks to UserManager directly
int main() {
    UserManager manager;
    manager.createUser("Alice");
    manager.createUser("Bob");
}

Adapted from the Wikipedia article “Poltergeist (computer programming)” (revision 1321576717), available under the CC BY-SA 4.0 license; the text has been edited and examples added.