استكشاف أفكار جون أوسترهوت حول التصميم البرمجي العملي، إرث لغة Tcl، نقاش أوسترهوت مقابل بروكس، وكيف يُغرق التعقيد المنتجات.

جون أوسترهوت عالم حاسوب ومهندس عمل في البحث والأنظمة الحقيقية. اخترع لغة البرمجة Tcl، ساهم في تشكيل أنظمة الملفات الحديثة، ولاحقًا كَوّن عقودًا من الخبرة في ادّعاء بسيط، قد يسبب بعض الانزعاج: التعقيد هو العدو الرئيسي للبرمجيات.
تظل هذه الرسالة ملائمة لأن معظم الفرق لا تفشل لندرة الميزات أو نقص الجهد—بل لأنها تصبح أنظمتها (ومنظّماتها) صعبة الفهم، صعبة التغيير، وسهلة الكسر. التعقيد لا يبطئ المهندسين فحسب؛ بل يتسرّب إلى قرارات المنتج، ثقة خارطة الطريق، ثقة العملاء، تكرار الحوادث، وحتى التوظيف—لأن الانخراط يصبح تجربة استيعاب تستغرق شهورًا.
إطار أوسترهوت عملي: عندما يتراكم في النظام حالات خاصة واستثناءات واعتمادات مخفية وتصحيحات "لمرة واحدة فقط"، فالتكلفة لا تقتصر على قاعدة الشيفرة. المنتج بأكمله يصبح أكثر كلفة للتطور. الميزات تستغرق وقتًا أطول، ضبط الجودة يصعب، الإصدارات تصبح أكثر خطورة، وتبدأ الفرق بتجنب التحسينات لأن لمس أي شيء يبدو محفوفًا بالمخاطر.
هذا ليس نداءً للنقاء الأكاديمي. هو تذكير بأن كل اختصار له دفعات فوائد—والتعقيد هو أعلى دين فائدة.
لجعل الفكرة ملموسة (وليس مجرد تحفيز)، سنتناول رسالة أوسترهوت من ثلاث زوايا:
هذا النص ليس موجهًا فقط لمهووسي اللغات. إذا كنت تبني منتجات، تقود فرقًا، أو تتخذ مقايضات في خارطة الطريق، فستجد طرقًا عملية لرصد التعقيد مبكرًا، منعه من أن يصبح مؤسسة، ومعاملة البساطة كقيد أساسي—ليس ميزة اختيارية بعد الإطلاق.
التعقيد ليس "كثير من الشيفرة" أو "رياضيات صعبة". هو الفجوة بين ما تظن أن النظام سيفعله عند تغييره وما يفعله فعليًا. النظام معقّد عندما تبدو التعديلات الصغيرة خطيرة—لأنك لا تستطيع التنبؤ بنطاق الأثر.
في الشيفرة الصحية، يمكنك الإجابة عن: "إذا غيّرنا هذا، ما الذي قد ينكسر؟" التعقيد هو ما يجعل هذا السؤال مكلفًا.
غالبًا ما يختبئ في:
الفرق تشعر بالتعقيد كـ تباطؤ في التسليم (وقت أكثر للتحقيق)، مزيد من الأخطاء (لأن السلوك مفاجئ)، وأنظمة هشة (التغييرات تتطلب تنسيقًا عبر كثير من الناس والخدمات). كما أنه يستنزف الاستيعاب: الزملاء الجدد لا يستطيعون بناء نموذج ذهني، فيتجنّبون لمس التدفقات الأساسية.
بعض التعقيد أساسي: قواعد العمل، متطلبات الامتثال، وحالات الحافة في العالم الحقيقي. لا يمكنك حذفها.
لكثير من التعقيد جانب عَرَضي: واجهات برمجة غامضة، منطق مكرر، أعلام "مؤقتة" تصبح دائمة، ووحدات تتسرب تفاصيلها الداخلية. هذا هو التعقيد الذي تخلقه قرارات التصميم—وهو النوع الوحيد الذي يمكنك تقليله بانتظام.
بدأت Tcl بهدف عملي: تسهيل أتمتة البرمجيات وتمديد التطبيقات القائمة دون إعادة كتابتها. صمّمها جون أوسترهوت حتى يتمكن الفرق من إضافة "قدر كافٍ من البرمجة" إلى أداة—ثم تسليم تلك القوة للمستخدمين، المشغلين، ضمان الجودة، أو أي شخص يحتاج لكتابة سكربتات.
شاع Tcl فكرة لغة اللاصق: طبقة سكربت صغيرة ومرنة تربط مكوّنات مكتوبة بلغات أسرع وأدنى مستوى. بدلًا من بناء كل ميزة في مونوليث، يمكنك تصدير مجموعة أوامر، ثم تركيبها لسلوكيات جديدة.
ثبت هذا النموذج فاعليته لأنه طابق كيفية سير العمل فعليًا. الناس لا يبنون منتجات فقط؛ بل يبنون أنظمة بناء، حِوامل اختبار، أدوات إدارة، محولات بيانات، وأتمتات لمرة واحدة. طبقة سكربت خفيفة تجعل هذه المهام تتحول من "فتح تذكرة" إلى "كتابة سكربت".
جعلت Tcl تضمين المفسر أمرًا ذا أولوية. يمكنك إسقاط مفسر داخل تطبيق، تصدير واجهة أوامر نظيفة، وكسب القدرة على التكوين والتكرار السريع فورًا.
نفس النمط يظهر اليوم في أنظمة الإضافات، لغات التكوين، واجهات التمديد، وروتنيات السكربت المضمنة—سواء بدا تركيب السكربت شبيهًا بـ Tcl أم لا.
كما عززت عادة تصميم مهمة: فصل البدائيات المستقرة (قدرات نواة التطبيق) عن التركيب القابل للتغيير (السكربتات). عندما يعمل هذا، تتطور الأدوات أسرع دون زعزعة النواة باستمرار.
قد تبدو صياغة Tcl ونموذج "كل شيء سلسلة" غير بديهية، وقواعد شيفرات Tcl الكبيرة قد تصبح صعبة الفهم دون اتفاقيات صارمة. ومع ظهور بيئات تقدم مكتبات معيارية أغنى، أدوات أفضل، ومجتمعات أكبر، هاجر كثير من الفرق طبيعيًا.
لا يمحو أي من ذلك إرث Tcl: فقد ساعدت في تعميم فكرة أن القابلية للتمديد والأتمتة ليست إضافات—بل ميزات منتج يمكن أن تقلل التعقيد بشكل كبير لمن يستخدم ويحافظ على النظام.
بُنيت Tcl حول فكرة تبدو صارمة: اجعل النواة صغيرة، اجعل التركيب قويًا، واجعل السكربتات قابلة للقراءة بما يكفي حتى يعمل الناس معًا دون ترجمة دائمة.
بدلًا من شحن مجموعة ضخمة من الميزات المتخصّصة، اعتمدت Tcl على مجموعة مختصرة من البدائيات (سلاسل، أوامر، قواعد تقييم بسيطة) وتوقعت من المستخدمين دمجها. هذه الفلسفة توجه المصممين نحو عدد أقل من المفاهيم يعاد استخدامها في سياقات متعددة. الدرس لتصميم المنتج وواجهات برمجة التطبيقات بسيط: إذا استطعت حل عشر حاجات باثنين أو ثلاثة ركائز متسقة، تقلّل مساحة السطح التي يجب على الناس تعلمها.
فخ أساسي في تصميم البرمجيات هو التحسين لصالح راحة البناء. قد تكون ميزة سهلة التنفيذ (نسخ خيار موجود، إضافة علم خاص، رقع زاوية) بينما تجعل المنتج أصعب استخدامًا.
تأكيد Tcl كان عكسيًا: اجعل نموذج التفكير ضيقًا، حتى لو كان التنفيذ يحتاج لمزيد من العمل خلف الكواليس.
عند مراجعة اقتراح، اسأل: هل يقلل هذا من عدد المفاهيم التي يجب أن يتذكرها المستخدم، أم يضيف استثناءً آخر؟
التقليل يساعد فقط عندما تكون البدائيات متسقة. إذا بدا أمران متشابهان لكنهما يتصرّفان بشكل مختلف في حالات الهامش، ينتهي الأمر بالمستخدمين إلى حفظ تفصيلات صغيرة. مجموعة صغيرة من الأدوات قد تصبح "حواف حادة" عندما تختلف القواعد بدقة.
فكر في مطبخ: سكين جيد، مقلاة، وفرن يسمحان بصنع وجبات عديدة بتركيب تقنيات. جهاز يشرّح الأفوكادو فقط هو ميزة لمرة واحدة—سهل البيع لكنه يكدّس الأدراج.
فلسفة Tcl تجادل لصالح السكين والمقلاة: أدوات عامة تُركّب بسلاسة، فلا تحتاج إلى جهاز جديد لكل وصفة.
في 1986 كتب فريد بروكس مقالًا باستنتاج استفزازي مقصود: لا يوجد اختراق واحد—لا "رصاصة فضية"—يجعل تطوير البرمجيات أسرع أو أرخص أو أكثر موثوقية بمرتبة واحدة في قفزة واحدة.
لم يقصد أن التقدم مستحيل. قصد أن البرمجيات وسط يمكننا فيه فعل أي شيء تقريبًا، وأن هذه الحرية تحمل عبئًا فريدًا: نحن باستمرار نعرّف الشيء أثناء بنائه. الأدوات الأفضل تساعد، لكنها لا تمحو الجزء الأصعب من العمل.
قسّم بروكس التعقيد إلى دلوين:
الأدوات تستطيع سحق التعقيد العَرَضي. فكر بما اكتسبناه من لغات أعلى مستوى، التحكم في النسخ، CI، الحاويات، قواعد البيانات المدارَة، وIDE جيدة. لكن بروكس جادل أن التعقيد الأساسي يهيمن، ولا يختفي لمجرّد تحسّن الأدوات.
حتى مع المنصات الحديثة، تقضي الفرق معظم طاقتها في التفاوض على المتطلبات، دمج الأنظمة، معالجة الاستثناءات، والحفاظ على السلوك متسقًا مع الزمن. قد تتغيّر مساحة السطح (واجهات سحابة بدلًا من برامج تشغيل الأجهزة)، لكن التحدي الأساسي يبقى: ترجمة احتياجات بشرية إلى سلوك محدد وقابل للصيانة.
هذا يهيئ التوتر الذي يراهن عليه أوسترهوت: إذا كان لا يمكن حذف التعقيد الأساسي، هل يمكن للتصميم المنضبط أن يقلل بشكل ملموس مدى تسريب هذا التعقيد إلى الشيفرة—وإلى رؤوس المطورين يومًا بعد يوم؟
أحيانًا يُصور "أوسترهوت مقابل بروكس" كصراع بين التفاؤل والواقعية. أكثر فائدة قراءته كاثنين من المهندسين ذوي الخبرة يصفان أجزاء مختلفة من نفس المشكلة.
مقال بروكس يقول إنه لا توجد قفزة سحرية تمحو الجزء الأصعب من البرمجيات. أوسترهوت لا يعترض على ذلك فعليًا.
دفعته العملية أضيق: كثير من الفرق تتعامل مع التعقيد كأمر محتوم بينما الكثير منه قابل للتجنّب.
من وجهة نظر أوسترهوت، التصميم الجيد يمكن أن يقلل التعقيد بشكل ملموس—ليس بجعل البرمجيات "سهلة"، لكن بجعلها أقل إرباكًا للتغيير. هذا ادعاء كبير لأنه الإرباك هو ما يحول العمل اليومي إلى عمل بطيء.
يركز بروكس على ما يسميه الصعوبة الأساسية: البرمجيات يجب أن تُجسّد واقعًا فوضويًا ومتغيرًا وحالات حافة خارج قاعدة الشيفرة. حتى مع أدوات رائعة، لا يمكنك حذف هذا. يمكنك فقط إدارته.
يتفقان أكثر مما يُعتقد:
بدلًا من سؤال "من على حق؟"، اسأل: أي تعقيد نستطيع التحكم به هذا الربع؟
الفرق لا تستطيع التحكم في تغيّرات السوق أو صعوبة المجال الجوهرية. لكنها تستطيع التحكم فيما إذا كانت الميزات الجديدة تضيف حالات خاصة، ما إذا كانت الواجهات تُجبر المستدعين على حفظ قواعد مخفية، وهل الوحدات تخفي التعقيد أم تتسرب منه.
هذا هو الوسط العملي: اقبل التعقيد الأساسي، وكن صارمًا بشأن التعقيد العَرَضي.
الوحدة العميقة هي مكوّن يفعل الكثير بينما يعرِض واجهة صغيرة وسهلة الفهم. "العمق" هو مقدار التعقيد الذي تأخذه الوحدة عن كاهلك: المستدعون لا يحتاجون لمعرفة التفاصيل الفوضوية، والواجهة لا تُجبرهم على ذلك.
الوحدة السطحية على النقيض: قد تغطي منطقًا بسيطًا، لكنها تدفع التعقيد للخارج—عبر كثير من المعاملات، أعلام خاصة، ترتيب استدعاء مطلوب، أو قواعد "عليك أن تتذكر…".
فكر في مطعم. الوحدة العميقة هي المطبخ: تطلب "باستا" من قائمة بسيطة ولا تهتم بمورّد المكونات أو أوقات الغليان أو التقديم.
الوحدة السطحية هي "مطبخ" يسلمك مكونات خام مع قائمة تعليمات مكونة من 12 خطوة ويطلب منك إحضار المقلاة الخاصة. العمل لا يزال يتم—لكنه انتقل إلى العميل.
الطبقات الإضافية تكون رائعة إذا جمعت كثيرًا من القرارات في اختيار واحد واضح.
مثال: طبقة تخزين تعرض save(order) وتتولى داخليًا إعادة المحاولة، التسلسل، والفهرسة—هذه وحدة عميقة.
الطبقات تضر عندما تعيد تسميّة الأشياء أو تضيف خيارات. إذا أدخل تجريد جديد مزيدًا من التكوين أكثر مما يزيل—مثل save(order, format, retries, timeout, mode, legacyMode)—فمن المرجح أنه سطحي. قد تبدو الشفرة "منظمة"، لكن العبء المعرفي يظهر في كل موضع استدعاء.
useCache, skipValidation, force, legacy.الوحدات العميقة لا "تغلق الكود" فحسب؛ بل تغلق القرارات.
الواجهة "الجيدة" ليست فقط التي تفعل الكثير. إنها التي يمكن للناس حملها في رؤوسهم أثناء العمل.
عدسة أوسترهوت تدفعك إلى تقييم الواجهة بحسب الجهد العقلي الذي تطلبه: كم عدد القواعد التي يجب تذكرها، كم الاستثناءات التي يجب التنبؤ بها، ومدى سهولة فعل الخطأ عن طريق الخطأ.
واجهات برمجة التطبيقات الصديقة للإنسان عادةً ما تكون صغيرة، متسقة، وصعبة الإساء��.
الصغيرة لا تعني ناقصة القوة—بل تعني أن مساحة السطح مركزة في عدد قليل من المفاهيم التي تُركّب جيدًا. المتسقة تعني أن نفس النمط يعمل عبر النظام كله (المعاملات، التعامل مع الأخطاء، التسمية، أنماط الإرجاع). صعبة الإساءة تعني أن الواجهة ترشدك إلى مسارات آمنة: ثوابت واضحة، تحقق عند الحدود، وفحوصات نوع أو تنفيذ تفشل مبكرًا.
كل علم إضافي أو وضع أو تكوين يصبح ضريبة على جميع المستخدمين. حتى إذا احتاج 5% فقط من المستدعين له، يجب على 100% أن يعرفوا بوجوده، يتساءلوا إذا كانوا بحاجة إليه، ويفسروا السلوك عندما يتفاعل مع خيارات أخرى.
هكذا تتراكم التعقيدات في الواجهات: ليس في استدعاء واحد، بل في التوافيق.
القيم الافتراضية لطفٌ: تتيح لغالبية المستدعين حذف القرار والحصول على سلوك معقول. الاتفاقيات (طريقة واضحة واحدة) تقلّل التفرع في ذهن المستخدم. التسمية تقوم بعمل حقيقي أيضًا: اختر أفعالًا وأسماء تتطابق مع نية المستخدم، واحتفظ بتسميات متشابهة للعمليات المماثلة.
تذكير آخر: واجهات داخلية مهمة بقدر العامة. معظم التعقيد في المنتجات يعيش خلف الكواليس—حدود الخدمات، المكتبات المشتركة، الوحدات "المساعدة". عامِل تلك الواجهات كمنتجات، مع مراجعات وانضباط إدارة إصدار (راجع أيضًا /blog/deep-modules).
نادراً ما يصل التعقيد كقرار واحد "سيئ". يتراكم عبر رقع صغيرة ومعقولة المظهر—خاصة عندما تكون الفرق تحت ضغط موعد نهائي والهدف الفوري هو الشحن.
فخّ شائع هو أعلام الميزات في كل مكان. الأعلام مفيدة للنشر الآمن، لكن عندما تطول مدتها، يضاعف كل علم عدد السلوكيات المحتملة. يتوقف المهندسون عن التفكير في "النظام" ويبدأون التفكير في "النظام، إلا عندما يكون العلم A مفعلًا والمستخدم في الشريحة B".
آخر هو منطق الحالات الخاصة: "عملاء المؤسسة يحتاجون X"، "باستثناء في المنطقة Y"، "إلا إذا كان الحساب أقدم من 90 يومًا". تنتشر هذه الاستثناءات عبر الشيفرة، وبعد أشهر لا أحد يعرف أيها لازمة.
ثالث هو التجريدات المتسربة. واجهة تجبر المستدعين على فهم تفاصيل داخلية (التوقيت، صيغة التخزين، قواعد الكاش) تدفع التعقيد خارجيًا. بدلاً من أن تتحمّل وحدة واحدة العبء، يتعلّم كل مستدٍ العيوب.
البرمجة التكتيكية تُحسّن لهذا الأسبوع: حلول سريعة، تغييرات بسيطة، "اركبه".
البرمجة الاستراتيجية تُحسّن للسنة القادمة: إعادة تصميمات صغيرة تمنع فئات الأخطاء نفسها وتقلل العمل المستقبلي.
الخطر هو "فائدة الصيانة". حل سريع يشعر أنك دفعت قليلًا الآن، لكنك ستدفع الفائدة لاحقًا: استيعاب أبطأ، إصدارات هشة، وتطور مدفوع بالخوف حيث لا يريد أحد لمس الشيفرة القديمة.
أضف مطالبات خفيفة لمراجعة الكود: "هل يضيف هذا حالة خاصة جديدة؟" "هل يمكن للواجهة إخفاء هذه التفصيلة؟" "ما التعقيد الذي نتركه وراءنا؟"
احتفظ بسجلات قرارات قصيرة للقي trade-offs غير التافهة (بضع نقاط تكفي). وخصص ميزانية إعادة هيكلة صغيرة كل سباق حتى لا تُعامل الإصلاحات الاستراتيجية كعمل خارجي.
التعقيد لا يبقى محشورًا في الهندسة. يتسرّب إلى الجداول الزمنية، الموثوقية، وطريقة تجربة العملاء للمنتج.
عندما يصبح النظام صعب الفهم، يستغرق كل تغيير وقتًا أطول. يتأخر وقت الوصول إلى السوق لأن كل إصدار يتطلب مزيدًا من التنسيق، اختبارات الانحدار، ودورات مراجعة "لأجل الأمان".
تعاني الموثوقية أيضًا. الأنظمة المعقّدة تخلق تفاعلات لا يمكن لأحد توقعها بالكامل، فتظهر أخطاء كحالات هامشية: فشل الدفع يحدث فقط عندما يجتمع قسيم، سلة محفوظة، وقاعدة ضريبية إقليمية بطريقة معينة. تلك الحوادث الأصعب استنساخًا والأبطأ إصلاحًا.
الاستيعاب يصبح حملاً مخفيًا. الزملاء الجدد لا يستطيعون بناء نموذج مفيد، فيتجنبون لمس المناطق الخطرة، ينسخون أنماطًا لا يفهمونها، ويضيفون عن غير قصد المزيد من التعقيد.
العملاء لا يهتمون بما إذا كان السلوك ناجمًا عن "حالة خاصة" في الشيفرة. يختبرونه كعدم تناسق: إعدادات لا تنطبق في كل مكان، تدفقات تتغيّر اعتمادًا على مسار الوصول، ميزات تعمل "معظم الوقت".
تنخفض الثقة، يرتفع الارتداد، ويتوقف الاعتماد.
فرق الدعم تدفع التعقيد من خلال تذاكر أطول ومزيد من المراسلات للحصول على السياق. التشغيل يدفع عبر مزيد من التنبيهات، كتيبات التشغيل، ونشر أكثر حذرًا. كل استثناء يصبح شيئًا يجب مراقبته، توثيقه، وشرحه.
تخيل طلبات لـ "قاعدة إشعار إضافية". تبدو الإضافة سريعة، لكنها تُدخل فرعًا آخر في السلوك، مزيدًا من نصوص واجهة المستخدم، مزيدًا من حالات الاختبار، ومزيدًا من طرق خطأ إعداد المستخدمين.
قارن ذلك بتبسيط تدفق الإشعارات القائم: أنواع قواعد أقل، قيم افتراضية أوضح، وسلوك متسق عبر الويب والجوال. قد تطرح أقل من المقابض، لكنك تقلّل المفاجآت—مما يجعل المنتج أسهل استخدامًا، أسهل دعمًا، وأسرع تطورًا.
عامل التعقيد مثل الأداء أو الأمان: شيء تخطط له، تقيسه، وتحميه. إذا لاحظت التعقيد فقط عندما يتباطأ التسليم، فأنت تدفع بالفعل فائدة.
إلى جانب نطاق الميزة، عرّف مقدار التعقيد الجديد الذي يُسمح به للإصدار. يمكن أن تكون الميزانية بسيطة: "لا مفاهيم صافية جديدة ما لم نُزل واحدة"، أو "أي تكامل جديد يجب أن يستبدل مسارًا قديمًا".
اجعل المقايضات صريحة في التخطيط: إذا كانت الميزة تتطلب ثلاث أوضاع إعداد جديدة وحالتين استثنائيتين، يجب أن تكلف أكثر من ميزة تناسب المفاهيم القائمة.
لا تحتاج أرقامًا مثالية—فقط إشارات تميل في الاتجاه الصحيح:
تتبّع هذه لكل إصدار، واربطها بالقرارات: "أضفنا خيارين عامين؛ ماذا أزلنا أو بسطنا للتعويض؟"
كثير من النماذج الأولية تُقَيَّم بـ "هل يمكننا بناؤها؟". بدلًا من ذلك، استخدمها للإجابة: "هل يبدو هذا بسيطًا في الاستخدام وصعب الإساءة؟"
اطلب من شخص غير مطلع على الميزة محاولة إتمام مهمة واقعية بالنموذج الأولي. قس وقت النجاح، الأسئلة المطروحة، وأين ارتكبوا افتراضات خاطئة. تلك نقاط ساخنة للتعقيد.
هنا أيضًا حيث يمكن لتدفقات العمل الحديثة أن تقلل التعقيد العَرَضي—إذا أبقت التكرار ضيقًا وسهّلت التراجع عن الأخطاء. على سبيل المثال، عندما تستخدم الفرق منصة توليد مثل Koder.ai لتخطيط أداة داخلية أو تدفق جديد عبر المحادثة، ميزات مثل وضع التخطيط (لتوضيح النية قبل التوليد) واللقطات/التراجع (لإلغاء تغييرات محفوفة بالمخاطر بسرعة) يمكن أن تجعل التجربة الأولية أكثر أمانًا—بدون الالتزام بكومة تجريدات نصف منتهية. إذا تخرج النموذج الأولي إلى الإنتاج، يمكنك تصدير الشيفرة المصدرية وتطبيق نفس انضباط "الوحدة العميقة" وتصميم الواجهات الموصوف أعلاه.
اجعل أعمال "تنظيف التعقيد" دورية (ربع سنوية أو كل إصدار رئيسي)، وعرّف ما يعنيه "إنجاز":
الهدف ليس شفرة أنظف مجردًا—بل مفاهيم أقل، استثناءات أقل، وتغيّر أكثر أمانًا.
فيما يلي خطوات قصيرة تحول فكرة أوسترهوت "التعقيد هو العدو" إلى عادات أسبوعية للفريق.
اختر نظامًا فرعيًا يسبب ارتباكًا متكررًا (ألم الاستيعاب، أخطاء متكررة، كثير من أسئلة "كيف يعمل هذا؟").
متابعات داخلية يمكنك تشغيلها: مراجعة "التعقيد" في التخطيط (/blog/complexity-review) وفحص سريع هل أدواتكم تقلل التعقيد العَرَضي بدلًا من إضافة طبقات (/pricing).
ما قطعة واحدة من التعقيد ستزيلها أولًا لو كان بإمكانك حذف حالة خاصة واحدة هذا الأسبوع؟
التعقيد هو الفجوة بين ما تتوقعه أن يحدث عندما تُجري تغييرًا في النظام وما يحدث بالفعل.
تُشعر به عندما تبدو التعديلات البسيطة خطيرة لأنك لا تستطيع التنبؤ بنطاق الأثر (اختبارات، خدمات، إعدادات، عملاء، أو حالات هامشية قد تتعطّل).
ابحث عن إشارات تفيد بأن التفكير صار مكلفًا:
التعقيد الأساسي ينبع من المجال نفسه (لوائح، حالات هامشية في العالم الحقيقي، قواعد عمل جوهرية). لا يمكنك حذفه—بل يجب نمذجته جيدًا.
التعقيد العَرَضي هو الذي نُحدثه بأنفسنا (واجهات متسربة، منطق مكرر، أوضاع/أعلام كثيرة، واجهات برمجية غير واضحة). هذا هو الجزء الذي يمكن للفرق تقليله بانتظام عبر التصميم والتبسيط.
وحدة عميقة تقوم بالكثير وتعرض واجهة صغيرة، مستقرة، وسهلة الفهم. تمتص الوحدة العميقة التفاصيل الفوضوية (إعادة المحاولة، التسلسل، الصيغ، الثوابت) حتى لا يحتاج المستدعون لمعرفة تلك التعقيدات.
اختبار عملي: إذا كان أغلب المستدعين يمكنهم استخدام الوحدة بشكل صحيح دون معرفة القواعد الداخلية، فهي عميقة؛ إذا اضطر المستدعون لحفظ قواعد وتسلسلات، فهي سطحية.
أعراض شائعة:
legacy, skipValidation, force, mode).فضلًا واجهات برمجة تطبيقات تكون:
عندما تفكر في إضافة "خيار واحد فقط" اسأل أولًا هل يمكن إعادة تصميم الواجهة حتى لا يضطر معظم المستدعين للتفكير في هذا الخيار.
استعمل الأعلام للنشر الآمن، ثم عاملها كدين يجب سداده:
الأعلام الطويلة الأمد تضاعف عدد "الأنظمة" التي يجب على المهندسين التفكير بها.
اجعل التعقيد صريحًا أثناء التخطيط، لا تكتفه بمراجعات الكود:
الهدف هو فرض المقايضات لئلا يصبح التعقيد مؤسسيًا.
البرمجة التكتيكية تَحسّن لهذا الأسبوع: تصحيحات سريعة، تغييرات قليلة، "اشحنها".
البرمجة الاستراتيجية تَحسّن للعام القادم: إعادة تصميم صغيرة تمنع نفس فئات الأخطاء وتقلل العمل المستقبلي.
قاعدة عملية: إذا تطلب الإصلاح معرفة من المستدعي ("تذكّر أن تنادي X أولًا" أو "ضَع هذا العلم فقط في الإنتاج"), فغالبًا تحتاج إلى تغيير استراتيجي لإخفاء ذلك التعقيد داخل الوحدة.
الدرس الدائم من Tcl هو قوة مجموعة صغيرة من البدائل مع تركيز على التركيب—غالبًا كطبقة "لاصقة" مضمّنة.
نُظُم معاصرة مكافئة:
الهدف التصميمي نفسه: اجعل النواة بسيطة ومستقرة، ودَع التغيير يحدث عبر واجهات واضحة.
الوحدات السطحية قد تبدو منظمة لكنها تنقل التعقيد إلى كل مستدٍ.