إصدار PDF من عنوان تنزيل PPT:
ملاحظة: خلال عملية الترتيب ، وجدت أن أفكار المؤلف تكررت ، لذلك حذف بعضها. إذا كانت لغتك الإنجليزية جيدة ، فيرجى قراءة PPT الإنجليزية مباشرة.
فيما يلي الفصول الرئيسية لهذه المقالة:
1. ما هو "برنامج JavaScript الكبير"؟
2. النظر في بنية البرنامج الحالية
3. الاعتبار على المدى الطويل
4. العصف الذهني
5. الهندسة المعمارية المقترحة
5.1 نمط التصميم
5.1.1 نظرية الوحدة النمطية
5.1.1.1 نظرة عامة
5.1.1.2 وضع الوحدة النمطية
5.1.1.3 كائن حجم الوجه الذاتي
5.1.1.4 وحدة CommonJS
5.1.2 وضع الواجهة
5.1.3 وضع الوسيط
5.2 تنطبق على الهندسة المعمارية الخاصة بك
5.2.1 واجهة - التجريد الأساسي
5.2.2 الوسيط - Core Program
5.2.3 العمل عن كثب
6. نشر الحانة/الامتداد الفرعي: أحداث التسجيل التلقائي
7. سؤال وجواب
8. شكر وتقدير
ما هو "برنامج JavaScript الكبير"؟
قبل أن نبدأ ، دعونا نحدد موقع JavaScript الكبير. كما تم تحدي العديد من خبراء تطوير JS ذوي الخبرة. يقول بعض الأشخاص أن أكثر من 100000 سطر من كود JavaScript يعتبر كبيرًا ، ويقول بعض الأشخاص إن رمز JavaScript يجب أن يكون حجمه أكثر من 1 ميغابايت. في الواقع ، لا يوجد أي منهما صحيح ، لأنه لا يمكن قياس كمية الكود كعدد الرموز المثبتة. يمكن أن تتجاوز العديد من رمز JS التافهة 100000 سطر بسهولة.
تعريفي لـ "Big" على النحو التالي. على الرغم من أنه قد لا يكون صحيحًا ، إلا أنه يجب أن يكون قريبًا نسبيًا:
أنا شخصياً أعتقد أن برامج JavaScript الكبيرة يجب أن تكون مهمة للغاية وأن تتضمن العديد من جهود المطورين المتميزين لمعالجة بيانات الوزن الثقيل وعرضها على المتصفح.
مراجعة بنية البرنامج الحالية
لا يمكنني التأكيد على مدى أهمية هذه القضية. غالبًا ما يقول العديد من المطورين ذوي الخبرة: "إن أنماط الإبداع والتصميم الحالية تعمل بشكل جيد للغاية في مشروعي السابق متوسط الحجم ، لذلك يجب أن يكون من الجيد استخدامها مرة أخرى في برنامج أكبر قليلاً ، أليس كذلك؟" ، هذا صحيح على برامج معينة ، ولكن لا تنسى أنه نظرًا لأنه برنامج كبير ، يجب أن يكون هناك عادة مخاوف كبيرة يجب أن يتم إحياءها وإحياء الاهتمام. أشرح بإيجاز كيف يستغرق الأمر بعض الوقت لمراجعة بنية البرنامج التي تم تشغيلها لفترة طويلة. في معظم الحالات ، يجب أن تبدو بنية برنامج JavaScript الحالية مثل هذا (لاحظ أنها بنية JS ، وليس ما يسميه الجميع في كثير من الأحيان ASP.NET MVC):
الأدوات الحاجيات المخصصة
النماذج
وجهات النظر
وحدات التحكم
قوالب
المكتبات/مجموعات الأدوات
جوهر التطبيق.
يمكنك أيضًا تغليف البرنامج إلى وحدات متعددة وحدها ، أو استخدام أنماط تصميم أخرى ، وهو أمر رائع ، ولكن إذا كانت هذه الهياكل تمثل بنيةك بالكامل ، فقد تكون هناك بعض المشكلات المحتملة. لنلقي نظرة على بعض النقاط المهمة:
1. كم عدد الأشياء في الهندسة المعمارية التي يمكن إخراجها وإعادة استخدامها على الفور؟
هل هناك بعض الوحدات النمطية التي لا تعتمد على التعليمات البرمجية الأخرى؟ هل هو مستقل ذاتي؟ إذا ذهبت إلى قاعدة التعليمات البرمجية التي تستخدمها ، ثم حدد بعض رموز الوحدة النمطية ووضعها على صفحة جديدة ، هل يمكن استخدامها على الفور؟ قد تقول أن المبدأ على ما يرام. أقترح عليك التخطيط لفترة طويلة. إذا طورت شركتك العديد من البرامج المهمة من قبل ، فجأة قال أحدهم أن وحدة الدردشة في هذا المشروع جيدة ، دعنا نخرجها ونضعها في مشروع آخر. هل يمكنك فقط استخدامه دون تعديل الرمز؟
2. كم عدد الوحدات النمطية التي يحتاجها النظام إلى الاعتماد على وحدات أخرى؟
هل جميع وحدات النظام مقترنة بإحكام؟ قبل أن أتناول هذا السؤال كقلق ، سأشرح أولاً. ليس الأمر أن جميع الوحدات يجب ألا يكون لها أي تبعيات. على سبيل المثال ، يمكن تمديد وظيفة الحبيبات الدقيقة من وظيفة الأساس. مشكلتي تختلف عن هذا الموقف. أنا أتحدث عن التبعيات قبل الوحدات الوظيفية المختلفة. من الناحية النظرية ، لا ينبغي أن تحتوي جميع الوحدات الوظيفية المختلفة على الكثير من التبعيات.
3. إذا حدث خطأ ما في جزء واحد من برنامجك ، فهل ستظل الأجزاء الأخرى تعمل؟
إذا قمت بإنشاء برنامج مشابه لـ Gmail ، فيمكنك أن تجد أنه يتم تحميل العديد من الوحدات في Gmail ديناميكيًا ، مثل وحدة دردشة الدردشة ، والتي لا يتم تحميلها عند تهيئة الصفحة ، وحتى إذا حدث خطأ بعد التحميل ، يمكن استخدام أجزاء أخرى من الصفحة بشكل طبيعي.
4. هل يمكنك اختبار الوحدات النمطية الخاصة بك بطريقة بسيطة للغاية؟
يمكن استخدام كل من وحداتك في مواقع كبيرة مع ملايين المستخدمين ، أو حتى مواقع متعددة تستخدمها ، لذلك تحتاج وحداتك إلى الوقوف في الاختبار ، أي سواء داخل البنية أو خارجها ، يجب أن تكون قادرة على اختبارها بكل بساطة ، بما في ذلك معظم التأكيدات التي يمكن تمريرها في بيئات مختلفة.
النظر على المدى الطويل
عند هيكلة البرامج الكبيرة ، فإن أهم شيء هو أن تكون تطلعية. لا يمكنك التفكير في الموقف بعد شهر واحد أو سنة واحدة فقط. يجب أن تفكر في إمكانية حدوث تغييرات في فترة زمنية أطول؟ غالبًا ما يربط المطورون رمز عمليات DOM وبرنامجه بإحكام للغاية ، على الرغم من أنهم في بعض الأحيان قد غازوا منطقًا منفصلًا في وحدات مختلفة. فكر في سبب كونها غير جيدة على المدى الطويل.
قال زميل لي ذات مرة إن الهندسة المعمارية الدقيقة قد لا تكون مناسبة للسيناريوهات المستقبلية ، وأحيانًا يكون ذلك صحيحًا ، ولكن عندما تحتاج إلى القيام بذلك ، ستدفع الكثير من المال. على سبيل المثال ، قد تحتاج إلى اختيار استبدال Dojo و JQuery و Zepto و Yui لبعض أسباب الأداء والأمان والتصميم. في هذا الوقت ، هناك مشكلة. معظم الوحدات لديها تبعيات ، والتي تتطلب المال والوقت والناس ، أليس كذلك؟
لا بأس بالنسبة لبعض المواقع الصغيرة ، لكن المواقع الكبيرة تحتاج إلى توفير آلية أكثر مرونة دون القلق بشأن المشكلات المختلفة بين الوحدات المختلفة. هذا يوفر المال والوقت.
لتلخيص ، هل يمكنك الآن التأكد من أنه يمكنك استبدال بعض مكتبات الفصل دون إعادة كتابة البرنامج بأكمله؟ إذا لم يكن الأمر كذلك ، فإن ما سنتحدث عنه أدناه هو أكثر ملاءمة لك.
قدم العديد من مطوري JavaScript ذوي الخبرة بعض الملاحظات الرئيسية:
قال جاستن ماير ، مؤلف كتاب JavaScriptMVC ،
إن أكبر سر لبناء برامج كبيرة هو أنك لا تقوم أبدًا ببناء برامج كبيرة ، ولكنها تقسم البرامج إلى وحدات صغيرة لجعل كل وحدة صغيرة يمكن اختبارها ، كبيرة ، ثم دمجها في البرنامج.
مؤلف مواقع جافا سكريبت عالية الأداء نيكولاس ، زكاس:
"المفتاح هو الإقرار منذ البداية بأنه ليس لديك أي فكرة عن كيفية نمو هذا. عندما تقبل أنك لا تعرف كل شيء ، فأنت تبدأ في تصميم النظام بشكل دفاعي. يمكنك تحديد المجالات الرئيسية التي قد تتغير ، والتي غالبًا ما تكون سهلة للغاية عندما تضع بعض الوقت فيه. -
الكثير من مشاكل النص مزعجة للغاية. لتلخيص ، يمكن تغيير كل شيء ، لذلك يجب أن يكون مجردة.
مؤلفة جويكري أساسيات ريبيكا مورفي:
كلما اقتربت العلاقة بين كل وحدة ، كلما كان قابلاً لإعادة الاستخدام أقل ، وكلما زادت صعوبة تغييرها.
الآراء المهمة أعلاه هي العناصر الأساسية لبناء الهندسة المعمارية ونحن بحاجة إلى تذكرها طوال الوقت.
العصف الذهني
دعونا نعتزم العصف الذهني. نحتاج إلى بنية مقترنة بشكل فضفاض ، مع عدم وجود تبعيات بين الوحدات ، كل وحدة وبرنامج تواصل ، ثم تتولى الطبقة الوسيطة الرسائل المقابلة.
على سبيل المثال ، إذا كان لدينا جافا سكريبت بناء برنامج مخبز عبر الإنترنت ، فإن الوحدة النمطية ترسل رسالة قد تكون "هناك 42 طلقة تحتاج إلى تسليمها". نستخدم طبقات طبقات مختلفة لمعالجة الرسائل المرسلة بواسطة الوحدة ، ونقوم بما يلي:
الوحدات النمطية لا تصل مباشرة إلى جوهر البرنامج
الوحدات النمطية لا تتصل مباشرة أو تؤثر على الوحدات الأخرى
هذا سيمنعنا من ارتكاب أخطاء في جميع الوحدات النمطية بسبب الأخطاء في وحدة معينة.
مشكلة أخرى هي الأمن. الوضع الحقيقي هو أن معظم الناس لا يعتقدون أن الأمن الداخلي يمثل مشكلة. نقول في قلوبنا أن البرامج بنيت بنفسي. أنا أعرف أي منها عامة وخاصة. لا توجد مشكلة في الأمان ، ولكن هل لديك طريقة لتحديد الوحدة النمطية للوصول إلى جوهر البرنامج؟ على سبيل المثال ، هناك وحدة دردشة الدردشة التي لا أريدها أن أتصل بوحدة المسؤول ، أو لا أريدها أن أتصل بوحدة مع أذونات كتابة DB ، لأن هناك هشاشة بينهما ومن السهل التسبب في هجمات XSS. لا ينبغي أن تكون كل وحدة قادرة على القيام بكل شيء ، ولكن رمز JavaScript في معظم البنى لديه هذه المشكلة حاليًا. توفير طبقة وسيطة للتحكم في الوحدة التي يمكنها الوصول إلى هذا الجزء المصرح به ، أي أن الوحدة النمطية يمكنها فقط تحقيق معظم الجزء الذي أذن به.
العمارة المقترحة
ينصب تركيز مقالتنا على أن البنية التي نقترحها هذه المرة تستخدم أنماط التصميم التي نعتبرها جميعًا معروفة: الوحدة النمطية والواجهة والوسيط.
على عكس النماذج التقليدية ، من أجل فصل كل وحدة ، ندع الوحدة فقط تنشر بعض أحداث الأحداث. يمكن أن يكون وضع الوسيط مسؤولاً عن الاشتراك في رسائل الرسائل من هذه الوحدات ، ثم التحكم في استجابة الإخطار. يقيد مستخدمو وضع الواجهة أذونات كل وحدة.
فيما يلي الأجزاء التي نحتاجها للانتباه إلى:
1 نمط التصميم
1.1 نظرية الوحدة النمطية
1.1.1 نظرة عامة
1.1.2 وضع الوحدة النمطية
1.1.3 كائن حجم الوجه الذاتي
1.1.4 وحدة CommonJS
1.2 وضع الواجهة
1.3 وضع الوسيط
2 تنطبق على الهندسة المعمارية الخاصة بك
2.1 واجهة - التجريد الأساسي
2.2 الوسيط - CORE البرنامج
2.3 العمل بشكل وثيق معا
نظرية مشروط
قد يكون كل شخص قد استخدم رمزًا معياريًا أكثر أو أقل. الوحدة هي جزء من بنية البرنامج الكاملة والقوية. يتم إنشاء كل وحدة لغرض منفصل. بالعودة إلى Gmail ، دعنا نأخذ مثالًا. يبدو أن وحدة دردشة الدردشة جزء منفصل ، ولكن في الواقع لديها العديد من العلامات الفرعية المنفصلة. على سبيل المثال ، تعد وحدة التعبير في الداخل عبارة عن وحدة فرعية منفصلة ، والتي يتم استخدامها أيضًا على النافذة لإرسال رسائل البريد الإلكتروني.
آخر هو أنه يمكن تحميل الوحدات النمطية وحذفها واستبدالها ديناميكيًا.
في JavaScript ، لدينا عدة طرق لتنفيذ الوحدات النمطية. الجميع على دراية بأنماط الوحدة النمطية والحرفية الكائن. إذا كنت على دراية بذلك بالفعل ، فيرجى تجاهل هذا القسم والقفز مباشرة إلى جزء CommonJS.
وضع الوحدة النمطية
نمط الوحدة هو نمط تصميم شائع نسبيا. يمكن أن يتغلف المتغيرات الخاصة والأساليب والولايات من خلال الأقواس. من خلال لف هذه المحتويات ، لا يمكن الوصول إلى الكائنات العالمية بشكل عام مباشرة. في نمط التصميم هذا ، يتم إرجاع واجهة برمجة تطبيقات واحدة فقط ، ويتم تغليف جميع المحتويات الأخرى على أنها خاصة.
بالإضافة إلى ذلك ، يشبه هذا النمط تعبيرات الوظيفة المنفذة ذاتيا. الفرق الوحيد هو أن الوحدة تُرجع كائنًا ، بينما يقوم تعبير الوظيفة ذاتي التنفيذ بإرجاع وظيفة.
كما نعلم جميعًا ، لا تريد JavaScript أن يكون لدى اللغات الأخرى معدلات الوصول ، ولا يمكنها إعلان المعدلات الخاصة والعامة لكل حقل أو طريقة. فكيف ننفذ هذا النمط؟ وهذا هو لإرجاع كائن ، بما في ذلك بعض الأساليب العامة ، التي لديها القدرة على استدعاء الكائنات الداخلية.
ألق نظرة على الرمز أدناه. هذا الرمز هو رمز التنفيذ الذاتي. يتضمن الإعلان كائن عالمي Batterymodule. صفيف السلة هو خاص ، لذلك لا يمكن للبرنامج بأكمله الوصول إلى هذه المجموعة الخاصة. في الوقت نفسه ، نعيد كائن ، والذي يحتوي على 3 طرق (مثل AddItem ، GetItemCount ، GetTotal). يمكن لهذه الطرق الثلاثة الوصول إلى صفيف السلة الخاص.
var SCANEDMODULE = (function () {var basket =] } return p ؛}} ()) ؛لاحظ أيضًا أن الكائن الذي نرجعه يتم تعيينه مباشرة إلى سلة السلة ، حتى نتمكن من استخدامه مثل ما يلي:
. console.log (SCATERModule.getItemCount ()) ؛ console.log (SCATERMODULE.GETTOTAL ()) ؛ // ومع ذلك ، فإن ما يلي لن يعمل: console.log (scarentmodule.basket) ؛ // (غير محدد كما لا داخل الكائن الذي تم إرجاعه) console.log (السلة) ؛ // (موجود فقط في نطاق الإغلاق)
فكيف تفعل ذلك في العديد من المكتبات الدراسية الشعبية (مثل Dojo ، jQuery)؟
دوجو
يحاول دوجو استخدام dojo.declare لتوفير طرق إعلان على غرار الفصل. يمكننا استخدامه لتنفيذ نمط الوحدة النمطية. على سبيل المثال ، إذا كنت تريد إعلان كائن سلة تحت مساحة اسم المتجر ، فيمكنك القيام بذلك:
// متجر Wayvar التقليدي = Window.store || {} ؛ store.basket = store.basket || {} ؛ // باستخدام dojo.setObjectDojo.setObject ("store.basket.object" ، (function () {var basket =]إنه قوي جدًا عند دمجه مع dojo.provide.
يوي
الرمز التالي هو التنفيذ الأصلي لـ Yui:
yahoo.store.basket = function () {// "private" المتغيرات: var myprivarvar = "يمكن الوصول إلى فقط داخل yahoo.store.basket." ؛ // "الخاص" الطريقة: var myprivatemethod = function () {yahoo.log ("يمكن الوصول إلى فقط من داخل yahoo.store.basket") ؛ } return {myPublicProperty: "أنا خاصية عامة." ، mypublicmethod: function () {yahoo.log ("أنا طريقة عامة.") ؛ // داخل السلة ، يمكنني الوصول إلى Vars والطرق "الخاصة": yahoo.log (myPrivinVar) ؛ yahoo.log (myprivatemethod ()) ؛ // النطاق الأصلي لـ MyPublicMethod هو المتجر حتى نتمكن من الوصول إلى أعضاء Public باستخدام "This": yahoo.log (this.mypublicProperty) ؛ }} ؛} () ؛jQuery
هناك العديد من تطبيقات نمط الوحدة النمطية في jQuery. دعونا نلقي نظرة على مثال مختلف. تعلن وظيفة المكتبة عن مكتبة جديدة. ثم عند إنشاء المكتبة ، يتم تنفيذ طريقة init تلقائيًا في المستند. جاهز.
Function Library (module) {$ (function () {if (module.init) {module.init () ؛}}) ؛ وحدة الإرجاع ؛} var mylibrary = library (function () {return {init: function () { /*explive* /}} ؛} ()) ؛كائن حجم الوجه الذاتي
يتم الإعلان عن قياس الوجه الذاتي للكائن في الأقواس ، والكلمة الرئيسية الجديدة غير مطلوبة عند استخدامها. إذا كنت لا تهتم كثيرًا بالجمهور/الخاص لحقول السمات في وحدة نمطية ، فيمكنك استخدام هذه الطريقة ، ولكن يرجى ملاحظة أن هذه الطريقة تختلف عن JSON. كائن الحجم الذاتي: var item = {name: "tom" ، القيمة: 123} json: var item = {"name": "tom" ، "value": 123}.
var mymodule = {myProperty: 'SomeValue' ، // يمكن أن تحتوي الحرفية على خصائص وطرق. // هنا ، يتم تعريف كائن آخر للتكوين // الأغراض: myConfig: {Usecaching: true ، اللغة: 'en'} ، // طريقة أساسية للغاية mymethod: function () {console.log ('I an an an an an ang haz؟') ؛ } ، // إخراج قيمة تعتمد على التكوين الحالي mymethod2: function () {console.log ('التخزين المؤقت هو:' + (this.myconfig.usecaching)؟ } ، // تجاوز التكوين الحالي mymethod3: function (newConfig) {if (typeof newConfig == 'Object') {this.myconfig = newConfig ؛ console.log (this.myconfig.language) ؛ }}} ؛ mymodule.mymethod () ؛ // يمكنني haz functionalitymymodule.mymethod2 () ؛ // مخرجات EnupplyMymodule.myMethod3 ({language: 'fr' ، usecaching: false}) ؛ // الابCommonJs
لن أتحدث عن إدخال CommonJs هنا. قدمت العديد من المقالات من قبل. ما نريد أن نذكره هنا هو أن هناك صادرتان مهمتان ويتطلبان في معيار CommonJS. تمثل الصادرات الوحدة المراد تحميلها ، وتتطلب أن هذه الوحدات المحملة تحتاج إلى الاعتماد على وحدات أخرى وتحتاج أيضًا إلى تحميلها.
/*مثال على تحقيق التوافق مع AMD و Commonjs القياسية عن طريق وضع Boilerplate حول تنسيق وحدة CommonJS القياسية:*/(الدالة (define) {define (function (require ، orports) {// module contents var dep1 = require ("dep1") ؛ exports.someexportedfunction = function () {...} ؛ define == "function"؟ define: function (factory) {factory (require ، orports)}) ؛هناك العديد من تطبيقات تحميل الوحدة النمطية CommonJS. ما أفضل هو المطلوبة. هل يمكنه تحميل الوحدات النمطية ووحدات التبعية ذات الصلة جيدًا؟ لنأخذ مثالًا بسيطًا. على سبيل المثال ، إذا كنت بحاجة إلى تحويل الصورة إلى رمز ASCII ، فنحن أولا تحميل وحدة التشفير ، ثم نحصل على طريقة encodetoascii الخاصة بها. من الناحية النظرية ، يجب أن يكون الرمز كما يلي:
var encodetoascii = require ("encoder"). encodetoascii ؛ orports.encodesomesource = function () {// بعد عمليات أخرى ، ثم استدعاء encodetoascii}ومع ذلك ، فإن الكود أعلاه لا يعمل ، لأن وظيفة encodetoascii لا تستخدم لتوصيلها بكائن النافذة ، لذلك لا يمكن استخدامها. هذا ما يحتاجه تحسين الكود:
define (function (require ، orports ، module) {var encodetoascii = require ("Encoder"). Encodetoascii ؛ exports.encodesomesource = function () {// process ثم استدعاء encodetoascii}}) ؛لدى CommonJS إمكانات كبيرة ، ولكن نظرًا لأن العم ليس على دراية به ، فلن أقدمه كثيرًا.
وضع الواجهة
يحتل نموذج الواجهة دورًا مهمًا في بنية هذا النموذج. تنعكس العديد من مكتبات فئة JavaScript أو الأطر في هذا النموذج. الوظيفة الأكبر هي تضمين واجهة برمجة التطبيقات للمستوى العالي لإخفاء تطبيقات محددة. هذا يعني أننا نعرض الواجهات فقط ، ويمكننا اتخاذ قرارات التطبيقات الداخلية من قبل أنفسنا ، مما يعني أيضًا أنه يمكن تعديل رمز التنفيذ الداخلي وتحديثه بسهولة. على سبيل المثال ، تستخدم اليوم jQuery لتنفيذها ، وغدًا تريد تغيير Yui ، وهو مريح للغاية.
في المثال التالي ، يمكننا أن نرى أننا نقدم العديد من الأساليب الخاصة ، ثم كشف واجهة برمجة تطبيقات بسيطة للسماح للعالم الخارجي بتنفيذ الأساليب الداخلية واتصالها:
var module = (function () {var _private = {i: 5 ، get: function () {console.log ('value current:' + this.i) ؛} ، set: function (val) {this.i = val ؛} ، Run: function () {console.log ('running') ؛ (args) {_private.set (args.val) ؛الفرق بين الواجهة وما نتحدث عنه أدناه هو أن الواجهة توفر فقط الوظائف الحالية ، بينما يمكن للوسطاء إضافة وظائف جديدة.
وضع الوسيط
قبل الحديث عن الوسيط ، دعونا نقدم مثالاً. نظام مراقبة الطيران في المطار ، وهو البرج الأسطوري ، له قوة مطلقة. يمكن أن تتحكم في وقت الإقلاع والهبوط ومكان أي طائرة. لا يُسمح للطائرة والطائرة بالتواصل من قبل ، مما يعني أن البرج هو جوهر المطار ، والوسيط يعادل هذا البرج.
يتم استخدام الوسيط للحصول على وحدات متعددة في البرنامج ولا تريد أن يكون لكل وحدة تبعيات ، فإن وضع الوسيط يمكن أن يحقق الغرض من التحكم المركزي. في السيناريوهات الفعلية ، يقوم الوسيط بتغليف العديد من الوحدات التي لا يرغبون في القيام بها ، مما يسمح لهم بالتوصيل من خلال الوسطاء ، وأيضًا اقترانهم بشكل فضفاض ، بحيث يتعين عليهم التواصل من خلال الوسطاء.
إذن ما هي مزايا وضع الوسيط؟ هذا هو الفصل. إذا كان لديك فهم جيد لنمط المراقب من قبل ، فسيكون من السهل نسبيًا فهم مخطط الوسيط أدناه. الشكل التالي هو مخطط نمط الوسيط عالي المستوى:
فكر في الأمر ، كل وحدة ناشر ، والوسيط هو ناشر ومشترك.
تبث الوحدة 1 شيئًا فعليًا للوسيط ، قائلاً إن شيئًا ما يجب القيام به
بعد أن يلتقط الوسيط الرسالة ، ابدأ على الفور الوحدة 2 التي يجب استخدامها لمعالجة الرسالة. بعد الانتهاء من معالجة الوحدة 2 ، أعد المعلومات إلى الوسيط.
في الوقت نفسه ، يبدأ الوسيط أيضًا الوحدة 3 ، ويسجل تلقائيًا إلى الوحدة 3 عند تلقي رسالة الإرجاع للوحدة 2.
يمكن ملاحظة أنه لا يوجد اتصال بين الوحدات النمطية. بالإضافة إلى ذلك ، يمكن للوسيط أيضًا تنفيذ وظيفة مراقبة حالة كل وحدة. على سبيل المثال ، إذا كان هناك خطأ في الوحدة 3 ، يمكن للوسيط أن يرغب مؤقتًا فقط في وحدات أخرى ، ثم أعد تشغيل الوحدة 3 ، ثم تستمر في التنفيذ.
إذا نظرنا إلى الوراء ، يمكننا أن نرى أن ميزة الوسيط هي أن الوحدة النمطية المزدوجة يتم التحكم فيها بواسطة الوسيط نفسه. تحتاج الوحدة فقط إلى البث والاستماع إلى الأحداث ، وليس هناك حاجة للاتصال المباشر بين الوحدات النمطية. بالإضافة إلى ذلك ، يمكن استخدام وحدات متعددة لمعالجة المعلومات في وقت واحد ، مما يسهلنا أيضًا إلى إضافة وحدات جديدة إلى منطق التحكم الحالي في المستقبل.
من المؤكد أنه نظرًا لأن جميع الوحدات لا يمكن أن تتواصل مباشرة ، فقد يكون هناك انخفاض طفيف في الأداء في كل شيء نسبيًا ، لكنني أعتقد أن الأمر يستحق ذلك.
دعونا نستخدم عرضًا بسيطًا استنادًا إلى التفسير أعلاه:
var mediator = (function () {var subscribe = function (channel ، fn) {if (! mediator.channels [channel]) midiator.channels [channel] = [] Array.Protype.Slice.Call (الوسيطات ، (VAR I = 0 ، L = MIDIATRED.CHANNELS ؛ الاشتراك: installto: function (obj) {obj.subscribe = اشترك ؛ثم هناك وحدتان تسمى:
// pub/sub على وسيط وسيط مركزي. name = "tim" ؛ mediator.subscribe ('namechange' ، function (arg) {console.log (this.name) ؛ this.name = arg ؛ console.log (this.name) ؛}) ؛ MEDIATR.Publish ('NameChange' ، 'David') ؛ // Tim ، David // pub/sub عبر الوسيط من طرف ثالث var obj = {name: 'sam'} ؛ mediator.installto (obj) ؛ obj.subscribe ('namechange' ، function (arg) {console.log (this.name) ؛ this.name = arg OBJ.Publish ('namechange' ، 'John') ؛ // سام ، جونواجهة التطبيق: تجريد جوهر التطبيق
الواجهة تعمل كملخص ل Core Application ، وهي مسؤولة عن التواصل بين الوسيط والوحدة. لا يمكن لكل وحدة التواصل إلا مع جوهر البرنامج من خلال هذه الواجهة. تتمثل المسؤولية كتجريدي في التأكد من توفير هذه الوحدات مع واجهة متسقة في أي وقت ، والتي تشبه دور وحدة التحكم في SendBox. تتواصل جميع مكونات الوحدة النمطية مع الوسطاء من خلالها ، لذلك يجب أن تكون الواجهة موثوقة وجديرة بالثقة. في الوقت نفسه ، كدالة لتوفير واجهة للوحدة ، تحتاج الواجهة إلى لعب دور آخر ، أي السيطرة على الأمان ، أي لتحديد جزء من البرنامج يمكن الوصول إليه بواسطة وحدة. لا يمكن لمكونات الوحدة النمطية استدعاء أساليبها إلا ولا يمكنها الوصول إلى أي محتوى غير مصرح به. على سبيل المثال ، قد تبث وحدة DataValidationCompletedWritEdB ، حيث تحتاج فحص الأمان إلى التأكد من أن الوحدة النمطية تحتوي على أذونات للكتابة إلى قاعدة البيانات.
باختصار ، يمكن للوسيط إجراء معالجة المعلومات فقط بعد اكتشاف تفويض الواجهة.
وسيط التطبيق: جوهر التطبيق
يعمل الوسيط كدور أساسي للتطبيق ، دعنا نتحدث بإيجاز عن مسؤولياته. المهمة الأكثر جوهرية هي إدارة دورة حياة الوحدة النمطية. عندما يلتقط هذا النواة أي معلومات ، فإنه يحتاج إلى الحكم على كيفية تعامله مع البرنامج - أي ، لتحديد الوحدة النمطية التي ستبدأ أو تتوقف. عند بدء تشغيل الوحدة النمطية ، يجب أن يكون قادرًا على التنفيذ تلقائيًا ، دون أن يقرر جوهر التطبيق ما إذا كان ينبغي تنفيذها (على سبيل المثال ، ما إذا كان ينبغي تنفيذها عندما تكون DOM جاهزة) ، لذلك تحتاج الوحدة نفسها إلى تحديدها.
قد يكون لديك سؤال ، تحت أي ظروف ستتوقف الوحدة النمطية؟ عندما يكتشف البرنامج أن الوحدة النمطية تفشل أو ارتكبت خطأ ، يحتاج البرنامج إلى اتخاذ قرار لمنع الطريقة في الوحدة النمطية من الاستمرار في التنفيذ بحيث يمكن إعادة تشغيل المكون ، مع الغرض الرئيسي من تحسين تجربة المستخدم.
بالإضافة إلى ذلك ، يجب أن يكون النواة قادرة على إضافة أو حذف الوحدات النمطية أو حذفها ديناميكيًا دون التأثير على أي وظائف أخرى. مثال شائع هو أن الوحدة النمطية غير متوفرة في بداية تحميل الصفحة ، ولكن بعد عمل المستخدم ، يحتاج إلى تحميل الوحدة النمطية ثم تنفيذها. تمامًا مثل وظيفة الدردشة في Gmail ، يجب أن يكون من السهل فهمها من الغرض من تحسين الأداء.
تتم معالجة معالجة الأخطاء الاستثناء أيضًا بواسطة جوهر التطبيق. بالإضافة إلى ذلك ، عندما تبث كل وحدة معلومات ، فإنها تبث أيضًا أي أخطاء إلى القلب بحيث يمكن لبرنامج CORE إيقاف/إعادة تشغيل هذه الوحدات وفقًا للموقف. هذا أيضًا جزء مهم للغاية من الهندسة المعمارية المربوطة. لا نحتاج إلى تغيير أي وحدات يدويًا. يمكننا القيام بذلك باستخدام النشر/الاشتراك من خلال الوسيط.
تجمع
كل وحدة تحتوي على وظائف مختلفة في البرنامج. عندما يكون لديهم معلومات يجب معالجتها ، فإنهم يصدرون معلومات لإعلام البرنامج (هذه هي مسؤوليتهم الرئيسية). ذكر قسم ضمان الجودة التالي أن الوحدات النمطية يمكن أن تعتمد على بعض طرق تشغيل أدوات DOM ، ولكن لا ينبغي أن تعتمد على وحدات أخرى من النظام. يجب ألا تنتبه الوحدة النمطية للمحتوى التالي:
1. أي كائن أو وحدة مشتركة بين المعلومات التي نشرتها هذه الوحدة
2. هل هذه الكائنات عميل أو كائنات من جانب الخادم
3. كم عدد الكائنات التي اشتركت في معلوماتك
يتجنب جوهر تطبيق تجريد الواجهة التواصل المباشر بين الوحدات النمطية. يشترك في معلومات من كل وحدة ، وهي مسؤولة أيضًا عن اكتشاف التفويض ، مما يضمن أن لكل وحدة ترخيص منفصل خاص بها.
يستخدم الوسيط (Core Application) وضع الوسيط للعب دور مدير النشر/الاشتراك ، المسؤول عن إدارة الوحدات النمطية وتنفيذ وحدة بدء/إيقاف ، ويمكنه تحميل وحدات وإعادة تشغيلها مع أخطاء.
تتمثل نتيجة هذه البنية في أنه لا يوجد أي اعتماد بين الوحدات النمطية ، بسبب التطبيقات المقترنة بشكل فضفاض ، يمكن اختبارها بسهولة وصيانتها ، يمكن إعادة استخدام كل وحدة بسهولة في مشاريع أخرى ، أو يمكن إضافتها وحذفها ديناميكيًا دون التأثير على البرنامج.
نشر الحانة/الامتداد الفرعي: تسجيل الأحداث التلقائي
فيما يتعلق بالتسجيل التلقائي للأحداث ، يجب اتباع بعض مواصفات التسمية. على سبيل المثال ، إذا نشرت وحدة نمطية حدث يسمى MessageUpdate ، فسيتم تنفيذ جميع الوحدات باستخدام طريقة MessageUpdate تلقائيًا. هناك فوائد ومزايا وعيوب. لطرق التنفيذ المحددة ، يمكنك رؤية منشور آخر مني: الإصدار السحري الذي تمت ترقيته من JQuery Custom Binding.
QA
1. هل من الممكن عدم استخدام واجهة أو وضع رمل مشابه؟
على الرغم من أن الخطوط العريضة للهندسة المعمارية تقترح أن الواجهة يمكنها تنفيذ وظائف التحقق من التفويض ، إلا أنه من الممكن تمامًا أن يتمكن الوسطاء من القيام بذلك. ما يجب أن يفعله بنية الضوء هو نفسه تقريبًا ، أي فصل وضمان أن كل وحدة يتواصل مباشرة مع جوهر التطبيق أمر جيد.
2. لقد تحسنت أن الوحدة لا يمكن أن تعتمد مباشرة. هل يعني ذلك أنه لا يمكن أن يعتمد على أي مكتبة طرف ثالث (مثل jQuery).
هذه في الواقع قضية على الوجهين. كما ذكرنا أعلاه ، قد تحتوي الوحدة النمطية على بعض العلامات الفرعية ، أو الوحدات الأساسية ، مثل فئات أداة تشغيل DOM الأساسية ، وما إلى ذلك ، في هذا المستوى ، يمكننا استخدام مكتبة الطرف الثالث ، ولكن يرجى التأكد من أنه يمكننا استبدالها بسهولة.
3. أحب هذه الهندسة المعمارية وأريد البدء في استخدام هذه البنية. هل هناك أي عينات رمز يمكن استخدامها للإشارة إليها؟
أخطط لعمل نموذج رمز للرجوع إليه ، ولكن قبل ذلك ، يمكنك الرجوع إلى أندرو بيرجيس بعد كتابة جافا سكريبت.
4. هل من الممكن إذا احتاجت الوحدة إلى التواصل مباشرة مع جوهر التطبيق؟
من الناحية الفنية ، لا يوجد سبب يمنع الوحدات النمطية مباشرة مع جوهر التطبيق الآن ، ولكن بالنسبة لمعظم تجارب التطبيق ، لا يزال مسموحًا به. نظرًا لأنك اخترت هذه الهندسة المعمارية ، يجب عليك الالتزام بالقواعد المحددة من قبل الهندسة المعمارية.
شكر وتقدير
بفضل Nicholas Zakas على المنشور الأصلي ، لتلخيص الأفكار معًا ، إلى Andree Hansson للمراجعة الفنية ، إلى Rebecca Murphey ، وجوستين ماير ، وجون هان ، وبيتر ميشو ، وبول إيرش ، وأليكس سيكستون ، قدموا جميعهم الكثير من المعلومات المتعلقة بهذه الجلسة.