window.pipedriveLeadboosterConfig = { base: pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster on jo olemassa') } 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 }) }, } } })() Avoin-suljettu-periaate. Tarvitseeko minun koskaan käyttää sitä? - The Codest
Codest
  • Tietoa meistä
  • Palvelut
    • Ohjelmistokehitys
      • Frontend-kehitys
      • Backend-kehitys
    • Staff Augmentation
      • Frontend-kehittäjät
      • Backend-kehittäjät
      • Tietoinsinöörit
      • Pilvi-insinöörit
      • QA insinöörit
      • Muut
    • Se neuvoa-antava
      • Tilintarkastus & konsultointi
  • Toimialat
    • Fintech & pankkitoiminta
    • E-commerce
    • Adtech
    • Terveysteknologia
    • Valmistus
    • Logistiikka
    • Autoteollisuus
    • IOT
  • Arvo
    • TOIMITUSJOHTAJA
    • CTO
    • Toimituspäällikkö
  • Tiimimme
  • Tapaustutkimukset
  • Tiedä miten
    • Blogi
    • Tapaamiset
    • Webinaarit
    • Resurssit
Työurat Ota yhteyttä
  • Tietoa meistä
  • Palvelut
    • Ohjelmistokehitys
      • Frontend-kehitys
      • Backend-kehitys
    • Staff Augmentation
      • Frontend-kehittäjät
      • Backend-kehittäjät
      • Tietoinsinöörit
      • Pilvi-insinöörit
      • QA insinöörit
      • Muut
    • Se neuvoa-antava
      • Tilintarkastus & konsultointi
  • Arvo
    • TOIMITUSJOHTAJA
    • CTO
    • Toimituspäällikkö
  • Tiimimme
  • Tapaustutkimukset
  • Tiedä miten
    • Blogi
    • Tapaamiset
    • Webinaarit
    • Resurssit
Työurat Ota yhteyttä
Takaisin nuoli PALAA TAAKSE
2019-07-02
Ohjelmistokehitys

Avoin-suljettu-periaate. Tarvitseeko minun koskaan käyttää sitä?

Mateusz Lesniak

Useimmat kehittäjät ovat kuulleet avoimen ja suljetun periaatteen, joka on yksi Bob-sedän SOLID-periaatteista. Se kuulostaa järkevältä, mutta se voi silti olla hieman epäselvä, kunnes sitä käytetään ensimmäistä kertaa "elävässä" koodissa. Periaatteen täydellinen sisältö on seuraava: ohjelmistokokonaisuuksien (luokat, moduulit, funktiot jne.) pitäisi olla avoimia laajennuksille, mutta suljettuja muutoksille.

Mitä se siis todella tarkoittaa?

Törmäsimme kehitysongelmaan, joka on osoittanut meille, mistä avoin-suljettu-periaatteessa todella on kyse. Eräässä verkkosovelluksessamme oli lomake, jossa oli kaksi osiota (muun muassa):

  • kysyntäkanavat
  • dynaamiset suodattimet

Käyttäjät voivat lisätä niin monta suodatinta kuin haluavat, mutta on olemassa joitakin sääntöjä - suodattimien saatavuus riippuu valituista kanavista.

Kysyntäkanavat: ADVAIHTO, OTSIKKOTARJOUSPYYNTÖ, VARAUS, MUUT Dynaamiset suodattimet(ulottuvuudet): verkkosivusto, mainosyksikkö, geo, luovakoko, laite

Tämä artikkeli käsittelee pääasiassa koodin uudistamista, joten alla on paljon koodinpätkiä. Yritin vähentää sitä, mutta jonkin verran koodia on tarpeen, jotta voidaan osoittaa, että koodin uudelleenkäsittely. Sinun ei tarvitse ymmärtää jokaista koodin pientä osaa ymmärtääkseen pääajatuksen.

Ongelman ensimmäinen toteutus oli yksinkertainen:

luokka 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) { _shouldDisableFields (disablingDemandChannels) {
    // onko jokin disablingDemandChannels-kohdista tarkistettu ?
  }
}

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

