الشبح (برمجة الكمبيوتر).
كائن قصير العمر وغير مناسب
في برمجة الكمبيوتر، يُعتبر الشبح (poltergeist) (أو عربة الغجر gypsy wagon) هو كائن قصير العمر، وعادةً ما يكون عديم الحالة (stateless)، يُستخدم لتنفيذ التهيئة أو لاستدعاء طرق (methods) في فئة أخرى أكثر ديمومة. ويُعتبر هذا النمط نمطاً مضاداً (anti-pattern). التعريف الأصلي كتبه مايكل أكرويد في مؤتمر Object World West عام 1996:
مثلما تظهر عربة الغجر أو الشبح وتختفي بشكل غامض، كذلك يظهر ويختفي هذا الكائن قصير العمر. ونتيجة لذلك، يصبح الكود أكثر صعوبة في الصيانة وهناك هدر غير ضروري للموارد. السبب النموذجي لهذا النمط المضاد هو تصميم الكائنات السيء.
غالباً ما يمكن التعرف على كائن الشبح (poltergeist) من اسمه؛ حيث يشتمل اسمه عادةً على كلمات مثل "Manager"، أو "Controller"، أو "Supervisor"، أو "StartProcess"، إلخ.
أحياناً، يتم إنشاء فئات الشبح لأن المبرمج توقع الحاجة إلى بنية أكثر تعقيداً. على سبيل المثال، ينشأ الشبح إذا كانت الطريقة (method) نفسها تعمل كـ عميل (client) ومستدعي (invoker) في نمط الأمر (command pattern)، وتوقع المبرمج فصل المرحلتين. ومع ذلك، قد لا تتحقق هذه البنية الأكثر تعقيداً على الإطلاق.
لا ينبغي خلط كائنات الشبح مع الكائنات طويلة العمر التي تحمل حالة في نمط مثل نموذج - عرض - متحكم (MVC)، أو الأنماط التي تفصل بين الطبقات مثل نمط مندوب الأعمال (business delegate pattern).
لإزالة كائن الشبح، احذف الفئة (class) وأدرج وظائفها في الفئة المستدعاة، وربما يتم ذلك عن طريق الوراثة (inheritance) أو كـ مزيج (mixin).
تم اقتراح طرق للكشف عن كائنات الشبح في الكود لإعادة الهيكلة.
مثال
يمكن اعتبار فئة Poltergeist في هذا المثال بلغة C++ كـ "كائن شبح"، لأنها لا تضيف وظائف إضافية أو كبسلة (encapsulation) وتزيد فقط من التعقيد بتجريد غير ضروري.
import std;
using String = std::string;
// فئة Poltergeist التي تحتفظ فقط بمؤشر، ولكنها لا تضيف أي سلوك ذي معنى
class Poltergeist {
private:
String* s; // مؤشر إلى سلسلة نصية، ولكن الفئة نفسها لا تفعل أي شيء مفيد
public:
explicit Poltergeist(String* s):
s{s} {}
~Poltergeist() {
delete s;
}
[[nodiscard]]
String get() const noexcept {
return s;
}
// لا يوجد سلوك إضافي أو وظيفة ذات معنى
};
int main() {
// إنشاء كائن Poltergeist يحتفظ فقط بمؤشر إلى السلسلة النصية
Poltergeist p(new String("Hello, world!"));
// يقوم فقط بتمرير البيانات دون إضافة أي قيمة
std::println(*p.get());
return 0;
}
يمكن بدلاً من ذلك القيام بذلك بشكل أكثر ملاءمة باستخدام مؤشر ذكي (smart pointer).
import std;
using String = std::string;
template <typename T>
using UniquePtr = std::unique_ptr<T>;
// استخدام المؤشرات الذكية مباشرة لإدارة الذاكرة
UniquePtr<String> s = std::make_unique<String>("Hello, World!");
std::println(*s);
مثال آخر على كائن الشبح/عربة الغجر، هو ما يلي، حيث يتم إنشاء UserCreator فقط لأداء بعض الإجراءات الأساسية.
import std;
using String = std::string;
class UserManager {
public:
void createUser(const String& name) {
std::println("User created: {}", name);
}
};
// فئة الشبح (poltergeist)
class UserCreator {
public:
explicit UserCreator(const String& name) {
UserManager manager;
manager.createUser(name);
}
};
int main() {
// إنشاء كائن شبح فقط لاستدعاء createUser()
UserCreator("Alice");
UserCreator("Bob");
}
يمكن القيام بذلك بشكل أكثر ملاءمة كما يلي، وتجنب فئة الشبح تماماً:
// تجنب كائن الشبح UserCreator تماماً
int main() {
UserManager manager;
manager.createUser("Alice");
manager.createUser("Bob");
}