تأثير المنصة الداخلية.
تأثير المنصة الداخلية هو بناء نظام قابل للتخصيص إلى حد يجعله نسخة رديئة من المنصة التي يعمل عليها، كقاعدة بيانات داخل قاعدة بيانات.
إنّ تأثير المنصة الداخلية (inner-platform effect) هو نزعة معماريي البرمجيات إلى تصميم نظام قابل للتخصيص بدرجة كبيرة لدرجة تجعله نسخة مكررة، وغالباً ما تكون نسخة رديئة، من منصة تطوير البرمجيات التي يستخدمونها. هذا الأمر غير فعال بشكل عام، وغالباً ما تُعتبر هذه الأنظمة أمثلة على نمط مضاد (anti-pattern).
أمثلة
تظهر الأمثلة بوضوح في البرمجيات القائمة على المكونات الإضافية (plugins) مثل بعض محررات النصوص ومتصفحات الويب، حيث يقوم المطورون غالباً بإنشاء إضافات تعيد بناء برمجيات يفترض أن تعمل مباشرة فوق نظام التشغيل نفسه. على سبيل المثال، تم استخدام آلية الإضافات في متصفح Firefox لتطوير عدد من عملاء FTP ومتصفحات الملفات، والتي تكرر فعلياً بعض ميزات نظام التشغيل، وإن كان ذلك على منصة أكثر محدودية.
في عالم قواعد البيانات، يميل المطورون أحياناً إلى تجاوز نظام إدارة قواعد البيانات العلاجية (RDBMS)، على سبيل المثال من خلال تخزين كل شيء في جدول كبير واحد (table) يحتوي على ثلاثة أعمدة تحمل العناوين: معرف الكيان (entity ID)، والمفتاح (key)، والقيمة (value). ورغم أن نموذج الكيان والصفة والقيمة (entity-attribute-value model) هذا يسمح للمطور بالخروج من الهيكل الذي تفرضه قاعدة بيانات SQL، إلا أنه يفقد كل المزايا، حيث يُجبر التطبيق على القيام بكل العمل الذي كان يمكن لـ RDBMS القيام به بكفاءة. وتصبح الاستعلامات أكثر تعقيداً بكثير، ولا تعود الفهارس ومُحسن الاستعلامات تعمل بفعالية، ولا يتم فرض قيود التحقق من صحة البيانات. وقد يكون الأداء وقابلية الصيانة سيئين للغاية.
وهناك إغراء مماثل في لغة XML، حيث يفضل المطورون أحياناً استخدام أسماء عناصر عامة واستخدام السمات لتخزين المعلومات ذات المعنى. على سبيل المثال، قد يُسمى كل عنصر باسم item ويحتوي على السمات type وvalue. تطلب هذه الممارسة إجراء عمليات ربط (joins) عبر سمات متعددة من أجل استخراج المعنى. نتيجة لذلك، تصبح تعبيرات XPath أكثر تعقيداً، ويكون التقييم أقل كفاءة، ولا يقدم التحقق الهيكلي من الصحة فائدة تذكر.
مثال آخر هو ظاهرة أسطح المكتب على الويب، حيث تعمل بيئة سطح مكتب كاملة (desktop environment)—تتضمن غالباً متصفح ويب—داخل متصفح (والذي يعمل هو نفسه عادةً داخل بيئة سطح مكتب التي يوفرها نظام التشغيل). إن وجود سطح مكتب داخل سطح مكتب يمكن أن يكون مربكاً وغير مريح للمستخدم بشكل غير عادي، وبالتالي لا يتم ذلك عموماً إلا لتشغيل البرامج التي لا يمكن نشرها بسهولة على أنظمة المستخدمين النهائيين، أو عن طريق إخفاء سطح المكتب الخارجي.
الأثر
من الطبيعي لمطوري البرمجيات إنشاء مكتبة من الدوال المخصصة التي تتعلق بمشروعهم المحدد. ويحدث تأثير المنصة الداخلية عندما تتوسع هذه المكتبة لتشمل دوال عامة تكرر وظائف متاحة بالفعل كجزء من لغة البرمجة أو المنصة. ونظراً لأن كل دالة من هذه الدوال الجديدة ستقوم عموماً باستدعاء عدد من الدوال الأصلية، فإنها تميل إلى أن تكون أبطأ، وإذا كُتبت بشكل سيء، فإنها تكون أقل موثوقية أيضاً.
من ناحية أخرى، يتم إنشاء مثل هذه الدوال غالباً لتقديم طبقة تجريد أبسط (وغالباً أكثر قابلية للنقل) فوق الخدمات ذات المستوى الأدنى التي إما أن تكون واجهتها صعبة الاستخدام، أو معقدة للغاية، أو غير قابلة للنقل أو قابلة للنقل بشكل غير كافٍ، أو ببساطة لا تتناسب بشكل جيد مع كود التطبيق ذي المستوى الأعلى.
الاستخدامات المناسبة
يمكن أن تكون المنصة الداخلية مفيدة لأسباب تتعلق بقابلية النقل وفصل الصلاحيات—بمعنى آخر، حتى يتمكن التطبيق نفسه من العمل على مجموعة واسعة من المنصات الخارجية دون التأثير على أي شيء خارج بيئة معزولة (sandbox) تديرها المنصة الداخلية. على سبيل المثال، صممت شركة Sun Microsystems منصة Java لتحقيق كلا الهدفين.
مثال
بدلاً من جدول لكل كيان، يُوضع كل شيء في جدول عام واحد على نموذج «كيان–سمة–قيمة»، فيضطر التطبيق إلى إعادة بناء ما توفره قاعدة البيانات أصلاً: الأنواع والقيود والربط بين الجداول. حتى الترشيح البسيط يحتاج إلى ربط الجدول بنفسه وتحويل النوع، ولا شيء يمنع أن يبقى عميل بلا بريد إلكتروني أو بحدّ ائتماني سالب.
import sqlite3
db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE entity (id INTEGER, attr TEXT, value TEXT)")
def save_customer(cid, name, email, credit_limit):
db.executemany(
"INSERT INTO entity VALUES (?, ?, ?)",
[(cid, "name", name), (cid, "email", email), (cid, "credit_limit", str(credit_limit))],
)
def customers_over(limit):
return db.execute(
"SELECT n.id, n.value FROM entity n "
"JOIN entity c ON c.id = n.id AND c.attr = 'credit_limit' "
"WHERE n.attr = 'name' AND CAST(c.value AS REAL) > ?",
(limit,),
).fetchall()
يتيح المخطط الحقيقي لنظام إدارة قواعد البيانات العلائقية فرض الأنواع والقيود واستخدام الفهرس وتحسين الاستعلام، فلا يعود التطبيق يعيد تنفيذ المنصة التي يعمل عليها.
import sqlite3
db = sqlite3.connect(":memory:")
db.execute(
"CREATE TABLE customer ("
" id INTEGER PRIMARY KEY,"
" name TEXT NOT NULL,"
" email TEXT NOT NULL UNIQUE,"
" credit_limit REAL NOT NULL CHECK (credit_limit >= 0))"
)
db.execute("CREATE INDEX customer_credit_limit ON customer (credit_limit)")
def save_customer(cid, name, email, credit_limit):
db.execute("INSERT INTO customer VALUES (?, ?, ?, ?)", (cid, name, email, credit_limit))
def customers_over(limit):
return db.execute("SELECT id, name FROM customer WHERE credit_limit > ?", (limit,)).fetchall()
مقتبس من مقالة ويكيبيديا “Inner-platform effect” (المراجعة 1319593770)، والمتاحة بموجب رخصة CC BY-SA 4.0؛ تمت ترجمة النص وتحريره وإضافة أمثلة.