window.pipedriveLeadboosterConfig = { base: leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster on juba olemas') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() Avatud-suletud põhimõte. Kas ma pean seda kunagi kasutama? - The Codest
The Codest
  • Meie kohta
  • Teenused
    • Tarkvaraarendus
      • Frontend arendus
      • Backend arendus
    • Staff Augmentation
      • Frontend arendajad
      • Backend arendajad
      • Andmeinsenerid
      • Pilveinsenerid
      • QA insenerid
      • Muud
    • See nõuandev
      • Audit ja nõustamine
  • Tööstusharud
    • Fintech & pangandus
    • E-commerce
    • Adtech
    • Healthtech
    • Tootmine
    • Logistika
    • Autotööstus
    • IOT
  • Väärtus
    • CEO
    • CTO
    • Tarnejuht
  • Meie meeskond
  • Case Studies
  • Tea kuidas
    • Blogi
    • Kohtumised
    • Veebiseminarid
    • Ressursid
Karjäärivõimalused Võtke ühendust
  • Meie kohta
  • Teenused
    • Tarkvaraarendus
      • Frontend arendus
      • Backend arendus
    • Staff Augmentation
      • Frontend arendajad
      • Backend arendajad
      • Andmeinsenerid
      • Pilveinsenerid
      • QA insenerid
      • Muud
    • See nõuandev
      • Audit ja nõustamine
  • Väärtus
    • CEO
    • CTO
    • Tarnejuht
  • Meie meeskond
  • Case Studies
  • Tea kuidas
    • Blogi
    • Kohtumised
    • Veebiseminarid
    • Ressursid
Karjäärivõimalused Võtke ühendust
Tagasi nool TAGASI
2019-07-02
Tarkvaraarendus

Avatud-suletud põhimõte. Kas ma pean seda kunagi kasutama?

Mateusz Lesniak

Enamik arendajaid on kuulnud avatud - suletud põhimõttest - üks onu Bobi SOLIDi põhimõtetest. See kõlab mõistlikult, kuid see võib siiski olla veidi ähmane kuni esimese kasutamiseni "elusas" koodis. Põhimõtte täielik olek on: tarkvara üksused (klassid, moodulid, funktsioonid jne) peaksid olema avatud laiendamiseks, kuid suletud muutmiseks.

Mida see siis tegelikult tähendab?

Me puutusime kokku ühe arendusprobleemiga, mis näitas meile, mida avatud-suletud põhimõte tegelikult tähendab. Ühes meie veebirakenduses oli meil (muu hulgas) kahe sektsiooniga vorm:

  • nõudluskanalid
  • dünaamilised filtrid

Kasutajad võivad lisada nii palju filtreid kui nad soovivad, kuid on mõned reeglid - filtrite kättesaadavus sõltub valitud kanalitest.

Nõudluskanalid: ADVAHETUS, PÄISPAKKUMINE, RESERVEERIMINE, MUUD Dünaamilised filtrid(mõõtmed): veebileht, kuulutusüksus, geo, loomingulinesuurus, seade

See artikkel käsitleb peamiselt koodi refaktoorimist, nii et allpool on palju koodilõike. Ma püüdsin seda vähendada, kuid mõningane kogus koodi on vajalik, et näidata koodi refaktooring. Te ei pea mõistma iga väikest koodi osa, et saada aru peamisest ideest.

Probleemi esimene rakendamine oli lihtne:

class ResearchFormStateUpdater {
  update () {
    (...)
    this._updateDynamicFilters();
  }

  _updateDynamicFilters () {
    $('.dynamic-filter').each((_, filter) => {
      $(filter).trigger('dynamicFilter:disableWebsites', this._shouldDisableWebsitesFields());
    });
  }

  _shouldDisableWebsitesFields () {
    return this._shouldDisableFields(ResearchFormStateUpdater.WEBSITE_DISABLING_DEMAND_CHANNELS);
  }

  _shouldDisableFields (disablingDemandChannels) {
    // kas mõni disablingDemandChannels on kontrollitud ?
  }
}

ResearchFormStateUpdater.WEBSITE_DISABLING_DEMAND_CHANNELS = ['header_bidding', 'reservation', 'other'];

class ResearchDynamicFilter {
  _setDynamicFilterDisableWebsitesEvent () {
    $(this._getBody()).on('dynamicFilter:disableWebsites', (event, shouldDisableWebsites) => { {
      // veebisaitide filtrite keelamine
    });
  }
}

Nagu näete, peaks veebilehe filter olema HEADERi jaoks kättesaamatu.BIDDING, RESERVATION ja muud kanalid, nii et see on saadaval ainult ADVAHETUSKANAL.

Viimane asi, mida saab öelda koodi kohta, on see, et see on püsiv või staatiline. Seega on meil rohkem kliendipäringuid, mis teevad need klassid suuremaks ja keerulisemaks.

Funktsiooni arendamine

  • Lisa veel üks kanal - EBDA (Veebilehe filter ei tohiks olla kättesaadav, kui EBDA on valitud):

    • laiendada DISABLING_DEMAND_CHANNELS EBDA nõudluskanali järgi
    • palju nimemuutusi - esimeses rakenduses määrasime meetodite ja konstandide nimedes veebilehe. Näiteks:

      • isWebsitesDimensionDisabled et _areFormStateDimensionsDisabled
      • VEEBILEHE_VÄLJALÜLITAMINE_NÕUDLUSKANALITE_VÄLJALÜLITAMINE aadressile DISABLING_DEMAND_CHANNELS

Spoiler hoiatus -> kui komponent on avatud muudatuste jaoks, muutub tulevikus palju nimesid. Järgmistes sammudes me sellele tähelepanu ei pööra.

  • Lisa veel üks filter 'Toote' jaoks (Toode filtri kättesaadavuse skeem on sama nagu veebisaidil)

    • ResearchDynamicFilter klass peab kontrollima veel ühte mõõdet, kui väljad keelatakse/aktiveeritakse.
  • Läheme suuremaks ja lisame kanalite kohal mõne lüliti -> 'Source'. Kõik nõudluskanalid, mis meil seni olid, on Ad Manager allikas. Uues allikas - SSP - ei ole nõudluskanaleid ja ainus olemasolev filter on veebileht.

    • Reeglid:

      • Allikas on kahes seisundis: SSP.
      • Kõik meie nõudluskanalid on saadaval ainult Ad Manageri allikale.
      • SSP allikale ei ole nõudluskanaleid
      • 'Veebileht' on ainus SSP allika jaoks saadaval olev filter.
    • Rakendamine:

      • Kui on valitud "SSP":

        • Lülitage nõudluskanalid välja.
        • vallandada 'dynamicFilter:disableWebsitesAndProducts' <- lubage mõlemad
        • vallandada 'dynamicFilter:disableNonSspOptions'
      • Kui reklaamihaldur on kontrollitud:

        • vallandada 'dynamicFilter:disableWebsitesAndProducts' <- kontrollige, kas ilm on lubatud või keelatud
  • Lisa veel üks filter 'Platvormi' jaoks

    • Reeglid:

      • Platvorm on saadaval ainult siis, kui allikas on SSP
    • Raskusaste:

      • Nüüd on meil 'Website', mis on saadaval AD_EXCHANGE kanalile Ad Manager ja Ssp ja meil on 'Platform', mis on saadaval Ssp, kuid mitte Ad Manager
      • Vaheldumine vormi olek võib muutuda väga keeruliseks ja segaseks.

Uue funktsionaalsusega rakendamine:

Esitan teile järgmise katkendi peamiselt selleks, et näidata koodi keerukust. Jäta see vabalt peidetud.

class ResearchFormStateUpdater {
  update () {
    (...)
    this._triggerCallbacks();
  }

  _triggerCallbacks () {
    // valime callbackid sõltuvalt allikast
  }

  _adManagerSourceCallbacks () {
    (...)
    this._enableDemandChannels(ResearchFormStateUpdater.AD_MANAGER_DEMAND_CHANNELS);
    this._updateDefaultStateOfDynamicFilters();
    this._updateAdManagerDynamicFilters();
  }

  _sspSourceCallbacks () {
    (...)
    this._removeDemandChannelsActiveClassAndDisable(ResearchFormStateUpdater.AD_MANAGER_DEMAND_CHANNELS);
    this._updateDefaultStateOfDynamicFilters();
  }

  _updateDefaultStateOfDynamicFilters () {
    $('.dynamic-filter').each((_, filter) => {
      $(filter).trigger('dynamicFilter:enableSspFilters', this.isSourceSsp);
    });
  }

  _updateAdManagerDynamicFilters () {
    $('.dynamic-filter').each((_, filter) => { {
      $(filter).trigger('dynamicFilter:disableWebsitesAndProducts', this._areFormStateDimensionsDisabled() && !this.isSourceSsp);
    });
  }

  _shouldDisableFields (disablingDemandChannels) {
    // on mis tahes disablingDemandChannels kontrollitud
  }
}

ResearchFormStateUpdater.AD_MANAGER_DISABLING_DEMAND_CHANNELS = ['header_bidding', 'reservation', 'other', 'ebda'];

class ResearchDynamicFilter {
  // Ma ei lihtsustanud neid kahte meetodi keha, et näidata praegust rakendamise keerukust.

  _setDefaultDynamicFiltersToggleEvent () {
    $(this._getBody()).on('dynamicFilter:enableSspFilters', (event, shouldEnableSspOptions) => { {
      this._setDefaultFiltersOptionDisabledState(shouldEnableSspOptions);

      const selectedFilterDimension = this._getFiltersDimension().find('option:selected').val();
      if (selectedFilterDimension === 'website') {
        this._toggleChosenFilterDisabledState(false);
      } else if (selectedFilterDimension === 'platform') {
        this._toggleChosenFilterDisabledState(!shouldEnableSspOptions);
      } else {
        this._toggleChosenFilterDisabledState(shouldEnableSspOptions);
      }
    });
  }

  _setDynamicFilterDisableWebsitesAndProductsEvent () {
    $(this._getBody()).on('dynamicFilter:disableWebsitesAndProducts', (event, shouldDisableWebsitesAndProducts) => {
      const selectedFilterDimension = this._getFiltersDimension().find('option:selected').val();
      if ($.inArray(selectedFilterDimension, ['website', 'product']) >= 0) {
        this._toggleChosenFilterDisabledState(shouldDisableWebsitesAndProducts);
      }
      this._setMethodSelectWebsiteAndProductOptionDisabledState(shouldDisableWebsitesAndProducts);
    });
  }

  _toggleNonSspFilters (dimensionSelect, shouldDisable) {
    $.each(ResearchDynamicFilter.NON_SSP_FILTERS_OPTIONS, (_, option) => {
      // lülitab filtri olekut sõltuvalt 'shouldDisable'.
    });
  }
}

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

Me kasutame endiselt mõningaid 'toggle' mehhanism. On tõesti raske vahetada 4 hooba ja jõuda oodatud olekusse ja nüüd peab DynamicFilter teadma, millised mõõtmed ei ole ssp allikas.

Meil on olemas ResearchFormStateUpdater, miks ei peaks see olema vastutav?

Lõplik taotlus

Lisa veel üks filter 'Yield partner' jaoks

See on täpselt see hetk, mil me otsustasime need klassid ümber kujundada. Analüüsitavad kanalid ja filtrid on vaid väike osa probleemist. Siin on mitu vormilõiku ja kõigil neil on sama probleem. Meie refaktor peaks neutraliseerima vajaduse muuta nende klasside sisemised meetodid *selleks*, et lisada mõned uued kanalid või mõõtmed.

Järgmises katkendis jätsin põhiklassid peaaegu samaks, nagu need on meie tootmiskoodis, et näidata, kui lihtne on neid nüüd mõista.

class ResearchFormStateUpdater {
  update () {
    (...)
    this._updateDynamicFilters();
  }

  _updateDynamicFilters () {
    this._toggleAllDynamicFiltersState(this._dynamicFiltersDimensionsToBeDisabled());
  }

  _dynamicFiltersDimensionsToBeDisabled () {
    if (this.isSourceSsp) { return ResearchFormStateUpdater.NO_SSP_FILTERS; }

    var disabledFilters = ResearchFormStateUpdater.ONLY_SSP_FILTERS;
    if (this.areDemandChannelsExceptAdxSelected) {
      disabledFilters = disabledFilters.concat(ResearchFormStateUpdater.ONLY_ADX_FILTERS);
    }
    return disabledFilters;
  }

  _toggleAllDynamicFiltersState (disabledFilters) {
    $('.dynamic-filter').each((_, filter) => {
      this._toggleDynamicFilterState(filter, disabledFilters);
    });
  }

  _toggleDynamicFilterState (dynamicFilter, disabledFilters) {
    $(dynamicFilter).trigger('dynamicFilter:toggleDynamicFilters', disabledFilters);
  }
}

ResearchFormStateUpdater.NO_SSP_FILTERS = ['ad_unit', 'creative_size', 'geo', 'device', 'product'];

ResearchFormStateUpdater.ONLY_SSP_FILTERS = ['platform'];

ResearchFormStateUpdater.ONLY_ADX_FILTERS = ['website', 'product'];

class ResearchDynamicFilter {
  _setDynamicFiltersToggleEvent () {
    $(this._getBody()).on('dynamicFilter:toggleDynamicFilters', (event, disabledFilters) => {
      this._disableFilters(disabledFilters.split(','));
      this._enableFilters(disabledFilters.split(',')));
    });
  }

  _disableFilters (filtersToDisable) {
    // disable filtersToDisable
  }

  _enableFilters (filtersToDisable) {
    const filtersToEnable = $(ResearchDynamicFilter.ALL_FILTERS).not(filtersToDisable).get();
    // enable filtersToEnable
  }
}

ResearchDynamicFilter.ALL_FILTERS = ['website', 'ad_unit', 'creative_size', 'geo', 'device', 'product', 'platform'];

Me tegime seda! Kas me tegime?

Nüüd on ainus asi, mida 'ResearchDynamicFilter' peab teadma, kõigi filtrite nimekiri - tundub õiglane. Ülejäänud loogika ja kontroll tuleb ülaltpoolt - mõned kõrgemad meetodid ja konstandid.

Proovime siis meie uut struktuuri, lisades filtri 'Yield_partner':

class ResearchFormStateUpdater {
  _dynamicFiltersDimensionsToBeDisabled () {
    (...)
    if (this.areDemandChannelsExceptEbdaSelected) {
      disabledFilters = disabledFilters.concat(ResearchFormStateUpdater.ONLY_EBDA_FILTERS);
    }
    return disabledFilters;
  }
}

ResearchFormStateUpdater.NO_SSP_FILTERS = [(...), 'yield_partner'];

ResearchFormStateUpdater.ONLY_EBDA_FILTERS = [(...), 'yield_partner'];

ResearchDynamicFilter.ALL_FILTERS = [(...), 'yield_partner'];

Nagu näete, on tegemist mõne väärtuse lisamisega konstandidele ja mõnedele lisatingimustele.

Tänu "avatud-suletud põhimõttele" saame muuta vormi äriloogikat, lisades vaid mõned väärtused ja tingimused kõrgemal abstraktsioonitasemel. Meil ei ole vaja minna komponendi sisemusse ja midagi muuta. See refaktor puudutas kogu vormi ja seal oli rohkem sektsioone ning need kõik järgivad nüüd avatud-kinni põhimõtet.

Me ei vähendanud koodi hulka - tegelikult me isegi suurendasime seda (enne/pärast):

  • ResearchFormStateUpdater - 211/282 rida
  • ResearchDynamicFilter - 267/256 rida

See kõik on umbes kogumise konstandid -> see on meie avalik liides nüüd, meie konsool kontrollida protsessi ilma kümneid lülitid.

Loe ka:

  • Kuidas kirjutada head ja kvaliteetset koodi?
  • Vuelendar. Uus Codesti projekt, mis põhineb Vue.js-l.
  • Mis on Ruby on Jets ja kuidas seda kasutades rakendust luua?

Seotud artiklid

Tarkvaraarendus

Tulevikukindlate veebirakenduste loomine: The Codest ekspertide meeskonna ülevaade

Avastage, kuidas The Codest paistab skaleeritavate, interaktiivsete veebirakenduste loomisel silma tipptehnoloogiatega, mis pakuvad sujuvat kasutajakogemust kõigil platvormidel. Saate teada, kuidas meie eksperditeadmised aitavad kaasa digitaalsele ümberkujundamisele ja äritegevusele...

THECODEST
Tarkvaraarendus

Top 10 Lätis asuvat tarkvaraarendusettevõtet

Tutvu Läti parimate tarkvaraarendusettevõtete ja nende innovaatiliste lahendustega meie viimases artiklis. Avastage, kuidas need tehnoloogiajuhid saavad aidata teie äri edendada.

thecodest
Enterprise & Scaleups lahendused

Java tarkvaraarenduse põhitõed: A Guide to Outsourcing Successfully

Tutvuge selle olulise juhendiga, kuidas edukalt outsourcing Java tarkvara arendada, et suurendada tõhusust, pääseda ligi eksperditeadmistele ja edendada projekti edu The Codest abil.

thecodest
Tarkvaraarendus

Ülim juhend Poola allhanke kohta

outsourcing kasv Poolas on tingitud majanduslikust, hariduslikust ja tehnoloogilisest arengust, mis soodustab IT kasvu ja ettevõtlussõbralikku kliimat.

TheCodest
Enterprise & Scaleups lahendused

Täielik juhend IT-auditi vahendite ja tehnikate kohta

IT-auditid tagavad turvalised, tõhusad ja nõuetele vastavad süsteemid. Lisateavet nende tähtsuse kohta leiate kogu artiklist.

The Codest
Jakub Jakubowicz CTO & kaasasutajad

Tellige meie teadmistebaas ja jääge kursis IT-sektori eksperditeadmistega.

    Meie kohta

    The Codest - rahvusvaheline tarkvaraarendusettevõte, mille tehnoloogiakeskused asuvad Poolas.

    Ühendkuningriik - peakorter

    • Büroo 303B, 182-184 High Street North E6 2JA
      London, Inglismaa

    Poola - kohalikud tehnoloogiakeskused

    • Fabryczna büroopark, Aleja
      Pokoju 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Varssavi, Poola

      The Codest

    • Kodu
    • Meie kohta
    • Teenused
    • Case Studies
    • Tea kuidas
    • Karjäärivõimalused
    • Sõnastik

      Teenused

    • See nõuandev
    • Tarkvaraarendus
    • Backend arendus
    • Frontend arendus
    • Staff Augmentation
    • Backend arendajad
    • Pilveinsenerid
    • Andmeinsenerid
    • Muud
    • QA insenerid

      Ressursid

    • Faktid ja müüdid koostööst välise tarkvaraarenduspartneriga
    • USAst Euroopasse: Miks otsustavad Ameerika idufirmad Euroopasse ümber asuda?
    • Tech Offshore arenduskeskuste võrdlus: Euroopa (Poola), ASEAN (Filipiinid), Euraasia (Türgi).
    • Millised on CTO ja CIOde peamised väljakutsed?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Copyright © 2025 by The Codest. Kõik õigused kaitstud.

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