class ResearchDynamicFilter {
  _setDynamicFilterDisableWebsitesEvent () {
    $(this._getBody()).on('dynamicFilter:disableWebsites', (event, shouldDisableWebsites) => { {
      // poista verkkosivujen suodattimet käytöstä
    });
  }
}

Kuten näet, verkkosivujen suodattimen ei pitäisi olla käytettävissä HEADERin osaltaBIDDING-, RESERVATION- ja OTHER-kanavat, joten se on käytettävissä vain AD:lle.Vaihtokanava.

Viimeinen asia, mitä koodista voi sanoa, on se, että se on pysyvää tai staattista. Asiakkaamme esittävät siis yhä enemmän pyyntöjä, mikä tekee näistä luokista suurempia ja monimutkaisempia.

Ominaisuuksien kehittäminen

  • Lisää toinen kanava - EBDA (Verkkosivuston suodattimen ei pitäisi olla käytettävissä, kun EBDA on valittu):

    • laajenna DISABLING_DEMAND_CHANNELS EBDA-kysyntäkanavan mukaan
    • paljon nimenmuutoksia - ensimmäisessä toteutuksessa määrittelimme verkkosivuston metodien ja vakioiden nimissä. Esimerkiksi:

      • isWebsitesDimensionDisabled jotta _areFormStateDimensionsDisabled
      • VERKKOSIVUSTON_KYSYNTÄKANAVIEN_POISTAMINEN KÄYTÖSTÄ osoitteeseen DISABLING_DEMAND_CHANNELS

Spoilerivaroitus -> kun komponentti on avoinna muutoksille, nimiä vaihdetaan tulevaisuudessa paljon. Emme kiinnitä tähän huomiota seuraavissa vaiheissa.

  • Lisää toinen suodatin sanalle 'Tuote' (Tuote suodattimen saatavuusjärjestelmä on sama kuin verkkosivustolla)

    • ResearchDynamicFilter luokan on tarkistettava vielä yksi ulottuvuus, kun kentät poistetaan käytöstä tai otetaan käyttöön.
  • Mennään isommaksi ja lisätään kanavien yläpuolelle kytkin -> 'Source'. Kaikki tähän asti käyttämämme kysyntäkanavat ovat Ad Manager -lähteessä. Uudessa lähteessä - SSP - ei ole kysyntäkanavia, ja ainoa käytettävissä oleva suodatin on verkkosivusto.

    • Säännöt:

      • Lähteen tiloja on kaksi: Ad Manager, SSP.
      • Kaikki kysyntäkanavamme ovat saatavilla vain Ad Manager -lähteelle.
      • SSP-lähteelle ei ole kysyntäkanavia
      • 'Verkkosivusto' on ainoa käytettävissä oleva suodatin SSP-lähdettä varten.
    • Toteutus:

      • Kun valitaan 'SSP':

        • Poista kysyntäkanavat käytöstä.
        • laukaise 'dynamicFilter:disableWebsitesAndProducts' <- ota molemmat käyttöön
        • laukaise 'dynamicFilter:disableNonSspOptions'
      • Kun Ad Manager on tarkistettu:

        • laukaise 'dynamicFilter:disableWebsitesAndProducts' <- tarkista, onko sää käytössä vai ei
  • Lisää toinen suodatin sanalle 'Platform'

    • Säännöt:

      • Alusta on käytettävissä vain, kun lähde on SSP.
    • Vaikeus:

      • Nyt meillä on 'Verkkosivusto', joka on saatavilla AD_EXCHANGE-kanavalle Ad Managerissa ja Ssp:ssä, ja meillä on 'Alusta', joka on saatavilla Ssp:ssä mutta ei Ad Managerissa.
      • Vaihtaminen lomakkeen tila voi olla todella hankala ja sekava.

Uusien toimintojen käyttöönotto:

Esittelen seuraavan pätkän lähinnä osoittaakseni koodin monimutkaisuuden. Voit vapaasti jättää sen piiloon.

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

