Window.pipedriveLeadboosterConfig = { القاعدة: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', الإصدار: 2, } ؛(الدالة () { var w = نافذة إذا كان (w.LeadBooster) { console.warn('LeadBooster موجود بالفعل') } وإلا { { w.LeadBooster = { q: [], على: دالة (ن، ح) { { هذا.q.push({ t: 'o'، n: n، n: n، h: h }) }, الزناد: الدالة (n) { هذا.q.push({ t: 't'، n: n: n }) }, } } })() مبدأ الانفتاح المغلق. هل يجب أن أستخدمه؟ - The Codest
The Codest
  • نبذة عنا
  • الخدمات
    • تطوير البرمجيات
      • تطوير الواجهة الأمامية
      • تطوير الواجهة الخلفية
    • Staff Augmentation
      • مطورو الواجهة الأمامية
      • مطورو الواجهة الخلفية
      • مهندسو البيانات
      • مهندسو السحابة
      • مهندسو ضمان الجودة
      • أخرى
    • استشاري
      • التدقيق والاستشارات
  • الصناعات
    • التكنولوجيا المالية والمصرفية
    • E-commerce
    • أدتك
    • التكنولوجيا الصحية
    • التصنيع
    • الخدمات اللوجستية
    • السيارات
    • إنترنت الأشياء
  • القيمة مقابل
    • CEO
    • CTO
    • مدير التوصيل
  • فريقنا
  • دراسات الحالة
  • اعرف كيف
    • المدونة
    • اللقاءات
    • ندوات عبر الإنترنت
    • الموارد
الوظائف تواصل معنا
  • نبذة عنا
  • الخدمات
    • تطوير البرمجيات
      • تطوير الواجهة الأمامية
      • تطوير الواجهة الخلفية
    • Staff Augmentation
      • مطورو الواجهة الأمامية
      • مطورو الواجهة الخلفية
      • مهندسو البيانات
      • مهندسو السحابة
      • مهندسو ضمان الجودة
      • أخرى
    • استشاري
      • التدقيق والاستشارات
  • القيمة مقابل
    • CEO
    • CTO
    • مدير التوصيل
  • فريقنا
  • دراسات الحالة
  • اعرف كيف
    • المدونة
    • اللقاءات
    • ندوات عبر الإنترنت
    • الموارد
الوظائف تواصل معنا
السهم الخلفي العودة إلى الوراء
2019-07-02
تطوير البرمجيات

مبدأ الفتح المغلق. هل يجب أن أستخدمه؟

ماتيوس ليسنياك

سمع معظم المطورين عن مبدأ الانفتاح - الانغلاق - أحد مبادئ العم بوب SOLID. يبدو الأمر معقولًا، لكنه قد يكون ضبابيًا بعض الشيء حتى الاستخدام الأول على شيفرة "حية". الحالة الكاملة للمبدأ هي: يجب أن تكون كيانات البرمجيات (الأصناف والوحدات والدوال وما إلى ذلك) مفتوحة للتوسع، ولكنها مغلقة للتعديل.

فما الذي يعنيه ذلك حقاً؟

لقد واجهتنا مشكلة تطوير أظهرت لنا ماهية مبدأ الانفتاح المغلق. في أحد تطبيقات الويب الخاصة بنا كان لدينا نموذج يحتوي على قسمين (من بين تطبيقات أخرى):

  • قنوات الطلب
  • مرشحات ديناميكية

يمكن للمستخدمين إضافة العديد من الفلاتر كما يحلو لهم، ولكن هناك بعض القواعد - يعتمد توافر الفلاتر على القنوات المختارة.

قنوات الطلب: إعلانالتبادل، الرأسالمزايدة، الحجز، مرشحات (أبعاد) ديناميكية أخرى: الموقع الإلكتروني، الإعلانالوحدة، الجغرافية، الإبداعيةالحجم، الجهاز

تدور هذه المقالة في الغالب حول إعادة بناء الشيفرة، لذا سيكون هناك الكثير من مقتطفات الشيفرة أدناه. لقد حاولت تقليلها، ولكن بعض الكودات ضرورية لإظهار إعادة هيكلة التعليمات البرمجية. لست بحاجة إلى فهم كل جزء صغير من التعليمات البرمجية لفهم الفكرة الرئيسية.

كان التنفيذ الأول للمشكلة بسيطاً:

فئة ResearchFormStateUpdater {
  تحديث () {
    (...)
    هذا._updateDynamicFilters();
  }

  _updateDynamicFilters () { {
    $('.عامل التصفية الديناميكي').كل ((_، فلتر)) => {
      $(.filter).trigger('dynamicFilter:disableWebsites', this._shouldDisableWebsitesFields());
    });
  }

  _shouldDisableDisableWebsitesFields () { {
    إرجاع هذا._shouldDisDisableDisableFields(ResearchFormStateUpdater.WEBSITE_DISABLING_DEMAND_CHANELS);
  }

  _shouldDisDisableFields (disablingDemandChannels) {
    // هل تم التحقق من أي من disablingDemandChannels؟
  }
}

ResearchFormFormStateUpdater.WEBSITE_DISABLING_DEMAND_CHANELS = ['header_bidding'، 'حجز'، 'أخرى'];

فئة ResearchDynamicFilter {
  _ SetDynamicDynamicFilterDisableWebsitesEvent () {
    $(this._getBody()).on('dynamicFilter:disableWebsites', (الحدث، shouldDisableWebsites) => {
      // تعطيل مرشحات مواقع الويب
    });
  }
}

كما ترى، من المفترض أن يكون عامل تصفية الموقع الإلكتروني غير متاح لـ HEADERالعطاءات والحجز والقنوات الأخرى، لذا فهي متاحة فقط لقنوات الإعلاناتقناة التبادل.

آخر شيء يمكنك قوله عن الكود هو أنه دائم أو ثابت. لذلك لدينا المزيد من الطلبات من عملائنا مما يجعل هذه الفئات أكبر وأكثر تعقيدًا.

تطوير الميزات

  • إضافة قناة أخرى - EBDA (يجب أن يكون فلتر الموقع الإلكتروني غير متاح أثناء اختيار EBDA):

    • توسيع تعطيل_تعطيل_قنوات_الطلب حسب قناة الطلب EBDA
    • الكثير من تغيير الأسماء - في التنفيذ الأول، حددنا الموقع في أسماء الطرق والثوابت. على سبيل المثال:

      • هو مواقع الويب المعطلة إلى _معطلة هيFormStateDim الأبعاد معطلة
      • الموقع_تعطيل_قنوات_الطلب_موقع_الإنترنت_تعطيل_قنوات_الطلب إلى تعطيل_تعطيل_قنوات_الطلب

تنبيه مفسد -> عندما يكون المكون مفتوحًا للتغييرات، سيكون هناك الكثير من التغييرات في الاسم في المستقبل. لن ننتبه إلى ذلك في الخطوات التالية.

  • إضافة فلتر آخر ل "المنتج (المنتج مخطط توفر المرشح هو نفسه الموقع الإلكتروني)

    • مرشح البحث الديناميكي يجب على الفصل التحقق من بُعد آخر أثناء تعطيل/تمكين الحقول
  • دعنا نكبر ونضيف بعض المحوّل فوق القنوات -> "المصدر". جميع قنوات الطلب التي كانت لدينا حتى الآن موجودة في مصدر مدير الإعلانات. المصدر الجديد - SSP - لا يوجد به قنوات طلب، والمرشح الوحيد المتاح هو الموقع الإلكتروني.

    • القواعد:

      • هناك حالتان للمصدر: مدير الإعلان، SSP.
      • جميع قنوات الطلب لدينا متاحة فقط لمصدر مدير الإعلانات.
      • لا توجد قنوات طلب لمصدر SSP
      • "الموقع الإلكتروني" هو عامل التصفية الوحيد المتاح لمصدر SSP.
    • التنفيذ:

      • عند اختيار "SSP":

        • تعطيل قنوات الطلب.
        • الزناد 'dynamicFilter:disableWebsitesAndProducts' <- تمكين كليهما
        • الزناد 'dynamicFilter:disableNonSspOptions'
      • عند التحقق من مدير الإعلانات

        • الزناد 'dynamicFilter:disableWebsitesAndProducts' <- التحقق من الطقس ممكّن أو معطل
  • إضافة فلتر آخر ل "المنصة

    • القواعد:

      • النظام الأساسي متاح فقط عندما يكون المصدر هو SSP
    • الصعوبة:

      • لدينا الآن "الموقع الإلكتروني"، وهو متاح لقناة AD_EXCHANGE من مدير الإعلانات ولـ SSP ولدينا "المنصة" وهي متاحة لـ SSP ولكن ليس لمدير الإعلانات
      • التبديل يمكن أن تصبح حالة النموذج خادعة ومربكة حقًا

التنفيذ بوظائف جديدة:

أقدم لكم المقتطف التالي بشكل أساسي لإظهار تعقيد الكود. لا تتردد في تركه مخفيًا.

فئة ResearchFormStateUpdater {
  تحديث () {
    (...)
    هذا._triggerCallbacks();
  }

  _triggerCallbacks () { {
    // اختر عمليات الاسترجاع اعتمادًا على المصدر
  }

  _adManagerSourceCallbacks () { {
    (...)
    هذا._enableDemableDemandChannels(ResearchFormStateStateUpdater.AD_MANAGER_DEMAND_CHANNELS);
    هذا._updateDefateDefaultStateOfDynamicFilters();
    هذا._updateAdAdAdManagerDynamicFilters()؛ هذا._updateAdManagerDynamicFilters();
  }

  _sspSpSourceCallbacks () { {
    (...)
    هذا._removeDemoveDemandChannelsActiveClassAndDisable(ResearchFormStateUpdater.AD_MANAGER_DEMAND_CHANELS);
    هذا._updateDefateDefaultStateOfDynamicFilters();
  }

  _updateDefateDefaultStateOfDynamicFilters () {
    $(".مرشح ديناميكي").كل ((_، مرشح) => {
      $(.filter).trigger('dynamicFilter:enableSspFilters', this.isSourceSsp);
    });
  }

  _updateAdateAdManagerDynamicFilters () { {
    $('.dynamic-filter').every((_، فلتر) => {
      $(.filter).trigger('dynamicFilter:disableWeableWebsitesAndProducts', this._areFormStateDim الأبعاد معطلة() & !this.isSourceSsp);
    });
  }

  _shouldDisableFields (disablingDemandChannels) {
    // هل تم التحقق من أي من disablingDemandChannels
  }
}

ResearchFormFormStateUpdater.AD_MANAGER_DISABLING_DEMAND_CHANELS = ['header_bidding'، 'حجز'، 'أخرى'، 'ebda'];

فئة ResearchDynamicFilter {
  // لم أبسط هاتين الطريقتين لإظهار تعقيد التنفيذ الحالي

  _setDefaultDefaultDynamicFiltersToggleEvent () {
    $(this._getBody()).on('dynamicFilter:enableSspFilters', (الحدث، shouldEnableSspOptions) => {
      هذا._setDefaultDefaultFiltersOiltersOptionDisabledState(shouldEnableSspOptions);

      const selectedFilterDimension = this._getFiltersDimension().find('option:selected').val();
      إذا (إذا كان (SelectFilterDimension === 'موقع ويب') {
        هذا._toggleChosenChosenFilterDisabledState (خطأ);
      } آخر إذا كان (SelectFilterDimension === 'النظام الأساسي') { {
        هذا._toggleChosenChosenFilterDisabledState(!shouldEnableSspOptions);
      غير ذلك {} {
        هذا._toggleChosenChosenFilterDisabledState(!shouldEnableSspOptions);
      }
    });
  }

  _setDynamicDynamicFilterDisableWebsitesAndProductsEvent () { {
    $(this._getBody()).on('dynamicFilter:disableWebsiteAndProducts'، (الحدث، shouldDisableWebsitesAndProducts) => {
      const selectedFilterDimension = this._getFiltersDimension().find('option:selected').val();
      إذا كان ($.inArray(SelectFilterDimension, ['موقع ويب'، 'منتج'])>= 0) { {
        هذا._toggleChosenChosenFilterDisabledState(shouldDisableWebsitesAndProducts);
      }
      هذا._setMethodMetSelectSelectWebsiteAndProductOptionDisabledState(shouldDisableWebsitesAndProducts);
    });
  }

  _toggleNonSspFilters (dimensionSelect, shouldDisisable) {
    $.each(ResearchDynamicFilter.NON_SSP_FILTERS_OPTIONS, (_, option) => {
      // تبديل حالة المرشح اعتمادًا على 'shouldDisDisable'
    });
  }
}

ResearchDynamicFilter.NON_SSP_FILTERS_OPTIONS = ['ad_unit'، 'creative_size'، 'creative_size'، 'geo'، 'device'، 'product'];

ما زلنا نستخدم بعض 'تبديل' الآلية. من الصعب حقًا تبديل 4 أذرع والوصول إلى الحالة المتوقعة والآن يجب أن يعرف DynamicFilter، أي الأبعاد ليست لمصدر ssp.

لدينا بالفعل ResearchFormStateUpdater، لماذا لا يكون مسؤولاً؟

الطلب النهائي

إضافة فلتر آخر ل "شريك العائد

هذه هي اللحظة التي قررنا فيها إعادة هيكلة تلك الفئات. القنوات والمرشحات التي يتم تحليلها هي مجرد جزء صغير من المشكلة. هناك العديد من أقسام النماذج هنا وجميعها تعاني من نفس المشكلة. يجب أن تُبطل عملية إعادة الهيكلة التي أجريناها الحاجة إلى تغيير داخل طرائق تلك الأصناف *لإضافة بعض القنوات أو الأبعاد الجديدة.

في المقتطف التالي، تركت الفئات الرئيسية كما هي تقريبًا كما هي في شيفرة الإنتاج الخاصة بنا لأوضح لك مدى سهولة فهمها الآن.

فئة ResearchFormStateUpdater {
  تحديث () {
    (...)
    هذا._updateDynamicFilters();
  }

  _updateDynamicFilters () { {
    هذا._toggleAllDynamicDynamicFiltersState (هذا._dynamicFiltersDynamicFiltersDimensionsToBeDisabled()));
  }

  _dynamicFiltersDynamicFiltersDynamicDiltersDimensionsToBeDisabled ()؛ {
    إذا (this.isSourceSsp) { إرجاع ResearchFormStateUpdater.NO_SSP_FILTERS؛ }

    var disabledFilters = ResearchFormStateUpdater.ONLY_SSP_FILTERS;
    إذا (هذا (areDemandChannelsExceptAdxSelected) {
      disabledFilters = disabledFilters.concat(ResearchFormStateUpdater.ONLY_ADX_FILTERS);
    }
    إرجاع المعطلة;
  }

  _toggleAllDynamicDynamicFiltersState (معطلةFilters) {
    $('.dynamic-filter').every((_، فلتر) => {
      هذا._toggleDynamicDynamicFilterState(فلتر، معطلةFilters);
    });
  }

  _toggleDynamicDynamicFilterState (مرشح ديناميكي، معطّل، معطّل) {
    $(فلتر ديناميكي).مشغل('dynamicFilter:toggleDynamicFilters'، معطلةالفلاتر);
  }
}

SearchFormFormStateUpdater.NO_SSP_FILTERS = ['ad_unit'، 'creative_size'، 'geo'، 'device'، 'product'];

ResearchFormFormStateUpdater.ONLY_SSP_FILTERS = ['النظام الأساسي'];

ResearchFormFormStateUpdater.ONLY_ADX_FILTERS = ['الموقع الإلكتروني'، 'المنتج'];

فئة ResearchDynamicFilter {
  _ SetDynamicDynamicFiltersToggleEvent () {
    $(this._getBody()).on('dynamicFilter:toggleDynamicFilters', (حدث، تعطيل المرشحات) => {
      هذا._disableFilters(disabledFilters.split('،'));
      هذا._enableFilters(disabledFilters.split(','))));
    });
  }

  _disableFilters (فلاترToDisable) {
    // تعطيل الفلاترToDisable
  }

  _enableFilters (فلاترToDisable) { {
    const const filtersToEnable = $(ResearchDynamicFilter.ALL_FILTERS).not(filtersToDisable).get();
    // تمكين الفلاترToEnable
  }
}

ResearchDynamicDynamicFilter.ALL_FILTERS = ['الموقع الإلكتروني'، 'الموقع الإلكتروني'، 'وحدة_إعلانية'، 'حجم_إبداعي'، 'جغرافي'، 'جهاز'، 'منتج'، 'منصة'];

لقد فعلناها! هل فعلناها؟

الآن الشيء الوحيد الذي يجب أن يعرفه 'ResearchDynamicFilter' هو قائمة بجميع الفلاتر - يبدو عادلاً. تأتي بقية المنطق والتحكم من الأعلى - بعض الطرق والثوابت العليا.

لذا دعونا نجرب هيكلنا الجديد بإضافة عامل تصفية لـ "Yield_partner":

فئة ResearchFormStateUpdater {
  _dynamicFiltersDiltersDimensionsToBeDisabled () {
    (...)
    إذا (هذا (areDemandChannelsExceptEbdaSelected) {
      disabledFilters = disabledFilters.concat(ResearchFormStateUpdater.ONLY_EBDA_FILTERS);
    }
    إرجاع المعطلة;
  }
}

ResearchFormFormStateUpdater.NO_SSP_FILTERS = [(...)، 'yield_partner'];

ResearchFormFormStateUpdater.ONLY_EBDA_FILTERS = [(...)، 'yield_partner'];

ResearchDynamicFilter.ALL_FILTERS = [(...)، 'yield_partner']؛

كما ترى، الأمر كله يتعلق بإضافة بعض القيم إلى الثوابت وبعض الشروط الإضافية.

بفضل "مبدأ "مفتوح-مغلق" يمكننا تغيير منطق العمل الخاص بالنموذج بإضافة بعض القيم والشروط على مستوى أعلى من التجريد. لا نحتاج إلى الدخول داخل المكوّن وتغيير أي شيء. أثرت عملية إعادة الهيكلة هذه على النموذج بأكمله وكان هناك المزيد من الأقسام وجميعها تخضع لمبدأ "مفتوح-مغلق" الآن.

لم نقم بتقليل كمية التعليمات البرمجية - بل قمنا بزيادتها (قبل/بعد):

  • نموذج البحثFormStateUpdater - 211/282 سطر
  • مرشح البحث الديناميكي - 267/256 سطر

الأمر كله يتعلق بالمجموعة في الثوابت -> إنها واجهتنا العامة الآن، وحدة التحكم في العملية بدون عشرات المحولات.

اقرأ أيضًا:

  • كيف تكتب كودًا جيدًا وعالي الجودة؟
  • Vuelendar. مشروع كودست جديد يستند إلى Vue.js
  • ما هو Ruby on Jets وكيفية إنشاء تطبيق باستخدامه؟

مقالات ذات صلة

تطوير البرمجيات

إنشاء تطبيقات ويب مستقبلية: رؤى من فريق خبراء The Codest

اكتشف كيف تتفوق شركة The Codest في إنشاء تطبيقات ويب تفاعلية قابلة للتطوير باستخدام أحدث التقنيات، وتقديم تجارب مستخدم سلسة عبر جميع المنصات. اكتشف كيف تقود خبرتنا التحول الرقمي والأعمال التجارية...

ذا كوديست
تطوير البرمجيات

أفضل 10 شركات لتطوير البرمجيات في لاتفيا

تعرّف على أفضل شركات تطوير البرمجيات في لاتفيا وحلولها المبتكرة في أحدث مقالاتنا. اكتشف كيف يمكن لهذه الشركات الرائدة في مجال التكنولوجيا المساعدة في الارتقاء بأعمالك.

thecodest
الحلول المؤسسية وحلول التوسعة

أساسيات تطوير برمجيات جافا: دليل للاستعانة بمصادر خارجية بنجاح

استكشف هذا الدليل الأساسي حول تطوير برمجيات جافا outsourcing بنجاح لتعزيز الكفاءة والوصول إلى الخبرة وتحقيق نجاح المشروع باستخدام The Codest.

thecodest
تطوير البرمجيات

الدليل الشامل للاستعانة بمصادر خارجية في بولندا

إن الطفرة في outsourcing في بولندا مدفوعة بالتقدم الاقتصادي والتعليمي والتكنولوجي، مما يعزز نمو تكنولوجيا المعلومات والمناخ الملائم للأعمال.

ذا كوديست
الحلول المؤسسية وحلول التوسعة

الدليل الكامل لأدوات وتقنيات تدقيق تكنولوجيا المعلومات

تضمن عمليات تدقيق تكنولوجيا المعلومات وجود أنظمة آمنة وفعالة ومتوافقة. تعرف على المزيد حول أهميتها من خلال قراءة المقال كاملاً.

The Codest
ياكوب جاكوب جاكوبوفيتش CTO وشريك مؤسس CTO

اشترك في قاعدة معارفنا وابقَ على اطلاع على آخر المستجدات في قطاع تكنولوجيا المعلومات.

    نبذة عنا

    The Codest - شركة دولية لتطوير البرمجيات لها مراكز تقنية في بولندا.

    المملكة المتحدة - المقر الرئيسي

    • المكتب 303 ب، 182-184 شارع هاي ستريت نورث E6 2JA
      لندن، إنجلترا

    بولندا - مراكز التكنولوجيا المحلية

    • مجمع مكاتب فابريتشنا المكتبي، أليجا
      بوكوجو 18، 31-564 كراكوف
    • سفارة الأدمغة، كونستروكتورسكا
      11, 02-673 02-673 وارسو، بولندا

      The Codest

    • الصفحة الرئيسية
    • نبذة عنا
    • الخدمات
    • دراسات الحالة
    • اعرف كيف
    • الوظائف
    • القاموس

      الخدمات

    • استشاري
    • تطوير البرمجيات
    • تطوير الواجهة الخلفية
    • تطوير الواجهة الأمامية
    • Staff Augmentation
    • مطورو الواجهة الخلفية
    • مهندسو السحابة
    • مهندسو البيانات
    • أخرى
    • مهندسو ضمان الجودة

      الموارد

    • حقائق وأساطير حول التعاون مع شريك خارجي لتطوير البرمجيات
    • من الولايات المتحدة الأمريكية إلى أوروبا: لماذا تقرر الشركات الأمريكية الناشئة الانتقال إلى أوروبا؟
    • مقارنة مراكز تطوير التكنولوجيا في الخارج: تك أوفشور أوروبا (بولندا)، آسيان (الفلبين)، أوراسيا (تركيا)
    • ما هي أهم التحديات التي تواجه CTOs ومديري تكنولوجيا المعلومات؟
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • شروط استخدام الموقع الإلكتروني

    جميع الحقوق محفوظة © 2025 بواسطة The Codest. جميع الحقوق محفوظة.

    arArabic
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek arArabic