Poltergeist (programação de computadores).
Objeto de vida curta inadequado
Na programação de computadores, um poltergeist (ou gypsy wagon) é um objeto de vida curta, normalmente sem estado, usado para realizar inicializações ou para invocar métodos em outra classe, mais permanente. É considerado um antipadrão. A definição original é de Michael Akroyd, na Object World West Conference de 1996:
Assim como uma gypsy wagon (carroça cigana) ou um poltergeist aparece e desaparece misteriosamente, o mesmo acontece com esse objeto de vida curta. Como consequência, o código fica mais difícil de manter e há desperdício desnecessário de recursos. A causa típica desse antipadrão é um projeto de objeto deficiente.
Um poltergeist muitas vezes pode ser identificado pelo nome; eles costumam incluir no nome palavras como "Manager", "Controller", "Supervisor", "StartProcess", etc.
Às vezes, classes poltergeist são criadas porque o programador anteviu a necessidade de uma arquitetura mais complexa. Por exemplo, um poltergeist surge se o mesmo método atua tanto como cliente quanto como invocador em um padrão Command, e o programador antecipa a separação das duas fases. No entanto, essa arquitetura mais complexa pode, na verdade, nunca se concretizar.
Poltergeists não devem ser confundidos com os objetos de vida longa e portadores de estado de um padrão como o model–view–controller, ou de padrões de separação de camadas como o business delegate.
Para remover um poltergeist, exclua a classe e insira sua funcionalidade na classe invocada, possivelmente por herança ou como um mixin.
Foram propostos métodos para detectar poltergeists em código com vistas à refatoração.
Exemplo
A classe Poltergeist neste exemplo em C++ pode ser vista como um "objeto poltergeist", por não adicionar funcionalidade ou encapsulamento adicionais e apenas aumentar a complexidade com uma abstração desnecessária.
import std;
using String = std::string;
// Classe Poltergeist que apenas guarda um ponteiro, mas não adiciona comportamento significativo
class Poltergeist {
private:
String* s; // ponteiro para string, mas a própria classe não faz nada útil
public:
explicit Poltergeist(String* s):
s{s} {}
~Poltergeist() {
delete s;
}
[[nodiscard]]
String get() const noexcept {
return s;
}
// Nenhum comportamento adicional ou funcionalidade significativa
};
int main() {
// Cria um objeto Poltergeist que apenas guarda um ponteiro para a string
Poltergeist p(new String("Hello, world!"));
// Apenas repassa os dados sem agregar valor
std::println(*p.get());
return 0;
}
Em vez disso, isso poderia ser feito de forma mais apropriada usando um ponteiro inteligente.
import std;
using String = std::string;
template <typename T>
using UniquePtr = std::unique_ptr<T>;
// Usa ponteiros inteligentes diretamente para gerenciar a memória
UniquePtr<String> s = std::make_unique<String>("Hello, World!");
std::println(*s);
Outro exemplo de objeto poltergeist/gypsy wagon é o seguinte, em que UserCreator é instanciado apenas para realizar algumas ações básicas.
import std;
using String = std::string;
class UserManager {
public:
void createUser(const String& name) {
std::println("User created: {}", name);
}
};
// A classe poltergeist
class UserCreator {
public:
explicit UserCreator(const String& name) {
UserManager manager;
manager.createUser(name);
}
};
int main() {
// Cria um poltergeist apenas para chamar createUser()
UserCreator("Alice");
UserCreator("Bob");
}
Isso poderia ser feito de forma mais apropriada da seguinte maneira, evitando completamente qualquer classe poltergeist:
// Evita completamente o poltergeist UserCreator
int main() {
UserManager manager;
manager.createUser("Alice");
manager.createUser("Bob");
}