  _triggerCallbacks () {
    // valitse callbackit lähteen mukaan
  }

  _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) {
    // onko jokin disablingDemandChannels tarkistettu.
  }
}

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

class ResearchDynamicFilter {
  // En yksinkertaistanut näitä kahta metodirunkoa osoittaakseni nykyisen toteutuksen monimutkaisuuden.

  _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) => {
      // vaihda suodattimen tilaa 'shouldDisable'-arvon mukaan.
    });
  }
}

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

Käytämme edelleen joitakin 'toggle' mekanismi. On todella vaikeaa vaihtaa 4 vipua ja päästä odotettuun tilaan, ja nyt DynamicFilterin on tiedettävä, mitkä mitat eivät ole ssp-lähdettä varten.

Meillä on ResearchFormStateUpdater, miksi se ei voisi olla vastuussa?

Lopullinen pyyntö

Lisää toinen suodatin hakusanalle 'Yield partner'

Juuri sillä hetkellä päätimme muokata näitä luokkia. Analysoitavat kanavat ja suodattimet ovat vain pieni osa ongelmaa. Tässä on useita lomakeosioita, ja kaikissa niissä on sama ongelma. Refaktorointimme pitäisi poistaa tarve muuttaa näiden luokkien sisäisiä metodeja, jotta voidaan *lisätä* uusia kanavia tai ulottuvuuksia.

Seuraavassa pätkässä jätin pääluokat melkein sellaisiksi kuin ne ovat tuotantokoodissamme, jotta näet, kuinka helppotajuisia ne ovat nyt.

luokka 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) { _enableFilters (filtersToDisable) {
    const filtersToEnable = $(ResearchDynamicFilter.ALL_FILTERS).not(filtersToDisable).get();
    // ota filtersToEnable käyttöön
  }
}

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

Me teimme sen! Teimmekö?

Nyt 'ResearchDynamicFilter'in on tiedettävä vain luettelo kaikista suodattimista - vaikuttaa reilulta. Loput logiikasta ja valvonnasta tulee ylhäältä - joitakin korkeampia metodeja ja vakioita.

Kokeillaan uutta rakennetta lisäämällä suodatin 'Yield_partner':

luokka 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'];

Kuten näet, kyse on vain arvojen lisäämisestä vakioihin ja muutamista lisäehdoista.

Avoimen ja suljetun periaatteen ansiosta voimme muuttaa lomakkeen liiketoimintalogiikkaa vain lisäämällä joitakin arvoja ja ehtoja korkeammalla abstraktiotasolla. Meidän ei tarvitse mennä komponentin sisälle ja muuttaa mitään. Tämä refaktorointi vaikutti koko lomakkeeseen, ja siinä oli useampia osioita, ja ne kaikki noudattavat nyt avoimen ja suljetun periaatetta.

Emme vähentäneet koodin määrää - itse asiassa jopa lisäsimme sitä (ennen/jälkeen):

  • ResearchFormStateUpdater - 211/282 riviä
  • ResearchDynamicFilter - 267/256 riviä

Kyse on vain vakioiden kokoelmasta -> se on nyt julkinen käyttöliittymämme, konsolimme, jolla voimme hallita prosessia ilman kymmeniä kytkimiä.

Lue myös:

  • Miten kirjoittaa hyvää ja laadukasta koodia?
  • 1TP53Kalenteri. Uusi Codestin projekti, joka perustuu Vue.js:ään.
  • Mikä on Ruby on Jets ja miten rakentaa sovellus sen avulla?

Aiheeseen liittyvät artikkelit

Ohjelmistokehitys

Tulevaisuuden web-sovellusten rakentaminen: The Codest:n asiantuntijatiimin näkemyksiä

Tutustu siihen, miten The Codest loistaa skaalautuvien, interaktiivisten verkkosovellusten luomisessa huipputeknologian avulla ja tarjoaa saumattomia käyttäjäkokemuksia kaikilla alustoilla. Lue, miten asiantuntemuksemme edistää digitaalista muutosta ja liiketoimintaa...

THECODEST
Ohjelmistokehitys

Top 10 Latviassa toimivaa ohjelmistokehitysyritystä

Tutustu Latvian parhaisiin ohjelmistokehitysyrityksiin ja niiden innovatiivisiin ratkaisuihin uusimmassa artikkelissamme. Tutustu siihen, miten nämä teknologiajohtajat voivat auttaa nostamaan liiketoimintaasi.

thecodest
Yritys- ja skaalausratkaisut

Java-ohjelmistokehityksen perusteet: A Guide to Outsourcing Successfully

Tutustu tähän keskeiseen oppaaseen Java-ohjelmistokehityksen onnistuneesta ulkoistamisesta tehokkuuden parantamiseksi, asiantuntemuksen saamiseksi ja projektin onnistumiseksi The Codestin avulla.

thecodest
Ohjelmistokehitys

Perimmäinen opas ulkoistamiseen Puolassa

Ulkoistamisen lisääntyminen Puolassa johtuu taloudellisesta, koulutuksellisesta ja teknologisesta kehityksestä, joka edistää tietotekniikan kasvua ja yritysystävällistä ilmapiiriä.

TheCodest
Yritys- ja skaalausratkaisut

Täydellinen opas IT-tarkastustyökaluihin ja -tekniikoihin

Tietotekniikan tarkastuksilla varmistetaan turvalliset, tehokkaat ja vaatimustenmukaiset järjestelmät. Lue lisää niiden merkityksestä lukemalla koko artikkeli.

Codest
Jakub Jakubowicz teknologiajohtaja ja toinen perustaja

Tilaa tietopankkimme ja pysy ajan tasalla IT-alan asiantuntemuksesta.

    Tietoa meistä

    The Codest - Kansainvälinen ohjelmistokehitysyritys, jolla on teknologiakeskuksia Puolassa.

    Yhdistynyt kuningaskunta - pääkonttori

    • Toimisto 303B, 182-184 High Street North E6 2JA
      Lontoo, Englanti

    Puola - Paikalliset teknologiakeskukset

    • Fabryczna Office Park, Aleja
      Pokoju 18, 31-564 Krakova
    • Brain Embassy, Konstruktorska
      11, 02-673 Varsova, Puola

      Codest

    • Etusivu
    • Tietoa meistä
    • Palvelut
    • Tapaustutkimukset
    • Tiedä miten
    • Työurat
    • Sanakirja

      Palvelut

    • Se neuvoa-antava
    • Ohjelmistokehitys
    • Backend-kehitys
    • Frontend-kehitys
    • Staff Augmentation
    • Backend-kehittäjät
    • Pilvi-insinöörit
    • Tietoinsinöörit
    • Muut
    • QA insinöörit

      Resurssit

    • Faktoja ja myyttejä yhteistyöstä ulkoisen ohjelmistokehityskumppanin kanssa
    • Yhdysvalloista Eurooppaan: Miksi amerikkalaiset startup-yritykset päättävät muuttaa Eurooppaan?
    • Tech Offshore -kehityskeskusten vertailu: Tech Offshore Eurooppa (Puola), ASEAN (Filippiinit), Euraasia (Turkki).
    • Mitkä ovat teknologiajohtajien ja tietohallintojohtajien tärkeimmät haasteet?
    • Codest
    • Codest
    • Codest
    • Privacy policy
    • Verkkosivuston käyttöehdot

    Tekijänoikeus © 2025 by The Codest. Kaikki oikeudet pidätetään.

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